summaryrefslogtreecommitdiffstats
path: root/kipi-plugins
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-19 18:22:05 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-19 18:22:05 +0000
commit57e10fedbcb8c3e8c6590ff0935dbf017ce5587f (patch)
tree3000a7649ca4e40e43f9e7feed963236a0b0f56b /kipi-plugins
downloadkipi-plugins-57e10fedbcb8c3e8c6590ff0935dbf017ce5587f.tar.gz
kipi-plugins-57e10fedbcb8c3e8c6590ff0935dbf017ce5587f.zip
Import abandoned KDE3 version of kipi plugins
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/libraries/kipi-plugins@1077221 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kipi-plugins')
-rw-r--r--kipi-plugins/AUTHORS63
-rw-r--r--kipi-plugins/COPYING340
-rw-r--r--kipi-plugins/ChangeLog16185
-rw-r--r--kipi-plugins/INSTALL184
-rw-r--r--kipi-plugins/Makefile.am134
-rw-r--r--kipi-plugins/NEWS450
-rw-r--r--kipi-plugins/README140
-rw-r--r--kipi-plugins/TODO54
-rw-r--r--kipi-plugins/acquireimages/Makefile.am23
-rw-r--r--kipi-plugins/acquireimages/acquireimagedialog.cpp585
-rw-r--r--kipi-plugins/acquireimages/acquireimagedialog.h131
-rw-r--r--kipi-plugins/acquireimages/kipiplugin_acquireimages.desktop55
-rw-r--r--kipi-plugins/acquireimages/plugin_acquireimages.cpp169
-rw-r--r--kipi-plugins/acquireimages/plugin_acquireimages.h62
-rw-r--r--kipi-plugins/acquireimages/screenshotdialog.cpp311
-rw-r--r--kipi-plugins/acquireimages/screenshotdialog.h115
-rw-r--r--kipi-plugins/batchprocessimages/Makefile.am39
-rw-r--r--kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp1092
-rw-r--r--kipi-plugins/batchprocessimages/batchprocessimagesdialog.h246
-rw-r--r--kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp115
-rw-r--r--kipi-plugins/batchprocessimages/batchprocessimagesitem.h84
-rw-r--r--kipi-plugins/batchprocessimages/batchprocessimageslist.cpp113
-rw-r--r--kipi-plugins/batchprocessimages/batchprocessimageslist.h57
-rw-r--r--kipi-plugins/batchprocessimages/borderimagesdialog.cpp338
-rw-r--r--kipi-plugins/batchprocessimages/borderimagesdialog.h80
-rw-r--r--kipi-plugins/batchprocessimages/borderoptionsdialog.cpp160
-rw-r--r--kipi-plugins/batchprocessimages/borderoptionsdialog.h64
-rw-r--r--kipi-plugins/batchprocessimages/colorimagesdialog.cpp325
-rw-r--r--kipi-plugins/batchprocessimages/colorimagesdialog.h72
-rw-r--r--kipi-plugins/batchprocessimages/coloroptionsdialog.cpp112
-rw-r--r--kipi-plugins/batchprocessimages/coloroptionsdialog.h59
-rw-r--r--kipi-plugins/batchprocessimages/convertimagesdialog.cpp376
-rw-r--r--kipi-plugins/batchprocessimages/convertimagesdialog.h77
-rw-r--r--kipi-plugins/batchprocessimages/convertoptionsdialog.cpp121
-rw-r--r--kipi-plugins/batchprocessimages/convertoptionsdialog.h63
-rw-r--r--kipi-plugins/batchprocessimages/data/Makefile.am2
-rw-r--r--kipi-plugins/batchprocessimages/data/handcursor.pngbin0 -> 271 bytes
-rw-r--r--kipi-plugins/batchprocessimages/effectimagesdialog.cpp442
-rw-r--r--kipi-plugins/batchprocessimages/effectimagesdialog.h83
-rw-r--r--kipi-plugins/batchprocessimages/effectoptionsdialog.cpp257
-rw-r--r--kipi-plugins/batchprocessimages/effectoptionsdialog.h78
-rw-r--r--kipi-plugins/batchprocessimages/filterimagesdialog.cpp365
-rw-r--r--kipi-plugins/batchprocessimages/filterimagesdialog.h78
-rw-r--r--kipi-plugins/batchprocessimages/filteroptionsdialog.cpp201
-rw-r--r--kipi-plugins/batchprocessimages/filteroptionsdialog.h69
-rw-r--r--kipi-plugins/batchprocessimages/hi32-action-borderimages.pngbin0 -> 938 bytes
-rw-r--r--kipi-plugins/batchprocessimages/hi32-action-colorimages.pngbin0 -> 1716 bytes
-rw-r--r--kipi-plugins/batchprocessimages/hi32-action-convertimages.pngbin0 -> 1100 bytes
-rw-r--r--kipi-plugins/batchprocessimages/hi32-action-effectimages.pngbin0 -> 978 bytes
-rw-r--r--kipi-plugins/batchprocessimages/hi32-action-filterimages.pngbin0 -> 1518 bytes
-rw-r--r--kipi-plugins/batchprocessimages/hi32-action-recompressimages.pngbin0 -> 380 bytes
-rw-r--r--kipi-plugins/batchprocessimages/hi32-action-renameimages.pngbin0 -> 1619 bytes
-rw-r--r--kipi-plugins/batchprocessimages/hi32-action-resizeimages.pngbin0 -> 1025 bytes
-rw-r--r--kipi-plugins/batchprocessimages/imagepreview.cpp386
-rw-r--r--kipi-plugins/batchprocessimages/imagepreview.h142
-rw-r--r--kipi-plugins/batchprocessimages/kipiplugin_batchprocessimages.desktop57
-rw-r--r--kipi-plugins/batchprocessimages/outputdialog.cpp112
-rw-r--r--kipi-plugins/batchprocessimages/outputdialog.h71
-rw-r--r--kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp313
-rw-r--r--kipi-plugins/batchprocessimages/plugin_batchprocessimages.h80
-rw-r--r--kipi-plugins/batchprocessimages/recompressimagesdialog.cpp272
-rw-r--r--kipi-plugins/batchprocessimages/recompressimagesdialog.h74
-rw-r--r--kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp140
-rw-r--r--kipi-plugins/batchprocessimages/recompressoptionsdialog.h67
-rw-r--r--kipi-plugins/batchprocessimages/renameimagesbase.ui359
-rw-r--r--kipi-plugins/batchprocessimages/renameimagesdialog.cpp94
-rw-r--r--kipi-plugins/batchprocessimages/renameimagesdialog.h70
-rw-r--r--kipi-plugins/batchprocessimages/renameimageswidget.cpp553
-rw-r--r--kipi-plugins/batchprocessimages/renameimageswidget.h107
-rw-r--r--kipi-plugins/batchprocessimages/resizeimagesdialog.cpp575
-rw-r--r--kipi-plugins/batchprocessimages/resizeimagesdialog.h92
-rw-r--r--kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp373
-rw-r--r--kipi-plugins/batchprocessimages/resizeoptionsdialog.h101
-rw-r--r--kipi-plugins/calendar/Makefile.am21
-rw-r--r--kipi-plugins/calendar/calevents.cpp79
-rw-r--r--kipi-plugins/calendar/calevents.h50
-rw-r--r--kipi-plugins/calendar/caleventsbase.ui210
-rw-r--r--kipi-plugins/calendar/calformatter.cpp218
-rw-r--r--kipi-plugins/calendar/calformatter.h62
-rw-r--r--kipi-plugins/calendar/calpainter.cpp625
-rw-r--r--kipi-plugins/calendar/calpainter.h104
-rw-r--r--kipi-plugins/calendar/calprint.h28
-rw-r--r--kipi-plugins/calendar/calselect.cpp166
-rw-r--r--kipi-plugins/calendar/calselect.h66
-rw-r--r--kipi-plugins/calendar/calsettings.cpp74
-rw-r--r--kipi-plugins/calendar/calsettings.h88
-rw-r--r--kipi-plugins/calendar/caltemplate.cpp259
-rw-r--r--kipi-plugins/calendar/caltemplate.h75
-rw-r--r--kipi-plugins/calendar/calwidget.cpp88
-rw-r--r--kipi-plugins/calendar/calwidget.h59
-rw-r--r--kipi-plugins/calendar/calwizard.cpp348
-rw-r--r--kipi-plugins/calendar/calwizard.h107
-rw-r--r--kipi-plugins/calendar/kipiplugin_calendar.desktop62
-rw-r--r--kipi-plugins/calendar/monthwidget.cpp195
-rw-r--r--kipi-plugins/calendar/monthwidget.h77
-rw-r--r--kipi-plugins/calendar/plugin_calendar.cpp98
-rw-r--r--kipi-plugins/calendar/plugin_calendar.h56
-rw-r--r--kipi-plugins/cdarchiving/Makefile.am30
-rw-r--r--kipi-plugins/cdarchiving/actions.h66
-rw-r--r--kipi-plugins/cdarchiving/autorun/Makefile.am6
-rw-r--r--kipi-plugins/cdarchiving/autorun/ShellExecute.bat1
-rw-r--r--kipi-plugins/cdarchiving/autorun/cdalbums.icobin0 -> 7358 bytes
-rw-r--r--kipi-plugins/cdarchiving/autorun/index.htm5
-rw-r--r--kipi-plugins/cdarchiving/cdarchiving.cpp1942
-rw-r--r--kipi-plugins/cdarchiving/cdarchiving.h220
-rw-r--r--kipi-plugins/cdarchiving/cdarchivingdialog.cpp902
-rw-r--r--kipi-plugins/cdarchiving/cdarchivingdialog.h249
-rw-r--r--kipi-plugins/cdarchiving/gohome.pngbin0 -> 5212 bytes
-rw-r--r--kipi-plugins/cdarchiving/image_broken.pngbin0 -> 5456 bytes
-rw-r--r--kipi-plugins/cdarchiving/kipiplugin_cdarchiving.desktop57
-rw-r--r--kipi-plugins/cdarchiving/plugin_cdarchiving.cpp350
-rw-r--r--kipi-plugins/cdarchiving/plugin_cdarchiving.h72
-rw-r--r--kipi-plugins/cdarchiving/up.pngbin0 -> 5462 bytes
-rw-r--r--kipi-plugins/cdarchiving/valid-html401.pngbin0 -> 2948 bytes
-rw-r--r--kipi-plugins/common/Makefile.am2
-rw-r--r--kipi-plugins/common/include/kpaboutdata.h51
-rw-r--r--kipi-plugins/common/include/pluginsversion.h27
-rw-r--r--kipi-plugins/common/libkipiplugins/Makefile.am14
-rw-r--r--kipi-plugins/common/libkipiplugins/kpaboutdata.cpp69
-rw-r--r--kipi-plugins/configure.in.bot158
-rw-r--r--kipi-plugins/configure.in.in476
-rw-r--r--kipi-plugins/findimages/Doxyfile1228
-rw-r--r--kipi-plugins/findimages/Makefile.am29
-rw-r--r--kipi-plugins/findimages/actions.cpp52
-rw-r--r--kipi-plugins/findimages/actions.h69
-rw-r--r--kipi-plugins/findimages/compareoperation.h40
-rw-r--r--kipi-plugins/findimages/displaycompare.cpp463
-rw-r--r--kipi-plugins/findimages/displaycompare.h117
-rw-r--r--kipi-plugins/findimages/fastcompare.cpp191
-rw-r--r--kipi-plugins/findimages/fastcompare.h55
-rw-r--r--kipi-plugins/findimages/finddupplicatedialog.cpp337
-rw-r--r--kipi-plugins/findimages/finddupplicatedialog.h122
-rw-r--r--kipi-plugins/findimages/finddupplicateimages.cpp436
-rw-r--r--kipi-plugins/findimages/finddupplicateimages.h103
-rw-r--r--kipi-plugins/findimages/fuzzycompare.cpp344
-rw-r--r--kipi-plugins/findimages/fuzzycompare.h64
-rw-r--r--kipi-plugins/findimages/hi32-action-finddupplicateimages.pngbin0 -> 2282 bytes
-rw-r--r--kipi-plugins/findimages/imagesimilaritydata.h74
-rw-r--r--kipi-plugins/findimages/kipiplugin_findimages.desktop59
-rw-r--r--kipi-plugins/findimages/plugin_findimages.cpp311
-rw-r--r--kipi-plugins/findimages/plugin_findimages.h75
-rw-r--r--kipi-plugins/flickrexport/Makefile.am23
-rw-r--r--kipi-plugins/flickrexport/TODO5
-rw-r--r--kipi-plugins/flickrexport/flickralbumdialog.ui197
-rw-r--r--kipi-plugins/flickrexport/flickritem.h140
-rw-r--r--kipi-plugins/flickrexport/flickrtalker.cpp1020
-rw-r--r--kipi-plugins/flickrexport/flickrtalker.h151
-rw-r--r--kipi-plugins/flickrexport/flickrviewitem.cpp107
-rw-r--r--kipi-plugins/flickrexport/flickrviewitem.h60
-rw-r--r--kipi-plugins/flickrexport/flickrwidget.cpp218
-rw-r--r--kipi-plugins/flickrexport/flickrwidget.h102
-rw-r--r--kipi-plugins/flickrexport/flickrwindow.cpp588
-rw-r--r--kipi-plugins/flickrexport/flickrwindow.h167
-rw-r--r--kipi-plugins/flickrexport/imageslist.cpp342
-rw-r--r--kipi-plugins/flickrexport/imageslist.h122
-rw-r--r--kipi-plugins/flickrexport/kipiplugin_flickrexport.desktop55
-rw-r--r--kipi-plugins/flickrexport/login.cpp123
-rw-r--r--kipi-plugins/flickrexport/login.h59
-rw-r--r--kipi-plugins/flickrexport/mpform.cpp163
-rw-r--r--kipi-plugins/flickrexport/mpform.h61
-rw-r--r--kipi-plugins/flickrexport/plugin_flickrexport.cpp114
-rw-r--r--kipi-plugins/flickrexport/plugin_flickrexport.h56
-rw-r--r--kipi-plugins/galleryexport/Makefile.am31
-rw-r--r--kipi-plugins/galleryexport/TODO13
-rw-r--r--kipi-plugins/galleryexport/galleries.cpp250
-rw-r--r--kipi-plugins/galleryexport/galleries.h112
-rw-r--r--kipi-plugins/galleryexport/gallery.pngbin0 -> 29021 bytes
-rw-r--r--kipi-plugins/galleryexport/galleryalbumdialog.ui197
-rw-r--r--kipi-plugins/galleryexport/galleryconfig.cpp161
-rw-r--r--kipi-plugins/galleryexport/galleryconfig.h59
-rw-r--r--kipi-plugins/galleryexport/galleryitem.h88
-rw-r--r--kipi-plugins/galleryexport/gallerylist.cpp208
-rw-r--r--kipi-plugins/galleryexport/gallerylist.h61
-rw-r--r--kipi-plugins/galleryexport/gallerympform.cpp182
-rw-r--r--kipi-plugins/galleryexport/gallerympform.h57
-rw-r--r--kipi-plugins/galleryexport/gallerytalker.cpp681
-rw-r--r--kipi-plugins/galleryexport/gallerytalker.h118
-rw-r--r--kipi-plugins/galleryexport/galleryviewitem.cpp93
-rw-r--r--kipi-plugins/galleryexport/galleryviewitem.h55
-rw-r--r--kipi-plugins/galleryexport/gallerywidget.cpp167
-rw-r--r--kipi-plugins/galleryexport/gallerywidget.h62
-rw-r--r--kipi-plugins/galleryexport/gallerywindow.cpp654
-rw-r--r--kipi-plugins/galleryexport/gallerywindow.h108
-rw-r--r--kipi-plugins/galleryexport/kipiplugin_galleryexport.desktop59
-rw-r--r--kipi-plugins/galleryexport/plugin_galleryexport.cpp190
-rw-r--r--kipi-plugins/galleryexport/plugin_galleryexport.h67
-rw-r--r--kipi-plugins/gpssync/Makefile.am35
-rw-r--r--kipi-plugins/gpssync/getlonlat.php186
-rw-r--r--kipi-plugins/gpssync/getlonlatalt.php206
-rw-r--r--kipi-plugins/gpssync/gpsbabelbinary.cpp125
-rw-r--r--kipi-plugins/gpssync/gpsbabelbinary.h66
-rw-r--r--kipi-plugins/gpssync/gpsdatacontainer.h78
-rw-r--r--kipi-plugins/gpssync/gpsdataparser.cpp275
-rw-r--r--kipi-plugins/gpssync/gpsdataparser.h74
-rw-r--r--kipi-plugins/gpssync/gpseditdialog.cpp339
-rw-r--r--kipi-plugins/gpssync/gpseditdialog.h79
-rw-r--r--kipi-plugins/gpssync/gpslistviewitem.cpp246
-rw-r--r--kipi-plugins/gpssync/gpslistviewitem.h83
-rw-r--r--kipi-plugins/gpssync/gpsmapwidget.cpp188
-rw-r--r--kipi-plugins/gpssync/gpsmapwidget.h82
-rw-r--r--kipi-plugins/gpssync/gpssyncdialog.cpp548
-rw-r--r--kipi-plugins/gpssync/gpssyncdialog.h87
-rw-r--r--kipi-plugins/gpssync/hi16-action-gpsimagetag.pngbin0 -> 908 bytes
-rw-r--r--kipi-plugins/gpssync/hi32-action-gpsimagetag.pngbin0 -> 2436 bytes
-rw-r--r--kipi-plugins/gpssync/kipiplugin_gpssync.desktop40
-rw-r--r--kipi-plugins/gpssync/kmlexport.cpp523
-rw-r--r--kipi-plugins/gpssync/kmlexport.h195
-rw-r--r--kipi-plugins/gpssync/kmlexportconfig.cpp479
-rw-r--r--kipi-plugins/gpssync/kmlexportconfig.h138
-rw-r--r--kipi-plugins/gpssync/kmlgpsdataparser.cpp141
-rw-r--r--kipi-plugins/gpssync/kmlgpsdataparser.h107
-rw-r--r--kipi-plugins/gpssync/plugin_gpssync.cpp342
-rw-r--r--kipi-plugins/gpssync/plugin_gpssync.h66
-rw-r--r--kipi-plugins/helloworld/Makefile.am23
-rw-r--r--kipi-plugins/helloworld/kipiplugin_helloworld.desktop53
-rw-r--r--kipi-plugins/helloworld/plugin_helloworld.cpp185
-rw-r--r--kipi-plugins/helloworld/plugin_helloworld.h58
-rw-r--r--kipi-plugins/htmlexport/.vimrc4
-rw-r--r--kipi-plugins/htmlexport/Makefile.am39
-rw-r--r--kipi-plugins/htmlexport/THEME_HOWTO293
-rw-r--r--kipi-plugins/htmlexport/TODO8
-rw-r--r--kipi-plugins/htmlexport/abstractthemeparameter.cpp70
-rw-r--r--kipi-plugins/htmlexport/abstractthemeparameter.h72
-rw-r--r--kipi-plugins/htmlexport/colorthemeparameter.cpp48
-rw-r--r--kipi-plugins/htmlexport/colorthemeparameter.h46
-rw-r--r--kipi-plugins/htmlexport/galleryinfo.cpp61
-rw-r--r--kipi-plugins/htmlexport/galleryinfo.h97
-rw-r--r--kipi-plugins/htmlexport/generator.cpp532
-rw-r--r--kipi-plugins/htmlexport/generator.h56
-rw-r--r--kipi-plugins/htmlexport/htmlexportconfig.kcfg62
-rw-r--r--kipi-plugins/htmlexport/htmlexportconfig.kcfgc5
-rw-r--r--kipi-plugins/htmlexport/imagesettingspage.ui456
-rw-r--r--kipi-plugins/htmlexport/intthemeparameter.cpp77
-rw-r--r--kipi-plugins/htmlexport/intthemeparameter.h54
-rw-r--r--kipi-plugins/htmlexport/kipiplugin_htmlexport.desktop57
-rw-r--r--kipi-plugins/htmlexport/listthemeparameter.cpp91
-rw-r--r--kipi-plugins/htmlexport/listthemeparameter.h48
-rw-r--r--kipi-plugins/htmlexport/outputpage.ui83
-rw-r--r--kipi-plugins/htmlexport/plugin.cpp112
-rw-r--r--kipi-plugins/htmlexport/plugin.h55
-rw-r--r--kipi-plugins/htmlexport/stringthemeparameter.cpp45
-rw-r--r--kipi-plugins/htmlexport/stringthemeparameter.h40
-rw-r--r--kipi-plugins/htmlexport/theme.cpp211
-rw-r--r--kipi-plugins/htmlexport/theme.h78
-rw-r--r--kipi-plugins/htmlexport/themepage.ui41
-rw-r--r--kipi-plugins/htmlexport/themeparameterspage.ui92
-rw-r--r--kipi-plugins/htmlexport/themes/Makefile.am8
-rw-r--r--kipi-plugins/htmlexport/themes/classic/Makefile.am6
-rw-r--r--kipi-plugins/htmlexport/themes/classic/classic.desktop258
-rw-r--r--kipi-plugins/htmlexport/themes/classic/gohome.pngbin0 -> 5212 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/classic/template.xsl238
-rw-r--r--kipi-plugins/htmlexport/themes/classic/up.pngbin0 -> 5462 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/Makefile.am13
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/black.css82
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/blue.css82
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/brown.css82
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/cleanframes.desktop92
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/green.css115
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/lavender.css86
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/pink.css77
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/red.css82
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/star.pngbin0 -> 2776 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/template.xsl221
-rw-r--r--kipi-plugins/htmlexport/themes/cleanframes/yellow.css82
-rw-r--r--kipi-plugins/htmlexport/themes/frames/Makefile.am5
-rw-r--r--kipi-plugins/htmlexport/themes/frames/frames.desktop49
-rw-r--r--kipi-plugins/htmlexport/themes/frames/style.css121
-rw-r--r--kipi-plugins/htmlexport/themes/frames/template.xsl222
-rw-r--r--kipi-plugins/htmlexport/themes/matrix/Makefile.am6
-rw-r--r--kipi-plugins/htmlexport/themes/matrix/bg.pngbin0 -> 28639 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/matrix/matrix.desktop40
-rw-r--r--kipi-plugins/htmlexport/themes/matrix/style.css82
-rw-r--r--kipi-plugins/htmlexport/themes/matrix/template.xsl187
-rw-r--r--kipi-plugins/htmlexport/themes/s0/Makefile.am10
-rw-r--r--kipi-plugins/htmlexport/themes/s0/arrows_source.svg130
-rw-r--r--kipi-plugins/htmlexport/themes/s0/next.pngbin0 -> 1054 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/s0/next_disabled.pngbin0 -> 1197 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/s0/previous.pngbin0 -> 1056 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/s0/previous_disabled.pngbin0 -> 1163 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/s0/s0.desktop36
-rw-r--r--kipi-plugins/htmlexport/themes/s0/style.css112
-rw-r--r--kipi-plugins/htmlexport/themes/s0/template.xsl161
-rw-r--r--kipi-plugins/htmlexport/themes/s0/up.pngbin0 -> 849 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/simple/Makefile.am6
-rw-r--r--kipi-plugins/htmlexport/themes/simple/dark.css76
-rw-r--r--kipi-plugins/htmlexport/themes/simple/natural.css72
-rw-r--r--kipi-plugins/htmlexport/themes/simple/simple.desktop88
-rw-r--r--kipi-plugins/htmlexport/themes/simple/template.xsl169
-rw-r--r--kipi-plugins/htmlexport/themes/snow/Makefile.am6
-rw-r--r--kipi-plugins/htmlexport/themes/snow/next.pngbin0 -> 2352 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/snow/next.svg180
-rw-r--r--kipi-plugins/htmlexport/themes/snow/next_disabled.pngbin0 -> 2363 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/snow/previous.pngbin0 -> 2258 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/snow/previous_disabled.pngbin0 -> 2277 bytes
-rw-r--r--kipi-plugins/htmlexport/themes/snow/snow.desktop59
-rw-r--r--kipi-plugins/htmlexport/themes/snow/style.css67
-rw-r--r--kipi-plugins/htmlexport/themes/snow/template.xsl164
-rw-r--r--kipi-plugins/htmlexport/wizard.cpp298
-rw-r--r--kipi-plugins/htmlexport/wizard.h60
-rw-r--r--kipi-plugins/htmlexport/xmlutils.h156
-rw-r--r--kipi-plugins/imageviewer/Makefile.am25
-rw-r--r--kipi-plugins/imageviewer/README69
-rw-r--r--kipi-plugins/imageviewer/TODO2
-rw-r--r--kipi-plugins/imageviewer/cursors/Makefile.am3
-rw-r--r--kipi-plugins/imageviewer/cursors/hand.pngbin0 -> 168 bytes
-rw-r--r--kipi-plugins/imageviewer/cursors/nullImage.pngbin0 -> 83245 bytes
-rw-r--r--kipi-plugins/imageviewer/cursors/zoom.pngbin0 -> 352 bytes
-rw-r--r--kipi-plugins/imageviewer/help.ui122
-rw-r--r--kipi-plugins/imageviewer/hi16-action-ogl.pngbin0 -> 1033 bytes
-rw-r--r--kipi-plugins/imageviewer/hi32-action-ogl.pngbin0 -> 2749 bytes
-rw-r--r--kipi-plugins/imageviewer/kipiplugin_viewer.desktop49
-rw-r--r--kipi-plugins/imageviewer/plugin_viewer.cpp116
-rw-r--r--kipi-plugins/imageviewer/plugin_viewer.h55
-rw-r--r--kipi-plugins/imageviewer/texture.cpp440
-rw-r--r--kipi-plugins/imageviewer/texture.h80
-rw-r--r--kipi-plugins/imageviewer/timer.cpp45
-rw-r--r--kipi-plugins/imageviewer/timer.h43
-rw-r--r--kipi-plugins/imageviewer/viewerwidget.cpp690
-rw-r--r--kipi-plugins/imageviewer/viewerwidget.h129
-rw-r--r--kipi-plugins/ipodexport/Makefile.am27
-rw-r--r--kipi-plugins/ipodexport/imagelist.cpp145
-rw-r--r--kipi-plugins/ipodexport/imagelist.h60
-rw-r--r--kipi-plugins/ipodexport/imagelistitem.h47
-rw-r--r--kipi-plugins/ipodexport/ipodexportdialog.cpp798
-rw-r--r--kipi-plugins/ipodexport/ipodexportdialog.h136
-rw-r--r--kipi-plugins/ipodexport/ipodheader.cpp125
-rw-r--r--kipi-plugins/ipodexport/ipodheader.h56
-rw-r--r--kipi-plugins/ipodexport/ipodlistitem.cpp70
-rw-r--r--kipi-plugins/ipodexport/ipodlistitem.h56
-rw-r--r--kipi-plugins/ipodexport/kipiplugin_ipodexport.desktop45
-rw-r--r--kipi-plugins/ipodexport/plugin_ipodexport.cpp75
-rw-r--r--kipi-plugins/ipodexport/plugin_ipodexport.h41
-rw-r--r--kipi-plugins/jpeglossless/Makefile.am29
-rw-r--r--kipi-plugins/jpeglossless/actions.h74
-rw-r--r--kipi-plugins/jpeglossless/actionthread.cpp237
-rw-r--r--kipi-plugins/jpeglossless/actionthread.h94
-rw-r--r--kipi-plugins/jpeglossless/convert2grayscale.cpp270
-rw-r--r--kipi-plugins/jpeglossless/convert2grayscale.h67
-rw-r--r--kipi-plugins/jpeglossless/imageflip.cpp226
-rw-r--r--kipi-plugins/jpeglossless/imageflip.h71
-rw-r--r--kipi-plugins/jpeglossless/imagerotate.cpp249
-rw-r--r--kipi-plugins/jpeglossless/imagerotate.h72
-rw-r--r--kipi-plugins/jpeglossless/jinclude.h96
-rw-r--r--kipi-plugins/jpeglossless/jpegint.h392
-rw-r--r--kipi-plugins/jpeglossless/jpegtransform.cpp441
-rw-r--r--kipi-plugins/jpeglossless/jpegtransform.h132
-rw-r--r--kipi-plugins/jpeglossless/kipiplugin_jpeglossless.desktop55
-rw-r--r--kipi-plugins/jpeglossless/libjpeg62.README385
-rw-r--r--kipi-plugins/jpeglossless/mtqueue.h89
-rw-r--r--kipi-plugins/jpeglossless/pics/Makefile.am2
-rw-r--r--kipi-plugins/jpeglossless/pics/hi32-action-flip.pngbin0 -> 1402 bytes
-rw-r--r--kipi-plugins/jpeglossless/pics/hi32-action-grayscaleconvert.pngbin0 -> 1405 bytes
-rw-r--r--kipi-plugins/jpeglossless/plugin_jpeglossless.cpp503
-rw-r--r--kipi-plugins/jpeglossless/plugin_jpeglossless.h87
-rw-r--r--kipi-plugins/jpeglossless/transupp.cpp940
-rw-r--r--kipi-plugins/jpeglossless/transupp.h145
-rw-r--r--kipi-plugins/jpeglossless/utils.cpp302
-rw-r--r--kipi-plugins/jpeglossless/utils.h82
-rw-r--r--kipi-plugins/kameraklient/Makefile.am29
-rw-r--r--kipi-plugins/kameraklient/camerafolderitem.cpp76
-rw-r--r--kipi-plugins/kameraklient/camerafolderitem.h54
-rw-r--r--kipi-plugins/kameraklient/camerafolderview.cpp115
-rw-r--r--kipi-plugins/kameraklient/camerafolderview.h68
-rw-r--r--kipi-plugins/kameraklient/cameraiconitem.cpp100
-rw-r--r--kipi-plugins/kameraklient/cameraiconitem.h59
-rw-r--r--kipi-plugins/kameraklient/cameraiconview.cpp144
-rw-r--r--kipi-plugins/kameraklient/cameraiconview.h69
-rw-r--r--kipi-plugins/kameraklient/cameralist.cpp172
-rw-r--r--kipi-plugins/kameraklient/cameralist.h64
-rw-r--r--kipi-plugins/kameraklient/cameraselection.cpp266
-rw-r--r--kipi-plugins/kameraklient/cameraselection.h93
-rw-r--r--kipi-plugins/kameraklient/cameratype.cpp80
-rw-r--r--kipi-plugins/kameraklient/cameratype.h53
-rw-r--r--kipi-plugins/kameraklient/cameraui.cpp667
-rw-r--r--kipi-plugins/kameraklient/cameraui.h188
-rw-r--r--kipi-plugins/kameraklient/dmessagebox.cpp119
-rw-r--r--kipi-plugins/kameraklient/dmessagebox.h61
-rw-r--r--kipi-plugins/kameraklient/gpcamera.cpp601
-rw-r--r--kipi-plugins/kameraklient/gpcamera.h93
-rw-r--r--kipi-plugins/kameraklient/gpcommand.h259
-rw-r--r--kipi-plugins/kameraklient/gpcontroller.cpp457
-rw-r--r--kipi-plugins/kameraklient/gpcontroller.h99
-rw-r--r--kipi-plugins/kameraklient/gpeventfilter.cpp128
-rw-r--r--kipi-plugins/kameraklient/gpeventfilter.h62
-rw-r--r--kipi-plugins/kameraklient/gpevents.h243
-rw-r--r--kipi-plugins/kameraklient/gpfileitemcontainer.cpp243
-rw-r--r--kipi-plugins/kameraklient/gpfileitemcontainer.h98
-rw-r--r--kipi-plugins/kameraklient/gpfileiteminfo.cpp121
-rw-r--r--kipi-plugins/kameraklient/gpfileiteminfo.h77
-rw-r--r--kipi-plugins/kameraklient/gpfileiteminfodlg.cpp163
-rw-r--r--kipi-plugins/kameraklient/gpfileiteminfodlg.h46
-rw-r--r--kipi-plugins/kameraklient/gpiface.cpp143
-rw-r--r--kipi-plugins/kameraklient/gpiface.h42
-rw-r--r--kipi-plugins/kameraklient/gpmessages.cpp42
-rw-r--r--kipi-plugins/kameraklient/gpmessages.h52
-rw-r--r--kipi-plugins/kameraklient/gpstatus.cpp103
-rw-r--r--kipi-plugins/kameraklient/gpstatus.h62
-rw-r--r--kipi-plugins/kameraklient/hi16-action-documents.pngbin0 -> 640 bytes
-rw-r--r--kipi-plugins/kameraklient/hi16-action-generic.pngbin0 -> 440 bytes
-rw-r--r--kipi-plugins/kameraklient/hi16-action-multimedia.pngbin0 -> 877 bytes
-rw-r--r--kipi-plugins/kameraklient/hi16-action-new.pngbin0 -> 524 bytes
-rw-r--r--kipi-plugins/kameraklient/hi16-action-pictures.pngbin0 -> 905 bytes
-rw-r--r--kipi-plugins/kameraklient/hi16-action-sound.pngbin0 -> 826 bytes
-rw-r--r--kipi-plugins/kameraklient/hi22-action-documents.pngbin0 -> 952 bytes
-rw-r--r--kipi-plugins/kameraklient/hi22-action-generic.pngbin0 -> 565 bytes
-rw-r--r--kipi-plugins/kameraklient/hi22-action-multimedia.pngbin0 -> 1359 bytes
-rw-r--r--kipi-plugins/kameraklient/hi22-action-new.pngbin0 -> 777 bytes
-rw-r--r--kipi-plugins/kameraklient/hi22-action-pictures.pngbin0 -> 1407 bytes
-rw-r--r--kipi-plugins/kameraklient/hi22-action-sound.pngbin0 -> 1266 bytes
-rw-r--r--kipi-plugins/kameraklient/hi32-action-documents.pngbin0 -> 1501 bytes
-rw-r--r--kipi-plugins/kameraklient/hi32-action-generic.pngbin0 -> 733 bytes
-rw-r--r--kipi-plugins/kameraklient/hi32-action-multimedia.pngbin0 -> 2384 bytes
-rw-r--r--kipi-plugins/kameraklient/hi32-action-new.pngbin0 -> 1302 bytes
-rw-r--r--kipi-plugins/kameraklient/hi32-action-pictures.pngbin0 -> 2474 bytes
-rw-r--r--kipi-plugins/kameraklient/hi32-action-sound.pngbin0 -> 2186 bytes
-rw-r--r--kipi-plugins/kameraklient/hi48-action-documents.pngbin0 -> 2121 bytes
-rw-r--r--kipi-plugins/kameraklient/hi48-action-generic.pngbin0 -> 1129 bytes
-rw-r--r--kipi-plugins/kameraklient/hi48-action-multimedia.pngbin0 -> 4315 bytes
-rw-r--r--kipi-plugins/kameraklient/hi48-action-new.pngbin0 -> 2436 bytes
-rw-r--r--kipi-plugins/kameraklient/hi48-action-pictures.pngbin0 -> 4456 bytes
-rw-r--r--kipi-plugins/kameraklient/hi48-action-sound.pngbin0 -> 3876 bytes
-rw-r--r--kipi-plugins/kameraklient/kameraklient.cpp77
-rw-r--r--kipi-plugins/kameraklient/kameraklient.h51
-rw-r--r--kipi-plugins/kameraklient/kipiplugin_kameraklient.desktop48
-rw-r--r--kipi-plugins/kameraklient/mtlist.h204
-rw-r--r--kipi-plugins/kameraklient/mtqueue.h80
-rw-r--r--kipi-plugins/kameraklient/savefiledialog.cpp75
-rw-r--r--kipi-plugins/kameraklient/savefiledialog.h66
-rw-r--r--kipi-plugins/kameraklient/setupcamera.cpp245
-rw-r--r--kipi-plugins/kameraklient/setupcamera.h79
-rw-r--r--kipi-plugins/kameraklient/thumbitem.cpp383
-rw-r--r--kipi-plugins/kameraklient/thumbitem.h101
-rw-r--r--kipi-plugins/kameraklient/thumbview.cpp1028
-rw-r--r--kipi-plugins/kameraklient/thumbview.h124
-rw-r--r--kipi-plugins/kipi-plugins.lsm17
-rw-r--r--kipi-plugins/kipiplugins.kdevelop217
-rw-r--r--kipi-plugins/metadataedit/Makefile.am38
-rw-r--r--kipi-plugins/metadataedit/commenteditdialog.cpp221
-rw-r--r--kipi-plugins/metadataedit/commenteditdialog.h80
-rw-r--r--kipi-plugins/metadataedit/commentremovedialog.cpp219
-rw-r--r--kipi-plugins/metadataedit/commentremovedialog.h76
-rw-r--r--kipi-plugins/metadataedit/exifadjust.cpp369
-rw-r--r--kipi-plugins/metadataedit/exifadjust.h59
-rw-r--r--kipi-plugins/metadataedit/exifcaption.cpp385
-rw-r--r--kipi-plugins/metadataedit/exifcaption.h70
-rw-r--r--kipi-plugins/metadataedit/exifdatetime.cpp421
-rw-r--r--kipi-plugins/metadataedit/exifdatetime.h68
-rw-r--r--kipi-plugins/metadataedit/exifdevice.cpp772
-rw-r--r--kipi-plugins/metadataedit/exifdevice.h59
-rw-r--r--kipi-plugins/metadataedit/exifeditdialog.cpp384
-rw-r--r--kipi-plugins/metadataedit/exifeditdialog.h88
-rw-r--r--kipi-plugins/metadataedit/exiflens.cpp425
-rw-r--r--kipi-plugins/metadataedit/exiflens.h59
-rw-r--r--kipi-plugins/metadataedit/exiflight.cpp375
-rw-r--r--kipi-plugins/metadataedit/exiflight.h59
-rw-r--r--kipi-plugins/metadataedit/iptccaption.cpp350
-rw-r--r--kipi-plugins/metadataedit/iptccaption.h69
-rw-r--r--kipi-plugins/metadataedit/iptccategories.cpp309
-rw-r--r--kipi-plugins/metadataedit/iptccategories.h65
-rw-r--r--kipi-plugins/metadataedit/iptccredits.cpp350
-rw-r--r--kipi-plugins/metadataedit/iptccredits.h59
-rw-r--r--kipi-plugins/metadataedit/iptcdatetime.cpp501
-rw-r--r--kipi-plugins/metadataedit/iptcdatetime.h67
-rw-r--r--kipi-plugins/metadataedit/iptceditdialog.cpp412
-rw-r--r--kipi-plugins/metadataedit/iptceditdialog.h83
-rw-r--r--kipi-plugins/metadataedit/iptckeywords.cpp250
-rw-r--r--kipi-plugins/metadataedit/iptckeywords.h65
-rw-r--r--kipi-plugins/metadataedit/iptcorigin.cpp683
-rw-r--r--kipi-plugins/metadataedit/iptcorigin.h59
-rw-r--r--kipi-plugins/metadataedit/iptcstatus.cpp485
-rw-r--r--kipi-plugins/metadataedit/iptcstatus.h59
-rw-r--r--kipi-plugins/metadataedit/iptcsubjects.cpp250
-rw-r--r--kipi-plugins/metadataedit/iptcsubjects.h65
-rw-r--r--kipi-plugins/metadataedit/kipiplugin_metadataedit.desktop46
-rw-r--r--kipi-plugins/metadataedit/metadatacheckbox.cpp62
-rw-r--r--kipi-plugins/metadataedit/metadatacheckbox.h59
-rw-r--r--kipi-plugins/metadataedit/plugin_metadataedit.cpp588
-rw-r--r--kipi-plugins/metadataedit/plugin_metadataedit.h63
-rw-r--r--kipi-plugins/mpegencoder/Makefile.am29
-rw-r--r--kipi-plugins/mpegencoder/checkbinprog.cpp133
-rw-r--r--kipi-plugins/mpegencoder/checkbinprog.h52
-rwxr-xr-xkipi-plugins/mpegencoder/images2mpg957
-rw-r--r--kipi-plugins/mpegencoder/images2mpg.1192
-rw-r--r--kipi-plugins/mpegencoder/kimg2mpg.cpp1238
-rw-r--r--kipi-plugins/mpegencoder/kimg2mpg.h183
-rw-r--r--kipi-plugins/mpegencoder/kimg2mpgbase.ui1341
-rw-r--r--kipi-plugins/mpegencoder/kipiplugin_mpegencoder.desktop54
-rw-r--r--kipi-plugins/mpegencoder/kshowdebuggingoutput.cpp82
-rw-r--r--kipi-plugins/mpegencoder/kshowdebuggingoutput.h62
-rw-r--r--kipi-plugins/mpegencoder/optionsdialog.cpp134
-rw-r--r--kipi-plugins/mpegencoder/optionsdialog.h63
-rw-r--r--kipi-plugins/mpegencoder/plugin_mpegencoder.cpp119
-rw-r--r--kipi-plugins/mpegencoder/plugin_mpegencoder.h51
-rw-r--r--kipi-plugins/picasawebexport/Makefile.am22
-rw-r--r--kipi-plugins/picasawebexport/PicasawebNewAlbumDialog.ui237
-rw-r--r--kipi-plugins/picasawebexport/kipiplugin_picasawebexport.desktop42
-rw-r--r--kipi-plugins/picasawebexport/mpform.cpp181
-rw-r--r--kipi-plugins/picasawebexport/mpform.h61
-rw-r--r--kipi-plugins/picasawebexport/picasawebitem.h135
-rw-r--r--kipi-plugins/picasawebexport/picasaweblogin.cpp145
-rw-r--r--kipi-plugins/picasawebexport/picasaweblogin.h61
-rw-r--r--kipi-plugins/picasawebexport/picasawebtalker.cpp959
-rw-r--r--kipi-plugins/picasawebexport/picasawebtalker.h165
-rw-r--r--kipi-plugins/picasawebexport/picasawebviewitem.cpp87
-rw-r--r--kipi-plugins/picasawebexport/picasawebviewitem.h65
-rw-r--r--kipi-plugins/picasawebexport/picasawebwidget.cpp80
-rw-r--r--kipi-plugins/picasawebexport/picasawebwidget.h78
-rw-r--r--kipi-plugins/picasawebexport/picasawebwindow.cpp594
-rw-r--r--kipi-plugins/picasawebexport/picasawebwindow.h173
-rw-r--r--kipi-plugins/picasawebexport/plugin_picasawebexport.cpp114
-rw-r--r--kipi-plugins/picasawebexport/plugin_picasawebexport.h60
-rw-r--r--kipi-plugins/picasawebexport/uploadwidget.ui442
-rw-r--r--kipi-plugins/printwizard/Makefile.am20
-rw-r--r--kipi-plugins/printwizard/cropframe.cpp315
-rw-r--r--kipi-plugins/printwizard/cropframe.h69
-rw-r--r--kipi-plugins/printwizard/frmprintwizard.cpp1988
-rw-r--r--kipi-plugins/printwizard/frmprintwizard.h154
-rw-r--r--kipi-plugins/printwizard/frmprintwizardbase.ui2330
-rw-r--r--kipi-plugins/printwizard/kipiplugin_printwizard.desktop62
-rw-r--r--kipi-plugins/printwizard/plugin_printwizard.cpp128
-rw-r--r--kipi-plugins/printwizard/plugin_printwizard.h52
-rw-r--r--kipi-plugins/printwizard/tphoto.cpp152
-rw-r--r--kipi-plugins/printwizard/tphoto.h74
-rw-r--r--kipi-plugins/printwizard/utils.cpp95
-rw-r--r--kipi-plugins/printwizard/utils.h37
-rw-r--r--kipi-plugins/rawconverter/Makefile.am28
-rw-r--r--kipi-plugins/rawconverter/actions.h63
-rw-r--r--kipi-plugins/rawconverter/actionthread.cpp267
-rw-r--r--kipi-plugins/rawconverter/actionthread.h103
-rw-r--r--kipi-plugins/rawconverter/batchdialog.cpp661
-rw-r--r--kipi-plugins/rawconverter/batchdialog.h130
-rw-r--r--kipi-plugins/rawconverter/clistviewitem.h116
-rw-r--r--kipi-plugins/rawconverter/iccjpeg.c270
-rw-r--r--kipi-plugins/rawconverter/iccjpeg.h96
-rw-r--r--kipi-plugins/rawconverter/kipiplugin_rawconverter.desktop55
-rw-r--r--kipi-plugins/rawconverter/mtqueue.h87
-rw-r--r--kipi-plugins/rawconverter/pics/Makefile.am2
-rw-r--r--kipi-plugins/rawconverter/pics/hi128-action-rawconverterbatch.pngbin0 -> 18146 bytes
-rw-r--r--kipi-plugins/rawconverter/pics/hi128-action-rawconvertersingle.pngbin0 -> 18192 bytes
-rw-r--r--kipi-plugins/rawconverter/plugin_rawconverter.cpp225
-rw-r--r--kipi-plugins/rawconverter/plugin_rawconverter.h64
-rw-r--r--kipi-plugins/rawconverter/previewwidget.cpp198
-rw-r--r--kipi-plugins/rawconverter/previewwidget.h71
-rw-r--r--kipi-plugins/rawconverter/profiles/Makefile.am2
-rw-r--r--kipi-plugins/rawconverter/profiles/adobergb.icmbin0 -> 2036 bytes
-rw-r--r--kipi-plugins/rawconverter/profiles/prophoto.icmbin0 -> 566 bytes
-rw-r--r--kipi-plugins/rawconverter/profiles/srgb.icmbin0 -> 2032 bytes
-rw-r--r--kipi-plugins/rawconverter/profiles/widegamut.icmbin0 -> 2044 bytes
-rw-r--r--kipi-plugins/rawconverter/rawdecodingiface.cpp668
-rw-r--r--kipi-plugins/rawconverter/rawdecodingiface.h101
-rw-r--r--kipi-plugins/rawconverter/savesettingswidget.cpp153
-rw-r--r--kipi-plugins/rawconverter/savesettingswidget.h79
-rw-r--r--kipi-plugins/rawconverter/singledialog.cpp597
-rw-r--r--kipi-plugins/rawconverter/singledialog.h124
-rw-r--r--kipi-plugins/sendimages/Makefile.am29
-rw-r--r--kipi-plugins/sendimages/actions.h62
-rw-r--r--kipi-plugins/sendimages/kipiplugin_sendimages.desktop57
-rw-r--r--kipi-plugins/sendimages/listimageserrordialog.cpp92
-rw-r--r--kipi-plugins/sendimages/listimageserrordialog.h55
-rw-r--r--kipi-plugins/sendimages/plugin_sendimages.cpp292
-rw-r--r--kipi-plugins/sendimages/plugin_sendimages.h74
-rw-r--r--kipi-plugins/sendimages/sendimages.cpp944
-rw-r--r--kipi-plugins/sendimages/sendimages.h190
-rw-r--r--kipi-plugins/sendimages/sendimagesdialog.cpp689
-rw-r--r--kipi-plugins/sendimages/sendimagesdialog.h173
-rw-r--r--kipi-plugins/simpleviewerexport/Makefile.am25
-rw-r--r--kipi-plugins/simpleviewerexport/firstrundlg.cpp161
-rw-r--r--kipi-plugins/simpleviewerexport/firstrundlg.h92
-rw-r--r--kipi-plugins/simpleviewerexport/index.template96
-rw-r--r--kipi-plugins/simpleviewerexport/kipiplugin_simpleviewer.desktop39
-rw-r--r--kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp93
-rw-r--r--kipi-plugins/simpleviewerexport/plugin_simpleviewer.h55
-rw-r--r--kipi-plugins/simpleviewerexport/simpleviewerexport.cpp728
-rw-r--r--kipi-plugins/simpleviewerexport/simpleviewerexport.h175
-rw-r--r--kipi-plugins/simpleviewerexport/space.pngbin0 -> 153 bytes
-rw-r--r--kipi-plugins/simpleviewerexport/svedialog.cpp517
-rw-r--r--kipi-plugins/simpleviewerexport/svedialog.h157
-rw-r--r--kipi-plugins/slideshow/Makefile.am30
-rw-r--r--kipi-plugins/slideshow/hi22-action-slideshow.pngbin0 -> 710 bytes
-rw-r--r--kipi-plugins/slideshow/imageloadthread.cpp180
-rw-r--r--kipi-plugins/slideshow/imageloadthread.h88
-rw-r--r--kipi-plugins/slideshow/kbeffect.cpp192
-rw-r--r--kipi-plugins/slideshow/kbeffect.h101
-rw-r--r--kipi-plugins/slideshow/kipiplugin_slideshow.desktop60
-rw-r--r--kipi-plugins/slideshow/listimageitems.cpp87
-rw-r--r--kipi-plugins/slideshow/listimageitems.h84
-rw-r--r--kipi-plugins/slideshow/plugin_slideshow.cpp267
-rw-r--r--kipi-plugins/slideshow/plugin_slideshow.h69
-rw-r--r--kipi-plugins/slideshow/screenproperties.cpp105
-rw-r--r--kipi-plugins/slideshow/screenproperties.h49
-rw-r--r--kipi-plugins/slideshow/slideshow.cpp1214
-rw-r--r--kipi-plugins/slideshow/slideshow.h189
-rw-r--r--kipi-plugins/slideshow/slideshowconfig.cpp785
-rw-r--r--kipi-plugins/slideshow/slideshowconfig.h121
-rw-r--r--kipi-plugins/slideshow/slideshowconfigbase.ui1522
-rw-r--r--kipi-plugins/slideshow/slideshowgl.cpp1508
-rw-r--r--kipi-plugins/slideshow/slideshowgl.h172
-rw-r--r--kipi-plugins/slideshow/slideshowkb.cpp578
-rw-r--r--kipi-plugins/slideshow/slideshowkb.h190
-rw-r--r--kipi-plugins/slideshow/slideshowloader.cpp219
-rw-r--r--kipi-plugins/slideshow/slideshowloader.h109
-rw-r--r--kipi-plugins/slideshow/toolbar.cpp192
-rw-r--r--kipi-plugins/slideshow/toolbar.h84
-rw-r--r--kipi-plugins/sync/Makefile.am33
-rw-r--r--kipi-plugins/sync/TODO13
-rw-r--r--kipi-plugins/sync/gallery.pngbin0 -> 29021 bytes
-rw-r--r--kipi-plugins/sync/galleryalbumdialog.ui197
-rw-r--r--kipi-plugins/sync/galleryconfig.cpp161
-rw-r--r--kipi-plugins/sync/galleryconfig.h59
-rw-r--r--kipi-plugins/sync/galleryitem.h88
-rw-r--r--kipi-plugins/sync/galleryviewitem.cpp93
-rw-r--r--kipi-plugins/sync/galleryviewitem.h55
-rw-r--r--kipi-plugins/sync/gallerywidget.cpp157
-rw-r--r--kipi-plugins/sync/gallerywidget.h60
-rw-r--r--kipi-plugins/sync/gallerywindow.cpp637
-rw-r--r--kipi-plugins/sync/gallerywindow.h106
-rw-r--r--kipi-plugins/sync/kipiplugin_sync.desktop41
-rw-r--r--kipi-plugins/sync/libkipi2/collection.cpp78
-rw-r--r--kipi-plugins/sync/libkipi2/collection.h84
-rw-r--r--kipi-plugins/sync/libkipi2/interface.cpp3
-rw-r--r--kipi-plugins/sync/libkipi2/interface.h35
-rw-r--r--kipi-plugins/sync/libkipi2/item.cpp25
-rw-r--r--kipi-plugins/sync/libkipi2/item.h34
-rw-r--r--kipi-plugins/sync/plugin_sync.cpp195
-rw-r--r--kipi-plugins/sync/plugin_sync.h68
-rw-r--r--kipi-plugins/sync/sink.cpp112
-rw-r--r--kipi-plugins/sync/sink.h89
-rw-r--r--kipi-plugins/sync/sinkfactory.cpp46
-rw-r--r--kipi-plugins/sync/sinkfactory.h62
-rw-r--r--kipi-plugins/sync/sinklist.cpp169
-rw-r--r--kipi-plugins/sync/sinklist.h60
-rw-r--r--kipi-plugins/sync/sinklistbase.ui180
-rw-r--r--kipi-plugins/sync/sinks.cpp191
-rw-r--r--kipi-plugins/sync/sinks.h81
-rw-r--r--kipi-plugins/sync/sinks/gallery/gallerycollection.cpp20
-rw-r--r--kipi-plugins/sync/sinks/gallery/gallerycollection.h29
-rw-r--r--kipi-plugins/sync/sinks/gallery/galleryform.cpp135
-rw-r--r--kipi-plugins/sync/sinks/gallery/galleryform.h61
-rw-r--r--kipi-plugins/sync/sinks/gallery/galleryitem.cpp19
-rw-r--r--kipi-plugins/sync/sinks/gallery/galleryitem.h29
-rw-r--r--kipi-plugins/sync/sinks/gallery/gallerysink.cpp686
-rw-r--r--kipi-plugins/sync/sinks/gallery/gallerysink.h120
-rw-r--r--kipi-plugins/timeadjust/Makefile.am25
-rw-r--r--kipi-plugins/timeadjust/kipiplugin_timeadjust.desktop55
-rw-r--r--kipi-plugins/timeadjust/plugin_timeadjust.cpp106
-rw-r--r--kipi-plugins/timeadjust/plugin_timeadjust.h55
-rw-r--r--kipi-plugins/timeadjust/timeadjustdialog.cpp550
-rw-r--r--kipi-plugins/timeadjust/timeadjustdialog.h84
-rw-r--r--kipi-plugins/tips238
-rw-r--r--kipi-plugins/wallpaper/Makefile.am18
-rw-r--r--kipi-plugins/wallpaper/kipiplugin_wallpaper.desktop62
-rw-r--r--kipi-plugins/wallpaper/plugin_wallpaper.cpp274
-rw-r--r--kipi-plugins/wallpaper/plugin_wallpaper.h81
653 files changed, 122997 insertions, 0 deletions
diff --git a/kipi-plugins/AUTHORS b/kipi-plugins/AUTHORS
new file mode 100644
index 0000000..831f702
--- /dev/null
+++ b/kipi-plugins/AUTHORS
@@ -0,0 +1,63 @@
+KIPI-PLUGINS TEAM :
+
+MAIN DEVELOPERS:
+Gilles Caulier <caulier dot gilles at gmail dot com>
+Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+Vardhman Jain <vardhman at gmail.com>
+Colin Guthrie <kde at colin dot guthr dot ie>
+Aurelien Gateau <aurelien dot gateau at free.fr>
+Valerio Fuoglio <valerio dot fuoglio at gmail com>
+Angelo Naselli <anaselli at linux dot it>
+Seb Ruiz <me at sebruiz dot net>
+Jesper K. Pedersen <blackie at kde.org>
+Kare Sars <kare dot sars at kolumbus dot fi>
+
+CONTRIBUTORS:
+Gerhard Kulzer <gerhard at kulzer dot net>
+Orgad Shaneh <orgads at gmail dot com>
+Achim Bohnet <ach at mpe dot mpg dot de>
+Michael Hoechstetter <michael dot hoechstetter at gmx dot de>
+Joern Ahrens <joern dot ahrens at kdemail dot net>
+Ruediger Bente <ruediger dot bente at gmx dot de>
+Beth Marmorstein <purplegamba at cox dot net>
+Robert Marmorstein <rmmarm at sdf dot lonestar dot org>
+Richard Groult <Richard dot Groult at jalix.org>
+
+OLD CONTRIBUTORS:
+Tudor Calin <tudor at 1xtech dot com>
+Owen Hirst <n8rider at sbcglobal dot net>
+Todd Shoemaker <todd at theshoemakers dot net>
+Gregory Kokanosky <gregory dot kokanosky at free dot fr>
+
+PLUGINS MAINTAINERS
+Acquire images : Gilles Caulier and Kare Sars
+Jpeglossless : Gilles Caulier and Marcel Wiesweg
+Raw converter : Gilles Caulier and Marcel Wiesweg
+GPSSync : Gilles Caulier
+MetadataEdit : Gilles Caulier
+Time adjust : Gilles Caulier
+Flickr export : Vardhman jain
+PicasaWeb export : Vardhman jain
+Gallery export : Colin Guthrie
+Cd archiving : Angelo Naselli
+Print wizard : Angelo Naselli
+Mpeg encoder : Angelo Naselli and Valerio Fuoglio
+Slideshow : Valerio Fuoglio
+Batch Process : Aurelien Gateau
+HTML export : Aurelien Gateau
+Kamera Klient : Aurelien Gateau and Michael J Gruber
+Ipod export : Seb Ruiz
+Calendar : Orgad Shaneh
+Image viewer : Markus Leuthold
+Sendimages : Michael Hoechstetter
+Simpleviewer export : Joern Ahrens
+Find images : Jesper K. Pedersen and Richard Groult
+Wallpaper : Jesper K. Pedersen
+
+PROJECT COORDINATOR:
+Angelo Naselli <anaselli at linux dot it>
+
+FORMER MAINTAINER:
+Renchi Raju <renchi at pooh.tam.uiuc.edu>
+Tom Albers <tomalbers at kde.nl>
+Ralf Hoelzer <kde at ralfhoelzer dot com>
diff --git a/kipi-plugins/COPYING b/kipi-plugins/COPYING
new file mode 100644
index 0000000..0fc8a21
--- /dev/null
+++ b/kipi-plugins/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Steet, 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Steet, 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.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/kipi-plugins/ChangeLog b/kipi-plugins/ChangeLog
new file mode 100644
index 0000000..e7c7b90
--- /dev/null
+++ b/kipi-plugins/ChangeLog
@@ -0,0 +1,16185 @@
+V 0.1.7 - 2008-12-13
+----------------------------------------------------------------------------
+
+2008-12-11 04:42 cgilles
+
+ * NEWS: update
+
+2008-12-10 22:30 gateau
+
+ * batchprocessimages/renameimagesbase.ui,
+ batchprocessimages/renameimageswidget.cpp: Applied patches from
+ Piotr Tarnowski and tomas to provide more formating
+ options to the batch renamer.
+ BUG:132982
+
+2008-12-08 15:07 cgilles
+
+ * NEWS: update
+
+2008-12-08 15:04 cgilles
+
+ * NEWS: update
+
+2008-12-08 15:03 cgilles
+
+ * NEWS: update
+
+2008-12-08 15:01 cgilles
+
+ * NEWS: update
+
+2008-12-08 09:49 cgilles
+
+ * NEWS: update
+
+2008-12-08 08:34 cgilles
+
+ * NEWS: update
+
+2008-12-08 08:16 cgilles
+
+ * NEWS: update
+
+2008-12-08 08:08 cgilles
+
+ * NEWS: update
+
+2008-12-08 07:51 cgilles
+
+ * NEWS: update
+
+2008-12-08 07:49 cgilles
+
+ * NEWS: update
+
+2008-12-08 05:03 cgilles
+
+ * NEWS: update
+
+2008-12-08 05:02 cgilles
+
+ * NEWS: update
+
+2008-12-08 05:00 cgilles
+
+ * NEWS: update
+
+2008-12-08 04:59 cgilles
+
+ * NEWS: update
+
+2008-12-07 19:49 cgilles
+
+ * NEWS: update
+
+2008-12-01 17:19 cgilles
+
+ * metadataedit/exifdevice.cpp, metadataedit/exifdevice.h: fix url
+ BUG: 176640
+
+2008-11-17 09:45 cgilles
+
+ * gpssync/gpseditdialog.cpp: backport commit #885395 from trunk
+
+2008-11-16 18:44 cgilles
+
+ * NEWS: update
+
+2008-11-15 21:26 cgilles
+
+ * picasawebexport/picasaweblogin.cpp,
+ picasawebexport/picasawebtalker.cpp: backport commit #884771 from
+ trunk
+
+2008-11-14 04:58 cgilles
+
+ * NEWS: update
+
+2008-11-05 17:43 cgilles
+
+ * NEWS, common/include/kpaboutdata.h,
+ common/include/pluginsversion.h,
+ common/libkipiplugins/kpaboutdata.cpp, kipi-plugins.lsm: dump
+ version
+
+2008-11-04 19:41 cgilles
+
+ * gpssync/gpseditdialog.cpp, gpssync/gpsmapwidget.cpp: sync with
+ trunk : fix crash about new Google API
+
+2008-10-11 12:36 cgilles
+
+ * common/include/pluginsversion.h: prepare 0.1.6
+
+2008-10-11 12:36 cgilles
+
+ * README, kipi-plugins.lsm: prepare 0.1.6
+
+2008-10-11 12:34 cgilles
+
+ * ChangeLog: prepare 0.1.6
+
+2008-10-11 12:27 cgilles
+
+ * NEWS: prepare 0.1.6
+
+V 0.1.6 - 2008-10-11
+----------------------------------------------------------------------------
+
+2008-10-06 06:07 cgilles
+
+ * NEWS: update
+
+2008-09-14 16:36 cgilles
+
+ * rawconverter/rawdecodingiface.cpp: compile
+
+2008-09-14 13:30 cgilles
+
+ * rawconverter/plugin_rawconverter.cpp: compile with new libkdcraw
+
+2008-09-14 13:27 cgilles
+
+ * printwizard/tphoto.cpp: compile with new libkdcraw
+
+2008-09-14 13:26 cgilles
+
+ * simpleviewerexport/simpleviewerexport.cpp: compile with new
+ libkdcraw
+
+2008-09-14 13:25 cgilles
+
+ * sendimages/sendimages.cpp: compile with new libkdcraw
+
+2008-09-14 13:21 cgilles
+
+ * picasawebexport/picasawebtalker.cpp: compile with new libkdcraw
+
+2008-09-14 13:20 cgilles
+
+ * jpeglossless/utils.cpp: compile with new libkdcraw
+
+2008-09-14 13:19 cgilles
+
+ * imageviewer/texture.cpp: compile with new libkdcraw
+
+2008-09-14 13:18 cgilles
+
+ * flickrexport/flickrtalker.cpp: compile with new libkdcraw
+
+2008-08-27 18:59 cgilles
+
+ * NEWS: update
+
+2008-08-27 18:59 cgilles
+
+ * NEWS: update
+
+2008-08-27 18:58 cgilles
+
+ * NEWS: update
+
+2008-08-27 18:13 jaiva
+
+ * picasawebexport/picasawebtalker.cpp,
+ picasawebexport/picasawebwindow.cpp: Fixing the upload photo to
+ allow uploading in albums with spaces in the album name,
+ basically changed the upload post url to use album id instead of
+ album name.
+
+ BUG:1501912
+
+2008-08-11 19:13 cgilles
+
+ * rawconverter/rawdecodingiface.cpp: do not record IPTC preview
+ into JPEG.
+
+2008-08-07 13:52 cgilles
+
+ * rawconverter/batchdialog.cpp, rawconverter/singledialog.cpp:
+ support median filter passes
+
+2008-08-07 10:09 cgilles
+
+ * rawconverter/batchdialog.cpp, rawconverter/singledialog.cpp:
+ polish
+
+2008-08-07 09:43 cgilles
+
+ * rawconverter/batchdialog.cpp, rawconverter/singledialog.cpp:
+ compile with older libkdcraw
+
+2008-08-07 09:21 cgilles
+
+ * rawconverter/batchdialog.cpp, rawconverter/singledialog.cpp:
+ compile
+
+2008-08-06 08:57 cgilles
+
+ * rawconverter/singledialog.cpp: polish
+
+2008-08-06 08:51 cgilles
+
+ * rawconverter/batchdialog.cpp, rawconverter/singledialog.cpp:
+ added white point settings support
+
+2008-07-16 18:43 aclemens
+
+ * NEWS: update
+
+2008-07-16 11:19 aclemens
+
+ * printwizard/frmprintwizard.cpp: connection missing for
+ BtnCropRotate
+
+2008-07-16 11:09 aclemens
+
+ * printwizard/frmprintwizard.cpp: connections for crop buttons were
+ missing.
+
+ CCBUGS:166712
+
+2008-07-10 06:57 cgilles
+
+ * NEWS: update
+
+2008-07-09 13:35 cgilles
+
+ * gpssync/gpslistviewitem.cpp, gpssync/gpslistviewitem.h,
+ gpssync/plugin_gpssync.cpp: kipi-plugins from KDE3 branch : with
+ Exiv2 0.18, we will be able to set GPS info to TIFF files on the
+ fly. so, no need to limit GPS location recording to JPEG files.
+
+2008-07-08 13:12 cgilles
+
+ * rawconverter/rawdecodingiface.cpp: fix broken compilation with
+ gcc 4.3.1
+
+2008-07-07 21:26 kusi
+
+ * imageviewer/TODO, imageviewer/texture.cpp, imageviewer/texture.h,
+ imageviewer/viewerwidget.cpp, imageviewer/viewerwidget.h:
+ backport from kde4: respect exif orientation
+
+2008-07-03 13:34 cgilles
+
+ * jpeglossless/actionthread.cpp: backport commit #827616 from KDE4
+
+2008-06-23 06:29 cgilles
+
+ * rawconverter/rawdecodingiface.cpp: Tiff writer now generate a
+ thumb in IFD1
+
+2008-06-22 21:27 cgilles
+
+ * rawconverter/rawdecodingiface.cpp: polish
+
+2008-06-22 21:22 cgilles
+
+ * rawconverter/rawdecodingiface.cpp: Raw converter no store all
+ metadata to tiff file is Exiv2 0.18 is used
+
+2008-06-13 07:54 cgilles
+
+ * flickrexport/flickrwindow.cpp: backport commit #820103 from KDE4
+
+2008-06-11 10:27 cgilles
+
+ * flickrexport/imageslist.cpp: polish
+
+2008-06-10 17:15 aclemens
+
+ * cdarchiving/actions.h, cdarchiving/cdarchiving.cpp,
+ cdarchiving/cdarchiving.h, cdarchiving/cdarchivingdialog.cpp,
+ cdarchiving/cdarchivingdialog.h,
+ cdarchiving/plugin_cdarchiving.cpp,
+ cdarchiving/plugin_cdarchiving.h: * code cleanup
+ * fixed indentation
+
+2008-06-10 16:59 aclemens
+
+ * cdarchiving/cdarchiving.cpp, cdarchiving/cdarchiving.h,
+ cdarchiving/plugin_cdarchiving.cpp: fixed progress bar issue...
+ the number of total actions was not calculated correctly, so when
+ exporting many images, the progress bar didn't move for quite a
+ long time.
+
+ CCBUG: 163529
+ TODO: KDE4PORT
+
+2008-06-09 18:29 aclemens
+
+ * flickrexport/flickrwindow.cpp: check for HostSupportsTags moved
+ to readSettings() to make sure that everything is setup well
+
+2008-06-09 13:33 aclemens
+
+ * flickrexport/flickrwindow.cpp: "Strip Space..." checkbox should
+ only be enabled if "Use Host Application Tags" is set, too.
+
+2008-06-09 06:19 cgilles
+
+ * picasawebexport/mpform.cpp, picasawebexport/mpform.h:
+ kipi-plugins from KDE3 branch : Picasa Web Export tool : backport
+ MPForm class utf-8 support patch from HJ D Lee.
+ Jain, it's a simple fix backported from FlickrExport tool (see
+ B.K.O #155270).
+ Indeep tests are require with strings using Arab, asia, and
+ non-latin1 encoding.
+ CCMAIL: vardhman@gmail.com
+
+ Work for me. indeep tests are require especially with
+ asian/greek/arab/etc... charsets.
+
+2008-06-09 04:19 cgilles
+
+ * NEWS: update
+
+2008-06-06 15:27 jaiva
+
+ * picasawebexport/picasawebtalker.cpp,
+ picasawebexport/picasawebtalker.h,
+ picasawebexport/picasawebwindow.cpp: Added listAllAlbums()
+ replacing listAlbums() which now uses authenticated call to fetch
+ the list of all albums for the user including the unlisted
+ albums.
+
+ BUG:162994
+
+2008-06-03 14:54 cgilles
+
+ * TODO: update
+
+2008-05-28 08:02 cgilles
+
+ * flickrexport/imageslist.cpp: missing signal to toggle Upload
+ button when d&d is used from digiKam
+
+2008-05-28 08:00 cgilles
+
+ * flickrexport/imageslist.cpp: fix obsolete signal
+
+2008-05-27 09:40 cgilles
+
+ * NEWS: update
+
+2008-05-25 20:32 anaselli
+
+ * common/include/pluginsversion.h: SVN_SILENT: kipi-plugins 0.1.6 -
+ beta1
+
+2008-05-25 20:31 anaselli
+
+ * kipi-plugins.lsm: SVN_SILENT: kipi-plugins 0.1.6 - beta1
+
+2008-05-25 20:31 anaselli
+
+ * ChangeLog: SVN_SILENT: kipi-plugins 0.1.6 - beta1
+
+2008-05-25 20:17 anaselli
+
+ * NEWS: SVN_SILENT: kipi-plugins 0.1.6 - beta1
+
+V 0.1.6-beta1 - 2008-05-25
+----------------------------------------------------------------------------
+
+2008-05-25 09:06 cgilles
+
+ * [r812276] kipi-plugins/picasawebexport/picasaweblogin.cpp,
+ kipi-plugins/picasawebexport/picasawebtalker.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.cpp:
+ polish
+
+2008-05-23 19:14 cgilles
+
+ * [r811829] kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/imageslist.cpp,
+ kipi-plugins/flickrexport/imageslist.h:
+ add Drag & Drop support
+
+2008-05-23 17:41 cgilles
+
+ * [r811797]
+ kipi-plugins/picasawebexport/PicasawebNewAlbumDialog.ui.h:
+ auto build file. no need to store it to svn
+
+2008-05-23 05:00 cgilles
+
+ * [r811458] kipi-plugins/NEWS:
+ update
+
+2008-05-22 20:41 cgilles
+
+ * [r811388] kipi-plugins/flickrexport/flickrwindow.cpp:
+ disable host tags support if necessary
+
+2008-05-22 20:38 cgilles
+
+ * [r811385] kipi-plugins/NEWS:
+ update
+
+2008-05-22 20:37 cgilles
+
+ * [r811384] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h:
+ added new option to strip white space from host applications
+ tags.
+ BUGS: 153206
+
+2008-05-22 20:16 cgilles
+
+ * [r811371] kipi-plugins/NEWS:
+ update
+
+2008-05-22 20:15 cgilles
+
+ * [r811370] kipi-plugins/flickrexport/flickrtalker.cpp:
+ remove IPTC keywords from file to upload to prevent dupplicate
+ Tags entries in Flickr web interface
+ BUGS: 153207
+
+2008-05-22 20:00 cgilles
+
+ * [r811364] kipi-plugins/NEWS:
+ update
+
+2008-05-22 19:53 cgilles
+
+ * [r811360] kipi-plugins/picasawebexport/picasawebwindow.cpp,
+ kipi-plugins/picasawebexport/uploadwidget.ui:
+ fix layout
+
+2008-05-22 19:31 cgilles
+
+ * [r811352]
+ kipi-plugins/picasawebexport/PicasawebNewAlbumDialog.ui:
+ use namespace
+
+2008-05-22 19:23 cgilles
+
+ * [r811351] kipi-plugins/picasawebexport/picasawebwidget.h,
+ kipi-plugins/picasawebexport/uploadwidget.ui:
+ use name space
+
+2008-05-22 19:10 cgilles
+
+ * [r811347] kipi-plugins/picasawebexport/newAlbumWindow.cpp,
+ kipi-plugins/picasawebexport/newAlbumWindow.h:
+ unused files
+
+2008-05-22 19:08 cgilles
+
+ * [r811345] kipi-plugins/picasawebexport/picasawebitem.cpp:
+ this file is never used
+
+2008-05-22 19:07 cgilles
+
+ * [r811344] kipi-plugins/picasawebexport/picasawebitem.cpp,
+ kipi-plugins/picasawebexport/picasawebitem.h:
+ polish
+
+2008-05-22 19:02 cgilles
+
+ * [r811343] kipi-plugins/picasawebexport/picasaweblogin.cpp,
+ kipi-plugins/picasawebexport/picasaweblogin.h:
+ polish
+
+2008-05-22 18:57 cgilles
+
+ * [r811342] kipi-plugins/picasawebexport/picasawebviewitem.cpp,
+ kipi-plugins/picasawebexport/picasawebviewitem.h:
+ polish
+
+2008-05-22 18:53 cgilles
+
+ * [r811340] kipi-plugins/picasawebexport/picasawebwidget.cpp,
+ kipi-plugins/picasawebexport/picasawebwidget.h,
+ kipi-plugins/picasawebexport/picasawebwindow.cpp:
+ polish, fox header, fix coding style
+
+2008-05-22 18:45 cgilles
+
+ * [r811336] kipi-plugins/picasawebexport/mpform.cpp,
+ kipi-plugins/picasawebexport/mpform.h:
+ polish
+
+2008-05-22 18:23 cgilles
+
+ * [r811301] kipi-plugins/picasawebexport/picasawebwindow.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.h:
+ polish
+
+2008-05-22 14:40 cgilles
+
+ * [r811190] kipi-plugins/NEWS:
+ update
+
+2008-05-22 14:37 cgilles
+
+ * [r811187] kipi-plugins/picasawebexport/picasawebwindow.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.h:
+ use active window
+
+2008-05-22 14:15 cgilles
+
+ * [r811176] kipi-plugins/NEWS:
+ update
+
+2008-05-22 13:56 cgilles
+
+ * [r811168] kipi-plugins/NEWS:
+ update
+
+2008-05-22 13:38 cgilles
+
+ * [r811162] kipi-plugins/NEWS:
+ update
+
+2008-05-22 12:30 cgilles
+
+ * [r811145] kipi-plugins/picasawebexport/picasawebtalker.cpp:
+ support RAW file preview.
+
+2008-05-22 10:45 cgilles
+
+ * [r811120] kipi-plugins/NEWS:
+ update
+
+2008-05-22 10:36 cgilles
+
+ * [r811118] kipi-plugins/picasawebexport/picasawebwidget.h,
+ kipi-plugins/picasawebexport/picasawebwindow.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.h:
+ fix crash
+
+2008-05-22 10:25 cgilles
+
+ * [r811112] kipi-plugins/picasawebexport/picasawebtalker.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.h:
+ fix broken signals
+
+2008-05-22 10:13 cgilles
+
+ * [r811106] kipi-plugins/picasawebexport/picasawebtalker.cpp:
+ use active window
+
+2008-05-22 10:09 cgilles
+
+ * [r811104] kipi-plugins/picasawebexport/Makefile.am,
+ kipi-plugins/picasawebexport/exifrestorer.cpp,
+ kipi-plugins/picasawebexport/exifrestorer.h,
+ kipi-plugins/picasawebexport/jpegsection.h,
+ kipi-plugins/picasawebexport/picasawebtalker.cpp,
+ kipi-plugins/picasawebexport/picasawebtalker.h:
+ use libkexiv2 instead ExifRestorer
+
+2008-05-22 09:55 cgilles
+
+ * [r811098] kipi-plugins/picasawebexport/Makefile.am:
+ link with libkdcraw and libkexiv2
+
+2008-05-22 09:11 cgilles
+
+ * [r811092] kipi-plugins/flickrexport/flickrwidget.cpp:
+ polish
+
+2008-05-22 09:09 cgilles
+
+ * [r811091] kipi-plugins/flickrexport/flickrwidget.cpp:
+ added tooltip
+
+2008-05-22 09:01 cgilles
+
+ * [r811090] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/mpform.cpp:
+ apply MPForm class utf-8 support patch from HJ D Lee.
+
+ Work for me. indeep tests are require especially with
+ asian/greek/arab/etc... charsets.
+
+ CCBUGS: 155270
+
+2008-05-22 08:51 cgilles
+
+ * [r811089] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h:
+ polish
+
+2008-05-22 08:47 cgilles
+
+ * [r811088] kipi-plugins/flickrexport/flickrwidget.cpp:
+ fix layout. Polish again and again and again
+
+2008-05-22 08:38 cgilles
+
+ * [r811087] kipi-plugins/flickrexport/flickrwindow.cpp:
+ toogle to list of items during dowload
+
+2008-05-22 08:29 cgilles
+
+ * [r811085] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h,
+ kipi-plugins/flickrexport/imageslist.cpp,
+ kipi-plugins/flickrexport/imageslist.h:
+ when an image is uploaded to Flickr, remove item from the list
+
+2008-05-22 07:54 cgilles
+
+ * [r811074] kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h,
+ kipi-plugins/flickrexport/imageslist.cpp,
+ kipi-plugins/flickrexport/imageslist.h:
+ enable/disable upload button is list is empty or not
+
+2008-05-21 20:12 cgilles
+
+ * [r810906] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h,
+ kipi-plugins/flickrexport/imageslist.cpp,
+ kipi-plugins/flickrexport/imageslist.h:
+ enable image list in dialog. fully suitable now
+
+2008-05-21 17:55 cgilles
+
+ * [r810839] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/imageslist.cpp:
+ polish
+
+2008-05-21 17:47 cgilles
+
+ * [r810837] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/imageslist.cpp:
+ polish
+
+2008-05-21 14:44 cgilles
+
+ * [r810758] kipi-plugins/flickrexport/imageslist.cpp,
+ kipi-plugins/flickrexport/imageslist.h:
+ fix namespace
+
+2008-05-21 14:42 cgilles
+
+ * [r810757] kipi-plugins/flickrexport/Makefile.am,
+ kipi-plugins/flickrexport/imageslist.cpp,
+ kipi-plugins/flickrexport/imageslist.h:
+ new image list widget. not yet suitable.
+
+2008-05-21 13:41 cgilles
+
+ * [r810741] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h:
+ use KTabWidget to separate uploading options and files list
+
+2008-05-21 13:02 cgilles
+
+ * [r810730] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h:
+ polish
+
+2008-05-21 12:57 cgilles
+
+ * [r810727] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h:
+ polish
+
+2008-05-21 12:35 cgilles
+
+ * [r810724] kipi-plugins/flickrexport/flickrwindow.cpp:
+ polish
+
+2008-05-21 12:22 cgilles
+
+ * [r810720] kipi-plugins/flickrexport/mpform.cpp:
+ polish
+
+2008-05-21 12:12 cgilles
+
+ * [r810718] kipi-plugins/flickrexport/mpform.cpp,
+ kipi-plugins/flickrexport/mpform.h:
+ polish
+
+2008-05-21 12:00 cgilles
+
+ * [r810715] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h:
+ getPhotoProperty method use getApiSig method based on KURL
+
+2008-05-21 11:25 cgilles
+
+ * [r810706] kipi-plugins/flickrexport/flickrtalker.cpp:
+ listPhotoSets method use getApiSig method based on KURL
+
+2008-05-21 11:15 cgilles
+
+ * [r810703] kipi-plugins/flickrexport/flickrtalker.cpp:
+ slotAuthenticate method use getApiSig method based on KURL
+
+2008-05-21 11:10 cgilles
+
+ * [r810700] kipi-plugins/flickrexport/flickrtalker.cpp:
+ checkToken method use getApiSig method based on KURL
+
+2008-05-21 11:06 cgilles
+
+ * [r810696] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h:
+ getFrob method use getApiSig method based on KURL
+
+2008-05-21 10:40 cgilles
+
+ * [r810688] kipi-plugins/flickrexport/flickrwidget.cpp:
+ polish
+
+2008-05-21 10:39 cgilles
+
+ * [r810686] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h:
+ add link to flickr
+
+2008-05-21 10:01 cgilles
+
+ * [r810683] kipi-plugins/flickrexport/flickrwindow.cpp:
+ polish
+
+2008-05-21 09:07 cgilles
+
+ * [r810652] kipi-plugins/NEWS:
+ update
+
+2008-05-21 09:05 cgilles
+
+ * [r810651] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h:
+ kipi-plugins from KDE3 branch : FlickrExport tool : UTF-8 support
+ - Use KURL to host addPhoto url
+ - new method to compute MD5 signature based on KURL.
+
+ I have tested to upload photo using accentuate char from Tags or
+ comments. Now all work fine.
+
+ BUGS: 153758
+ CCBUGS: 155270
+
+2008-05-21 04:39 cgilles
+
+ * [r810603] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h:
+ polish
+
+2008-05-21 04:32 cgilles
+
+ * [r810600] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h:
+ polish
+
+2008-05-20 20:11 cgilles
+
+ * [r810472] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwindow.cpp:
+ add button icons
+
+2008-05-20 19:58 cgilles
+
+ * [r810467] kipi-plugins/flickrexport/flickrwidget.cpp:
+ set icon on button
+
+2008-05-20 17:34 cgilles
+
+ * [r810414] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp:
+ fix memory leak. there is 2 instance of authorization dialog
+ created at the same time
+
+2008-05-20 17:14 cgilles
+
+ * [r810408] kipi-plugins/flickrexport/flickrtalker.cpp:
+ use active window to open message box
+
+2008-05-20 17:02 cgilles
+
+ * [r810405] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h:
+ save and restore all dialog settings
+
+2008-05-20 16:39 cgilles
+
+ * [r810396] kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h:
+ polish
+
+2008-05-20 14:56 cgilles
+
+ * [r810368] kipi-plugins/flickrexport/flickrtalker.cpp:
+ polish
+
+2008-05-20 13:56 cgilles
+
+ * [r810343] kipi-plugins/flickrexport/flickrtalker.cpp:
+ polish
+
+2008-05-20 13:49 cgilles
+
+ * [r810336] kipi-plugins/flickrexport/flickrtalker.cpp:
+ polish
+
+2008-05-20 13:46 cgilles
+
+ * [r810334] kipi-plugins/flickrexport/flickrwindow.cpp:
+ polish
+
+2008-05-20 13:44 cgilles
+
+ * [r810332] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwindow.cpp:
+ polish
+
+2008-05-20 13:15 cgilles
+
+ * [r810311] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwindow.cpp:
+ polish
+
+2008-05-20 13:05 cgilles
+
+ * [r810304] kipi-plugins/flickrexport/flickrwidget.cpp:
+ fix layout
+
+2008-05-20 12:58 cgilles
+
+ * [r810302] kipi-plugins/flickrexport/flickrtalker.cpp:
+ polish
+
+2008-05-20 12:57 cgilles
+
+ * [r810301] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h:
+ fix API
+
+2008-05-20 12:48 cgilles
+
+ * [r810298] kipi-plugins/NEWS:
+ update
+
+2008-05-20 12:45 cgilles
+
+ * [r810297] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrwidget.cpp:
+ kipi-plugins from KDE3 branch : severals improvements into
+ FlickrExport tool:
+
+ - added support RAW files: embeded JPEG preview is used to export
+ RAW image to Flickr
+ - all others image formats supported by Qt are properlly drived
+ now. The uploaded image is always converted to JPEG.
+ Uploading work with previous implementation _only_ if image been
+ resized.
+ - plugin dialog layout rewritten. more suitable.
+
+ BUGS: 154289
+
+2008-05-20 11:41 cgilles
+
+ * [r810283] kipi-plugins/flickrexport/flickrwindow.cpp:
+ polish
+
+2008-05-20 09:56 cgilles
+
+ * [r810247] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h:
+ polish
+
+2008-05-20 09:53 cgilles
+
+ * [r810243] kipi-plugins/flickrexport/flickrwidget.cpp:
+ fix layout
+
+2008-05-20 09:48 cgilles
+
+ * [r810238] kipi-plugins/flickrexport/flickrwidget.cpp:
+ optimize layout
+
+2008-05-20 09:31 cgilles
+
+ * [r810231] kipi-plugins/flickrexport/flickrwidget.cpp:
+ fix layout
+
+2008-05-20 09:23 cgilles
+
+ * [r810225] kipi-plugins/flickrexport/flickrwidget.cpp:
+ fix spacing
+
+2008-05-20 09:05 cgilles
+
+ * [r810212] kipi-plugins/flickrexport/flickrwidget.cpp:
+ polish
+
+2008-05-20 08:57 cgilles
+
+ * [r810198] kipi-plugins/flickrexport/flickrwidget.cpp:
+ polish
+
+2008-05-20 08:52 cgilles
+
+ * [r810194] kipi-plugins/flickrexport/flickrwindow.cpp:
+ polish
+
+2008-05-20 08:25 cgilles
+
+ * [r810185] kipi-plugins/flickrexport/flickrwindow.cpp:
+ polish
+
+2008-05-20 08:23 cgilles
+
+ * [r810184] kipi-plugins/flickrexport/flickrwindow.cpp:
+ NULL => 0
+
+2008-05-20 08:13 cgilles
+
+ * [r810181] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h:
+ start to polish plugin GUI : move "Satrt Uploading" button to
+ dialog footer
+
+2008-05-20 08:04 cgilles
+
+ * [r810178] kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h:
+ fix i18n. polish
+
+2008-05-20 07:57 cgilles
+
+ * [r810175]
+ kipi-plugins/picasawebexport/plugin_picasawebexport.cpp,
+ kipi-plugins/picasawebexport/plugin_picasawebexport.h:
+ use icon
+
+2008-05-20 07:56 cgilles
+
+ * [r810174] kipi-plugins/flickrexport/plugin_flickrexport.cpp,
+ kipi-plugins/flickrexport/plugin_flickrexport.h:
+ polish
+
+2008-05-20 07:29 cgilles
+
+ * [r810169] kipi-plugins/flickrexport/plugin_flickrexport.cpp:
+ polish
+
+2008-05-20 07:24 cgilles
+
+ * [r810168] kipi-plugins/flickrexport/plugin_flickrexport.cpp:
+ use icon
+
+2008-05-20 07:21 cgilles
+
+ * [r810167] kipi-plugins/flickrexport/flickrwidget.cpp:
+ polish
+
+2008-05-20 06:44 cgilles
+
+ * [r810155] kipi-plugins/flickrexport/flickrviewitem.cpp,
+ kipi-plugins/flickrexport/flickrviewitem.h:
+ polish
+
+2008-05-20 06:38 cgilles
+
+ * [r810154] kipi-plugins/flickrexport/flickrviewitem.cpp,
+ kipi-plugins/flickrexport/flickrviewitem.h:
+ fix coding style
+
+2008-05-20 06:34 cgilles
+
+ * [r810153] kipi-plugins/flickrexport/flickrtalker.cpp:
+ polish
+
+2008-05-20 06:19 cgilles
+
+ * [r810150] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h:
+ polish
+
+2008-05-20 06:08 cgilles
+
+ * [r810149] kipi-plugins/flickrexport/mpform.cpp,
+ kipi-plugins/flickrexport/mpform.h,
+ kipi-plugins/flickrexport/plugin_flickrexport.cpp,
+ kipi-plugins/flickrexport/plugin_flickrexport.h:
+ polish
+
+2008-05-20 06:06 cgilles
+
+ * [r810148] kipi-plugins/flickrexport/login.cpp,
+ kipi-plugins/flickrexport/login.h:
+ polish
+
+2008-05-20 06:02 cgilles
+
+ * [r810147] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h:
+ polish
+
+2008-05-20 05:54 cgilles
+
+ * [r810146] kipi-plugins/flickrexport/flickritem.h:
+ fix coding style
+
+2008-05-19 21:27 cgilles
+
+ * [r810018] kipi-plugins/flickrexport/flickrtalker.cpp:
+ fix coding style
+
+2008-05-19 21:09 cgilles
+
+ * [r810000] kipi-plugins/flickrexport/ChangeLog,
+ kipi-plugins/flickrexport/Makefile.am,
+ kipi-plugins/flickrexport/exifrestorer.cpp,
+ kipi-plugins/flickrexport/exifrestorer.h,
+ kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h,
+ kipi-plugins/flickrexport/jpegsection.h:
+ do not use ExifRestorer. use Kexiv2 instead
+
+2008-05-19 20:44 cgilles
+
+ * [r809992] kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h:
+ fix header
+ fix coding style
+ fix moc includes
+
+2008-05-19 20:13 cgilles
+
+ * [r809975] kipi-plugins/flickrexport/login.cpp,
+ kipi-plugins/flickrexport/login.h,
+ kipi-plugins/flickrexport/mpform.cpp,
+ kipi-plugins/flickrexport/mpform.h,
+ kipi-plugins/flickrexport/plugin_flickrexport.cpp,
+ kipi-plugins/flickrexport/plugin_flickrexport.h:
+ fix header
+ fix coding style
+ fix moc includes
+
+2008-05-15 13:53 cgilles
+
+ * [r808044] kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/rawconverter/rawdecodingiface.cpp:
+ set IPTC preview size to 1280x1024 instead 800x600
+
+2008-05-07 12:10 cgilles
+
+ * [r805033] kipi-plugins/jpeglossless/transupp.cpp:
+ polish
+
+2008-05-07 11:55 cgilles
+
+ * [r805027] kipi-plugins/jpeglossless/transupp.cpp:
+ polish
+
+2008-05-06 21:28 mueller
+
+ * [r804757] kipi-plugins/picasawebexport/picasaweblogin.cpp,
+ kipi-plugins/picasawebexport/picasaweblogin.h:
+ those are setters, and not returning anything
+
+2008-05-06 21:27 mueller
+
+ * [r804756] kipi-plugins/slideshow/screenproperties.cpp:
+ always return at least something
+
+2008-05-02 06:56 cgilles
+
+ * [r803158] kipi-plugins/README:
+ update
+
+2008-03-18 20:46 cgilles
+
+ * [r787235] kipi-plugins/mpegencoder/plugin_mpegencoder.cpp:
+ fix action type from host
+
+2008-03-18 20:44 cgilles
+
+ * [r787234] kipi-plugins/ipodexport/plugin_ipodexport.cpp:
+ fix icon and action type from host
+
+2008-03-18 18:34 cgilles
+
+ * [r787182] kipi-plugins/kipi-plugins.lsm:
+ update
+
+2008-03-18 18:33 cgilles
+
+ * [r787181] kipi-plugins/common/include/pluginsversion.h:
+ update
+
+2008-03-18 12:02 cgilles
+
+ * [r786982] kipi-plugins/NEWS:
+ update
+
+2008-03-17 11:13 cgilles
+
+ * [r786550] kipi-plugins/NEWS:
+ update
+
+2008-03-17 11:12 cgilles
+
+ * [r786549] kipi-plugins/rawconverter/rawdecodingiface.cpp,
+ kipi-plugins/rawconverter/rawdecodingiface.h:
+ kipi-plugins from KD3 branch : RAWConverter : use 99 compression
+ level instead 100 with output JPEG images
+
+2008-03-17 10:55 cgilles
+
+ * [r786533] kipi-plugins/imagesgallery:
+ remove obsolete plugin
+
+2008-03-16 21:19 cgilles
+
+ * [r786367] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ polish
+
+2008-03-16 21:14 cgilles
+
+ * [r786365] kipi-plugins/NEWS:
+ update
+
+2008-03-16 21:12 cgilles
+
+ * [r786363] kipi-plugins/timeadjust/timeadjustdialog.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.h:
+ kipi-plugins from KDE3 branch : TimeAdjust : set all Exif Date
+ tags as excepted
+ BUG: 149890
+
+2008-03-16 20:56 cgilles
+
+ * [r786355] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ kipi-plugins from KDE3 branch : TimeAdjust : set file date time
+ after than Exiv2 play with metadata
+ CCBUGS: 149890
+
+2008-03-12 21:24 anaselli
+
+ * [r784955] kipi-plugins/configure.in.bot,
+ kipi-plugins/configure.in.in:
+ Added libkdcraw 0.1.3 dependency as needed. (Achim Bohnet)
+
+ CCMAIL: kde-imaging@kde.org
+
+----------------------------------------------------------------------------
+V 0.1.5 - 2008-03-09
+----------------------------------------------------------------------------
+
+2008-03-02 08:24 cgilles
+
+ * [r781200] kipi-plugins/simpleviewerexport/svedialog.cpp:
+ fix i18n
+
+2008-02-27 07:02 cgilles
+
+ * [r779860] kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.h:
+ backport commit #779856 from KDE4
+
+2008-02-26 11:21 cgilles
+
+ * [r779519] kipi-plugins/simpleviewerexport/Makefile.am,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ backport commit #779517 from KDE4
+
+2008-02-26 09:19 cgilles
+
+ * [r779484] kipi-plugins/simpleviewerexport/svedialog.cpp:
+ fix icon
+
+2008-02-26 06:57 cgilles
+
+ * [r779441] kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/printwizard/tphoto.cpp,
+ kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ backaport from KDE4 : use KDcrawIface::DCrawBinary::rawFiles()
+ everywhere
+
+2008-02-26 04:36 cgilles
+
+ * [r779427] kipi-plugins/NEWS:
+ update
+
+2008-02-26 04:35 cgilles
+
+ * [r779425] kipi-plugins/simpleviewerexport/Makefile.am,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ kipi-plugins from KDE3 branch : Flash Export tool now suppor Raw
+ files
+
+2008-02-25 20:05 cgilles
+
+ * [r779299] kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ compile
+
+2008-02-25 20:03 cgilles
+
+ * [r779298] kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.h:
+ backport commit #779285 from KDE4
+
+2008-02-25 13:41 cgilles
+
+ * [r779093] kipi-plugins/NEWS:
+ update
+
+2008-02-25 13:39 cgilles
+
+ * [r779092] kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ SimpleViewer Export from KDE3 branch : backport from KDE4 :
+ handle UTF-8 encoding with XML file
+ CCBUGS: 150393
+
+2008-02-25 13:06 cgilles
+
+ * [r779082] kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ kipi-plugins/calendar/calwizard.cpp,
+ kipi-plugins/cdarchiving/cdarchivingdialog.cpp,
+ kipi-plugins/findimages/displaycompare.cpp,
+ kipi-plugins/findimages/finddupplicatedialog.cpp,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/galleryexport/gallerywindow.cpp,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/htmlexport/wizard.cpp,
+ kipi-plugins/imagesgallery/imgallerydialog.cpp,
+ kipi-plugins/kameraklient/cameraselection.cpp,
+ kipi-plugins/kameraklient/cameraui.cpp,
+ kipi-plugins/kameraklient/setupcamera.cpp,
+ kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.cpp,
+ kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/sync/gallerywindow.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ fix release number
+
+2008-02-25 13:02 cgilles
+
+ * [r779081] kipi-plugins/simpleviewerexport/firstrundlg.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.cpp:
+ fix i18n
+
+2008-02-25 12:56 cgilles
+
+ * [r779080] kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ fix depreciate
+
+2008-02-25 12:52 cgilles
+
+ * [r779075] kipi-plugins/simpleviewerexport/svedialog.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.h:
+ polish
+
+2008-02-25 12:37 cgilles
+
+ * [r779068] kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ polish
+
+2008-02-25 12:21 cgilles
+
+ * [r779060] kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ polish
+
+2008-02-25 12:14 cgilles
+
+ * [r779058] kipi-plugins/simpleviewerexport/firstrundlg.cpp:
+ polish
+
+2008-02-25 12:09 cgilles
+
+ * [r779055] kipi-plugins/simpleviewerexport/firstrundlg.cpp,
+ kipi-plugins/simpleviewerexport/kipiplugin_simpleviewer.desktop:
+ polish
+
+2008-02-25 12:05 cgilles
+
+ * [r779053] kipi-plugins/NEWS:
+ update
+
+2008-02-25 11:57 cgilles
+
+ * [r779051] kipi-plugins/simpleviewerexport/Makefile.am,
+ kipi-plugins/simpleviewerexport/kipiplugin_simpleviewer.desktop,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.cpp:
+ SimpleViewerExport kipi-plugin from KDE3 branch : sync with KDE4.
+ now plugin is compatible with SimpleViewer 1.8.x
+ CCBUGS:134774
+
+2008-02-25 11:41 cgilles
+
+ * [r779048] kipi-plugins/simpleviewerexport/index.template,
+ kipi-plugins/simpleviewerexport/svedialog.cpp,
+ kipi-plugins/simpleviewerexport/upgrade.html:
+ sync with KDE4
+
+2008-02-25 09:37 cgilles
+
+ * [r779017] kipi-plugins/simpleviewerexport/firstrundlg.cpp,
+ kipi-plugins/simpleviewerexport/firstrundlg.h,
+ kipi-plugins/simpleviewerexport/svedialog.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.h:
+ sync with KDE4
+
+2008-02-25 09:30 cgilles
+
+ * [r779014] kipi-plugins/simpleviewerexport/firstrundlg.cpp,
+ kipi-plugins/simpleviewerexport/firstrundlg.h,
+ kipi-plugins/simpleviewerexport/svedialog.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.h:
+ sync with KDE4
+
+2008-02-25 09:20 cgilles
+
+ * [r779012] kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ kipi-plugins/acquireimages/screenshotdialog.cpp,
+ kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ kipi-plugins/calendar/calwizard.cpp,
+ kipi-plugins/cdarchiving/cdarchivingdialog.cpp,
+ kipi-plugins/findimages/displaycompare.cpp,
+ kipi-plugins/findimages/finddupplicatedialog.cpp,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/galleryexport/gallerywindow.cpp,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/htmlexport/wizard.cpp,
+ kipi-plugins/imagesgallery/imgallerydialog.cpp,
+ kipi-plugins/kameraklient/cameraselection.cpp,
+ kipi-plugins/kameraklient/cameraui.cpp,
+ kipi-plugins/kameraklient/setupcamera.cpp,
+ kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.cpp,
+ kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.cpp,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/sync/gallerywindow.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ use "Plugin Handbook" string everywhere (sync with KDE4)
+
+2008-02-25 07:12 cgilles
+
+ * [r778989] kipi-plugins/simpleviewerexport/firstrundlg.h,
+ kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp,
+ kipi-plugins/simpleviewerexport/plugin_simpleviewer.h,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.h,
+ kipi-plugins/simpleviewerexport/svedialog.h:
+ fix coding style again. Fix plugin action name
+
+2008-02-25 07:07 cgilles
+
+ * [r778988] kipi-plugins/simpleviewerexport/firstrundlg.cpp,
+ kipi-plugins/simpleviewerexport/firstrundlg.h,
+ kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp,
+ kipi-plugins/simpleviewerexport/plugin_simpleviewer.h,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.h,
+ kipi-plugins/simpleviewerexport/svedialog.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.h:
+ start to syn KDE3 branch with KDE4 fixes : fix headers and coding
+ style
+
+2008-02-24 21:33 cgilles
+
+ * [r778912] kipi-plugins/simpleviewerexport/test.txt:
+ dumy
+
+2008-02-24 21:33 cgilles
+
+ * [r778911] kipi-plugins/simpleviewerexport/index.html:
+ obsolete
+
+2008-02-24 21:32 cgilles
+
+ * [r778910] kipi-plugins/simpleviewerexport/README:
+ obsolete
+
+2008-02-24 21:31 cgilles
+
+ * [r778908] kipi-plugins/simpleviewerexport/Makefile.am:
+ enable i18n
+
+2008-02-22 14:24 vfuoglio
+
+ * [r778103] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/batchdialog.h,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/rawconverter/singledialog.h, libkdcraw/NEWS,
+ libkdcraw/libkdcraw/dcrawsettingswidget.cpp,
+ libkdcraw/libkdcraw/dcrawsettingswidget.h,
+ libkdcraw/libkdcraw/kdcraw.cpp, libkdcraw/libkdcraw/kdcraw.h,
+ libkdcraw/libkdcraw/rawdecodingsettings.h:
+ White balance with RAW files improvements (related to bug
+ #142055).
+
+ Patches by Guillaume Castagnino.
+
+ CCMAIL : kde-imaging@kde.org
+ CCMAIL : casta@xwing.info
+ CCMAIL : caulier.gilles@gmail.com
+
+2008-02-21 20:22 vfuoglio
+
+ * [r777878] kipi-plugins/NEWS, kipi-plugins/slideshow/Makefile.am:
+ Fixed linking error in slideshow/Makefile.am (missing -lXrandr).
+
+ Thanks to Rex Dieter for his patch.
+
+ CCMAIL: kde-imaging@kde.org
+ BUG: 158176
+
+2008-02-16 15:59 gkulzer
+
+ * [r775762] kipi-plugins/gpssync/gpseditdialog.cpp:
+ add moving the marker
+
+2008-02-16 13:50 gkulzer
+
+ * [r775673] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ fix i18n: positive time offset is pointing eastwards
+
+2008-02-14 06:43 gkulzer
+
+ * [r774825] kipi-plugins/gpssync/getlonlatalt.php:
+ add info about topocoding behaviour
+
+2008-02-13 10:45 gkulzer
+
+ * [r774491] kipi-plugins/gpssync/getlonlatalt.php,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h:
+ unused method remove, copyright update
+
+2008-02-13 09:00 gkulzer
+
+ * [r774421] kipi-plugins/gpssync/getlonlat.php:
+ revert, this stays lonlat, no alt here
+
+2008-02-13 08:37 gkulzer
+
+ * [r774411] kipi-plugins/gpssync/getlonlat.php,
+ kipi-plugins/gpssync/getlonlatalt.php,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h:
+ introduction of altitude service in geolocator
+ CCMAIL:caulier.gilles@gmail.com
+
+2008-02-09 22:20 anaselli
+
+ * [r773014] kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/printwizard/frmprintwizardbase.ui:
+ fixed dialog layout, it was broken with localization
+ added Valerio Fuoglio as contributor
+ GUI:
+ CCMAIL: valerio.fuoglio@gmail.com
+
+2008-02-09 18:26 cgilles
+
+ * [r772916] kipi-plugins/gpssync/getlonlat.php,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h:
+ sync with trunk
+
+2008-02-09 14:18 cgilles
+
+ * [r772721] kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.cpp:
+ compile
+
+2008-02-09 14:17 cgilles
+
+ * [r772719] kipi-plugins/findimages/displaycompare.cpp,
+ kipi-plugins/kameraklient/cameraselection.cpp,
+ kipi-plugins/kameraklient/setupcamera.cpp:
+ compile
+
+2008-02-09 14:15 cgilles
+
+ * [r772717] kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ kipi-plugins/acquireimages/screenshotdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ kipi-plugins/calendar/calwizard.cpp,
+ kipi-plugins/cdarchiving/cdarchivingdialog.cpp,
+ kipi-plugins/findimages/displaycompare.cpp,
+ kipi-plugins/findimages/finddupplicatedialog.cpp,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/galleryexport/gallerywindow.cpp,
+ kipi-plugins/htmlexport/wizard.cpp,
+ kipi-plugins/imagesgallery/imgallerydialog.cpp,
+ kipi-plugins/kameraklient/cameraselection.cpp,
+ kipi-plugins/kameraklient/cameraui.cpp,
+ kipi-plugins/kameraklient/setupcamera.cpp,
+ kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.cpp,
+ kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.cpp,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/sync/gallerywindow.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ set plugins version everywhere
+
+2008-02-09 14:04 cgilles
+
+ * [r772713] kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.cpp:
+ set version
+
+2008-02-09 13:40 cgilles
+
+ * [r772703] kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h:
+ polish
+
+2008-02-07 10:29 cgilles
+
+ * [r771961] kipi-plugins/gpssync/getlonlat.php:
+ restore map click event rules
+
+2008-02-07 10:07 cgilles
+
+ * [r771955] kipi-plugins/gpssync/getlonlat.php,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.cpp:
+ backport commit #771947 from KDE3 branch
+
+2008-02-06 17:31 cgilles
+
+ * [r771669] kipi-plugins/gpssync/getlonlat.php:
+ polish
+
+2008-02-06 14:48 cgilles
+
+ * [r771624] kipi-plugins/gpssync/getlonlat.php,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h:
+ backport commit #771622 to KDE3 branch
+
+2008-02-05 14:38 cgilles
+
+ * [r771230] kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h:
+ missing slotHelp
+
+2008-02-05 12:30 cgilles
+
+ * [r771172] kipi-plugins/gpssync/plugin_gpssync.cpp:
+ polish
+
+2008-02-04 19:50 cgilles
+
+ * [r770942] kipi-plugins/gpssync/gpsbabelbinary.cpp:
+ polish
+
+2008-02-04 19:47 cgilles
+
+ * [r770941] kipi-plugins/gpssync/gpsbabelbinary.cpp:
+ polish
+
+2008-02-04 14:45 cgilles
+
+ * [r770841] kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h:
+ polish
+
+2008-02-04 13:44 cgilles
+
+ * [r770765] kipi-plugins/NEWS:
+ update
+
+2008-02-04 13:43 cgilles
+
+ * [r770759] kipi-plugins/gpssync/getlonlat.php,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h:
+ kipi-plugins from KDE3 branch : GPSSync tool : remember google
+ map type between sessions
+ BUG: 152526
+
+2008-02-04 11:52 cgilles
+
+ * [r770689] kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h:
+ kipi-plugins from KDE3 branch : GPSSync tool : remember google
+ map zoom level between session
+ CCBUGS: 152526
+
+2008-02-04 11:17 cgilles
+
+ * [r770676] kipi-plugins/gpssync/kmlexport.cpp,
+ kipi-plugins/gpssync/kmlexport.h,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/gpssync/kmlgpsdataparser.cpp,
+ kipi-plugins/gpssync/kmlgpsdataparser.h:
+ polish
+
+2008-02-04 11:00 cgilles
+
+ * [r770671] kipi-plugins/gpssync/kmlexport.cpp,
+ kipi-plugins/gpssync/kmlexport.h,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.h,
+ kipi-plugins/gpssync/kmlgpsdataparser.cpp,
+ kipi-plugins/gpssync/kmlgpsdataparser.h,
+ kipi-plugins/gpssync/plugin_gpssync.cpp:
+ polish
+
+2008-02-04 10:18 cgilles
+
+ * [r770656] kipi-plugins/NEWS:
+ update
+
+2008-02-04 10:16 cgilles
+
+ * [r770654] kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h:
+ kipi-plugins from KDE3 branch : GPSSync tool: add new button to
+ Goto a location from map when user change lattitude or longitude
+ text field.
+ BUG: 144070
+
+2008-02-04 07:04 cgilles
+
+ * [r770599] kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h:
+ new method to set gps position
+
+2008-02-03 19:38 cgilles
+
+ * [r770453] kipi-plugins/NEWS:
+ update
+
+2008-02-03 17:16 gkulzer
+
+ * [r770409] kipi-plugins/gpssync/gpsdataparser.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/plugin_gpssync.cpp,
+ kipi-plugins/gpssync/plugin_gpssync.h:
+ Bug solved: multiplication by 3600 was performed twice on the
+ time zone offset. Also polished some i18n. CCBUG:154849
+ CCMAIL:caulier.gilles@gmail.com
+
+2008-02-02 12:08 cgilles
+
+ * [r769911] kipi-plugins/NEWS:
+ update
+
+2008-02-02 09:56 cgilles
+
+ * [r769872] kipi-plugins/gpssync/gpsbabelbinary.cpp,
+ kipi-plugins/gpssync/gpsbabelbinary.h,
+ kipi-plugins/gpssync/gpsdatacontainer.h,
+ kipi-plugins/gpssync/gpsdataparser.cpp,
+ kipi-plugins/gpssync/gpsdataparser.h,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.h,
+ kipi-plugins/gpssync/plugin_gpssync.cpp,
+ kipi-plugins/gpssync/plugin_gpssync.h:
+ fix (c)
+
+2008-02-02 09:52 cgilles
+
+ * [r769869] kipi-plugins/gpssync/gpsdataparser.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.cpp:
+ kipi-plugins from KDE3 branch: fix iterator around list of items
+ to matches date against GPX file...
+ I don't know how this bug have been introduce. Just one line have
+ been changed in gpssyncdialog.cpp...
+ Gerhard, it's sound work here with 3 images from your Iceland
+ collection and your GPX file using this settings:
+
+ - no interpolation
+ - max gap time = 30s
+ - time zone = GMT+0
+
+ If interpolation is on, another one file is set.
+
+ Please check indeep and report...
+
+ CCBUGS: 154849
+
+----------------------------------------------------------------------------
+V 0.1.5-rc2 - 2008-02-01
+----------------------------------------------------------------------------
+2008-02-01 21:00 cgilles
+
+ * [r769693] kipi-plugins/NEWS:
+ update
+
+2008-02-01 20:58 cgilles
+
+ * [r769692] kipi-plugins/gpssync/getlonlat.php:
+ kipi-plugins from KDE3 branch : added Google Search widget in the
+ map to perform fast jump to location
+ Thanks to Trevino for this patch.
+ BUG: 155371
+ CCMAIL: trevi55@gmail.com
+
+2008-01-16 21:21 cguthrie
+
+ * [r762358] kipi-plugins/galleryexport/gallerytalker.cpp,
+ kipi-plugins/galleryexport/gallerytalker.h,
+ kipi-plugins/galleryexport/gallerywidget.cpp,
+ kipi-plugins/galleryexport/gallerywidget.h,
+ kipi-plugins/galleryexport/gallerywindow.cpp,
+ kipi-plugins/galleryexport/gallerywindow.h:
+ Add the ability to set the title and/or description of the
+ uploaded images.
+ Thanks to Tom Kliethermes for the patch.
+ BUG: 153456
+
+2008-01-15 20:14 kusi
+
+ * [r761975] kipi-plugins/configure.in.in:
+ disable imageviewer if no opengl is available
+
+2008-01-10 22:38 anaselli
+
+ * [r759603] kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/printwizard/frmprintwizard.h,
+ kipi-plugins/printwizard/frmprintwizardbase.ui:
+ printwizard now can print more exif info on caption
+ BUG: 98225
+
+2008-01-04 12:44 cgilles
+
+ * [r757195]
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp:
+ check if ImageMagick command line is exit normally when process
+ is done, not just fater to startup it.
+
+ BUG: 151578
+
+2008-01-01 21:47 cgilles
+
+ * [r755591] kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/printwizard/tphoto.cpp,
+ kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ kipi-plugins/sendimages/sendimages.cpp:
+ prevert : plugins must still compilable with last stable release
+ of libkdcraw until kipi-plugins will be released
+
+2008-01-01 20:03 cgilles
+
+ * [r755539] kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/printwizard/tphoto.cpp,
+ kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ kipi-plugins/sendimages/sendimages.cpp,
+ libkdcraw/libkdcraw/dcrawbinary.cpp,
+ libkdcraw/libkdcraw/dcrawbinary.h:
+ new method to get raw files extension string depending of the
+ libkdcraw version installled on computer.
+
+2007-12-29 13:19 coolo
+
+ * [r754274] kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.cpp:
+ speed up autorotate of a full album in not touching files
+ that do not need touching
+
+2007-12-27 01:29 kusi
+
+ * [r753251] kipi-plugins/imageviewer/help.ui:
+ move HelpDialog into namespace
+
+2007-12-26 21:18 kusi
+
+ * [r753201] kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/imageviewer/viewerwidget.cpp:
+ zooming is performed with an image with a reduced resolution. the
+ downsampled img seemed to have a small offset.
+ reason: the texels were aligned at the upper left corner instead
+ of its center point.
+
+2007-12-18 19:49 kusi
+
+ * [r750144] kipi-plugins/imageviewer/viewerwidget.cpp:
+ improve caching: preload 2nd image in startup sequence
+
+2007-12-18 19:27 kusi
+
+ * [r750135] kipi-plugins/imageviewer/Makefile.am,
+ kipi-plugins/imageviewer/ogl.cpp, kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/plugin_viewer.cpp,
+ kipi-plugins/imageviewer/plugin_viewer.h,
+ kipi-plugins/imageviewer/viewerwidget.cpp,
+ kipi-plugins/imageviewer/viewerwidget.h:
+ refactoring: rename class ogl to ViewerWidget
+
+2007-12-18 18:29 kusi
+
+ * [r750124] kipi-plugins/imageviewer/ogl.cpp:
+ make help dialog stay on top (modal=true doesn't work since the
+ help dialog becomes modal to the host app and not to the plugin)
+
+2007-12-17 23:59 kusi
+
+ * [r749829] kipi-plugins/imageviewer/help.ui:
+ revert modal dialog to modeless. the dialog must not be modal to
+ the hostapp but to the plugin. I'll solve that later
+
+2007-12-17 21:51 kusi
+
+ * [r749786] kipi-plugins/imageviewer/help.ui,
+ kipi-plugins/imageviewer/ogl.cpp, kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/plugin_viewer.cpp,
+ kipi-plugins/imageviewer/plugin_viewer.h,
+ kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/imageviewer/texture.h,
+ kipi-plugins/imageviewer/timer.cpp,
+ kipi-plugins/imageviewer/timer.h:
+ - big cleanup, make code readable
+ - set CACHESIZE from 3 to 4
+ - make help dialog modal
+
+2007-12-17 18:11 kusi
+
+ * [r749724] kipi-plugins/imageviewer/ogl.cpp:
+ pressing SHIFT doesn't open help dialog anymore.
+ Bug 154244 on b.k.o
+
+2007-12-14 06:32 gkulzer
+
+ * [r748311] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ i18n polish
+
+2007-12-13 15:02 anaselli
+
+ * [r748080] kipi-plugins/mpegencoder/images2mpg:
+ Added a check that programs needed are in the system
+ CCBUG: 153962
+
+2007-12-11 13:18 cgilles
+
+ * [r747251] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ polish
+
+2007-12-11 13:18 cgilles
+
+ * [r747249] kipi-plugins/NEWS:
+ update
+
+2007-12-11 13:17 cgilles
+
+ * [r747248] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ GPSSync kipi-plugin from KDE3 branch : increase limit of max time
+ gap to 1000000, not 999
+ BUG: 150114
+
+2007-12-11 13:03 cgilles
+
+ * [r747242] kipi-plugins/NEWS:
+ update
+
+2007-12-11 13:02 cgilles
+
+ * [r747241] kipi-plugins/gpssync/gpsdataparser.cpp,
+ kipi-plugins/gpssync/gpsdataparser.h,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp:
+ GPSSync kipi-plugin from KDE3 branch : add full list of time zone
+ available over the world.
+
+ Gerhard, can you test with a GPS trace generated by your GPS
+ device if all work fine for you. Thanks in advance...
+
+ BUG: 149491
+ CCMAIL: gerhard@kulzer.net
+
+2007-12-11 11:37 orgads
+
+ * [r747219] kipi-plugins/calendar/calformatter.cpp:
+ * recurring events now shows also on the first and last days of
+ the year
+
+2007-12-11 09:25 orgads
+
+ * [r747183] kipi-plugins/calendar/calformatter.cpp,
+ kipi-plugins/calendar/calselect.cpp,
+ kipi-plugins/calendar/calwizard.cpp:
+ * fixed recurring events not showing (only first date was showed)
+ * setting special events only once (before printing), instead of
+ once for every page
+
+2007-12-11 09:02 cgilles
+
+ * [r747174] kipi-plugins/NEWS:
+ update
+
+2007-12-11 08:57 cgilles
+
+ * [r747172] kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.h:
+ GPSSync kipi-plugins from KDE3 branch : Use only one KIOslave to
+ handle images preview
+ BUG: 152215
+
+2007-11-22 19:40 cgilles
+
+ * [r740198] kipi-plugins/cdarchiving/cdarchivingdialog.cpp,
+ kipi-plugins/findimages/displaycompare.cpp,
+ kipi-plugins/findimages/finddupplicatedialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/kipiplugins.kdevelop:
+ optimize layout: remove line on bottom of dialogs
+
+2007-11-22 17:35 cgilles
+
+ * [r740158] kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ kipi-plugins/acquireimages/acquireimagedialog.h,
+ kipi-plugins/acquireimages/plugin_acquireimages.cpp,
+ kipi-plugins/acquireimages/plugin_acquireimages.h,
+ kipi-plugins/acquireimages/screenshotdialog.cpp,
+ kipi-plugins/acquireimages/screenshotdialog.h:
+ fix header
+
+2007-11-22 17:23 cgilles
+
+ * [r740151] kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ kipi-plugins/acquireimages/screenshotdialog.cpp:
+ layout optimization : no separator on bottom of dialogs
+
+2007-11-21 15:09 cgilles
+
+ * [r739683] kipi-plugins/sendimages/listimageserrordialog.cpp:
+ rm header
+
+2007-11-21 15:08 cgilles
+
+ * [r739682] kipi-plugins/calendar/calwizard.cpp:
+ rm header
+
+2007-11-21 15:08 cgilles
+
+ * [r739681] kipi-plugins/kameraklient/cameraselection.cpp,
+ kipi-plugins/kameraklient/cameraui.cpp,
+ kipi-plugins/kameraklient/setupcamera.cpp:
+ rm header
+
+2007-11-21 15:07 cgilles
+
+ * [r739680] kipi-plugins/findimages/displaycompare.cpp:
+ rm header
+
+2007-11-21 15:05 cgilles
+
+ * [r739679] kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.cpp:
+ rm header
+
+2007-11-21 14:54 cgilles
+
+ * [r739672] kipi-plugins/ipodexport/ipodexportdialog.cpp:
+ rm header
+
+2007-11-21 14:53 cgilles
+
+ * [r739667] kipi-plugins/acquireimages/screenshotdialog.cpp:
+ rm header
+
+2007-11-21 14:50 cgilles
+
+ * [r739665] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ rm header
+
+2007-11-21 11:38 cgilles
+
+ * [r739599] kipi-plugins/calendar/calselect.cpp,
+ kipi-plugins/calendar/caltemplate.cpp,
+ kipi-plugins/calendar/calwizard.cpp:
+ rm header
+
+2007-11-21 11:26 cgilles
+
+ * [r739592] kipi-plugins/mpegencoder/kimg2mpgbase.ui:
+ rm frame
+
+2007-11-21 11:16 cgilles
+
+ * [r739589] kipi-plugins/slideshow/slideshowconfigbase.ui:
+ rm frame
+
+2007-11-19 21:44 cgilles
+
+ * [r738866] kipi-plugins/gpssync/kmlexportconfig.cpp:
+ polish
+
+2007-11-19 21:41 cgilles
+
+ * [r738863] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ polish
+
+2007-11-19 21:09 cgilles
+
+ * [r738848]
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp:
+ missing to apply a part of Pawel patch here...
+
+ CCBUGS: 151578
+
+2007-11-19 20:50 cgilles
+
+ * [r738842] kipi-plugins/NEWS:
+ update
+
+2007-11-19 20:49 cgilles
+
+ * [r738840]
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp:
+ Kipi-plugins from KDE3 branch : Batch Process : restore metadata
+ properlly with JPEG file during conversion.
+ Pawel, This patch sound like properlly under KDE3.5, but not
+ under KDE 3.4. I suspect a bug in KProcess or something like
+ that.
+ BUG: 152210
+
+2007-11-19 16:00 cgilles
+
+ * [r738760] kipi-plugins/NEWS:
+ update
+
+2007-11-19 15:59 cgilles
+
+ * [r738759] kipi-plugins/batchprocessimages/Makefile.am,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.h,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.h,
+ kipi-plugins/batchprocessimages/imagepreview.cpp:
+ Do not test is KProcess is out imediatly.
+ BUG: 151578
+
+2007-11-19 13:40 cgilles
+
+ * [r738699]
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.cpp,
+ kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.cpp,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimageswidget.cpp,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp:
+ polish
+
+2007-11-19 13:26 cgilles
+
+ * [r738696]
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.h,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.h,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.h,
+ kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/borderimagesdialog.h,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.h,
+ kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/colorimagesdialog.h,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.h,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.h,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.h,
+ kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/effectimagesdialog.h,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.h,
+ kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/filterimagesdialog.h,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.h,
+ kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.h,
+ kipi-plugins/batchprocessimages/outputdialog.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.h,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.h,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.h,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.h,
+ kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimagesdialog.h,
+ kipi-plugins/batchprocessimages/renameimageswidget.cpp,
+ kipi-plugins/batchprocessimages/renameimageswidget.h,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.h,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.h:
+ fix header
+
+2007-11-17 04:06 vfuoglio
+
+ * [r737715] kipi-plugins/slideshow/slideshowconfig.cpp:
+ Fixed OpenGL effect selection issue.
+
+ Not reported in NEWS file: bug introduced in svn (rev. 736830)
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-11-16 14:26 cgilles
+
+ * [r737556] kipi-plugins/slideshow/slideshowkb.cpp:
+ fix warning
+
+2007-11-16 06:44 cgilles
+
+ * [r737340] kipi-plugins/slideshow/toolbar.cpp:
+ polish
+
+2007-11-15 17:20 cgilles
+
+ * [r737161] kipi-plugins/slideshow/toolbar.h:
+ polish
+
+2007-11-15 17:18 cgilles
+
+ * [r737160] kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp:
+ fix indent
+
+2007-11-15 17:05 cgilles
+
+ * [r737156] kipi-plugins/slideshow/listimageitems.cpp,
+ kipi-plugins/slideshow/listimageitems.h:
+ fix indent
+
+2007-11-15 14:52 cgilles
+
+ * [r737120] kipi-plugins/slideshow/toolbar.cpp,
+ kipi-plugins/slideshow/toolbar.h:
+ Valerio, Slideshow polish is now complete. Ready to start KDE4
+ port...
+
+ CCMAIL: valerio.fuoglio@gmail.com
+
+2007-11-15 14:48 cgilles
+
+ * [r737119] kipi-plugins/slideshow/imageloadthread.cpp,
+ kipi-plugins/slideshow/slideshowloader.cpp,
+ kipi-plugins/slideshow/slideshowloader.h:
+ polish
+
+2007-11-15 14:44 cgilles
+
+ * [r737117] kipi-plugins/slideshow/slideshowkb.cpp,
+ kipi-plugins/slideshow/slideshowkb.h:
+ polish
+
+2007-11-15 14:38 cgilles
+
+ * [r737113] kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h:
+ polish
+
+2007-11-15 14:31 cgilles
+
+ * [r737111] kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h:
+ polish
+
+2007-11-15 14:21 cgilles
+
+ * [r737108] kipi-plugins/slideshow/screenproperties.cpp,
+ kipi-plugins/slideshow/screenproperties.h:
+ polish
+
+2007-11-15 14:17 cgilles
+
+ * [r737107] kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/plugin_slideshow.h:
+ polish
+
+2007-11-15 14:08 cgilles
+
+ * [r737104] kipi-plugins/slideshow/listimageitems.cpp,
+ kipi-plugins/slideshow/listimageitems.h:
+ polish
+
+2007-11-15 13:58 cgilles
+
+ * [r737101] kipi-plugins/slideshow/kbeffect.cpp,
+ kipi-plugins/slideshow/kbeffect.h:
+ polish
+
+2007-11-15 13:55 cgilles
+
+ * [r737099] kipi-plugins/printwizard/Makefile.am:
+ compile. Mising libkdcraw header path
+
+2007-11-15 13:53 cgilles
+
+ * [r737098] kipi-plugins/slideshow/imageloadthread.cpp,
+ kipi-plugins/slideshow/imageloadthread.h:
+ Code polishing :
+
+ - Header revamping following tip from Achim.
+ - Always put the .moc includes with the list on local includes
+ files. This must be the last one.
+ - In header, place declaration in right order. It's more readable
+ : public, signals, protected, private.
+
+ Valerio, when you can, i recommend you to use a "d" private class
+ everywhere to host all private member. This will speedup
+ compilation and reduce
+ depencies between other sources file (in a library, this way
+ improve binary compatibility)
+
+ CCMAIL: valerio.fuoglio@gmail.com
+
+2007-11-14 23:15 vfuoglio
+
+ * [r736830] kipi-plugins/NEWS, kipi-plugins/slideshow/Makefile.am,
+ kipi-plugins/slideshow/imageloadthread.cpp,
+ kipi-plugins/slideshow/imageloadthread.h,
+ kipi-plugins/slideshow/kbeffect.cpp,
+ kipi-plugins/slideshow/kbeffect.h,
+ kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/screenproperties.cpp,
+ kipi-plugins/slideshow/screenproperties.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h,
+ kipi-plugins/slideshow/slideshowconfigbase.ui,
+ kipi-plugins/slideshow/slideshowgl.cpp,
+ kipi-plugins/slideshow/slideshowkb.cpp,
+ kipi-plugins/slideshow/slideshowkb.h:
+ Added Ken Burns effect.
+ Backported some code from SmoothSlideSaver (by Carsten Weinhold).
+
+ Next step: port SlideShow to KDE4.
+
+ BUG: 102021
+ CCMAIL: kde-imaging@kde.org
+ GUI:
+
+2007-11-11 19:57 vfuoglio
+
+ * [r735465] kipi-plugins/NEWS, kipi-plugins/slideshow/Makefile.am,
+ kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/plugin_slideshow.h,
+ kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h,
+ kipi-plugins/slideshow/slideshowconfigbase.ui,
+ kipi-plugins/slideshow/slideshowgl.cpp,
+ kipi-plugins/slideshow/slideshowgl.h,
+ kipi-plugins/slideshow/slideshowloader.cpp,
+ kipi-plugins/slideshow/slideshowloader.h,
+ kipi-plugins/slideshow/toolbar.cpp,
+ kipi-plugins/slideshow/toolbar.h:
+ Added new caching mechanism.
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-11-11 13:51 vfuoglio
+
+ * [r735366] kipi-plugins/NEWS,
+ kipi-plugins/slideshow/slideshow.cpp:
+ Solved minor issue in filename printing (2D slideshow).
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-11-09 21:56 anaselli
+
+ * [r734760] kipi-plugins/printwizard/Makefile.am,
+ kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/printwizard/tphoto.cpp,
+ kipi-plugins/printwizard/tphoto.h:
+ Added raw file management with libkdcraw dependency
+ BUG: 151604
+
+2007-11-08 21:21 cgilles
+
+ * [r734435] kipi-plugins/sendimages/sendimagesdialog.cpp:
+ this is just a string, not a path
+
+2007-11-08 14:14 cgilles
+
+ * [r734300] kipi-plugins/sendimages/sendimagesdialog.cpp:
+ missing i18n
+
+2007-11-07 13:05 cgilles
+
+ * [r733882] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp:
+ do not use UF8 encoding in source code
+
+2007-10-28 10:59 cgilles
+
+ * [r730285] kipi-plugins/AUTHORS:
+ update
+
+2007-10-28 10:58 cgilles
+
+ * [r730283] kipi-plugins/AUTHORS,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp:
+ fix email
+
+2007-10-28 10:37 cgilles
+
+ * [r730275] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp:
+ fix credits
+
+2007-10-27 18:36 cgilles
+
+ * [r730045] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp:
+ polish
+
+2007-10-27 16:53 cgilles
+
+ * [r730007] kipi-plugins/sendimages/actions.h,
+ kipi-plugins/sendimages/listimageserrordialog.h,
+ kipi-plugins/sendimages/plugin_sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h:
+ polish
+
+2007-10-27 16:29 cgilles
+
+ * [r729994] kipi-plugins/gpssync/kmlexport.cpp:
+ polish
+
+2007-10-27 14:24 cgilles
+
+ * [r729962] kipi-plugins/gpssync/kmlgpsdataparser.cpp,
+ kipi-plugins/gpssync/kmlgpsdataparser.h:
+ polish
+
+2007-10-27 14:21 cgilles
+
+ * [r729960] kipi-plugins/gpssync/kmlexportconfig.h:
+ polish
+
+2007-10-27 14:16 cgilles
+
+ * [r729958] kipi-plugins/gpssync/kmlexport.cpp,
+ kipi-plugins/gpssync/kmlexport.h:
+ polish
+
+2007-10-27 12:42 cgilles
+
+ * [r729929] kipi-plugins/gpssync/getlonlat.php,
+ kipi-plugins/gpssync/gpsbabelbinary.cpp,
+ kipi-plugins/gpssync/gpsbabelbinary.h,
+ kipi-plugins/gpssync/gpsdatacontainer.h,
+ kipi-plugins/gpssync/gpsdataparser.cpp,
+ kipi-plugins/gpssync/gpsdataparser.h,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.h,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.h:
+ prepare to port to KDE4 : polish and fix header
+
+2007-10-27 12:41 cgilles
+
+ * [r729928] kipi-plugins/sendimages/actions.h,
+ kipi-plugins/sendimages/listimageserrordialog.cpp,
+ kipi-plugins/sendimages/listimageserrordialog.h,
+ kipi-plugins/sendimages/plugin_sendimages.cpp,
+ kipi-plugins/sendimages/plugin_sendimages.h,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.h:
+ prepare to port to KDE4 : polish and fix header
+
+2007-10-21 10:45 hasso
+
+ * [r727631] kipi-plugins/gpssync/kmlexport.cpp,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ Correct includes. For getpid(2) is required, and sys/types.h has
+ to be
+ included before utime.h.
+
+ Fixes compile problems in DragonFly BSD.
+
+2007-10-09 07:36 cgilles
+
+ * [r723280] kipi-plugins/metadataedit/iptcorigin.cpp:
+ polish
+
+----------------------------------------------------------------------------
+V 0.1.5-rc1 - 2007-12-29
+----------------------------------------------------------------------------
+2007-12-29 13:19 coolo
+
+ * [r754274] kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.cpp:
+ speed up autorotate of a full album in not touching files
+ that do not need touching
+
+2007-12-27 01:29 kusi
+
+ * [r753251] kipi-plugins/imageviewer/help.ui:
+ move HelpDialog into namespace
+
+2007-12-26 21:18 kusi
+
+ * [r753201] kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/imageviewer/viewerwidget.cpp:
+ zooming is performed with an image with a reduced resolution. the
+ downsampled img seemed to have a small offset.
+ reason: the texels were aligned at the upper left corner instead
+ of its center point.
+
+2007-12-18 19:49 kusi
+
+ * [r750144] kipi-plugins/imageviewer/viewerwidget.cpp:
+ improve caching: preload 2nd image in startup sequence
+
+2007-12-18 19:27 kusi
+
+ * [r750135] kipi-plugins/imageviewer/Makefile.am,
+ kipi-plugins/imageviewer/ogl.cpp, kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/plugin_viewer.cpp,
+ kipi-plugins/imageviewer/plugin_viewer.h,
+ kipi-plugins/imageviewer/viewerwidget.cpp,
+ kipi-plugins/imageviewer/viewerwidget.h:
+ refactoring: rename class ogl to ViewerWidget
+
+2007-12-18 18:29 kusi
+
+ * [r750124] kipi-plugins/imageviewer/ogl.cpp:
+ make help dialog stay on top (modal=true doesn't work since the
+ help dialog becomes modal to the host app and not to the plugin)
+
+2007-12-17 23:59 kusi
+
+ * [r749829] kipi-plugins/imageviewer/help.ui:
+ revert modal dialog to modeless. the dialog must not be modal to
+ the hostapp but to the plugin. I'll solve that later
+
+2007-12-17 21:51 kusi
+
+ * [r749786] kipi-plugins/imageviewer/help.ui,
+ kipi-plugins/imageviewer/ogl.cpp, kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/plugin_viewer.cpp,
+ kipi-plugins/imageviewer/plugin_viewer.h,
+ kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/imageviewer/texture.h,
+ kipi-plugins/imageviewer/timer.cpp,
+ kipi-plugins/imageviewer/timer.h:
+ - big cleanup, make code readable
+ - set CACHESIZE from 3 to 4
+ - make help dialog modal
+
+2007-12-17 19:23 cgilles
+
+ * [r749744] kipi-plugins/NEWS:
+ update
+
+2007-12-17 18:11 kusi
+
+ * [r749724] kipi-plugins/imageviewer/ogl.cpp:
+ pressing SHIFT doesn't open help dialog anymore.
+ Bug 154244 on b.k.o
+
+2007-12-14 06:32 gkulzer
+
+ * [r748311] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ i18n polish
+
+2007-12-13 15:02 anaselli
+
+ * [r748080] kipi-plugins/mpegencoder/images2mpg:
+ Added a check that programs needed are in the system
+ CCBUG: 153962
+
+2007-12-11 13:18 cgilles
+
+ * [r747251] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ polish
+
+2007-12-11 13:18 cgilles
+
+ * [r747249] kipi-plugins/NEWS:
+ update
+
+2007-12-11 13:17 cgilles
+
+ * [r747248] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ GPSSync kipi-plugin from KDE3 branch : increase limit of max time
+ gap to 1000000, not 999
+ BUG: 150114
+
+2007-12-11 13:03 cgilles
+
+ * [r747242] kipi-plugins/NEWS:
+ update
+
+2007-12-11 13:02 cgilles
+
+ * [r747241] kipi-plugins/gpssync/gpsdataparser.cpp,
+ kipi-plugins/gpssync/gpsdataparser.h,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp:
+ GPSSync kipi-plugin from KDE3 branch : add full list of time zone
+ available over the world.
+
+ Gerhard, can you test with a GPS trace generated by your GPS
+ device if all work fine for you. Thanks in advance...
+
+ BUG: 149491
+ CCMAIL: gerhard@kulzer.net
+
+2007-12-11 11:37 orgads
+
+ * [r747219] kipi-plugins/calendar/calformatter.cpp:
+ * recurring events now shows also on the first and last days of
+ the year
+
+2007-12-11 09:25 orgads
+
+ * [r747183] kipi-plugins/calendar/calformatter.cpp,
+ kipi-plugins/calendar/calselect.cpp,
+ kipi-plugins/calendar/calwizard.cpp:
+ * fixed recurring events not showing (only first date was showed)
+ * setting special events only once (before printing), instead of
+ once for every page
+
+2007-12-11 09:02 cgilles
+
+ * [r747174] kipi-plugins/NEWS:
+ update
+
+2007-12-11 08:57 cgilles
+
+ * [r747172] kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.h:
+ GPSSync kipi-plugins from KDE3 branch : Use only one KIOslave to
+ handle images preview
+ BUG: 152215
+
+2007-11-22 19:40 cgilles
+
+ * [r740198] kipi-plugins/cdarchiving/cdarchivingdialog.cpp,
+ kipi-plugins/findimages/displaycompare.cpp,
+ kipi-plugins/findimages/finddupplicatedialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/kipiplugins.kdevelop:
+ optimize layout: remove line on bottom of dialogs
+
+2007-11-22 17:35 cgilles
+
+ * [r740158] kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ kipi-plugins/acquireimages/acquireimagedialog.h,
+ kipi-plugins/acquireimages/plugin_acquireimages.cpp,
+ kipi-plugins/acquireimages/plugin_acquireimages.h,
+ kipi-plugins/acquireimages/screenshotdialog.cpp,
+ kipi-plugins/acquireimages/screenshotdialog.h:
+ fix header
+
+2007-11-22 17:23 cgilles
+
+ * [r740151] kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ kipi-plugins/acquireimages/screenshotdialog.cpp:
+ layout optimization : no separator on bottom of dialogs
+
+2007-11-21 15:09 cgilles
+
+ * [r739683] kipi-plugins/sendimages/listimageserrordialog.cpp:
+ rm header
+
+2007-11-21 15:08 cgilles
+
+ * [r739682] kipi-plugins/calendar/calwizard.cpp:
+ rm header
+
+2007-11-21 15:08 cgilles
+
+ * [r739681] kipi-plugins/kameraklient/cameraselection.cpp,
+ kipi-plugins/kameraklient/cameraui.cpp,
+ kipi-plugins/kameraklient/setupcamera.cpp:
+ rm header
+
+2007-11-21 15:07 cgilles
+
+ * [r739680] kipi-plugins/findimages/displaycompare.cpp:
+ rm header
+
+2007-11-21 15:05 cgilles
+
+ * [r739679] kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.cpp:
+ rm header
+
+2007-11-21 14:54 cgilles
+
+ * [r739672] kipi-plugins/ipodexport/ipodexportdialog.cpp:
+ rm header
+
+2007-11-21 14:53 cgilles
+
+ * [r739667] kipi-plugins/acquireimages/screenshotdialog.cpp:
+ rm header
+
+2007-11-21 14:50 cgilles
+
+ * [r739665] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ rm header
+
+2007-11-21 11:38 cgilles
+
+ * [r739599] kipi-plugins/calendar/calselect.cpp,
+ kipi-plugins/calendar/caltemplate.cpp,
+ kipi-plugins/calendar/calwizard.cpp:
+ rm header
+
+2007-11-21 11:26 cgilles
+
+ * [r739592] kipi-plugins/mpegencoder/kimg2mpgbase.ui:
+ rm frame
+
+2007-11-21 11:16 cgilles
+
+ * [r739589] kipi-plugins/slideshow/slideshowconfigbase.ui:
+ rm frame
+
+2007-11-19 21:44 cgilles
+
+ * [r738866] kipi-plugins/gpssync/kmlexportconfig.cpp:
+ polish
+
+2007-11-19 21:41 cgilles
+
+ * [r738863] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ polish
+
+2007-11-19 21:09 cgilles
+
+ * [r738848]
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp:
+ missing to apply a part of Pawel patch here...
+
+ CCBUGS: 151578
+
+2007-11-19 20:50 cgilles
+
+ * [r738842] kipi-plugins/NEWS:
+ update
+
+2007-11-19 20:49 cgilles
+
+ * [r738840]
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp:
+ Kipi-plugins from KDE3 branch : Batch Process : restore metadata
+ properlly with JPEG file during conversion.
+ Pawel, This patch sound like properlly under KDE3.5, but not
+ under KDE 3.4. I suspect a bug in KProcess or something like
+ that.
+ BUG: 152210
+
+2007-11-19 16:00 cgilles
+
+ * [r738760] kipi-plugins/NEWS:
+ update
+
+2007-11-19 15:59 cgilles
+
+ * [r738759] kipi-plugins/batchprocessimages/Makefile.am,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.h,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.h,
+ kipi-plugins/batchprocessimages/imagepreview.cpp:
+ Do not test is KProcess is out imediatly.
+ BUG: 151578
+
+2007-11-19 13:40 cgilles
+
+ * [r738699]
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.cpp,
+ kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.cpp,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimageswidget.cpp,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp:
+ polish
+
+2007-11-19 13:26 cgilles
+
+ * [r738696]
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.h,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.h,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.h,
+ kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/borderimagesdialog.h,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.h,
+ kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/colorimagesdialog.h,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.h,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.h,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.h,
+ kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/effectimagesdialog.h,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.h,
+ kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/filterimagesdialog.h,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.h,
+ kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.h,
+ kipi-plugins/batchprocessimages/outputdialog.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.h,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.h,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.h,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.h,
+ kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimagesdialog.h,
+ kipi-plugins/batchprocessimages/renameimageswidget.cpp,
+ kipi-plugins/batchprocessimages/renameimageswidget.h,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.h,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.h:
+ fix header
+
+2007-11-17 04:06 vfuoglio
+
+ * [r737715] kipi-plugins/slideshow/slideshowconfig.cpp:
+ Fixed OpenGL effect selection issue.
+
+ Not reported in NEWS file: bug introduced in svn (rev. 736830)
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-11-16 14:26 cgilles
+
+ * [r737556] kipi-plugins/slideshow/slideshowkb.cpp:
+ fix warning
+
+2007-11-16 06:44 cgilles
+
+ * [r737340] kipi-plugins/slideshow/toolbar.cpp:
+ polish
+
+2007-11-15 17:20 cgilles
+
+ * [r737161] kipi-plugins/slideshow/toolbar.h:
+ polish
+
+2007-11-15 17:18 cgilles
+
+ * [r737160] kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp:
+ fix indent
+
+2007-11-15 17:05 cgilles
+
+ * [r737156] kipi-plugins/slideshow/listimageitems.cpp,
+ kipi-plugins/slideshow/listimageitems.h:
+ fix indent
+
+2007-11-15 14:52 cgilles
+
+ * [r737120] kipi-plugins/slideshow/toolbar.cpp,
+ kipi-plugins/slideshow/toolbar.h:
+ Valerio, Slideshow polish is now complete. Ready to start KDE4
+ port...
+
+ CCMAIL: valerio.fuoglio@gmail.com
+
+2007-11-15 14:48 cgilles
+
+ * [r737119] kipi-plugins/slideshow/imageloadthread.cpp,
+ kipi-plugins/slideshow/slideshowloader.cpp,
+ kipi-plugins/slideshow/slideshowloader.h:
+ polish
+
+2007-11-15 14:44 cgilles
+
+ * [r737117] kipi-plugins/slideshow/slideshowkb.cpp,
+ kipi-plugins/slideshow/slideshowkb.h:
+ polish
+
+2007-11-15 14:38 cgilles
+
+ * [r737113] kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h:
+ polish
+
+2007-11-15 14:31 cgilles
+
+ * [r737111] kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h:
+ polish
+
+2007-11-15 14:21 cgilles
+
+ * [r737108] kipi-plugins/slideshow/screenproperties.cpp,
+ kipi-plugins/slideshow/screenproperties.h:
+ polish
+
+2007-11-15 14:17 cgilles
+
+ * [r737107] kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/plugin_slideshow.h:
+ polish
+
+2007-11-15 14:08 cgilles
+
+ * [r737104] kipi-plugins/slideshow/listimageitems.cpp,
+ kipi-plugins/slideshow/listimageitems.h:
+ polish
+
+2007-11-15 13:58 cgilles
+
+ * [r737101] kipi-plugins/slideshow/kbeffect.cpp,
+ kipi-plugins/slideshow/kbeffect.h:
+ polish
+
+2007-11-15 13:55 cgilles
+
+ * [r737099] kipi-plugins/printwizard/Makefile.am:
+ compile. Mising libkdcraw header path
+
+2007-11-15 13:53 cgilles
+
+ * [r737098] kipi-plugins/slideshow/imageloadthread.cpp,
+ kipi-plugins/slideshow/imageloadthread.h:
+ Code polishing :
+
+ - Header revamping following tip from Achim.
+ - Always put the .moc includes with the list on local includes
+ files. This must be the last one.
+ - In header, place declaration in right order. It's more readable
+ : public, signals, protected, private.
+
+ Valerio, when you can, i recommend you to use a "d" private class
+ everywhere to host all private member. This will speedup
+ compilation and reduce
+ depencies between other sources file (in a library, this way
+ improve binary compatibility)
+
+ CCMAIL: valerio.fuoglio@gmail.com
+
+2007-11-14 23:15 vfuoglio
+
+ * [r736830] kipi-plugins/NEWS, kipi-plugins/slideshow/Makefile.am,
+ kipi-plugins/slideshow/imageloadthread.cpp,
+ kipi-plugins/slideshow/imageloadthread.h,
+ kipi-plugins/slideshow/kbeffect.cpp,
+ kipi-plugins/slideshow/kbeffect.h,
+ kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/screenproperties.cpp,
+ kipi-plugins/slideshow/screenproperties.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h,
+ kipi-plugins/slideshow/slideshowconfigbase.ui,
+ kipi-plugins/slideshow/slideshowgl.cpp,
+ kipi-plugins/slideshow/slideshowkb.cpp,
+ kipi-plugins/slideshow/slideshowkb.h:
+ Added Ken Burns effect.
+ Backported some code from SmoothSlideSaver (by Carsten Weinhold).
+
+ Next step: port SlideShow to KDE4.
+
+ BUG: 102021
+ CCMAIL: kde-imaging@kde.org
+ GUI:
+
+2007-11-11 19:57 vfuoglio
+
+ * [r735465] kipi-plugins/NEWS, kipi-plugins/slideshow/Makefile.am,
+ kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/plugin_slideshow.h,
+ kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h,
+ kipi-plugins/slideshow/slideshowconfigbase.ui,
+ kipi-plugins/slideshow/slideshowgl.cpp,
+ kipi-plugins/slideshow/slideshowgl.h,
+ kipi-plugins/slideshow/slideshowloader.cpp,
+ kipi-plugins/slideshow/slideshowloader.h,
+ kipi-plugins/slideshow/toolbar.cpp,
+ kipi-plugins/slideshow/toolbar.h:
+ Added new caching mechanism.
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-11-11 13:51 vfuoglio
+
+ * [r735366] kipi-plugins/NEWS,
+ kipi-plugins/slideshow/slideshow.cpp:
+ Solved minor issue in filename printing (2D slideshow).
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-11-10 15:33 cgilles
+
+ * [r734958] kipi-plugins/NEWS:
+ typo
+
+2007-11-09 22:05 anaselli
+
+ * [r734761] kipi-plugins/NEWS:
+ SNV_SILENT: updated for bug 151604
+
+2007-11-09 21:56 anaselli
+
+ * [r734760] kipi-plugins/printwizard/Makefile.am,
+ kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/printwizard/tphoto.cpp,
+ kipi-plugins/printwizard/tphoto.h:
+ Added raw file management with libkdcraw dependency
+ BUG: 151604
+
+2007-11-08 21:21 cgilles
+
+ * [r734435] kipi-plugins/sendimages/sendimagesdialog.cpp:
+ this is just a string, not a path
+
+2007-11-08 14:14 cgilles
+
+ * [r734300] kipi-plugins/sendimages/sendimagesdialog.cpp:
+ missing i18n
+
+2007-11-07 13:05 cgilles
+
+ * [r733882] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp:
+ do not use UF8 encoding in source code
+
+2007-10-28 10:59 cgilles
+
+ * [r730285] kipi-plugins/AUTHORS:
+ update
+
+2007-10-28 10:58 cgilles
+
+ * [r730283] kipi-plugins/AUTHORS,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp:
+ fix email
+
+2007-10-28 10:37 cgilles
+
+ * [r730275] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp:
+ fix credits
+
+2007-10-27 18:36 cgilles
+
+ * [r730045] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp:
+ polish
+
+2007-10-27 16:53 cgilles
+
+ * [r730007] kipi-plugins/sendimages/actions.h,
+ kipi-plugins/sendimages/listimageserrordialog.h,
+ kipi-plugins/sendimages/plugin_sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h:
+ polish
+
+2007-10-27 16:29 cgilles
+
+ * [r729994] kipi-plugins/gpssync/kmlexport.cpp:
+ polish
+
+2007-10-27 14:24 cgilles
+
+ * [r729962] kipi-plugins/gpssync/kmlgpsdataparser.cpp,
+ kipi-plugins/gpssync/kmlgpsdataparser.h:
+ polish
+
+2007-10-27 14:21 cgilles
+
+ * [r729960] kipi-plugins/gpssync/kmlexportconfig.h:
+ polish
+
+2007-10-27 14:16 cgilles
+
+ * [r729958] kipi-plugins/gpssync/kmlexport.cpp,
+ kipi-plugins/gpssync/kmlexport.h:
+ polish
+
+2007-10-27 12:42 cgilles
+
+ * [r729929] kipi-plugins/gpssync/getlonlat.php,
+ kipi-plugins/gpssync/gpsbabelbinary.cpp,
+ kipi-plugins/gpssync/gpsbabelbinary.h,
+ kipi-plugins/gpssync/gpsdatacontainer.h,
+ kipi-plugins/gpssync/gpsdataparser.cpp,
+ kipi-plugins/gpssync/gpsdataparser.h,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.h,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.h:
+ prepare to port to KDE4 : polish and fix header
+
+2007-10-27 12:41 cgilles
+
+ * [r729928] kipi-plugins/sendimages/actions.h,
+ kipi-plugins/sendimages/listimageserrordialog.cpp,
+ kipi-plugins/sendimages/listimageserrordialog.h,
+ kipi-plugins/sendimages/plugin_sendimages.cpp,
+ kipi-plugins/sendimages/plugin_sendimages.h,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.h:
+ prepare to port to KDE4 : polish and fix header
+
+2007-10-21 10:45 hasso
+
+ * [r727631] kipi-plugins/gpssync/kmlexport.cpp,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ Correct includes. For getpid(2) is required, and sys/types.h has
+ to be
+ included before utime.h.
+
+ Fixes compile problems in DragonFly BSD.
+
+2007-10-09 07:36 cgilles
+
+ * [r723280] kipi-plugins/metadataedit/iptcorigin.cpp:
+ polish
+
+----------------------------------------------------------------------------
+V 0.1.5-beta1 - 2007-10-07
+----------------------------------------------------------------------------
+2007-10-07 17:58 anaselli
+
+ * [r722604] kipi-plugins/Makefile.am, kipi-plugins/NEWS,
+ kipi-plugins/configure.in.bot, kipi-plugins/configure.in.in:
+ Added configure options to disable plugins provided by Matej
+ Laitl
+ CCBUG: 149666
+
+2007-10-05 21:19 anaselli
+
+ * [r721684] kipi-plugins/printwizard/frmprintwizard.cpp:
+ Accepted patch provided by Joerg for caption size
+
+ CCMAIL: joerg.kuehne@web.de
+
+2007-10-05 20:31 anaselli
+
+ * [r721662] kipi-plugins/printwizard/frmprintwizard.cpp:
+ changed tha call from gimp to gimp-remote
+
+ CCMAIL: joerg.kuehne@web.de
+
+2007-10-05 10:49 cgilles
+
+ * [r721492] kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifdatetime.cpp,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptcdatetime.cpp:
+ fix i18n
+
+2007-10-05 10:43 cgilles
+
+ * [r721488] kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.cpp:
+ fix i18n
+
+2007-10-05 10:23 cgilles
+
+ * [r721477] kipi-plugins/metadataedit/commenteditdialog.cpp:
+ fix i18n
+
+2007-10-05 07:27 cgilles
+
+ * [r721403] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ fix i18n
+
+2007-10-05 07:14 cgilles
+
+ * [r721390] kipi-plugins/metadataedit/exifcaption.cpp:
+ fix i18n
+
+2007-10-05 07:09 cgilles
+
+ * [r721386] kipi-plugins/metadataedit/commentremovedialog.cpp,
+ kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifdatetime.cpp,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptcdatetime.cpp:
+ Gerhard, something is wrong with Comments/Caption terminology.
+ Let's me explain why :
+
+ In genral, i'm agree to use "Caption" as generic and common term
+ to define a text embeded in a picture as a description.
+ But with Metadata Edit kipi-plugins, the technical term as used
+ to said what field with be changed accordinly with user settings:
+
+ JFIF caption ==> no, the JPEG spec said than the field name is
+ "JFIF Comments Section (COM marker)".
+ (http://en.wikipedia.org/wiki/JPEG#JPEG_Interchange_Format_file_format)
+ EXIF caption ==> no, the EXIF spec said than the tag name
+ Exif.UserComment
+ (http://www.digicamsoft.com/exif22/exif22/html/exif22_34.htm?gInitialPosX=10px&gInitialPosY=10px&gZoomValue=100)
+
+ If we don't repect the right terms, it can be confuse for end
+ users.
+
+ Note : For IPTC and XMP, using Caption term is fine.
+
+ CCMAIL: gerhard@kulzer.net
+
+2007-10-05 06:47 cgilles
+
+ * [r721380] kipi-plugins/metadataedit/commentremovedialog.cpp:
+ polish
+
+2007-10-05 06:33 cgilles
+
+ * [r721376] kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/iptccategories.cpp:
+ compile
+
+2007-10-05 06:31 cgilles
+
+ * [r721373] kipi-plugins/metadataedit/commenteditdialog.cpp:
+ polish
+
+2007-10-04 19:16 cgilles
+
+ * [r721187] kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.cpp:
+ polish
+
+2007-10-04 19:13 cgilles
+
+ * [r721186] kipi-plugins/metadataedit/iptceditdialog.cpp:
+ polish
+
+2007-10-04 08:58 cgilles
+
+ * [r720991] kipi-plugins/metadataedit/exiflight.cpp:
+ polish
+
+2007-10-03 16:24 cgilles
+
+ * [r720746] kipi-plugins/rawconverter/plugin_rawconverter.cpp:
+ fix i18n
+
+2007-10-03 12:48 cgilles
+
+ * [r720664] kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifdevice.cpp:
+ add ink to wikipedia
+
+2007-10-03 12:35 cgilles
+
+ * [r720661] kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.cpp:
+ fix layout
+
+2007-10-03 12:26 cgilles
+
+ * [r720658] kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptccredits.cpp,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.cpp:
+ polish
+
+2007-10-03 12:24 cgilles
+
+ * [r720656] kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.cpp:
+ fix i18n
+
+2007-10-03 12:05 cgilles
+
+ * [r720650] kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptccredits.cpp,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.cpp:
+ add link to wikipedia
+
+2007-10-03 12:00 cgilles
+
+ * [r720647] kipi-plugins/metadataedit/exifadjust.cpp,
+ kipi-plugins/metadataedit/exifadjust.h,
+ kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifcaption.h,
+ kipi-plugins/metadataedit/exifdatetime.cpp,
+ kipi-plugins/metadataedit/exifdatetime.h,
+ kipi-plugins/metadataedit/exifdevice.cpp,
+ kipi-plugins/metadataedit/exifdevice.h,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.h,
+ kipi-plugins/metadataedit/exiflens.cpp,
+ kipi-plugins/metadataedit/exiflens.h,
+ kipi-plugins/metadataedit/exiflight.cpp,
+ kipi-plugins/metadataedit/exiflight.h:
+ fix header
+
+2007-10-03 11:56 cgilles
+
+ * [r720642] kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commenteditdialog.h,
+ kipi-plugins/metadataedit/commentremovedialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.h,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptccaption.h,
+ kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptccategories.h,
+ kipi-plugins/metadataedit/iptccredits.cpp,
+ kipi-plugins/metadataedit/iptccredits.h,
+ kipi-plugins/metadataedit/iptcdatetime.cpp,
+ kipi-plugins/metadataedit/iptcdatetime.h,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.h,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptckeywords.h,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcorigin.h,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcstatus.h,
+ kipi-plugins/metadataedit/iptcsubjects.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.h,
+ kipi-plugins/metadataedit/metadatacheckbox.cpp,
+ kipi-plugins/metadataedit/metadatacheckbox.h,
+ kipi-plugins/metadataedit/plugin_metadataedit.cpp,
+ kipi-plugins/metadataedit/plugin_metadataedit.h:
+ fix header
+
+2007-09-28 14:27 gkulzer
+
+ * [r718359] kipi-plugins/findimages/displaycompare.cpp,
+ kipi-plugins/imagesgallery/imgallerydialog.cpp,
+ kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.cpp,
+ kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/metadataedit/plugin_metadataedit.cpp,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.cpp,
+ kipi-plugins/slideshow/slideshowconfigbase.ui,
+ libkipi/libkipi/imagecollectionselector.cpp:
+ comment->caption = better English
+
+2007-09-28 14:22 gkulzer
+
+ * [r718356] kipi-plugins/acquireimages/acquireimagedialog.cpp:
+ comments->caption = clearer English
+
+2007-09-28 14:20 gkulzer
+
+ * [r718354] kipi-plugins/cdarchiving/cdarchiving.cpp:
+ comments->caption = clearer English
+
+2007-09-26 11:52 cgilles
+
+ * [r717247] kipi-plugins/jpeglossless/actionthread.cpp:
+ polish
+
+2007-09-26 11:51 cgilles
+
+ * [r717246] kipi-plugins/jpeglossless/actionthread.cpp,
+ kipi-plugins/jpeglossless/actionthread.h,
+ kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/convert2grayscale.h,
+ kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imageflip.h,
+ kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/imagerotate.h:
+ backport commit #717239 from KDE4 branch
+
+2007-09-26 06:40 cgilles
+
+ * [r717144] kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.h:
+ fix header
+
+2007-09-25 19:27 cgilles
+
+ * [r716980] kipi-plugins/jpeglossless/utils.cpp:
+ polish
+
+2007-09-25 18:15 cgilles
+
+ * [r716958] kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imagerotate.cpp:
+ polish
+
+2007-09-25 17:01 cgilles
+
+ * [r716939] kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/imagerotate.h:
+ polish
+
+2007-09-25 14:16 cgilles
+
+ * [r716889] kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/imagerotate.h,
+ kipi-plugins/jpeglossless/jpegtransform.cpp,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/jpeglossless/utils.h:
+ kipi-plugins from KDE3 branch : JPEGLossLess plugin : new method
+ to update metadata from non-JPEG pictures processed with
+ ImageMagick (TIFF/PNG for Ex.)
+ Updating include IPTC preview image used to render thumbnails in
+ digiKam.
+ CCBUGS: 144388
+
+2007-09-25 13:32 cgilles
+
+ * [r716878]
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.cpp:
+ kipi-plugins from KDE3 branch : Bugfix with ImageMagick
+ background process creation : always checking if process
+ (KProcess) is ended properlly (no ImageMagick crash for ex.)
+
+2007-09-25 11:00 cgilles
+
+ * [r716838] kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/iptcstatus.cpp:
+ fixw app name
+
+2007-09-25 10:54 cgilles
+
+ * [r716837] kipi-plugins/sendimages/sendimages.cpp:
+ fix app name
+
+2007-09-25 10:53 cgilles
+
+ * [r716836] kipi-plugins/rawconverter/rawdecodingiface.cpp:
+ fix apps name
+
+2007-09-25 10:31 cgilles
+
+ * [r716830] kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/convert2grayscale.h,
+ kipi-plugins/jpeglossless/jpegtransform.cpp,
+ kipi-plugins/jpeglossless/mtqueue.h,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.h,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/jpeglossless/utils.h:
+ kDebug => qDebug
+
+2007-09-25 10:23 cgilles
+
+ * [r716825] kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imageflip.h,
+ kipi-plugins/jpeglossless/imagerotate.h:
+ kDegug => qDebug
+
+2007-09-25 10:20 cgilles
+
+ * [r716824] kipi-plugins/jpeglossless/actions.h,
+ kipi-plugins/jpeglossless/actionthread.cpp,
+ kipi-plugins/jpeglossless/actionthread.h:
+ kDebug => qDebug
+
+2007-09-25 10:17 cgilles
+
+ * [r716823] kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/imagerotate.h:
+ kDebug => qDebug
+
+2007-09-24 11:47 cgilles
+
+ * [r716268]
+ kipi-plugins/rawconverter/pics/hi128-action-rawconverterbatch.png,
+ kipi-plugins/rawconverter/pics/hi128-action-rawconvertersingle.png,
+ kipi-plugins/rawconverter/pics/hi32-action-rawconverterbatch.png,
+ kipi-plugins/rawconverter/pics/hi32-action-rawconvertersingle.png:
+ new icons
+
+2007-09-24 09:21 cgilles
+
+ * [r716230] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp:
+ polish
+
+2007-09-23 08:30 cgilles
+
+ * [r715842] kipi-plugins/rawconverter/rawdecodingiface.cpp,
+ kipi-plugins/rawconverter/rawdecodingiface.h:
+ use const ref
+
+2007-09-20 10:26 cgilles
+
+ * [r714710] kipi-plugins/rawconverter/rawdecodingiface.cpp:
+ missing to detroy JPEG encoder instance
+
+2007-09-20 08:05 cgilles
+
+ * [r714675] kipi-plugins/rawconverter/rawdecodingiface.h:
+ fix includes order
+
+2007-09-20 07:36 cgilles
+
+ * [r714669] kipi-plugins/rawconverter/rawdecodingiface.cpp:
+ factorize metadata handling source code
+
+2007-09-20 06:34 cgilles
+
+ * [r714654] kipi-plugins/rawconverter/rawdecodingiface.h:
+ polish
+
+2007-09-20 06:33 cgilles
+
+ * [r714653] kipi-plugins/rawconverter/rawdecodingiface.h:
+ polish
+
+2007-09-19 10:45 cgilles
+
+ * [r714356] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/batchdialog.h,
+ kipi-plugins/rawconverter/savesettingswidget.cpp,
+ kipi-plugins/rawconverter/savesettingswidget.h,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/rawconverter/singledialog.h:
+ optimize layout
+
+2007-09-19 10:24 cgilles
+
+ * [r714353] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp:
+ optimize layout
+
+2007-09-14 12:01 mueller
+
+ * [r712436] kipi-plugins/rawconverter/rawdecodingiface.cpp:
+ fix compiler warning
+
+2007-09-08 15:49 cgilles
+
+ * [r709928] kipi-plugins/rawconverter/rawdecodingiface.cpp:
+ kipi-plugins RAW converter : set JPEG subsampling factor to
+ Medium.
+ CCBUGS: 149578
+
+2007-09-02 13:25 mwiesweg
+
+ * [r707626] kipi-plugins/jpeglossless/actionthread.cpp:
+ If the image had already an exif rotation flag set, this code
+ part would cause
+ this taken into account twice, add the JPEG specific code does
+ its own
+ sophisticated checking with matrix multiplication.
+
+ BUG: 148621
+
+2007-08-26 22:07 anaselli
+
+ * [r705018] kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/printwizard/frmprintwizardbase.ui:
+ now we can print each photo more than once
+
+ GUI:
+ BUG: 100471
+ CCMAIL: kde-imaging@kde.org
+
+2007-08-24 15:47 anaselli
+
+ * [r704311] kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/printwizard/frmprintwizard.h,
+ kipi-plugins/printwizard/frmprintwizardbase.ui:
+ - Added 10x13.33cm into a4 (provided by Joerg Kuehne)
+ - Added A6 size to get the old configuration for 10x15cm page
+ - Changed page size to real 10x15cm instead of A6 (need to set up
+ right page size)
+ - Added a new page size 13x18cm (need to set up right page size)
+
+ CCMAIL: joerg.kuehne@gmx.de, kde-imaging@kde.org
+ GUI:
+
+2007-08-24 09:09 anaselli
+
+ * [r704188] kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/printwizard/frmprintwizard.h,
+ kipi-plugins/printwizard/frmprintwizardbase.ui:
+ - minimal gui review (used some icons on wizard)
+ - added a checkbox to print out with no margins
+
+ GUI:
+ BUG: 103152
+ CCMAIL: kde-imaging@kde.org
+
+2007-08-23 11:30 anaselli
+
+ * [r703811] kipi-plugins/printwizard/frmprintwizard.cpp:
+ - Clean m_photoSize memory if page layout is changed
+ - A4 is really default by now
+ - 10x15 photos layout fixing to print with hp driver (4x6" full
+ bleed mode)
+ it needs test with other printers
+
+ TODO
+ - A6 is not good for 10x15cm, better implementation of pagesize
+ should be needed
+ - need to add 13x18cm (5x7") managed by hp driver
+ - add dpi management, with some tests has improved my print-out
+ quality (needs a code review though)
+
+ Comments and help are welcome :)
+ CCMAIL: kde-imaging@kde.org
+
+2007-08-23 11:21 anaselli
+
+ * [r703809] kipi-plugins/printwizard/utils.cpp,
+ kipi-plugins/printwizard/utils.h:
+ Removed useless code
+
+2007-08-22 13:25 cgilles
+
+ * [r703417] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp:
+ kipi-plugins from KDE3 branch : RAW Converter : patch from
+ Guillaume Castagnino to support new chromatic aberration
+ reduction options from libkdcraw
+
+ CCBUGS: 148561
+ CCMAIL: casta@xwing.info
+
+2007-07-27 22:37 anaselli
+
+ * [r693423] kipi-plugins/printwizard/frmprintwizard.cpp,
+ kipi-plugins/printwizard/frmprintwizard.h,
+ kipi-plugins/printwizard/frmprintwizardbase.ui,
+ kipi-plugins/printwizard/tphoto.cpp,
+ kipi-plugins/printwizard/tphoto.h:
+ Added font management for captions
+ - font family
+ - font color
+ - caption size
+ CCMAIL: kde-imaging@kde.org, digikam-devel@kde.org
+ GUI:
+
+2007-07-23 21:39 anaselli
+
+ * [r691547] kipi-plugins/printwizard/tphoto.cpp:
+ Date is now printed following locale KDE settings
+ CCMAIL: joerg.kuehne@gmx.de, kde-imaging@kde.org
+
+2007-07-23 14:32 cgilles
+
+ * [r691383] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ update
+
+2007-07-22 17:18 vfuoglio
+
+ * [r690988] kipi-plugins/Makefile.am, kipi-plugins/NEWS,
+ kipi-plugins/README, kipi-plugins/configure.in.bot,
+ kipi-plugins/configure.in.in, kipi-plugins/slideshow/Makefile.am,
+ kipi-plugins/slideshow/imlibiface.cpp,
+ kipi-plugins/slideshow/imlibiface.h,
+ kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h:
+ Dropped imlib2 dipendency from SlideShow plugin
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-07-22 12:58 cgilles
+
+ * [r690887] kipi-plugins/AUTHORS:
+ update
+
+2007-07-18 09:18 cgilles
+
+ * [r689447] kipi-plugins/README:
+ update
+
+2007-07-18 09:12 cgilles
+
+ * [r689443] kipi-plugins/AUTHORS:
+ update
+
+2007-07-17 18:06 jaiva
+
+ * [r689130] kipi-plugins/Makefile.am, kipi-plugins/picasawebexport,
+ kipi-plugins/picasawebexport/Makefile,
+ kipi-plugins/picasawebexport/Makefile.am,
+ kipi-plugins/picasawebexport/Makefile.in,
+ kipi-plugins/picasawebexport/PicasawebNewAlbumDialog.ui,
+ kipi-plugins/picasawebexport/PicasawebNewAlbumDialog.ui.h,
+ kipi-plugins/picasawebexport/exifrestorer.cpp,
+ kipi-plugins/picasawebexport/exifrestorer.h,
+ kipi-plugins/picasawebexport/jpegsection.h,
+ kipi-plugins/picasawebexport/kipiplugin_picasawebexport.desktop,
+ kipi-plugins/picasawebexport/mpform.cpp,
+ kipi-plugins/picasawebexport/mpform.h,
+ kipi-plugins/picasawebexport/newAlbumWindow.cpp,
+ kipi-plugins/picasawebexport/newAlbumWindow.h,
+ kipi-plugins/picasawebexport/picasawebitem.cpp,
+ kipi-plugins/picasawebexport/picasawebitem.h,
+ kipi-plugins/picasawebexport/picasaweblogin.cpp,
+ kipi-plugins/picasawebexport/picasaweblogin.h,
+ kipi-plugins/picasawebexport/picasawebtalker.cpp,
+ kipi-plugins/picasawebexport/picasawebtalker.h,
+ kipi-plugins/picasawebexport/picasawebviewitem.cpp,
+ kipi-plugins/picasawebexport/picasawebviewitem.h,
+ kipi-plugins/picasawebexport/picasawebwidget.cpp,
+ kipi-plugins/picasawebexport/picasawebwidget.h,
+ kipi-plugins/picasawebexport/picasawebwindow.cpp,
+ kipi-plugins/picasawebexport/picasawebwindow.h,
+ kipi-plugins/picasawebexport/plugin_picasawebexport.cpp,
+ kipi-plugins/picasawebexport/plugin_picasawebexport.h,
+ kipi-plugins/picasawebexport/uploadwidget.ui:
+ First release PicasaWeb Exporter plugin. Features include
+ Uploading photos, Creating Albums and support Tags and resize on
+ photos.
+ Some more GUI improvements would be done soon.
+
+----------------------------------------------------------------------------
+V 0.1.4 - 2007-06-28
+----------------------------------------------------------------------------
+
+2007-06-21 22:11 gateau
+
+ * [r678657] kipi-plugins/htmlexport/wizard.cpp:
+ Make sure widgets which do not want to get stretched aren't.
+
+2007-06-21 22:01 gateau
+
+ * [r678652] kipi-plugins/htmlexport/theme.cpp:
+ Display parameters in the same order as in the desktop file.
+
+2007-06-21 22:01 gateau
+
+ * [r678651] kipi-plugins/htmlexport/intthemeparameter.cpp:
+ Remove useless kdebug
+
+2007-06-21 21:24 gateau
+
+ * [r678631] kipi-plugins/htmlexport/themes/classic/classic.desktop,
+ kipi-plugins/htmlexport/themes/classic/template.xsl:
+ Added missing color parameters.
+
+2007-06-21 21:23 gateau
+
+ * [r678630] kipi-plugins/htmlexport/themes/classic/classic.desktop,
+ kipi-plugins/htmlexport/themes/classic/template.xsl:
+ Make use of the new int parameter type.
+
+2007-06-21 21:23 gateau
+
+ * [r678629] kipi-plugins/htmlexport/Makefile.am,
+ kipi-plugins/htmlexport/THEME_HOWTO,
+ kipi-plugins/htmlexport/intthemeparameter.cpp,
+ kipi-plugins/htmlexport/intthemeparameter.h,
+ kipi-plugins/htmlexport/theme.cpp:
+ Added a new theme parameter type: int.
+
+2007-06-21 21:23 gateau
+
+ * [r678627] kipi-plugins/htmlexport/abstractthemeparameter.h:
+ Prevent troubles. d pointer should be private, not protected.
+
+2007-06-20 21:18 gateau
+
+ * [r678196] kipi-plugins/htmlexport/generator.cpp:
+ Fixed crash when trying to create /a/b/c if b does not exist.
+
+2007-06-20 17:06 vfuoglio
+
+ * [r678081] kipi-plugins/slideshow/Makefile.am:
+ Fixed problem with libkio linking into Makefile.am.
+ Thanks to Rex Dieter for the patch.
+
+ CCMAIL: kde-imaging@kde.org
+
+----------------------------------------------------------------------------
+V 0.1.4-beta2 - 2007-06-20
+----------------------------------------------------------------------------
+2007-06-20 17:06 vfuoglio
+
+ * [r678081] kipi-plugins/slideshow/Makefile.am:
+ Fixed problem with libkio linking into Makefile.am.
+ Thanks to Rex Dieter for the patch.
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-06-18 22:43 ach
+
+ * [r677342] kipi-plugins/common/include/kpaboutdata.h:
+ kipi-plugins currently does not compile with
+ gcc-hidden-visibility because the
+ common lib does not export its classes (KPAboutData).
+ If a class is contained in a library is used from outside this
+ library, it
+ must be exported to be visible.
+ The attached patch fixes the problem.
+
+ Patch from Marcel Wiesweg
+
+2007-06-18 22:40 ach
+
+ * [r677341] kipi-plugins/configure.in.bot,
+ kipi-plugins/configure.in.in:
+ allow libgpod versions > 0.4.2 not only = 0.4.2
+
+2007-06-18 21:49 vfuoglio
+
+ * [r677319] kipi-plugins/ChangeLog,
+ kipi-plugins/common/include/pluginsversion.h,
+ kipi-plugins/kipi-plugins.lsm, prepare_kipiplugins.rb:
+ Preparing release of kipi-plugins-0.1.4-beta2
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-06-18 00:08 vfuoglio
+
+ * [r676928] kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfigbase.ui,
+ kipi-plugins/slideshow/slideshowgl.cpp,
+ kipi-plugins/slideshow/slideshowgl.h:
+ Progress indicator printing doesn't depend from file name
+ printing anymore.
+
+ GUI:
+ CCMAIL: kde-imaging@kde.org
+
+2007-06-14 22:23 vfuoglio
+
+ * [r675742] kipi-plugins/slideshow/plugin_slideshow.cpp:
+ Fixed BUG 146799 , titled "digikam 0.9.2 crashes when exiting -
+ slideshow error".
+
+ BUG: 146799
+ CCMAIL: kde-imaging@kde.org
+ CCMAIL: digikam-users@kde.org
+
+2007-06-14 05:39 cgilles
+
+ * [r675348] kipi-plugins/NEWS:
+ update
+
+2007-06-13 21:17 vfuoglio
+
+ * [r675261] kipi-plugins/NEWS, kipi-plugins/slideshow/Makefile.am,
+ kipi-plugins/slideshow/listimageitems.cpp,
+ kipi-plugins/slideshow/listimageitems.h,
+ kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/plugin_slideshow.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h,
+ kipi-plugins/slideshow/slideshowconfigbase.ui:
+ Images can be sorted/added/removed manually.
+
+ CCMAIL: kde-imaging@kde.org
+ GUI:
+
+2007-06-13 06:13 hoechstetter
+
+ * [r674794] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.h:
+ M sendimages/sendimages.cpp
+ M sendimages/sendimagesdialog.cpp
+ M sendimages/sendimagesdialog.h
+
+
+2007-06-11 12:09 cgilles
+
+ * [r673925] kipi-plugins/README:
+ fix depencies
+
+2007-06-11 12:07 cgilles
+
+ * [r673924] kipi-plugins/configure.in.bot,
+ kipi-plugins/configure.in.in:
+ fix depencies
+
+2007-06-11 07:53 cgilles
+
+ * [r673866]
+ kipi-plugins/rawconverter/kipiplugin_rawconverter.desktop:
+ fix author
+
+2007-06-11 07:50 cgilles
+
+ * [r673865] kipi-plugins/rawconverter/actions.h,
+ kipi-plugins/rawconverter/actionthread.cpp,
+ kipi-plugins/rawconverter/actionthread.h,
+ kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/batchdialog.h,
+ kipi-plugins/rawconverter/clistviewitem.h,
+ kipi-plugins/rawconverter/mtqueue.h,
+ kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ kipi-plugins/rawconverter/plugin_rawconverter.h,
+ kipi-plugins/rawconverter/previewwidget.cpp,
+ kipi-plugins/rawconverter/previewwidget.h,
+ kipi-plugins/rawconverter/rawdecodingiface.cpp,
+ kipi-plugins/rawconverter/rawdecodingiface.h,
+ kipi-plugins/rawconverter/savesettingswidget.cpp,
+ kipi-plugins/rawconverter/savesettingswidget.h,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/rawconverter/singledialog.h:
+ fix header
+
+2007-06-11 06:46 cgilles
+
+ * [r673857] kipi-plugins/rawconverter/Makefile.am,
+ kipi-plugins/rawconverter/hi32-action-rawconverterbatch.png,
+ kipi-plugins/rawconverter/hi32-action-rawconvertersingle.png,
+ kipi-plugins/rawconverter/pics,
+ kipi-plugins/rawconverter/pics/Makefile.am,
+ kipi-plugins/rawconverter/pics/hi32-action-rawconverterbatch.png,
+ kipi-plugins/rawconverter/pics/hi32-action-rawconvertersingle.png:
+ move png files to pics sub-folder
+
+2007-06-11 06:41 cgilles
+
+ * [r673855] kipi-plugins/jpeglossless/Makefile.am,
+ kipi-plugins/jpeglossless/hi32-action-flip.png,
+ kipi-plugins/jpeglossless/hi32-action-grayscaleconvert.png,
+ kipi-plugins/jpeglossless/pics,
+ kipi-plugins/jpeglossless/pics/Makefile.am,
+ kipi-plugins/jpeglossless/pics/hi32-action-flip.png,
+ kipi-plugins/jpeglossless/pics/hi32-action-grayscaleconvert.png:
+ move png files to pics sub-folder
+
+2007-06-11 06:20 cgilles
+
+ * [r673854] kipi-plugins/timeadjust/kipiplugin_timeadjust.desktop:
+ fix email
+
+2007-06-11 06:12 cgilles
+
+ * [r673850] kipi-plugins/jpeglossless/actions.h,
+ kipi-plugins/jpeglossless/actionthread.cpp,
+ kipi-plugins/jpeglossless/actionthread.h,
+ kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/convert2grayscale.h,
+ kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imageflip.h,
+ kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/imagerotate.h,
+ kipi-plugins/jpeglossless/jpegtransform.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.h,
+ kipi-plugins/jpeglossless/kipiplugin_jpeglossless.desktop,
+ kipi-plugins/jpeglossless/mtqueue.h,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.h,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/jpeglossless/utils.h:
+ fix header
+
+2007-06-11 00:39 vfuoglio
+
+ * [r673751] kipi-plugins/mpegencoder/kimg2mpgbase.ui:
+ Fixed preview's stretch error.
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-06-10 00:05 vfuoglio
+
+ * [r673346] kipi-plugins/NEWS,
+ kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h,
+ kipi-plugins/slideshow/slideshowconfigbase.ui,
+ kipi-plugins/slideshow/slideshowgl.cpp,
+ kipi-plugins/slideshow/slideshowgl.h:
+ Added possibility to navigate between images using mouse wheel
+ scroll.
+
+ CCMAIL : kde-imaging@kde.org
+ GUI :
+
+2007-06-09 09:59 cgilles
+
+ * [r673188] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ more debug info
+
+2007-06-09 09:57 cgilles
+
+ * [r673187] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ polish
+
+2007-06-09 09:49 cgilles
+
+ * [r673186] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ polish
+
+2007-06-09 09:35 cgilles
+
+ * [r673184] kipi-plugins/kipiplugins.kdevelop,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ only show error dialog if meatadata has changed
+
+2007-06-09 09:07 cgilles
+
+ * [r673179] kipi-plugins/NEWS:
+ --Cetupdatete ligne, et les suivantes ci-dessous, seront
+ ignorées--
+
+ M NEWS
+
+2007-06-09 09:06 cgilles
+
+ * [r673178] kipi-plugins/timeadjust/timeadjustdialog.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.h:
+ kipi-plugins from KDE3 branch : TimeAdjust : remember the custom
+ date set by user between session. Add button to reset custom date
+ to current date.
+ BUG: 144185
+
+2007-06-09 08:21 cgilles
+
+ * [r673173] kipi-plugins/NEWS:
+ update
+
+2007-06-09 08:20 cgilles
+
+ * [r673172] kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ kipi-plugins from KDE3 branch : TimeAdjust : use local date time
+ encoding to display exemple on bottom of dialog
+ BUG: 140890
+
+2007-06-08 20:41 cgilles
+
+ * [r673047] kipi-plugins/NEWS:
+ --Cette ligupdatene, et les suivantes ci-dessous, seront
+ ignorées--
+
+ M NEWS
+
+2007-06-08 20:40 cgilles
+
+ * [r673045] kipi-plugins/timeadjust/plugin_timeadjust.cpp,
+ kipi-plugins/timeadjust/plugin_timeadjust.h,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.h:
+ kipi-plugins from KDE3 branch : Time Adjust plugin : fix
+ modification and access file date accordinly to setting of tool.
+ BUG: 138880
+
+2007-06-08 19:18 cgilles
+
+ * [r673016] kipi-plugins/configure.in.in:
+ compile
+
+2007-06-08 19:16 kusi
+
+ * [r673014] kipi-plugins/README:
+ adding KIPI imageviewer
+
+2007-06-08 12:18 cgilles
+
+ * [r672887] kipi-plugins/kipi-plugins.lsm:
+ fix email
+
+2007-06-07 22:11 gateau
+
+ * [r672709] kipi-plugins/AUTHORS:
+ Added HTMLExport theme authors
+
+2007-06-07 22:11 gateau
+
+ * [r672708] kipi-plugins/NEWS:
+ Added latest changes from HTMLExport
+
+2007-06-07 15:30 cgilles
+
+ * [r672585] kipi-plugins/jpeglossless/Makefile.am:
+ libkdcraw rules are missing
+
+2007-06-07 15:13 cgilles
+
+ * [r672578] kipi-plugins/htmlexport/themes/cleanframes/Makefile.in:
+ rm
+
+2007-06-07 15:12 cgilles
+
+ * [r672577] kipi-plugins/configure.in.in,
+ kipi-plugins/htmlexport/themes/cleanframes/Makefile.in:
+ compile--Cette ligne, et les suivantes ci-dessous, seront
+ ignorées--
+
+ M kipi-plugins/htmlexport/themes/cleanframes/Makefile.in
+ M kipi-plugins/configure.in.in
+
+2007-06-07 14:56 cgilles
+
+ * [r672569] kipi-plugins/configure.in.in:
+ compile
+
+2007-06-07 03:57 vfuoglio
+
+ * [r672427] kipi-plugins/NEWS,
+ kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshowgl.cpp:
+ Skip to next or previous image can be also done with a mouse
+ click.
+
+ Backported some code from digiKam's slideshow (thanks to Gilles).
+
+ CCMAIL: kde-imaging@kde.org
+ BUG: 143450
+
+2007-06-06 21:07 gateau
+
+ * [r672369] kipi-plugins/htmlexport/themes/cleanframes/Makefile.am,
+ kipi-plugins/htmlexport/themes/cleanframes/black.css,
+ kipi-plugins/htmlexport/themes/cleanframes/blue.css,
+ kipi-plugins/htmlexport/themes/cleanframes/brown.css,
+ kipi-plugins/htmlexport/themes/cleanframes/cleanframes.desktop,
+ kipi-plugins/htmlexport/themes/cleanframes/green.css,
+ kipi-plugins/htmlexport/themes/cleanframes/lavender.css,
+ kipi-plugins/htmlexport/themes/cleanframes/pink.css,
+ kipi-plugins/htmlexport/themes/cleanframes/red.css,
+ kipi-plugins/htmlexport/themes/cleanframes/star.png,
+ kipi-plugins/htmlexport/themes/cleanframes/style.css,
+ kipi-plugins/htmlexport/themes/cleanframes/template.xsl,
+ kipi-plugins/htmlexport/themes/cleanframes/yellow.css:
+ New version, featuring several color variants. Many thanks to
+ Beth Marmorstein!
+ CCMAIL: purplegamba@verizon.net
+
+2007-06-06 16:34 anaselli
+
+ * [r672285] kipi-plugins/configure.in.in:
+ Rex Dieter reported a libgobject2-0 problem and a patch to fix
+ it.
+
+ Please check if there are problems.
+ CCMAIL: kde-imaging@kde.org
+
+2007-06-06 06:49 cgilles
+
+ * [r672128] kipi-plugins/NEWS:
+ update
+
+2007-06-06 00:56 hoechstetter
+
+ * [r672009] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h:
+ If a description is available, it is used as name for the new
+ generated foto. This is the most simple and cleanest solution;
+ BUG: 140477;
+
+2007-06-04 22:42 gateau
+
+ * [r671521] kipi-plugins/htmlexport/THEME_HOWTO:
+ Added doc about original images.
+
+2007-06-04 22:35 gateau
+
+ * [r671519] kipi-plugins/htmlexport/THEME_HOWTO:
+ - Explained how to use i18n parameters in attributes.
+ - Simplified theme parameters example.
+
+2007-06-04 22:31 gateau
+
+ * [r671518] kipi-plugins/htmlexport/themes/Makefile.am,
+ kipi-plugins/htmlexport/themes/classic,
+ kipi-plugins/htmlexport/themes/classic/Makefile.am,
+ kipi-plugins/htmlexport/themes/classic/classic.desktop,
+ kipi-plugins/htmlexport/themes/classic/gohome.png,
+ kipi-plugins/htmlexport/themes/classic/template.xsl,
+ kipi-plugins/htmlexport/themes/classic/up.png:
+ Added port of the theme from the old plugin. Not finished, but
+ working.
+
+2007-06-03 22:08 anaselli
+
+ * [r671150] kipi-plugins/ChangeLog, kipi-plugins/kipi-plugins.lsm:
+ Release 0.1.4 - beta1
+
+----------------------------------------------------------------------------
+V 0.1.4-beta1 - 2007-06-04
+----------------------------------------------------------------------------
+
+2007-06-03 21:49 anaselli
+
+ * [r671143] kipi-plugins/mpegencoder/kimg2mpg.cpp:
+ sigkill wrongly sent to application
+ BUG: 145771
+
+2007-06-03 15:31 gateau
+
+ * [r671035] kipi-plugins/htmlexport/colorthemeparameter.h,
+ kipi-plugins/htmlexport/galleryinfo.h,
+ kipi-plugins/htmlexport/generator.cpp,
+ kipi-plugins/htmlexport/generator.h,
+ kipi-plugins/htmlexport/listthemeparameter.h,
+ kipi-plugins/htmlexport/plugin.h,
+ kipi-plugins/htmlexport/stringthemeparameter.h,
+ kipi-plugins/htmlexport/wizard.h:
+ Updated Doxygen doc.
+
+2007-06-03 14:01 gkulzer
+
+ * [r671014] kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp:
+ i18n patch from Frank Siegert
+
+2007-06-02 14:14 helio
+
+ * [r670712] ., trunk/extragear/libs:
+ - First directory to move. No 4.x apps here yet.
+
+2007-06-02 10:57 gateau
+
+ * [r670657] kipi-plugins/htmlexport/themes/s0/template.xsl:
+ Make theme use only i18n parameters for texts.
+
+2007-06-02 10:55 gateau
+
+ * [r670656] kipi-plugins/htmlexport/themes/Makefile.am,
+ kipi-plugins/htmlexport/themes/s0/Makefile.am:
+ Fix install of s0 theme.
+
+2007-06-02 10:53 gateau
+
+ * [r670655] kipi-plugins/htmlexport/THEME_HOWTO,
+ kipi-plugins/htmlexport/generator.cpp:
+ Added new i18n parameter: i18nUp
+
+2007-06-01 21:31 gateau
+
+ * [r670526] kipi-plugins/htmlexport/themes/Makefile.am,
+ kipi-plugins/htmlexport/themes/cleanframes,
+ kipi-plugins/htmlexport/themes/cleanframes/Makefile.am,
+ kipi-plugins/htmlexport/themes/cleanframes/Makefile.in,
+ kipi-plugins/htmlexport/themes/cleanframes/cleanframes.desktop,
+ kipi-plugins/htmlexport/themes/cleanframes/style.css,
+ kipi-plugins/htmlexport/themes/cleanframes/template.xsl:
+ Added a new theme: "Clean Frames", from Elizabeth Marmorstein
+
+2007-05-31 15:09 cgilles
+
+ * [r670170] kipi-plugins/NEWS:
+ typo
+
+2007-05-31 15:05 cgilles
+
+ * [r670168] kipi-plugins/NEWS:
+ update
+
+2007-05-31 14:49 vfuoglio
+
+ * [r670164] kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h,
+ kipi-plugins/slideshow/slideshowconfigbase.ui:
+ Changed start and exit buttons name.
+ Added possibility to use seconds instead of milliseconds.
+ 'Seconds' is the new default unit.
+
+ CCMAIL: kde-imaging@kde.org
+ BUG: 146084
+ GUI:
+
+2007-05-24 13:39 cgilles
+
+ * [r667931] kipi-plugins/common/include/kpaboutdata.h:
+ fix date
+
+2007-05-24 13:38 cgilles
+
+ * [r667930] kipi-plugins/kipi-plugins.lsm:
+ update
+
+2007-05-24 13:37 cgilles
+
+ * [r667929] kipi-plugins/NEWS:
+ update
+
+2007-05-24 13:34 cgilles
+
+ * [r667926] kipi-plugins/flickrexport/flickrtalker.cpp:
+ kipi-plugins from trunk : patch from Andrew Wilkinson to prevent
+ multiple Tags creation with Flickr Export plugin when Tags
+ strings include spaces.
+ CCMAIL: ajw140@york.ac.uk
+ BUG: 135945
+
+2007-05-22 08:17 gateau
+
+ * [r667224] kipi-plugins/htmlexport/wizard.cpp:
+ - Do not crash when switching between themes.
+ - Skip the "Theme Parameters" page if the selected theme does not
+ contain any
+ parameter.
+
+2007-05-21 10:25 cgilles
+
+ * [r666938] kipi-plugins/printwizard/plugin_printwizard.cpp,
+ kipi-plugins/printwizard/plugin_printwizard.h:
+ kipi-plugins from trunk : Print Wizard tool :
+
+ - Add CTRL+P shortcut.
+ - Change EXPORTPLUGIN plugin category to IMAGESPLUGIN. The tool
+ never work on a complete album, only with a selection of
+ pictures.
+
+ BUG : 144640
+
+2007-05-21 09:28 fsalvi
+
+ * [r666920] kipi-plugins/Makefile.am:
+ Prevent calendar from being compiled when libkcal test is
+ negative.
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-05-16 07:23 cgilles
+
+ * [r665214] kipi-plugins/AUTHORS:
+ update
+
+2007-05-13 18:46 gateau
+
+ * [r664351] kipi-plugins/htmlexport/THEME_HOWTO,
+ kipi-plugins/htmlexport/TODO:
+ Added a theme howto. Would be nice to have someone review it :-)
+ CCMAIL:kde-imaging@kde.org
+
+2007-05-13 18:45 gateau
+
+ * [r664350] kipi-plugins/htmlexport/abstractthemeparameter.h,
+ kipi-plugins/htmlexport/theme.h:
+ Added some Doxygen info
+
+2007-05-07 20:08 cgilles
+
+ * [r662290] kipi-plugins/jpeglossless/plugin_jpeglossless.cpp:
+ kipi-plugins from trunk : JPEGLossLess : fix crash with
+ auto-close of progress dialog when kipi host is closed.
+
+2007-05-06 17:42 orgads
+
+ * [r661820] kipi-plugins/configure.in.bot,
+ kipi-plugins/configure.in.in:
+ * Added checking for libkcal (calendar plugin) and appropriate
+ messages
+
+2007-05-06 17:23 orgads
+
+ * [r661814] kipi-plugins/README:
+ * Added dependency for calendar: libkcal
+
+2007-05-05 10:53 gateau
+
+ * [r661368] kipi-plugins/htmlexport/themes/simple/Makefile.am,
+ kipi-plugins/htmlexport/themes/simple/dark.css,
+ kipi-plugins/htmlexport/themes/simple/natural.css,
+ kipi-plugins/htmlexport/themes/simple/simple.desktop,
+ kipi-plugins/htmlexport/themes/simple/style.css,
+ kipi-plugins/htmlexport/themes/simple/template.xsl:
+ Added a theme variant to the "Simple" theme. This variant is
+ called "Dark".
+ Now you get to see what I have been doing with those theme
+ parameters.
+ CCMAIL: kde-imaging@kde.org
+
+2007-05-04 12:43 orgads
+
+ * [r661032] kipi-plugins/calendar/calevents.cpp,
+ kipi-plugins/calendar/calevents.h,
+ kipi-plugins/calendar/caleventsbase.ui,
+ kipi-plugins/calendar/calformatter.cpp,
+ kipi-plugins/calendar/calformatter.h:
+ * Added some missing files.
+
+2007-05-04 12:38 orgads
+
+ * [r661026] kipi-plugins/calendar/Makefile.am,
+ kipi-plugins/calendar/calpainter.cpp,
+ kipi-plugins/calendar/calpainter.h,
+ kipi-plugins/calendar/calselect.cpp,
+ kipi-plugins/calendar/calselect.h,
+ kipi-plugins/calendar/calsettings.cpp,
+ kipi-plugins/calendar/calwidget.cpp,
+ kipi-plugins/calendar/calwizard.cpp,
+ kipi-plugins/calendar/calwizard.h,
+ kipi-plugins/calendar/monthwidget.cpp:
+ * Added support for non-gregorian calendar system (active
+ calendar system by locale settings)
+ * The calendar cells have different width and heights in order to
+ fill the complete page width.
+ * The font is bigger
+ * The calendar lines are printed by default.
+ * The unused "printCalendar" function is deleted (why was it
+ there?).
+ * There is a new page in the wizard that lets you choose 2
+ iCalendar files.
+ This step is totally optional. The events from the first file are
+ going to be
+ printed on red and the second one on green. This lets you print
+ the official
+ holidays (red) and your private ones (green).
+ * Because of e) the libkcal (kdepim) dependency has been
+ introduced.
+ (thanks to Maciek Borowka)
+
+2007-05-02 19:54 gateau
+
+ * [r660468] kipi-plugins/htmlexport/Makefile.am,
+ kipi-plugins/htmlexport/colorthemeparameter.cpp,
+ kipi-plugins/htmlexport/colorthemeparameter.h,
+ kipi-plugins/htmlexport/theme.cpp:
+ Added new type of theme parameter: color.
+
+2007-05-02 19:53 gateau
+
+ * [r660466] kipi-plugins/htmlexport/stringthemeparameter.cpp,
+ kipi-plugins/htmlexport/stringthemeparameter.h:
+ Removed useless overload and d pointer.
+
+2007-05-02 08:03 gateau
+
+ * [r660294] kipi-plugins/htmlexport/wizard.cpp:
+ Add a spacer on the right of theme parameter widgets.
+
+2007-05-02 08:01 gateau
+
+ * [r660293] kipi-plugins/htmlexport/generator.cpp,
+ kipi-plugins/htmlexport/themes/frames/template.xsl,
+ kipi-plugins/htmlexport/themes/matrix/template.xsl,
+ kipi-plugins/htmlexport/themes/s0/template.xsl,
+ kipi-plugins/htmlexport/themes/simple/template.xsl,
+ kipi-plugins/htmlexport/themes/snow/template.xsl:
+ Applied modified version of Colin McMillen which add links to
+ download original
+ images.
+
+ Just replaced the english text for "View original image" with a
+ new $i18n
+ variable: $i18nOriginalImage. This way themes remain fully
+ translated.
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-05-02 07:26 cgilles
+
+ * [r660288] kipi-plugins/gpssync/getlonlat.php:
+ fix email
+
+2007-05-02 07:24 cgilles
+
+ * [r660287] kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commenteditdialog.h,
+ kipi-plugins/metadataedit/commentremovedialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.h,
+ kipi-plugins/metadataedit/exifadjust.cpp,
+ kipi-plugins/metadataedit/exifadjust.h,
+ kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifcaption.h,
+ kipi-plugins/metadataedit/exifdatetime.cpp,
+ kipi-plugins/metadataedit/exifdatetime.h,
+ kipi-plugins/metadataedit/exifdevice.cpp,
+ kipi-plugins/metadataedit/exifdevice.h,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.h,
+ kipi-plugins/metadataedit/exiflens.cpp,
+ kipi-plugins/metadataedit/exiflens.h,
+ kipi-plugins/metadataedit/exiflight.cpp,
+ kipi-plugins/metadataedit/exiflight.h,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptccaption.h,
+ kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptccategories.h,
+ kipi-plugins/metadataedit/iptccredits.cpp,
+ kipi-plugins/metadataedit/iptccredits.h,
+ kipi-plugins/metadataedit/iptcdatetime.cpp,
+ kipi-plugins/metadataedit/iptcdatetime.h,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.h,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptckeywords.h,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcorigin.h,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcstatus.h,
+ kipi-plugins/metadataedit/iptcsubjects.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.h,
+ kipi-plugins/metadataedit/metadatacheckbox.cpp,
+ kipi-plugins/metadataedit/metadatacheckbox.h,
+ kipi-plugins/metadataedit/plugin_metadataedit.cpp,
+ kipi-plugins/metadataedit/plugin_metadataedit.h:
+ fix headers
+
+2007-05-02 07:05 cgilles
+
+ * [r660281] kipi-plugins/jpeglossless/actionthread.cpp,
+ kipi-plugins/jpeglossless/actionthread.h,
+ kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/convert2grayscale.h,
+ kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imageflip.h,
+ kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/imagerotate.h,
+ kipi-plugins/jpeglossless/jpegtransform.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.h,
+ kipi-plugins/jpeglossless/mtqueue.h,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.h,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/jpeglossless/utils.h:
+ fix headers
+
+2007-05-02 06:55 cgilles
+
+ * [r660278] kipi-plugins/gpssync/gpsbabelbinary.cpp,
+ kipi-plugins/gpssync/gpsbabelbinary.h,
+ kipi-plugins/gpssync/gpsdatacontainer.h,
+ kipi-plugins/gpssync/gpsdataparser.cpp,
+ kipi-plugins/gpssync/gpsdataparser.h,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.h,
+ kipi-plugins/gpssync/kipiplugin_gpssync.desktop,
+ kipi-plugins/gpssync/plugin_gpssync.cpp,
+ kipi-plugins/gpssync/plugin_gpssync.h,
+ kipi-plugins/jpeglossless/actions.h,
+ kipi-plugins/jpeglossless/actionthread.cpp,
+ kipi-plugins/jpeglossless/actionthread.h,
+ kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/convert2grayscale.h,
+ kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imageflip.h,
+ kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/imagerotate.h,
+ kipi-plugins/jpeglossless/jpegtransform.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.h,
+ kipi-plugins/jpeglossless/mtqueue.h,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/jpeglossless/utils.h,
+ kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commenteditdialog.h,
+ kipi-plugins/metadataedit/commentremovedialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.h,
+ kipi-plugins/metadataedit/exifadjust.cpp,
+ kipi-plugins/metadataedit/exifadjust.h,
+ kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifcaption.h,
+ kipi-plugins/metadataedit/exifdatetime.cpp,
+ kipi-plugins/metadataedit/exifdatetime.h,
+ kipi-plugins/metadataedit/exifdevice.cpp,
+ kipi-plugins/metadataedit/exifdevice.h,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.h,
+ kipi-plugins/metadataedit/exiflens.cpp,
+ kipi-plugins/metadataedit/exiflens.h,
+ kipi-plugins/metadataedit/exiflight.cpp,
+ kipi-plugins/metadataedit/exiflight.h,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptccaption.h,
+ kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptccategories.h,
+ kipi-plugins/metadataedit/iptccredits.cpp,
+ kipi-plugins/metadataedit/iptccredits.h,
+ kipi-plugins/metadataedit/iptcdatetime.cpp,
+ kipi-plugins/metadataedit/iptcdatetime.h,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.h,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptckeywords.h,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcorigin.h,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcstatus.h,
+ kipi-plugins/metadataedit/iptcsubjects.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.h,
+ kipi-plugins/metadataedit/kipiplugin_metadataedit.desktop,
+ kipi-plugins/metadataedit/metadatacheckbox.cpp,
+ kipi-plugins/metadataedit/metadatacheckbox.h,
+ kipi-plugins/metadataedit/plugin_metadataedit.cpp,
+ kipi-plugins/metadataedit/plugin_metadataedit.h,
+ kipi-plugins/mpegencoder/plugin_mpegencoder.cpp,
+ kipi-plugins/mpegencoder/plugin_mpegencoder.h,
+ kipi-plugins/sendimages/actions.h,
+ kipi-plugins/sendimages/listimageserrordialog.cpp,
+ kipi-plugins/sendimages/listimageserrordialog.h,
+ kipi-plugins/sendimages/plugin_sendimages.cpp,
+ kipi-plugins/sendimages/plugin_sendimages.h,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.h,
+ kipi-plugins/timeadjust/plugin_timeadjust.cpp,
+ kipi-plugins/timeadjust/plugin_timeadjust.h,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.h:
+ fix email
+
+2007-05-01 23:08 gateau
+
+ * [r660206] kipi-plugins/htmlexport/Makefile.am,
+ kipi-plugins/htmlexport/abstractthemeparameter.cpp,
+ kipi-plugins/htmlexport/abstractthemeparameter.h,
+ kipi-plugins/htmlexport/galleryinfo.cpp,
+ kipi-plugins/htmlexport/galleryinfo.h,
+ kipi-plugins/htmlexport/generator.cpp,
+ kipi-plugins/htmlexport/listthemeparameter.cpp,
+ kipi-plugins/htmlexport/listthemeparameter.h,
+ kipi-plugins/htmlexport/stringthemeparameter.cpp,
+ kipi-plugins/htmlexport/stringthemeparameter.h,
+ kipi-plugins/htmlexport/wizard.cpp:
+ Save values of theme parameters.
+
+2007-05-01 22:13 gateau
+
+ * [r660196] kipi-plugins/htmlexport/generator.cpp,
+ kipi-plugins/htmlexport/theme.cpp,
+ kipi-plugins/htmlexport/theme.h,
+ kipi-plugins/htmlexport/wizard.cpp:
+ Identify theme by internal name, not by path.
+
+2007-05-01 21:39 gateau
+
+ * [r660187] kipi-plugins/htmlexport/abstractthemeparameter.cpp,
+ kipi-plugins/htmlexport/abstractthemeparameter.h,
+ kipi-plugins/htmlexport/listthemeparameter.cpp,
+ kipi-plugins/htmlexport/listthemeparameter.h,
+ kipi-plugins/htmlexport/stringthemeparameter.cpp,
+ kipi-plugins/htmlexport/stringthemeparameter.h,
+ kipi-plugins/htmlexport/theme.cpp,
+ kipi-plugins/htmlexport/wizard.cpp:
+ Renamed ThemeParameter::name to internalName and
+ ThemeParameter::title to name.
+ This is more consistent with the Theme class.
+
+2007-05-01 21:28 gateau
+
+ * [r660186] kipi-plugins/htmlexport/Makefile.am,
+ kipi-plugins/htmlexport/listthemeparameter.cpp,
+ kipi-plugins/htmlexport/listthemeparameter.h,
+ kipi-plugins/htmlexport/theme.cpp:
+ Implemented a new type of theme parameter: List.
+
+2007-04-30 20:15 gateau
+
+ * [r659794] kipi-plugins/htmlexport/Makefile.am,
+ kipi-plugins/htmlexport/abstractthemeparameter.cpp,
+ kipi-plugins/htmlexport/abstractthemeparameter.h,
+ kipi-plugins/htmlexport/galleryinfo.h,
+ kipi-plugins/htmlexport/generator.cpp,
+ kipi-plugins/htmlexport/stringthemeparameter.cpp,
+ kipi-plugins/htmlexport/stringthemeparameter.h,
+ kipi-plugins/htmlexport/theme.cpp,
+ kipi-plugins/htmlexport/theme.h,
+ kipi-plugins/htmlexport/themeparameterspage.ui,
+ kipi-plugins/htmlexport/wizard.cpp:
+ Started to add support for theme parameters.
+
+2007-04-29 15:03 gateau
+
+ * [r659139] kipi-plugins/htmlexport/themes/Makefile.am,
+ kipi-plugins/htmlexport/themes/frames,
+ kipi-plugins/htmlexport/themes/frames/Makefile.am,
+ kipi-plugins/htmlexport/themes/frames/frames.desktop,
+ kipi-plugins/htmlexport/themes/frames/style.css,
+ kipi-plugins/htmlexport/themes/frames/template.xsl:
+ Added new theme by Rüdiger Bente. Thanks!
+
+2007-04-28 22:37 gateau
+
+ * [r658936] kipi-plugins/htmlexport/imagesettingspage.ui:
+ Oups, forgot to rename widget.
+
+2007-04-28 22:16 gateau
+
+ * [r658933] kipi-plugins/htmlexport/generator.cpp,
+ kipi-plugins/htmlexport/plugin.cpp,
+ kipi-plugins/htmlexport/wizard.cpp,
+ kipi-plugins/htmlexport/wizard.h:
+ Fix indentation and coding style.
+
+2007-04-28 22:04 gateau
+
+ * [r658930] kipi-plugins/htmlexport/generator.cpp,
+ kipi-plugins/htmlexport/htmlexportconfig.kcfg,
+ kipi-plugins/htmlexport/imagesettingspage.ui:
+ Added support for including original image for download, based on
+ a patch by
+ Colin McMillen. Thanks Colin!
+
+2007-04-28 19:40 gkulzer
+
+ * [r658898] kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ kipi-plugins/acquireimages/acquireimagedialog.h,
+ kipi-plugins/acquireimages/plugin_acquireimages.cpp,
+ kipi-plugins/acquireimages/plugin_acquireimages.h,
+ kipi-plugins/acquireimages/screenshotdialog.cpp,
+ kipi-plugins/acquireimages/screenshotdialog.h,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.h,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.h,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.h,
+ kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/borderimagesdialog.h,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.h,
+ kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/colorimagesdialog.h,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.h,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.h,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.h,
+ kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/effectimagesdialog.h,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.h,
+ kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/filterimagesdialog.h,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.h,
+ kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.h,
+ kipi-plugins/batchprocessimages/outputdialog.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.h,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.h,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.h,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.h,
+ kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimagesdialog.h,
+ kipi-plugins/batchprocessimages/renameimageswidget.cpp,
+ kipi-plugins/batchprocessimages/renameimageswidget.h,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.h,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.h,
+ kipi-plugins/calendar/calpainter.cpp,
+ kipi-plugins/calendar/calpainter.h,
+ kipi-plugins/calendar/calprint.h,
+ kipi-plugins/calendar/calselect.cpp,
+ kipi-plugins/calendar/calselect.h,
+ kipi-plugins/calendar/calsettings.cpp,
+ kipi-plugins/calendar/calsettings.h,
+ kipi-plugins/calendar/caltemplate.cpp,
+ kipi-plugins/calendar/caltemplate.h,
+ kipi-plugins/calendar/calwidget.cpp,
+ kipi-plugins/calendar/calwidget.h,
+ kipi-plugins/calendar/calwizard.cpp,
+ kipi-plugins/calendar/calwizard.h,
+ kipi-plugins/calendar/monthwidget.cpp,
+ kipi-plugins/calendar/monthwidget.h,
+ kipi-plugins/calendar/plugin_calendar.cpp,
+ kipi-plugins/calendar/plugin_calendar.h,
+ kipi-plugins/cdarchiving/actions.h,
+ kipi-plugins/cdarchiving/cdarchiving.cpp,
+ kipi-plugins/cdarchiving/cdarchiving.h,
+ kipi-plugins/cdarchiving/cdarchivingdialog.cpp,
+ kipi-plugins/cdarchiving/cdarchivingdialog.h,
+ kipi-plugins/cdarchiving/plugin_cdarchiving.cpp,
+ kipi-plugins/cdarchiving/plugin_cdarchiving.h,
+ kipi-plugins/common/include/kpaboutdata.h,
+ kipi-plugins/common/include/pluginsversion.h,
+ kipi-plugins/common/libkipiplugins/kpaboutdata.cpp,
+ kipi-plugins/findimages/actions.cpp,
+ kipi-plugins/findimages/actions.h,
+ kipi-plugins/findimages/compareoperation.h,
+ kipi-plugins/findimages/displaycompare.cpp,
+ kipi-plugins/findimages/displaycompare.h,
+ kipi-plugins/findimages/fastcompare.cpp,
+ kipi-plugins/findimages/fastcompare.h,
+ kipi-plugins/findimages/finddupplicatedialog.cpp,
+ kipi-plugins/findimages/finddupplicatedialog.h,
+ kipi-plugins/findimages/finddupplicateimages.cpp,
+ kipi-plugins/findimages/finddupplicateimages.h,
+ kipi-plugins/findimages/fuzzycompare.cpp,
+ kipi-plugins/findimages/fuzzycompare.h,
+ kipi-plugins/findimages/imagesimilaritydata.h,
+ kipi-plugins/findimages/plugin_findimages.cpp,
+ kipi-plugins/findimages/plugin_findimages.h,
+ kipi-plugins/flickrexport/exifrestorer.cpp,
+ kipi-plugins/flickrexport/exifrestorer.h,
+ kipi-plugins/flickrexport/flickritem.h,
+ kipi-plugins/flickrexport/flickrtalker.cpp,
+ kipi-plugins/flickrexport/flickrtalker.h,
+ kipi-plugins/flickrexport/flickrviewitem.cpp,
+ kipi-plugins/flickrexport/flickrviewitem.h,
+ kipi-plugins/flickrexport/flickrwidget.cpp,
+ kipi-plugins/flickrexport/flickrwidget.h,
+ kipi-plugins/flickrexport/flickrwindow.cpp,
+ kipi-plugins/flickrexport/flickrwindow.h,
+ kipi-plugins/flickrexport/jpegsection.h,
+ kipi-plugins/flickrexport/login.cpp,
+ kipi-plugins/flickrexport/login.h,
+ kipi-plugins/flickrexport/mpform.cpp,
+ kipi-plugins/flickrexport/mpform.h,
+ kipi-plugins/flickrexport/plugin_flickrexport.cpp,
+ kipi-plugins/flickrexport/plugin_flickrexport.h,
+ kipi-plugins/galleryexport/galleries.cpp,
+ kipi-plugins/galleryexport/galleries.h,
+ kipi-plugins/galleryexport/galleryconfig.cpp,
+ kipi-plugins/galleryexport/galleryconfig.h,
+ kipi-plugins/galleryexport/galleryitem.h,
+ kipi-plugins/galleryexport/gallerylist.cpp,
+ kipi-plugins/galleryexport/gallerylist.h,
+ kipi-plugins/galleryexport/gallerympform.cpp,
+ kipi-plugins/galleryexport/gallerympform.h,
+ kipi-plugins/galleryexport/gallerytalker.cpp,
+ kipi-plugins/galleryexport/gallerytalker.h,
+ kipi-plugins/galleryexport/galleryviewitem.cpp,
+ kipi-plugins/galleryexport/galleryviewitem.h,
+ kipi-plugins/galleryexport/gallerywidget.cpp,
+ kipi-plugins/galleryexport/gallerywidget.h,
+ kipi-plugins/galleryexport/gallerywindow.cpp,
+ kipi-plugins/galleryexport/gallerywindow.h,
+ kipi-plugins/galleryexport/plugin_galleryexport.cpp,
+ kipi-plugins/galleryexport/plugin_galleryexport.h,
+ kipi-plugins/gpssync/getlonlat.php,
+ kipi-plugins/gpssync/gpsbabelbinary.cpp,
+ kipi-plugins/gpssync/gpsbabelbinary.h,
+ kipi-plugins/gpssync/gpsdatacontainer.h,
+ kipi-plugins/gpssync/gpsdataparser.cpp,
+ kipi-plugins/gpssync/gpsdataparser.h,
+ kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/gpsmapwidget.cpp,
+ kipi-plugins/gpssync/gpsmapwidget.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.h,
+ kipi-plugins/gpssync/plugin_gpssync.cpp,
+ kipi-plugins/gpssync/plugin_gpssync.h,
+ kipi-plugins/helloworld/plugin_helloworld.cpp,
+ kipi-plugins/helloworld/plugin_helloworld.h,
+ kipi-plugins/htmlexport/galleryinfo.h,
+ kipi-plugins/htmlexport/generator.cpp,
+ kipi-plugins/htmlexport/generator.h,
+ kipi-plugins/htmlexport/plugin.cpp,
+ kipi-plugins/htmlexport/plugin.h,
+ kipi-plugins/htmlexport/theme.cpp,
+ kipi-plugins/htmlexport/theme.h,
+ kipi-plugins/htmlexport/wizard.cpp,
+ kipi-plugins/htmlexport/wizard.h,
+ kipi-plugins/htmlexport/xmlutils.h,
+ kipi-plugins/imagesgallery/actions.h,
+ kipi-plugins/imagesgallery/exifrestorer.cpp,
+ kipi-plugins/imagesgallery/exifrestorer.h,
+ kipi-plugins/imagesgallery/imagesgallery.cpp,
+ kipi-plugins/imagesgallery/imagesgallery.h,
+ kipi-plugins/imagesgallery/imgallerydialog.cpp,
+ kipi-plugins/imagesgallery/imgallerydialog.h,
+ kipi-plugins/imagesgallery/jpegsection.h,
+ kipi-plugins/imagesgallery/plugin_imagesgallery.cpp,
+ kipi-plugins/imagesgallery/plugin_imagesgallery.h,
+ kipi-plugins/imageviewer/ogl.cpp, kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/plugin_viewer.cpp,
+ kipi-plugins/imageviewer/plugin_viewer.h,
+ kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/imageviewer/texture.h,
+ kipi-plugins/imageviewer/timer.cpp,
+ kipi-plugins/imageviewer/timer.h,
+ kipi-plugins/ipodexport/imagelist.h,
+ kipi-plugins/jpeglossless/actions.h,
+ kipi-plugins/jpeglossless/actionthread.cpp,
+ kipi-plugins/jpeglossless/actionthread.h,
+ kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/convert2grayscale.h,
+ kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imageflip.h,
+ kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/imagerotate.h,
+ kipi-plugins/jpeglossless/jpegtransform.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.h,
+ kipi-plugins/jpeglossless/mtqueue.h,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.h,
+ kipi-plugins/jpeglossless/utils.cpp,
+ kipi-plugins/jpeglossless/utils.h,
+ kipi-plugins/kameraklient/camerafolderitem.cpp,
+ kipi-plugins/kameraklient/camerafolderitem.h,
+ kipi-plugins/kameraklient/camerafolderview.cpp,
+ kipi-plugins/kameraklient/camerafolderview.h,
+ kipi-plugins/kameraklient/cameraiconitem.cpp,
+ kipi-plugins/kameraklient/cameraiconitem.h,
+ kipi-plugins/kameraklient/cameraiconview.cpp,
+ kipi-plugins/kameraklient/cameraiconview.h,
+ kipi-plugins/kameraklient/cameralist.cpp,
+ kipi-plugins/kameraklient/cameralist.h,
+ kipi-plugins/kameraklient/cameraselection.cpp,
+ kipi-plugins/kameraklient/cameraselection.h,
+ kipi-plugins/kameraklient/cameratype.cpp,
+ kipi-plugins/kameraklient/cameratype.h,
+ kipi-plugins/kameraklient/cameraui.cpp,
+ kipi-plugins/kameraklient/cameraui.h,
+ kipi-plugins/kameraklient/dmessagebox.cpp,
+ kipi-plugins/kameraklient/dmessagebox.h,
+ kipi-plugins/kameraklient/gpcamera.cpp,
+ kipi-plugins/kameraklient/gpcamera.h,
+ kipi-plugins/kameraklient/gpcommand.h,
+ kipi-plugins/kameraklient/gpcontroller.cpp,
+ kipi-plugins/kameraklient/gpcontroller.h,
+ kipi-plugins/kameraklient/gpeventfilter.cpp,
+ kipi-plugins/kameraklient/gpeventfilter.h,
+ kipi-plugins/kameraklient/gpevents.h,
+ kipi-plugins/kameraklient/gpfileitemcontainer.cpp,
+ kipi-plugins/kameraklient/gpfileitemcontainer.h,
+ kipi-plugins/kameraklient/gpfileiteminfo.cpp,
+ kipi-plugins/kameraklient/gpfileiteminfo.h,
+ kipi-plugins/kameraklient/gpfileiteminfodlg.cpp,
+ kipi-plugins/kameraklient/gpfileiteminfodlg.h,
+ kipi-plugins/kameraklient/gpiface.cpp,
+ kipi-plugins/kameraklient/gpiface.h,
+ kipi-plugins/kameraklient/gpstatus.cpp,
+ kipi-plugins/kameraklient/gpstatus.h,
+ kipi-plugins/kameraklient/kameraklient.cpp,
+ kipi-plugins/kameraklient/kameraklient.h,
+ kipi-plugins/kameraklient/mtlist.h,
+ kipi-plugins/kameraklient/mtqueue.h,
+ kipi-plugins/kameraklient/savefiledialog.cpp,
+ kipi-plugins/kameraklient/savefiledialog.h,
+ kipi-plugins/kameraklient/setupcamera.cpp,
+ kipi-plugins/kameraklient/setupcamera.h,
+ kipi-plugins/kameraklient/thumbitem.cpp,
+ kipi-plugins/kameraklient/thumbitem.h,
+ kipi-plugins/kameraklient/thumbview.cpp,
+ kipi-plugins/kameraklient/thumbview.h,
+ kipi-plugins/metadataedit/commenteditdialog.cpp,
+ kipi-plugins/metadataedit/commenteditdialog.h,
+ kipi-plugins/metadataedit/commentremovedialog.cpp,
+ kipi-plugins/metadataedit/commentremovedialog.h,
+ kipi-plugins/metadataedit/exifadjust.cpp,
+ kipi-plugins/metadataedit/exifadjust.h,
+ kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifcaption.h,
+ kipi-plugins/metadataedit/exifdatetime.cpp,
+ kipi-plugins/metadataedit/exifdatetime.h,
+ kipi-plugins/metadataedit/exifdevice.cpp,
+ kipi-plugins/metadataedit/exifdevice.h,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.h,
+ kipi-plugins/metadataedit/exiflens.cpp,
+ kipi-plugins/metadataedit/exiflens.h,
+ kipi-plugins/metadataedit/exiflight.cpp,
+ kipi-plugins/metadataedit/exiflight.h,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptccaption.h,
+ kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptccategories.h,
+ kipi-plugins/metadataedit/iptccredits.cpp,
+ kipi-plugins/metadataedit/iptccredits.h,
+ kipi-plugins/metadataedit/iptcdatetime.cpp,
+ kipi-plugins/metadataedit/iptcdatetime.h,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.h,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptckeywords.h,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcorigin.h,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcstatus.h,
+ kipi-plugins/metadataedit/iptcsubjects.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.h,
+ kipi-plugins/metadataedit/metadatacheckbox.cpp,
+ kipi-plugins/metadataedit/metadatacheckbox.h,
+ kipi-plugins/metadataedit/plugin_metadataedit.cpp,
+ kipi-plugins/metadataedit/plugin_metadataedit.h,
+ kipi-plugins/mpegencoder/checkbinprog.cpp,
+ kipi-plugins/mpegencoder/checkbinprog.h,
+ kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ kipi-plugins/mpegencoder/kimg2mpg.h,
+ kipi-plugins/mpegencoder/kshowdebuggingoutput.cpp,
+ kipi-plugins/mpegencoder/kshowdebuggingoutput.h,
+ kipi-plugins/mpegencoder/optionsdialog.cpp,
+ kipi-plugins/mpegencoder/optionsdialog.h,
+ kipi-plugins/mpegencoder/plugin_mpegencoder.cpp,
+ kipi-plugins/mpegencoder/plugin_mpegencoder.h,
+ kipi-plugins/printwizard/cropframe.cpp,
+ kipi-plugins/printwizard/plugin_printwizard.cpp,
+ kipi-plugins/printwizard/plugin_printwizard.h,
+ kipi-plugins/printwizard/tphoto.cpp,
+ kipi-plugins/rawconverter/actions.h,
+ kipi-plugins/rawconverter/actionthread.cpp,
+ kipi-plugins/rawconverter/actionthread.h,
+ kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/batchdialog.h,
+ kipi-plugins/rawconverter/clistviewitem.h,
+ kipi-plugins/rawconverter/mtqueue.h,
+ kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ kipi-plugins/rawconverter/plugin_rawconverter.h,
+ kipi-plugins/rawconverter/previewwidget.cpp,
+ kipi-plugins/rawconverter/previewwidget.h,
+ kipi-plugins/rawconverter/rawdecodingiface.cpp,
+ kipi-plugins/rawconverter/rawdecodingiface.h,
+ kipi-plugins/rawconverter/savesettingswidget.cpp,
+ kipi-plugins/rawconverter/savesettingswidget.h,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/rawconverter/singledialog.h,
+ kipi-plugins/sendimages/actions.h,
+ kipi-plugins/sendimages/listimageserrordialog.cpp,
+ kipi-plugins/sendimages/listimageserrordialog.h,
+ kipi-plugins/sendimages/plugin_sendimages.cpp,
+ kipi-plugins/sendimages/plugin_sendimages.h,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.h,
+ kipi-plugins/simpleviewerexport/firstrundlg.cpp,
+ kipi-plugins/simpleviewerexport/firstrundlg.h,
+ kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp,
+ kipi-plugins/simpleviewerexport/plugin_simpleviewer.h,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ kipi-plugins/simpleviewerexport/simpleviewerexport.h,
+ kipi-plugins/simpleviewerexport/svedialog.cpp,
+ kipi-plugins/simpleviewerexport/svedialog.h,
+ kipi-plugins/slideshow/imlibiface.cpp,
+ kipi-plugins/slideshow/imlibiface.h,
+ kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/plugin_slideshow.h,
+ kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h,
+ kipi-plugins/slideshow/slideshowgl.cpp,
+ kipi-plugins/slideshow/slideshowgl.h,
+ kipi-plugins/slideshow/toolbar.cpp,
+ kipi-plugins/slideshow/toolbar.h,
+ kipi-plugins/sync/galleryconfig.cpp,
+ kipi-plugins/sync/galleryconfig.h,
+ kipi-plugins/sync/galleryitem.h,
+ kipi-plugins/sync/galleryviewitem.cpp,
+ kipi-plugins/sync/galleryviewitem.h,
+ kipi-plugins/sync/gallerywidget.cpp,
+ kipi-plugins/sync/gallerywidget.h,
+ kipi-plugins/sync/gallerywindow.cpp,
+ kipi-plugins/sync/gallerywindow.h,
+ kipi-plugins/sync/libkipi2/collection.cpp,
+ kipi-plugins/sync/libkipi2/collection.h,
+ kipi-plugins/sync/libkipi2/interface.h,
+ kipi-plugins/sync/libkipi2/item.cpp,
+ kipi-plugins/sync/libkipi2/item.h,
+ kipi-plugins/sync/plugin_sync.cpp,
+ kipi-plugins/sync/plugin_sync.h, kipi-plugins/sync/sink.cpp,
+ kipi-plugins/sync/sink.h, kipi-plugins/sync/sinkfactory.cpp,
+ kipi-plugins/sync/sinkfactory.h, kipi-plugins/sync/sinklist.cpp,
+ kipi-plugins/sync/sinklist.h, kipi-plugins/sync/sinks.cpp,
+ kipi-plugins/sync/sinks.h,
+ kipi-plugins/sync/sinks/gallery/gallerycollection.cpp,
+ kipi-plugins/sync/sinks/gallery/gallerycollection.h,
+ kipi-plugins/sync/sinks/gallery/galleryform.cpp,
+ kipi-plugins/sync/sinks/gallery/galleryform.h,
+ kipi-plugins/sync/sinks/gallery/galleryitem.cpp,
+ kipi-plugins/sync/sinks/gallery/galleryitem.h,
+ kipi-plugins/sync/sinks/gallery/gallerysink.cpp,
+ kipi-plugins/sync/sinks/gallery/gallerysink.h,
+ kipi-plugins/timeadjust/plugin_timeadjust.cpp,
+ kipi-plugins/timeadjust/plugin_timeadjust.h,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.h,
+ kipi-plugins/wallpaper/plugin_wallpaper.cpp,
+ kipi-plugins/wallpaper/plugin_wallpaper.h:
+ BUG:144455
+ thanks a lot to Stéphane Pontier
+
+2007-04-28 13:28 gateau
+
+ * [r658763] kipi-plugins/htmlexport/generator.cpp:
+ Applied variant of the patch by Colin McMillen to rotate images
+ according to
+ angle() info.
+
+2007-04-26 10:45 fsalvi
+
+ * [r658210] kipi-plugins/gpssync/kmlexport.cpp,
+ kipi-plugins/gpssync/kmlexport.h,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.h,
+ kipi-plugins/gpssync/kmlgpsdataparser.cpp,
+ kipi-plugins/gpssync/kmlgpsdataparser.h,
+ kipi-plugins/gpssync/plugin_gpssync.cpp:
+ Apply patch from Stephane Pontier.
+ Fix i18n issues reported by Brian Remedios.
+
+ CCBUG: 139793
+ CCMAIL: shadow.walker@free.fr
+
+2007-04-25 16:50 anaselli
+
+ * [r657992] kipi-plugins/sendimages/Makefile.am,
+ kipi-plugins/sendimages/sendimages.cpp:
+ Added raw support to sendimage plugin using Gilles' patch
+ CCMAIL: michael.hoechstetter@gmx.de, caulier.gilles@gmail.com
+
+2007-04-20 13:31 cgilles
+
+ * [r656158] kipi-plugins/configure.in.bot:
+ xstl ==> xslt
+
+2007-04-18 04:17 cgilles
+
+ * [r655252] kipi-plugins/README:
+ update
+
+2007-04-18 04:14 cgilles
+
+ * [r655251] kipi-plugins/NEWS:
+ update
+
+2007-04-18 00:50 cguthrie
+
+ * [r655231] kipi-plugins/galleryexport/gallerympform.cpp,
+ kipi-plugins/galleryexport/gallerytalker.cpp:
+ Fix login to Gallery 2.2.
+
+ This was a very annoying bug to track down but it essentially
+ relates
+ to a bug in the generation of Cookies in Gallery 2.2.
+
+ Gallery actually generates 3 Set-Cookie headers in it's response
+ which
+ seems excessive. The first one is a GALLERYSID=<blank> and the
+ other
+ two set it to the correct value. The routine that parses cookies
+ is
+ somewhat dumb and just passes any cookies it receives back to the
+ server on the next request. By passing the blank GALLERYSID,
+ Gallery
+ ensured that it did not connect to your logged in session.
+
+ The cookie parsing code should be make more intellegent, but in
+ the
+ mean time I've put in a very simple fix.
+
+ Testing and feedback appreciated.
+
+ This also applies the patch by Martin Kaufmann - thanks.
+ BUG: 142259
+
+2007-04-13 11:13 scripty
+
+ * [r653450] kipi-plugins/flickrexport/exifrestorer.cpp,
+ kipi-plugins/flickrexport/exifrestorer.h,
+ kipi-plugins/flickrexport/jpegsection.h:
+ C++ files should not be executable
+ (goutte)
+
+2007-04-10 21:04 djarvie
+
+ * [r652387]
+ trunk/extragear/graphics/digikam/digikam/albumfiletip.cpp,
+ trunk/extragear/graphics/digikam/digikam/albumiconitem.cpp,
+ trunk/extragear/graphics/digikam/digikam/kdateedit.cpp,
+ trunk/extragear/graphics/digikam/libs/imageproperties/cameraitempropertiestab.cpp,
+ trunk/extragear/graphics/digikam/libs/imageproperties/imagepropertiestab.cpp,
+ trunk/extragear/graphics/digikam/libs/thumbbar/thumbbar.cpp,
+ trunk/extragear/graphics/digikam/utilities/slideshow/slideshow.cpp,
+ trunk/extragear/graphics/kgraphviewer/src/printing/simpleprintingengine.cpp,
+ trunk/extragear/graphics/kphotoalbum/DateBar/ViewHandler.cpp,
+ trunk/extragear/graphics/showimg/showimg/batchrenamer.cpp,
+ trunk/extragear/graphics/showimg/showimg/mainwindow.cpp,
+ kipi-plugins/rawconverter/actionthread.cpp,
+ trunk/extragear/multimedia/kaffeine/src/input/dvb/kevents.cpp,
+ trunk/extragear/network/kchat/kchatmainwindow.cpp,
+ trunk/extragear/network/knemo/knemod/interfacestatisticsdialog.cpp,
+ trunk/extragear/office/datakiosk/datakiosk/src/dateedit.cpp,
+ trunk/extragear/office/datakiosk/src/dateedit.cpp,
+ trunk/extragear/utils/kedit/kedit.cpp,
+ trunk/extragear/utils/krecipes/src/widgets/kdateedit.cpp:
+ Revert KLocale::formatDate(), formatDateTime() commit for KDE3
+ modules
+
+2007-04-10 19:03 djarvie
+
+ * [r652351]
+ trunk/extragear/graphics/digikam/digikam/albumfiletip.cpp,
+ trunk/extragear/graphics/digikam/digikam/albumiconitem.cpp,
+ trunk/extragear/graphics/digikam/digikam/kdateedit.cpp,
+ trunk/extragear/graphics/digikam/libs/imageproperties/cameraitempropertiestab.cpp,
+ trunk/extragear/graphics/digikam/libs/imageproperties/imagepropertiestab.cpp,
+ trunk/extragear/graphics/digikam/libs/thumbbar/thumbbar.cpp,
+ trunk/extragear/graphics/digikam/utilities/slideshow/slideshow.cpp,
+ trunk/extragear/graphics/kgraphviewer/src/printing/simpleprintingengine.cpp,
+ trunk/extragear/graphics/kphotoalbum/DateBar/ViewHandler.cpp,
+ trunk/extragear/graphics/kst/src/extdate/kstextdatepicker.cpp,
+ trunk/extragear/graphics/showimg/showimg/batchrenamer.cpp,
+ trunk/extragear/graphics/showimg/showimg/mainwindow.cpp,
+ kipi-plugins/rawconverter/actionthread.cpp,
+ trunk/extragear/multimedia/amarok/src/tagdialog.cpp,
+ trunk/extragear/multimedia/kaffeine/src/input/dvb/kevents.cpp,
+ trunk/extragear/network/kchat/kchatmainwindow.cpp,
+ trunk/extragear/network/knemo/knemod/interfacestatisticsdialog.cpp,
+ trunk/extragear/office/datakiosk/datakiosk/src/dateedit.cpp,
+ trunk/extragear/office/datakiosk/src/dateedit.cpp,
+ trunk/extragear/office/kile/kile/quickdocumentdialog.cpp,
+ trunk/extragear/utils/kedit/kedit.cpp,
+ trunk/extragear/utils/krecipes/src/widgets/kdateedit.cpp:
+ Add fancy date option to KLocale::formatDate(),
+ KLocale::formatDateTime()
+
+2007-04-09 17:58 anaselli
+
+ * [r651952] kipi-plugins/README:
+ Added missed requirements to run images2mpg (mpegencoder plugin)
+
+ CCBUG:143979
+
+2007-04-08 20:14 kusi
+
+ * [r651660] kipi-plugins/imageviewer/Makefile.am,
+ kipi-plugins/imageviewer/help.ui,
+ kipi-plugins/imageviewer/ogl.cpp:
+ display a help dialog if an unsupported key was pressed
+
+2007-04-07 15:42 cgilles
+
+ * [r651404] kipi-plugins/NEWS:
+ update
+
+2007-04-07 15:41 cgilles
+
+ * [r651403] kipi-plugins/NEWS:
+ update
+
+2007-04-07 15:39 cgilles
+
+ * [r651402] kipi-plugins/gpssync/Makefile.am,
+ kipi-plugins/gpssync/gpsdataparser.h,
+ kipi-plugins/gpssync/kmlexport.cpp,
+ kipi-plugins/gpssync/kmlexport.h,
+ kipi-plugins/gpssync/kmlexportconfig.cpp,
+ kipi-plugins/gpssync/kmlexportconfig.h,
+ kipi-plugins/gpssync/kmlgpsdataparser.cpp,
+ kipi-plugins/gpssync/kmlgpsdataparser.h,
+ kipi-plugins/gpssync/plugin_gpssync.cpp,
+ kipi-plugins/gpssync/plugin_gpssync.h:
+ kipi-plugins from trunk : GPSSync : patch from Stéphane Pontier
+ to add new option for export GPS position from pictures to a KML
+ file. This one can be viewed in GoogleEarth or GoogleMaps !
+
+ BUG: 139793
+ CCMAIL: shadow.walker@free.fr
+ CCMAIL: kde-imaging@kde.org
+
+2007-04-01 20:38 anaselli
+
+ * [r648990] kipi-plugins/mpegencoder/kimg2mpg.cpp:
+ Added a test to avoid files not reachable are passed to img2mpg
+ script as reported by a Mandriva user:
+ "open gwenview from konqueror when it is using the protocol
+ system:/ so the path is something like
+ /media/hdxx/user_home/file.jpg
+ instead of /home/user_home/file.jpg"
+
+ CCMAIL:kde-imaging@kde.org
+
+2007-03-30 08:34 cgilles
+
+ * [r648022] kipi-plugins/NEWS:
+ update
+
+2007-03-30 08:12 gkulzer
+
+ * [r648020] kipi-plugins/gpssync/gpsdataparser.cpp:
+ correcting interpolation
+ CCMAIL:caulier.gilles@gmail.com, shadow.walker@free.fr
+ BUG:143594
+
+2007-03-29 20:46 anaselli
+
+ * [r647905] kipi-plugins/printwizard/frmprintwizard.cpp:
+ Added 8 photos per page (A4) option
+
+ CCMAIL:cannewilson@googlemail.com
+
+2007-03-24 17:24 lure
+
+ * [r646131] kipi-plugins/jpeglossless/plugin_jpeglossless.cpp:
+ Use Ctrl-Shift-arrow as shortcut for Rotate-Left/Right
+
+ Ctrl-arrow is used in some other applications and may confuse
+ users.
+
+ CCBUG: 141530
+
+2007-03-18 13:17 cguthrie
+
+ * [r643808] kipi-plugins/sync/libkipi2/collection.cpp,
+ kipi-plugins/sync/libkipi2/interface.cpp,
+ kipi-plugins/sync/libkipi2/interface.h,
+ kipi-plugins/sync/sink.cpp, kipi-plugins/sync/sink.h,
+ kipi-plugins/sync/sinkfactory.cpp,
+ kipi-plugins/sync/sinkfactory.h, kipi-plugins/sync/sinks.cpp,
+ kipi-plugins/sync/sinks.h,
+ kipi-plugins/sync/sinks/gallery/gallerysink.cpp,
+ kipi-plugins/sync/sinks/gallery/gallerysink.h:
+ Some more moves towards this plugin. Slow going as not got much
+ time to concentrate on it.
+
+2007-03-17 16:24 kusi
+
+ * [r643495] kipi-plugins/imageviewer/ogl.cpp:
+ don't zoom if zoomdelta=0. This fixes corruption if you try to
+ zoom with a horizontal mouse move (+right button)
+
+2007-03-14 12:13 cgilles
+
+ * [r642433] kipi-plugins/NEWS:
+ update
+
+2007-03-13 16:49 mueller
+
+ * [r642206] kipi-plugins/flickrexport/flickrtalker.cpp:
+ compile++
+
+2007-03-12 08:47 cgilles
+
+ * [r641671] kipi-plugins/NEWS:
+ update
+
+2007-03-12 08:47 cgilles
+
+ * [r641670] kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.h:
+ kipi-plugins from trunk : GPS Sync dialog : add missing GMT+13
+ and GMT+14 time zone
+ BUG: 142848
+
+2007-03-09 23:40 kusi
+
+ * [r641087] kipi-plugins/imageviewer/ogl.cpp,
+ kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/plugin_viewer.cpp:
+ proper error handling in case no OpenGL context is found or
+ GL_ARB_texture_rectangle is not supported
+
+2007-03-06 09:22 lure
+
+ * [r639921] kipi-plugins/NEWS,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.cpp:
+ JPEGLossLess: Use Rotate Left/Right actions instead of rotate
+ by degree (90/180/270). This is more intuitive and easier for
+ user.
+ Use Ctrl-Left and Ctrl-Right as keyboard shortcuts.
+
+ BUG: 141530
+
+2007-03-06 08:38 cgilles
+
+ * [r639912] kipi-plugins/NEWS:
+ update
+
+2007-03-03 14:05 kusi
+
+ * [r638833] kipi-plugins/imageviewer/texture.cpp:
+ fixing "zoom to original size"
+
+2007-03-03 12:41 kusi
+
+ * [r638817] kipi-plugins/imageviewer/ogl.cpp:
+ ctrl + scrollwheel does zooming now
+
+2007-03-03 11:56 kusi
+
+ * [r638798] kipi-plugins/imageviewer/README,
+ kipi-plugins/imageviewer/ogl.h:
+ updated README
+
+2007-03-03 03:38 gkulzer
+
+ * [r638734] kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ kipi-plugins/jpeglossless/plugin_jpeglossless.h:
+ If no error occurs, run dialog will be automatically closed.
+ BUG:141528
+ CCMAIL:caulier.gilles@gmail.com
+
+2007-02-24 13:18 gkulzer
+
+ * [r636853] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ clean out formatting from i18n
+
+2007-02-24 09:50 gkulzer
+
+ * [r636811] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ missing blanc in i18n
+
+2007-02-24 09:47 gkulzer
+
+ * [r636810] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ improve i18n strings for better understanding
+ CCMAIL:caulier.gilles@gmail.com
+
+2007-02-24 09:17 gkulzer
+
+ * [r636808] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ correct and improve i18n strings (distance time -> time distance,
+ gap time -> time gap)
+ CCMAIL:caulier.gilles@gmail.com
+
+2007-02-24 08:25 gkulzer
+
+ * [r636799] kipi-plugins/gpssync/gpssyncdialog.cpp:
+ correct and improve i18n strings
+
+2007-02-23 11:49 cgilles
+
+ * [r636507] kipi-plugins/rawconverter/actionthread.cpp,
+ kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/savesettingswidget.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp:
+ fix i18n
+
+2007-02-23 11:47 cgilles
+
+ * [r636506] kipi-plugins/rawconverter/singledialog.cpp:
+ using PPM to faster preview
+
+2007-02-23 11:44 cgilles
+
+ * [r636505] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/batchdialog.h,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/rawconverter/singledialog.h:
+ disable settings if busy
+
+2007-02-23 06:56 cgilles
+
+ * [r636447] kipi-plugins/rawconverter/actionthread.cpp:
+ polish
+
+2007-02-22 14:59 cgilles
+
+ * [r636239] kipi-plugins/rawconverter/previewwidget.cpp:
+ refresh preview properlly if dialog is resized
+
+2007-02-22 12:01 cgilles
+
+ * [r636211] kipi-plugins/kipiplugins.kdevelop,
+ kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ libkdcraw/dcraw/dcraw.c, libkdcraw/dcraw/kdcraw.1,
+ libkdcraw/dcrawbinary.cpp, libkdcraw/dcrawsettingswidget.cpp,
+ libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp,
+ libkdcraw/libkdcraw.kdevelop, libkdcraw/rawdecodingsettings.h,
+ libkexiv2/libkexiv2.kdevelop:
+ libkdcraw from trunk : backport last dcraw implementation "8.60"
+ : the old noise reduction algorithm used with 8.54 version have
+ been remplaced by a wavelet algorithm witch is more intuitive,
+ more easy to use (just one threshold setting) and very powerfull.
+
+ Kipi-plugins RAWConverter from svn trunk is fixed.
+ The patch to use libkdcraw with current implementation of digiKam
+ have been updated :
+
+ http://digikam3rdparty.free.fr/misc.tarballs/libkdcrawdigikamport.patch
+
+ CCMAIL: digikam-users@kde.org
+ CCMAIL: digikam-devel@kde.org
+ CCMAIL: kde-imaging@kde.org
+
+2007-02-20 19:41 cgilles
+
+ * [r635741] kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ kipi-plugins/acquireimages/kipiplugin_acquireimages.desktop,
+ kipi-plugins/acquireimages/plugin_acquireimages.cpp,
+ kipi-plugins/acquireimages/screenshotdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesdialog.h,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimagesitem.h,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.cpp,
+ kipi-plugins/batchprocessimages/batchprocessimageslist.h,
+ kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/borderimagesdialog.h,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/borderoptionsdialog.h,
+ kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/colorimagesdialog.h,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/coloroptionsdialog.h,
+ kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/convertimagesdialog.h,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/convertoptionsdialog.h,
+ kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/effectimagesdialog.h,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/effectoptionsdialog.h,
+ kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/filterimagesdialog.h,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/filteroptionsdialog.h,
+ kipi-plugins/batchprocessimages/imagepreview.cpp,
+ kipi-plugins/batchprocessimages/imagepreview.h,
+ kipi-plugins/batchprocessimages/kipiplugin_batchprocessimages.desktop,
+ kipi-plugins/batchprocessimages/outputdialog.cpp,
+ kipi-plugins/batchprocessimages/outputdialog.h,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp,
+ kipi-plugins/batchprocessimages/plugin_batchprocessimages.h,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressimagesdialog.h,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/recompressoptionsdialog.h,
+ kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/renameimagesdialog.h,
+ kipi-plugins/batchprocessimages/renameimageswidget.cpp,
+ kipi-plugins/batchprocessimages/renameimageswidget.h,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeimagesdialog.h,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp,
+ kipi-plugins/batchprocessimages/resizeoptionsdialog.h,
+ kipi-plugins/cdarchiving/actions.h,
+ kipi-plugins/cdarchiving/cdarchiving.cpp,
+ kipi-plugins/cdarchiving/cdarchiving.h,
+ kipi-plugins/cdarchiving/cdarchivingdialog.cpp,
+ kipi-plugins/cdarchiving/cdarchivingdialog.h,
+ kipi-plugins/cdarchiving/kipiplugin_cdarchiving.desktop,
+ kipi-plugins/cdarchiving/plugin_cdarchiving.cpp,
+ kipi-plugins/cdarchiving/plugin_cdarchiving.h,
+ kipi-plugins/findimages/actions.h,
+ kipi-plugins/findimages/displaycompare.cpp,
+ kipi-plugins/findimages/displaycompare.h,
+ kipi-plugins/findimages/fastcompare.cpp,
+ kipi-plugins/findimages/fastcompare.h,
+ kipi-plugins/findimages/finddupplicatedialog.cpp,
+ kipi-plugins/findimages/finddupplicatedialog.h,
+ kipi-plugins/findimages/finddupplicateimages.cpp,
+ kipi-plugins/findimages/finddupplicateimages.h,
+ kipi-plugins/findimages/fuzzycompare.cpp,
+ kipi-plugins/findimages/fuzzycompare.h,
+ kipi-plugins/findimages/imagesimilaritydata.h,
+ kipi-plugins/findimages/kipiplugin_findimages.desktop,
+ kipi-plugins/findimages/plugin_findimages.cpp,
+ kipi-plugins/findimages/plugin_findimages.h,
+ kipi-plugins/ipodexport/imagelist.h,
+ kipi-plugins/jpeglossless/mtqueue.h,
+ kipi-plugins/mpegencoder/checkbinprog.cpp,
+ kipi-plugins/mpegencoder/checkbinprog.h,
+ kipi-plugins/mpegencoder/images2mpg,
+ kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ kipi-plugins/mpegencoder/kimg2mpg.h,
+ kipi-plugins/mpegencoder/kipiplugin_mpegencoder.desktop,
+ kipi-plugins/mpegencoder/kshowdebuggingoutput.cpp,
+ kipi-plugins/mpegencoder/kshowdebuggingoutput.h,
+ kipi-plugins/mpegencoder/optionsdialog.cpp,
+ kipi-plugins/mpegencoder/optionsdialog.h,
+ kipi-plugins/mpegencoder/plugin_mpegencoder.cpp,
+ kipi-plugins/mpegencoder/plugin_mpegencoder.h,
+ kipi-plugins/rawconverter/mtqueue.h,
+ kipi-plugins/sendimages/actions.h,
+ kipi-plugins/sendimages/kipiplugin_sendimages.desktop,
+ kipi-plugins/sendimages/listimageserrordialog.cpp,
+ kipi-plugins/sendimages/listimageserrordialog.h,
+ kipi-plugins/sendimages/plugin_sendimages.cpp,
+ kipi-plugins/sendimages/plugin_sendimages.h,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h,
+ kipi-plugins/sendimages/sendimagesdialog.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.h,
+ kipi-plugins/wallpaper/plugin_wallpaper.cpp,
+ kipi-plugins/wallpaper/plugin_wallpaper.h,
+ libkipi/libkipi/batchprogressdialog.cpp,
+ libkipi/libkipi/batchprogressdialog.h, libkipi/libkipi/version.h:
+ fix email
+
+2007-02-20 14:20 cgilles
+
+ * [r635648] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ libkdcraw/dcrawsettingswidget.cpp,
+ libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp,
+ libkdcraw/rawdecodingsettings.h:
+ libkdcraw from trunk : introduce the color balance multipliers
+ settings
+
+2007-02-20 10:38 cgilles
+
+ * [r635569] kipi-plugins/imageviewer/Makefile.am,
+ kipi-plugins/imageviewer/hi16-action-ogl.png,
+ kipi-plugins/imageviewer/hi16-app-ogl.png,
+ kipi-plugins/imageviewer/hi32-action-ogl.png,
+ kipi-plugins/imageviewer/hi32-app-ogl.png,
+ kipi-plugins/imageviewer/plugin_viewer.cpp:
+ fix plugin icons : they are action like not app. Install it
+ properlly.
+
+2007-02-20 10:32 cgilles
+
+ * [r635566] kipi-plugins/imageviewer/kipiplugin_viewer.desktop:
+ missing Comment (used by libkipi setup widget)
+
+2007-02-20 10:26 vfuoglio
+
+ * [r635564] kipi-plugins/slideshow/Makefile.am,
+ kipi-plugins/slideshow/imlibiface.cpp:
+ Added libkdcraw support.
+ Thanks to Gilles for the patch.
+
+ CCMAIL: kde-imaging@kde.org
+ CCMAIL: caulier.gilles@gmail.com
+
+2007-02-20 09:49 cgilles
+
+ * [r635552] kipi-plugins/rawconverter/previewwidget.cpp,
+ kipi-plugins/rawconverter/previewwidget.h,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/rawconverter/singledialog.h:
+ kipi-plugins from trunk : RAWConverter : draw raw preview image
+ under photo info in single dialog
+
+2007-02-20 08:47 cgilles
+
+ * [r635528] kipi-plugins/rawconverter/previewwidget.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp:
+ kipi-plugins from trunk : RAWConverter : remove temp file after
+ raw conversion at the wrong place
+
+2007-02-20 08:40 cgilles
+
+ * [r635524] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/previewwidget.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp:
+ kipi-plugins from trunk : RAWConverter : bugfix: missing to
+ remove temp file after raw conversion
+
+2007-02-20 08:23 cgilles
+
+ * [r635520] kipi-plugins/rawconverter/actions.h,
+ kipi-plugins/rawconverter/actionthread.cpp,
+ kipi-plugins/rawconverter/actionthread.h,
+ kipi-plugins/rawconverter/singledialog.cpp:
+ kipi-plugins from trunk : RAWConverter : capability to show more
+ photo infos in single dailog
+
+2007-02-19 22:44 kusi
+
+ * [r635415] kipi-plugins/imageviewer/Makefile.am,
+ kipi-plugins/imageviewer/ogl.cpp,
+ kipi-plugins/imageviewer/texture.cpp:
+ applying slightly modified patch from Gilles
+ - fix Makefile.am
+ - initial RAW support: please note that not the entire RAW image
+ is loaded but only a preview -> fast image loading but crappy
+ zooming
+
+2007-02-19 22:15 cgilles
+
+ * [r635401] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp:
+ compile
+
+2007-02-19 15:05 cgilles
+
+ * [r635242] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ libkdcraw/dcrawsettingswidget.cpp,
+ libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp,
+ libkdcraw/rawdecodingsettings.h:
+ libkdcraw from trunk : introduce the blackpoint compensation
+ value settings
+
+2007-02-19 13:22 cgilles
+
+ * [r635218] kipi-plugins/README:
+ fix
+
+2007-02-19 13:19 cgilles
+
+ * [r635217] kipi-plugins/README:
+ update
+
+2007-02-19 13:11 cgilles
+
+ * [r635214] kipi-plugins/AUTHORS:
+ update
+
+2007-02-19 13:09 cgilles
+
+ * [r635213] kipi-plugins/rawconverter/actions.h,
+ kipi-plugins/rawconverter/actionthread.cpp,
+ kipi-plugins/rawconverter/actionthread.h,
+ kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/batchdialog.h,
+ kipi-plugins/rawconverter/clistviewitem.h,
+ kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ kipi-plugins/rawconverter/plugin_rawconverter.h,
+ kipi-plugins/rawconverter/previewwidget.cpp,
+ kipi-plugins/rawconverter/previewwidget.h,
+ kipi-plugins/rawconverter/rawdecodingiface.cpp,
+ kipi-plugins/rawconverter/rawdecodingiface.h,
+ kipi-plugins/rawconverter/savesettingswidget.cpp,
+ kipi-plugins/rawconverter/savesettingswidget.h,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/rawconverter/singledialog.h:
+ optimize layout. fix email
+
+2007-02-19 12:26 nikolaus
+
+ * [r635200] kipi-plugins/imageviewer/Makefile.am:
+ Build. It's $(LIB_KPARTS), not $(LIB KPARTS).
+
+2007-02-19 12:01 cgilles
+
+ * [r635196] kipi-plugins/NEWS:
+ update
+
+2007-02-19 11:56 cgilles
+
+ * [r635195] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ libkdcraw/dcraw/README, libkdcraw/dcraw/dcraw.c,
+ libkdcraw/dcrawbinary.cpp, libkdcraw/dcrawbinary.h,
+ libkdcraw/dcrawinfocontainer.h,
+ libkdcraw/dcrawsettingswidget.cpp,
+ libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp,
+ libkdcraw/rawdecodingsettings.h:
+ After 8 days of intensive work, I'm very proud to announce the
+ first LibKdcraw shared library 0.1.0 beta release.
+
+ LibKdcraw is a C++ interface around dcraw binary program used to
+ decode RAW picture files. This library is actually used by
+ kipi-plugins (trunk), and later by digiKam (with future 0.9.2
+ release).
+
+ http://digikam3rdparty.free.fr/Screenshots/newkipirawconverter.png
+
+ The library documentation is available on header files. Check svn
+ trunk repository for details :
+
+ http://websvn.kde.org/trunk/extragear/libs/libkdcraw
+
+ Libkdcraw include the last dcraw program (version 8.54) from Dave
+ Coffin. It provide a kdcraw binary witch is used instead dcraw.
+ This way prevent _all_ compatibility problems with all options
+ see with dcraw. In fact the dcraw author to not respect a
+ compatibilty between dcraw release witch break all RAW workflow !
+ Also, he won't provide dcraw as a shared library. We have lost a
+ waste a time with these problems in digiKam project. Using a
+ specific version of dcraw in the library, we will valid this one
+ with the library API and preserve the compatibility for the
+ future.
+
+ The dcraw source code can be updated easily using the
+ libkdcraw/dcraw/README file where i have written a notice for
+ that. The library don't touch the content of dcraw source code.
+ It use it as well...
+
+ With this library, you can extract preview image (used by camera
+ to display picture on TV screen) as a QImage, and extract all
+ informations given by dcraw to identify a RAW file. Of course,
+ you can decode and extract the RAW pictures with a lot of
+ settings. The image data (8 or 16 bits color depth) is returned
+ in a QByteArray container. The library include a widget to
+ control all RAW decoding settings in your application :
+
+ http://digikam3rdparty.free.fr/Screenshots/rawsettings.png
+
+ Using the last dcraw source code, the libary support all last
+ Camera models, especially all models out at Christmas 2006. The
+ complete list is given below :
+
+ Adobe Digital Negative (DNG)
+ AVT F-145C
+ AVT F-201C
+ AVT F-510C
+ AVT F-810C
+ Canon PowerShot 600
+ Canon PowerShot A5
+ Canon PowerShot A5 Zoom
+ Canon PowerShot A50
+ Canon PowerShot A610
+ Canon PowerShot A620
+ Canon PowerShot Pro70
+ Canon PowerShot Pro90 IS
+ Canon PowerShot G1
+ Canon PowerShot G2
+ Canon PowerShot G3
+ Canon PowerShot G5
+ Canon PowerShot G6
+ Canon PowerShot S2 IS
+ Canon PowerShot S3 IS
+ Canon PowerShot S30
+ Canon PowerShot S40
+ Canon PowerShot S45
+ Canon PowerShot S50
+ Canon PowerShot S60
+ Canon PowerShot S70
+ Canon PowerShot Pro1
+ Canon EOS D30
+ Canon EOS D60
+ Canon EOS 5D
+ Canon EOS 10D
+ Canon EOS 20D
+ Canon EOS 30D
+ Canon EOS 300D / Digital Rebel / Kiss Digital
+ Canon EOS 350D / Digital Rebel XT / Kiss Digital N
+ Canon EOS 400D / Digital Rebel XTi / Kiss Digital X
+ Canon EOS D2000C
+ Canon EOS-1D
+ Canon EOS-1DS
+ Canon EOS-1D Mark II
+ Canon EOS-1D Mark II N
+ Canon EOS-1Ds Mark II
+ Casio QV-2000UX
+ Casio QV-3000EX
+ Casio QV-3500EX
+ Casio QV-4000
+ Casio QV-5700
+ Casio QV-R51
+ Casio QV-R61
+ Casio EX-S100
+ Casio EX-Z4
+ Casio EX-Z50
+ Casio EX-Z55
+ Casio Exlim Pro 505
+ Casio Exlim Pro 600
+ Casio Exlim Pro 700
+ Contax N Digital
+ Creative PC-CAM 600
+ Epson R-D1
+ Foculus 531C
+ Fuji FinePix E550
+ Fuji FinePix E900
+ Fuji FinePix F700
+ Fuji FinePix F710
+ Fuji FinePix F800
+ Fuji FinePix F810
+ Fuji FinePix S2Pro
+ Fuji FinePix S3Pro
+ Fuji FinePix S20Pro
+ Fuji FinePix S5000
+ Fuji FinePix S5100/S5500
+ Fuji FinePix S5200/S5600
+ Fuji FinePix S6000fd
+ Fuji FinePix S7000
+ Fuji FinePix S9000/S9500
+ Imacon Ixpress 16-megapixel
+ Imacon Ixpress 22-megapixel
+ Imacon Ixpress 39-megapixel
+ ISG 2020x1520
+ Kodak DC20 (see Oliver Hartman's page)
+ Kodak DC25 (see Jun-ichiro Itoh's page)
+ Kodak DC40
+ Kodak DC50
+ Kodak DC120 (also try kdc2tiff)
+ Kodak DCS200
+ Kodak DCS315C
+ Kodak DCS330C
+ Kodak DCS420
+ Kodak DCS460
+ Kodak DCS460A
+ Kodak DCS520C
+ Kodak DCS560C
+ Kodak DCS620C
+ Kodak DCS620X
+ Kodak DCS660C
+ Kodak DCS660M
+ Kodak DCS720X
+ Kodak DCS760C
+ Kodak DCS760M
+ Kodak EOSDCS1
+ Kodak EOSDCS3B
+ Kodak NC2000F
+ Kodak ProBack
+ Kodak PB645C
+ Kodak PB645H
+ Kodak PB645M
+ Kodak DCS Pro 14n
+ Kodak DCS Pro 14nx
+ Kodak DCS Pro SLR/c
+ Kodak DCS Pro SLR/n
+ Kodak P850
+ Kodak P880
+ Kodak KAI-0340
+ Konica KD-400Z
+ Konica KD-510Z
+ Leaf Aptus 17
+ Leaf Aptus 22
+ Leaf Aptus 65
+ Leaf Aptus 75
+ Leaf Cantare
+ Leaf CatchLight
+ Leaf CMost
+ Leaf DCB2
+ Leaf Valeo 6
+ Leaf Valeo 11
+ Leaf Valeo 17
+ Leaf Valeo 22
+ Leaf Volare
+ Leica Digilux 2
+ Leica Digilux 3
+ Leica D-LUX2
+ Leica D-LUX3
+ Leica V-LUX1
+ Logitech Fotoman Pixtura
+ Micron 2010
+ Minolta RD175
+ Minolta DiMAGE 5
+ Minolta DiMAGE 7
+ Minolta DiMAGE 7i
+ Minolta DiMAGE 7Hi
+ Minolta DiMAGE A1
+ Minolta DiMAGE A2
+ Minolta DiMAGE A200
+ Minolta DiMAGE G400
+ Minolta DiMAGE G500
+ Minolta DiMAGE G530
+ Minolta DiMAGE G600
+ Minolta DiMAGE Z2
+ Minolta Alpha/Dynax/Maxxum 5D
+ Minolta Alpha/Dynax/Maxxum 7D
+ Nikon D1
+ Nikon D1H
+ Nikon D1X
+ Nikon D2H
+ Nikon D2Hs
+ Nikon D2X
+ Nikon D40
+ Nikon D50
+ Nikon D70
+ Nikon D70s
+ Nikon D80
+ Nikon D100
+ Nikon D200
+ Nikon E700 ("DIAG RAW" hack)
+ Nikon E800 ("DIAG RAW" hack)
+ Nikon E880 ("DIAG RAW" hack)
+ Nikon E900 ("DIAG RAW" hack)
+ Nikon E950 ("DIAG RAW" hack)
+ Nikon E990 ("DIAG RAW" hack)
+ Nikon E995 ("DIAG RAW" hack)
+ Nikon E2100 ("DIAG RAW" hack)
+ Nikon E2500 ("DIAG RAW" hack)
+ Nikon E3200 ("DIAG RAW" hack)
+ Nikon E3700 ("DIAG RAW" hack)
+ Nikon E4300 ("DIAG RAW" hack)
+ Nikon E4500 ("DIAG RAW" hack)
+ Nikon E5000
+ Nikon E5400
+ Nikon E5700
+ Nikon E8400
+ Nikon E8700
+ Nikon E8800
+ Olympus C3030Z
+ Olympus C5050Z
+ Olympus C5060WZ
+ Olympus C7070WZ
+ Olympus C70Z,C7000Z
+ Olympus C740UZ
+ Olympus C770UZ
+ Olympus C8080WZ
+ Olympus E-1
+ Olympus E-10
+ Olympus E-20
+ Olympus E-300
+ Olympus E-330
+ Olympus E-400
+ Olympus E-500
+ Olympus SP310
+ Olympus SP320
+ Olympus SP350
+ Olympus SP500UZ
+ Panasonic DMC-FZ30
+ Panasonic DMC-FZ50
+ Panasonic DMC-L1
+ Panasonic DMC-LC1
+ Panasonic DMC-LX1
+ Panasonic DMC-LX2
+ Pentax *ist D
+ Pentax *ist DL
+ Pentax *ist DL2
+ Pentax *ist DS
+ Pentax *ist DS2
+ Pentax K10D
+ Pentax K100D
+ Pentax Optio S
+ Pentax Optio S4
+ Pentax Optio 33WR
+ Phase One LightPhase
+ Phase One H 10
+ Phase One H 20
+ Phase One H 25
+ Phase One P 20
+ Phase One P 25
+ Phase One P 30
+ Phase One P 45
+ Pixelink A782
+ Polaroid x530
+ Rollei d530flex
+ RoverShot 3320af
+ Samsung GX-1S
+ Sarnoff 4096x5440
+ Sigma SD9
+ Sigma SD10
+ Sinar 3072x2048
+ Sinar 4080x4080
+ Sinar 4080x5440
+ Sinar STI format
+ SMaL Ultra-Pocket 3
+ SMaL Ultra-Pocket 4
+ SMaL Ultra-Pocket 5
+ Sony DSC-F828
+ Sony DSC-R1
+ Sony DSC-V3
+ Sony DSLR-A100
+ Sony XCD-SX910CR
+ STV680 VGA
+
+ About digiKam and this library, I have a big patch on my computer
+ to use this library with all RAW files. I will commit this code
+ in svn repository later digiKam 0.9.1 release. It will be
+ available for 0.9.2 release. If you is impatient to test it, the
+ patch against current svn implementation of digiKam can be
+ downloaded at this url :
+
+ http://digikam3rdparty.free.fr/misc.tarballs/libkdcrawdigikamport.patch
+
+ Of course, you need to checkout, compile and install LibKdcraw
+ first. It is stored on extragear/libs folder of svn trunk.
+
+ All feedbacks are welcome, especially all RAW pictures sample
+ taken with a recent camera to perform advanced test. Thanks in
+ advance for your help...
+
+ Gilles Caulier
+ digiKam team
+
+ BUG: 140865
+ CCBUG : 138744
+ CCMAIL: digikam-users@kde.org, digikam-devel@kde.org,
+ kde-imaging@kde.org
+
+2007-02-18 16:27 cgilles
+
+ * [r634859] kipi-plugins/rawconverter/rawdecodingiface.cpp,
+ kipi-plugins/rawconverter/rawdecodingiface.h:
+ compile with last libkdcraw
+
+2007-02-18 15:53 anaselli
+
+ * [r634852] kipi-plugins/imageviewer/Makefile.am:
+ fixed libkipi dependency when compiling under svn tree
+
+2007-02-17 20:56 cgilles
+
+ * [r634617] kipi-plugins/rawconverter/rawdecodingiface.cpp:
+ compile
+
+2007-02-17 17:21 cgilles
+
+ * [r634582] kipi-plugins/rawconverter/plugin_rawconverter.cpp:
+ compile
+
+2007-02-16 22:01 cgilles
+
+ * [r634334] kipi-plugins/rawconverter/actionthread.cpp,
+ kipi-plugins/rawconverter/rawdecodingiface.cpp,
+ libkdcraw/kdcraw.cpp, libkexiv2/kexiv2.cpp:
+ fix comments
+
+2007-02-16 13:38 cgilles
+
+ * [r634151] kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/batchdialog.h,
+ kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ kipi-plugins/rawconverter/plugin_rawconverter.h,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/rawconverter/singledialog.h:
+ update
+
+2007-02-16 12:30 cgilles
+
+ * [r634130] kipi-plugins/rawconverter/dcrawsettingswidget.cpp,
+ kipi-plugins/rawconverter/dcrawsettingswidget.h:
+ obsolete files
+
+2007-02-16 12:29 cgilles
+
+ * [r634129] kipi-plugins/common/include/rawfiles.h,
+ kipi-plugins/imageviewer/ogl.cpp,
+ kipi-plugins/jpeglossless/utils.cpp:
+ Kipi-Plugins from trunk : using RAW files extensions string given
+ by libkdcraw
+
+2007-02-16 12:25 cgilles
+
+ * [r634123] kipi-plugins/common/include/pluginsversion.h:
+ update
+
+2007-02-16 12:24 cgilles
+
+ * [r634121] kipi-plugins/NEWS:
+ update
+
+2007-02-16 12:21 cgilles
+
+ * [r634120] Makefile.am.in, kipi-plugins/README,
+ kipi-plugins/configure.in.bot, kipi-plugins/configure.in.in,
+ kipi-plugins/rawconverter/Makefile.am,
+ kipi-plugins/rawconverter/actions.h,
+ kipi-plugins/rawconverter/actionthread.cpp,
+ kipi-plugins/rawconverter/actionthread.h,
+ kipi-plugins/rawconverter/batchdialog.cpp,
+ kipi-plugins/rawconverter/batchdialog.h,
+ kipi-plugins/rawconverter/clistviewitem.h,
+ kipi-plugins/rawconverter/dcraw.c,
+ kipi-plugins/rawconverter/dcrawbinary.cpp,
+ kipi-plugins/rawconverter/dcrawbinary.h,
+ kipi-plugins/rawconverter/dcrawiface.cpp,
+ kipi-plugins/rawconverter/dcrawiface.h,
+ kipi-plugins/rawconverter/mtqueue.h,
+ kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ kipi-plugins/rawconverter/plugin_rawconverter.h,
+ kipi-plugins/rawconverter/rawdecodingiface.cpp,
+ kipi-plugins/rawconverter/rawdecodingiface.h,
+ kipi-plugins/rawconverter/rawdecodingsettings.h,
+ kipi-plugins/rawconverter/savesettingswidget.cpp,
+ kipi-plugins/rawconverter/savesettingswidget.h,
+ kipi-plugins/rawconverter/singledialog.cpp,
+ kipi-plugins/rawconverter/singledialog.h:
+ Kipi-Plugins from trunk : RAW Pictures Converter : using the new
+ libkdcraw shared library to decode RAW images.
+
+ The new libkdcraw library implementation is now ready to use on
+ extragear/libs. I have work hard to merge digiKam dcraw interface
+ and the old RAW Converter dcraw interface. Now a common
+ implementation is available and this kipi-plugins is the first
+ one to use it. Next stage is to port digiKam core, but i will do
+ it later 0.9.1-final release.
+
+ To Kipi-Plugins developpers : The API is documented into all
+ header files. It's simple to use. You can extract RAW preview
+ pictures for example to send it by mail, Export an HTML page,
+ Slide pictures to screen, etc. The Preview image extraction is
+ very fast and a QImage instance is returned. You can take a look
+ into RAW Converter code to see how i use this library. If you
+ want more informations, lets me hear on kde-imaging@kde.org
+ mailing list.
+
+ Marcel, i will port digiKam core on my computer using current
+ implementation from trunk. I will send you a patch to test at
+ soon...
+
+ To digiKam users : the dcraw version in libkdcraw still the 8.41.
+ I will update it later when digiKam core will be ported to
+ libkdcraw. In fact it will be more easy to do because just one
+ common implementation need to be fixed in likdcraw (instead RAW
+ converter and digiKam core).
+
+ To packagers : this shared library must be packaged later digiKam
+ 0.9.1-final, not now. All the API are not yet finalized. I will
+ need to polish it when i will port digiKam core. This one require
+ more options, especially to decode 16 bits RAW images.
+
+ CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org,
+ marcel.wiesweg@gmx.de
+
+2007-02-16 08:26 cgilles
+
+ * [r634062] kipi-plugins/rawconverter/Makefile.am:
+ polish
+
+2007-02-16 08:08 cgilles
+
+ * [r634061] kipi-plugins/rawconverter/Makefile.am:
+ polish
+
+2007-02-13 22:34 kusi
+
+ * [r633375] kipi-plugins/imageviewer/cursors/nullImage.png:
+ nullImage which is displayed in case QImage couldn't load the
+ image
+
+2007-02-13 22:29 kusi
+
+ * [r633373] kipi-plugins/imageviewer/cursors/Makefile.am,
+ kipi-plugins/imageviewer/ogl.cpp, kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/texture.cpp:
+ drop support for RAW files
+ do not crash in case QImage can't load the file
+
+2007-02-13 21:03 kusi
+
+ * [r633341] kipi-plugins/imageviewer/ogl.cpp,
+ kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/plugin_viewer.cpp,
+ kipi-plugins/imageviewer/plugin_viewer.h,
+ kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/imageviewer/texture.h,
+ kipi-plugins/imageviewer/timer.cpp,
+ kipi-plugins/imageviewer/timer.h:
+ introducing namespace KIPIviewer
+ fixing compiler warning
+
+2007-02-13 16:54 kusi
+
+ * [r633261] kipi-plugins/Makefile.am:
+ add imageviewer to Makefile.am
+ TODO: check for OpenGL?
+
+2007-02-13 08:39 kusi
+
+ * [r633109] kipi-plugins/imageviewer/ogl.cpp,
+ kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/plugin_viewer.cpp,
+ kipi-plugins/imageviewer/plugin_viewer.h,
+ kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/imageviewer/texture.h,
+ kipi-plugins/imageviewer/timer.cpp,
+ kipi-plugins/imageviewer/timer.h:
+ fix GPL license (wrong address)
+
+2007-02-12 11:39 cgilles
+
+ * [r632812] kipi-plugins/configure.in.in:
+ removing unused compile variable
+
+2007-02-12 10:09 cgilles
+
+ * [r632782] kipi-plugins/NEWS:
+ update
+
+2007-02-11 23:11 hoechstetter
+
+ * [r632707] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp:
+ BUG:138241;
+ Added a patch that adds support for the Claws Mail MUA by
+ paul@claws-mail.org
+
+2007-02-11 21:20 kusi
+
+ * [r632663] kipi-plugins/imageviewer/timer.h:
+ cleanup in comments
+
+2007-02-11 21:06 kusi
+
+ * [r632659] kipi-plugins/NEWS:
+ added imageviewer to NEWS
+
+2007-02-11 20:54 kusi
+
+ * [r632655] kipi-plugins/AUTHORS, kipi-plugins/imageviewer,
+ kipi-plugins/imageviewer/Makefile.am,
+ kipi-plugins/imageviewer/README, kipi-plugins/imageviewer/TODO,
+ kipi-plugins/imageviewer/cursors,
+ kipi-plugins/imageviewer/cursors/Makefile.am,
+ kipi-plugins/imageviewer/cursors/hand.png,
+ kipi-plugins/imageviewer/cursors/zoom.png,
+ kipi-plugins/imageviewer/hi16-app-ogl.png,
+ kipi-plugins/imageviewer/hi32-app-ogl.png,
+ kipi-plugins/imageviewer/kipiplugin_viewer.desktop,
+ kipi-plugins/imageviewer/ogl.cpp, kipi-plugins/imageviewer/ogl.h,
+ kipi-plugins/imageviewer/plugin_viewer.cpp,
+ kipi-plugins/imageviewer/plugin_viewer.h,
+ kipi-plugins/imageviewer/texture.cpp,
+ kipi-plugins/imageviewer/texture.h,
+ kipi-plugins/imageviewer/timer.cpp,
+ kipi-plugins/imageviewer/timer.h:
+ initial checkin of an OpenGL image viewer
+
+2007-02-10 18:37 cgilles
+
+ * [r632341] kipi-plugins/slideshow/plugin_slideshow.cpp:
+ kipi-plugins from trunk : SlideShow tool : fix menu entry from
+ "SlideShow" to "Advanced SlideShow"
+ CCBUGS: 129739
+
+2007-02-04 21:09 cguthrie
+
+ * [r630245] kipi-plugins/sync/Makefile.am,
+ kipi-plugins/sync/gallerympform.cpp,
+ kipi-plugins/sync/gallerympform.h,
+ kipi-plugins/sync/gallerytalker.cpp,
+ kipi-plugins/sync/gallerytalker.h, kipi-plugins/sync/libkipi2,
+ kipi-plugins/sync/libkipi2/collection.cpp,
+ kipi-plugins/sync/libkipi2/collection.h,
+ kipi-plugins/sync/libkipi2/interface.cpp,
+ kipi-plugins/sync/libkipi2/interface.h,
+ kipi-plugins/sync/libkipi2/item.cpp,
+ kipi-plugins/sync/libkipi2/item.h, kipi-plugins/sync/sink.cpp,
+ kipi-plugins/sync/sink.h, kipi-plugins/sync/sinkfactory.cpp,
+ kipi-plugins/sync/sinkfactory.h, kipi-plugins/sync/sinks,
+ kipi-plugins/sync/sinks.cpp, kipi-plugins/sync/sinks/gallery,
+ kipi-plugins/sync/sinks/gallery/gallerycollection.cpp,
+ kipi-plugins/sync/sinks/gallery/gallerycollection.h,
+ kipi-plugins/sync/sinks/gallery/galleryform.cpp,
+ kipi-plugins/sync/sinks/gallery/galleryform.h,
+ kipi-plugins/sync/sinks/gallery/galleryitem.cpp,
+ kipi-plugins/sync/sinks/gallery/galleryitem.h,
+ kipi-plugins/sync/sinks/gallery/gallerysink.cpp,
+ kipi-plugins/sync/sinks/gallery/gallerysink.h:
+ Some more work on the Sync Framework.
+ This is still very much work in progress so it is not yet usable.
+ Some of the concepts may be subject to change as I work through
+ some ideas.
+
+2007-02-03 09:13 cgilles
+
+ * [r629585] kipi-plugins/NEWS:
+ update
+
+2007-02-03 09:10 cgilles
+
+ * [r629584] kipi-plugins/NEWS:
+ update
+
+2007-01-30 12:11 cgilles
+
+ * [r628568] kipi-plugins/README:
+ update
+
+2007-01-30 10:22 cgilles
+
+ * [r628540] kipi-plugins/galleryexport/gallerytalker.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/plugin_gpssync.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.h,
+ kipi-plugins/metadataedit/exifadjust.cpp,
+ kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifdatetime.cpp,
+ kipi-plugins/metadataedit/exifdevice.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/exiflens.cpp,
+ kipi-plugins/metadataedit/exiflight.cpp,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptccredits.cpp,
+ kipi-plugins/metadataedit/iptcdatetime.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.cpp,
+ kipi-plugins/metadataedit/plugin_metadataedit.cpp,
+ kipi-plugins/rawconverter/dcrawiface.cpp,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp,
+ libkexiv2/Makefile.am, libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h,
+ libkexiv2/kexiv2_export.h, libkexiv2/libkexiv2.cpp,
+ libkexiv2/libkexiv2.h:
+ kipi-plugins from trunk : fix libkexiv2 header file name
+
+2007-01-30 09:45 cgilles
+
+ * [r628536] kipi-plugins/galleryexport/gallerytalker.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/plugin_gpssync.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.h,
+ kipi-plugins/metadataedit/exifadjust.cpp,
+ kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifdatetime.cpp,
+ kipi-plugins/metadataedit/exifdevice.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/exiflens.cpp,
+ kipi-plugins/metadataedit/exiflight.cpp,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptccredits.cpp,
+ kipi-plugins/metadataedit/iptcdatetime.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.cpp,
+ kipi-plugins/metadataedit/plugin_metadataedit.cpp,
+ kipi-plugins/rawconverter/dcrawiface.cpp,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp,
+ libkexiv2/libkexiv2.cpp, libkexiv2/libkexiv2.h:
+ kipi-plugins from trunk : fix libkexiv2 namespace and interface
+ class name
+
+2007-01-28 20:58 coolo
+
+ * [r628018] kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.h:
+ it's a _very_ bad idea to overwrite the identity matrix
+ or you'll get strange results on the next rotation (as I did)
+
+2007-01-28 19:42 cgilles
+
+ * [r627984] kipi-plugins/rawconverter/dcrawiface.h:
+ compile under OpenBSD
+
+2007-01-27 10:37 cgilles
+
+ * [r627589] kipi-plugins/configure.in.bot,
+ kipi-plugins/configure.in.in:
+ cleanup and backport KDE hiden visiblity detection from digiKam
+
+2007-01-26 20:40 cgilles
+
+ * [r627501] kipi-plugins/NEWS, kipi-plugins/README,
+ kipi-plugins/common/Makefile.am, kipi-plugins/common/exiv2iface,
+ kipi-plugins/configure.in.bot, kipi-plugins/configure.in.in,
+ kipi-plugins/galleryexport/Makefile.am,
+ kipi-plugins/galleryexport/gallerytalker.cpp,
+ kipi-plugins/gpssync/Makefile.am,
+ kipi-plugins/gpssync/gpslistviewitem.cpp,
+ kipi-plugins/gpssync/gpslistviewitem.h,
+ kipi-plugins/gpssync/plugin_gpssync.cpp,
+ kipi-plugins/gpssync/plugin_gpssync.h,
+ kipi-plugins/jpeglossless/Makefile.am,
+ kipi-plugins/jpeglossless/jpegtransform.cpp,
+ kipi-plugins/jpeglossless/jpegtransform.h,
+ kipi-plugins/metadataedit/Makefile.am,
+ kipi-plugins/metadataedit/exifadjust.cpp,
+ kipi-plugins/metadataedit/exifcaption.cpp,
+ kipi-plugins/metadataedit/exifdatetime.cpp,
+ kipi-plugins/metadataedit/exifdevice.cpp,
+ kipi-plugins/metadataedit/exifeditdialog.cpp,
+ kipi-plugins/metadataedit/exiflens.cpp,
+ kipi-plugins/metadataedit/exiflight.cpp,
+ kipi-plugins/metadataedit/iptccaption.cpp,
+ kipi-plugins/metadataedit/iptccategories.cpp,
+ kipi-plugins/metadataedit/iptccredits.cpp,
+ kipi-plugins/metadataedit/iptcdatetime.cpp,
+ kipi-plugins/metadataedit/iptceditdialog.cpp,
+ kipi-plugins/metadataedit/iptckeywords.cpp,
+ kipi-plugins/metadataedit/iptcorigin.cpp,
+ kipi-plugins/metadataedit/iptcstatus.cpp,
+ kipi-plugins/metadataedit/iptcsubjects.cpp,
+ kipi-plugins/metadataedit/plugin_metadataedit.cpp,
+ kipi-plugins/rawconverter/Makefile.am,
+ kipi-plugins/rawconverter/dcrawiface.cpp,
+ kipi-plugins/rawconverter/dcrawiface.h,
+ kipi-plugins/sendimages/Makefile.am,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h,
+ kipi-plugins/sync/Makefile.am,
+ kipi-plugins/sync/gallerytalker.cpp,
+ kipi-plugins/timeadjust/Makefile.am,
+ kipi-plugins/timeadjust/timeadjustdialog.cpp,
+ kipi-plugins/timeadjust/timeadjustdialog.h,
+ libkexiv2/libkexiv2.cpp, libkexiv2/libkexiv2.h:
+ kipi-plugins from trunk : all plugins use the new shared library
+ libkexiv2 instead KipiPlugins::EXiv2Iface class.
+
+ Marcel, next stage is to derivate the DigiKam::DMetadata class
+ from LibKExiv2. Let's me hear when you whant to do it...
+
+ CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org,
+ marcel.wiesweg@gmx.de
+
+2007-01-26 17:50 hoechstetter
+
+ * [r627469] kipi-plugins/sendimages/listimageserrordialog.cpp,
+ kipi-plugins/sendimages/listimageserrordialog.h,
+ kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h:
+ qDebug Translation to english
+ Adding comments
+
+2007-01-25 15:55 lure
+
+ * [r627061] kipi-plugins/NEWS,
+ kipi-plugins/common/exiv2iface/exiv2iface.cpp:
+ Prefer Exif DateTimeOriginal for image date/time
+ (DateTimeDigitized and DateTime only used as fallback)
+
+ CCBUG: 139264
+
+2007-01-25 01:04 hoechstetter
+
+ * [r626934] kipi-plugins/sendimages/sendimages.cpp:
+ BUG: 139074;
+ Changed the qDebug messages to an int-cast
+
+2007-01-24 23:15 anaselli
+
+ * [r626918] kipi-plugins/ipodexport/Makefile.am:
+ Added message target for translators
+
+ CCMAIL:kde-i18n-doc@kde.org
+ CCMAIL:kde-imaging@kde.org
+
+----------------------------------------------------------------------------
+V 0.1.3 - 2007-01-24
+----------------------------------------------------------------------------
+
+2007-01-24 20:46 anaselli
+
+ * [r626875] kipi-plugins/ChangeLog,
+ kipi-plugins/common/include/pluginsversion.h,
+ kipi-plugins/kipi-plugins.lsm:
+ Kipi-plugins 0.1.3 final
+
+ CCMAIL: <kde-imaging@kde.org>
+
+2007-01-24 20:38 anaselli
+
+ * [r626873] kipi-plugins/README:
+ Added beta in iPodExport Plugin
+
+ CCMAIL: <kde-imaging@kde.org>
+
+2007-01-24 18:04 amantia
+
+ * [r626836] kipi-plugins/kameraklient/gpcamera.cpp:
+ Fix compilation.
+
+2007-01-24 07:56 seb
+
+ * [r626678] kipi-plugins/Makefile.am,
+ kipi-plugins/configure.in.bot, kipi-plugins/configure.in.in:
+ Since libgpod 0.4.2 has been released, I've re-enabled the ipod
+ export plugin. I've also returned home so i can resume
+ maintaining the plugin.
+ Now, now more problems with API breakages since we rely on a
+ stable release.
+
+ RFC, please!
+
+ CCMAIL: kde-imaging@kde.org
+
+2007-01-23 22:46 anaselli
+
+ * [r626621] kipi-plugins/README, kipi-plugins/configure.in.bot:
+ Added a note into README and a warning into configure.bot file
+ that ipod export has been disabled
+
+ REMEMBER to remove it after final ;)
+
+ CCMAIL: <kde-imaging@kde.org>
+
+2007-01-23 22:35 anaselli
+
+ * [r626618] kipi-plugins/Makefile.am:
+ disabled ipodexport for incoming release
+
+ CCMAIL: <kde-imaging@kde.org>
+
+2007-01-23 22:33 anaselli
+
+ * [r626616] kipi-plugins/configure.in.in:
+ fixed libgpod test
+
+ CCMAIL: <kde-imaging@kde.org>
+
+2007-01-22 08:54 cguthrie
+
+ * [r626123] kipi-plugins/sync/Makefile.am,
+ kipi-plugins/sync/sinkfactory.cpp,
+ kipi-plugins/sync/sinkfactory.h, kipi-plugins/sync/sinklist.cpp,
+ kipi-plugins/sync/sinklistbase.ui, kipi-plugins/sync/sinks.cpp,
+ kipi-plugins/sync/sinks.h:
+ Slowly work towards a structure for creating Sinks (definition of
+ Sink is still very incomplete)
+
+2007-01-20 19:49 cguthrie
+
+ * [r625683] kipi-plugins/sync, kipi-plugins/sync/Makefile.am,
+ kipi-plugins/sync/plugin_sync.cpp,
+ kipi-plugins/sync/plugin_sync.h, kipi-plugins/sync/sinklist.cpp,
+ kipi-plugins/sync/sinklist.h, kipi-plugins/sync/sinklistbase.ui,
+ kipi-plugins/sync/sinks.cpp, kipi-plugins/sync/sinks.h:
+ Convert the listing dialog to a .ui file and adapt other parts to
+ use it.
+ By no means complete or funtioning.
+
+2007-01-20 13:51 cguthrie
+
+ * [r625578] kipi-plugins/sync/gallerylist.cpp,
+ kipi-plugins/sync/gallerylist.h, kipi-plugins/sync/sinklist.cpp,
+ kipi-plugins/sync/sinklist.h:
+ More gallery->sync renames: This really needs proper refactoring,
+ but just trying to get something that at least partly compiles
+ first.
+
+2007-01-20 13:01 cguthrie
+
+ * [r625569] kipi-plugins/ipodexport/ipodexportdialog.cpp:
+ Fix to compile with latest libgpod 0.4.2
+ Warning: I do not have an ipod to test this, so you may still
+ want to disable this for final release Angelo.
+ The only changes were to add 0 values for position and rotation
+ in two functions calls, so I shouldn't expect too much fall out.
+ CCBUG: 67873
+
+2007-01-16 15:18 hoechstetter
+
+ * [r624155] kipi-plugins/NEWS:
+
+
+2007-01-15 09:14 cguthrie
+
+ * [r623691] kipi-plugins/sync/galleries.cpp,
+ kipi-plugins/sync/galleries.h,
+ kipi-plugins/sync/kipiplugin_galleryexport.desktop,
+ kipi-plugins/sync/kipiplugin_sync.desktop,
+ kipi-plugins/sync/plugin_galleryexport.cpp,
+ kipi-plugins/sync/plugin_galleryexport.h,
+ kipi-plugins/sync/plugin_sync.cpp,
+ kipi-plugins/sync/plugin_sync.h, kipi-plugins/sync/sinks.cpp,
+ kipi-plugins/sync/sinks.h:
+ Started renaming files/classes etc.
+ Nowhere near ready or compilable yet.
+ (Don't worry Angelo, it shouldn't get in the way of release, but
+ if it does just kill it)
+ CCMAIL: kde-imaging@kde.org
+
+2007-01-14 21:24 cguthrie
+
+ * [r623450] kipi-plugins/sync:
+ Copy galleryexport to 'sync' for work on new generic
+ synchronisation framework.
+ Please don't expect any fast development on this from me, but
+ I'll try and give it some focus in the coming months.
+ If this in some way messes up the release process, please just
+ svn rm the folder as I can always resurect it. I will not commit
+ any updated Makefile.am's etc. in the kipi-plugins directory.
+ CCMAIL: kde-imaging@kde.org
+
+2007-01-06 14:06 cgilles
+
+ * [r620531] kipi-plugins/gpssync/gpseditdialog.cpp,
+ kipi-plugins/gpssync/gpseditdialog.h,
+ kipi-plugins/gpssync/gpssyncdialog.cpp,
+ kipi-plugins/gpssync/gpssyncdialog.h:
+ kipi-plugins from trunk : GPS Sync tool : patch from Heiner
+ Lamprecht to remember the last GPS position used by user between
+ plugin session.
+
+ CCMAIL: heiner@heiner-lamprecht.net
+
+2007-01-06 14:05 cgilles
+
+ * [r620528] kipi-plugins/gpssync/getlonlat.php:
+ kipi-plugins from trunk : GPS Sync tool : patch from Heiner
+ Lamprecht to port Google maps interface from HTML to XHTML
+
+ CCMAIL: heiner@heiner-lamprecht.net
+
+2007-01-06 11:28 hoechstetter
+
+ * [r620497] kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimages.h:
+ BUG: 132220;
+ implemented a replacement of not welcomed characters in filenames
+ and
+ fixed the mozilla, thunderbird, ... commandline
+
+2007-01-03 16:27 mwiesweg
+
+ * [r619526] kipi-plugins/jpeglossless/jpegtransform.cpp:
+ Port back fix for digikam bug 139197 to JPEGLossLess:
+ Use proper libjpeg error handling.
+ In case of an error, libjpeg would call exit() from the default
+ error handler.
+
+ CCBUG: 139197
+
+2007-01-03 09:33 cgilles
+
+ * [r619378] kipi-plugins/jpeglossless/plugin_jpeglossless.cpp:
+ kipi-plugins from trunk : JPEGLossLess shortcuts : use CTRL
+ instead SHIFT to prevent conflict with new rule from Comments
+ Text edit widget focus from digiKam right side bar.
+
+ CCBUGS: 131743
+
+2007-01-02 17:04 cguthrie
+
+ * [r619053] kipi-plugins/NEWS:
+ Update news after fixing bug 137582
+
+2007-01-02 15:05 cguthrie
+
+ * [r619007] kipi-plugins/galleryexport/gallerytalker.cpp:
+ Be consistent with the order of statics vs. vars (to prevent
+ thinkos when you accidentally put only = when you mean ==)
+
+2007-01-02 15:01 cguthrie
+
+ * [r619005] kipi-plugins/galleryexport/TODO,
+ kipi-plugins/galleryexport/gallerympform.cpp,
+ kipi-plugins/galleryexport/gallerytalker.cpp,
+ kipi-plugins/galleryexport/gallerytalker.h:
+ Implement new security feature required by upcoming Gallery v2.2.
+ This is as yet untested but I have tested with Gallery v2.1 to
+ ensure no regressions.
+ Hopefully when Gallery v2.2 is releases this will Just Work(tm),
+ if not then I will have to patch it accordingly.
+ I have assumed as per the spec doc suggests that the auth token
+ will not change since login.
+ BUG: 137582
+
+2006-12-31 14:45 ach
+
+ * [r618196] kipi-plugins/INSTALL:
+ kipi-plugins: remove out of date requirements section
+ and refer to README instead
+
+2006-12-31 14:42 ach
+
+ * [r618195] kipi-plugins/README:
+ kipi-plugins: update README
+ o use new kipi-plugins website URL. kipi info
+ on extragear is out of date
+ o fix typo
+ o add note that ipodexport plugin is currently
+ broken with latest stable libgpod 0.4.0 release
+
+2006-12-31 14:34 anaselli
+
+ * [r618192] kipi-plugins/README:
+ libgpod > 0.4.0 - version 0.4.0 isn't compatible with current
+ ipodexport plugin implementation
+
+2006-12-31 13:13 ach
+
+ * [r618170] kipi-plugins/gpssync/Makefile.am,
+ kipi-plugins/metadataedit/Makefile.am:
+ kipi-plugins: list all and only directly used libraries.
+ Move kipiplugins library from LDFLAGS to LIBADD
+
+2006-12-30 14:21 anaselli
+
+ * [r617899] kipi-plugins/configure.in.bot:
+ libkipi >= 0.1.5 now
+
+2006-12-30 13:33 anaselli
+
+ * [r617822] kipi-plugins/batchprocessimages/renameimagesbase.ui,
+ kipi-plugins/batchprocessimages/renameimageswidget.cpp:
+ leave old plugins compatible to kde 3.3 by now
+
+2006-12-29 14:08 anaselli
+
+ * [r617540] kipi-plugins/NEWS:
+ updated
+
+2006-12-28 01:08 anaselli
+
+ * [r617108] kipi-plugins/TODO:
+ remind me todo
+
+----------------------------------------------------------------------------
+V 0.1.3-rc1 - 2006-12-28
+----------------------------------------------------------------------------
+
+2006-12-27 23:39 vfuoglio
+
+ * [r617085] kipi-plugins/ChangeLog,
+ kipi-plugins/common/include/pluginsversion.h,
+ kipi-plugins/kipi-plugins.lsm:
+ kipi-plugins 0.1.3 rc1
+
+2006-12-27 23:20 anaselli
+
+ * [r617080] kipi-plugins/NEWS:
+ prepare 0.1.3 rc1
+
+2006-12-19 17:12 vkrause
+
+ * [r614961] kipi-plugins/slideshow/slideshowconfig.cpp:
+ compile
+
+2006-12-18 19:27 cgilles
+
+ * [r614741] kipi-plugins/configure.in.bot:
+ fix Exiv2 detection error message
+
+2006-12-14 22:04 anaselli
+
+ * [r613716] kipi-plugins/common/exiv2iface/Makefile.am,
+ kipi-plugins/configure.in.in:
+ new exiv2 test using pkg-config
+
+2006-12-14 06:59 cgilles
+
+ * [r613593] kipi-plugins/NEWS:
+ update
+
+2006-12-13 23:18 vfuoglio
+
+ * [r613541] kipi-plugins/slideshow/slideshowconfigbase.ui:
+ Now slideshow interval can be set below 1000 ms (min 100 ms).
+
+ CCMAIL: kde-imaging@kde.org
+ BUG: 108147
+
+2006-12-13 08:32 cgilles
+
+ * [r613037] kipi-plugins/rawconverter/Makefile.am:
+ add comment
+
+2006-12-13 08:26 cgilles
+
+ * [r613036] kipi-plugins/kameraklient/Makefile.am,
+ kipi-plugins/kameraklient/gpiface.cpp:
+ kipi-plugins from trunk : support of "--enable-final" compilation
+ option
+
+2006-12-13 05:14 cgilles
+
+ * [r612924] kipi-plugins/NEWS:
+ update
+
+2006-12-12 14:25 cgilles
+
+ * [r612755] kipi-plugins/common/exiv2iface/exiv2iface.cpp:
+ kipi-plugins from trunk : if file dir-path is read-only, do not
+ try to save metadata on pictures.
+ CCBUGS: 138540
+
+2006-12-12 01:56 vfuoglio
+
+ * [r612634] kipi-plugins/NEWS, kipi-plugins/TODO,
+ kipi-plugins/slideshow/plugin_slideshow.cpp,
+ kipi-plugins/slideshow/plugin_slideshow.h,
+ kipi-plugins/slideshow/slideshow.cpp,
+ kipi-plugins/slideshow/slideshow.h,
+ kipi-plugins/slideshow/slideshowconfig.cpp,
+ kipi-plugins/slideshow/slideshowconfig.h,
+ kipi-plugins/slideshow/slideshowconfigbase.ui,
+ kipi-plugins/slideshow/slideshowgl.cpp,
+ kipi-plugins/slideshow/slideshowgl.h:
+ Added possibility to show image comments.
+
+ CCMAIL: kde-imaging@kde.org
+ BUG: 106133
+ GUI:
+
+2006-12-10 19:34 anaselli
+
+ * [r612297] kipi-plugins/mpegencoder/kimg2mpg.cpp:
+ If users press cancel there's no need to tell them again they're
+ using "Default"...
+
+ CCMAIL: <kde-imaging@kde.org>
+
+2006-12-10 18:45 vfuoglio
+
+ * [r612280] kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ kipi-plugins/mpegencoder/kimg2mpg.h,
+ kipi-plugins/mpegencoder/kimg2mpgbase.ui,
+ libkipi/libkipi/hi128-app-kipi.png:
+ - Fixed dialog resizing issues
+ - Added warning dialog for mjpegtools version check
+
+ CCMAIL: kde-imaging@kde.org
+ GUI
+
+2006-12-10 10:22 cgilles
+
+ * [r612080] kipi-plugins/jpeglossless/plugin_jpeglossless.cpp:
+ kipi-plugins from trunk : add JPEGLossLess Flip/rotate keyboard
+ shortcut actions. Using the same than digiKam image editor.
+ CCBUGS: 133091
+ CCMAIL: ach@mpe.mpg.de
+
+2006-12-09 22:27 anaselli
+
+ * [r611887] kipi-plugins/NEWS:
+ updated
+
+2006-12-09 00:24 anaselli
+
+ * [r611631] kipi-plugins/configure.in.bot:
+ changed libgpod version required
+
+2006-12-09 00:18 anaselli
+
+ * [r611628] kipi-plugins/configure.in.in:
+ never commit when you're asleep...
+
+ CCMAIL: <kde-imaging@kde.org>
+
+2006-12-09 00:10 anaselli
+
+ * [r611626] kipi-plugins/kameraklient/gpcamera.cpp,
+ kipi-plugins/kameraklient/gpiface.cpp:
+ changed to get it working for new libgphoto2
+
+ CCMAIL: <kde-imaging@kde.org>
+
+2006-12-09 00:07 anaselli
+
+ * [r611625] kipi-plugins/configure.in.in:
+ - changed PKG_CHECK_MODULES with KDE_PKG_CHECK_MODULES
+ as provided by Fabien's patch
+ - now if exiv2 is missed configure aborts
+ - now libkipi 0.1.5 is required
+
+ CCMAIL: <kde-imaging@kde.org>
+
+2006-12-07 12:33 cgilles
+
+ * [r611248] kipi-plugins/common/exiv2iface/exiv2iface.cpp:
+ kipi-plugins from trunk : Don't touch read-only file when
+ metadata need to be updated.
+ CCBUG: 137770
+
+2006-12-05 22:17 anaselli
+
+ * [r610876] kipi-plugins/configure.in.in:
+ At the moment we know only libgpod 0.4.0 is not ok so a greater
+ version should be enough (waiting for seb to be back)
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-12-04 14:34 cgilles
+
+ * [r610568] kipi-plugins/NEWS:
+ update
+
+2006-12-04 14:11 cgilles
+
+ * [r610562] kipi-plugins/NEWS:
+ update
+
+2006-12-04 13:28 cgilles
+
+ * [r610484] kipi-plugins/NEWS:
+ update
+
+2006-12-04 13:21 cgilles
+
+ * [r610468] kipi-plugins/NEWS:
+ update
+
+2006-12-04 13:01 cgilles
+
+ * [r610462] kipi-plugins/NEWS:
+ update
+
+2006-12-04 12:41 cgilles
+
+ * [r610452] kipi-plugins/NEWS:
+ update
+
+2006-12-04 06:28 cgilles
+
+ * [r610328] kipi-plugins/metadataedit/exiflight.cpp:
+ typo
+
+2006-11-30 16:39 vfuoglio
+
+ * [r609404] kipi-plugins/AUTHORS,
+ kipi-plugins/mpegencoder/Makefile.am,
+ kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ kipi-plugins/mpegencoder/kimg2mpg.h,
+ kipi-plugins/mpegencoder/kimg2mpgbase.ui:
+ - Used new GUI (created with designer)
+ - Added me as maintainer (in accord with Angelo Naselli)
+
+ CCMAIL: kde-imaging@kde.org
+ GUI
+
+2006-11-30 13:02 anaselli
+
+ * [r609369] kipi-plugins/NEWS:
+ changed version and added new list for future 0.1.3 beta/rc
+
+----------------------------------------------------------------------------
+v 0.1.3-beta1 - 2006-11-29
+----------------------------------------------------------------------------
+
+2006-11-29 22:07 anaselli
+
+ * [r609259] kipi-plugins/ChangeLog,
+ kipi-plugins/common/include/pluginsversion.h,
+ kipi-plugins/kipi-plugins.lsm:
+ kipi-plugins 0.1.3 beta 1
+ svn2log.py seems to be broken again used svn2cl instead
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-29 20:45 anaselli
+
+ * [r609230] configure.in.in:
+ fixed wrong message if exiv2_config is not present
+
+2006-11-29 12:54 anaselli
+
+ * [r609050] configure.in.in:
+ improved exiv2 test
+
+2006-11-29 09:45 anaselli
+
+ * [r609024] configure.in.in:
+ changed warning message
+
+2006-11-28 23:06 anaselli
+
+ * [r608932] configure.in.in:
+ Added libexiv2 >= 0.12 requirement
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-27 16:43 cgilles
+
+ * [r608467] README:
+ fix depency to Exiv2 0.12
+
+2006-11-27 12:45 cgilles
+
+ * [r608312] rawconverter/dcrawiface.cpp:
+ digikam from trunk : fix debug message
+
+2006-11-27 08:47 cgilles
+
+ * [r608242] NEWS:
+ update
+
+2006-11-27 08:46 cgilles
+
+ * [r608241] metadataedit/iptcorigin.cpp:
+ kipi-plugins from trunk : fix country name extraction for combox.
+ BUG: 137921
+
+2006-11-25 20:58 anaselli
+
+ * [r607806] mpegencoder/kimg2mpg.cpp:
+ kimg2mpg now calls by default images2mpg with "-S 420mpeg2"
+ passed to
+ ppmtoy4m. The old one, named "Default" in the configuration
+ dialog, is left to
+ get back-compatibility since some old versions of ppmtoy4m used
+ "-S 420_mpeg2".
+
+ Note that if you upgrade kipi-plugins, you should remember that
+ the default behavior is already set into your kipirc.
+ CCMAIL: <kde-imaging@kde.org>
+
+2006-11-24 12:40 cgilles
+
+ * [r607391] sendimages/sendimages.cpp:
+ kipi-plugins from trunk : SendImages : patch from Michael
+ Höchstetter to fix kdDebug() statements to qDebug() in
+ multithreaded section.
+
+ Important nocice to kipi developpers : never use kdDebug() in
+ QThread because it not thread-safe! Please look the story on
+ http://bugs.kde.org/show_bug.cgi?id=133026
+
+ CCMAIL: kde-imaging@kde.org, michael.hoechstetter@gmx.de
+ CCBUGS: 133026
+
+2006-11-24 09:22 cgilles
+
+ * [r607351] sendimages/listimageserrordialog.cpp,
+ sendimages/listimageserrordialog.h,
+ sendimages/plugin_sendimages.cpp, sendimages/sendimages.h,
+ sendimages/sendimagesdialog.cpp, sendimages/sendimagesdialog.h:
+ kipi-plugins from trunk : SendImages : Fix Coding style
+ CCMAIL: michael.hoechstetter@gmx.de
+
+2006-11-24 09:00 cgilles
+
+ * [r607344] sendimages/plugin_sendimages.cpp,
+ sendimages/plugin_sendimages.h, sendimages/sendimages.cpp,
+ sendimages/sendimages.h:
+ kipi-plugins from trunk : SendImages : Fix Coding style
+ CCMAIL: michael.hoechstetter@gmx.de
+
+2006-11-24 08:20 cgilles
+
+ * [r607337] sendimages/Makefile.am, sendimages/exifrestorer.cpp,
+ sendimages/exifrestorer.h, sendimages/jpegsection.h,
+ sendimages/sendimages.cpp, sendimages/sendimages.h:
+ kipi-plugins from trunk : SendImages : patch from Michael
+ Höchstetter :
+
+ - Support Exiv2Iface class instead JpegRestorer.
+ - Fix small bug concerning filenames and thunderbird, mozilla
+ ....
+ Now it is possible, that the path and filename contains
+ "spaces", however it
+ still is not possible to contain signs like kommas. Still todo.
+
+ CCMAIL: kde-imaging@kde.org, michael.hoechstetter@gmx.de
+
+2006-11-23 14:09 cgilles
+
+ * [r607169] timeadjust/timeadjustdialog.cpp:
+ fix layout
+
+2006-11-23 13:50 cgilles
+
+ * [r607163] timeadjust/timeadjustdialog.cpp:
+ kipi-plugins from trunk : TimeAdjust : now the plugin remember
+ the Adjustment Type settings between session
+
+2006-11-23 13:27 cgilles
+
+ * [r607160] timeadjust/timeadjustdialog.cpp,
+ timeadjust/timeadjustdialog.h:
+ kipi-plugins from trunk : TimeAdjust : using d private internal
+ class
+
+2006-11-23 13:05 cgilles
+
+ * [r607155] timeadjust/timeadjustdialog.cpp:
+ kipi-plugins from trunk : TimeAdjust : More readable report if
+ writting operations on files are failed
+
+2006-11-23 12:40 cgilles
+
+ * [r607153] gpssync/plugin_gpssync.cpp:
+ kipi-plugins from trunk : GPSSync : More redeable report if
+ wrtting operation files are failed
+
+2006-11-23 12:40 cgilles
+
+ * [r607152] metadataedit/plugin_metadataedit.cpp:
+ kipi-plugins from trunk : MetadataEdit : More redeable report if
+ wrtting operation files are failed
+
+2006-11-23 06:41 cgilles
+
+ * [r607102] NEWS:
+ update
+
+2006-11-22 23:20 gateau
+
+ * [r607073] batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/batchprocessimagesdialog.h:
+ Replaced UploadWidget with a KURLRequester
+ BUG: 117399
+ BUG: 135408
+
+2006-11-22 23:15 gateau
+
+ * [r607072] batchprocessimages/renameimagesbase.ui:
+ Cleanup
+
+2006-11-22 22:31 cgilles
+
+ * [r607062] NEWS:
+ update
+
+2006-11-22 22:23 cgilles
+
+ * [r607061] timeadjust/plugin_timeadjust.cpp,
+ timeadjust/plugin_timeadjust.h, timeadjust/timeadjustdialog.cpp,
+ timeadjust/timeadjustdialog.h:
+ kipi-plugins from trunk : Time Adjust : add new options to sync
+ timestamp to EXIF and IPTC Creation Date.
+
+2006-11-22 15:23 cgilles
+
+ * [r606977] NEWS:
+ update
+
+2006-11-22 15:22 cgilles
+
+ * [r606976] timeadjust/timeadjustdialog.cpp,
+ timeadjust/timeadjustdialog.h:
+ kipi-plugins from trunk : TimeAdjust plugin : new option to
+ customize Date and Time at a specific timestamp.
+
+2006-11-22 14:25 cgilles
+
+ * [r606970] metadataedit/iptcdatetime.cpp:
+ fix layout
+
+2006-11-22 14:14 cgilles
+
+ * [r606968] timeadjust/timeadjustdialog.cpp,
+ timeadjust/timeadjustdialog.h:
+ polish
+
+2006-11-22 14:09 cgilles
+
+ * [r606965] timeadjust/timeadjustdialog.cpp:
+ fix i18n
+
+2006-11-22 08:50 cgilles
+
+ * [r606886] metadataedit/exifdatetime.cpp,
+ metadataedit/exifdatetime.h, metadataedit/exifeditdialog.cpp,
+ metadataedit/iptcdatetime.cpp, metadataedit/iptcdatetime.h,
+ metadataedit/iptceditdialog.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : IPTC Edit Dialog
+ : add 2 new options to sync IPTC Creation Date with EXIF
+ Creation Date, and kipi host application Creation date (digiKam
+ timestamp)
+
+ CCBUGS: 136260
+
+2006-11-22 08:12 cgilles
+
+ * [r606881] metadataedit/exifcaption.cpp,
+ metadataedit/exifcaption.h, metadataedit/exifeditdialog.cpp,
+ metadataedit/iptccaption.cpp, metadataedit/iptccaption.h,
+ metadataedit/iptceditdialog.cpp, metadataedit/iptceditdialog.h,
+ metadataedit/plugin_metadataedit.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : IPTC Edit Dialog
+ : add 3 new options to sync IPTC Caption with JFIF comment
+ section, EXIF User Comment, and kipi host application comments
+ (digiKam comment)
+
+ CCBUGS: 136260
+
+2006-11-22 06:22 cgilles
+
+ * [r606869] metadataedit/exifeditdialog.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : commit missing
+ files.
+
+2006-11-21 21:24 cgilles
+
+ * [r606808] rawconverter/dcrawiface.cpp:
+ kipi-plugins from trunk : RAWConverter : backport patch from
+ Marcel (from digiKam core) about to take a care if dcraw fail to
+ decode a RAW file (look B.K.O #137495 for details)
+
+2006-11-21 13:32 cgilles
+
+ * [r606713] metadataedit/exifdatetime.cpp,
+ metadataedit/exifdatetime.h:
+ kipi-plugins from trunk : MetadataEdit plugin : Exif Edit Dialog
+ : add 2 new options to sync Exif Creation Date with IPTC
+ Creation Date, and kipi host application Creation Date (digiKam
+ Date & Time)
+
+ CCBUGS: 136260
+
+2006-11-21 13:01 cgilles
+
+ * [r606705] metadataedit/exifcaption.cpp,
+ metadataedit/exifcaption.h, metadataedit/exifeditdialog.cpp:
+ kipi-plugins from trunk : MetadataEdit : polish implementation
+
+2006-11-21 12:52 cgilles
+
+ * [r606701] common/exiv2iface/exiv2iface.cpp:
+ fix warning
+
+2006-11-21 12:00 cgilles
+
+ * [r606686] metadataedit/iptcsubjects.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 11:59 cgilles
+
+ * [r606684] metadataedit/iptcstatus.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 11:54 cgilles
+
+ * [r606682] metadataedit/iptcorigin.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 11:51 cgilles
+
+ * [r606680] metadataedit/iptckeywords.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 11:49 cgilles
+
+ * [r606679] metadataedit/iptcdatetime.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 11:43 cgilles
+
+ * [r606677] metadataedit/iptccredits.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 11:40 cgilles
+
+ * [r606676] metadataedit/iptccategories.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 11:36 cgilles
+
+ * [r606674] metadataedit/iptccaption.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 09:32 cgilles
+
+ * [r606653] metadataedit/exiflight.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 09:30 cgilles
+
+ * [r606652] metadataedit/exiflens.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 09:22 cgilles
+
+ * [r606650] metadataedit/exifdevice.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 08:57 cgilles
+
+ * [r606648] metadataedit/exifdatetime.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 08:50 cgilles
+
+ * [r606646] metadataedit/exifadjust.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-21 08:47 cgilles
+
+ * [r606645] metadataedit/exifcaption.cpp:
+ kipi-plugins from trunk : MetadataEdit : missing to clean widget
+ before to change current picture to edit.
+
+2006-11-20 12:48 cgilles
+
+ * [r606427] metadataedit/commentremovedialog.cpp,
+ metadataedit/commentremovedialog.h,
+ metadataedit/plugin_metadataedit.cpp:
+ code polishing
+
+2006-11-20 12:35 cgilles
+
+ * [r606424] metadataedit/Makefile.am,
+ metadataedit/commenteditdialog.cpp,
+ metadataedit/commenteditdialog.h,
+ metadataedit/commentremovedialog.cpp,
+ metadataedit/commentremovedialog.h,
+ metadataedit/plugin_metadataedit.cpp,
+ metadataedit/plugin_metadataedit.h:
+ kipi-plugins from trunk : MetadataEdit : new option to remove
+ Comments to a group of pictures. This tool will remove comments
+ from all selected pictures selected on host application. You can
+ remove IPTC/EXIF/JFIF comments at the same time.
+
+ CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org
+
+2006-11-20 11:00 seb
+
+ * [r606400] configure.in.in:
+ Fix the check for libgpod in the configure, as some of the
+ methods changed
+
+2006-11-20 09:34 cgilles
+
+ * [r606390] metadataedit/commenteditdialog.cpp,
+ metadataedit/exifcaption.cpp:
+ Fix i18n
+
+2006-11-20 09:22 cgilles
+
+ * [r606387] metadataedit/Makefile.am,
+ metadataedit/commenteditdialog.cpp,
+ metadataedit/commenteditdialog.h,
+ metadataedit/plugin_metadataedit.cpp:
+ kipi-plugins from trunk : MetadataEdit : new option to set
+ Comments to a group of pictures. This tool will set the same
+ comments to all selected pictures from host application. You can
+ sync IPTC/EXIF/JFIF comments at the same time.
+
+ A fresh screenshot :
+
+ http://digikam3rdparty.free.fr/Screenshots/KipipluginBatchCommentsEditor.png
+
+ CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org
+
+2006-11-20 07:56 cgilles
+
+ * [r606372] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipi-plugins from trunk : Exiv2iface : fix return bool value
+ with SetComments()
+
+2006-11-20 00:41 vfuoglio
+
+ * [r606320] timeadjust/Makefile.am,
+ timeadjust/timeadjustdialog.cpp, timeadjust/timeadjustdialog.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-20 00:34 vfuoglio
+
+ * [r606319] simpleviewerexport/Makefile.am,
+ simpleviewerexport/svedialog.cpp,
+ simpleviewerexport/svedialog.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-20 00:27 vfuoglio
+
+ * [r606317] kameraklient/Makefile.am,
+ kameraklient/cameraselection.cpp,
+ kameraklient/cameraselection.h, kameraklient/cameraui.cpp,
+ kameraklient/cameraui.h, kameraklient/setupcamera.cpp,
+ kameraklient/setupcamera.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-20 00:10 vfuoglio
+
+ * [r606313] imagesgallery/Makefile.am,
+ imagesgallery/imgallerydialog.cpp,
+ imagesgallery/imgallerydialog.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-19 23:58 vfuoglio
+
+ * [r606312] htmlexport/Makefile.am, htmlexport/wizard.cpp,
+ htmlexport/wizard.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-19 23:36 vfuoglio
+
+ * [r606309] flickrexport/Makefile.am,
+ flickrexport/flickrwindow.cpp, flickrexport/flickrwindow.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-19 23:24 vfuoglio
+
+ * [r606306] findimages/Makefile.am, findimages/displaycompare.cpp,
+ findimages/displaycompare.h,
+ findimages/finddupplicatedialog.cpp,
+ findimages/finddupplicatedialog.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-19 22:21 vfuoglio
+
+ * [r606294] calendar/Makefile.am, calendar/calwizard.cpp,
+ calendar/calwizard.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-19 22:10 vfuoglio
+
+ * [r606289] batchprocessimages/Makefile.am,
+ batchprocessimages/borderimagesdialog.cpp,
+ batchprocessimages/borderimagesdialog.h,
+ batchprocessimages/colorimagesdialog.cpp,
+ batchprocessimages/colorimagesdialog.h,
+ batchprocessimages/convertimagesdialog.cpp,
+ batchprocessimages/convertimagesdialog.h,
+ batchprocessimages/effectimagesdialog.cpp,
+ batchprocessimages/effectimagesdialog.h,
+ batchprocessimages/filterimagesdialog.cpp,
+ batchprocessimages/filterimagesdialog.h,
+ batchprocessimages/imagepreview.cpp,
+ batchprocessimages/imagepreview.h,
+ batchprocessimages/outputdialog.cpp,
+ batchprocessimages/outputdialog.h,
+ batchprocessimages/recompressimagesdialog.cpp,
+ batchprocessimages/recompressimagesdialog.h,
+ batchprocessimages/renameimagesdialog.cpp,
+ batchprocessimages/renameimagesdialog.h,
+ batchprocessimages/resizeimagesdialog.cpp,
+ batchprocessimages/resizeimagesdialog.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-19 20:53 vfuoglio
+
+ * [r606276] acquireimages/Makefile.am,
+ acquireimages/acquireimagedialog.cpp,
+ acquireimages/acquireimagedialog.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-19 16:27 cguthrie
+
+ * [r606207] galleryexport/gallerywindow.cpp,
+ galleryexport/gallerywindow.h:
+ Fix that memory leak all the cool kids are talking about.
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-19 16:18 cgilles
+
+ * [r606205] metadataedit/plugin_metadataedit.cpp:
+ typo again
+
+2006-11-19 15:09 cgilles
+
+ * [r606172] metadataedit/plugin_metadataedit.cpp,
+ metadataedit/plugin_metadataedit.h:
+ fix typo
+
+2006-11-19 08:43 cgilles
+
+ * [r606084] README:
+ update
+
+2006-11-19 08:41 cgilles
+
+ * [r606082] README:
+ update Exiv2 depency to future 0.12 release duing of an indeep
+ internal bug into current 0.11 release.
+
+2006-11-18 18:53 cgilles
+
+ * [r605968] gpssync/getlonlat.php:
+ patch from Heiner Lamprecht to show google map scale.
+
+2006-11-18 07:19 cgilles
+
+ * [r605769] NEWS:
+ update
+
+2006-11-18 03:41 seb
+
+ * [r605748] htmlexport, htmlexport/themes/s0, slideshow:
+ Update more of the svn:ignore propset
+
+2006-11-18 03:40 seb
+
+ * [r605747] rawconverter:
+ Ignore the binary
+
+2006-11-18 03:39 seb
+
+ * [r605746] common/libkipiplugins:
+ ignore generated files/dirs
+
+2006-11-18 03:38 seb
+
+ * [r605745] metadataedit:
+ ignore generated files
+
+2006-11-18 03:37 seb
+
+ * [r605744] configure.in.in:
+ update configure
+
+2006-11-18 03:37 seb
+
+ * [r605743] ipodexport/Makefile.am, ipodexport/imagelist.cpp,
+ ipodexport/imagelist.h, ipodexport/imagelistitem.h,
+ ipodexport/ipodexportdialog.cpp, ipodexport/ipodexportdialog.h,
+ ipodexport/ipodheader.cpp, ipodexport/ipodheader.h,
+ ipodexport/ipodlistitem.cpp, ipodexport/ipodlistitem.h:
+ Merge ipod export sources to be current, and ready for release
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-17 22:28 anaselli
+
+ * [r605713] common/libkipiplugins/kpaboutdata.cpp:
+ setProgramLogo is defined from kde 3.4.0 on
+ CCBUG: 134037
+
+2006-11-17 16:20 vfuoglio
+
+ * [r605642] printwizard/Makefile.am,
+ printwizard/frmprintwizard.cpp, printwizard/frmprintwizard.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-17 16:18 vfuoglio
+
+ * [r605641] mpegencoder/kimg2mpg.cpp, mpegencoder/kimg2mpg.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-17 16:17 vfuoglio
+
+ * [r605639] cdarchiving/Makefile.am,
+ cdarchiving/cdarchivingdialog.cpp,
+ cdarchiving/cdarchivingdialog.h:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-17 09:52 cgilles
+
+ * [r605575] common/exiv2iface/exiv2iface.cpp:
+ fix return Exiv2 test values
+
+2006-11-17 07:26 cgilles
+
+ * [r605554] common/exiv2iface/exiv2iface.cpp:
+ test return value from Exiv2
+
+2006-11-17 07:19 cgilles
+
+ * [r605552] common/exiv2iface/exiv2iface.cpp:
+ test return value from Exiv2
+
+ CCBUGS: 136855
+
+2006-11-17 07:13 cgilles
+
+ * [r605551] metadataedit/iptceditdialog.cpp:
+ iptc <> exif
+
+ CCBUGS: 136855
+
+2006-11-16 20:15 cgilles
+
+ * [r605460] metadataedit/exifcaption.cpp:
+ missing signals/slots connections
+
+2006-11-16 19:34 vfuoglio
+
+ * [r605452] metadataedit/exifeditdialog.cpp,
+ metadataedit/iptceditdialog.cpp:
+ Fixed memory leaks (KHelpMenu unallocate about data)
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-16 16:38 vfuoglio
+
+ * [r605397] rawconverter/singledialog.cpp,
+ rawconverter/singledialog.h:
+ Fixed memory leaks (KHelpMenu unallocate about data)
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-16 16:37 vfuoglio
+
+ * [r605396] sendimages/sendimagesdialog.cpp,
+ sendimages/sendimagesdialog.h:
+ Fixed memory leaks (KHelpMenu unallocate about data)
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-16 16:37 vfuoglio
+
+ * [r605395] rawconverter/batchdialog.cpp,
+ rawconverter/batchdialog.h:
+ Fixed memory leaks (KHelpMenu unallocate about data)
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-16 16:31 vfuoglio
+
+ * [r605390] gpssync/gpssyncdialog.cpp:
+ Fixed memory leaks (KHelpMenu unallocate about data)
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-16 14:39 cgilles
+
+ * [r605374] metadataedit/exifcaption.cpp,
+ metadataedit/exifcaption.h, metadataedit/exifeditdialog.cpp,
+ metadataedit/exifeditdialog.h, metadataedit/iptceditdialog.cpp,
+ metadataedit/plugin_metadataedit.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : Exif Edit Dialog
+ : add 3 new options to sync Exif User Comment with JFIF comment
+ section, IPTC caption, and kipi host application comments
+ (digiKam comment)
+
+ CCBUGS: 136260
+
+2006-11-16 14:27 vfuoglio
+
+ * [r605372] slideshow/slideshowconfig.cpp,
+ slideshow/slideshowconfig.h:
+ Class SlideShowConfig: Renamed member "about" to "m_about".
+
+2006-11-16 13:46 cgilles
+
+ * [r605360] AUTHORS:
+ typo
+
+2006-11-16 09:45 cgilles
+
+ * [r605303] common/exiv2iface/exiv2iface.h:
+ compile
+
+2006-11-16 09:28 cgilles
+
+ * [r605301] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipi-plugins from trunk : compile under kubuntu without using
+ C++ exception management everywhere : do not include exiv2
+ headers in Exiv2Iface header.
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-16 08:08 cgilles
+
+ * [r605279] NEWS:
+ update
+
+2006-11-16 07:25 gateau
+
+ * [r605272] batchprocessimages/renameimagesbase.ui,
+ batchprocessimages/renameimageswidget.cpp,
+ batchprocessimages/renameimageswidget.h:
+ It's now possible to move files in the list.
+ CCBUG: 136941
+
+2006-11-15 15:42 vfuoglio
+
+ * [r605150] slideshow/slideshowconfig.cpp,
+ slideshow/slideshowconfig.h:
+ Fixed memory leaks (KHelpMenu unallocate about data)
+
+ CCMAIL: kdeimaging@kde.org
+
+2006-11-15 00:57 vfuoglio
+
+ * [r605023] sendimages/Makefile.am,
+ sendimages/sendimagesdialog.cpp:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-15 00:56 vfuoglio
+
+ * [r605022] rawconverter/Makefile.am,
+ rawconverter/batchdialog.cpp, rawconverter/singledialog.cpp:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-15 00:51 vfuoglio
+
+ * [r605020] metadataedit/Makefile.am,
+ metadataedit/exifeditdialog.cpp,
+ metadataedit/iptceditdialog.cpp:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-15 00:49 vfuoglio
+
+ * [r605019] gpssync/Makefile.am, gpssync/gpssyncdialog.cpp:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-14 23:54 cguthrie
+
+ * [r605011] galleryexport/Makefile.am,
+ galleryexport/galleryconfig.cpp, galleryexport/gallerylist.cpp,
+ galleryexport/gallerywindow.cpp:
+ New KPAboutData changes.
+ Added me as maintainer.
+ Removed some unnecessary headers (still a few in there tho').
+ Copied Valerio's changes from Slideshow. Thanks :)
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-14 23:13 anaselli
+
+ * [r605002] AUTHORS:
+ Added Orgad Shaneh as the new Calendar maintainer
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-14 22:37 vfuoglio
+
+ * [r604984] slideshow/Makefile.am, slideshow/slideshowconfig.cpp:
+ Used new KPAboutData
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-14 12:21 cgilles
+
+ * [r604810] metadataedit/plugin_metadataedit.cpp:
+ Fix memory leak. Thanks mr valgrind
+
+2006-11-12 20:42 anaselli
+
+ * [r604437] NEWS:
+ updated for bug 127476
+
+2006-11-12 20:40 anaselli
+
+ * [r604435] printwizard/frmprintwizard.cpp,
+ printwizard/frmprintwizard.h, printwizard/frmprintwizardbase.ui:
+ Added a workaround to allow user to understand what's happening
+ looking at kjobviewer.
+
+ BUG: 127476
+
+2006-11-11 17:49 cgilles
+
+ * [r604146] metadataedit/exifeditdialog.cpp,
+ metadataedit/iptceditdialog.cpp:
+ fix i18n
+
+2006-11-10 15:30 gateau
+
+ * [r603870] batchprocessimages/renameimagesbase.ui,
+ batchprocessimages/renameimageswidget.cpp:
+ Set most settings in ui file. Disable sorting by clicking
+ headers.
+
+2006-11-10 15:00 gateau
+
+ * [r603862] batchprocessimages/renameimagesbase.ui:
+ Moved image list below options and make sure it uses all the
+ available height
+ if dialog is resized.
+
+2006-11-09 18:28 cgilles
+
+ * [r603682] NEWS:
+ update
+
+2006-11-09 18:27 cgilles
+
+ * [r603681] NEWS:
+ update
+
+2006-11-09 17:20 gateau
+
+ * [r603670] htmlexport/generator.cpp,
+ htmlexport/htmlexportconfig.kcfg,
+ htmlexport/imagesettingspage.ui:
+ Reworked image and XML generation.
+ Added an option to use the original file.
+ BUG: 128341
+
+2006-11-09 16:38 cgilles
+
+ * [r603661] metadataedit/metadataeditdialog.cpp,
+ metadataedit/metadataeditdialog.h,
+ metadataedit/metadataitem.cpp, metadataedit/metadataitem.h:
+ kipiplugins from trunk : MetadataEdit : clean up
+
+2006-11-09 16:32 cgilles
+
+ * [r603659] metadataedit/plugin_metadataedit.cpp,
+ metadataedit/plugin_metadataedit.h:
+ kipiplugins from trunk : MetadataEdit : Added Import EXif and
+ Import IPTC options. Finalize plugin interface with host
+ application. Ask properly to user before to apply definitive
+ changes in metadata from pictures.
+
+ BUG: 136257
+
+2006-11-09 08:06 cgilles
+
+ * [r603482] sendimages/sendimagesdialog.cpp:
+ fix QString
+
+2006-11-09 08:00 cgilles
+
+ * [r603481] sendimages/sendimages.cpp,
+ sendimages/sendimagesdialog.cpp:
+ kipi-plugins from trunk: SendImages plugin: patch from Michael
+ Höchstetter <michael.hoechstetter@gmx.de>:
+
+ - correction of a too big factor (emails hat a maximal size of
+ 10.3 instead
+  of 10 MB)
+ - added a resize factor of 1600 pixels for printing purpose.
+
+2006-11-08 21:37 cgilles
+
+ * [r603423] metadataedit/exifeditdialog.cpp,
+ metadataedit/exifeditdialog.h, metadataedit/iptceditdialog.cpp,
+ metadataedit/iptceditdialog.h:
+ kipi-plugins from trunk : MetadataEdit plugin : Cancel button to
+ Close button
+
+2006-11-07 12:13 cgilles
+
+ * [r602965] NEWS, rawconverter/dcraw.c:
+ kipi-plugins from trunk : RAWConverter : updated dcraw.c
+ implementation to version 8.41
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-05 14:53 anaselli
+
+ * [r602252] AUTHORS:
+ authors revising
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-11-05 00:29 gateau
+
+ * [r602017] htmlexport/generator.cpp:
+ Clean up: moved some code from generateImagesAndXML to a new
+ method.
+
+2006-11-03 12:19 cgilles
+
+ * [r601480] NEWS:
+ update
+
+2006-11-03 12:11 cgilles
+
+ * [r601479] metadataedit/Makefile.am, metadataedit/exifadjust.cpp,
+ metadataedit/exifadjust.h, metadataedit/exifcaption.cpp,
+ metadataedit/exifcaption.h, metadataedit/exifdatetime.cpp,
+ metadataedit/exifdatetime.h, metadataedit/exifdevice.cpp,
+ metadataedit/exifdevice.h, metadataedit/exifeditdialog.cpp,
+ metadataedit/exifeditdialog.h, metadataedit/exiflens.cpp,
+ metadataedit/exiflens.h, metadataedit/exiflight.cpp,
+ metadataedit/exiflight.h, metadataedit/iptccaption.cpp,
+ metadataedit/iptccaption.h, metadataedit/iptccategories.cpp,
+ metadataedit/iptccategories.h, metadataedit/iptccredits.cpp,
+ metadataedit/iptccredits.h, metadataedit/iptcdatetime.cpp,
+ metadataedit/iptcdatetime.h, metadataedit/iptceditdialog.cpp,
+ metadataedit/iptceditdialog.h, metadataedit/iptckeywords.cpp,
+ metadataedit/iptckeywords.h, metadataedit/iptcorigin.cpp,
+ metadataedit/iptcorigin.h, metadataedit/iptcstatus.cpp,
+ metadataedit/iptcstatus.h, metadataedit/iptcsubjects.cpp,
+ metadataedit/iptcsubjects.h,
+ metadataedit/metadataeditdialog.cpp,
+ metadataedit/plugin_metadataedit.cpp,
+ metadataedit/plugin_metadataedit.h:
+ kipi-plugins from trunk : MetadataEdit plugin :
+ - The main dialog is now removed. This one do not give
+ susbtancial informations to user : the host application
+ interface is now used intead and it enough for this plugin.
+ - All user actions are encapsuled into Images/Metadata sub-menu.
+ - Actions are : Edit IPTC, Edit EXIF, Remove IPTC, Remove EXIF.
+ - Add warning message when IPTC/EXIF data are removed from files.
+ - The Editor dialogs are now inspired from old Comment&Tags Edit
+ dialog from digiKam 0.8.x.
+ - TODO : new option to add EXIF/IPTC to a list of picture using
+ a file picture metadata. Of course all the pictures will have
+ the same metadata.
+
+ CCMAIL: digikam-devel@kde.org
+ BUG: 136257
+
+2006-11-03 00:18 vfuoglio
+
+ * [r601365] slideshow/plugin_slideshow.cpp:
+ Fix previous commit
+
+2006-11-02 23:43 vfuoglio
+
+ * [r601358] slideshow/Makefile.am, slideshow/plugin_slideshow.cpp,
+ slideshow/slideshowconfig.cpp, slideshow/slideshowconfig.h,
+ slideshow/slideshowconfigbase.ui:
+ Created, with qtdesigner, slideshowconfigbase dialog for
+ slideshowconfig class.
+ Added me as maintainer.
+ CCMAIL: kde-imaging@kde.org
+ GUI
+
+2006-10-31 21:17 cgilles
+
+ * [r600798] common/exiv2iface/exiv2iface.cpp:
+ revert
+
+2006-10-31 21:10 cgilles
+
+ * [r600795] common/exiv2iface/exiv2iface.cpp:
+ invert
+
+2006-10-31 20:52 cgilles
+
+ * [r600788] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ new method to check if a file is read only with Exiv2
+
+2006-10-31 10:01 cgilles
+
+ * [r600640] gpssync/plugin_gpssync.cpp:
+ show warning message when GPS info will be removed
+
+2006-10-30 09:47 cgilles
+
+ * [r600299] metadataedit/Makefile.am,
+ metadataedit/iptccaption.cpp, metadataedit/iptceditdialog.cpp,
+ metadataedit/iptcsubjects.cpp, metadataedit/iptcsubjects.h:
+ kipiplugins from trunk : MetadataEdit plugin: Fix IPTC Subjects
+ edit method. because IPTC Subjects tags can be repeatable, a new
+ tab have been added for that. This subjects editor do not
+ provide a simple way to edit the IPTC Subjects following the
+ IPTC spec appendix H-J but it resepct the repeatability of
+ values in datasets (witch old implementation do not support).
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-10-30 09:34 cgilles
+
+ * [r600292] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipiplugins from trunk : Exiv2 interface : new methods to
+ set/get IPTC Subjects data.
+
+2006-10-27 07:35 cgilles
+
+ * [r599450] metadataedit/iptcorigin.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: IPTC Origin editor
+ settings use MetadataCheckBox widget.
+
+2006-10-27 07:30 cgilles
+
+ * [r599445] metadataedit/exifcaption.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: if only Exif
+ Editor is used, record too Program ID tags.
+
+2006-10-27 07:16 cgilles
+
+ * [r599442] metadataedit/iptcstatus.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: IPTC Status editor
+ settings use MetadataCheckBox widget.
+
+2006-10-26 19:43 cgilles
+
+ * [r599361] metadataedit/exifadjust.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : Exif Adjustments
+ editor use MetadataCheckBox
+
+2006-10-26 14:36 cgilles
+
+ * [r599290] metadataedit/exiflight.cpp:
+ kipiplugins from trunk : GPSSync plugin: fix Light Source tag
+ value handling
+
+2006-10-26 12:21 cgilles
+
+ * [r599256] metadataedit/exiflight.cpp:
+ kipiplugins from trunk : MetadataEdit plugin : Exif Light editor
+ : add MetadataCheckBox support
+
+2006-10-26 12:11 cgilles
+
+ * [r599253] metadataedit/exifadjust.cpp,
+ metadataedit/exifdevice.cpp, metadataedit/exiflens.cpp,
+ metadataedit/exiflight.cpp:
+ polish
+
+2006-10-26 12:06 cgilles
+
+ * [r599250] metadataedit/exiflens.cpp:
+ kipiplugins from trunk : MetadataEdit plugin : Exif Lens editor
+ : add MetadataCheckBox support
+
+2006-10-26 11:16 cgilles
+
+ * [r599234] metadataedit/metadatacheckbox.cpp,
+ metadataedit/metadatacheckbox.h:
+ add more desc.
+
+2006-10-26 09:14 cgilles
+
+ * [r599205] gpssync/plugin_gpssync.cpp:
+ kipiplugins from trunk : GPSSync plugin: fix error handling
+ during read/write exif metadata from files
+ CCMAIL: kde-imaging@kde.org
+
+2006-10-25 14:12 cgilles
+
+ * [r599038] metadataedit/exifdevice.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Device editor
+ settings use MetadataCheckBox widget.
+
+2006-10-25 13:45 cgilles
+
+ * [r599029] metadataedit/Makefile.am,
+ metadataedit/metadatacheckbox.cpp,
+ metadataedit/metadatacheckbox.h:
+ kipiplugins from trunk : MetadataEdit plugin: new metadata
+ checkbox widget with a flag to be abble to check if the original
+ tag value respect Exif spec.
+
+2006-10-25 11:13 cgilles
+
+ * [r598992] metadataedit/exifdevice.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Device
+ informations editor: add Subject Distance Range settings
+
+ CCBUGS: 103255
+
+2006-10-25 10:39 cgilles
+
+ * [r598987] metadataedit/exifdevice.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Device
+ informations editor: add Scene Capture Type settings
+
+ CCBUGS: 103255
+
+2006-10-25 10:26 cgilles
+
+ * [r598985] metadataedit/exifdevice.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Device
+ informations editor: add File Source settings
+
+ CCBUGS: 103255
+
+2006-10-25 08:58 cgilles
+
+ * [r598974] metadataedit/Makefile.am, metadataedit/exifadjust.cpp,
+ metadataedit/exifcaption.cpp, metadataedit/exifdevice.cpp,
+ metadataedit/exifdevice.h, metadataedit/exifeditdialog.cpp,
+ metadataedit/exifexposure.cpp, metadataedit/exifexposure.h:
+ kipiplugins from trunk : MetadataEdit plugin: rename Exif
+ Exposure to Exif Device. Move 'Make' and 'Model' tags from
+ Caption to Device Editor
+
+2006-10-25 07:46 cgilles
+
+ * [r598965] metadataedit/metadataeditdialog.cpp:
+ fix comments
+
+2006-10-25 07:43 cgilles
+
+ * [r598962] gpssync/gpssyncdialog.cpp, gpssync/plugin_gpssync.cpp:
+ kipiplugins from trunk : GPSSync plugin: refresh Image to
+ updated picture when using 'Edit Geo. Coordinates' and 'Remove
+ Geo. Coordinates' menu options.
+
+2006-10-25 07:32 cgilles
+
+ * [r598960] NEWS:
+ update
+
+2006-10-25 07:30 cgilles
+
+ * [r598959] htmlexport/themes/s0,
+ htmlexport/themes/s0/Makefile.am,
+ htmlexport/themes/s0/arrows_source.svg,
+ htmlexport/themes/s0/next.png,
+ htmlexport/themes/s0/next_disabled.png,
+ htmlexport/themes/s0/previous.png,
+ htmlexport/themes/s0/previous_disabled.png,
+ htmlexport/themes/s0/s0.desktop, htmlexport/themes/s0/style.css,
+ htmlexport/themes/s0/template.xsl, htmlexport/themes/s0/up.png:
+ kipiplugins from trunk : new HTML Export theme named "s0" from
+ Petr Vanek
+ See http://www.yarpen.cz/digikam for details
+ CCMAIL: aurelien.gateau@free.fr
+
+2006-10-24 13:34 cgilles
+
+ * [r598749] metadataedit/exifeditdialog.cpp:
+ i18n
+
+2006-10-24 13:14 cgilles
+
+ * [r598747] metadataedit/exifexposure.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Exposure
+ informations editor: add Sensing Method settings
+
+ CCBUGS: 103255
+
+2006-10-24 12:43 cgilles
+
+ * [r598741] metadataedit/exifadjust.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Picture
+ Adjustments informations editor: add Custom Rendered settings
+
+ CCBUGS: 103255
+
+2006-10-24 12:26 cgilles
+
+ * [r598736] metadataedit/exifadjust.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Picture
+ Adjustments informations editor: add Sharpness settings
+
+ CCBUGS: 103255
+
+2006-10-24 12:21 cgilles
+
+ * [r598735] metadataedit/exifadjust.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Picture
+ Adjustments informations editor: add Saturation settings
+
+ CCBUGS: 103255
+
+2006-10-24 12:15 cgilles
+
+ * [r598734] metadataedit/exifadjust.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Picture
+ Adjustments informations editor: add Contrast settings
+
+ CCBUGS: 103255
+
+2006-10-24 12:09 cgilles
+
+ * [r598732] metadataedit/Makefile.am, metadataedit/exifadjust.cpp,
+ metadataedit/exifadjust.h, metadataedit/exifeditdialog.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: add Exif Picture
+ Adjustments informations editor
+
+ CCBUGS: 103255
+
+2006-10-24 11:02 cgilles
+
+ * [r598657] metadataedit/exifexposure.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Exposure
+ informations editor: handle Exposure Index settings accordinly
+ with ISO Speed Rating settings
+
+ CCBUGS: 103255
+
+2006-10-24 10:53 cgilles
+
+ * [r598656] metadataedit/exifexposure.cpp:
+ i18n
+
+2006-10-24 10:47 cgilles
+
+ * [r598655] metadataedit/exifexposure.cpp,
+ metadataedit/exiflens.cpp, metadataedit/exiflight.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Exposure
+ informations editor: add Exposure Bias Value settings
+
+ CCBUGS: 103255
+
+2006-10-24 10:27 cgilles
+
+ * [r598651] metadataedit/exiflens.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Lens
+ informations editor: add Digital Zoom Ratio settings
+
+ CCBUGS: 103255
+
+2006-10-24 09:36 cgilles
+
+ * [r598637] metadataedit/Makefile.am,
+ metadataedit/exifeditdialog.cpp, metadataedit/exifexposure.cpp,
+ metadataedit/exifexposure.h, metadataedit/exiflens.cpp,
+ metadataedit/exiflens.h, metadataedit/exiflight.cpp,
+ metadataedit/exiflight.h, metadataedit/exifphoto.cpp,
+ metadataedit/exifphoto.h:
+ kipiplugins from trunk : MetadataEdit plugin: separate Exif
+ photo informations to 3 sub-categories : Lens, Exposure, and
+ Light
+
+ CCBUGS: 103255
+
+2006-10-24 08:05 cgilles
+
+ * [r598626] gpssync/plugin_gpssync.cpp:
+ i18n
+
+2006-10-24 08:00 cgilles
+
+ * [r598625] gpssync/gpseditdialog.cpp, gpssync/plugin_gpssync.cpp,
+ gpssync/plugin_gpssync.h:
+ kipiplugins from trunk : GPSSync plugin:
+
+ plugin now provides 3 sub-menu entries (instead just one) :
+
+ - Start GPS device correlator using current pictures selection.
+ - Start Geographical Coordinates editor to tag current pictures
+ selection.
+ - Remove Geographical Coordinates from current pictures selection
+
+ CCBUGS: 135451
+ CCMAIL: kde-imaging@kde.org, digikam-devel@kde.org
+
+2006-10-23 14:16 cgilles
+
+ * [r598409] metadataedit/exifphoto.cpp:
+ i18n
+
+2006-10-23 14:12 cgilles
+
+ * [r598407] metadataedit/exifphoto.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif photo
+ informations editor: add Flash Energy settings
+
+ CCBUGS: 103255
+
+2006-10-23 13:20 cgilles
+
+ * [r598395] metadataedit/exifphoto.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif photo
+ informations editor: add Focal Lenght In 35mm Film settings
+
+ CCBUGS: 103255
+
+2006-10-23 12:59 cgilles
+
+ * [r598385] metadataedit/exifphoto.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif photo
+ informations editor: add White Balance settings
+
+ CCBUGS: 103255
+
+2006-10-23 12:42 cgilles
+
+ * [r598380] metadataedit/exifphoto.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif photo
+ informations editor: control Aperture Value tag with FNumber tag
+
+ CCBUGS: 103255
+
+2006-10-23 12:15 cgilles
+
+ * [r598367] metadataedit/exifphoto.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif photo
+ informations editor: control Shutter Speed Value tag with
+ Exposure Time tag
+
+ CCBUGS: 103255
+
+2006-10-23 09:17 anaselli
+
+ * [r598335] mpegencoder/Makefile.am:
+ fixed wrong commit
+
+2006-10-23 08:58 cgilles
+
+ * [r598331] metadataedit/exifphoto.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif photo
+ informations editor: added Max Aperture Value settings.
+
+ CCBUGS: 103255
+
+2006-10-23 06:37 cgilles
+
+ * [r598284] metadataedit/exifphoto.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif photo
+ informations editor: Fix Aperture values controls again (ex.
+ F2.8 ==> f/2.8)
+
+2006-10-23 06:00 cgilles
+
+ * [r598278] metadataedit/exifphoto.cpp:
+ fix header
+
+2006-10-22 21:38 anaselli
+
+ * [r598211] mpegencoder/Makefile.am, mpegencoder/kimg2mpg.cpp:
+ - Used new KPAboutData
+ - Added me as a contributor
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-10-22 18:58 cgilles
+
+ * [r598173] metadataedit/metadataeditdialog.cpp,
+ metadataedit/metadataitem.cpp:
+ moved status info to Exif and Iptc col.
+
+2006-10-22 08:08 cgilles
+
+ * [r597975] metadataedit/metadataitem.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : Finalize plugin
+
+ BUG: 91812, 103255
+
+2006-10-22 07:51 cgilles
+
+ * [r597969] metadataedit/iptckeywords.cpp:
+ typo again (:=)))
+
+2006-10-21 21:40 anaselli
+
+ * [r597868] common/Makefile.am, common/include/kpaboutdata.h,
+ common/libkipiplugins/Makefile.am,
+ common/libkipiplugins/kpaboutdata.cpp, configure.in.in:
+ Added new libkipiplugins common library
+ - KPAboutData to be used into AboutDialog of each plugins
+
+ Please test, use and improve it
+ CCMAIL: kde-imaging@kde.org
+
+2006-10-21 21:29 anaselli
+
+ * [r597864] common/libkipiplugins:
+ libkipiplugins directory for kipi-plugins common dialogs
+
+2006-10-21 19:20 cgilles
+
+ * [r597836] metadataedit/iptckeywords.cpp:
+ typo
+
+2006-10-20 18:07 dfaure
+
+ * [r597552] gpssync/gpssyncdialog.cpp:
+ You can't use \n in a message with a plural form, since the \n
+ is the delimiter between translations
+ (plus it was even used inconsistently)
+
+2006-10-20 14:03 cgilles
+
+ * [r597484] metadataedit/exifphoto.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Exposure
+ informations editor: Fix Aperture values controls
+
+2006-10-20 12:59 cgilles
+
+ * [r597468] metadataedit/exifphoto.cpp:
+ i18n
+
+2006-10-20 12:58 cgilles
+
+ * [r597465] metadataedit/Makefile.am,
+ metadataedit/exifeditdialog.cpp, metadataedit/exifexposure.cpp,
+ metadataedit/exifexposure.h, metadataedit/exifphoto.cpp,
+ metadataedit/exifphoto.h:
+ kipiplugins from trunk : MetadataEdit plugin: exifexposure ==>
+ exifphoto
+
+2006-10-20 12:48 cgilles
+
+ * [r597460] metadataedit/exifexposure.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Exposure
+ informations editor: added Flash Mode settings.
+
+ CCBUGS: 103255
+
+2006-10-20 11:11 cgilles
+
+ * [r597432] metadataedit/exifexposure.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Exposure
+ informations editor: added lens Focal Length settings.
+
+ CCBUGS: 103255
+
+2006-10-20 09:40 cgilles
+
+ * [r597411] metadataedit/exifexposure.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Exposure
+ informations editor: added Aperture (F-number) settings.
+
+ CCBUGS: 103255
+
+2006-10-20 09:39 cgilles
+
+ * [r597410] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipiplugins from trunk : Exiv2 interface: using long int instead
+ int with num and den extracted from Rational values
+
+2006-10-20 05:39 aumuell
+
+ * [r597364] ipodexport/ipodexportdialog.cpp:
+ use SizeHuge instead of SizeEnormous icons below buttons in
+ order to not exceed height of 768 pixels
+
+2006-10-19 19:59 cgilles
+
+ * [r597277] metadataedit/exifexposure.cpp:
+ fix layout
+
+2006-10-19 19:41 cgilles
+
+ * [r597265] metadataedit/exifexposure.cpp:
+ fix Light Source settings rules
+
+2006-10-19 19:20 cgilles
+
+ * [r597256] metadataedit/exifexposure.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : Exif Exposure
+ editor : add Light Source settings
+
+ CCBUGS: 103255
+
+2006-10-19 18:55 cgilles
+
+ * [r597251] metadataedit/exifeditdialog.cpp,
+ metadataedit/iptceditdialog.cpp:
+ i18n
+
+2006-10-19 18:53 cgilles
+
+ * [r597250] metadataedit/exifeditdialog.cpp:
+ i18n
+
+2006-10-19 18:50 cgilles
+
+ * [r597249] metadataedit/exifexposure.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : Exif Exposure
+ editor : add Metering Mode settings
+
+ CCBUGS: 103255
+
+2006-10-18 20:29 cgilles
+
+ * [r596893] metadataedit/exifexposure.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : Exif Exposure
+ editor : add ISO speed ratings settings
+
+ CCBUGS: 103255
+
+2006-10-18 17:25 cgilles
+
+ * [r596848] metadataedit/exifexposure.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : Exif Exposure
+ editor : add Exposure Mode settings
+
+ CCBUGS: 103255
+
+2006-10-18 17:00 cgilles
+
+ * [r596842] metadataedit/exifexposure.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : Exif Exposure
+ editor : add Exposure Program settings
+
+ CCBUGS: 103255
+
+2006-10-18 16:52 cgilles
+
+ * [r596840] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipi-plugins from trunk : Exiv2 Interface : new methods to
+ add/remove EXIF long tag values
+
+2006-10-18 14:28 cgilles
+
+ * [r596795] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipiplugins from trunk : Exiv2 interface: New method set/unset
+ Exif tag rational value
+
+2006-10-18 14:27 cgilles
+
+ * [r596794] metadataedit/Makefile.am,
+ metadataedit/exifeditdialog.cpp, metadataedit/exifexposure.cpp,
+ metadataedit/exifexposure.h:
+ kipiplugins from trunk : MetadataEdit plugin: started Exif
+ Exposure informations editor. Not yet complete
+
+ CCBUGS: 103255
+
+2006-10-18 13:09 seb
+
+ * [r596775] ipodexport/ipodexportdialog.cpp:
+ Change the hdd icon to a system icon
+
+2006-10-18 11:40 cgilles
+
+ * [r596732] metadataedit/exifdatetime.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Date & Time
+ informations editor support now sub-seconds time values.
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 103255
+
+2006-10-18 09:00 cgilles
+
+ * [r596705] metadataedit/Makefile.am,
+ metadataedit/exifdatetime.cpp, metadataedit/exifdatetime.h,
+ metadataedit/exifeditdialog.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Date & Time
+ informations editor is fully implemented.
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 103255
+
+2006-10-18 07:45 cgilles
+
+ * [r596693] metadataedit/metadataeditdialog.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: capabaility to
+ load EXIF metadata from a specific picture and apply it to a
+ list of pictures
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 103255
+
+2006-10-18 07:39 cgilles
+
+ * [r596690] metadataedit/iptccategories.cpp,
+ metadataedit/iptcdatetime.cpp, metadataedit/iptckeywords.cpp,
+ metadataedit/metadataeditdialog.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: fix IPTC editor
+ i18n following Mikolaj Machowski tips.
+
+ CCBUGS: 91812
+
+2006-10-18 07:29 cgilles
+
+ * [r596688] metadataedit/exifcaption.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: Exif Caption
+ informations editor is fully implemented.
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 103255
+
+2006-10-18 07:03 cgilles
+
+ * [r596680] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipiplugins from trunk : Exiv2 interface: New method backported
+ from digiKam core to get/set Exif user Comment. Give credit to
+ Marcel
+
+2006-10-17 22:35 seb
+
+ * [r596599] ipodexport/imagelist.cpp, ipodexport/imagelist.h,
+ ipodexport/ipodexportdialog.cpp, ipodexport/ipodexportdialog.h:
+ Merge my long overdue local changes to the ipod export. I've
+ refactored a little bit of it to ensure that the plugin can be
+ used as a standalone application for when that time comes.
+ I also seemed to lose the "About Data" which colin added, but it
+ wouldn't compile either, so i'll look into that a little later.
+
+2006-10-17 20:01 cgilles
+
+ * [r596525] metadataedit/exifcaption.cpp,
+ metadataedit/exifeditdialog.cpp:
+ Exif metadata editor GUI implemented.
+
+2006-10-17 14:45 cgilles
+
+ * [r596449] metadataedit/exifcaption.cpp:
+ compile
+
+2006-10-17 14:45 cgilles
+
+ * [r596448] metadataedit/Makefile.am,
+ metadataedit/exifcaption.cpp, metadataedit/exifcaption.h:
+ kipiplugins from trunk : MetadataEdit plugin: add EXIF caption
+ page (not yet complete)
+
+2006-10-17 14:35 cgilles
+
+ * [r596444] metadataedit/Makefile.am,
+ metadataedit/exifeditdialog.cpp, metadataedit/exifeditdialog.h,
+ metadataedit/metadataeditdialog.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: starting
+ implementation of EXIF editor
+
+2006-10-17 13:54 cgilles
+
+ * [r596432] metadataedit/metadataeditdialog.cpp:
+ fix i18n
+
+2006-10-17 13:52 cgilles
+
+ * [r596431] metadataedit/metadataeditdialog.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: capabaility to
+ load IPTC metadata from a specific picture and apply it to a
+ list of pictures
+
+2006-10-17 11:47 cgilles
+
+ * [r596404] NEWS:
+ update
+
+2006-10-17 09:53 cgilles
+
+ * [r596376] metadataedit/iptcorigin.cpp:
+ fix country code decoding
+
+2006-10-17 09:06 cgilles
+
+ * [r596365] metadataedit/iptccategories.cpp:
+ fix i18n
+
+2006-10-17 08:59 cgilles
+
+ * [r596364] metadataedit/iptcstatus.cpp:
+ add comment
+
+2006-10-17 08:58 cgilles
+
+ * [r596363] metadataedit/iptcstatus.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: store host app
+ name and version in IPTC ProgramName tag
+
+2006-10-17 08:35 cgilles
+
+ * [r596354] metadataedit/iptcorigin.cpp:
+ kipiplugins from trunk : MetadataEdit plugin: IPTC Origin
+ informations editor now support all country codes define by
+ ISO-3166 norm.
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-16 11:06 cgilles
+
+ * [r595975] metadataedit/iptcstatus.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : polish source
+ code : set automaticly IPTC Program/version tags
+
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-16 09:50 cgilles
+
+ * [r595961] metadataedit/iptcstatus.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : add
+ ObjectAttribute IPTC tag to status editor page.
+
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-16 09:02 cgilles
+
+ * [r595953] metadataedit/iptcstatus.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : add ObjectType
+ IPTC tag to status editor page.
+
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-16 07:51 cgilles
+
+ * [r595936] metadataedit/iptccategories.cpp:
+ compile
+
+2006-10-16 07:50 cgilles
+
+ * [r595935] metadataedit/iptccategories.cpp,
+ metadataedit/iptckeywords.cpp:
+ kipi-plugins from trunk : add whatthis
+
+2006-10-16 07:38 cgilles
+
+ * [r595932] metadataedit/iptccategories.cpp,
+ metadataedit/iptccategories.h:
+ kipi-plugins from trunk : MetadataEdit plugin : IPTC Categories
+ editor page is now implemented.
+
+ CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-16 07:26 cgilles
+
+ * [r595930] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipi-plugins from trunk : Exiv2Iface : new methods to add/remove
+ IPTC Sub-Categories
+
+2006-10-16 07:03 cgilles
+
+ * [r595926] metadataedit/Makefile.am,
+ metadataedit/iptceditdialog.cpp, metadataedit/iptcorigin.cpp:
+ typo
+
+2006-10-15 16:32 cgilles
+
+ * [r595781] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipi-plugins from trunk : Exiv2Iface : backport methods from
+ digiKam core to add/remove IPTC keywords
+
+2006-10-15 16:31 cgilles
+
+ * [r595780] metadataedit/Makefile.am,
+ metadataedit/iptceditdialog.cpp, metadataedit/iptckeywords.cpp,
+ metadataedit/iptckeywords.h:
+ kipi-plugins from trunk : MetadataEdit plugin : IPTC Keywords
+ editor page is now implemented.
+
+ CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-14 12:54 cgilles
+
+ * [r595477] metadataedit/iptcorigin.cpp:
+ kipi-plugins from trunk : IPTC origin page can set/unset tags
+
+2006-10-14 12:34 cgilles
+
+ * [r595475] metadataedit/iptcstatus.cpp:
+ kipi-plugins from trunk : IPTC status page can set/unset tags
+
+2006-10-14 11:49 cgilles
+
+ * [r595464] metadataedit/iptccredits.cpp:
+ kipi-plugins from trunk : IPTC credit page can set/unset tags
+
+2006-10-13 20:41 cgilles
+
+ * [r595284] metadataedit/iptccaption.cpp:
+ capbility to set/unset IPTC Caption tags from metadata
+
+2006-10-13 19:11 cgilles
+
+ * [r595263] metadataedit/metadataeditdialog.cpp:
+ typo
+
+2006-10-13 14:32 cgilles
+
+ * [r595212] metadataedit/iptcorigin.cpp:
+ kipiplugins from trunk : MetadataEdit plugin:
+
+ Missing IPTC LocationName and LocationCode tags.
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-13 14:11 cgilles
+
+ * [r595205] metadataedit/iptccaption.cpp,
+ metadataedit/iptccredits.cpp:
+ kipiplugins from trunk : MetadataEdit plugin:
+
+ Missing IPTC Contact and Subject tags.
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-13 13:50 cgilles
+
+ * [r595193] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipi-plugins from trunk : new methods to remove Exif or Iptc tag
+
+2006-10-13 13:49 cgilles
+
+ * [r595192] metadataedit/Makefile.am,
+ metadataedit/iptcdatetime.cpp, metadataedit/iptcdatetime.h,
+ metadataedit/iptceditdialog.cpp:
+ kipiplugins from trunk : MetadataEdit plugin:
+
+ Added IPTC Date & Time informations in IPTC Edit dialog
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-13 12:09 cgilles
+
+ * [r595152] metadataedit/Makefile.am,
+ metadataedit/iptceditdialog.cpp, metadataedit/iptceditdialog.h,
+ metadataedit/iptcorigin.cpp, metadataedit/iptcorigin.h:
+ kipiplugins from trunk : MetadataEdit plugin:
+
+ Added IPTC Origin informations in IPTC Edit dialog
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-13 09:16 cgilles
+
+ * [r595071] metadataedit/Makefile.am,
+ metadataedit/iptccredits.cpp, metadataedit/iptceditdialog.cpp,
+ metadataedit/iptcstatus.cpp, metadataedit/iptcstatus.h:
+ kipiplugins from trunk : MetadataEdit plugin:
+
+ Added IPTC Status informations in IPTC Edit dialog
+
+ CCMAIL: kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-13 07:43 cgilles
+
+ * [r595034] metadataedit/metadataitem.cpp:
+ kipi-plugins from trunk : MetadataEdit plugin : to be able to
+ clear Exif or Iptc metadata
+
+2006-10-13 07:40 cgilles
+
+ * [r595033] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipi-plugins from trunk : new methods to clear Exif or Iptc
+ metadata
+
+2006-10-13 07:20 cgilles
+
+ * [r595027] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipiplugins from trunk : Exiv2Iface update : to be able to
+ set/get IPTC/exif text tags
+
+2006-10-13 07:19 cgilles
+
+ * [r595026] metadataedit/iptccaption.cpp,
+ metadataedit/iptccredits.cpp, metadataedit/iptceditdialog.cpp,
+ metadataedit/metadataeditdialog.cpp,
+ metadataedit/metadataitem.cpp:
+ kipiplugins from trunk : MetadataEdit plugin:
+
+ "Et Voila"... The IPTC metadata can be changed/set from
+ pictures. The IPTC data set to edit is not yet complete, but a
+ more complete edit dialog coming soon...
+
+ CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-13 05:30 cgilles
+
+ * [r595011] metadataedit/iptccaption.cpp,
+ metadataedit/iptccaption.h, metadataedit/iptccredits.cpp,
+ metadataedit/iptccredits.h, metadataedit/iptceditdialog.cpp:
+ Fix read/save metadata methods
+
+2006-10-12 20:30 cgilles
+
+ * [r594928] README:
+ update
+
+2006-10-12 19:24 cgilles
+
+ * [r594900] Makefile.am:
+ update
+
+2006-10-12 19:23 cgilles
+
+ * [r594899] metadataedit, metadataedit/Makefile.am,
+ metadataedit/iptccaption.cpp, metadataedit/iptccaption.h,
+ metadataedit/iptccredits.cpp, metadataedit/iptccredits.h,
+ metadataedit/iptceditdialog.cpp, metadataedit/iptceditdialog.h,
+ metadataedit/kipiplugin_metadataedit.desktop,
+ metadataedit/metadataeditdialog.cpp,
+ metadataedit/metadataeditdialog.h,
+ metadataedit/metadataitem.cpp, metadataedit/metadataitem.h,
+ metadataedit/plugin_metadataedit.cpp,
+ metadataedit/plugin_metadataedit.h:
+ kipiplugins from trunk : new plugin to edit EXIF photograph tags
+ and IPTC tags of pictures
+ This tool can be used on single or batch mode.
+
+ Note: this plugin is under developement. It's not yet suitable.
+
+ CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org
+ CCBUGS: 91812, 133276, 103255
+
+2006-10-12 12:40 cgilles
+
+ * [r594825] ipodexport/Makefile.am,
+ ipodexport/ipodexportdialog.cpp, ipodexport/ipodexportdialog.h:
+ kipi-plugins from trunk: iPod Export plugin : just add standard
+ main dialog Help menu like others plugins witch provide :
+
+ - kipi-plugins release number.
+ - link to the right bug report in B.K.O
+ - info about author
+ - link to the future handbook.
+
+2006-10-12 10:38 cgilles
+
+ * [r594790] NEWS:
+ update
+
+2006-10-12 10:37 cgilles
+
+ * [r594789] gpssync/gpssyncdialog.cpp,
+ gpssync/kipiplugin_gpssync.desktop, gpssync/plugin_gpssync.cpp:
+ kipi-plugins from trunk : using 'geolocalization' to naming
+ GPSSync plugin on hosts.
+ BUG: 135353
+
+2006-10-12 10:35 cgilles
+
+ * [r594788] README:
+ update
+
+2006-10-12 08:51 cgilles
+
+ * [r594769] NEWS:
+ update
+
+2006-10-12 06:55 cgilles
+
+ * [r594746] gpssync/gpslistviewitem.cpp:
+ kipiplugins from trunk : GPSSync : missing to pass parent
+ instance to QObject.
+ This can cause broken dispatch events.
+
+ Please, let's me hear if this patch fix the problem. I have
+ located others implementations
+ where this problem exist.
+
+ CCBUGS: 135484
+
+2006-10-11 13:24 cgilles
+
+ * [r594499] gpssync/gpssyncdialog.cpp:
+ polish
+
+2006-10-11 11:31 cgilles
+
+ * [r594457] jpeglossless/utils.cpp, rawconverter/dcrawiface.cpp,
+ rawconverter/plugin_rawconverter.cpp:
+ kipi-plugins from trunk : Raw converter and JPEGLossLess plugin
+ don't check properly the filenale extension.
+ CCBUGS: 135237
+
+2006-10-11 11:23 cgilles
+
+ * [r594452] NEWS:
+ update
+
+2006-10-11 11:18 cgilles
+
+ * [r594449] gpssync/gpslistviewitem.cpp,
+ gpssync/gpssyncdialog.cpp:
+ polish read only pictures status rule
+
+2006-10-11 08:03 cgilles
+
+ * [r594416] gpssync/gpslistviewitem.cpp,
+ gpssync/gpssyncdialog.cpp:
+ polish
+
+2006-10-11 07:46 cgilles
+
+ * [r594412] gpssync/gpssyncdialog.cpp:
+ typo
+
+2006-10-11 07:43 cgilles
+
+ * [r594410] gpssync/gpssyncdialog.cpp:
+ typo
+
+2006-10-11 07:39 cgilles
+
+ * [r594409] gpssync/gpssyncdialog.cpp:
+ polish
+
+2006-10-11 07:37 cgilles
+
+ * [r594408] gpssync/gpssyncdialog.cpp:
+ polish
+
+2006-10-11 07:33 cgilles
+
+ * [r594406] gpssync/gpssyncdialog.cpp, gpssync/gpssyncdialog.h:
+ polish
+
+2006-10-11 06:49 cgilles
+
+ * [r594401] gpssync/plugin_gpssync.h:
+ polish
+
+2006-10-11 06:40 cgilles
+
+ * [r594398] gpssync/plugin_gpssync.cpp, gpssync/plugin_gpssync.h:
+ polish
+
+2006-10-11 05:52 cgilles
+
+ * [r594388] rawconverter/savesettingswidget.cpp:
+ kipi-plugins from trunk : fix automaticly to automatically
+ BUG:135430
+
+2006-10-10 14:15 cgilles
+
+ * [r594212] gpssync/gpslistviewitem.cpp,
+ gpssync/gpslistviewitem.h, gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : GPSSync : to be able to handle Read
+ Only pictures file format. Just to display GPS location if it
+ available.
+
+2006-10-10 12:35 cgilles
+
+ * [r594192] rawconverter/Makefile.am, rawconverter/dcraw.c,
+ rawconverter/dcrawbinary.cpp, rawconverter/dcrawiface.cpp,
+ rawconverter/plugin_rawconverter.cpp:
+ kipi-plugins from trunk : RAW Converter : bye bye external dcraw
+ depency :
+
+ Raw onverter plugin use a dedicaced dcraw binary program to run.
+ This is mandatory since dcraw author have broken the command
+ line options
+ compatibility with the 8.x serie.
+
+ Also, dcraw is not available like a library!
+
+ The dcraw.c source code embeded in plugin is just a copy of
+ official implementation, but this one have been completly tested
+ with plugin.
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-10-10 12:30 cgilles
+
+ * [r594189] NEWS, README:
+ update
+
+2006-10-08 17:02 cguthrie
+
+ * [r593666] galleryexport/Makefile.am,
+ galleryexport/exifrestorer.cpp, galleryexport/exifrestorer.h,
+ galleryexport/gallerytalker.cpp, galleryexport/jpegsection.h:
+ Convert to Exiv2 Exif restorer.
+ CCBUG: 129856
+
+2006-10-08 12:56 cguthrie
+
+ * [r593599] configure.in.in:
+ iPod Export requires libgpod 0.4.0+
+
+2006-10-08 12:25 cguthrie
+
+ * [r593587] configure.in.bot:
+ Fix small copy/paste typo in the message relating Exiv2 not
+ being found.
+
+2006-10-05 21:15 anaselli
+
+ * [r592815] NEWS, sendimages/plugin_sendimages.cpp,
+ sendimages/sendimages.cpp, sendimages/sendimages.h,
+ sendimages/sendimagesdialog.cpp, sendimages/sendimagesdialog.h:
+ Added size limit per mail (by Michael Höchstetter)
+ Added a check if at least one image has been added to a mail
+
+ CCMAIL: kde-imaging@kde.org, michael.hoechstetter@gmx.de
+
+2006-10-05 16:31 cgilles
+
+ * [r592758] NEWS:
+ update
+
+2006-10-05 16:29 cgilles
+
+ * [r592757] gpssync/gpssyncdialog.cpp:
+ typo
+
+2006-10-05 16:28 cgilles
+
+ * [r592756] gpssync/gpslistviewitem.cpp:
+ Fix disty status when Metadata are written in pictures.
+
+ BUG:135157
+
+2006-10-05 16:20 cgilles
+
+ * [r592750] NEWS:
+ update
+
+2006-10-05 07:41 cgilles
+
+ * [r592623] gpssync/gpssyncdialog.cpp, gpssync/gpssyncdialog.h:
+ kipi-plugins from trunk : GPSSync : if one image is dirty from
+ the list, closing dialog will please user to take a care about
+ to apply pictures changes
+
+2006-10-05 07:34 cgilles
+
+ * [r592621] jpeglossless/jpegtransform.cpp:
+ wrong commit. revert
+
+2006-10-05 07:32 cgilles
+
+ * [r592620] gpssync/gpssyncdialog.cpp,
+ jpeglossless/jpegtransform.cpp:
+ kipi-plugins from trunk : GPSSync : if one image is dirty from
+ the list, closing dialog will please user to take a care about
+ to apply pictures changes
+
+2006-10-05 07:03 cgilles
+
+ * [r592615] gpssync/Makefile.am, jpeglossless/Makefile.am,
+ rawconverter/Makefile.am, timeadjust/Makefile.am:
+ kipi-plugins from trunk : check libexiv2iface depency when it's
+ mandatory
+
+2006-10-04 10:25 anaselli
+
+ * [r592295] acquireimages/Makefile.am,
+ batchprocessimages/Makefile.am, calendar/Makefile.am,
+ cdarchiving/Makefile.am, common/exiv2iface/Makefile.am,
+ configure.in.in, findimages/Makefile.am,
+ flickrexport/Makefile.am, galleryexport/Makefile.am,
+ gpssync/Makefile.am, htmlexport/Makefile.am,
+ imagesgallery/Makefile.am, jpeglossless/Makefile.am,
+ kameraklient/Makefile.am, mpegencoder/Makefile.am,
+ printwizard/Makefile.am, rawconverter/Makefile.am,
+ sendimages/Makefile.am, simpleviewerexport/Makefile.am,
+ slideshow/Makefile.am, timeadjust/Makefile.am:
+ fix problem using automake & co.
+ - added KIPI_PLUGINS_COMMON_INCLUDE into configure.in.in
+ (please test it for regressions)
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-10-04 10:23 cgilles
+
+ * [r592292] common/exiv2iface/exiv2iface.cpp:
+ kipi-plugins from trunk : bugfix in altitude and longitude
+ decoding
+
+2006-10-03 10:19 cgilles
+
+ * [r591843] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ kipi-plugins from trunk : Exiv2 interface : fix lat/lon/alt GPS
+ ref extraction
+
+2006-10-03 10:18 cgilles
+
+ * [r591842] gpssync/gpslistviewitem.cpp,
+ gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : GPSSync : re-design list view contents
+ like Sony GPS Image tracker do.
+
+2006-10-03 07:38 cgilles
+
+ * [r591810] common/exiv2iface/exiv2iface.cpp:
+ kipi-plugins from trunk : fix broken GPS location decoding using
+ current Exiv2 implementation. Backport getGPSInfo method from
+ digikam core
+
+2006-10-02 13:26 cgilles
+
+ * [r591457] gpssync/getlonlat.php, gpssync/gpsmapwidget.cpp:
+ kipi-plugins from trunk : GPSSync tool : fix php script
+ parameters
+
+2006-10-02 12:46 cgilles
+
+ * [r591444] gpssync/gpsmapwidget.cpp:
+ kipi-plugins from trunk: GPSSync: Fix broken mouse release event
+ with google map widget. Thanks to Marcel for this report
+
+2006-10-01 18:18 cgilles
+
+ * [r591107] gpssync/gpseditdialog.cpp:
+ fix typo
+
+2006-09-30 12:55 cgilles
+
+ * [r590552] gpssync/gpsmapwidget.cpp:
+ using Safari browser is do not improve gg maps rendering
+
+2006-09-30 12:33 cgilles
+
+ * [r590544] gpssync/gpsmapwidget.cpp:
+ force KHTLMPart to use safari browser id with google maps
+
+2006-09-30 09:09 cgilles
+
+ * [r590455] NEWS:
+ update
+
+2006-09-30 09:03 cgilles
+
+ * [r590452] gpssync/gpsdataparser.cpp:
+ kipi-plugins from trunk : GPSSync : optimize GPX data parsing to
+ search the minimal diff time.
+
+ Fabien, your patch is not optimum because it don't check all
+ items in the list. In fact if the date list of GPS point isn't
+ sorted using time stamp, your optimization don't work.
+
+ Of course i will very surprise if the gps data list is not
+ sorted in time (:=))). But like I have none experience with GPS
+ data, we must care about this point.
+
+ Please test this patch indeep and give me your feedback. Thanks
+ in advance.
+
+ CCBUGS: 134747
+
+2006-09-29 13:15 cgilles
+
+ * [r590188] gpssync/gpseditdialog.cpp:
+ fix typo
+
+2006-09-29 13:12 cgilles
+
+ * [r590187] gpssync/gpseditdialog.cpp:
+ fix typo
+
+2006-09-29 12:45 cgilles
+
+ * [r590177] gpssync/gpseditdialog.cpp, gpssync/gpseditdialog.h,
+ gpssync/gpslistviewitem.cpp, gpssync/gpslistviewitem.h,
+ gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : GPSSync tool : set properly the map
+ zoom level if picture don't have GPS info
+
+2006-09-29 12:32 cgilles
+
+ * [r590169] gpssync/gpseditdialog.h, gpssync/gpsmapwidget.cpp,
+ gpssync/gpsmapwidget.h:
+ using d private internal class
+
+2006-09-29 12:28 cgilles
+
+ * [r590167] gpssync/getlonlat.php, gpssync/gpsmapwidget.cpp:
+ kipi-plugins from trunk : GPSSync tool : handle properly the
+ zoom level from the Google Maps
+
+2006-09-29 11:51 cgilles
+
+ * [r590155] gpssync/getlonlat.php, gpssync/gpsmapwidget.cpp,
+ gpssync/gpsmapwidget.h:
+ remember map zoom level if map is resized.
+
+2006-09-29 10:10 cgilles
+
+ * [r590113] gpssync/gpseditdialog.h:
+ compile with GCC 4.1
+
+2006-09-29 10:04 cgilles
+
+ * [r590109] gpssync/getlonlat.php, gpssync/gpseditdialog.cpp,
+ gpssync/gpseditdialog.h, gpssync/gpsmapwidget.cpp,
+ gpssync/gpsmapwidget.h:
+ kipi-plugins from trunk : GPSSync tool : The GPS location editor
+ dialog now display the Google Maps view like a real widget,
+ without margin and depending of the dialog size. If you reduce
+ or increase dialog size, the world map size will be updated in
+ live.
+
+ CCMAIL: gerhard@kulzer.net, kde-imaging@ke.org
+
+ BUG: 133359
+ CCBUGS: 111560
+
+2006-09-28 21:15 cgilles
+
+ * [r589881] gpssync/gpsmapwidget.cpp:
+ fix html property
+
+2006-09-28 21:11 cgilles
+
+ * [r589879] gpssync/gpseditdialog.cpp, gpssync/gpseditdialog.h,
+ gpssync/gpsmapwidget.cpp, gpssync/gpsmapwidget.h:
+ reduce signal emits to check new lat. lon. from map before to
+ send it
+
+2006-09-28 20:57 cgilles
+
+ * [r589877] gpssync/gpseditdialog.cpp:
+ fix layout
+
+2006-09-28 20:53 cgilles
+
+ * [r589875] gpssync/gpseditdialog.cpp, gpssync/gpseditdialog.h:
+ fix events to use to save settings properly.
+
+2006-09-28 14:12 cgilles
+
+ * [r589712] gpssync/gpseditdialog.cpp, gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : GPSSync tool : fix signals from buttons
+
+2006-09-28 14:07 cgilles
+
+ * [r589704] gpssync/gpseditdialog.cpp:
+ kipi-plugins from trunk : GPSSync tool : fix layout
+
+2006-09-28 10:51 cgilles
+
+ * [r589554] gpssync/Makefile.am, gpssync/getlonlat.php,
+ gpssync/gpseditdialog.cpp, gpssync/gpseditdialog.h,
+ gpssync/gpsmapwidget.cpp, gpssync/gpsmapwidget.h:
+ kipi-plugins from trunk : GPSSync tool : The GPS location editor
+ dialognow use a dediced Google Maps to select the right place
+ where have been taken the pictures.
+
+ Improvements :
+
+ - If the current picture already have GPS coordinates, the map
+ will pan to the right place automaiticly at session startup!
+
+ - The GPS coordinates are automaticly captured by the dialog
+ when the user right click on the map ! There is nothing to do
+ manually to set the GPS location...
+
+ Angelo: with this plugin, i'm using a little php script to
+ handle the google map with is interfaced with the plugin dialog
+ ! This php script is hosted actually in a 3rd party digikam
+ page. I would to host this page in the new kipi-plugins web
+ project page. Can you help me ?
+
+ Noe : there is a copy of php script in svn.
+
+ CCMAIL: gerhard@kulzer.net, kde-imaging@ke.org
+
+ BUG: 133359
+ CCBUGS: 111560
+
+2006-09-28 06:47 cgilles
+
+ * [r589488] gpssync/gpseditdialog.cpp, gpssync/gpseditdialog.h,
+ gpssync/gpssyncdialog.cpp, gpssync/gpssyncdialog.h:
+ kipi-plugins from trunk : GPSSync tool : "Remove" button to
+ delete GPS data from picture is now on main dialog.
+
+ CCMAIL: gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-28 00:21 seb
+
+ * [r589347] ipodexport/ipodexportdialog.cpp:
+ Improve ipod detection times by a magnitude
+
+2006-09-27 15:17 seb
+
+ * [r589076] configure.in.in, ipodexport/Makefile.am,
+ ipodexport/imagelistitem.cpp, ipodexport/imagelistitem.h,
+ ipodexport/ipodexportdialog.cpp:
+ Port to newer libgpod-cvs api (still works with 0.4.0)
+
+2006-09-27 14:46 cgilles
+
+ * [r589066] NEWS:
+ update
+
+2006-09-27 14:45 cgilles
+
+ * [r589065] common/exiv2iface/exiv2iface.cpp:
+ kipi-plugins from trunk : fix GPS altitude value extraction.
+
+ BUG: 134749
+
+2006-09-27 14:21 cgilles
+
+ * [r589056] gpssync/gpseditdialog.cpp, gpssync/gpseditdialog.h:
+ kipi-plugins from trunk : GPSSync tool : remember the GPS
+ position editor dialog settings between sessions.
+
+ CCMAIL: gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-27 12:28 cgilles
+
+ * [r589006] gpssync/gpseditdialog.cpp:
+ fix i18n
+
+2006-09-27 12:27 cgilles
+
+ * [r589005] gpssync/gpslistviewitem.cpp,
+ gpssync/gpslistviewitem.h, gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : GPSSync tool : added capabilty to
+ add/remove GPS position manually to more than one pictures at
+ the same time. Just take your pictures selection on the list
+ using SHIFT/CTRL keys and push "Edit Coordinates" button.
+
+ CCMAIL: gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-27 10:02 cgilles
+
+ * [r588886] gpssync/gpseditdialog.cpp:
+ always enable JavaScript
+
+2006-09-27 08:52 cgilles
+
+ * [r588865] gpssync/Makefile.am, gpssync/gpseditdialog.cpp,
+ gpssync/gpseditdialog.h, gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : GPSSync tool : use a KHTMLPart widget
+ to embed web locator page in GPS positions editor dialog
+
+ CCMAIL: gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-26 11:37 cgilles
+
+ * [r588569] gpssync/gpseditdialog.cpp, gpssync/gpseditdialog.h,
+ gpssync/gpslistviewitem.cpp:
+ kipi-plugins from trunk : GPSSync tool : improve GPS position
+ editor dialog with a better precision. Don't use a
+ KDoubleNumInput widget but a KLineEdit instead to be able to cut
+ and paste easily position coordinate from konqueror. Added
+ buttons to clear GPS position entries.
+
+ CCMAIL: gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-26 09:14 cgilles
+
+ * [r588511] gpssync/gpseditdialog.cpp:
+ kipi-plugins from trunk : GPSSync tool : added mapki link
+ CCMAIL: gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-26 08:54 cgilles
+
+ * [r588502] gpssync/gpslistviewitem.cpp,
+ gpssync/gpslistviewitem.h:
+ kipi-plugins from trunk : GPSSync tool : to be able to set GPS
+ info in pictures if time stamp is not available and if user set
+ GPS coordinate manually
+
+ CCMAIL: kde-imaging@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-25 18:28 cgilles
+
+ * [r588355] gpssync/gpslistviewitem.cpp:
+ using more generic Exiv2iface api
+
+2006-09-25 18:27 cgilles
+
+ * [r588354] common/exiv2iface/exiv2iface.cpp:
+ more generic api
+
+2006-09-25 18:22 cgilles
+
+ * [r588351] gpssync/gpsdatacontainer.h, gpssync/gpssyncdialog.cpp,
+ gpssync/gpssyncdialog.h:
+ fix broken compilation with gcc 4.1
+
+2006-09-25 14:27 cgilles
+
+ * [r588294] gpssync/gpseditdialog.cpp, gpssync/gpseditdialog.h:
+ kipi-plugins from trunk : GPSSync tool : add links to external
+ web tools to get GPS coordinate. First one is CapeLinks web
+ site...
+
+ CCMAIL: kde-imaging@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-25 13:54 cgilles
+
+ * [r588276] gpssync/gpseditdialog.cpp:
+ fix precision
+
+2006-09-25 13:05 seb
+
+ * [r588255] ipodexport/imagelist.cpp,
+ ipodexport/ipodexportdialog.cpp, ipodexport/ipodexportdialog.h:
+ After transferring photos to the ipod, repopulate the target
+ album to show the uploaded pictures
+
+2006-09-25 12:53 cgilles
+
+ * [r588251] gpssync/Makefile.am, gpssync/gpseditdialog.cpp,
+ gpssync/gpseditdialog.h, gpssync/gpslistviewitem.cpp,
+ gpssync/gpslistviewitem.h, gpssync/gpssyncdialog.cpp,
+ gpssync/gpssyncdialog.h:
+ kipi-plugins from trunk : GPSSync tool :
+
+ - New options :
+ * to set GPS coordinates manually.
+ * to remove all GPS info from file.
+
+ - Bug fix (relevant of EXIV2 library ?) : we need to clean up
+ all GPS info from file before to rewrite it.
+ Andreas, i have seen that if a picture has already GPS infos, if
+ i don't process a clean up of all Exif.GPSInfo tags,
+ the lattitude and altitude values are set to 0.
+
+ CCMAIL: kde-imaging@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net, ahuggel@gmx.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-25 12:34 seb
+
+ * [r588249] ipodexport/ipodexportdialog.cpp,
+ ipodexport/ipodexportdialog.h:
+ * Add button to rename ipod photo albums
+ * Fix potential crashes if libgpod 0.4.0 was used
+
+2006-09-25 12:15 cgilles
+
+ * [r588242] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ new method to erase all GPS Exif tags
+
+2006-09-25 08:41 cgilles
+
+ * [r588176] gpssync/gpssyncdialog.cpp:
+ time is in minutes from gui, not seconds.
+
+2006-09-25 07:56 seb
+
+ * [r588164] ipodexport/ipodexportdialog.cpp:
+ Missed an #define for a patch which will go upstream for libgpod
+ 0.4.1.
+ Thanks to Gilles for finding this!
+
+2006-09-25 06:46 cgilles
+
+ * [r588155] README:
+ update depency
+
+2006-09-25 06:44 cgilles
+
+ * [r588154] gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : GPSSync tool : new option to set the
+ maximum distance time in minutes to get matched points from GPX
+ file around a GPS point to interpolate.
+
+ CCMAIL: kde-imaging@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-25 06:18 cgilles
+
+ * [r588150] gpssync/gpsdataparser.cpp, gpssync/gpsdataparser.h,
+ gpssync/gpssyncdialog.cpp:
+ code polishing
+
+2006-09-25 04:06 seb
+
+ * [r588136] configure.in.bot, configure.in.in,
+ ipodexport/imagelist.cpp, ipodexport/imagelist.h,
+ ipodexport/imagelistitem.cpp, ipodexport/imagelistitem.h,
+ ipodexport/ipodexportdialog.cpp, ipodexport/ipodexportdialog.h,
+ ipodexport/plugin_ipodexport.cpp:
+ * Detect libgpod 0.4.0 release, now required
+ * Subclass the imagelist for ipod and upload types, drawing
+ balloon help bubbles too
+ * Enclose the plugin in a namespace to prevent potential memory
+ conflicts between kipi-plugins
+ * Overhaul the UI design, allowing the user to create, delete,
+ and rename photo albums on the ipod
+ * Allow deleting of photos/albums if libgpod-cvs is used
+ CCMAIL: kde-imaging@kde.org
+
+2006-09-24 18:50 cgilles
+
+ * [r588048] gpssync/gpsdataparser.cpp, gpssync/gpsdataparser.h,
+ gpssync/gpssyncdialog.cpp:
+ using GPSDataContainer everywhere
+
+2006-09-23 21:15 cgilles
+
+ * [r587737] gpssync/gpsbabelbinary.cpp:
+ fix debug statement
+
+2006-09-23 12:28 cgilles
+
+ * [r587620] gpssync/gpsdatacontainer.h, gpssync/gpsdataparser.cpp,
+ gpssync/gpslistviewitem.cpp, gpssync/gpslistviewitem.h,
+ gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : using GPSDataContainer class
+ everywhere. polish source code.
+
+2006-09-23 06:05 seb
+
+ * [r587561] ipodexport/ipodexportdialog.cpp:
+ Disable the ipod list if there is no ipod plugged in.
+
+ Heres a new screenshot:
+ http://www.sebruiz.net/files/ipod_photo.png
+
+2006-09-23 05:56 seb
+
+ * [r587555] ipodexport/ipodexportdialog.cpp,
+ ipodexport/ipodexportdialog.h:
+ * Re-enable transferring of photos to the ipod
+ * Allow creating new photo albums on the ipod
+
+2006-09-23 05:25 seb
+
+ * [r587551] ipodexport/ipodexportdialog.cpp,
+ ipodexport/ipodexportdialog.h:
+ New widget for displaying contents of the ipod. soon to have
+ previews and add/remove album functionality.
+ Transferring is temporarily disabled
+
+2006-09-22 23:03 seb
+
+ * [r587474] ipodexport/ipodexportdialog.cpp:
+ Disable the Start button if there is no ipod plugged in
+
+2006-09-22 16:17 cgilles
+
+ * [r587401] gpssync/gpssyncdialog.cpp:
+ fix
+
+2006-09-22 15:48 seb
+
+ * [r587389] ipodexport/ipodexportdialog.cpp:
+ Add a green label to show successful finding of ipod
+
+2006-09-22 15:32 seb
+
+ * [r587386] ipodexport/plugin_ipodexport.cpp,
+ ipodexport/plugin_ipodexport.h:
+ Remove unneeded secondary action, and make the primary action an
+ entry in the Tools Menu
+
+2006-09-22 15:29 seb
+
+ * [r587385] trunk/extragear/libs, htmlexport,
+ trunk/extragear/libs/libkexif,
+ trunk/extragear/libs/libkipi/libkipi:
+ Update ignores
+
+2006-09-22 15:28 seb
+
+ * [r587384] ipodexport/ipodexportdialog.cpp,
+ ipodexport/ipodexportdialog.h:
+ Complete the dialog initialisation:
+ - add the selected files to the list view
+ - allow adding/removal of files
+ - update the progress bar as images are uploaded
+
+2006-09-22 15:04 seb
+
+ * [r587381] ipodexport/Makefile.am, ipodexport/imagelist.cpp,
+ ipodexport/imagelistitem.cpp, ipodexport/imagelistitem.h,
+ ipodexport/ipodexportdialog.cpp, ipodexport/ipodexportdialog.h:
+ Make the ipod upload dialog work well!
+ Add and remove item functionality to the list view (which was
+ stolen from the batch image processing!)
+
+2006-09-22 14:36 cgilles
+
+ * [r587368] gpssync/gpsdataparser.cpp:
+ kipi-plugins from trunk : GPSSync tool : interpolate altitude
+ value like latitude and longitude.
+
+ CCMAIL: kde-imaging@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-22 13:10 cgilles
+
+ * [r587348] gpssync/gpsdataparser.cpp, gpssync/gpsdataparser.h,
+ gpssync/gpslistviewitem.cpp, gpssync/gpslistviewitem.h,
+ gpssync/gpssyncdialog.cpp, gpssync/gpssyncdialog.h:
+ kipi-plugins from trunk : GPSSync tool : added new option to
+ interpolate GPS positions.
+
+ CCMAIL: kde-imaging@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-22 10:42 cgilles
+
+ * [r587322] gpssync/gpsdataparser.cpp, gpssync/gpsdataparser.h,
+ gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : GPSSync tool : added new option to set
+ camera time-zone in hours to match properly all pictures with
+ GPS data using GMT time.
+
+ CCMAIL: kde-imaging@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-22 09:11 seb
+
+ * [r587316] configure.in.in:
+ Hopefully a better check for libgpod cvs. Check directly for
+ the itdb photo methods
+
+2006-09-22 09:01 seb
+
+ * [r587315] ipodexport, ipodexport/ipodexportdialog.cpp,
+ ipodexport/ipodexportdialog.h:
+ Disable the contents of the dialog and provide a warning label
+ if there is no ipod connected
+
+2006-09-22 08:59 cgilles
+
+ * [r587313] gpssync/gpssyncdialog.cpp:
+ missing i18n
+
+2006-09-22 08:47 cgilles
+
+ * [r587310] gpssync/gpssyncdialog.cpp:
+ kipi-plugins from trunk : GPSSync tool : added new option to set
+ the max gap time in seconds to synchronize pictures with GPS
+ data. default value is 30s.
+
+ CCMAIL: kde-imaging@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net
+
+ CCBUGS: 133359, 111560
+
+2006-09-22 08:15 seb
+
+ * [r587306] ipodexport/Makefile.am, ipodexport/imagelist.cpp,
+ ipodexport/imagelist.h, ipodexport/ipodexportdialog.cpp,
+ ipodexport/ipodexportdialog.h, ipodexport/plugin_ipodexport.cpp:
+ * Copy over the batch image processing image list view for use
+ with ipod export
+ * More work towards the dialog
+ * Dont crash if there is no ipod plugged in
+
+2006-09-22 07:54 seb
+
+ * [r587303] ipodexport/plugin_ipodexport.cpp:
+ Include necessary for g_init_type()
+
+2006-09-22 07:44 seb
+
+ * [r587298] ipodexport/plugin_ipodexport.cpp:
+ Don't do crazy crashing stuff
+
+2006-09-22 07:37 cgilles
+
+ * [r587297] README:
+ upate
+
+2006-09-22 07:29 cgilles
+
+ * [r587290] README:
+ update
+
+2006-09-22 07:05 cgilles
+
+ * [r587287] NEWS:
+ update
+
+2006-09-22 06:59 seb
+
+ * [r587286] acquireimages, batchprocessimages, calendar,
+ cdarchiving, common, common/exiv2iface, findimages,
+ flickrexport, galleryexport, gpssync, htmlexport,
+ htmlexport/themes/simple, ipodexport, jpeglossless,
+ kameraklient, mpegencoder, printwizard, rawconverter,
+ rawconverter/profiles, sendimages, simpleviewerexport,
+ slideshow, timeadjust, wallpaper:
+ Totally update all the svn:ignore properties, of nearly all the
+ kipi-plugins...
+
+2006-09-22 06:52 seb
+
+ * [r587284] Makefile.am, configure.in.bot, configure.in.in,
+ ipodexport, ipodexport/Makefile.am,
+ ipodexport/ipodexportdialog.cpp, ipodexport/ipodexportdialog.h,
+ ipodexport/kipiplugin_ipodexport.desktop,
+ ipodexport/plugin_ipodexport.cpp,
+ ipodexport/plugin_ipodexport.h:
+ Import of a kipi plugin to transfer photos to an iPod photo/video
+ Requires libgpod > 0.3.2 (ie cvs version)
+
+ Testing is welcomed, but I would advise not using it if you have
+ a well established and important photo database which is already
+ on the ipod.
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-09-21 21:42 anaselli
+
+ * [r587182] TODO, trunk/extragear/libs/prepare_kipiplugins.rb:
+ change release also in
+ kipi-plugins/common/include/pluginsversion.h
+ to prepare kipi-plugins release
+
+2006-09-21 18:24 cgilles
+
+ * [r587143] gpssync/gpssyncdialog.cpp, gpssync/gpssyncdialog.h:
+ using internal d private class
+
+2006-09-21 18:04 cgilles
+
+ * [r587140] gpssync/gpsdatacontainer.h, gpssync/gpsdataparser.cpp,
+ gpssync/gpsdataparser.h:
+ separate class GPSData and GPSDataParser
+
+2006-09-21 16:39 cgilles
+
+ * [r587123] configure.in.bot:
+ fix
+
+2006-09-21 16:38 cgilles
+
+ * [r587122] configure.in.in:
+ fix
+
+2006-09-21 12:53 cgilles
+
+ * [r587074] NEWS:
+ update
+
+2006-09-21 12:52 cgilles
+
+ * [r587073] gpssync/gpsdataparser.cpp, gpssync/gpsdataparser.h,
+ gpssync/gpslistviewitem.cpp, gpssync/gpslistviewitem.h,
+ gpssync/gpssyncdialog.cpp, gpssync/gpssyncdialog.h,
+ gpssync/plugin_gpssync.cpp:
+ kipi-plugins from trunk : new plugin to synchronize pictures
+ metadata with a GPS data file.
+
+ First beta version of GPSSync kipi-plugin is now available for
+ testing.
+
+ To use it, you need a GPX xml file generated by your GPS device.
+ The GPX file must be generated to render a wayspoints or
+ trackpoints list.
+
+ If your GPS device do not support GPX, you can generate it using
+ GPSBabel program like this :
+
+ # gpsbabel -w -i mapsource -f Driveback.mps -o gpx -F
+ Driveback.gpx
+
+ The plugin use the Exif time-stamp to correlate GPS data.
+ Accuracy of 30s is used to diff camera and GPS time-stamp. Of
+ course, the date of your GPS device and your camera must be set
+ properly (:=))).
+
+ Some links:
+
+ GPSBalbel: http://www.gpsbabel.org
+ GPX file format: http://www.topografix.com/gpx.asp
+ Plugin in action:
+ http://digikam3rdparty.free.fr/Screenshots/newkipigpssyncplugin.png
+
+ CCMAIL: kde-imaging@kde.org, digikam-devel@kde.org,
+ digikam-users@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net
+
+ BUG: 111560
+ CCBUGS: 133359
+
+2006-09-21 12:38 cgilles
+
+ * [r587069] Makefile.am:
+ GPSSync kipi plugin can be compiled and used now.
+
+2006-09-21 08:11 cgilles
+
+ * [r586987] gpssync/gpslistviewitem.h:
+ fix
+
+2006-09-21 08:10 cgilles
+
+ * [r586986] gpssync/gpslistviewitem.cpp,
+ gpssync/gpslistviewitem.h:
+ using d private class to store private members
+
+2006-09-21 07:58 cgilles
+
+ * [r586982] imagesgallery/plugin_imagesgallery.cpp:
+ fix i18n
+
+2006-09-21 07:57 cgilles
+
+ * [r586980] htmlexport/Makefile.am, htmlexport/wizard.cpp,
+ htmlexport/wizard.h:
+ kipi-plugins from trunk : HTML Export plugin : just add a full
+ help button like others plugin.
+
+2006-09-20 20:37 cgilles
+
+ * [r586878] gpssync/gpslistviewitem.cpp,
+ gpssync/gpssyncdialog.cpp:
+ fix listview col. order
+ fix JPEG extension decoding
+
+2006-09-20 14:57 cgilles
+
+ * [r586770] gpssync, gpssync/Makefile.am,
+ gpssync/gpsbabelbinary.cpp, gpssync/gpsbabelbinary.h,
+ gpssync/gpsdataparser.cpp, gpssync/gpsdataparser.h,
+ gpssync/gpslistviewitem.cpp, gpssync/gpslistviewitem.h,
+ gpssync/gpssyncdialog.cpp, gpssync/gpssyncdialog.h,
+ gpssync/hi16-action-gpsimagetag.png,
+ gpssync/hi32-action-gpsimagetag.png,
+ gpssync/kipiplugin_gpssync.desktop, gpssync/plugin_gpssync.cpp,
+ gpssync/plugin_gpssync.h:
+ kipi-plugins from trunk : new plugin to synchronize pictures
+ metadata with a GPS data file.
+
+ This plugin is under development and not yet done (missing GPS
+ file parser implementation using GPSBabel program).
+ It will not be compiled.
+
+ CCMAIL: kde-imaging@kde.org, alexios.beveratos@gmail.com,
+ gerhard@kulzer.net
+
+2006-09-20 08:47 cgilles
+
+ * [r586666] rawconverter/batchdialog.cpp,
+ rawconverter/dcrawbinary.cpp,
+ rawconverter/dcrawsettingswidget.cpp,
+ rawconverter/dcrawsettingswidget.h,
+ rawconverter/singledialog.cpp:
+ fix minimum dcraw release number : 8.16 at least
+
+2006-09-20 08:46 cgilles
+
+ * [r586665] README:
+ update
+
+2006-09-20 07:03 cgilles
+
+ * [r586636] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h:
+ new methods to set/get GPS info into Exif metadata
+
+2006-09-19 20:32 cgilles
+
+ * [r586509] rawconverter/rawdecodingsettings.h:
+ polish
+
+2006-09-19 09:46 anaselli
+
+ * [r586275] TODO:
+ a todo for reminding me something
+
+2006-09-19 09:43 anaselli
+
+ * [r586272] NEWS:
+ added bug 91545 - try following Gilles way :)
+
+2006-09-19 09:40 anaselli
+
+ * [r586270] slideshow/plugin_slideshow.cpp:
+ patch provided by drajar <djarca73 at yahoo dot com>
+ Tested by Gilles
+ BUG: 91545
+
+2006-09-19 06:05 cgilles
+
+ * [r586232] Makefile.am:
+ compile
+
+2006-09-19 06:02 cgilles
+
+ * [r586230] configure.in.in:
+ kipi-plugins from trunk : if Exiv2 library is not found,
+ kipi-plugins cannot be compiled
+
+2006-09-19 05:50 cgilles
+
+ * [r586229] jpeglossless/Makefile.am:
+ fix
+
+2006-09-19 05:49 cgilles
+
+ * [r586228] timeadjust/Makefile.am:
+ fix
+
+2006-09-19 05:37 cgilles
+
+ * [r586226] configure.in.bot:
+ kipi-plugins from trunk : more detailled results of .configure
+ script
+
+2006-09-18 14:34 cgilles
+
+ * [r586023] Makefile.am:
+ fix
+
+2006-09-18 14:30 cgilles
+
+ * [r586022] configure.in.in:
+ update
+
+2006-09-18 14:25 cgilles
+
+ * [r586020] configure.in.in:
+ update
+
+2006-09-18 14:24 cgilles
+
+ * [r586019] configure.in.bot:
+ update
+
+2006-09-18 14:22 cgilles
+
+ * [r586018] configure.in.bot:
+ update
+
+2006-09-18 13:32 cgilles
+
+ * [r586002] NEWS:
+ update
+
+2006-09-18 13:28 cgilles
+
+ * [r585999] Makefile.am:
+ compile
+
+2006-09-18 12:31 cgilles
+
+ * [r585980] trunk/extragear/libs/PACKAGING, README,
+ configure.in.bot, configure.in.in:
+ kipi-plugins from trunk : removing libkexif depency ! We using
+ Exiv2 instead everywhere.
+
+ Developpers, please take a look into the new Exiv2 interface
+ kipi-plugins/common/exiv2iface.cpp to manage metadata into your
+ kipi-plugins.
+ This class is a simplified version of the DMetadata class from
+ digiKam core. Please contact digiKam team if you want to
+ add/fix/improve new
+ methods. Thanks in advance.
+
+ CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org
+
+2006-09-18 12:19 cgilles
+
+ * [r585975] NEWS:
+ update
+
+2006-09-18 12:17 cgilles
+
+ * [r585974] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h, jpeglossless/Makefile.am,
+ jpeglossless/jpegtransform.cpp, jpeglossless/jpegtransform.h,
+ kipiplugins.kdevelop:
+ kipi-plugins from trunk : JPEGLossLess plugin : Using Exiv2
+ library intead libkexif.
+ CCMAIL: kde-imaging@kde.org
+
+2006-09-18 12:06 cgilles
+
+ * [r585969] common/exiv2iface/Makefile.am:
+ file missing
+
+2006-09-18 11:35 cgilles
+
+ * [r585956] timeadjust/Makefile.am:
+ polish
+
+2006-09-18 11:14 cgilles
+
+ * [r585945] rawconverter/plugin_rawconverter.cpp:
+ fix typo
+
+2006-09-18 10:50 cgilles
+
+ * [r585936] NEWS:
+ update
+
+2006-09-18 10:46 cgilles
+
+ * [r585935] jpeglossless/imageflip.cpp:
+ polish
+
+2006-09-18 10:44 cgilles
+
+ * [r585933] timeadjust/timeadjustdialog.cpp:
+ kipi-plugins from trunk : TimeAdjust plugin : polish dialog
+
+2006-09-18 10:21 cgilles
+
+ * [r585927] common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h, rawconverter/dcrawiface.cpp,
+ timeadjust/Makefile.am, timeadjust/plugin_timeadjust.cpp,
+ timeadjust/plugin_timeadjust.h, timeadjust/timeadjustdialog.cpp,
+ timeadjust/timeadjustdialog.h:
+ kipi-plugins from trunk : TimeAdjust plugin : Using Exiv2
+ library intead libkexif.
+ CCMAIL: kde-imaging@kde.org
+
+2006-09-18 09:35 cgilles
+
+ * [r585913] Makefile.am:
+ compile
+
+2006-09-18 09:32 cgilles
+
+ * [r585911] rawconverter/Makefile.am:
+ compile
+
+2006-09-18 09:26 cgilles
+
+ * [r585910] common/Makefile.am, common/exiv2iface,
+ common/exiv2iface/exiv2iface.cpp,
+ common/exiv2iface/exiv2iface.h, rawconverter/Makefile.am,
+ rawconverter/exiv2iface.cpp, rawconverter/exiv2iface.h:
+ kipi-plugins from trunk : moving exiv2 interface to plugins
+ common place
+
+2006-09-18 08:48 cgilles
+
+ * [r585900] rawconverter/dcrawiface.cpp,
+ rawconverter/exiv2iface.cpp, rawconverter/exiv2iface.h:
+ kipi-plugins from trunk : Raw Converter : More Exif/Iptc
+ informations are updated during conversion
+
+2006-09-18 06:42 cgilles
+
+ * [r585881] rawconverter/batchdialog.cpp,
+ rawconverter/savesettingswidget.cpp,
+ rawconverter/singledialog.cpp:
+ kipi-plugins from trunk : Raw Converter : using KIO::renameDlg
+ instead KFileDialog.
+
+2006-09-15 13:50 cgilles
+
+ * [r584777] rawconverter/batchdialog.cpp:
+ following the current item in the list during conversion
+
+2006-09-15 13:25 cgilles
+
+ * [r584767] README:
+ update
+
+2006-09-15 13:23 cgilles
+
+ * [r584765] NEWS:
+ update
+
+2006-09-15 13:17 cgilles
+
+ * [r584763] Makefile.am, configure.in.bot, configure.in.in,
+ kipiplugins.kdevelop, rawconverter/Makefile.am,
+ rawconverter/dcrawiface.cpp, rawconverter/dcrawiface.h,
+ rawconverter/exiv2iface.cpp, rawconverter/exiv2iface.h:
+ kipi-plugins from trunk : Raw Converter :
+ Exif/makernotes/iptc/gps metadata restoration after RAW image
+ decoding.
+
+ - Add Exiv2 depency. I recommend to use the current
+ implementation of Exiv2 from svn (Exiv2 0.11 will be release in
+ a near future)
+
+ - Add a new Exiv2 interface class based on some part of digiKam
+ core. This class will be will be moved later to the common
+ plugins folder to remplace libkexif depency everywhere. I need
+ to polish and improve the code before.
+
+ - Actually, 2 output file formats are fully supported to store
+ metadata : JPEG and PNG. Note PNG Exif/Iptc storing use
+ ImageMagick raw profile stored in compressed text chunk.
+ Tiff file format will be added when Exiv2 library will support
+ Tiff write io (normally later 0.11 release)
+
+ To all digiKam users : after to have converted Raw files using
+ this plugin, you will have the pleasure to see all metadata into
+ target files using Metadata side bar (:=)))
+
+ CCMAIL: kde-imaging@kde.org
+
+ BUG : 107905
+ CCBUGS: 128394
+
+2006-09-15 10:25 cgilles
+
+ * [r584591] rawconverter/dcrawbinary.h,
+ rawconverter/dcrawiface.cpp, rawconverter/dcrawiface.h,
+ rawconverter/rawdecodingsettings.h,
+ rawconverter/singledialog.cpp:
+ kipi-plugins from trunk : Raw Converter : full cancelable (when
+ you want) dcraw instance during RAW image data decoding.
+ The code use now a KProcess instance instead a simple
+ non-cancelable popen() call. The implementation is inspired from
+ digiKam RAW image loader
+ CCBUGS: 107905, 128394
+
+2006-09-15 08:33 cgilles
+
+ * [r584564] batchprocessimages/Makefile.am,
+ batchprocessimages/borderimagesdialog.cpp,
+ batchprocessimages/colorimagesdialog.cpp,
+ batchprocessimages/convertimagesdialog.cpp,
+ batchprocessimages/effectimagesdialog.cpp,
+ batchprocessimages/filterimagesdialog.cpp,
+ batchprocessimages/imagepreview.cpp,
+ batchprocessimages/outputdialog.cpp,
+ batchprocessimages/recompressimagesdialog.cpp,
+ batchprocessimages/renameimagesdialog.cpp,
+ batchprocessimages/resizeimagesdialog.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 08:19 cgilles
+
+ * [r584556] acquireimages/Makefile.am,
+ acquireimages/acquireimagedialog.cpp,
+ acquireimages/screenshotdialog.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 08:17 cgilles
+
+ * [r584554] calendar/Makefile.am, calendar/calwizard.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 08:15 cgilles
+
+ * [r584553] cdarchiving/Makefile.am,
+ cdarchiving/cdarchivingdialog.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 08:14 cgilles
+
+ * [r584552] findimages/Makefile.am,
+ findimages/finddupplicatedialog.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 08:12 cgilles
+
+ * [r584551] galleryexport/Makefile.am,
+ galleryexport/gallerywindow.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 08:07 cgilles
+
+ * [r584549] imagesgallery/Makefile.am,
+ imagesgallery/imgallerydialog.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 08:05 cgilles
+
+ * [r584547] kameraklient/Makefile.am, kameraklient/cameraui.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 08:03 cgilles
+
+ * [r584546] mpegencoder/Makefile.am, mpegencoder/kimg2mpg.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 08:00 cgilles
+
+ * [r584545] printwizard/Makefile.am,
+ printwizard/frmprintwizard.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 07:56 cgilles
+
+ * [r584544] sendimages/Makefile.am,
+ sendimages/sendimagesdialog.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 07:54 cgilles
+
+ * [r584543] simpleviewerexport/Makefile.am,
+ simpleviewerexport/svedialog.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 07:53 cgilles
+
+ * [r584542] slideshow/Makefile.am, slideshow/slideshowconfig.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 07:51 cgilles
+
+ * [r584541] timeadjust/Makefile.am,
+ timeadjust/timeadjustdialog.cpp:
+ using kipi-plugins version instead libkipi into about data
+
+2006-09-15 07:46 cgilles
+
+ * [r584540] flickrexport/Makefile.am,
+ flickrexport/flickrwindow.cpp:
+ using kipi-plugins version instead libkipi
+
+2006-09-15 07:06 cgilles
+
+ * [r584532] NEWS:
+ update
+
+2006-09-15 07:04 cgilles
+
+ * [r584531] flickrexport/flickrtalker.cpp:
+ kipi plugins from trunk : flickr Export : patch from Debajyoti
+ Bera about new flickr API compliant
+ BUG:132659
+
+2006-09-14 14:38 cgilles
+
+ * [r584364] rawconverter/dcrawsettingswidget.cpp:
+ fix i18n
+
+2006-09-14 14:34 cgilles
+
+ * [r584363] rawconverter/dcrawsettingswidget.cpp:
+ fix i18n
+
+2006-09-14 14:32 cgilles
+
+ * [r584362] rawconverter/dcrawsettingswidget.cpp:
+ fix i18n
+
+2006-09-14 14:24 cgilles
+
+ * [r584359] rawconverter/dcrawiface.h,
+ rawconverter/rawdecodingsettings.h:
+ separate RawDecodingSettings class and DcrawIface class
+
+2006-09-14 12:28 cgilles
+
+ * [r584331] rawconverter/dcrawiface.cpp:
+ init pointer to 0
+
+2006-09-14 12:20 cgilles
+
+ * [r584324] rawconverter/dcrawiface.cpp:
+ int pointer to 0
+
+2006-09-14 12:15 cgilles
+
+ * [r584320] rawconverter/dcrawiface.cpp:
+ init pointer to 0
+
+2006-09-14 11:14 cgilles
+
+ * [r584218] rawconverter/batchdialog.cpp,
+ rawconverter/batchdialog.h,
+ rawconverter/dcrawsettingswidget.cpp,
+ rawconverter/dcrawsettingswidget.h,
+ rawconverter/savesettingswidget.cpp,
+ rawconverter/savesettingswidget.h,
+ rawconverter/singledialog.cpp, rawconverter/singledialog.h:
+ kipi-plugins from trunk : Raw Converter : add 'Default' button
+ to set all settings to default values.
+
+ CCMAIL: kde-imaging@kde.org
+
+ CCBUGS: 107905, 128394
+
+2006-09-14 11:00 cgilles
+
+ * [r584213] rawconverter/savesettingswidget.cpp:
+ fix 18n
+
+2006-09-14 10:55 cgilles
+
+ * [r584212] rawconverter/dcrawsettingswidget.cpp:
+ fix 18n
+
+2006-09-14 10:48 cgilles
+
+ * [r584211] rawconverter/dcrawsettingswidget.cpp:
+ add RGB color space descriptions
+
+2006-09-14 09:28 cgilles
+
+ * [r584185] rawconverter/batchdialog.cpp,
+ rawconverter/batchdialog.h,
+ rawconverter/dcrawsettingswidget.cpp,
+ rawconverter/dcrawsettingswidget.h,
+ rawconverter/plugin_rawconverter.cpp,
+ rawconverter/plugin_rawconverter.h,
+ rawconverter/singledialog.cpp, rawconverter/singledialog.h:
+ kipi-plugins from trunk : Raw Converter : print dcraw version
+ detected at startup to the header of RAW decoding settings area.
+
+ CCMAIL: kde-imaging@kde.org
+
+ CCBUGS: 107905, 128394
+
+2006-09-14 09:11 cgilles
+
+ * [r584176] rawconverter/Makefile.am,
+ rawconverter/dcrawbinary.cpp, rawconverter/dcrawbinary.h,
+ rawconverter/plugin_rawconverter.cpp:
+ kipi-plugins from trunk : Raw Converter : dcraw version
+ detection at startup. Code come from digiKam project
+
+ CCMAIL: kde-imaging@kde.org
+
+ CCBUGS: 107905, 128394
+
+2006-09-14 08:00 cgilles
+
+ * [r584167] rawconverter/actionthread.cpp,
+ rawconverter/actionthread.h, rawconverter/batchdialog.cpp,
+ rawconverter/singledialog.cpp:
+ code polishing
+
+2006-09-14 07:05 cgilles
+
+ * [r584156] rawconverter/Makefile.am,
+ rawconverter/actionthread.cpp, rawconverter/actionthread.h,
+ rawconverter/batchdialog.cpp, rawconverter/dcrawiface.cpp,
+ rawconverter/dcrawiface.h, rawconverter/dcrawsettingswidget.h,
+ rawconverter/dcrawutils.cpp, rawconverter/dcrawutils.h,
+ rawconverter/savesettingswidget.h,
+ rawconverter/singledialog.cpp:
+ DcrawUtils ==> DcrawIface class
+
+2006-09-14 06:18 cgilles
+
+ * [r584150] rawconverter/actionthread.cpp,
+ rawconverter/dcrawutils.cpp, rawconverter/dcrawutils.h:
+ new class
+
+2006-09-14 05:52 cgilles
+
+ * [r584143] rawconverter/previewwidget.cpp,
+ rawconverter/previewwidget.h:
+ using d private class
+
+2006-09-14 05:46 cgilles
+
+ * [r584140] rawconverter/singledialog.cpp,
+ rawconverter/singledialog.h:
+ polish source code
+
+2006-09-14 05:37 cgilles
+
+ * [r584122] rawconverter/Makefile.am,
+ rawconverter/batchdialog.cpp, rawconverter/dcrawutils.cpp,
+ rawconverter/singledialog.cpp:
+ compile
+
+2006-09-14 05:35 cgilles
+
+ * [r584112] common/include/pluginsversion.h,
+ common/include/version.h:
+ rename
+
+2006-09-14 05:34 cgilles
+
+ * [r584109] common/include/version.h:
+ fix
+
+2006-09-13 21:11 cgilles
+
+ * [r583960] rawconverter/batchdialog.cpp,
+ rawconverter/singledialog.cpp:
+ using kipiplugins version string
+
+2006-09-13 21:09 cgilles
+
+ * [r583957] rawconverter/dcrawutils.cpp:
+ using kip-plugins version string
+
+2006-09-13 21:07 cgilles
+
+ * [r583955] common/include/version.h:
+ fix name
+
+2006-09-13 21:05 cgilles
+
+ * [r583952] NEWS:
+ update
+
+2006-09-13 21:01 cgilles
+
+ * [r583950] common/include/version.h:
+ new version header file
+
+2006-09-13 20:02 cgilles
+
+ * [r583928] rawconverter/batchdialog.cpp,
+ rawconverter/dcrawsettingswidget.cpp,
+ rawconverter/dcrawsettingswidget.h, rawconverter/dcrawutils.cpp,
+ rawconverter/singledialog.cpp:
+ kipi-plugins from trunk : Raw Converter : new option to set the
+ output color space to use during RAW image data decoding : SRGB,
+ ADOBERGB, WIDEGAMUT, PROPHOTO
+
+ CCBUGS: 107905
+
+2006-09-13 19:31 cgilles
+
+ * [r583914] rawconverter/iccjpeg.c, rawconverter/iccjpeg.h:
+ missing files to compile
+
+2006-09-13 19:30 cgilles
+
+ * [r583913] rawconverter/Makefile.am, rawconverter/dcrawutils.cpp,
+ rawconverter/dcrawutils.h, rawconverter/profiles,
+ rawconverter/profiles/Makefile.am,
+ rawconverter/profiles/adobergb.icm,
+ rawconverter/profiles/prophoto.icm,
+ rawconverter/profiles/srgb.icm,
+ rawconverter/profiles/widegamut.icm:
+ kipi-plugins from trunk : Raw Converter :
+
+ - Store icc color space profile used to decode RAW data into
+ target image (JPEG, PNG, TIFF)
+ - 4 icc color profile files (comming from krita repository) are
+ available : SRGB, ADOBERGB, WIDEGAMUT, PROPHOTO
+
+ Actually, the implementation only use SRGB color space
+
+ CCBUGS: 107905
+
+2006-09-13 16:39 cgilles
+
+ * [r583835] rawconverter/batchdialog.cpp,
+ rawconverter/singledialog.cpp:
+ remember dialog size between sessions
+
+2006-09-13 16:38 cgilles
+
+ * [r583833] rawconverter/savesettingswidget.cpp:
+ fix i18n
+
+2006-09-13 16:30 cgilles
+
+ * [r583831] rawconverter/savesettingswidget.cpp:
+ fix i18n
+
+2006-09-13 16:29 cgilles
+
+ * [r583830] rawconverter/dcrawsettingswidget.cpp:
+ fix i18n
+
+2006-09-13 15:04 cgilles
+
+ * [r583807] NEWS:
+ update
+
+2006-09-13 15:03 cgilles
+
+ * [r583806] rawconverter/Makefile.am, rawconverter/actions.h,
+ rawconverter/actionthread.cpp, rawconverter/actionthread.h,
+ rawconverter/batchdialog.cpp, rawconverter/batchdialog.h,
+ rawconverter/clistviewitem.h, rawconverter/dcrawprocess.cpp,
+ rawconverter/dcrawsettingswidget.cpp,
+ rawconverter/dcrawsettingswidget.h, rawconverter/dcrawutils.cpp,
+ rawconverter/dcrawutils.h, rawconverter/kipidcrawclient.1,
+ rawconverter/mtqueue.h, rawconverter/processcontroller.cpp,
+ rawconverter/processcontroller.h,
+ rawconverter/savesettingswidget.cpp,
+ rawconverter/savesettingswidget.h,
+ rawconverter/singledialog.cpp, rawconverter/singledialog.h:
+ kipi-plugins from trunk : Raw Converter : complete rewrite raw
+ converter core !
+
+ - Removing old external sub program to invoque dcraw instance.
+ - Using multithreaded implementation based on JPEGLossLess
+ plugin core.
+ - New dcraw interface to invoque dcraw binary program directly
+ using a separate thread.
+ - New dcraw settings widget common to batch and single version
+ of converter.
+ - The new implementation always give RAW file thumbnails in
+ batch converter dialog.
+ - New save target file settings widget common to batch and
+ single version of converter.
+ - New option to convert raw file based on last dcraw version
+ avaialble (8.38) and similar than digiKam dcraw setup :
+ * quality decoding (Bilinear, AHD, VND).
+ * Interpolation as 4 colors.
+ * Use super CCD sensor.
+ * Auto Color balance.
+ * Camera whithe balance.
+ * Noise reduction settings.
+ * Highlight clipping (solid white, Unclip, Recontruct using
+ level)
+ * Brighness adjustements.
+
+ - Removing obsolete dcraw options comming from dcraw v. 8.xx :
+ red/blue adjustments.
+
+ - Code simplification and optimisations about compression level
+ with TIFF output files.
+
+ - Fresh screenshot:
+ http://digikam3rdparty.free.fr/Screenshots/newkipirawconverter.png
+
+
+ NOTES :
+
+ - The code have been tested with the last dcraw release from
+ today. Please take a care if you use an with old version.
+ - The code is in beta. Please take a care.
+
+ TODO :
+
+ - Metadata preservation using Exiv2 library.
+ - Embedding sRGB ICC color profile in JPEG/PNG/TIFF files.
+ - More output color space, like Adobe, and WideGamut.
+ - dcraw version detection.
+ - Fix dcraw decoding canceling to stop dcraw imediatly (actually
+ the implementation wait until the current raw file decoding is
+ done).
+ - Fix the dcraw interface class to use bach and single converter
+ plugin at the same time.
+
+ CCMAIL: kde-imaging@kde.org
+ BUG: 128394
+ CCBUGS: 107905
+
+2006-09-12 08:56 cgilles
+
+ * [r583399] jpeglossless/actionthread.h:
+ clean up code
+
+2006-09-12 08:54 cgilles
+
+ * [r583398] jpeglossless/actionthread.cpp,
+ jpeglossless/actionthread.h:
+ clean up code
+
+2006-09-12 08:50 cgilles
+
+ * [r583396] jpeglossless/actions.h:
+ clean up code
+
+2006-09-12 08:48 cgilles
+
+ * [r583395] jpeglossless/mtqueue.h:
+ clean up code
+
+2006-09-12 08:43 cgilles
+
+ * [r583394] jpeglossless/actionthread.cpp,
+ jpeglossless/actionthread.h, jpeglossless/convert2grayscale.cpp,
+ jpeglossless/imageflip.cpp, jpeglossless/imagerotate.cpp,
+ jpeglossless/plugin_jpeglossless.cpp,
+ jpeglossless/plugin_jpeglossless.h, jpeglossless/utils.cpp,
+ jpeglossless/utils.h:
+ clean up code
+
+2006-09-12 08:21 cgilles
+
+ * [r583390] configure.in.in:
+ fix depencies checking
+
+2006-09-12 07:29 cgilles
+
+ * [r583373] NEWS:
+ update
+
+2006-09-12 07:27 cgilles
+
+ * [r583372] configure.in.in:
+ kipi-plugins from trunk : removing libmagick++ depency
+
+2006-09-12 07:26 cgilles
+
+ * [r583371] README, configure.in.bot:
+ kipi-plugins from trunk : removing libmagick++ depency
+
+2006-09-12 07:16 cgilles
+
+ * [r583369] jpeglossless/Makefile.am,
+ jpeglossless/actionthread.cpp,
+ jpeglossless/convert2grayscale.cpp,
+ jpeglossless/convert2grayscale.h, jpeglossless/imageflip.cpp,
+ jpeglossless/imageflip.h, jpeglossless/imagerotate.cpp,
+ jpeglossless/imagerotate.h, jpeglossless/jpegtransform.cpp,
+ jpeglossless/jpegtransform.h, jpeglossless/mtqueue.h,
+ jpeglossless/plugin_jpeglossless.cpp, jpeglossless/utils.cpp,
+ jpeglossless/utils.h:
+ kipi-plugins from trunk : JPEGLossLess BugFix : with some TIFF
+ files generated under win32 and using non-standard tiff tags,
+ libmagick++ crash the host if the same file is parsed using
+ KFileMetaInfo API.
+
+ This is an indeep libtiff problem witch provide common/shared
+ static methods to handle tiff error/warnings. In fact
+ KFileMetaInfo try to use the tiff error static methods from
+ libMagick++ witch are invalid. Using a separate process to
+ perform ImageMagick transforms solve this problem.
+
+ This commit remove libmagick++ depency to process non-jpeg files
+ transforms. The plugin use an ImageMagick runtime dependency
+ instead (convert tool run by a KProcess instance).
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-09-11 17:33 cgilles
+
+ * [r583197] NEWS:
+ update
+
+2006-09-11 14:19 cgilles
+
+ * [r583146] rawconverter/Makefile.am,
+ rawconverter/plugin_rawconverter.cpp:
+ RAW converter use now the common raw file list
+
+2006-09-11 14:18 cgilles
+
+ * [r583145] common, common/include, common/include/rawfiles.h:
+ New folder to store common includes/implementations/pics shared
+ by all kipi-plugins.
+
+ CCMAIL: kde-imaging@kde.org
+
+2006-09-11 08:50 cgilles
+
+ * [r582986] jpeglossless/hi32-action-flip.png,
+ jpeglossless/hi32-action-flipimage.png,
+ jpeglossless/plugin_jpeglossless.cpp:
+ fix icon name
+
+2006-09-11 06:22 cgilles
+
+ * [r582952] jpeglossless/hi32-action-flip_image.png,
+ jpeglossless/hi32-action-flipimage.png,
+ jpeglossless/plugin_jpeglossless.cpp:
+ Fix icon name
+
+2006-09-10 19:58 cguthrie
+
+ * [r582859] galleryexport/gallerylist.cpp,
+ galleryexport/gallerylist.h:
+ Some small double click based niceness on the list of galleries.
+
+2006-09-10 19:21 cguthrie
+
+ * [r582849] galleryexport/Makefile.am,
+ galleryexport/exifrestorer.cpp, galleryexport/exifrestorer.h,
+ galleryexport/gallerytalker.cpp,
+ galleryexport/gallerywindow.cpp, galleryexport/jpegsection.h:
+ Fixes the disappearing EXIF bug. Copied from Flickr.
+ BUG: 129856
+
+2006-09-10 18:55 cguthrie
+
+ * [r582844] galleryexport/Makefile.am,
+ galleryexport/galleries.cpp, galleryexport/galleries.h,
+ galleryexport/gallery.png, galleryexport/galleryconfig.cpp,
+ galleryexport/galleryconfig.h, galleryexport/gallerylist.cpp,
+ galleryexport/gallerylist.h, galleryexport/gallerylogin.cpp,
+ galleryexport/gallerylogin.h, galleryexport/gallerywidget.cpp,
+ galleryexport/gallerywindow.cpp, galleryexport/gallerywindow.h,
+ galleryexport/plugin_galleryexport.cpp,
+ galleryexport/plugin_galleryexport.h:
+ Add support for multiple galleries.
+ Please can people test this? It works for me but there are no
+ doubt issues somewhere ;)
+ BUG: 94494
+
+2006-09-08 00:47 cguthrie
+
+ * [r581948] galleryexport/galleries.cpp,
+ galleryexport/galleries.h, galleryexport/galleryconfig.cpp,
+ galleryexport/galleryconfig.h:
+ Work towards supporting multiple galleries.
+ I wont commit the changes to existing files just yet as it's not
+ ready to go live.
+ I am now able to define, edit, delete multiple galleries which
+ save permanently in kipirc/wallet. Just need to update some more
+ UI elements to use this new list of galleries when logging in.
+ CCBUG: 94494
+
+2006-08-21 12:26 cgilles
+
+ * [r575369] jpeglossless/Makefile.am,
+ jpeglossless/convert2grayscale.cpp, jpeglossless/imageflip.cpp,
+ jpeglossless/imagerotate.cpp, jpeglossless/jpegtransform.cpp,
+ jpeglossless/transupp.c, jpeglossless/transupp.cpp,
+ jpeglossless/transupp.h, jpeglossless/utils.cpp:
+ kipi JPEGLossLess plugin : missing namesapce with transupp.c
+ transupp.c ==> transupp.cpp
+
+2006-08-17 13:22 cgilles
+
+ * [r573896] batchprocessimages/renameimagesoptionsdialog.cpp,
+ batchprocessimages/renameimagesoptionsdialog.h:
+ remove obsolete code (usused since a long time)
+
+2006-08-17 13:21 cgilles
+
+ * [r573895] NEWS:
+ update
+
+2006-08-17 13:16 cgilles
+
+ * [r573894] batchprocessimages/renameimagesbase.ui:
+ Batch rename image kipi plugin : fix min. and max prefix num
+ value from 1 to 999999 (like in digiKam 0.9.0 camera gui)
+ BUG: 127101
+
+2006-08-07 18:57 jahrens
+
+ * [r570803] simpleviewerexport/simpleviewerexport.cpp,
+ simpleviewerexport/svedialog.cpp,
+ simpleviewerexport/svedialog.h:
+ sve stores its configuration now
+
+2006-08-06 20:12 jahrens
+
+ * [r570463] simpleviewerexport/simpleviewerexport.cpp,
+ simpleviewerexport/simpleviewerexport.h:
+ simpleviewerexport is now able to upload the created gallery to
+ a webserver
+
+2006-08-03 09:06 jahrens
+
+ * [r569259] simpleviewerexport/firstrundlg.cpp:
+ simpleviewer launched a new version (1.8) which isn't compatible
+ yet
+
+2006-07-30 17:43 anaselli
+
+ * [r567951] cdarchiving/cdarchiving.cpp:
+ CCBUG: 131284
+ Fixed the case in which under the same tag there are two files
+ with similar name but some upper case letters using HTML
+ interface.
+
+2006-07-30 15:34 anaselli
+
+ * [r567908] cdarchiving/cdarchivingdialog.cpp:
+ added me as contributor
+
+2006-07-30 15:11 anaselli
+
+ * [r567902] cdarchiving/cdarchiving.cpp,
+ cdarchiving/cdarchiving.h:
+ BUG: 131284
+
+2006-07-29 18:06 anaselli
+
+ * [r567662] cdarchiving/cdarchiving.cpp,
+ cdarchiving/cdarchiving.h:
+ BUG: 125766
+
+2006-07-25 18:27 toma
+
+ * [r566299] sendimages/sendimages.cpp:
+ Thunderbird's commandline does not like ( and ). Filter them out
+ in the temp file name.
+ BUG:131343
+
+2006-07-18 18:07 toma
+
+ * [r563875] sendimages/sendimages.cpp:
+ Into the if statement.
+
+2006-07-18 18:05 jaiva
+
+ * [r563874] flickrexport/flickrwindow.cpp:
+ Removed the check for HostSupportsTags feature to be compatible
+ with old libkipi and digikam
+
+2006-07-18 17:39 toma
+
+ * [r563865] sendimages/sendimages.cpp,
+ sendimages/sendimagesdialog.cpp:
+ Adjust sendimages plugin to add the tags when the host apps has
+ them.
+
+2006-07-17 20:05 jaiva
+
+ * [r563539] flickrexport/flickrwidget.cpp,
+ flickrexport/flickrwidget.h, flickrexport/flickrwindow.cpp,
+ flickrexport/flickrwindow.h:
+ Application tags export support added. Digikam tags export works
+ now.
+
+2006-07-17 06:43 jaiva
+
+ * [r563270] flickrexport/flickrwindow.cpp,
+ flickrexport/plugin_flickrexport.cpp:
+ Plugin window is now non-modal, can be run in background
+
+2006-07-16 21:31 cgilles
+
+ * [r563174] rawconverter/batchdialog.cpp:
+ RAW batch converter dialog use a non-modal dialog now. Just need
+ to use a null parent in constructor and start dialog with show()
+ method.
+ A minimize button is also available to reduce the dialog during
+ conversions.
+
+ Vardhman: this is a right example for you to transform you
+ flicker export plugin in non-modal ! Look here :
+ http://digikam3rdparty.free.fr/Screenshots/batchrawconverter-nonmodal.png
+
+ CCMAIL: kde-imaging@kde.org, vardhman@gmail.com
+
+2006-07-15 13:38 jaiva
+
+ * [r562627] flickrexport/flickritem.h,
+ flickrexport/flickrtalker.cpp, flickrexport/flickrtalker.h,
+ flickrexport/flickrwidget.cpp, flickrexport/flickrwidget.h,
+ flickrexport/flickrwindow.cpp, flickrexport/flickrwindow.h:
+ Solves #128522. Removing the question regarding username. Shows
+ username in the plugin window and can be changed from there.
+
+2006-07-09 15:24 anaselli
+
+ * [r560227] ChangeLog:
+ svn2log.py seems to work again here... fixed changelogs entries
+
+v 0.1.2 - 2006-07-08
+----------------------------------------------------------------------------
+
+2006-07-08 15:50 +0000 [r559907] anaselli
+
+ * kipi-plugins/ChangeLog: new changelog svn2log.py seems to be
+ broken now, added entries by hands :(
+
+2006-07-08 14:55 +0000 [r559822] anaselli
+
+ * prepare_kipiplugins.rb, kipi-plugins/kipi-plugins.lsm: prepare
+ new release kipi-plugins 0.1.2 to fix missed po files, hope this
+ time is good...
+
+2006-06-29 21:02 +0000 [r556299] anaselli
+
+ * kipi-plugins/ChangeLog: missed 0.1.1 entry
+
+2006-06-27 22:37 +0000 [r555589] toma
+
+ * kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp: Fix comment, add a
+ fixme. Change the default path of thunderbird. I just hope that's
+ the name on more distros. CCMAIL: kde-imaging@kde.org
+
+2006-06-27 22:24 +0000 [r555585] toma
+
+ * kipi-plugins/sendimages/sendimages.cpp,
+ kipi-plugins/sendimages/sendimagesdialog.cpp: The dialog said
+ 'Kmail' but started the default mailer. Renamed that to
+ 'Default'. And added KMail has fixed setting. I so want to email
+ pictured.
+
+v 0.1.1 - 2006-06-26
+----------------------------------------------------------------------------
+
+2006-06-26 19:19 +0000 [r555236] anaselli
+
+ * prepare_kipiplugins.rb, kipi-plugins/kipi-plugins.lsm,
+ release_kipiplugins.rb: prepeare kipi-plugins 0.1.1 for missed po
+ files
+
+2006-06-25 15:57 +0000 [r554870-554871] gateau
+
+ * kipi-plugins/htmlexport/TODO: Video
+
+ * kipi-plugins/htmlexport/generator.cpp: Do not generate entries
+ for video. Patch by Erik <edg72@home.nl>
+
+v 0.1.0 - 2006-06-22
+----------------------------------------------------------------------------
+
+2006-06-22 21:15 +0000 [r554011] anaselli
+
+ * kipi-plugins/ChangeLog, kipi-plugins/NEWS,
+ kipi-plugins/kipi-plugins.lsm: prepare release 0.1.0 final
+
+2006-06-04 11:46 +0000 [r547996] cgilles
+
+ * kipi-plugins/rawconverter/dcrawprocess.cpp: add debug messages on
+ command line
+
+2006-06-04 10:35 +0000 [r547984] cguthrie
+
+ * kipi-plugins/galleryexport/gallerytalker.cpp: Add support for
+ multiple cookies by commiting a slightly modified patch. Tested
+ on G1/G2 for a single cookie environment. Please reopen if my
+ variation on the patch in some way doesn't work for you. BUG:
+ 123141
+
+2006-06-02 19:32 +0000 [r547624-547625] anaselli
+
+ * kipi-plugins/imagesgallery/up.png (removed),
+ kipi-plugins/imagesgallery/valid-html401.png (removed),
+ kipi-plugins/imagesgallery/Makefile.am,
+ kipi-plugins/imagesgallery/gohome.png (removed): and moved png
+ file from old imagesgallery plugin
+
+ * kipi-plugins/cdarchiving/up.png (added),
+ kipi-plugins/cdarchiving/cdarchiving.h,
+ kipi-plugins/cdarchiving/valid-html401.png (added),
+ kipi-plugins/cdarchiving/Makefile.am,
+ kipi-plugins/cdarchiving/gohome.png (added),
+ kipi-plugins/cdarchiving/cdarchiving.cpp: Added webifyFileName
+ (from html gallery) and moved png file from old imagesgallery
+ plugin BUG: 101656 BUG: 128125
+
+2006-06-01 17:20 +0000 [r547312] cguthrie
+
+ * kipi-plugins/galleryexport/gallerytalker.cpp: Fix the invalid
+ response error when uploading photos to gallery1. It would appear
+ G1 is outputting some information stating that it is resizing the
+ uploaded image and prevents us properly detecting the
+ #__GR2PROTO__ trigger. BUG: 123978
+
+2006-06-01 08:15 +0000 [r547200] cguthrie
+
+ * kipi-plugins/galleryexport/gallerympform.h,
+ kipi-plugins/galleryexport/gallerytalker.h,
+ kipi-plugins/galleryexport/gallerywindow.cpp,
+ kipi-plugins/galleryexport/galleryviewitem.cpp,
+ kipi-plugins/galleryexport/gallerywindow.h,
+ kipi-plugins/galleryexport/gallerympform.cpp,
+ kipi-plugins/galleryexport/gallerytalker.cpp: Misc. gallery
+ version related changes: * Rather than pass the g2 flag about,
+ make it a static call within GalleryTalker. * Correct the
+ auto-appended path for the gallery url when in g1 mode. * Fix the
+ album ref_num when in g1 mode. * Don't display the 'name' in g2
+ mode (in g2 this 'name' is actually a ref_num) CCMAIL:
+ kde-imaging@kde.org
+
+2006-05-28 15:13 +0000 [r545933] anaselli
+
+ * kipi-plugins/README: added Gallery 2 in README and changed
+ imagesgallery position CCMAIL: kde-imaging@kde.org
+
+2006-05-28 15:07 +0000 [r545930] anaselli
+
+ * kipi-plugins/AUTHORS: Added Colin Guthrie as a contributor
+ CCMAIL: colin@guthr.ie
+
+2006-05-28 15:03 +0000 [r545927] anaselli
+
+ * kipi-plugins/galleryexport/gallerympform.h,
+ kipi-plugins/galleryexport/gallerympform.cpp,
+ kipi-plugins/galleryexport/gallerytalker.cpp: Code review by
+ Colin Guthrie CCMAIL: colin@guthr.ie
+
+2006-05-28 09:28 +0000 [r545725] anaselli
+
+ * kipi-plugins/galleryexport/gallerympform.h,
+ kipi-plugins/galleryexport/gallerytalker.h,
+ kipi-plugins/galleryexport/gallerywindow.cpp,
+ kipi-plugins/galleryexport/gallerylogin.cpp,
+ kipi-plugins/galleryexport/gallerywindow.h,
+ kipi-plugins/galleryexport/gallerylogin.h,
+ kipi-plugins/galleryexport/gallerympform.cpp,
+ kipi-plugins/galleryexport/gallerytalker.cpp: Added a check box
+ and split the code to manage Gallery 2 in 0.1.0 CCMAIL:
+ kde-imaging@kde.org
+
+2006-05-21 13:32 +0000 [r543161] anaselli
+
+ * kipi-plugins/galleryexport/gallerywindow.cpp,
+ kipi-plugins/galleryexport/gallerytalker.cpp: applied patche by
+ Colin Guthrie Please next time open a new bug report. Thanks
+ CCBUG: 96352
+
+2006-05-20 17:19 +0000 [r542934] anaselli
+
+ * kipi-plugins/galleryexport/gallerywindow.cpp,
+ kipi-plugins/galleryexport/gallerympform.cpp,
+ kipi-plugins/galleryexport/gallerytalker.cpp,
+ kipi-plugins/galleryexport/galleryitem.h: applied patches by
+ Boris Kavod, Colin Guthrie and David Bremner BUG: 96352
+
+2006-05-20 10:36 +0000 [r542780] anaselli
+
+ * kipi-plugins/NEWS: wrong year :)
+
+2006-05-16 22:06 +0000 [r541654] ach
+
+ * kipi-plugins/jpeglossless/Makefile.am: kipi-plugins: disable
+ enabe-final for jpeglossless plugins again. Was removed by
+ mistake in a revert
+
+2006-05-16 21:37 +0000 [r541646] ach
+
+ * kipi-plugins/ChangeLog, kipi-plugins/NEWS: kipi-plugins: update
+ NEWS and Changelog
+
+2006-05-16 01:29 +0000 [r541356] ach
+
+ * kipi-plugins/slideshow/Makefile.am,
+ kipi-plugins/galleryexport/Makefile.am,
+ kipi-plugins/htmlexport/Makefile.am,
+ kipi-plugins/findimages/Makefile.am,
+ kipi-plugins/batchprocessimages/Makefile.am,
+ kipi-plugins/kameraklient/Makefile.am,
+ kipi-plugins/calendar/Makefile.am,
+ kipi-plugins/timeadjust/Makefile.am,
+ kipi-plugins/helloworld/Makefile.am,
+ kipi-plugins/flickrexport/Makefile.am,
+ kipi-plugins/printwizard/Makefile.am,
+ kipi-plugins/jpeglossless/Makefile.am,
+ kipi-plugins/simpleviewerexport/Makefile.am,
+ kipi-plugins/sendimages/Makefile.am,
+ kipi-plugins/acquireimages/Makefile.am,
+ kipi-plugins/cdarchiving/Makefile.am,
+ kipi-plugins/rawconverter/Makefile.am,
+ kipi-plugins/imagesgallery/Makefile.am,
+ kipi-plugins/wallpaper/Makefile.am,
+ kipi-plugins/mpegencoder/Makefile.am: kipi-plugins: link only
+ against and all libraries that contain symbols used by the
+ plugin. Reduces the # of library packages referenced in NEEDED
+ section of plugins by ~ factor of two (35 to 18 in kubuntu)
+ CCMAIL: kde-imaging@kde.org
+
+2006-05-15 19:35 +0000 [r541235] toma
+
+ * kipi-plugins/mpegencoder/kimg2mpg.cpp: Always return two numbers
+ for r,g and b, else image2mpg will fail. Maybe this is the root
+ of all evil for a long time? BUG: 127219
+
+2006-05-14 11:57 +0000 [r540657] toma
+
+ * kipi-plugins/calendar/calpainter.cpp: Look at the settings to
+ find out the first day of the week and adjust the calendars for
+ that. So if the first day of the week in your country is
+ wednesday, that will work now. CCBUG: 111697 BUG: 117105
+
+2006-05-14 10:50 +0000 [r540640] toma
+
+ * kipi-plugins/calendar/caltemplate.cpp: Draw grid by default
+ CCBUG: 116970
+
+2006-05-14 10:21 +0000 [r540633] toma
+
+ * kipi-plugins/calendar/monthwidget.h,
+ kipi-plugins/calendar/calselect.cpp,
+ kipi-plugins/calendar/calsettings.cpp,
+ kipi-plugins/calendar/calwizard.cpp,
+ kipi-plugins/calendar/monthwidget.cpp: - Cleanup some warnings. -
+ when you request a calendar and have some images selected in the
+ host application, use those images for the months.
+
+2006-05-13 20:54 +0000 [r540535] anaselli
+
+ * kipi-plugins/NEWS: Added all the bug fixed by 0.1.0rc2 release
+ and missed SimpleViewer CCMAIL: kde-imaging@kde.org
+
+2006-05-13 19:17 +0000 [r540527] cgilles
+
+ * kipi-plugins/jpeglossless/Makefile.am: revert to old version
+ broken by a previous commit.
+
+2006-05-12 13:52 +0000 [r540067] cgilles
+
+ * kipi-plugins/jpeglossless/Makefile.am: kipi-plugin JPEGLossLess :
+ fix exception rules in makefile.
+
+2006-05-10 19:26 +0000 [r539484] cgilles
+
+ * kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imagerotate.cpp: JpegLossLess plugin :
+ revert. wrong commit for these files. This code is not ready to
+ use (:=)))
+
+2006-05-10 19:22 +0000 [r539482] cgilles
+
+ * kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ kipi-plugins/jpeglossless/imageflip.cpp,
+ kipi-plugins/jpeglossless/imagerotate.cpp,
+ kipi-plugins/jpeglossless/Makefile.am: JpegLossLess plugin :
+ backport fix from digiKam (see file 126326 in B.K.O) about an
+ incompatibility with JPEG implementation and "enable-final"
+ option! CCMAIL: kde-imaging@kde.org CCBUGS: 126326
+
+2006-05-08 18:24 +0000 [r538737] gateau
+
+ * kipi-plugins/README: Added dependency on libxslt for htmlexport
+
+2006-05-07 11:34 +0000 [r538265] jahrens
+
+ * kipi-plugins/README: Plugin list update
+
+2006-05-06 22:01 +0000 [r538121] toma
+
+ * kipi-plugins/ChangeLog, libkexif/ChangeLog, libkipi/ChangeLog:
+ updates
+
+v0.1.0-rc2 - Last Changed Rev: 538177 - 2006-05-03
+----------------------------------------------------------------------------
+
+2006-05-06 20:45 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/ChangeLog,
+ trunk/extragear/libs/libkexif/ChangeLog,
+ trunk/extragear/libs/libkipi/ChangeLog: fix ChangeLog files
+
+2006-05-06 20:42 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/README: Update plugins list
+
+2006-05-06 20:24 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/kipi-plugins.lsm: updated
+ version for incoming release 0.1.0rc2
+
+2006-05-06 20:21 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/README: add libmagick++ depency
+
+2006-05-05 07:27 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/plugin_rawconverter.cpp:
+ Kipi Raw converter : - improvements of batch dialog : set cursor
+ busy during conversion. fix missing widget to disable. - fix
+ error message if dcraw cannot be found when batch/single
+ converter is started. CCMAIL : kde-imaging@kde.org,
+ digikam-devel@kde.org
+
+2006-05-04 21:58 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/themes/matrix/matrix.desktop,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/simple/simple.desktop,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/snow.desktop:
+ Changed url to my email address
+
+2006-05-04 20:56 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp:
+ Kipi Raw converter (batch mode) : improvements of dialog : blink
+ icon in Raw list files during conversion. CCMAIL :
+ kde-imaging@kde.org, digikam-devel@kde.org
+
+2006-05-04 19:55 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.h:
+ Kipi Raw converter (batch mode) : missing to toogle busy 3
+ QLabel during conversions.
+
+2006-05-04 19:50 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/Makefile.am: Removed
+ imagesgallery to avoid to compile it to build 0.1.0rc2 (please
+ re-add after release 0.1.0 rc2 if needed) CCMAIL:
+ kde-imaging@kde.org
+
+2006-05-04 19:46 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/ChangeLog: Added revision
+ marker
+
+2006-05-04 19:38 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/previewwidget.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/previewwidget.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.h:
+ Kipi Raw converter (single mode) : improvements of dialog : -
+ toogle busy mouse cursor during preview rendering and
+ conversion. - blink a message in preview widget during preview
+ rendering and conversion. CCMAIL : kde-imaging@kde.org,
+ digikam-devel@kde.org
+
+2006-05-04 18:48 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/plugin_rawconverter.h:
+ Kipi Raw converter (batch and single mode) : only use real Raw
+ files from current image collection selected checking file
+ extensions. This way prevent any problems with dcraw if we parse
+ JPEG files or TIFF/EP 16 bits files. CCMAIL :
+ kde-imaging@kde.org, digikam-devel@kde.org
+
+2006-05-04 13:31 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp:
+ Kipi Raw converter (batch mode) : fix 'Convert' and 'Abort'
+ buttons status when files list is empty and when all conversions
+ are complete.
+
+2006-05-04 13:13 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/clistviewitem.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/dmessagebox.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/dmessagebox.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/processcontroller.cpp:
+ Kipi Raw converter (batch mode) : - Improved batch dialog to
+ handle properlly non Raw files. - No need to use a separate
+ dialog to list non-Raw files. Just disable all non Raw file
+ items in the list. That all... - Code simplification again. -
+ Fix i18n again. CCMAIL : kde-imaging@kde.org,
+ digikam-devel@kde.org
+
+2006-05-04 10:58 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/clistviewitem.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/dcrawprocess.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/dmessagebox.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/dmessagebox.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/plugin_rawconverter.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/plugin_rawconverter.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/previewwidget.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/previewwidget.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/processcontroller.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/processcontroller.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.h:
+ Kipi Raw converter (batch and single mode) : support of PNG
+ format like ouput file - PNG file format is now the default
+ output format used by plugin. Max PNG compression is used. - set
+ JPEG compression is 100 by default to give a max quality of
+ output image. - Code cleanup and optimization. - Fix i18n at
+ all. CCMAIL : kde-imaging@kde.org, digikam-devel@kde.org BUG:
+ 93787
+
+2006-05-04 07:41 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp:
+ fix i18n
+
+2006-05-04 07:40 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp:
+ Kipi Raw converter (batch mode) : polish progress bar rule
+
+2006-05-03 23:36 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.h:
+ Kipi Raw converter (batch mode) : fix progress bar rule when
+ abort button is pressed
+
+2006-05-03 23:27 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp:
+ Kipi Raw converter (batch mode) : improvements of dialog. -
+ Using KDialogBase instead QDialog. - Using standard KDE spacing
+ and marging at all. - Source code cleanup and simplification.
+ CCMAIL: kde-imaging@kde.org, digikam-devel@kde.org
+
+2006-05-03 22:51 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/cspinbox.h,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp:
+ Kipi Raw converter (batch mode) : make it possible to enter
+ numbers with 2 digit precision in settings. - no need to
+ re-invent the wheel. We use KDoubleNumInput widget at all. -
+ Removing old spinbox widget. - Fix dialog layout. - Fix widget
+ order (label before a setting). CCMAIL: kde-imaging@kde.org,
+ digikam-devel@kde.org BUG : 101455
+
+2006-05-03 22:17 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.h:
+ Kipi Raw converter (single mode) : make it possible to enter
+ numbers with 2 digit precision in settings. - no need to
+ re-invent the wheel. We use KDoubleNumInput widget at all. - Fix
+ dialog layout. - Fix widget order (label before a setting).
+ CCMAIL: kde-imaging@kde.org, digikam-devel@kde.org CCBUGS :
+ 101455
+
+2006-05-03 21:21 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.h:
+ Kipi Raw converter (single mode) : improvements of dialog. -
+ Using KDialogBase instead QDialog. - Using standard KDE spacing
+ and marging at all. - Source code cleanup and simplification.
+ CCMAIL: kde-imaging@kde.org, digikam-devel@kde.org
+
+2006-05-03 20:41 toma
+
+ * trunk/extragear/libs/kipi-plugins/ChangeLog,
+ trunk/extragear/libs/kipi-plugins/NEWS: Update for release
+
+2006-05-03 20:16 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.h:
+ Kipi Raw converter (single mode) : fill a default file name into
+ the save as dialog. CCMAIL: kde-imaging@kde.org,
+ digikam-devel@kde.org BUG: 103763
+
+2006-05-03 17:59 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/configure.in.in: fix c++ flag
+
+2006-05-03 16:12 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/AUTHORS: Wrong email addr
+
+2006-05-03 09:05 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/actions.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/actionthread.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/actionthread.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.h:
+ fix email
+
+2006-05-03 08:39 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.h:
+ polish
+
+2006-05-03 08:20 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp:
+ kipi jpeglosslessplugin : If an error is detected during
+ rotate/flip/convertB&W image process, displaying error messages
+ into progress dialog like a warning. Note that all message from
+ ImageMagick are reported too. CCMAIL: kde-imaging@kde.org,
+ digikam-devel@kde.org
+
+2006-05-03 02:12 blackie
+
+ * trunk/extragear/libs/kipi-plugins/findimages/imagesimilaritydata.h:
+ fixed mitchmached malloc/delete.
+
+2006-05-02 21:42 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/configure.in.bot,
+ trunk/extragear/libs/kipi-plugins/configure.in.in: Added a test
+ check for libMagik needed by jpeglossless plugin CCMAIL:
+ kde-imaging@kde.org, digikam-devel@kde.org
+
+2006-05-02 20:11 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/messagebox.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/messagebox.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/progressdlg.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/progressdlg.h:
+ kipi jpeglosslessplugin : - using standard kipi batch progress
+ dialog to display process/error messages. No need to have 2
+ separate dialogs to render jobs. This way look like others kipi
+ plugins. - Remove obsolete dialogs. - Code cleanup and
+ simplifications. CCMAIL: kde-imaging@kde.org,
+ digikam-devel@kde.org
+
+2006-05-02 19:23 toma
+
+ * trunk/extragear/libs/kipi-plugins/calendar/calwizard.cpp: Start
+ KJobViewer at the last possible moment and add a note just
+ before generating. BUG: 120868
+
+2006-05-02 19:04 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/actionthread.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/actionthread.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.h:
+ polish
+
+2006-05-02 18:56 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/AUTHORS,
+ trunk/extragear/libs/kipi-plugins/kipiplugins.kdevelop: fix email
+
+2006-05-02 17:31 toma
+
+ * trunk/extragear/libs/kipi-plugins/AUTHORS: Update
+
+2006-05-02 15:24 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/actions.h: polish
+
+2006-05-02 15:22 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/mtqueue.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.h:
+ polish
+
+2006-05-02 15:18 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp:
+ polish
+
+2006-05-02 15:16 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.h:
+ polish
+
+2006-05-02 14:03 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/convert2grayscale.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/imageflip.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/imageflip.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/imagerotate.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/imagerotate.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/jpegtransform.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/jpegtransform.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/messagebox.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/messagebox.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/progressdlg.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/progressdlg.h,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/utils.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/utils.h: kipi
+ jpeglosslessplugin : - using ImageMagick C++ API to perform
+ action in non JPEG image. 16 bits images are preserved now. - Do
+ not handle RAW files type to perform action. - Add libMagick++
+ depency. - Remove libTiff API. - Simplify file name in dialog.
+ No need the complete filepath here to prevent large dialogs
+ size. Nota : a libMagick++ API detection is require into
+ kipi-plugins .configure file. CCMAIL: kde-imaging@kde.org,
+ digikam-devel@kde.org BUG: 123499
+
+2006-05-01 21:09 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/convert2grayscale.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/imageflip.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/imagerotate.cpp:
+ JPEGLossLess kipi plugin : disable Qt API method to
+ rotate/flip/convertB&W non JPEG files else RAW/TIFF/PNG 16 bits
+ images are broken ! This is want mean that only JPEG files will
+ be processed by this plugin. To solve this problem, Image Magick
+ API need to be used in this place instead Qt API. Nota : this
+ B.K.O file can be toggle from critic to normal. CCMAIL:
+ kde-imaging@kde.org CCBUGS: 123499
+
+2006-05-01 16:39 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/AUTHORS: Added me as a
+ contributor
+
+2006-05-01 16:34 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/ChangeLog: Added bugs fixed
+ for next release
+
+2006-05-01 15:36 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/TODO,
+ trunk/extragear/libs/kipi-plugins/htmlexport/theme.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/theme.h,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themepage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlexport/wizard.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/wizard.h: Show
+ theme info alongside theme list.
+
+2006-04-30 09:16 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/themes/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/simple,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/simple/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/simple/simple.desktop,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/simple/style.css,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/simple/template.xsl:
+ New theme: simple
+
+2006-04-30 09:14 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp:
+ Generate square thumbnails. It's easier to theme this way.
+
+2006-04-26 21:53 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/matrix/template.xsl,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/matrix/template.xslt,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/template.xsl,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/template.xslt:
+ Changed XSLT files extensions to .xsl. Seems to be more common.
+
+2006-04-26 11:52 blackie
+
+ * trunk/extragear/libs/kipi-plugins/findimages/compareoperation.h:
+ ups forgot to add
+
+2006-04-24 21:37 bram
+
+ * trunk/extragear/artwork/smoothslidesaver/src/smoothslidesaverui.ui,
+ trunk/extragear/graphics/kst/src/libkstapp/curvedialogwidget.ui,
+ trunk/extragear/graphics/kst/src/libkstapp/datawizard.ui,
+ trunk/extragear/graphics/kst/src/libkstapp/kstsettingsdlg.ui,
+ trunk/extragear/graphics/kst/src/libkstapp/kstviewmanager.ui,
+ trunk/extragear/libs/kipi-plugins/htmlexport/imagesettingspage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlexport/outputpage.ui,
+ trunk/extragear/multimedia/k3b/src/projects/base_k3bbootimageview.ui,
+ trunk/extragear/multimedia/k3b/src/projects/base_k3bmovixoptionswidget.ui,
+ trunk/extragear/multimedia/k3b/src/rip/base_k3bvideodvdrippingwidget.ui,
+ trunk/extragear/network/kftpgrabber/src/ui/config_general.ui,
+ trunk/extragear/network/kmyfirewall/KMFSysTray/details_designer.ui,
+ trunk/extragear/network/kmyfirewall/KMFSysTray/mainwidget_designer.ui,
+ trunk/extragear/network/kmyfirewall/kmyfirewall/kmfwidgets/kmyfirewallhostwidget.ui,
+ trunk/extragear/network/kmyfirewall/kmyfirewall/kmfwidgets/kmyfirewallinterfacewidget.ui,
+ trunk/extragear/network/kmyfirewall/kmyfirewall/kmfwidgets/kmyfirewallmynetworkwidget.ui,
+ trunk/extragear/network/kmyfirewall/kmyfirewall/kmfwidgets/kmyfirewallsystemsettingslinux.ui,
+ trunk/extragear/network/knemo/kcm/configdlg.ui,
+ trunk/extragear/network/knemo/knemod/interfacestatisticsdlg.ui,
+ trunk/extragear/network/knemo/knemod/interfacestatusdlg.ui,
+ trunk/extragear/network/knetstats/src/configurebase.ui,
+ trunk/extragear/network/knetstats/src/statisticsbase.ui,
+ trunk/extragear/network/konversation/src/autoreplace_preferencesui.ui,
+ trunk/extragear/network/konversation/src/chatwindowappearance_preferences.ui,
+ trunk/extragear/network/konversation/src/fontappearance_preferences.ui,
+ trunk/extragear/network/konversation/src/generalbehavior_preferences.ui,
+ trunk/extragear/network/konversation/src/quickbuttons_preferencesui.ui,
+ trunk/extragear/network/konversation/src/searchbarbase.ui,
+ trunk/extragear/network/konversation/src/tabbar_preferences.ui,
+ trunk/extragear/network/ktorrent/apps/ktorrent/downloadpref.ui,
+ trunk/extragear/network/ktorrent/apps/ktorrent/generalpref.ui,
+ trunk/extragear/network/ktorrent/apps/ktorrent/queuedlg.ui,
+ trunk/extragear/network/ktorrent/apps/ktupnptest/mainwidget.ui,
+ trunk/extragear/network/ktorrent/plugins/infowidget/infowidgetbase.ui,
+ trunk/extragear/network/ktorrent/plugins/infowidget/iwpref.ui,
+ trunk/extragear/network/ktorrent/plugins/infowidget/trackerviewbase.ui,
+ trunk/extragear/network/ktorrent/plugins/ipfilter/convert_dlg.ui,
+ trunk/extragear/network/ktorrent/plugins/scheduler/bwspage.ui,
+ trunk/extragear/office/datakiosk/src/relationeditordialog.ui,
+ trunk/extragear/utils/katapult/common/imagedisplaysettings.ui,
+ trunk/extragear/utils/katapult/katapult/confcatalogs.ui,
+ trunk/extragear/utils/katapult/katapult/confdisplay.ui,
+ trunk/extragear/utils/katapult/katapult/confgeneral.ui,
+ trunk/extragear/utils/katapult/plugins/catalogs/amarokcatalog/settings.ui,
+ trunk/extragear/utils/katapult/plugins/catalogs/bookmarkcatalog/settings.ui,
+ trunk/extragear/utils/katapult/plugins/catalogs/calculatorcatalog/settings.ui,
+ trunk/extragear/utils/katapult/plugins/catalogs/documentcatalog/settings.ui,
+ trunk/extragear/utils/katapult/plugins/catalogs/programcatalog/settings.ui,
+ trunk/extragear/utils/keurocalc/calculator.ui,
+ trunk/extragear/utils/keurocalc/settingsdialog.ui: Massive
+ fixuifiles
+
+2006-04-24 16:59 blackie
+
+ * trunk/extragear/libs/kipi-plugins/findimages/actions.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/fastcompare.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/fastcompare.h,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.h,
+ trunk/extragear/libs/kipi-plugins/findimages/fuzzycompare.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/fuzzycompare.h,
+ trunk/extragear/libs/kipi-plugins/findimages/plugin_findimages.cpp:
+ using QThread::terminate for cancel operation made the plugin go
+ bezerk. So now I ask it nicely to stop processing instead.
+
+2006-04-23 23:41 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/TODO: Updated
+
+2006-04-23 23:35 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/htmlexportconfig.kcfg,
+ trunk/extragear/libs/kipi-plugins/htmlexport/imagesettingspage.ui:
+ Implemented quality support
+
+2006-04-23 22:34 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/imagesettingspage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlexport/outputpage.ui:
+ Remove margins
+
+2006-04-23 22:24 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/imagesettingspage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlexport/outputpage.ui:
+ Buddy-ification
+
+2006-04-23 22:22 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/imagesettingspage.ui:
+ Use a separate checkbox to enable full image resizing. This make
+ it possible to setup a buddy for the fullsize spinbox.
+
+2006-04-23 22:07 gateau
+
+ * trunk/extragear/libs/configure.in.in,
+ trunk/extragear/libs/kipi-plugins/htmlexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/galleryinfo.h,
+ trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/htmlexportconfig.kcfg,
+ trunk/extragear/libs/kipi-plugins/htmlexport/htmlexportconfig.kcfgc,
+ trunk/extragear/libs/kipi-plugins/htmlexport/imagesettingspage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlexport/outputpage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlexport/plugin.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/theme.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/theme.h,
+ trunk/extragear/libs/kipi-plugins/htmlexport/wizard.cpp: Use
+ KConfigXT to store settings of the htmlexport plugin.
+
+2006-04-23 15:28 blackie
+
+ * trunk/extragear/libs/kipi-plugins/findimages/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/findimages/actions.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/actions.h,
+ trunk/extragear/libs/kipi-plugins/findimages/displaycompare.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/fastcompare.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/fastcompare.h,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.h,
+ trunk/extragear/libs/kipi-plugins/findimages/fuzzycompare.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/fuzzycompare.h,
+ trunk/extragear/libs/kipi-plugins/findimages/plugin_findimages.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/plugin_findimages.h:
+ avoid flooding of GUI thread
+
+2006-04-22 23:30 blackie
+
+ * trunk/extragear/libs/kipi-plugins/findimages/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/findimages/actions.h,
+ trunk/extragear/libs/kipi-plugins/findimages/displaycompare.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/displaycompare.h,
+ trunk/extragear/libs/kipi-plugins/findimages/fastcompare.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/fastcompare.h,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.h,
+ trunk/extragear/libs/kipi-plugins/findimages/fuzzycompare.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/fuzzycompare.h,
+ trunk/extragear/libs/kipi-plugins/findimages/imagesimilaritydata.h,
+ trunk/extragear/libs/kipi-plugins/findimages/plugin_findimages.cpp:
+ refactored the image compares into classes of their own, plus
+ some cleanup in usage of pointers
+
+2006-04-22 21:06 blackie
+
+ * trunk/extragear/libs/kipi-plugins/findimages,
+ trunk/extragear/libs/kipi-plugins/findimages/Doxyfile,
+ trunk/extragear/libs/kipi-plugins/findimages/displaycompare.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicatedialog.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.h,
+ trunk/extragear/libs/kipi-plugins/findimages/plugin_findimages.cpp:
+ Started maintenance of the Find Images plug-in. - added busy
+ cursors at various places. - fixed a layout error - added myself
+ as maintainer.
+
+2006-04-18 22:08 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/themes/matrix/template.xslt,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/template.xslt:
+ Use first image as collection image
+
+2006-04-18 17:45 gateau
+
+ * trunk/extragear/libs/kipi-plugins/kameraklient/cameraselection.cpp,
+ trunk/extragear/libs/kipi-plugins/kameraklient/cameraselection.h,
+ trunk/extragear/libs/kipi-plugins/kameraklient/mtlist.h,
+ trunk/extragear/libs/kipi-plugins/kameraklient/mtqueue.h,
+ trunk/extragear/libs/kipi-plugins/kameraklient/savefiledialog.cpp,
+ trunk/extragear/libs/kipi-plugins/kameraklient/savefiledialog.h,
+ trunk/extragear/libs/kipi-plugins/kameraklient/thumbitem.cpp,
+ trunk/extragear/libs/kipi-plugins/kameraklient/thumbitem.h,
+ trunk/extragear/libs/kipi-plugins/kameraklient/thumbview.cpp,
+ trunk/extragear/libs/kipi-plugins/kameraklient/thumbview.h:
+ Added missing copyrights, based on Digikam CVS:
+ http://cvs.sourceforge.net/viewcvs.py/digikam/digikam3/digikamcameraclient/cameraui/
+ BUG: 99157
+
+2006-04-15 14:01 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp:
+ A workaround stops the process if the target directory is not
+ writable. BUG: 117397
+
+2006-04-15 10:23 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp:
+ - typo BUG: 108945
+
+2006-04-14 18:20 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/galleryinfo.h,
+ trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/theme.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/theme.h,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/matrix/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/matrix/matrix.desktop,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/snow.desktop,
+ trunk/extragear/libs/kipi-plugins/htmlexport/wizard.cpp: Started
+ implementing theme description
+
+2006-04-09 22:19 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/TODO,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/matrix/template.xslt,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/template.xslt:
+ Implemented support for special case: "only one album", through
+ XSL.
+
+2006-04-09 19:49 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/TODO,
+ trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/matrix/template.xslt,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/template.xslt:
+ Added last missing translation. CCMAIL: kde-imaging@kde.org
+
+2006-04-08 15:53 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/acquireimages/plugin_acquireimages.cpp:
+ - fix bug 114519 BUG: 114519
+
+2006-04-04 21:23 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/mpegencoder/kimg2mpg.cpp: -
+ fix bug 114514 BUG: 114514
+
+2006-03-28 23:27 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/TODO,
+ trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp:
+ Properly quote XSLT params (scary!)
+
+2006-03-28 23:25 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/TODO: Updated,
+ splitted in two
+
+2006-03-25 19:37 jaiva
+
+ * trunk/extragear/libs/kipi-plugins/flickrexport/ChangeLog,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrtalker.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwidget.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwidget.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.h:
+ Improvement release, Allows Current selection to be uploaded,
+ and some UI improvements
+
+2006-03-22 23:00 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp: Use
+ local8Bit() to pass filenames to libxslt
+
+2006-03-12 22:04 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/mpegencoder/images2mpg: -
+ Changed project URL - Added a note why I inserted '-S' opiton
+ CCBUG:109739
+
+2006-03-11 22:06 anaselli
+
+ * trunk/extragear/libs/kipi-plugins/mpegencoder/images2mpg,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/kimg2mpg.h: fix
+ bugs #114515, #109739
+
+2006-03-08 23:02 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/TODO,
+ trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/template.xslt:
+ Started implementing i18n support, using XSLT params
+
+2006-03-05 23:32 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp:
+ Produce unique filenames using titles. This way it should be
+ possible to implement incremental updates of the gallery.
+
+2006-03-04 22:50 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlexport/kipiplugin_htmlexport.desktop,
+ trunk/extragear/libs/kipi-plugins/htmlexport/kipiplugin_htmlgallery.desktop:
+ Finished renaming
+
+2006-03-04 22:47 gateau
+
+ * trunk/extragear/libs/kipi-plugins/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/configure.in.bot,
+ trunk/extragear/libs/kipi-plugins/configure.in.in,
+ trunk/extragear/libs/kipi-plugins/htmlexport,
+ trunk/extragear/libs/kipi-plugins/htmlexport/.vimrc,
+ trunk/extragear/libs/kipi-plugins/htmlexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/TODO,
+ trunk/extragear/libs/kipi-plugins/htmlexport/galleryinfo.h,
+ trunk/extragear/libs/kipi-plugins/htmlexport/generator.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/generator.h,
+ trunk/extragear/libs/kipi-plugins/htmlexport/imagesettingspage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlexport/kipiplugin_htmlgallery.desktop,
+ trunk/extragear/libs/kipi-plugins/htmlexport/outputpage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlexport/plugin.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/plugin.h,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/matrix/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/next.svg,
+ trunk/extragear/libs/kipi-plugins/htmlexport/wizard.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlexport/wizard.h,
+ trunk/extragear/libs/kipi-plugins/htmlexport/xmlutils.h,
+ trunk/extragear/libs/kipi-plugins/htmlgallery: Renamed
+ htmlgallery to htmlexport
+
+2006-03-03 23:20 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlgallery/TODO,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/generator.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/xmlutils.h: -
+ Moved xml classes to their own files - Reimplemented xml
+ generation using libxml
+
+2006-03-03 19:52 toma
+
+ * trunk/extragear/libs/kipi-plugins/configure.in.bot: Adds libxslt
+ too the bot CCMAIL: aurelien.gateau@free.fr
+
+2006-03-02 14:22 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/template.xslt:
+ Removed failed attempt at i18n support
+
+2006-03-02 14:21 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlgallery/wizard.cpp: Fixed
+ the way themes are found
+
+2006-03-02 13:56 gateau
+
+ * trunk/extragear/libs/kipi-plugins/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/configure.in.in,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/Makefile.am: Fixed
+ compilation
+
+2006-03-02 13:36 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlgallery,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/matrix,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow:
+ Ignore Makefiles
+
+2006-03-02 13:33 gateau
+
+ * trunk/extragear/libs/kipi-plugins/htmlgallery/Makefile.in,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/Makefile.in,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/matrix/Makefile.in,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/Makefile.in:
+ Oups, shouldn't have committed those
+
+2006-03-01 23:36 gateau
+
+ * trunk/extragear/libs/kipi-plugins/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/configure.in.in,
+ trunk/extragear/libs/kipi-plugins/htmlgallery,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/.vimrc,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/Makefile.in,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/TODO,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/galleryinfo.h,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/generator.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/generator.h,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/imagesettingspage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/kipiplugin_htmlgallery.desktop,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/outputpage.ui,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/plugin.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/plugin.h,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/Makefile.in,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/matrix,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/matrix/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/matrix/Makefile.in,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/matrix/bg.png,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/matrix/style.css,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/matrix/template.xslt,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/Makefile.in,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/next.png,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/next.svg,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/next_disabled.png,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/previous.png,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/previous_disabled.png,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/style.css,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/themes/snow/template.xslt,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/wizard.cpp,
+ trunk/extragear/libs/kipi-plugins/htmlgallery/wizard.h: Imported
+ the HTMLGallery plugin, which should replace ImagesGallery.
+ CCMAIL: kde-imaging@kde.org
+
+2006-02-08 17:00 binner
+
+ * trunk/extragear/libs/kipi-plugins/kameraklient/cameraiconview.cpp:
+ actually call setThumbnailSize() method somewhere
+
+2006-01-30 09:36 mueller
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp:
+ the usual "daily unbreak compilation"
+
+2006-01-22 12:44 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/index.template:
+ disabling flash detection code, because it causes problems with
+ konqi
+
+2006-01-22 11:54 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/index.template:
+ argh...that doesn't belongs to the template.
+
+2006-01-15 17:41 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/svedialog.cpp:
+ yesyesyes allee: copyright.....
+
+2006-01-15 17:40 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/plugin_simpleviewer.h,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/svedialog.h:
+ yesyesyes allee: copyright.....
+
+2006-01-15 17:04 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/svedialog.cpp:
+ changed homepage
+
+2006-01-15 16:38 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/Makefile.am: The first version
+ of the plugin is ready to be launched. So this report can be
+ closed. http://www.jokele.de/simpleviewerexport/ BUG: 118637
+
+2006-01-15 11:14 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/index.template:
+ index template modifications
+
+2006-01-14 18:51 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/svedialog.cpp:
+ credits...
+
+2006-01-14 18:40 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/index.template,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.h,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/space.png:
+ - +index.template, kindly licensed for use from Mikkel B.
+ Stegmann - creating an index.html file based on that template -
+ handle the cancel button
+
+2006-01-10 17:34 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/slideshow/toolbar.cpp: He is
+ talking about the slideshow, where we used indeed different
+ icons. BUG: 119867
+
+2006-01-07 23:37 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ enable exporting...
+
+2006-01-07 20:34 toma
+
+ * trunk/extragear/libs/kipi-plugins/sendimages/sendimages.cpp,
+ trunk/extragear/libs/kipi-plugins/sendimages/sendimagesdialog.cpp:
+ Adds support for the Sylpheed-Claws mua. Based on a patch from
+ Paul Mangan. I modified the patch to prevent code duplication.
+ Can you verify if this solution works as well? Thanks dor the
+ patch. BUG: 119562
+
+2006-01-07 18:58 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.h:
+ what to do if export folder already exists...
+
+2006-01-07 17:15 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/imagesgallery/plugin_imagesgallery.cpp:
+ fixed typo
+
+2006-01-07 15:48 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/upgrade.html:
+ adding flash upgrade page
+
+2006-01-07 15:47 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/index.html:
+ adding index.html
+
+2006-01-07 11:13 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.h:
+ Extract all needed files from simoleviewer archive
+
+2006-01-07 02:09 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/firstrundlg.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/firstrundlg.h,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.h:
+ Extracting and installing SimpleViewer flash file. Still a lot
+ of todos & code cleaning left....
+
+2006-01-07 00:55 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/README,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/firstrundlg.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/firstrundlg.h,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.h,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/svedialog.cpp:
+ SimpleViewer is free to use, but uses a license which comes into
+ conflict with several distributions. Due to the license it is
+ not possible to ship it with this plugin. When SimpleViewer
+ isn't found on the system, the firstrun dialog is opened, which
+ lets the user install SimpleViewer.
+
+2006-01-03 22:41 mueller
+
+ * trunk/extragear/libs/kipi-plugins/imagesgallery/plugin_imagesgallery.cpp:
+ remove mis-placed semicolon after if()
+
+2005-12-31 13:15 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp:
+ show close button after the export has finished
+
+2005-12-31 12:40 toma
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/svedialog.h:
+ Missing class
+
+2005-12-31 12:32 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/Makefile.in:
+ that was too much, thanks Laurent
+
+2005-12-31 12:27 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/Makefile.in,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/README,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/kipiplugin_simpleviewer.desktop,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/plugin_simpleviewer.h,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/simpleviewerexport.h,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/svedialog.cpp,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/svedialog.h,
+ trunk/extragear/libs/kipi-plugins/simpleviewerexport/test.txt:
+ Initial commit for simpleviewerexport kipi-plugin
+
+2005-12-31 12:08 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/simpleviewerexport: Initial
+ commit for simpleviewerexport kipi-plugin
+
+2005-12-30 22:49 toma
+
+ * trunk/extragear/libs/kipi-plugins/printwizard/tphoto.cpp: Patch
+ from Anders Lund for bug: Printing using the KIPI printing
+ wizard is nearly impossible on my system, printing a 1600x1200
+ image makes my system go into infinite swapping. BUG:117670
+
+2005-12-28 17:20 toma
+
+ * trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.cpp:
+ Matiyam is right, return false if user says 'no' to the dialog
+ else it will crash... BUG: 116605
+
+2005-12-28 15:15 toma
+
+ * trunk/extragear/libs/kipi-plugins/calendar/calwizard.cpp:
+ Sometimes im really funny. Fix logic. BUG: 118936
+
+2005-12-28 15:06 toma
+
+ * trunk/extragear/libs/kipi-plugins/calendar/calwizard.cpp: Put in
+ an extra warning for making a calendar for a year in the past
+ and for the current year if it is in the second half of the
+ year... BUG: 118936
+
+2005-12-16 02:11 thiago
+
+ * trunk/extragear/libs/kipi-plugins/rawconverter/dcrawprocess.cpp:
+ * Remove getopt.h from the includes: it's only needed for
+ getopt_long, which isn't used here. * Add stdlib.h because
+ Solaris has getopt there instead of unistd.h (which sounds like
+ the correct place to be, since getopt isn't part of ISO C). *
+ Move sys/types.h to the top, just to be on the safe side.
+ BUG:118407
+
+2005-11-13 20:13 jaiva
+
+ * trunk/extragear/libs/kipi-plugins/flickrexport/flickrtalker.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrtalker.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwidget.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwidget.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.h:
+ Added the Image Quality factor option
+
+2005-11-05 12:44 jahrens
+
+ * trunk/extragear/libs/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp:
+ BUG: 114512
+
+2005-11-04 05:57 jaiva
+
+ * trunk/extragear/libs/kipi-plugins/flickrexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/flickrexport/TODO,
+ trunk/extragear/libs/kipi-plugins/flickrexport/exifrestorer.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/exifrestorer.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrtalker.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/jpegsection.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/plugin_flickrexport.cpp:
+ Added code to retain exif information while resizing JPG
+
+2005-11-01 23:15 mueller
+
+ * trunk/extragear/libs/kipi-plugins/configure.in.in,
+ trunk/extragear/libs/libkipi/configure.in.in,
+ trunk/extragear/libs/libkipi/libkipi/libkipi_export.h,
+ trunk/extragear/libs/libkipi/libkipi/libkipi_export.h.in: the
+ usual "daily unbreak compilation".. its getting tiresome
+
+2005-10-04 21:14 gateau
+
+ * trunk/extragear/libs/kipi-plugins/helloworld/plugin_helloworld.h:
+ Unbreak compilation
+
+2005-10-04 07:47 mueller
+
+ * trunk/extragear/libs/kipi-plugins/acquireimages/plugin_acquireimages.cpp,
+ trunk/extragear/libs/kipi-plugins/acquireimages/screenshotdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp,
+ trunk/extragear/libs/kipi-plugins/printwizard/frmprintwizardbase.ui,
+ trunk/extragear/libs/kipi-plugins/rawconverter/plugin_rawconverter.cpp:
+ daily "unbreak compilation"
+
+2005-09-30 15:17 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/imagesgallery/TODO: Possible
+ external tools list to use like external HTML generator CCMAIL :
+ tomalbers@kde.nl
+
+2005-09-26 18:54 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/AUTHORS: missing to give
+ credits to Jain and Tom
+
+2005-09-26 18:45 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/AUTHORS,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchivingdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchivingdialog.h:
+ add credits to Owen
+
+2005-09-26 05:51 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/sendimages/sendimages.cpp: fix
+ wrong revert commit
+
+2005-09-24 09:19 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/kameraklient/Makefile.am: fix
+
+2005-09-24 09:17 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/kameraklient/Makefile.am:
+ KameraKlient kipi plugin : added missing in i18n rules! CCMAIL:
+ oliver@doerr-privat.de
+
+2005-09-23 07:22 coolo
+
+ * trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.cpp:
+ don't rely on spaces and english plural
+
+2005-09-20 14:57 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ trunk/extragear/libs/kipi-plugins/acquireimages/acquireimagedialog.h,
+ trunk/extragear/libs/kipi-plugins/acquireimages/screenshotdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/acquireimages/screenshotdialog.h,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/batchprocessimagesdialog.h,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/renameimageswidget.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/resizeimagesdialog.h,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.cpp,
+ trunk/extragear/libs/kipi-plugins/galleryexport/gallerywindow.cpp,
+ trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.cpp,
+ trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.h,
+ trunk/extragear/libs/kipi-plugins/kameraklient/cameraui.cpp,
+ trunk/extragear/libs/kipi-plugins/kameraklient/cameraui.h,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/checkbinprog.cpp,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/checkbinprog.h,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/kimg2mpg.h,
+ trunk/extragear/libs/kipi-plugins/printwizard/frmprintwizard.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/rawconverter/singledialog.cpp,
+ trunk/extragear/libs/kipi-plugins/sendimages/sendimages.cpp,
+ trunk/extragear/libs/kipi-plugins/sendimages/sendimages.h,
+ trunk/extragear/libs/kipi-plugins/sendimages/sendimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/sendimages/sendimagesdialog.h,
+ trunk/extragear/libs/kipi-plugins/slideshow/plugin_slideshow.cpp,
+ trunk/extragear/libs/kipi-plugins/slideshow/slideshowconfig.cpp:
+ Revert last commit. Accordinly with Renchi, fix Raw converter to
+ use common kipirc file instead host app rc file.
+
+2005-09-20 13:08 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/acquireimages/acquireimagedialog.cpp,
+ trunk/extragear/libs/kipi-plugins/acquireimages/acquireimagedialog.h,
+ trunk/extragear/libs/kipi-plugins/acquireimages/screenshotdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/acquireimages/screenshotdialog.h,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/batchprocessimagesdialog.h,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/borderimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/colorimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/effectimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/filterimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/recompressimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/renameimageswidget.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/resizeimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/resizeimagesdialog.h,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp,
+ trunk/extragear/libs/kipi-plugins/findimages/finddupplicateimages.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.cpp,
+ trunk/extragear/libs/kipi-plugins/galleryexport/gallerywindow.cpp,
+ trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.cpp,
+ trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.h,
+ trunk/extragear/libs/kipi-plugins/kameraklient/cameraui.cpp,
+ trunk/extragear/libs/kipi-plugins/kameraklient/cameraui.h,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/checkbinprog.cpp,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/checkbinprog.h,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/kimg2mpg.cpp,
+ trunk/extragear/libs/kipi-plugins/mpegencoder/kimg2mpg.h,
+ trunk/extragear/libs/kipi-plugins/printwizard/frmprintwizard.cpp,
+ trunk/extragear/libs/kipi-plugins/sendimages/sendimages.h,
+ trunk/extragear/libs/kipi-plugins/sendimages/sendimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/sendimages/sendimagesdialog.h,
+ trunk/extragear/libs/kipi-plugins/slideshow/plugin_slideshow.cpp,
+ trunk/extragear/libs/kipi-plugins/slideshow/slideshowconfig.cpp:
+ kipi-plugins fix : using host apps rc file to store settings
+ instead common kipirc file. Using this way, each host
+ application can have a dedicaced plugins settings. Nota : I
+ don't know why any plugins used a dedicaced kipirc config file,
+ and others used host application rc file. CCMAIL:
+ digikam-devel@kde.org
+
+2005-09-13 03:12 pahlibar
+
+ * trunk/extragear/libs/kipi-plugins/configure.in.in: if we are not
+ using libkexif from the toplevel sources, define the conditional
+ compile_LIBKEXIF to true. needed when tarballs are built
+ separate from the src tree CCMAIL: tomalbers@kde.nl
+
+2005-09-10 20:51 toma
+
+ * trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.h,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchivingdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchivingdialog.h:
+ Fix this beast for ever. k3b is a unique app and does not
+ support the --temp-file parameter. I choose a more general
+ solution now: make a setting where you can enter additional
+ parameters for the executable. Default filled with --nofork. If
+ people use older k3b's they have to remove it. That should go in
+ the documentation as well.
+
+2005-09-07 11:37 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/galleryexport/gallerywindow.cpp,
+ trunk/extragear/libs/kipi-plugins/galleryexport/gallerywindow.h:
+ GalleryExport kipi plugin : Add link to handbook and About data.
+
+2005-09-07 11:14 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.h:
+ FlickrExport kipi plugin : Add link to handbook and About data.
+ CCMAIL: vardhman@students.iiit.net
+
+2005-09-07 10:40 jaiva
+
+ * trunk/extragear/libs/kipi-plugins/flickrexport/flickrtalker.cpp:
+ Fixed the handling of incomplete web-Authentication.
+
+2005-09-06 14:15 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.cpp:
+ save font size properly CCMAIL: cyrill.h@solnet.ch
+
+2005-09-06 08:43 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp:
+ Accordinly with Tom Albers, restoring temporally ' -nofork ' K3b
+ invocation for next RC release. This is a temp issue. A better
+ way will be to use the new (and complete) dcop interface
+ available on k3b. IMPORTANT : A new tool to ARCHIVE/RESTORE
+ digikam database is planed by me and Tom for digiKam 0.8.1. It
+ will be embeded on digiKam to support all database features.
+ kipi CDArchiving tool will be obsolete for digikam in the
+ future. We need a maintenor from kimdaba, gwenview or showimg
+ project for this tool. CCMAIL: kde-imaging@kde.org,
+ digikam-devel@kde.org
+
+v0.1.0-rc1 2005-02-08
+----------------------------------------------------------------------------
+
+2005-09-04 21:46 toma
+
+ * trunk/extragear/libs/kipi-plugins/ChangeLog,
+ trunk/extragear/libs/kipi-plugins/kipi-plugins.lsm: Preparing
+ for release.
+
+2005-09-03 16:08 gateau
+
+ * trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.h:
+ Replaced the QTimer with a call to QTimer::singleShot()
+
+2005-09-03 16:00 gateau
+
+ * trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.h: -
+ Create KConfig objects on the stack. - No need to keep a pointer
+ on it in the object.
+
+2005-09-03 15:51 gateau
+
+ * trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp:
+ More heap -> stack objects.
+
+2005-09-03 15:49 gateau
+
+ * trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp:
+ Do not create objects on the heap when they can be created on
+ the stack (C++ is not Java). This avoids memory leaks when
+ objects are not deleted.
+
+2005-09-03 15:22 toma
+
+ * trunk/extragear/libs/kipi-plugins/sendimages/sendimages.cpp:
+ Thunderbird does not return the dot in this error message, so
+ thunderbird was not started and the composer can not be started
+ in that case. Also replaced the 'contains' with a 'find' which
+ is faster, I learned that from Ingo, which is pretty funny in
+ this case ;-) BUGS: 108227 CCMAIL: oliver@doerr-privat.de
+
+2005-09-01 22:00 toma
+
+ * trunk/extragear/libs/kipi-plugins/flickrexport/flickrtalker.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwidget.cpp:
+ No tabs in strings, makes a mess for translators, added some
+ comments...
+
+2005-08-21 20:23 toma
+
+ * trunk/extragear/libs/kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp:
+ Add missing i18n() for filter names, some of them are based on
+ the names of persons, but now there is a possibility to
+ translate them for those who want that. BUG: 110982
+
+2005-08-19 07:06 cgilles
+
+ * trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.h,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/plugin_cdarchiving.cpp:
+ CDArchiving kipi plugin : patch from Owen Hirst CCBUGS: 98269
+ 89394 91651 100877 106568
+
+2005-08-15 20:16 toma
+
+ * trunk/extragear/graphics/digikam/digikam/albumdb.cpp,
+ trunk/extragear/graphics/digikam/digikam/albumdb.h,
+ trunk/extragear/graphics/digikam/digikam/digikamapp.cpp,
+ trunk/extragear/graphics/digikam/digikam/kipiinterface.cpp,
+ trunk/extragear/graphics/digikam/digikam/kipiinterface.h,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/batchprocessimagesitem.h,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/renameimagesbase.ui,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/renameimagesdialog.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/renameimagesdialog.h,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/renameimageswidget.cpp,
+ trunk/extragear/libs/kipi-plugins/batchprocessimages/renameimageswidget.h:
+ Owen Hirst <n8rider@sbcglobal.net> has provided a patch for KIPI
+ Rename Images (part of the BatchProcesses Plugin). kipi part: *
+ Complete rewrite * Use rename instead of copy * Allow formatting
+ of date string digikam part: * fixes the time and date
+ adjustment not working * Update database entry when a file is
+ renamed by a KIPI Plugin * make slideshow available right after
+ digikams start This fixes the following bugs:
+ BUGS:110391,110659,110698,110575,99895,104032,105727,110508,104511
+ great work!
+
+2005-08-07 21:00 pahlibar
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/actionthread.cpp:
+ in case of auto-rotate ignore the app specified angle. otherwise
+ apps using exif rotation angle will specify the same angle and
+ you end up having rotation by twice the actual needed angle
+
+2005-08-07 15:47 toma
+
+ * trunk/extragear/libs/kipi-plugins/calendar/calpainter.cpp,
+ trunk/extragear/libs/kipi-plugins/calendar/caltemplate.cpp:
+ Fixed 3 problems: - compiler deprecated barfs on monthNames. -
+ the weekday was not localized, so they were english. - default
+ font in pull down is now the application dafault font. BUG: 97187
+
+2005-08-07 14:12 toma
+
+ * trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.cpp,
+ trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.h:
+ Fixed two problems here: - when exporting tags a folder name
+ "Tag: foo", was used. Konqueror would state that that protocol
+ is not supported. Removed the : as a solution. - tags do not
+ have a url, so using that as unique identifier in the map, was
+ causing trouble. Exporting four tag albums resulted in four
+ identical folders, because the key always returned 0. Used a
+ QMapIterator and an int as a key. Could some people check if
+ this is ok? CCMAIL: digikam-devel@kde.org BUG: 102219
+
+2005-08-07 00:14 toma
+
+ * trunk/extragear/libs/kipi-plugins/imagesgallery/imagesgallery.cpp:
+ i18n fix for problem with a string. It had a space at the end of
+ the string, translaters left that space out when translating and
+ so a bug was born. BUG: 98199
+
+2005-08-05 17:54 jaiva
+
+ * trunk/extragear/libs/kipi-plugins/flickrexport,
+ trunk/extragear/libs/kipi-plugins/flickrexport/Makefile,
+ trunk/extragear/libs/kipi-plugins/flickrexport/Makefile.am,
+ trunk/extragear/libs/kipi-plugins/flickrexport/Makefile.in,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickralbumdialog.ui,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickritem.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrtalker.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrtalker.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrviewitem.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrviewitem.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwidget.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwidget.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/flickrwindow.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/kipiplugin_flickrexport.desktop,
+ trunk/extragear/libs/kipi-plugins/flickrexport/login.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/login.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/mpform.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/mpform.h,
+ trunk/extragear/libs/kipi-plugins/flickrexport/plugin_flickrexport.cpp,
+ trunk/extragear/libs/kipi-plugins/flickrexport/plugin_flickrexport.h:
+ First release of flickrexport kipi-plugin file upload is
+ completely supported and new auth API is implemented.
+
+2005-08-03 21:30 gateau
+
+ * trunk/extragear/libs/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp:
+ Make use of the available room when the user resizes the dialog.
+ CCMAIL: kde-imaging@kde.org
+
+2005-08-02 14:52 lunakl
+
+ * trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchiving.cpp,
+ trunk/extragear/libs/kipi-plugins/cdarchiving/cdarchivingdialog.cpp:
+ Hardcoding k3b by default to /usr/bin/k3b makes no sense. It's
+ usually in $PATH just like the KDE app using the KIPI plugin, so
+ just 'k3b' should do as well, and doesn't break for whoever puts
+ their KDE somewhere else than /usr/bin. I personally fail to see
+ the point of this option at all, but oh well.
+
+2005-07-11 05:22 pahlibar
+
+ * trunk/extragear/libs/kipi-plugins/jpeglossless/utils.cpp:
+ preserve timestamp of image when rotating/flipping BUG: 108537
+
+2005-05-08 11:55 mlaurent
+
+ * trunk/extragear/libs/configure.in.in,
+ trunk/extragear/libs/kipi-plugins/configure.in.in,
+ trunk/extragear/libs/libkexif/Makefile.am,
+ trunk/extragear/libs/libkexif/configure.in.in,
+ trunk/extragear/libs/libkexif/kexifdata.h,
+ trunk/extragear/libs/libkexif/kexifdialog.h,
+ trunk/extragear/libs/libkexif/kexifutils.h,
+ trunk/extragear/libs/libkexif/kexifwidget.h,
+ trunk/extragear/libs/libkexif/libkexif_export.h,
+ trunk/extragear/libs/libkipi/configure.in.in,
+ trunk/extragear/libs/libkipi/libkipi/Makefile.am,
+ trunk/extragear/libs/libkipi/libkipi/batchprogressdialog.h,
+ trunk/extragear/libs/libkipi/libkipi/imagecollection.h,
+ trunk/extragear/libs/libkipi/libkipi/imagecollectionselector.h,
+ trunk/extragear/libs/libkipi/libkipi/imagecollectionshared.h,
+ trunk/extragear/libs/libkipi/libkipi/imagedialog.h,
+ trunk/extragear/libs/libkipi/libkipi/imageinfo.h,
+ trunk/extragear/libs/libkipi/libkipi/imageinfoshared.h,
+ trunk/extragear/libs/libkipi/libkipi/interface.h,
+ trunk/extragear/libs/libkipi/libkipi/libkipi_export.h,
+ trunk/extragear/libs/libkipi/libkipi/plugin.h,
+ trunk/extragear/libs/libkipi/libkipi/pluginloader.h,
+ trunk/extragear/libs/libkipi/libkipi/uploadwidget.h: Add support
+ -fvisibility
+
+2005-04-26 15:47 pahlibar
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/galleryexport/gallerytalker.cpp:
+ caption, not albumName
+
+2005-04-24 15:57 cgilles
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/mpegencoder/images2mpg,
+ trunk/kdeextragear-libs-1/kipi-plugins/mpegencoder/kimg2mpg.cpp:
+ Patch from Thorsten Schnebeck <thorsten.schnebeck@gmx.net>
+ Please try again with this patch applied to CVS HEAD. In
+ according with results please close this bug. CCBUG:101110
+ CCMAIL: digikam-deve@lists.sourceforge.net
+
+2005-04-22 05:58 cgilles
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/sendimages/actions.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/exifrestorer.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/exifrestorer.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/jpegsection.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/listimageserrordialog.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/listimageserrordialog.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/plugin_sendimages.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/plugin_sendimages.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/sendimages.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/sendimages.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/sendimagesdialog.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/sendimages/sendimagesdialog.h:
+ KIPI SendImages plugins : Fix headers. support GmailAgent
+ (experimental) CCMAIL: digikam-devel@lists.sourceforge.net
+
+2005-04-22 05:34 cgilles
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/rawconverter/processcontroller.cpp:
+ Make compile. Renchi take a look if is correct for your !
+ CCMAIL: renchi@pooh.tam.uiuc.edu
+
+2005-04-05 22:57 pahlibar
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/rawconverter/batchdialog.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/rawconverter/batchdialog.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/rawconverter/dcrawprocess.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/rawconverter/processcontroller.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/rawconverter/processcontroller.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/rawconverter/singledialog.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/rawconverter/singledialog.h:
+ update to work with dcraw >= 6.x. will not work with lower
+ versions anymore BUGS: 99437
+
+2005-04-05 17:48 pahlibar
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/slideshow/imlibiface.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/slideshow/imlibiface.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/slideshow/plugin_slideshow.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/slideshow/slideshow.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/slideshow/slideshow.h,
+ trunk/kdeextragear-libs-1/kipi-plugins/slideshow/slideshowgl.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/slideshow/slideshowgl.h:
+ respect app set angle for rotating images in slideshow. need to
+ come up with an angle spec to allow flipping of images as well
+ (allowed by exif standard) BUGS: 103282
+
+2005-03-13 22:56 cgilles
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/batchprocessimages/renameimagesdialog.cpp:
+ patch from Cedric Pradalier. BUGS:99193 CCBUGS:99193
+
+2005-02-28 17:20 toma
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/sendimages/plugin_sendimages.cpp:
+ Make the menu entry for this plugin disabled when there is no
+ images selected and enabled when there is a (valid) selection
+
+2005-02-20 16:47 cgilles
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/mpegencoder/images2mpg:
+ MPEGEncoder : -Fixed kipi url -Added new audio Wav sampling to
+ 48000 for to use with DVD author ! Thanks to "bcl.man" for this
+ patch CCMAIL: kde-imaging@kde.org, bcl.man@free.fr
+
+2005-02-18 17:18 uga
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/wallpaper/plugin_wallpaper.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/wallpaper/plugin_wallpaper.h:
+ New wallpaper method "scale and crop" is available since kde 3.4
+ Beta1
+
+2005-02-10 12:20 cgilles
+
+ * trunk/kdeextragear-libs-1/kipi-plugins/batchprocessimages/convertimagesdialog.cpp,
+ trunk/kdeextragear-libs-1/kipi-plugins/batchprocessimages/convertimagesdialog.h:
+ Added EPS image file format support in kipi batchconvertimage
+ plugins. BUGS:99020 CCBUGS:99020
+ CCMAIL:kde-imaging@kde.org,digikam-devel@lists.sourceforge.net
+
+v0.1.0-beta2 2005-02-08
+----------------------------------------------------------------------------
+
+2005-02-04 15:15 cgilles
+
+ * batchprocessimages/borderimagesdialog.cpp: Added comments
+
+2005-02-02 22:15 scherfa
+
+ * slideshow/: plugin_slideshow.cpp, slideshowconfig.cpp,
+ slideshowgl.cpp, slideshowgl.h: Added Printfilename to GL
+ Slideshow ..
+
+2005-02-01 16:29 luis_pedro
+
+ * calendar/caltemplate.cpp: Due to the auto-accelerators, the text
+ got changed from "Top" to "&Top" (and "Left"->"&Left" and
+ "Right"->"&Right") Use numeric ids instead of strings
+
+ OKed by Renchi Raju
+
+2005-01-28 21:57 pahlibar
+
+ * configure.in.in:
+ remove local pkg-config check (in kde-common now)
+
+2005-01-27 09:46 cgilles
+
+ * batchprocessimages/resizeimagesdialog.cpp: BugFix in
+ BatchResizeImages kipi plugin: using ImageMagick "composite" do
+ not preserve Exif informations per default. Need to use
+ "-profile" option for resolve this problem. Note: ImageMagick
+ "Convert" program preverve it! CCMAIL: kde-imaging@kde.org,
+ digikam-devel@lists.sourceforge.net
+
+2005-01-25 11:52 adridg
+
+ * configure.in.in: Always use all_libraries, since it will have the
+ --with-extra* stuff
+
+2005-01-24 15:49 cgilles
+
+ * batchprocessimages/: resizeimagesdialog.cpp,
+ resizeimagesdialog.h, resizeoptionsdialog.cpp,
+ resizeoptionsdialog.h: Kipi Batch Resize Image : Patch from
+ Alfons Hoogervorst <alfons@proteus.demon.nl> for to use -quality
+ IM option with JPEG images. Adapting patch for Prepare to Print
+ option too. CCMAIL: kde-imaging@kde.org,
+ digikam-devel@lists.sourceforge.net
+
+2005-01-22 01:03 pahlibar
+
+ * sendimages/sendimages.cpp:
+ don't add the comments file if there are no comments BUG: 97069
+
+2005-01-18 18:58 pahlibar
+
+ * galleryexport/: gallerytalker.cpp, gallerywindow.cpp:
+ enable uploading for movie (and other non-image files) to gallery
+ BUG: 97298
+
+2005-01-14 21:21 adridg
+
+ * kameraklient/: gpcamera.cpp, gpiface.cpp: --enable-final: using
+ namespaces confuses the definition of CameraList
+
+2005-01-13 21:28 pahlibar
+
+ * slideshow/plugin_slideshow.cpp:
+ enable the slideshow plugin when an album is selected, to prevent
+ confusing the user
+
+2005-01-13 16:51 cgilles
+
+ * sendimages/: plugin_sendimages.cpp, sendimages.cpp, sendimages.h:
+ Fix thunderbird path url using in second stage
+
+2005-01-13 13:47 cgilles
+
+ * README, kipi-plugins.lsm, kipiplugins.kdevelop,
+ acquireimages/acquireimagedialog.cpp,
+ acquireimages/screenshotdialog.cpp,
+ batchprocessimages/borderimagesdialog.cpp,
+ batchprocessimages/colorimagesdialog.cpp,
+ batchprocessimages/convertimagesdialog.cpp,
+ batchprocessimages/effectimagesdialog.cpp,
+ batchprocessimages/filterimagesdialog.cpp,
+ batchprocessimages/imagepreview.cpp,
+ batchprocessimages/outputdialog.cpp,
+ batchprocessimages/recompressimagesdialog.cpp,
+ batchprocessimages/renameimagesdialog.cpp,
+ batchprocessimages/resizeimagesdialog.cpp,
+ calendar/calwizard.cpp, cdarchiving/cdarchiving.cpp,
+ cdarchiving/cdarchivingdialog.cpp, findimages/displaycompare.cpp,
+ findimages/finddupplicatedialog.cpp,
+ imagesgallery/imagesgallery.cpp,
+ imagesgallery/imgallerydialog.cpp,
+ kameraklient/cameraselection.cpp, kameraklient/cameraui.cpp,
+ kameraklient/setupcamera.cpp, mpegencoder/kimg2mpg.cpp,
+ printwizard/frmprintwizard.cpp, rawconverter/batchdialog.cpp,
+ rawconverter/singledialog.cpp, sendimages/sendimagesdialog.cpp,
+ slideshow/slideshowconfig.cpp, timeadjust/timeadjustdialog.cpp:
+ Fixed project url
+
+2004-12-28 22:24 pahlibar
+
+ * INSTALL, Makefile.am, README, configure.in.bot, configure.in.in,
+ acquireimages/Makefile.am, jpeglossless/Makefile.am,
+ jpeglossless/jinclude.h, rawconverter/Makefile.am,
+ rawconverter/batchdialog.cpp:
+ * check for presence of libtiff before trying to compiling
+ plugins which use it (jpeglossless,acquireimages,rawconverter)
+ * better info at the configure check bottom, as to whats missing
+ * updated the README and INSTALL files with dependency
+ requirements CCMAIL: kde-imaging@kde.org
+
+2004-12-28 20:36 pahlibar
+
+ * calendar/: calsettings.h, monthwidget.cpp, monthwidget.h:
+ * the selection for the month url was being done only if a
+ thumbnail could be generated. if the image size happens to be
+ larger than the user setting for the preview data, the url was
+ not being selected (as the thumbnail fails to generate). Fixed.
+ * Also use a generic image icon for the selected url till the
+ thumbnail is generated BUG: 95871
+
+2004-12-28 03:22 pahlibar
+
+ * galleryexport/: gallerytalker.cpp, gallerytalker.h,
+ gallerywidget.cpp, gallerywidget.h, gallerywindow.cpp,
+ gallerywindow.h:
+ * put widgets into splitter * clean out the resize options and
+ make it more unambiguous
+
+2004-12-28 01:38 pahlibar
+
+ * galleryexport/gallerywindow.cpp:
+ bail out if user uses unallowed chars in the album name
+
+2004-12-27 23:02 pahlibar
+
+ * README, TODO:
+ update
+
+2004-12-24 17:27 cgilles
+
+ * README, TODO: Fix
+
+2004-12-23 02:18 pahlibar
+
+ * galleryexport/: gallerytalker.cpp, gallerytalker.h,
+ gallerywidget.cpp, gallerywidget.h, gallerywindow.cpp,
+ gallerywindow.h:
+ allow setting maximum image dimensions before uploading BUG:
+ 94493
+
+2004-12-22 07:12 pahlibar
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ batchprocessimagesdialog.h, borderimagesdialog.cpp,
+ borderimagesdialog.h, colorimagesdialog.cpp, colorimagesdialog.h,
+ convertimagesdialog.cpp, convertimagesdialog.h,
+ effectimagesdialog.cpp, effectimagesdialog.h,
+ filterimagesdialog.cpp, filterimagesdialog.h,
+ recompressimagesdialog.cpp, recompressimagesdialog.h,
+ resizeimagesdialog.cpp, resizeimagesdialog.h:
+ * fix retrieving upload path from a virtual album
+ (libkipi/uploadwidget) * fix crash in batchprocess plugin when no
+ destination path is selected. the function thinks its being
+ called in preview mode, but the preview process is null there.
+ its dangerous to make an assumption of a passed arg being null,
+ when its being called from multiple places in different modes.
+ better use a separate explicit variable to indicate that the
+ function is being called in a different mode. good for the sanity
+ of those reading the code as well BUG: 94370
+
+2004-12-22 06:28 pahlibar
+
+ * cdarchiving/cdarchivingdialog.cpp:
+ integer overflow when calculating total size. use a double to
+ store the sum
+
+ BUG: 94549
+
+2004-12-22 06:16 pahlibar
+
+ * cdarchiving/cdarchiving.cpp:
+ respect host app settings and check for features before actually
+ accessing them BUG: 88883
+
+2004-12-22 05:12 pahlibar
+
+ * imagesgallery/imagesgallery.cpp:
+ use a simple hsv cycle algo to try and get contrasting colors for
+ links. not perfect, but will do BUG: 88870
+
+2004-12-22 03:30 pahlibar
+
+ * sendimages/sendimages.cpp:
+ fix issue with sending images with non-latin characters in
+ filepath. Use QFile::encodeName() if you want to deal with a non
+ qt/kde tool this code is a nightmare to read without proper
+ indentation
+
+2004-12-21 20:46 pahlibar
+
+ * slideshow/: slideshow.cpp, slideshow.h, slideshowgl.cpp,
+ slideshowgl.h:
+ use xinerma specific settings to fill up only the screen occupied
+ by the host app BUG: 95592
+
+2004-12-21 19:25 lukas
+
+ * batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/convertimagesdialog.cpp,
+ batchprocessimages/effectimagesdialog.cpp,
+ batchprocessimages/filterimagesdialog.cpp,
+ batchprocessimages/imagepreview.cpp,
+ batchprocessimages/outputdialog.cpp,
+ batchprocessimages/recompressimagesdialog.cpp,
+ batchprocessimages/resizeimagesdialog.cpp,
+ findimages/finddupplicatedialog.cpp,
+ galleryexport/gallerylogin.cpp,
+ imagesgallery/imgallerydialog.cpp,
+ kameraklient/cameraselection.cpp, kameraklient/cameraui.cpp,
+ kameraklient/dmessagebox.cpp, kameraklient/gpcamera.cpp,
+ kameraklient/gpfileiteminfo.cpp,
+ kameraklient/gpfileiteminfodlg.cpp, mpegencoder/checkbinprog.cpp,
+ mpegencoder/kimg2mpg.cpp, rawconverter/batchdialog.cpp,
+ rawconverter/previewwidget.cpp,
+ rawconverter/processcontroller.cpp,
+ rawconverter/singledialog.cpp, sendimages/sendimages.cpp,
+ sendimages/sendimagesdialog.cpp, timeadjust/timeadjustdialog.cpp,
+ wallpaper/plugin_wallpaper.cpp: i18n fixes, enough for today :)
+
+2004-12-17 13:09 craig
+
+ * findimages/: finddupplicatedialog.cpp, finddupplicateimages.cpp,
+ finddupplicateimages.h: Use KDE's standard dirs for cache
+ information
+
+2004-12-17 12:23 craig
+
+ * batchprocessimages/batchprocessimagesdialog.cpp,
+ cdarchiving/cdarchiving.cpp, imagesgallery/imagesgallery.cpp:
+ Directory -> Folder
+
+2004-12-17 00:46 craig
+
+ * acquireimages/plugin_acquireimages.cpp,
+ acquireimages/screenshotdialog.cpp, cdarchiving/cdarchiving.cpp,
+ cdarchiving/plugin_cdarchiving.cpp,
+ findimages/displaycompare.cpp,
+ findimages/finddupplicatedialog.cpp,
+ findimages/finddupplicateimages.cpp,
+ findimages/plugin_findimages.cpp,
+ galleryexport/gallerywindow.cpp, galleryexport/gallerywindow.h,
+ galleryexport/plugin_galleryexport.cpp,
+ imagesgallery/imagesgallery.cpp,
+ imagesgallery/imgallerydialog.cpp,
+ imagesgallery/plugin_imagesgallery.cpp,
+ mpegencoder/checkbinprog.cpp, mpegencoder/kimg2mpg.cpp,
+ mpegencoder/plugin_mpegencoder.cpp,
+ printwizard/plugin_printwizard.cpp, rawconverter/batchdialog.cpp,
+ rawconverter/batchdialog.h, rawconverter/plugin_rawconverter.cpp,
+ rawconverter/singledialog.cpp, rawconverter/singledialog.h,
+ sendimages/plugin_sendimages.cpp, sendimages/sendimages.cpp,
+ sendimages/sendimagesdialog.cpp, slideshow/plugin_slideshow.cpp,
+ slideshow/slideshowconfig.cpp, slideshow/slideshowconfig.h,
+ timeadjust/plugin_timeadjust.cpp, wallpaper/plugin_wallpaper.cpp:
+ Give dialogs parents.
+
+2004-12-12 19:15 ach
+
+ * galleryexport/kipiplugin_galleryexport.desktop,
+ imagesgallery/kipiplugin_imagesgallery.desktop: make it clear
+ what does what
+
+2004-12-04 04:07 pahlibar
+
+ * slideshow/: plugin_slideshow.cpp, slideshowconfig.cpp,
+ slideshowconfig.h:
+ add an option to shuffle images in slideshow BUG: 91360
+
+2004-12-04 01:38 pahlibar
+
+ * galleryexport/TODO:
+ update TODO
+
+2004-12-04 00:59 pahlibar
+
+ * galleryexport/TODO:
+ updated todo
+
+2004-12-04 00:46 pahlibar
+
+ * galleryexport/: galleryviewitem.cpp, gallerywindow.cpp,
+ gallerywindow.h:
+ * kwallet integration for saving/restoring password (for kde >
+ 3.1). for kde <= 3.1, only the url and username are saved
+ restored. * promote the album title as the main text (in the
+ album treeview list)
+
+ galleryexport to be considered feature-complete for kipi-plugins
+ 0.1 release, pending user input
+
+ CCBUG: 88262
+
+2004-12-03 21:21 pahlibar
+
+ * galleryexport/: Makefile.am, TODO, galleryviewitem.cpp,
+ galleryviewitem.h, gallerywindow.cpp:
+ polish, polish: show the album title along with the name. improve
+ the comments rendering under the thumbnail
+
+2004-12-03 08:14 pahlibar
+
+ * galleryexport/TODO:
+ added mini TODO file for galleryexport
+
+2004-12-03 08:13 pahlibar
+
+ * galleryexport/: Makefile.am, galleryalbumdialog.ui,
+ galleryitem.h, gallerylogin.cpp, gallerylogin.h,
+ gallerympform.cpp, gallerympform.h, gallerytalker.cpp,
+ gallerytalker.h, galleryviewitem.h, gallerywidget.cpp,
+ gallerywidget.h, gallerywindow.cpp, gallerywindow.h,
+ plugin_galleryexport.cpp:
+ * implemented uploading photos (with host application provided
+ captions) into remote gallery * now, generate the upload form
+ data using multipart. * show captions under thumbnails
+
+ Note to users: the code hasn't undergone a whole lot of testing.
+ I would like reports back, if things are broken. Might be prudent
+ to test on non-production remote gallery
+
+ BUG: 88262
+
+2004-12-01 20:42 pahlibar
+
+ * galleryexport/: Makefile.am, galleryalbumdialog.ui,
+ gallerylogin.h, gallerytalker.cpp, gallerytalker.h,
+ gallerywindow.cpp, gallerywindow.h:
+ * implemented creating new albums CCBUG: 88262
+
+2004-12-01 12:29 pahlibar
+
+ * Makefile.am, galleryexport/.cvsignore, galleryexport/Makefile.am,
+ galleryexport/galleryitem.h, galleryexport/gallerylogin.cpp,
+ galleryexport/gallerylogin.h, galleryexport/gallerytalker.cpp,
+ galleryexport/gallerytalker.h, galleryexport/galleryviewitem.h,
+ galleryexport/gallerywidget.cpp, galleryexport/gallerywidget.h,
+ galleryexport/gallerywindow.cpp, galleryexport/gallerywindow.h,
+ galleryexport/kipiplugin_galleryexport.desktop,
+ galleryexport/plugin_galleryexport.cpp,
+ galleryexport/plugin_galleryexport.h:
+ Initial implementation of remote gallery export kipi-plugin What
+ works now: * logging into remote gallery * listing albums *
+ listing photos in individual albums * showing thumbnails for
+ photos * clicking on thumbnails will open up the actual image in
+ kde standard imageviewer
+
+ Things to do: * implement adding new albums * implement adding
+ new photos * kwallet integration for saving/restoring
+ remote-url/username/password
+
+ So currently only read-only support. putting this in so that we
+ can get some user testing done for remote url access and also
+ modify the GUI based on user input. Screenshot at:
+ http://pooh.tam.uiuc.edu/gallery_export.png CCBUG: 88262
+
+2004-11-30 16:08 cgilles
+
+ * imagesgallery/imagesgallery.cpp: Added FireFox suppport
+
+2004-11-30 14:23 cgilles
+
+ * imagesgallery/: imagesgallery.cpp, imgallerydialog.cpp: Fixed
+ bool read config entries
+
+2004-11-29 22:00 cgilles
+
+ * imagesgallery/: imagesgallery.cpp, imagesgallery.h: Revert source
+ code.
+
+2004-11-29 21:42 cgilles
+
+ * findimages/: finddupplicatedialog.cpp, finddupplicatedialog.h,
+ finddupplicateimages.cpp: Patch to fix bug #93065
+
+2004-11-29 12:25 cgilles
+
+ * Makefile.am, configure.in.in, kipiplugins.kdevelop,
+ timeadjust/Makefile.am, timeadjust/timeadjustdialog.cpp,
+ timeadjust/timeadjustdialog.h: Bug #89993 : TimeAdjust kipi
+ plugin : apply patch for Renchi about to set date & time to that
+ of file exif date. CCMAIL: kde-imaging@kde.org
+
+2004-11-28 23:32 cgilles
+
+ * batchprocessimages/resizeimagesdialog.cpp: Bug #93065: using
+ -resize instead -geometry IM option CCMAIL:kde-imaging@kde.org
+
+2004-11-26 18:29 cgilles
+
+ * cdarchiving/cdarchiving.cpp: Remove --nofork option.
+
+2004-11-26 17:40 cgilles
+
+ * cdarchiving/cdarchiving.cpp: CDArchiving kipi plugin: -Added
+ '--nofork' option for k3b -Fix bool config option reading
+
+2004-11-23 13:24 faure
+
+ * jpeglossless/Makefile.am: local too -> before all_includes
+
+2004-11-23 13:23 faure
+
+ * acquireimages/Makefile.am, batchprocessimages/Makefile.am,
+ calendar/Makefile.am, cdarchiving/Makefile.am,
+ findimages/Makefile.am, helloworld/Makefile.am,
+ imagesgallery/Makefile.am, jpeglossless/Makefile.am,
+ kameraklient/Makefile.am, printwizard/Makefile.am,
+ rawconverter/Makefile.am, sendimages/Makefile.am,
+ timeadjust/Makefile.am, wallpaper/Makefile.am: $(all_includeS)
+ must be after $(LIBKIPI_CFLAGS) since that one is local (nice way
+ to fool my script) :)
+
+2004-11-23 12:50 faure
+
+ * mpegencoder/Makefile.am: all_includes must be last
+
+2004-11-20 06:35 bmeyer
+
+ * jpeglossless/jinclude.h: Add ifndef/define/endif to prevent
+ possible acidential double includes
+
+2004-11-13 20:05 adawit
+
+ * imagesgallery/: imagesgallery.cpp, imagesgallery.h: - Do not
+ append a file extension if the file already ends with that
+ extension. - Use a locally declared KConfig object whenever it
+ is short lived, i.e. deleted at the end of the function. - "if
+ (object) delete object;" is not necessary if the object is
+ already initialized properly.
+
+2004-11-11 18:52 pahlibar
+
+ * jpeglossless/utils.cpp:
+ replaced mmap based file copy with regular readblock/writeblock.
+ fixes issues with file copies on a nfs mounted partition
+
+2004-11-09 16:50 pahlibar
+
+ * jpeglossless/: jpegtransform.cpp, jpegtransform.h:
+ restore proper copyright owners
+
+2004-11-09 16:43 pahlibar
+
+ * jpeglossless/mtqueue.h:
+ added copyright
+
+2004-11-09 16:42 pahlibar
+
+ * calendar/main.cpp:
+ removed stale file
+
+2004-11-07 13:02 coolo
+
+ * configure.in.in: works without installed libkexif
+
+2004-11-06 05:07 bmeyer
+
+ * acquireimages/acquireimagedialog.cpp,
+ batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/batchprocessimagesitem.cpp,
+ cdarchiving/cdarchiving.cpp, cdarchiving/cdarchivingdialog.cpp,
+ findimages/displaycompare.cpp,
+ findimages/finddupplicatedialog.cpp,
+ findimages/finddupplicateimages.cpp,
+ imagesgallery/imagesgallery.cpp,
+ imagesgallery/imgallerydialog.cpp,
+ kameraklient/cameraiconview.cpp, kameraklient/cameraui.cpp,
+ kameraklient/kipiplugin_kameraklient.desktop,
+ mpegencoder/checkbinprog.cpp, mpegencoder/kimg2mpg.cpp,
+ mpegencoder/optionsdialog.cpp, printwizard/tphoto.cpp,
+ rawconverter/batchdialog.cpp, sendimages/sendimages.cpp,
+ sendimages/sendimagesdialog.cpp, slideshow/slideshowgl.cpp:
+ header fixes "" comparisions changed to use .isEmpty() Added
+ missing Encoding line to desktop file Fixed Build Build breakage
+
+2004-11-06 04:54 bmeyer
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ renameimagesdialog.cpp: remove QString::null and replace with
+ .isNull()
+
+2004-11-06 04:10 bmeyer
+
+ * kameraklient/Makefile.am: fix broken build
+
+2004-11-03 23:38 binner
+
+ * batchprocessimages/batchprocessimagesdialog.cpp: fix layout
+
+2004-10-27 23:10 gateau
+
+ * kipi-plugins.lsm: Initial import of .lsm files, needed to upload
+ to upload.kde.org.
+
+2004-10-24 05:40 pahlibar
+
+ * TODO, calendar/calpainter.cpp, calendar/caltemplate.cpp:
+ * use only smoothly scalable fonts * remove
+ kapp->processEvents(). no idea why i put it there in the first
+ place * updated todo
+
+2004-10-22 02:18 pahlibar
+
+ * calendar/calwizard.cpp, printwizard/frmprintwizard.cpp:
+ kde 3.1 compatiblity fixes
+
+2004-10-20 18:52 pahlibar
+
+ * calendar/calwizard.cpp, printwizard/frmprintwizard.cpp:
+ force kprinter to use printer resolution
+
+2004-10-19 21:30 jahrens
+
+ * findimages/: finddupplicatedialog.cpp, finddupplicatedialog.h:
+ Addition to #91548
+
+ CCMAIL: 91548@bugs.kde.org, digikam-devel@lists.sourceforge.net
+
+2004-10-19 21:07 jahrens
+
+ * findimages/finddupplicatedialog.cpp:
+ fixed in cvs
+
+ CCMAIL: 91548-done@bugs.kde.org,
+ digikam-devel@lists.sourceforge.net
+
+2004-10-19 17:36 jahrens
+
+ * mpegencoder/plugin_mpegencoder.cpp:
+ fixed in cvs
+
+ CCMAIL: 91547-done@bugs.kde.org,
+ digikam-devel@lists.sourceforge.net
+
+2004-10-19 14:49 cgilles
+
+ * sendimages/sendimagesdialog.cpp: SendImages kipi-plugin : fixed
+ bug #91596 CCMAIL: kde-imaging@kde.org,
+ digikam-devel@lists.sourceforge.net
+
+2004-10-18 15:57 mlaurent
+
+ * kameraklient/: cameraui.cpp, gpeventfilter.cpp,
+ gpfileitemcontainer.cpp: it++ -> ++it
+
+2004-10-18 02:53 pahlibar
+
+ * slideshow/: plugin_slideshow.cpp, plugin_slideshow.h,
+ slideshowconfig.cpp, slideshowconfig.h:
+ cleaner implementation. (note to self: its difficult to sneak in
+ hacks with the usability gurus watching ;) ). The slideshow
+ action is enabled only if there is a current valid album and has
+ images. also, if there is no current selection, the "selected
+ images only" option is disabled.
+
+2004-10-18 02:27 pahlibar
+
+ * slideshow/plugin_slideshow.cpp:
+ popup a sorry message if there are no images in current album and
+ slideshow action is clicked. also popup sorry message if user
+ selects slideshow with selected items only option and there are
+ no selected items
+
+2004-10-13 21:33 pahlibar
+
+ * INSTALL:
+ updated INSTALL file
+
+2004-10-11 18:07 pahlibar
+
+ * kameraklient/Makefile.am:
+ forgot the kameraklient on the update to the makefile.am
+
+2004-10-11 17:57 pahlibar
+
+ * configure.in.in, acquireimages/Makefile.am,
+ batchprocessimages/Makefile.am, calendar/Makefile.am,
+ cdarchiving/Makefile.am, findimages/Makefile.am,
+ helloworld/Makefile.am, imagesgallery/Makefile.am,
+ jpeglossless/Makefile.am, mpegencoder/Makefile.am,
+ printwizard/Makefile.am, rawconverter/Makefile.am,
+ sendimages/Makefile.am, slideshow/Makefile.am,
+ timeadjust/Makefile.am, wallpaper/Makefile.am:
+ fixed hardcoded libkipi path
+
+2004-10-11 13:57 cgilles
+
+ * Makefile.am: Fixed i18n extraction for tips
+
+2004-10-11 13:35 cgilles
+
+ * Makefile.am, README: Removed 'GammaCalibration' kipi plugin (must
+ be implemented in the hosts) CCMAIL: kde-imaging@kde.org
+
+2004-10-11 13:11 cgilles
+
+ * Makefile.am: Removed 'DirOperation' kipi-plugin This feature must
+ been implemented in the hosts. CCMAIL: kde-imaging@kde.org
+
+2004-10-10 22:32 cgilles
+
+ * batchprocessimages/: borderimagesdialog.cpp,
+ colorimagesdialog.cpp, effectimagesdialog.cpp,
+ filterimagesdialog.cpp, recompressimagesdialog.cpp,
+ resizeimagesdialog.cpp: Fixed bug relevant of a preview fix about
+ embeded image conversion. The fix must be done only for
+ BatchConvertImage
+
+2004-10-08 15:53 cgilles
+
+ * Makefile.am, tips: Moved kipiplugins tips to the plugins folder.
+ CCMAIL: kde-imaging@kde.org
+
+2004-10-07 18:34 cgilles
+
+ * sendimages/: sendimages.cpp, sendimagesdialog.cpp,
+ sendimagesdialog.h: SendImages Kipi plugin: Added Thunderbird bin
+ path setup in dialog CCMAIL: digikam-devel@lists.sourceforge.net,
+ kde-imaging@kde.org
+
+2004-10-07 15:29 cgilles
+
+ * batchprocessimages/batchprocessimagesdialog.cpp: Fixed header
+
+2004-10-06 18:36 pahlibar
+
+ * slideshow/: Makefile.am, pausetimer.cpp, pausetimer.h,
+ slideshow.cpp, slideshow.h, slideshowgl.cpp, slideshowgl.h,
+ toolbar.cpp, toolbar.h:
+ * implemented mouse and keyboard control for slideshow * mouse
+ control is with a toolbar which pops up when mouse is moved to
+ any of the four corners of the desktop * keyboard control:
+ PageUp (previous), PageDown (next), Escape (close), SpaceBar
+ (toggle play and pause) * fixed crash due to wierd mouseMoveEvent
+ being called after closeEvent
+
+ CCMAIL: 88600-done@bugs.kde.org
+
+2004-10-06 16:39 cgilles
+
+ * batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/imagepreview.cpp,
+ batchprocessimages/renameimagesoptionsdialog.cpp,
+ batchprocessimages/renameimagesoptionsdialog.h,
+ cdarchiving/plugin_cdarchiving.cpp,
+ findimages/plugin_findimages.cpp,
+ imagesgallery/plugin_imagesgallery.cpp,
+ sendimages/plugin_sendimages.cpp: Fixed KDE 3.1 compatibility
+
+2004-10-05 15:07 cgilles
+
+ * kipiplugins.kdevelop, cdarchiving/cdarchiving.cpp,
+ imagesgallery/imagesgallery.cpp: Fixed crash when 'CDArchiving'
+ and 'ImageGallery' kipi plugin are started and closed imediatly
+ (reported by Renchi with Digikam) There is unvalid delete QMap at
+ the destructor call.
+
+2004-10-05 04:17 pahlibar
+
+ * calendar/: calwizard.cpp, calwizard.h:
+ if you are modifying working code, make sure to test it before
+ you make the commits. fixed broken calendar plugin CCMAIL:
+ kde-imaging@kde.org
+
+2004-10-04 17:46 lunakl
+
+ * acquireimages/: screenshotdialog.cpp, screenshotdialog.h: Fix
+ crash with Gwenview, which apparently doesn't have
+ kapp->mainWidget() set for some reason. Just hiding and showing
+ only the main window is not technically right anyway in case the
+ app has more toplevel windows. CCMAIL: kde-imaging@kde.org
+ CCMAIL: gwenview-general@lists.sourceforge.net
+
+2004-10-02 20:09 deller
+
+ * acquireimages/acquireimagedialog.cpp,
+ imagesgallery/imagesgallery.cpp, mpegencoder/checkbinprog.cpp,
+ mpegencoder/kimg2mpg.cpp, printwizard/frmprintwizard.cpp,
+ sendimages/sendimagesdialog.cpp: - roaming user fixes (user
+ readPathEntry() and writePathEntry() instead of
+ readEntry()/writeEntry() where it refers to file-paths)
+
+ btw, those sources would benefit from a big cleanup with using
+ readBoolEntry() instead of readEntry("true")=="true" and such....
+
+2004-09-30 23:31 pahlibar
+
+ * slideshow/slideshowgl.cpp:
+ check for max texture value allowed before generating the
+ textures. one user had a rather low texture size of 512. fixed
+ problem over priv mail conversation. CCMAIL:
+ 90183-done@bugs.kde.org
+
+2004-09-29 23:33 blackie
+
+ * batchprocessimages/batchprocessimagesdialog.cpp: angle was wrong
+ due to some bugs I of course can't reproduce now
+
+2004-09-29 23:13 blackie
+
+ * batchprocessimages/batchprocessimagesdialog.cpp: man I hate when
+ I forget to save before cvs ci
+
+2004-09-29 23:11 blackie
+
+ * batchprocessimages/batchprocessimagesdialog.cpp: slotGotPreview
+ did just display the image it found on disk, which is not correct
+ if the host application in memory has the image rotated (as in
+ contrast to on disk). This change hopefully fixes this bug.
+
+ Gilles, please verify that it still works for digikam - which I'm
+ pretty convinced it does ;-)
+
+2004-09-27 16:55 cgilles
+
+ * cdarchiving/: cdarchiving.cpp, cdarchiving.h,
+ plugin_cdarchiving.cpp: Disable QThread implementation in Kipi
+ CDArchiving plugin. CCMAIL: renchi@pooh.tam.uiuc.edu
+
+2004-09-27 16:30 cgilles
+
+ * imagesgallery/: imagesgallery.cpp, imagesgallery.h,
+ plugin_imagesgallery.cpp: Disable QThread implementation in KIPI
+ imagegallery plugin. CCMAIL: renchi@pooh.tam.uiuc.edu
+
+2004-09-26 23:13 todd
+
+ * printwizard/frmprintwizard.cpp: - Added 11.5x15cm photo size to
+ A4 - Added two new collage arrangements to Letter
+
+2004-09-26 18:27 mhunter
+
+ * printwizard/frmprintwizard.cpp: i18n fix
+
+2004-09-25 23:34 todd
+
+ * printwizard/: frmprintwizard.cpp, frmprintwizard.h,
+ frmprintwizardbase.ui, tphoto.cpp: - Added listbox for changing
+ the order of printed photos. - Added pager buttons to preview
+ all pages
+
+2004-09-25 17:03 cgilles
+
+ * batchprocessimages/: renameimagesdialog.cpp,
+ renameimagesoptionsdialog.cpp, renameimagesoptionsdialog.h: patch
+ from Martin Laberge for KDE 3.1 compatibility. CCMAIL:
+ kde-imaging@kde.org, digikam-devel@lists.sourceforge.net
+
+2004-09-25 15:06 cgilles
+
+ * sendimages/: Makefile.am, exifrestorer.cpp, exifrestorer.h,
+ jpegsection.h, sendimages.cpp: KIPI sendimages plugin : now,
+ resized JPEG images don't lost the EXIF informations ! CCMAIL:
+ kde-imaging@kde.org, digikam-users@lists.sourceforge.net
+
+2004-09-24 15:50 cgilles
+
+ * imagesgallery/: Makefile.am, exifrestorer.cpp, exifrestorer.h,
+ imagesgallery.cpp, jpegsection.h: Fixed bug #88939: - Resizing
+ images have no effect if no resize images option enable. - JPEG
+ exif data stored to the JPEG target images. CCMAIL:
+ kde-imaging@kde.org, digikam-users@lists.sourceforge.net
+
+2004-09-24 14:46 cgilles
+
+ * cdarchiving/: cdarchiving.cpp, cdarchiving.h,
+ cdarchivingdialog.h, plugin_cdarchiving.cpp: Kipi CDArchiving
+ plugin: fixed threaded implementation ! CCMAIL:
+ renchi@pooh.tam.uiuc.edu
+
+2004-09-24 10:59 cgilles
+
+ * batchprocessimages/resizeoptionsdialog.cpp: Added 1400dpi support
+ in Prepare to print (request by Richard Taylor) CCMAIL:
+ rjt-digicam@thegrindstone.me.uk
+
+2004-09-23 15:33 cgilles
+
+ * imagesgallery/: imagesgallery.cpp, imagesgallery.h,
+ plugin_imagesgallery.cpp: Fixed threaded implementation about
+ kipi interface call under thread. Using QMap and a new class for
+ to store the Albums data from the hosts. All kipi interface call
+ and GUI call run on 'prepare' unthreaded method. Must be
+ tested... CCMAIL: renchi@pooh.tam.uiuc.edu
+
+2004-09-23 12:26 cgilles
+
+ * batchprocessimages/: renameimagesdialog.cpp,
+ renameimagesdialog.h, renameimagesoptionsdialog.cpp,
+ renameimagesoptionsdialog.h: Fixed BatchRenameImages KIPI plugin:
+ - Using KDateTimeWidget instead KDateWidget. - Fixed some
+ problems with the implementation provide by the team during
+ Digikamplugins port.
+
+2004-09-23 08:14 cgilles
+
+ * batchprocessimages/: renameimagesdialog.cpp,
+ renameimagesdialog.h: KIPI BatchRenameImages : fixed files date
+ correction using Qt API instead C ANSI (from Showimg). CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-22 16:43 cgilles
+
+ * batchprocessimages/renameimagesdialog.cpp: BatchRenameImage
+ plugin : Restored old filter file name method. TODO support KURL.
+ CCMAIL: kde-imaging@kde.org
+
+2004-09-22 16:03 cgilles
+
+ * imagesgallery/imagesgallery.cpp: Fixed kipi url and collection
+ category
+
+2004-09-22 16:03 cgilles
+
+ * cdarchiving/cdarchiving.cpp: Fixed kipi url
+
+2004-09-22 15:47 cgilles
+
+ * calendar/caltemplate.cpp: KIPI calendar plugin : - Fixed layout.
+ - Added i18n. - Remove Framed line (no used and no necessary ?)
+ CCMAIL: renchi@pooh.tam.uiuc.edu
+
+2004-09-22 14:56 cgilles
+
+ * findimages/: displaycompare.cpp, finddupplicatedialog.cpp,
+ finddupplicateimages.cpp, plugin_findimages.cpp: Fixed tasks
+ progress bar in Fast mode. Fixed progress messages. Fixed
+ dialog. CCMAIL: kde-imaging@kde.org
+
+2004-09-22 10:52 cgilles
+
+ * batchprocessimages/: borderimagesdialog.cpp,
+ colorimagesdialog.cpp, convertimagesdialog.cpp,
+ effectimagesdialog.cpp, filterimagesdialog.cpp,
+ recompressimagesdialog.cpp, resizeimagesdialog.cpp: Kipi
+ batchProcessimages plugins : fixed bug #89720 CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-22 10:44 cgilles
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ batchprocessimagesdialog.h, borderimagesdialog.cpp,
+ colorimagesdialog.cpp, convertimagesdialog.cpp,
+ effectimagesdialog.cpp, filterimagesdialog.cpp,
+ renameimagesdialog.cpp, renameimagesoptionsdialog.h,
+ resizeimagesdialog.cpp: Fixed batchprocessimages kipi plugins
+ dialogs size. CCMAIL: kde-imaging@kde.org
+
+2004-09-22 04:06 pahlibar
+
+ * batchprocessimages/plugin_batchprocessimages.cpp,
+ jpeglossless/plugin_jpeglossless.cpp,
+ mpegencoder/plugin_mpegencoder.cpp,
+ printwizard/plugin_printwizard.cpp,
+ rawconverter/plugin_rawconverter.cpp,
+ rawconverter/plugin_rawconverter.h,
+ sendimages/plugin_sendimages.cpp, slideshow/plugin_slideshow.cpp,
+ timeadjust/plugin_timeadjust.cpp:
+ * remove currentScope() and currentScopeChanged() (signal) *
+ plugins updated to reflect change * gentlemen, please update your
+ apps CCMAIL: kde-imaging@kde.org
+
+2004-09-22 01:55 pahlibar
+
+ * configure.in.in:
+ uhh... allow kipi-plugins to compile if detected from the same
+ source tree
+
+2004-09-21 19:59 pahlibar
+
+ * configure.in.bot, configure.in.in:
+ * pkg-configified libkipi * kipi-plugins configure.in.in updated
+ to include tests for externally installed libkipi CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-21 17:00 cgilles
+
+ * imagesgallery/imagesgallery.cpp: Fixed bug #88885 CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-21 16:13 cgilles
+
+ * calendar/: calselect.cpp, caltemplate.cpp, calwizard.cpp,
+ calwizard.h: Added graphical banner to the kipi calendar wizard
+
+2004-09-21 14:57 cgilles
+
+ * kameraklient/: cameraselection.cpp, cameraui.cpp,
+ setupcamera.cpp: Added graphical banner to the top of Kipi
+ KameraKlient plugin dialogs.
+
+2004-09-21 13:19 cgilles
+
+ * sendimages/: listimageserrordialog.cpp, sendimages.cpp: Added
+ graphical banner
+
+2004-09-21 13:07 cgilles
+
+ * batchprocessimages/outputdialog.cpp: Added Graphical banner
+
+2004-09-21 12:33 cgilles
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ batchprocessimagesdialog.h, borderimagesdialog.cpp,
+ borderoptionsdialog.cpp, borderoptionsdialog.h,
+ colorimagesdialog.cpp, colorimagesdialog.h,
+ coloroptionsdialog.cpp, coloroptionsdialog.h,
+ convertimagesdialog.cpp, convertimagesdialog.h,
+ convertoptionsdialog.cpp, convertoptionsdialog.h,
+ effectimagesdialog.cpp, effectoptionsdialog.cpp,
+ effectoptionsdialog.h, filterimagesdialog.cpp,
+ filterimagesdialog.h, filteroptionsdialog.cpp,
+ filteroptionsdialog.h, imagepreview.cpp, renameimagesdialog.cpp,
+ resizeimagesdialog.cpp, resizeoptionsdialog.cpp,
+ resizeoptionsdialog.h: Fixed i18n problem withh all options in
+ KIPI batchprocessimages plugins. CCMAIL: kde-imaging@kde.org,
+ rjt-digicam@thegrindstone.me.uk
+
+2004-09-21 09:15 cgilles
+
+ * rawconverter/: batchdialog.cpp, singledialog.cpp: Added graphical
+ banner to the top of KIPI Raw converter dialogs.
+
+2004-09-20 22:47 cgilles
+
+ * acquireimages/screenshotdialog.cpp: Added graphical banner to the
+ top of kipi screenshoot plugin dialog.
+
+2004-09-20 22:37 cgilles
+
+ * mpegencoder/kimg2mpg.cpp: Added graphical banner to the top of
+ kipi MPEG encoder plugin dialog.
+
+2004-09-20 22:17 cgilles
+
+ * findimages/displaycompare.cpp: Added graphical banner to the kipi
+ finduplicateimages plugin results dialog.
+
+2004-09-20 15:17 mueller
+
+ * jpeglossless/Makefile.am: oops. wasn't supposed to be committed
+
+2004-09-20 15:17 mueller
+
+ * jpeglossless/: Makefile.am, actions.h: fix compile
+
+2004-09-20 09:43 cgilles
+
+ * slideshow/slideshowconfig.cpp: Added kipi graphic titles on the
+ dialog top.
+
+2004-09-19 21:22 cgilles
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ batchprocessimagesdialog.h, borderimagesdialog.cpp,
+ colorimagesdialog.cpp, convertimagesdialog.cpp,
+ effectimagesdialog.cpp, filterimagesdialog.cpp,
+ recompressimagesdialog.cpp, renameimagesdialog.cpp,
+ resizeimagesdialog.cpp: BatchProcessImages kipi plugins : Added
+ graphic border in dialog
+
+2004-09-18 23:38 gateau
+
+ * printwizard/frmprintwizard.cpp: Fixed compilation on KDE 3.1.
+
+2004-09-17 22:31 gateau
+
+ * cdarchiving/cdarchivingdialog.cpp: There is no need to prefix a
+ signal with "signal".
+
+2004-09-17 10:12 cgilles
+
+ * findimages/: finddupplicatedialog.cpp, finddupplicatedialog.h,
+ finddupplicateimages.cpp: KIPI findduplicateimages plugin: using
+ ImageCollectionSelector widget from Renchi. CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-16 14:39 cgilles
+
+ * imagesgallery/imagesgallery.cpp: Fixed partially kipi access in
+ the thread.
+
+2004-09-16 14:22 cgilles
+
+ * imagesgallery/: imagesgallery.cpp, imagesgallery.h,
+ plugin_imagesgallery.cpp: ImageGallery kip plugin: Fixed dialog
+ acces under threaded implementation Todo : fix kipi interface
+ access. CCMAIL: kde-imageing@kde.org
+
+2004-09-16 10:52 cgilles
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ imagepreview.cpp, renameimagesdialog.cpp: Fixed depreciate method
+ in according with KDE version CCMAIL: oliver@doerr-privat.de
+
+2004-09-16 08:35 cgilles
+
+ * sendimages/: plugin_sendimages.cpp, plugin_sendimages.h,
+ sendimages.cpp, sendimages.h, sendimagesdialog.cpp: Fixed
+ dialog/kipi interface access in threaded operations. CCMAIL:
+ kde-imaging@kde.org, renchi@pooh.tam.uiuc.edu
+
+2004-09-16 04:44 todd
+
+ * printwizard/frmprintwizardbase.ui: Hopefully fixed compile errors
+ for Qt 3.1.2 users. Copied the XPM icons over the newer PNG
+ icons generated by qt designer.
+
+2004-09-15 21:28 pahlibar
+
+ * slideshow/plugin_slideshow.cpp:
+ return is urllist is empty
+
+2004-09-15 15:55 cgilles
+
+ * cdarchiving/: cdarchiving.cpp, cdarchivingdialog.cpp,
+ cdarchivingdialog.h: CDArchiving Kipi plugin: support
+ ImageCollection selector widget. CCMAIL:kde-imaging@kde.org
+
+2004-09-15 03:07 todd
+
+ * printwizard/frmprintwizard.cpp: Added thumbnails to A4 and A6
+ sizes.
+
+2004-09-15 02:45 todd
+
+ * printwizard/: cropframe.cpp, cropframe.h, frmprintwizard.cpp,
+ frmprintwizard.h, frmprintwizardbase.ui, tphoto.cpp, tphoto.h:
+ Added thumbnail layouts (20 per sheet and 30 per sheet). Added
+ autoRotate override so thumbnails would not be rotated. Added
+ filename captions option, which places the image filename in the
+ lower left corner of the image in white sans font. Will improve
+ the font and give it a black border later.
+
+2004-09-14 16:11 cgilles
+
+ * batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/imagepreview.cpp,
+ batchprocessimages/renameimagesdialog.cpp,
+ sendimages/sendimagesdialog.cpp: BatchProcessImage Kipi plugin: -
+ Fixed warning for depreceate KDE API methods. - Using new
+ getImageURLs method from Renchi. SendImages Kipi plugin: - Using
+ new getImageURLs method from Renchi. CCMAIL: kde-imaging@kde.org
+
+2004-09-14 12:35 cgilles
+
+ * sendimages/plugin_sendimages.cpp: SendImage plugin: Improve
+ progress dialog messages CCMAIL: kde-imaging@kde.org
+
+2004-09-13 23:47 gateau
+
+ * kameraklient/: cameradragobject.cpp, cameradragobject.h,
+ camerafolderitem.cpp, camerafolderitem.h, camerafolderview.cpp,
+ camerafolderview.h, cameraiconitem.cpp, cameraiconitem.h,
+ cameraiconview.cpp, cameraiconview.h, cameralist.cpp,
+ cameralist.h, cameraselection.cpp, cameraselection.h,
+ cameratype.cpp, cameratype.h, cameraui.cpp, cameraui.h,
+ dmessagebox.cpp, dmessagebox.h, gpcamera.cpp, gpcamera.h,
+ gpcommand.h, gpcontroller.cpp, gpcontroller.h, gpeventfilter.cpp,
+ gpeventfilter.h, gpevents.h, gpfileitemcontainer.cpp,
+ gpfileitemcontainer.h, gpfileiteminfo.cpp, gpfileiteminfo.h,
+ gpfileiteminfodlg.cpp, gpfileiteminfodlg.h, gpiface.cpp,
+ gpiface.h, gpmessages.cpp, gpmessages.h, gpstatus.cpp,
+ gpstatus.h, kameraklient.cpp, kameraklient.h, mtlist.h,
+ mtqueue.h, savefiledialog.cpp, savefiledialog.h, setupcamera.cpp,
+ setupcamera.h, thumbitem.cpp, thumbitem.h, thumbview.cpp,
+ thumbview.h: Patch by Tudor Calin to add back the namespace.
+
+2004-09-13 15:48 cgilles
+
+ * findimages/: displaycompare.cpp, displaycompare.h:
+ Findduplicateimages plugin : fixed missing kipi::delImage call
+ when the user remove a duplicate image to the list. CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-10 15:52 pahlibar
+
+ * helloworld/plugin_helloworld.cpp:
+ * removed AlbumEQDir feature from interface * added new virtual
+ function to imagecollection(shared) isDirectory(). base
+ implementation returns false. CCMAIL: kde-imaging@kde.org
+
+2004-09-09 20:57 pahlibar
+
+ * mpegencoder/kimg2mpg.cpp:
+ * Image Selection Dialog now works in two modes: single url
+ selection or multiple url selection (listview extended mode,
+ shift/ctrl to make multiple selections) * mpegencoder image
+ selection changed to use the new multiple selection mode, as an
+ example CCMAIL: kde-imaging@kde.org
+
+2004-09-08 17:35 adrian
+
+ * kameraklient/gpstatus.cpp: add missing return statement
+
+2004-09-08 15:40 cgilles
+
+ * findimages/: actions.h, displaycompare.cpp,
+ finddupplicateimages.cpp, plugin_findimages.cpp:
+ FindDuplicateImages KIPI plugin : - Fixed events. - Fixed
+ progress bar. - Fixed dialog.
+
+ Almost findduplicateimage method in album library results (with
+ Digikam) :
+
+ 1234 images. 629 Mb (png, tiff, jpeg). Matrix creation time:
+ 505773 us Comparison time: 28161 us 71 similar images found.
+ Cache purged before.
+
+ ==> no crash
+
+ CCMAIL: kde-imaging@kde.org
+
+2004-09-08 08:09 cgilles
+
+ * cdarchiving/kipiplugin_cdarchiving.desktop,
+ sendimages/kipiplugin_sendimages.desktop,
+ timeadjust/kipiplugin_timeadjust.desktop: Fixed
+
+2004-09-07 19:40 pahlibar
+
+ * README, configure.in.in:
+ use opengl configure check from amarok. lot cleaner and also
+ makes it possible to enable the slideshow plugin build if qt is
+ not linked with libGL, but loads it up dynamically (for qt >=
+ 3.2.0) CCMAIL: kde-imaging@kde.org
+
+2004-09-07 15:50 cgilles
+
+ * kameraklient/: cameraselection.cpp, cameraselection.h,
+ cameraui.cpp, cameraui.h, setupcamera.cpp, setupcamera.h: Added
+ About data in KameraKlient Kipi plugin. CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-07 13:44 cgilles
+
+ * mpegencoder/: kimg2mpg.cpp, kimg2mpg.h, kshowdebuggingoutput.h:
+ MPEGEncoder KIPI plugin : -Added About data. -Fixed KURL support
+ (partially: need to rewrite the plugin core for that. Need to
+ use a full C++ implementation instead the Bash script !) CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-07 12:40 cgilles
+
+ * imagesgallery/: imgallerydialog.cpp, imgallerydialog.h: Added
+ About data in KIPI ImageGallery plugin. CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-07 11:04 cgilles
+
+ * rawconverter/: batchdialog.cpp, batchdialog.h, singledialog.cpp,
+ singledialog.h: KIPI RAW converter plugin : - Added About data.
+ - Fixed bad slot for preview. CCMAIL: kde-imaging@kde.org
+
+2004-09-07 10:23 cgilles
+
+ * timeadjust/: timeadjustdialog.cpp, timeadjustdialog.h: Added
+ About data in KIPI TimeAdjust plugin. CCMAIL:
+ kde-imaging@kde.org
+
+2004-09-07 09:41 cgilles
+
+ * slideshow/: slideshowconfig.cpp, slideshowconfig.h: Added About
+ data in KIPI Slideshow plugin. CCMAIL: kde-imaging@kde.org
+
+2004-09-07 09:17 cgilles
+
+ * sendimages/sendimages.cpp: SendImage KIPI plugin: - Fixed
+ ReadWrite operations on comments file to WriteOnly. - Added
+ empty line in comments file. CCMAIL: kde-imaging@kde.org
+
+2004-09-07 03:29 pahlibar
+
+ * Makefile.am, configure.in.in, jpeglossless/Makefile.am:
+ * make use of pkg-config to distribute libkexif. makes it a lot
+ easier to do configure checking of installation and version *
+ update libkipi/configure.in.in to use pkg-config checking for
+ libkexif * jpeglossless compilation is now dependent on whether
+ libkexif is available or not * testing requested. CCMAIL:
+ digikam-devel@lists.sourceforge.net, kde-imaging@kde.org
+
+2004-09-06 18:59 cgilles
+
+ * findimages/: displaycompare.cpp, displaycompare.h,
+ finddupplicatedialog.cpp, finddupplicatedialog.h,
+ plugin_findimages.cpp, plugin_findimages.h: Added About data in
+ FindDuplicateImages KIPI plugin Fixed menu entry : no need a
+ sub-menu at this time. CCMAIL: kde-imaging@kde.org
+
+2004-09-06 18:01 cgilles
+
+ * printwizard/: frmprintwizard.cpp, frmprintwizard.h: Added About
+ data in PrintWizard KIPI plugin CCMAIL: kde-imaging@kde.org
+
+2004-09-06 15:53 cgilles
+
+ * calendar/: calwizard.cpp, calwizard.h: Added About data in
+ Calendar KIPI plugin CCMAIL: kde-imaging@kde.org
+
+2004-09-06 15:49 gateau
+
+ * cdarchiving/plugin_cdarchiving.cpp,
+ imagesgallery/plugin_imagesgallery.cpp,
+ sendimages/plugin_sendimages.cpp: Fixed typo in enum.
+
+2004-09-06 15:12 cgilles
+
+ * sendimages/: sendimagesdialog.cpp, sendimagesdialog.h: Fixed
+ slots
+
+
+v0.1.0-beta1 2004-09-06
+----------------------------------------------------------------------------
+
+2004-09-06 14:26 cgilles
+
+ * sendimages/: sendimages.cpp, sendimages.h: SendImage plugin :
+ fixed bug #87188 CCMAIL: kde-imaging@kde.org
+
+2004-09-06 13:30 cgilles
+
+ * kipiplugins.kdevelop,
+ batchprocessimages/plugin_batchprocessimages.cpp: Fixed scope to
+ test for batch actions.
+
+2004-09-06 12:53 cgilles
+
+ * sendimages/: listimageserrordialog.cpp, sendimagesdialog.cpp,
+ sendimagesdialog.h: Added About data in 'SendImages' plugin.
+ CCMAIL: kde-imaging@kde.org
+
+2004-09-04 16:12 pahlibar
+
+ * printwizard/: frmprintwizard.cpp, frmprintwizardbase.ui:
+ applied patch from Treeve Jelbert for additional paper size
+ (10x15cm). need to add more layout options for this paper size
+
+2004-09-04 15:39 cgilles
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ batchprocessimagesdialog.h, borderimagesdialog.cpp,
+ borderimagesdialog.h, colorimagesdialog.cpp, colorimagesdialog.h,
+ convertimagesdialog.cpp, convertimagesdialog.h,
+ effectimagesdialog.cpp, effectimagesdialog.h,
+ filterimagesdialog.cpp, filterimagesdialog.h, imagepreview.cpp,
+ imagepreview.h, outputdialog.cpp, outputdialog.h,
+ recompressimagesdialog.cpp, recompressimagesdialog.h,
+ renameimagesdialog.cpp, renameimagesdialog.h,
+ resizeimagesdialog.cpp, resizeimagesdialog.h: Added about data
+ for batch processes images plugins CCMAIL: kde-imaging@kde.org
+
+2004-09-03 16:48 cgilles
+
+ * kipiplugins.kdevelop, acquireimages/acquireimagedialog.cpp,
+ acquireimages/acquireimagedialog.h,
+ acquireimages/screenshotdialog.cpp,
+ acquireimages/screenshotdialog.h,
+ cdarchiving/cdarchivingdialog.cpp: Fixed about data in
+ cdarchiving dialog Added about data in Acquire images plugins
+ dialog CCMAIL: kdeimaging@kde.org
+
+2004-09-02 22:46 mlaurent
+
+ * kameraklient/: camerafolderview.cpp, cameraiconview.cpp,
+ cameralist.cpp, cameraselection.cpp, dmessagebox.cpp,
+ gpcontroller.cpp, gpeventfilter.cpp, gpfileitemcontainer.cpp,
+ gpmessages.cpp, gpstatus.cpp, savefiledialog.cpp,
+ setupcamera.cpp, thumbview.cpp: Includemoc
+
+2004-08-31 19:16 gateau
+
+ * kameraklient/: Makefile.am, camerafolderitem.cpp,
+ camerafolderitem.h, camerafolderview.cpp, camerafolderview.h,
+ cameraiconitem.cpp, cameraiconitem.h, cameraiconview.cpp,
+ cameraiconview.h, cameralist.cpp, cameralist.h,
+ cameraselection.cpp, cameraselection.h, cameratype.cpp,
+ cameratype.h, cameraui.cpp, cameraui.h, dmessagebox.cpp,
+ dmessagebox.h, gpcamera.cpp, gpcamera.h, gpcommand.h,
+ gpcontroller.cpp, gpcontroller.h, gpeventfilter.cpp,
+ gpeventfilter.h, gpevents.h, gpfileitemcontainer.cpp,
+ gpfileitemcontainer.h, gpfileiteminfo.cpp, gpfileiteminfo.h,
+ gpfileiteminfodlg.cpp, gpfileiteminfodlg.h, gpiface.cpp,
+ gpiface.h, gpmessages.cpp, gpmessages.h, gpstatus.cpp,
+ gpstatus.h, kameraklient.cpp, kameraklient.h, mtlist.h,
+ mtqueue.h, savefiledialog.cpp, savefiledialog.h, setupcamera.cpp,
+ setupcamera.h, thumbitem.cpp, thumbitem.h, thumbview.cpp,
+ thumbview.h: Applied patch from Tudor Calin.
+
+2004-08-30 09:09 cgilles
+
+ * cdarchiving/cdarchivingdialog.cpp: Fixed bug report infos
+
+2004-08-29 16:28 cgilles
+
+ * cdarchiving/: cdarchivingdialog.cpp, cdarchivingdialog.h: Added
+ kde bug report for testing
+
+2004-08-23 18:39 pahlibar
+
+ * findimages/finddupplicatedialog.cpp:
+ check if the app has the required feature
+ (date,collection,comment,...), before trying to use them CCMAIL:
+ renchi@pooh.tam.uiuc.edu
+
+2004-08-15 02:43 pahlibar
+
+ * jpeglossless/: plugin_jpeglossless.cpp, plugin_jpeglossless.h:
+
+ * make jpeglossless actions shallower in the menus * rename "exif
+ adjustment" to more user friendly: "Auto Rotate/Flip Using Exif
+ Information"
+
+ CCMAIL: kde-imaging@kde.org, digikam-devel@lists.sourceforge.net
+
+2004-08-15 02:18 pahlibar
+
+ * jpeglossless/: actionthread.cpp, convert2grayscale.cpp,
+ jpegtransform.cpp, messagebox.cpp, messagebox.h:
+ * use qfile::encodename instead of latin1 * the messagebox got
+ embedded in the mainwindow. fixed
+
+2004-08-15 00:05 jahrens
+
+ * slideshow/: Makefile.am, pausetimer.cpp, pausetimer.h,
+ slideshow.cpp, slideshowgl.cpp, slideshowgl.h: - Moved PauseTimer
+ to pausetimer[.h|.cpp] to be able to use this timer in slideshow
+ and slideshowGL as well - Added PauseTimer to slideshowGL - Both
+ slideshows can now be interrupted by pressing the spacebar
+ CCMAIL: digikam-devel@lists.sourceforge.net
+
+2004-08-14 11:19 jahrens
+
+ * slideshow/: slideshow.cpp, slideshow.h: When the spacebar is
+ pressed, the slideshow is interrupted until the spacebar is
+ pressed again.
+
+ -> Additionally, it has to be added an info when the slideshow is
+ paused, maybe an icon like this "||" or "paused" at the bottom
+ line.
+
+ CCMAIL: 87106@bugs.kde.org
+
+2004-08-08 12:13 mlaurent
+
+ * kameraklient/: camerafolderview.cpp, cameraiconview.cpp,
+ cameralist.cpp, cameraselection.cpp, dmessagebox.cpp,
+ gpcontroller.cpp, gpeventfilter.cpp, gpfileitemcontainer.cpp,
+ gpmessages.cpp, gpstatus.cpp, savefiledialog.cpp,
+ setupcamera.cpp, thumbview.cpp: Includemoc
+
+2004-08-06 12:31 cgilles
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ plugin_batchprocessimages.cpp: - Fixed modal mode of dialog
+ (request for Drag/drop capability) ! (Jesper: warning, this
+ feature have been removed during the port from Digikamplugins to
+ KIPIplugin) Fixed selection mode ! CCMAIl: kdeimaging@kde.org
+
+2004-08-02 15:06 cgilles
+
+ * cdarchiving/cdarchiving.cpp: CDArchiving : fixed progress bar if
+ no HTML interface CCMAIL: kde-imaging@kde.org
+
+2004-07-27 17:42 pahlibar
+
+ * mpegencoder/: Makefile.am, images2mpg.1, images2mpg.1.gz:
+ moved manpages.1.gz to manpages.1
+
+2004-07-27 17:40 pahlibar
+
+ * rawconverter/: Makefile.am, kipidcrawclient.1,
+ kipidcrawclient.1.gz:
+ move manpage.1.gz to manpage.1
+
+2004-07-22 15:14 pahlibar
+
+ * batchprocessimages/batchprocessimagesdialog.cpp,
+ mpegencoder/kimg2mpg.cpp, sendimages/sendimagesdialog.cpp:
+ changed all instances of ImageCollectionDialog to ImageDialog
+
+2004-07-22 00:06 gateau
+
+ * calendar/monthwidget.cpp: Actually ImageDialog is more
+ "KDE-like". Sorry for the double rename. CCMAIL:
+ kde-imaging@kde.org
+
+2004-07-21 23:56 gateau
+
+ * calendar/monthwidget.cpp: As discussed on the mailing-list,
+ renamed ImageCollectionDialog to ImageChooser.
+ CCMAIL:kde-imaging@kde.org
+
+2004-07-17 13:18 gateau
+
+ * imagesgallery/: imagesgallery.cpp, imgallerydialog.cpp,
+ imgallerydialog.h: Make use of KIPI::ImageCollectionSelector.
+
+2004-07-17 12:05 pahlibar
+
+ * slideshow/plugin_slideshow.cpp:
+ slideshow should use currentAlbumChanged not currentScopeChanged
+
+2004-07-14 23:14 cgilles
+
+ * kameraklient/: cameradragobject.cpp, cameradragobject.h,
+ camerafolderitem.cpp, camerafolderitem.h, camerafolderview.cpp,
+ camerafolderview.h, cameraiconitem.cpp, cameraiconitem.h,
+ cameraiconview.cpp, cameraiconview.h, cameralist.cpp,
+ cameralist.h, cameraselection.cpp, cameraselection.h,
+ cameratype.cpp, cameratype.h, cameraui.cpp, cameraui.h,
+ dmessagebox.cpp, dmessagebox.h, gpcamera.cpp, gpcamera.h,
+ gpcommand.h, gpcontroller.cpp, gpcontroller.h, gpeventfilter.cpp,
+ gpeventfilter.h, gpevents.h, gpfileitemcontainer.cpp,
+ gpfileitemcontainer.h, gpfileiteminfo.cpp, gpfileiteminfo.h,
+ gpfileiteminfodlg.cpp, gpfileiteminfodlg.h, gpiface.cpp,
+ gpiface.h, gpmessages.cpp, gpmessages.h, gpstatus.cpp,
+ gpstatus.h, kameraklient.cpp, kameraklient.h, mtlist.h,
+ mtqueue.h, savefiledialog.cpp, savefiledialog.h, setupcamera.cpp,
+ setupcamera.h, thumbitem.cpp, thumbitem.h, thumbview.cpp,
+ thumbview.h: KameraKlient plugin: namespace wrapper CCMAIL:
+ kde-imaging@kde.org
+
+2004-07-14 21:50 cgilles
+
+ * printwizard/: cropframe.cpp, cropframe.h, frmprintwizard.cpp,
+ frmprintwizard.h, frmprintwizardbase.ui, plugin_printwizard.cpp,
+ tphoto.cpp, tphoto.h, utils.cpp, utils.h: PrintWizard plugin:
+ provide a full namespace wrapper (including the .ui file !!!)
+ Nota: For provide a namespace in the ui. file, i have changed:
+ <class>FrmPrintWizardBase</class> to:
+ <class>KIPIPrintWizardPlugin::FrmPrintWizardBase</class> and
+ <class>CropFrame</class> to:
+ <class>KIPIPrintWizardPlugin::CropFrame</class> This way is
+ undocumented but work fine (thanks to Wilfried Huss <Wilfried dot
+ Huss at gmx.at> for this solution). CCMAIL: kde-imaging@kde.org,
+ renchi@pooh.tam.uiuc.edu
+
+2004-07-09 09:45 gateau
+
+ * kameraklient/: cameradragobject.cpp, cameradragobject.h,
+ camerafolderitem.cpp, camerafolderitem.h, camerafolderview.cpp,
+ camerafolderview.h, cameraiconitem.cpp, cameraiconitem.h,
+ cameraiconview.cpp, cameraiconview.h, cameralist.cpp,
+ cameralist.h, cameratype.cpp, cameratype.h, cameraui.cpp,
+ cameraui.h, dmessagebox.h, gpcamera.cpp, gpcamera.h, gpcommand.h,
+ gpcontroller.cpp, gpcontroller.h, gpeventfilter.cpp,
+ gpeventfilter.h, gpevents.h, gpfileitemcontainer.cpp,
+ gpfileitemcontainer.h, gpfileiteminfo.cpp, gpfileiteminfo.h,
+ gpiface.cpp, gpiface.h, gpmessages.cpp, gpstatus.cpp, gpstatus.h,
+ kameraklient.cpp, kameraklient.h, mtlist.h, setupcamera.cpp,
+ setupcamera.h: Added back the copyright lines
+
+2004-07-08 16:05 cgilles
+
+ * cdarchiving/plugin_cdarchiving.cpp,
+ imagesgallery/plugin_imagesgallery.cpp: Fixed
+ m_progressDlg->setButtonCancel( KStdGuiItem::close() ) in
+ CDArchiving an ImageGallery plugins. CCMAIL: kde-imaging@kde.org
+
+2004-07-08 15:46 cgilles
+
+ * sendimages/: plugin_sendimages.cpp, plugin_sendimages.h,
+ sendimages.cpp, sendimages.h, sendimagesdialog.cpp,
+ sendimagesdialog.h: Fixed drag and drop capability in sendImages
+ plugin dialog. CCMAil: kde-imaging@kde.org
+
+2004-07-08 08:39 cgilles
+
+ * cdarchiving/cdarchiving.cpp, cdarchiving/plugin_cdarchiving.cpp,
+ findimages/plugin_findimages.cpp,
+ imagesgallery/imagesgallery.cpp,
+ imagesgallery/plugin_imagesgallery.cpp: Improved progress actions
+ list for CDArchiving and ImagesGallery plugins : using now the
+ thumbnailization process CCMAIL: kde-imaging@kde.org,
+ digikam-devel@lists.sourceforge.net,
+ digikam-users@lists.sourceforge.net
+
+2004-07-07 15:25 cgilles
+
+ * sendimages/: actions.h, listimageserrordialog.cpp,
+ plugin_sendimages.cpp, plugin_sendimages.h, sendimages.cpp,
+ sendimages.h: SendImages Plugin : using new KIPI batch progress
+ dialog. CCMAIL: kde-imaging@kde.org
+
+2004-07-07 09:04 cgilles
+
+ * ChangeLog, TODO, kipiplugins.kdevelop, cdarchiving/Makefile.am,
+ cdarchiving/batchprogressdialog.cpp,
+ cdarchiving/batchprogressdialog.h,
+ cdarchiving/plugin_cdarchiving.cpp,
+ cdarchiving/plugin_cdarchiving.h,
+ findimages/plugin_findimages.cpp, findimages/plugin_findimages.h,
+ imagesgallery/Makefile.am, imagesgallery/batchprogressdialog.cpp,
+ imagesgallery/batchprogressdialog.h,
+ imagesgallery/plugin_imagesgallery.cpp,
+ imagesgallery/plugin_imagesgallery.h: Added new Batch Progress
+ Dialog in KIPI nameSpace used by ImagesGallery, CDArchiving,
+ FindDupplicateImages, and SendImages plugins. CCMAIL:
+ kde-imaging@kde.org
+
+2004-07-06 21:42 fawcett
+
+ * rawconverter/Makefile.am: fix linkage
+
+2004-07-06 17:57 cgilles
+
+ * findimages/: finddupplicatedialog.cpp, finddupplicatedialog.h,
+ finddupplicateimages.cpp: Added progress dialog during Albums
+ parsing. CCMAIL: kde-imaging@kde.org
+
+2004-07-06 15:10 cgilles
+
+ * imagesgallery/: Makefile.am, actions.h, batchprogressdialog.cpp,
+ imagesgallery.cpp, imagesgallery.h, imgallerydialog.cpp,
+ imgallerydialog.h, listimageserrordialog.cpp,
+ listimageserrordialog.h, plugin_imagesgallery.cpp,
+ plugin_imagesgallery.h, resizeimage.cpp, resizeimage.h:
+ ImagesGallery plugin: - Complete rewriting from scratch with
+ multithreading support based on JPEGLossLess implementation. -
+ Added an actions progress dialog. - Removed obsolet source code
+ (old dialog and old threaded thumbnail implementation). CCMAIL:
+ kde-imaging@kde.org, renchi@pooh.tam.uiuc.edu
+
+2004-07-06 15:05 cgilles
+
+ * cdarchiving/: cdarchiving.cpp, cdarchiving.h: Fixed coding style.
+ Fixed broken image status during thumbnails creation. CCMAIl:
+ kde-imaging@kde.org
+
+2004-07-06 09:44 gateau
+
+ * kameraklient/Makefile.am: Fixed include directive, thanks to Jean
+ Michel Fayard.
+
+2004-07-05 14:10 cgilles
+
+ * cdarchiving/: batchprogressdialog.cpp, batchprogressdialog.h,
+ cdarchiving.cpp, cdarchivingdialog.cpp, cdarchivingdialog.h,
+ plugin_cdarchiving.cpp: Improved batchProgress dialog and thread
+ post event. CCMAIL: kde-imaging@kde.org
+
+2004-07-04 23:32 gateau
+
+ * Makefile.am, configure.in.in, kameraklient/.cvsignore,
+ kameraklient/Makefile.am, kameraklient/cameradragobject.cpp,
+ kameraklient/cameradragobject.h,
+ kameraklient/camerafolderitem.cpp,
+ kameraklient/camerafolderitem.h,
+ kameraklient/camerafolderview.cpp,
+ kameraklient/camerafolderview.h, kameraklient/cameraiconitem.cpp,
+ kameraklient/cameraiconitem.h, kameraklient/cameraiconview.cpp,
+ kameraklient/cameraiconview.h, kameraklient/cameralist.cpp,
+ kameraklient/cameralist.h, kameraklient/cameraselection.cpp,
+ kameraklient/cameraselection.h, kameraklient/cameratype.cpp,
+ kameraklient/cameratype.h, kameraklient/cameraui.cpp,
+ kameraklient/cameraui.h, kameraklient/dmessagebox.cpp,
+ kameraklient/dmessagebox.h, kameraklient/gpcamera.cpp,
+ kameraklient/gpcamera.h, kameraklient/gpcommand.h,
+ kameraklient/gpcontroller.cpp, kameraklient/gpcontroller.h,
+ kameraklient/gpeventfilter.cpp, kameraklient/gpeventfilter.h,
+ kameraklient/gpevents.h, kameraklient/gpfileitemcontainer.cpp,
+ kameraklient/gpfileitemcontainer.h,
+ kameraklient/gpfileiteminfo.cpp, kameraklient/gpfileiteminfo.h,
+ kameraklient/gpfileiteminfodlg.cpp,
+ kameraklient/gpfileiteminfodlg.h, kameraklient/gpiface.cpp,
+ kameraklient/gpiface.h, kameraklient/gpmessages.cpp,
+ kameraklient/gpmessages.h, kameraklient/gpstatus.cpp,
+ kameraklient/gpstatus.h, kameraklient/hi16-action-documents.png,
+ kameraklient/hi16-action-generic.png,
+ kameraklient/hi16-action-multimedia.png,
+ kameraklient/hi16-action-new.png,
+ kameraklient/hi16-action-pictures.png,
+ kameraklient/hi16-action-sound.png,
+ kameraklient/hi22-action-documents.png,
+ kameraklient/hi22-action-generic.png,
+ kameraklient/hi22-action-multimedia.png,
+ kameraklient/hi22-action-new.png,
+ kameraklient/hi22-action-pictures.png,
+ kameraklient/hi22-action-sound.png,
+ kameraklient/hi32-action-documents.png,
+ kameraklient/hi32-action-generic.png,
+ kameraklient/hi32-action-multimedia.png,
+ kameraklient/hi32-action-new.png,
+ kameraklient/hi32-action-pictures.png,
+ kameraklient/hi32-action-sound.png,
+ kameraklient/hi48-action-documents.png,
+ kameraklient/hi48-action-generic.png,
+ kameraklient/hi48-action-multimedia.png,
+ kameraklient/hi48-action-new.png,
+ kameraklient/hi48-action-pictures.png,
+ kameraklient/hi48-action-sound.png,
+ kameraklient/kameraklient.cpp, kameraklient/kameraklient.h,
+ kameraklient/kipiplugin_kameraklient.desktop,
+ kameraklient/mtlist.h, kameraklient/mtqueue.h,
+ kameraklient/savefiledialog.cpp, kameraklient/savefiledialog.h,
+ kameraklient/setupcamera.cpp, kameraklient/setupcamera.h,
+ kameraklient/thumbitem.cpp, kameraklient/thumbitem.h,
+ kameraklient/thumbview.cpp, kameraklient/thumbview.h: Initial
+ import of KameraKlient. A KIPI plugin by Tudor Calin to import
+ images from digital cameras. Based on Digikam code.
+
+2004-07-04 22:56 cgilles
+
+ * cdarchiving/: actions.h, batchprogressdialog.cpp,
+ cdarchiving.cpp, cdarchivingdialog.cpp, cdarchivingdialog.h,
+ plugin_cdarchiving.cpp: Updated dispach errors messages between
+ thread and actions dialog. Added progress dialog when Albums are
+ parsing. CCMAIL: kde-imaging@kde.org
+
+2004-07-03 23:18 cgilles
+
+ * cdarchiving/: batchprogressdialog.cpp, cdarchiving.cpp,
+ plugin_cdarchiving.cpp: Fixed missing post envent when K3b is
+ done. Fixed disconnected signal when k3b is done. Cdarchiving
+ using multithreading capabilities done ! CCMAIL:
+ kde-imaging@kde.org
+
+2004-07-02 18:02 cgilles
+
+ * cdarchiving/: Makefile.am, actions.h, batchprogressdialog.cpp,
+ batchprogressdialog.h, cdarchiving.cpp, cdarchiving.h,
+ cdarchivingdialog.cpp, cdarchivingdialog.h,
+ plugin_cdarchiving.cpp, plugin_cdarchiving.h: CDArchiving plugin:
+ - Complete rewriting from scratch with multithreading support
+ based on JPEGLossLess implementation. - Added an actions
+ progress dialog (uncomplete). Work fine but must be improved!
+ CCMAIL: kde-imaging@kde.org, renchi@pooh.tam.uiuc.edu
+
+2004-07-01 17:50 cgilles
+
+ * sendimages/: plugin_sendimages.cpp, sendimages.cpp, sendimages.h:
+ Fixed i18n message. Fixed thread post event.
+
+2004-07-01 16:05 cgilles
+
+ * sendimages/: Makefile.am, actions.h, listimageserrordialog.cpp,
+ listimageserrordialog.h, plugin_sendimages.cpp,
+ plugin_sendimages.h, sendimages.cpp, sendimages.h,
+ sendimagesdialog.cpp, sendimagesdialog.h: SendImages plugin :
+ complete rewrite from scratch using multithreading capabilities
+ (inspired from JPEGLossLess plugin). 100% Done ! Work fine, but
+ can be certainly improved... CCMAIL: kde-imaging@kde.org,
+ renchi@pooh.tam.uiuc.edu
+
+2004-07-01 08:56 cgilles
+
+ * mpegencoder/: kimg2mpg.cpp, kimg2mpg.h: Fixed missing preview
+ failed slot.
+
+2004-06-29 14:12 cgilles
+
+ * mpegencoder/kimg2mpg.cpp, mpegencoder/kimg2mpg.h,
+ sendimages/sendimagesdialog.cpp, sendimages/sendimagesdialog.h:
+ Bugfix : image preview job is broken if the job instance isn't
+ declared under the main class not in local (memory reference
+ conflic ?) CCMAIL: kde-imaging@kde.org
+
+2004-06-29 13:25 cgilles
+
+ * sendimages/sendimagesdialog.cpp: Remove PENDING comments
+
+2004-06-29 13:23 cgilles
+
+ * acquireimages/: acquireimagedialog.cpp, acquireimagedialog.h,
+ screenshotdialog.cpp, screenshotdialog.h: Fixed bug: infinte loop
+ in find unique url code (provide during the kipi port). Fixed
+ PENDING tasks. CCMAIl: kde-imaging@kde.org
+
+2004-06-29 12:53 cgilles
+
+ * cdarchiving/cdarchiving.h, cdarchiving/cdarchivingdialog.cpp,
+ findimages/finddupplicatedialog.cpp,
+ imagesgallery/imgallerydialog.cpp: Added
+ 'AlbumsUseFirstImagePreview' feature support (disable preview of
+ current Album selected if this feature isn't supported by the
+ host) CCMAIL: kde-imaging@kde.org
+
+2004-06-29 12:50 cgilles
+
+ * imagesgallery/imgallerydialog.cpp: Added
+ 'AlbumsUseFirstImagePreview' feature support in ImagesGallery
+ dialog. CCMAIL: kde-im
+
+2004-06-29 12:48 cgilles
+
+ * mpegencoder/kimg2mpg.cpp: Added ImageCollectionDialog support in
+ MPEGEncoder plugin. Fixed PENDING tasks. CCMAIL:
+ kde-imaging@kde.org
+
+2004-06-29 10:01 gateau
+
+ * TODO: Updated to what we agreed on the mailing list.
+
+2004-06-28 16:02 cgilles
+
+ * sendimages/: listimageserrordialog.cpp, listimageserrordialog.h,
+ sendimagesdialog.cpp, sendimagesdialog.h: Fixed target images
+ files name (resized before to E-mail) without double file
+ extension (it's not really a bug). Using '_' instead "." for the
+ first file extension (like foo_png.jpg for example). CCMAIL:
+ kde-imaging@kde.org
+
+2004-06-28 13:56 cgilles
+
+ * acquireimages/plugin_acquireimages.cpp,
+ batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/imagepreview.cpp, cdarchiving/cdarchiving.cpp,
+ imagesgallery/resizeimage.cpp, jpeglossless/actions.h,
+ jpeglossless/actionthread.cpp, jpeglossless/actionthread.h,
+ jpeglossless/convert2grayscale.cpp,
+ jpeglossless/convert2grayscale.h, jpeglossless/imageflip.cpp,
+ jpeglossless/imageflip.h, jpeglossless/imagerotate.cpp,
+ jpeglossless/imagerotate.h, jpeglossless/jpegtransform.cpp,
+ jpeglossless/jpegtransform.h, jpeglossless/messagebox.cpp,
+ jpeglossless/messagebox.h, jpeglossless/mtqueue.h,
+ jpeglossless/plugin_jpeglossless.cpp,
+ jpeglossless/plugin_jpeglossless.h, jpeglossless/progressdlg.cpp,
+ jpeglossless/progressdlg.h, jpeglossless/utils.cpp,
+ jpeglossless/utils.h, mpegencoder/kimg2mpg.cpp,
+ printwizard/plugin_printwizard.cpp,
+ sendimages/plugin_sendimages.cpp,
+ sendimages/sendimagesdialog.cpp: Fixed namespace name in
+ JPEGLosLess plugin in according with other plugins namespaces.
+ Used kdDebug instead qDebug. Fixed tmp folder name.
+
+2004-06-28 08:53 cgilles
+
+ * cdarchiving/: cdarchiving.cpp, cdarchivingdialog.cpp,
+ cdarchivingdialog.h: Fixed missing Pending task provide by Jesper
+ (problem during K3b project creation) CDArchiving work fine now.
+ CCMAIL: kde-imaging@kde.org
+
+2004-06-24 23:31 cgilles
+
+ * cdarchiving/: cdarchiving.cpp, cdarchivingdialog.cpp,
+ cdarchivingdialog.h: CDArchiving plugin : fixed all pending tasks
+ !!! CCMAIL: kde-imaging@kde.org
+
+2004-06-24 15:56 cgilles
+
+ * findimages/: displaycompare.cpp, displaycompare.h,
+ finddupplicatedialog.cpp, finddupplicatedialog.h,
+ finddupplicateimages.cpp, finddupplicateimages.h:
+ FindDuplicateImages plugin : All pending tasks done !!! CCMAIL:
+ kde-imaging@kde.org
+
+2004-06-24 13:44 cgilles
+
+ * imagesgallery/: imagesgallery.cpp, imgallerydialog.cpp,
+ imgallerydialog.h: Fixed all PENDING tasks in KIPI ImagesGallery
+ plugin!!! CCMAIL: kde-imaging@kde.org
+
+2004-06-24 12:07 faure
+
+ * configure.in.in, mpegencoder/Makefile.am,
+ mpegencoder/images2mpg.1.gz, mpegencoder/images2mpg.man.gz,
+ rawconverter/Makefile.am, rawconverter/kipidcrawclient.1.gz,
+ rawconverter/kipidcrawclient.man.gz: Install man pages properly,
+ with man_MANS
+
+2004-06-24 11:50 faure
+
+ * cdarchiving/autorun/Makefile.am: What's simpler? broken
+ install-data-local crap, or two-liner correct rules as documented
+ on developer.kde.org? :/
+
+2004-06-24 11:42 faure
+
+ * Makefile.am, configure.in.in: If you want to conditionally
+ compile a subdir, check the Makefile.am howto on
+ developer.kde.org instead of breaking a perfectly ok Makefile.am.
+ This fixes compilation with unsermake. CCMAIL: Renchi Raju
+ <renchi@pooh.tam.uiuc.edu>
+
+2004-06-24 11:23 cgilles
+
+ * helloworld/plugin_helloworld.cpp: In according with Jesper : -
+ Added new KIPI features AlbumsHaveCategory and
+ AlbumsHaveCreationDate requested for ImagesGallery an CDArchiving
+ plugins. - Added new virtuals methods in KIPI::ImageCollection
+ and KIPI::ImageCollectionShared class in according with this new
+ features. CCMAIL: kde-imaging@kde.org
+
+2004-06-23 14:56 cgilles
+
+ * cdarchiving/cdarchiving.cpp, cdarchiving/cdarchiving.h,
+ imagesgallery/imagesgallery.cpp, imagesgallery/imagesgallery.h:
+ Added host application aboudata parsing used for provide to the
+ HTML page a name and an URL in according with. CCMAIL:
+ kde-imaging@kde.org
+
+2004-06-23 10:25 cgilles
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ convertimagesdialog.cpp, renameimagesdialog.cpp: Fixed a missing
+ statusbar refresh (probably removed during the KIPI port).
+
+2004-06-22 17:46 cgilles
+
+ * batchprocessimages/plugin_batchprocessimages.cpp,
+ calendar/plugin_calendar.cpp, cdarchiving/cdarchivingdialog.h,
+ cdarchiving/plugin_cdarchiving.cpp,
+ imagesgallery/plugin_imagesgallery.cpp,
+ mpegencoder/plugin_mpegencoder.cpp,
+ printwizard/plugin_printwizard.cpp: In according with Renchi Raju
+ : Fixed static_cast to dynamic_cast. Added test if kipi
+ interface is valid.
+
+2004-06-22 13:49 cgilles
+
+ * batchprocessimages/batchprocessimagesdialog.cpp: Fixed widget
+ size
+
+2004-06-22 12:33 cgilles
+
+ * batchprocessimages/batchprocessimagesdialog.cpp: BUGFIX : bad
+ config instance delete CCMAIL: kde-imaging@kde.org
+
+2004-06-22 11:36 cgilles
+
+ * acquireimages/plugin_acquireimages.cpp,
+ findimages/plugin_findimages.cpp,
+ helloworld/plugin_helloworld.cpp,
+ jpeglossless/plugin_jpeglossless.cpp,
+ rawconverter/plugin_rawconverter.cpp,
+ slideshow/plugin_slideshow.cpp, wallpaper/plugin_wallpaper.cpp:
+ Fix static_cast by dynamic_cast pointer on host kipi interface
+
+2004-06-21 16:09 cgilles
+
+ * batchprocessimages/plugin_batchprocessimages.cpp: Fix static cast
+
+2004-06-21 08:53 cgilles
+
+ * kipiplugins.kdevelop, acquireimages/acquireimagedialog.cpp,
+ acquireimages/screenshotdialog.cpp,
+ batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/borderimagesdialog.cpp,
+ batchprocessimages/colorimagesdialog.cpp,
+ batchprocessimages/convertimagesdialog.cpp,
+ batchprocessimages/effectimagesdialog.cpp,
+ batchprocessimages/filterimagesdialog.cpp,
+ batchprocessimages/recompressimagesdialog.cpp,
+ batchprocessimages/renameimagesdialog.cpp,
+ batchprocessimages/resizeimagesdialog.cpp,
+ calendar/calwizard.cpp, cdarchiving/cdarchivingdialog.cpp,
+ findimages/displaycompare.cpp,
+ findimages/finddupplicatedialog.cpp,
+ imagesgallery/imgallerydialog.cpp, mpegencoder/kimg2mpg.cpp,
+ printwizard/frmprintwizard.cpp, rawconverter/batchdialog.cpp,
+ rawconverter/singledialog.cpp, sendimages/sendimagesdialog.cpp,
+ slideshow/slideshowconfig.cpp, timeadjust/timeadjustdialog.cpp:
+ Update handbooks links
+
+2004-06-19 12:38 cgilles
+
+ * slideshow/: imlibiface.cpp, imlibiface.h, plugin_slideshow.cpp,
+ slideshow.cpp, slideshow.h, slideshowconfig.cpp,
+ slideshowconfig.h, slideshowgl.cpp, slideshowgl.h: Added
+ namespace in SlideShow plugin. CCMAIL: kde-imaging@kde.org
+
+2004-06-19 12:09 cgilles
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ batchprocessimagesdialog.h, batchprocessimagesitem.cpp,
+ batchprocessimagesitem.h, batchprocessimageslist.cpp,
+ batchprocessimageslist.h, borderimagesdialog.cpp,
+ borderimagesdialog.h, borderoptionsdialog.cpp,
+ borderoptionsdialog.h, colorimagesdialog.cpp,
+ colorimagesdialog.h, coloroptionsdialog.cpp,
+ coloroptionsdialog.h, convertimagesdialog.cpp,
+ convertimagesdialog.h, convertoptionsdialog.cpp,
+ convertoptionsdialog.h, effectimagesdialog.cpp,
+ effectimagesdialog.h, effectoptionsdialog.cpp,
+ effectoptionsdialog.h, filterimagesdialog.cpp,
+ filterimagesdialog.h, filteroptionsdialog.cpp,
+ filteroptionsdialog.h, imagepreview.cpp, imagepreview.h,
+ outputdialog.cpp, outputdialog.h, plugin_batchprocessimages.cpp,
+ plugin_batchprocessimages.h, recompressimagesdialog.cpp,
+ recompressimagesdialog.h, recompressoptionsdialog.cpp,
+ recompressoptionsdialog.h, renameimagesdialog.cpp,
+ renameimagesdialog.h, renameimagesoptionsdialog.cpp,
+ renameimagesoptionsdialog.h, resizeimagesdialog.cpp,
+ resizeimagesdialog.h, resizeoptionsdialog.cpp,
+ resizeoptionsdialog.h: Added namespace in batchProcessImages
+ plugin. CCMAIL: kde-imaging@kde.org
+
+2004-06-19 11:35 cgilles
+
+ * timeadjust/: plugin_timeadjust.cpp, plugin_timeadjust.h,
+ timeadjustdialog.cpp, timeadjustdialog.h: Added namespace in
+ TimeAdjust plugin. CCMAIL: kde-imaging@kde.org
+
+2004-06-19 11:16 cgilles
+
+ * sendimages/: listimageserrordialog.cpp, listimageserrordialog.h,
+ plugin_sendimages.cpp, plugin_sendimages.h, sendimagesdialog.cpp,
+ sendimagesdialog.h: Added namespace in Sendimages plugin CCMAIL:
+ kde-imaging@kde.org
+
+2004-06-19 11:08 cgilles
+
+ * mpegencoder/: checkbinprog.cpp, checkbinprog.h, kimg2mpg.cpp,
+ kimg2mpg.h, kshowdebuggingoutput.cpp, kshowdebuggingoutput.h,
+ optionsdialog.cpp, optionsdialog.h, plugin_mpegencoder.cpp: Added
+ namespace in MPEGEncoder plugin CCMAIL: kde-imaging@kde.org
+
+2004-06-19 10:51 cgilles
+
+ * acquireimages/: acquireimagedialog.cpp, acquireimagedialog.h,
+ plugin_acquireimages.cpp, plugin_acquireimages.h,
+ screenshotdialog.cpp, screenshotdialog.h: Added namespace for
+ AcquireImages plugins CCMAIL: kde-imaging@kde.org
+
+2004-06-19 10:50 cgilles
+
+ * kipiplugins.kdevelop: Added a basic kdevelop project for kipi
+ plugins. Must be improved (config)
+
+2004-06-19 02:55 craig
+
+ * cdarchiving/: cdarchiving.cpp, cdarchivingdialog.cpp: Add parents
+ to dialogs
+
+2004-06-19 02:48 craig
+
+ * calendar/: calwizard.cpp, calwizard.h, plugin_calendar.cpp: * Add
+ parents to dialogs * Add caption
+
+2004-06-19 02:41 craig
+
+ * batchprocessimages/: plugin_batchprocessimages.cpp,
+ resizeoptionsdialog.cpp: Add parents to dialogs
+
+2004-06-19 01:57 craig
+
+ * acquireimages/: acquireimagedialog.cpp, plugin_acquireimages.cpp,
+ screenshotdialog.cpp: Add parents to dialogs
+
+2004-06-19 01:48 craig
+
+ * jpeglossless/: messagebox.cpp, progressdlg.cpp, progressdlg.h: *
+ Add parents to dialogs * Use KPushButton and KStdGuiItem
+
+2004-06-19 00:07 craig
+
+ * jpeglossless/plugin_jpeglossless.cpp: Ask for confirmation before
+ converting an image to black and white.
+
+2004-06-18 16:03 cgilles
+
+ * findimages/: displaycompare.cpp, displaycompare.h,
+ finddupplicatedialog.cpp, finddupplicatedialog.h,
+ finddupplicateimages.cpp, finddupplicateimages.h,
+ plugin_findimages.cpp, plugin_findimages.h: Added namespace for
+ FindDupplicateImages plugin. CCMAIL: kde-imaging@kde.org
+
+2004-06-18 15:51 cgilles
+
+ * cdarchiving/: cdarchiving.cpp, cdarchiving.h,
+ cdarchivingdialog.cpp, cdarchivingdialog.h,
+ plugin_cdarchiving.cpp, plugin_cdarchiving.h: Added NameSpace in
+ CDArchiving plugin. CCMAIl: kde-imaging@kde.org
+
+2004-06-18 15:25 cgilles
+
+ * imagesgallery/: imagesgallery.cpp, imagesgallery.h,
+ imgallerydialog.cpp, imgallerydialog.h,
+ listimageserrordialog.cpp, listimageserrordialog.h,
+ plugin_imagesgallery.cpp, plugin_imagesgallery.h,
+ resizeimage.cpp, resizeimage.h: Added namespace for ImageGallery
+ == Fix memory conflic with CDArchiving !!! CCMAIL:
+ kde-imaging@kde.org
+
+2004-06-18 08:02 cgilles
+
+ * jpeglossless/plugin_jpeglossless.cpp,
+ timeadjust/plugin_timeadjust.cpp, wallpaper/plugin_wallpaper.cpp:
+ Fixed currentSelection to currentScope in according with Jesper.
+ Nota : No Change in WallPaper plugin because there is no scence :
+ only one image can be push on the desktop background at the same
+ time.
+
+ CCMAIL: kde-imaging@kde.org
+
+2004-06-17 20:04 pahlibar
+
+ * Makefile.am, configure.in.in:
+
+ "fixed" configure to allow slideshow to be compiled. added test
+ to check if qt has been compiled with opengl support if
+ --enable-opengl is not specified. testing requested.
+
+ CCMAIL: kde-imaging@kde.org
+
+2004-06-17 18:56 cgilles
+
+ * timeadjust/timeadjustdialog.cpp: Added handbook link
+
+2004-06-17 18:42 cgilles
+
+ * ChangeLog, jpeglossless/plugin_jpeglossless.cpp,
+ jpeglossless/plugin_jpeglossless.h,
+ timeadjust/plugin_timeadjust.cpp, wallpaper/plugin_wallpaper.cpp,
+ wallpaper/plugin_wallpaper.h: Fixed actions enabled/disabled in
+ according with current selection for JPEGLossLess, TimeAjust, and
+ WallPaper plugins. CCMAIL: kde-imaging@kde.org
+
+2004-06-17 12:45 cgilles
+
+ * ChangeLog, acquireimages/acquireimagedialog.cpp,
+ acquireimages/acquireimagedialog.h,
+ batchprocessimages/batchprocessimagesdialog.cpp,
+ cdarchiving/cdarchiving.cpp, cdarchiving/cdarchiving.h,
+ cdarchiving/cdarchivingdialog.cpp,
+ cdarchiving/cdarchivingdialog.h,
+ findimages/finddupplicatedialog.cpp,
+ findimages/finddupplicateimages.cpp,
+ imagesgallery/imagesgallery.cpp,
+ imagesgallery/imgallerydialog.cpp, mpegencoder/kimg2mpg.cpp,
+ mpegencoder/kimg2mpg.h, mpegencoder/plugin_mpegencoder.cpp,
+ sendimages/sendimagesdialog.cpp: Added new method
+ 'fileExtensions()' for images files sorting in plugins instead
+ digikamrc config file parsing. CCMAIL: kde-imaging@kde.org
+
+2004-06-16 15:29 cgilles
+
+ * acquireimages/acquireimagedialog.cpp,
+ cdarchiving/cdarchivingdialog.cpp,
+ imagesgallery/imgallerydialog.cpp, rawconverter/batchdialog.cpp,
+ rawconverter/singledialog.cpp, timeadjust/timeadjustdialog.cpp:
+ Added basic kipi icon. Change about plugins part in according.
+ CCMAIL: kde-imaging@kde.org
+
+2004-06-16 14:33 cgilles
+
+ * acquireimages/: plugin_acquireimages.cpp, plugin_acquireimages.h:
+ Remove KMenuAction (not necessary since this plugin is in
+ IMPORTPLUGIN category) CCMAIL: kde-imaging@kde.org
+
+2004-06-16 13:01 cgilles
+
+ * acquireimages/plugin_acquireimages.cpp,
+ acquireimages/plugin_acquireimages.h,
+ batchprocessimages/plugin_batchprocessimages.cpp,
+ batchprocessimages/plugin_batchprocessimages.h,
+ calendar/plugin_calendar.cpp, calendar/plugin_calendar.h,
+ cdarchiving/plugin_cdarchiving.cpp,
+ cdarchiving/plugin_cdarchiving.h,
+ findimages/plugin_findimages.cpp, findimages/plugin_findimages.h,
+ helloworld/plugin_helloworld.cpp, helloworld/plugin_helloworld.h,
+ imagesgallery/plugin_imagesgallery.cpp,
+ imagesgallery/plugin_imagesgallery.h,
+ jpeglossless/plugin_jpeglossless.cpp,
+ jpeglossless/plugin_jpeglossless.h,
+ mpegencoder/plugin_mpegencoder.cpp,
+ mpegencoder/plugin_mpegencoder.h,
+ printwizard/plugin_printwizard.cpp,
+ printwizard/plugin_printwizard.h,
+ rawconverter/plugin_rawconverter.cpp,
+ rawconverter/plugin_rawconverter.h,
+ sendimages/plugin_sendimages.cpp, sendimages/plugin_sendimages.h,
+ slideshow/plugin_slideshow.cpp, slideshow/plugin_slideshow.h,
+ timeadjust/plugin_timeadjust.cpp, timeadjust/plugin_timeadjust.h,
+ wallpaper/plugin_wallpaper.cpp, wallpaper/plugin_wallpaper.h:
+ Removed 'category()' method for plugins category identification.
+ CCMAIL: kde-imaging@kde.org
+
+2004-06-15 18:55 cgilles
+
+ * rawconverter/: plugin_rawconverter.cpp, plugin_rawconverter.h:
+ New plugin category identification method based on KAction
+ identification required for RawConverter plugin.
+
+ CCMAIL: kde-imaging@kde.org
+
+2004-06-15 15:13 cgilles
+
+ * acquireimages/acquireimagedialog.cpp,
+ acquireimages/plugin_acquireimages.cpp,
+ acquireimages/screenshotdialog.cpp,
+ batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/borderimagesdialog.cpp,
+ batchprocessimages/colorimagesdialog.cpp,
+ batchprocessimages/convertimagesdialog.cpp,
+ batchprocessimages/effectimagesdialog.cpp,
+ batchprocessimages/filterimagesdialog.cpp,
+ batchprocessimages/imagepreview.cpp,
+ batchprocessimages/recompressimagesdialog.cpp,
+ batchprocessimages/renameimagesdialog.cpp,
+ batchprocessimages/resizeimagesdialog.cpp,
+ calendar/calwizard.cpp, cdarchiving/cdarchiving.cpp,
+ cdarchiving/cdarchivingdialog.cpp,
+ cdarchiving/plugin_cdarchiving.cpp,
+ findimages/displaycompare.cpp,
+ findimages/finddupplicatedialog.cpp,
+ imagesgallery/imagesgallery.cpp,
+ imagesgallery/imgallerydialog.cpp,
+ imagesgallery/plugin_imagesgallery.cpp,
+ imagesgallery/resizeimage.cpp, jpeglossless/actionthread.cpp,
+ printwizard/frmprintwizard.cpp,
+ printwizard/plugin_printwizard.cpp, rawconverter/batchdialog.cpp,
+ rawconverter/processcontroller.cpp,
+ rawconverter/singledialog.cpp, slideshow/plugin_slideshow.cpp,
+ slideshow/slideshowconfig.cpp: Fix 'kipi' instead 'digikam': - In
+ comments. - In dialog text and title. - In temporaly folders
+ creation. - In ressource loading path (specific icons, script,
+ etc.) - Handbook page call (PENDING : the kipi handbook must be
+ created - based on Digikam plugins sections handbook).
+
+ IMPORTANT : There is a very important _PENDING_ task to do : the
+ kipirc file must have a config line for the images files filter
+ using in the plugins. Digikam rc file have this line from the
+ Albums files filter config.
+
+ For example, from the CDArchiving plugins, the pending
+ implementation is :
+
+ // PENDING (Gilles) : Using kipirc file!
+ // Read File Filter settings in digikamrc file.
+
+ m_config = new KConfig("digikamrc");
+ m_config->setGroup("Album Settings");
+ QString Temp = m_config->readEntry("File Filter", "*.jpg
+ *.jpeg *.tif *.tiff *.gif *.png *.bmp");
+ m_imagesFileFilter = Temp.lower() + " " + Temp.upper();
+
+2004-06-15 15:02 cgilles
+
+ * cdarchiving/autorun/Makefile.am: Fix 'kipi' installation folder
+ instead 'digikam' CCMAIL: kde-imaging@kde.org
+
+2004-06-15 14:00 cgilles
+
+ * ChangeLog, findimages/plugin_findimages.cpp: Added new plugin
+ category : COLLECTIONSPLUGIN. Changed category plugin for
+ 'DirOperations' and 'FindImages' to COLLECTIONSPLUGIN.
+
+ CCMAIL: kde-imaging@kde.org, digikam-devel@lists.sourceforge.net
+
+2004-06-15 04:57 pahlibar
+
+ * acquireimages/acquireimagedialog.cpp,
+ batchprocessimages/batchprocessimagesdialog.cpp,
+ cdarchiving/cdarchivingdialog.cpp,
+ findimages/finddupplicatedialog.cpp:
+ CCMAIL: kde-imaging@kde.org fix args for file preview job
+
+2004-06-15 04:24 pahlibar
+
+ * findimages/displaycompare.cpp, mpegencoder/kimg2mpg.cpp,
+ rawconverter/batchdialog.cpp, sendimages/sendimagesdialog.cpp:
+ CCMAIL: kde-imaging@kde.org attend to some pending tasks for me
+ by jesper
+
+2004-06-15 00:31 pahlibar
+
+ * configure.in.in:
+ forgot to fix ac_imlib_config to ac_imlib2_config
+
+2004-06-14 22:24 cgilles
+
+ * batchprocessimages/batchprocessimagesdialog.cpp: Fix indentation.
+
+2004-06-14 18:26 pahlibar
+
+ * README, configure.in.bot, configure.in.in, slideshow/Makefile.am,
+ slideshow/imlibiface.cpp, slideshow/imlibiface.h,
+ slideshow/plugin_slideshow.cpp, slideshow/slideshow.cpp,
+ slideshow/slideshow.h, slideshow/slideshowconfig.cpp,
+ slideshow/slideshowgl.cpp:
+ CCMAIL: kde-imaging@kde.org ported the slideshow plugin to use
+ imlib2. (requesting testing). added include mocs
+
+2004-06-14 16:34 cgilles
+
+ * batchprocessimages/batchprocessimagesdialog.cpp: Fixed
+ UploadWidget size !
+
+2004-06-14 10:41 cgilles
+
+ * rawconverter/: hi32-action-rawconverter.png,
+ hi32-action-rawconverterbatch.png,
+ hi32-action-rawconvertersingle.png, plugin_rawconverter.cpp:
+ Added new icons for single and batch RawConverter actions CCMAIL:
+ kde-imaging@kde.org
+
+2004-06-14 10:26 cgilles
+
+ * mpegencoder/plugin_mpegencoder.cpp: MPEGEncoder is now a
+ 'BATCHPLUGIN' category CCMAIL: kde-imaging@kde.org
+
+2004-06-13 22:26 blackie
+
+ * acquireimages/acquireimagedialog.cpp,
+ acquireimages/acquireimagedialog.h,
+ batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/batchprocessimagesdialog.h,
+ calendar/monthwidget.cpp, calendar/monthwidget.h,
+ cdarchiving/cdarchivingdialog.cpp,
+ cdarchiving/cdarchivingdialog.h, findimages/displaycompare.cpp,
+ findimages/displaycompare.h, findimages/finddupplicatedialog.cpp,
+ findimages/finddupplicatedialog.h,
+ imagesgallery/imgallerydialog.cpp,
+ imagesgallery/imgallerydialog.h, mpegencoder/kimg2mpg.cpp,
+ mpegencoder/kimg2mpg.h, rawconverter/batchdialog.cpp,
+ rawconverter/batchdialog.h, sendimages/sendimagesdialog.cpp,
+ sendimages/sendimagesdialog.h: CCMAIL: kde-imaging@kde.org
+ CCMAIL: kimdaba@klaralvdalens-datakonsult.se
+
+ Removed digikam dependencies through the KIPI::ThumbnailJob
+ class. The instances of this class has now been replaced with
+ KIPI::filePreview.
+
+ Renchi: Could you please go through each call in the source, and
+ look at the comment I placed above the call. There were some
+ arguments to ThumbnailJob I did not understand what did, but on
+ the other hand they don't seem to be missed.
+
+ Cheers Jesper.
+
+2004-06-13 17:33 cgilles
+
+ * batchprocessimages/: batchprocessimagesdialog.h,
+ plugin_batchprocessimages.cpp, plugin_batchprocessimages.h:
+ Remove 'Batch Proceses' menu
+
+2004-06-13 16:47 cgilles
+
+ * ChangeLog, calendar/plugin_calendar.cpp, findimages/Makefile.am,
+ findimages/plugin_findimages.cpp, jpeglossless/Makefile.am,
+ jpeglossless/plugin_jpeglossless.cpp, rawconverter/Makefile.am,
+ rawconverter/plugin_rawconverter.cpp, slideshow/Makefile.am,
+ slideshow/plugin_slideshow.cpp: Fix plugins menu icons rendering
+ in the hosts apps.
+
+ CCMAIL: kde-imaging@kde.org, digikam-devel@lists.sourceforge.net
+
+2004-06-13 12:36 faure
+
+ * configure.in.bot, configure.in.in: No idea why AC_MSG_WARN fails
+ for Jesper, but anyway this is better done with a
+ configure.in.bot
+
+2004-06-11 22:56 gateau
+
+ * configure.in.in, jpeglossless/Makefile.am: Better detection of
+ libkexif
+
+2004-06-11 22:56 gateau
+
+ * acquireimages/acquireimagedialog.cpp: Fix KDE3.1 compile
+
+2004-06-11 22:28 mlaurent
+
+ * jpeglossless/transupp.h: Fix --enable-final
+
+2004-06-11 22:25 mlaurent
+
+ * acquireimages/acquireimagedialog.cpp: Fix --enable-final
+
+2004-06-11 20:01 rhoezler
+
+ * jpeglossless/jpegtransform.cpp: Make it compile after libkexif
+ changes.
+
+2004-06-11 18:49 rhoezler
+
+ * AUTHORS, README, TODO: Lots of little documentation updates.
+
+2004-06-11 15:00 cgilles
+
+ * batchprocessimages/plugin_batchprocessimages.cpp: Fix menu name
+
+2004-06-10 15:53 cgilles
+
+ * timeadjust/plugin_timeadjust.cpp: Added menu icon
+
+2004-06-10 14:24 cgilles
+
+ * mpegencoder/kimg2mpg.cpp: Bugfix : unknow slot name specified !
+
+2004-06-10 14:14 brade
+
+ * jpeglossless/Makefile.am: Fix compiling with srcdir != builddir
+ and no preinstalled libkexif.
+
+2004-06-10 12:56 cgilles
+
+ * ChangeLog: Update
+
+2004-06-10 11:17 cgilles
+
+ * batchprocessimages/data/Makefile.am: Fix name
+
+2004-06-10 10:58 cgilles
+
+ * Makefile.am: Remove HelloWorld plugins per default durring
+ build/install process.
+
+2004-06-10 10:52 cgilles
+
+ * Makefile.am: Added GammaCalibration plugin
+
+2004-06-09 02:40 rhoezler
+
+ * jpeglossless/: actions.h, actionthread.cpp, imagerotate.cpp,
+ jpegtransform.cpp, jpegtransform.h, plugin_jpeglossless.cpp: Add
+ new option to JpegLossLess plugin, to rotate according to the
+ EXIF orientation tag. For example, if the image is saved by the
+ camera in landscape and the tag specifies rotating 90 degrees,
+ this function will rotate the image and reset the EXIF
+ orientation to normal, so every EXIF-unaware image viewer shows
+ the image correctly.
+
+ CCMAIL: digikam-devel@lists.sourceforge.net
+
+2004-06-08 23:19 rhoezler
+
+ * jpeglossless/: Makefile.am, actions.h, imageflip.cpp,
+ imagerotate.cpp, jpegtransform.cpp, jpegtransform.h: Improved
+ rotation/flipping based on EXIF orientation tag. The image is now
+ rotated taking the current EXIF orientation into account. For
+ example, if the image is rotated left 90 degrees, but the EXIF
+ tag corrects the rotation, the user will see the thumbnail in the
+ correct position. If the user now requests to rotate 90 degrees
+ to the right, the image will actually be rotated 180 degrees to
+ the right and the EXIF orientation will be reset to normal. This
+ is based on Marcel Wiesweg's matrix transformation patch.
+
+ CCMAIL: digikam-devel@lists.sourceforge.net
+
+2004-06-08 07:52 cgilles
+
+ * batchprocessimages/plugin_batchprocessimages.cpp: Fix category to
+ BATCHPLUGIN
+
+2004-06-07 23:35 rhoezler
+
+ * rawconverter/.cvsignore: Ignore kipidcrawclient
+
+2004-06-07 23:15 rhoezler
+
+ * TODO: Update.
+
+2004-06-07 19:10 rhoezler
+
+ * jpeglossless/: Makefile.am, imageflip.cpp, imagerotate.cpp: - Use
+ libkexif to reset EXIF orientation tag to normal, after rotates
+ and flips
+
+2004-06-07 15:09 cgilles
+
+ * cdarchiving/plugin_cdarchiving.cpp: Fix cdarchiving plugin type
+ like EXPORT plugins
+
+2004-06-06 21:09 blackie
+
+ * timeadjust/kipiplugin_timeadjust.desktop: ups a bit too much
+ cut'n'paste
+
+2004-06-06 19:24 gateau
+
+ * wallpaper/plugin_wallpaper.cpp: Typo
+
+2004-06-06 19:21 gateau
+
+ * wallpaper/plugin_wallpaper.cpp: KURL support.
+
+2004-06-05 21:16 mlaurent
+
+ * findimages/: finddupplicatedialog.cpp, finddupplicateimages.cpp,
+ plugin_findimages.cpp: Includemoc
+
+2004-06-04 00:09 blackie
+
+ * batchprocessimages/plugin_batchprocessimages.cpp,
+ jpeglossless/plugin_jpeglossless.cpp,
+ mpegencoder/plugin_mpegencoder.cpp,
+ printwizard/plugin_printwizard.cpp,
+ printwizard/plugin_printwizard.h,
+ rawconverter/plugin_rawconverter.cpp,
+ rawconverter/plugin_rawconverter.h,
+ sendimages/plugin_sendimages.cpp, slideshow/plugin_slideshow.cpp,
+ timeadjust/plugin_timeadjust.cpp, wallpaper/plugin_wallpaper.cpp:
+ CCMAIL: kde-imaging@kde.org
+
+ - I realized that most of the plugins had code looking like this:
+ ImageCollection images = interface->currentSelection();
+ if ( !images.isValid() ) images =
+ interface->currentAlbum(); I therefore added a function called
+ currentScope(), which does exactly this. Its implementation is
+ as simple as KIPI::ImageCollection
+ KIPI::Interface::currentScope() { ImageCollection
+ images = currentSelection(); if ( images.isValid() )
+ return images; else return currentAlbum();
+ }
+
+ - Added signals to KIPI::Interface. The host application may now
+ emit one of void selectionChanged( bool hasSelection );
+ void currentAlbumChanged( bool anyAlbum ); in addition the
+ interface will itself emit void currentScopeChanged( bool
+ asScope ); when one of the others are emitted.
+
+ - Added all the, till now, commented out lines for
+ enabling/disabling actions based on selection/album
+
+2004-06-02 15:13 gateau
+
+ * findimages/finddupplicateimages.h: Do not declare methods as
+ inline if they are not.
+
+2004-06-02 15:07 gateau
+
+ * rawconverter/Makefile.am: Do not link to digikam
+
+2004-06-02 00:16 blackie
+
+ * Makefile.am, findimages/displaycompare.cpp,
+ findimages/displaycompare.h, findimages/finddupplicatedialog.cpp,
+ findimages/finddupplicatedialog.h,
+ findimages/finddupplicateimages.cpp,
+ findimages/finddupplicateimages.h,
+ findimages/plugin_findimages.cpp: almost done porting findimages
+ plugin
+
+2004-05-31 23:53 mlaurent
+
+ * helloworld/plugin_helloworld.cpp: includemoc
+
+2004-05-31 22:55 blackie
+
+ * Makefile.am, rawconverter/batchdialog.cpp,
+ rawconverter/batchdialog.h, rawconverter/plugin_rawconverter.cpp,
+ rawconverter/plugin_rawconverter.h: ported plugin
+
+2004-05-31 22:30 blackie
+
+ * acquireimages/plugin_acquireimages.cpp,
+ acquireimages/plugin_acquireimages.h,
+ batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/plugin_batchprocessimages.cpp,
+ batchprocessimages/plugin_batchprocessimages.h,
+ calendar/plugin_calendar.cpp, calendar/plugin_calendar.h,
+ cdarchiving/plugin_cdarchiving.cpp,
+ cdarchiving/plugin_cdarchiving.h,
+ findimages/plugin_findimages.cpp, findimages/plugin_findimages.h,
+ helloworld/plugin_helloworld.cpp, helloworld/plugin_helloworld.h,
+ imagesgallery/plugin_imagesgallery.cpp,
+ imagesgallery/plugin_imagesgallery.h,
+ jpeglossless/plugin_jpeglossless.cpp,
+ jpeglossless/plugin_jpeglossless.h,
+ mpegencoder/plugin_mpegencoder.cpp,
+ mpegencoder/plugin_mpegencoder.h,
+ printwizard/plugin_printwizard.cpp,
+ printwizard/plugin_printwizard.h,
+ rawconverter/plugin_rawconverter.cpp,
+ rawconverter/plugin_rawconverter.h,
+ sendimages/plugin_sendimages.cpp, sendimages/plugin_sendimages.h,
+ slideshow/plugin_slideshow.cpp, slideshow/plugin_slideshow.h,
+ timeadjust/plugin_timeadjust.cpp, timeadjust/plugin_timeadjust.h,
+ wallpaper/plugin_wallpaper.cpp, wallpaper/plugin_wallpaper.h:
+ CC-MAIL:kde-imaging@kde.org
+
+ As an action may be located in several windows (e.g. in several
+ image viewers), the actions are now setup in a setup() method
+ which as argument take a widget which is the widget the
+ accelerators of the actionCollection should work on.
+
+ actionCollection() is now again public, so it is possible to
+ configure keybindings.
+
+ Host application must now call Plugin::setup( QWidget* ) after
+ having loaded the plugins.
+
+2004-05-31 21:11 blackie
+
+ * Makefile.am: *really* minor API changes, plus documentation
+
+2004-05-31 19:27 blackie
+
+ * Makefile.am, helloworld/plugin_helloworld.cpp,
+ slideshow/plugin_slideshow.cpp, slideshow/slideshowconfig.cpp:
+ ported the slideshow plugin. It does, however, complain that I
+ have not openGL compiled into Qt, and it does crash my X server
+ if I start the plugin with OpenGL support
+
+2004-05-31 16:13 blackie
+
+ * Makefile.am, batchprocessimages/plugin_batchprocessimages.cpp,
+ helloworld/plugin_helloworld.cpp,
+ jpeglossless/plugin_jpeglossless.cpp,
+ mpegencoder/plugin_mpegencoder.cpp,
+ printwizard/plugin_printwizard.cpp,
+ sendimages/plugin_sendimages.cpp,
+ timeadjust/plugin_timeadjust.cpp, wallpaper/plugin_wallpaper.cpp:
+ CCMAIL: kde-imaging@kde.org
+
+ Readded the hello world plugin. Host apps, which do not want to
+ see it, should simply ignore by adding it to the list given as
+ first argument to PluginLoader.
+
+ Added ImageCollection::isValid(). I realized that there was no
+ way for applications like digikam to indicate that there were no
+ album selected. So to indicate that an image collection is
+ invalid, the host application should give 0 for
+ ImageCollectionShared pointer on construction of ImageCollection.
+ This will make ImageCollection::isValid() return false. Plugins
+ should now test for isValid() before using data from image
+ collection.
+
+2004-05-31 14:11 blackie
+
+ * batchprocessimages/: batchprocessimagesdialog.h,
+ renameimagesdialog.cpp: completed plugin
+
+2004-05-28 20:10 blackie
+
+ * acquireimages/plugin_acquireimages.cpp,
+ batchprocessimages/Makefile.am,
+ batchprocessimages/plugin_batchprocessimages.cpp,
+ calendar/plugin_calendar.cpp, cdarchiving/plugin_cdarchiving.cpp,
+ findimages/plugin_findimages.cpp,
+ helloworld/plugin_helloworld.cpp,
+ imagesgallery/plugin_imagesgallery.cpp,
+ jpeglossless/plugin_jpeglossless.cpp,
+ mpegencoder/plugin_mpegencoder.cpp,
+ printwizard/plugin_printwizard.cpp,
+ rawconverter/plugin_rawconverter.cpp,
+ sendimages/plugin_sendimages.cpp, slideshow/plugin_slideshow.cpp,
+ timeadjust/plugin_timeadjust.cpp, wallpaper/plugin_wallpaper.cpp:
+ CCMAIL: kde-imaging@kde.org, dfaure@kde.org
+
+ Together with David Faure I did yesterday make the necessary
+ changes to allow icons local to each plugin.
+
+ The basic point of all this was that the
+ KIPI::Plugin::actionCollection() needed to know about the plugins
+ KInstance - as it was till this change, it got the KInstance for
+ the host application, and would thus look for icons in the host
+ applications directory.
+
+ Making this change did, however, reveal a conflict, namely that
+ each and every action in the plugin must have the
+ actionCollection as parent - which was not the case for items in
+ KMenuActions.
+
+ The way the host application finds actions right now is by
+ querying the actionCollection(), which with the above change
+ would also reveal those actions from menus.
+
+ I therefore needed to add another way for the host application to
+ get information about actions. I added a method called
+ KIPI::Plugin::actions() which the host application must call to
+ get information about actions. At the same time I made the
+ actionCollection() method protected, so the host application
+ can't get to that anymore.
+
+ To tell KIPI about actions, then plugins must now call
+ KIPI::Plugin::addAction() on each action they want to be in the
+ topmost menu (thus not actions located in KActionMenu's).
+
+ Let me summerize the changes - Host application now need to call
+ actions() rather than actionCollection() to get information
+ about action in the plugin. - plugins now need to give a pointer
+ to KGenericFactory<..>::instance() in the constructor of the
+ Plugin superclass. - the plugin must call addAction() for each
+ toplevel action.
+
+ And now to answer the question on how to get local icons. In
+ Makefile.am, you need a line similar to this:
+ kipibatchprocessimagesicondir =
+ $(kde_datadir)/kipiplugin_batchprocessimages/icons
+
+ The name specified above (the "kipiplugin_batchprocessimages"),
+ must be the same as what you specify to KGenericFactory in the
+ plugin:
+
+ typedef KGenericFactory<Plugin_BatchProcessImages> Factory;
+ K_EXPORT_COMPONENT_FACTORY( kipiplugin_batchprocessimages,
+ Factory("kipiplugin_batchprocessimages"));
+
+ Cheers Jesper
+
+2004-05-27 11:39 blackie
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ batchprocessimagesdialog.h, batchprocessimagesitem.cpp,
+ batchprocessimagesitem.h, batchprocessimageslist.cpp,
+ borderimagesdialog.cpp, colorimagesdialog.cpp,
+ convertimagesdialog.cpp, effectimagesdialog.cpp,
+ filterimagesdialog.cpp, recompressimagesdialog.cpp,
+ renameimagesdialog.cpp, resizeimagesdialog.cpp, data/Makefile.am:
+ more steps towards a working plugin. Everything should work now
+ except batch rename
+
+2004-05-27 01:08 gateau
+
+ * acquireimages/: acquireimagedialog.cpp, acquireimagedialog.h:
+ Implemented network transparency.
+
+2004-05-25 23:43 blackie
+
+ * acquireimages/: acquireimagedialog.cpp, acquireimagedialog.h:
+ completed the acquire plugin except some URL uncleanlyness.
+
+2004-05-25 09:12 blackie
+
+ * findimages/displaycompare.cpp, findimages/displaycompare.h,
+ findimages/finddupplicatedialog.h,
+ findimages/finddupplicateimages.cpp,
+ helloworld/plugin_helloworld.cpp,
+ imagesgallery/imgallerydialog.cpp, rawconverter/batchdialog.cpp,
+ rawconverter/plugin_rawconverter.cpp,
+ rawconverter/plugin_rawconverter.h,
+ slideshow/plugin_slideshow.cpp: removed the last few includes of
+ digikam header files
+
+2004-05-24 00:28 blackie
+
+ * acquireimages/: acquireimagedialog.cpp, acquireimagedialog.h:
+ more work on the acquire plugin.
+
+2004-05-23 23:47 gateau
+
+ * acquireimages/acquireimagedialog.cpp: AlbumsHaveDescriptions ->
+ AlbumsHaveComments
+
+2004-05-23 23:14 blackie
+
+ * acquireimages/: acquireimagedialog.cpp, acquireimagedialog.h,
+ plugin_acquireimages.cpp, screenshotdialog.cpp,
+ screenshotdialog.h: CCMAIL: kde-imaging@kde.org
+
+ Next try at solving the issue with uploading images. I've now
+ created a new widget (UploadWidget), which can be used to ask for
+ a directory to upload to (upload say a scan image from
+ acquireimage plugin, or a new image converted in batchprocessing
+ plugin).
+
+ The upload widget is a directory browser knowing about KURL's.
+ To let the browser start somewhere, I've added a new method
+ ImageCollection::uploadRoot.
+
+ This isn't 100% complete yet, but I want to show it to Aurelien
+ ;-)
+
+ The acquireimage plugin has been changed to used this new class.
+
+ I'd esp. like to get some input from the digikam team, as this
+ "breaks" their work with albums, but on the other hand when they
+ change to recursive albums, the current scheme will not work
+ anyway.
+
+ Cheers Jesper.
+
+2004-05-23 15:18 cgilles
+
+ * TODO: Update
+
+2004-05-20 23:49 mlaurent
+
+ * wallpaper/plugin_wallpaper.cpp: In this module, nobody want to
+ "includemoc"... I don't understand...
+
+2004-05-20 23:40 blackie
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ batchprocessimagesdialog.h, borderimagesdialog.cpp,
+ borderimagesdialog.h, colorimagesdialog.cpp, colorimagesdialog.h,
+ convertimagesdialog.cpp, convertimagesdialog.h,
+ effectimagesdialog.cpp, effectimagesdialog.h,
+ filterimagesdialog.cpp, filterimagesdialog.h,
+ recompressimagesdialog.cpp, recompressimagesdialog.h,
+ resizeimagesdialog.cpp, resizeimagesdialog.h: a bit more porting
+ done
+
+2004-05-20 22:29 blackie
+
+ * imagesgallery/imagesgallery.cpp: index file was not correctly
+ generated
+
+2004-05-20 16:53 blackie
+
+ * Makefile.am, wallpaper/.cvsignore, wallpaper/Makefile.am,
+ wallpaper/kipiplugin_wallpaper.desktop,
+ wallpaper/plugin_wallpaper.cpp, wallpaper/plugin_wallpaper.h:
+ ported miscoperations - split it into wallpaper and
+ diroperations, as they have diffferent requirements from host
+ operations
+
+2004-05-20 14:32 mlaurent
+
+ * timeadjust/: plugin_timeadjust.cpp, timeadjustdialog.cpp:
+ includemoc
+
+2004-05-20 12:57 blackie
+
+ * Makefile.am, timeadjust/.cvsignore, timeadjust/Makefile.am,
+ timeadjust/kipiplugin_timeadjust.desktop,
+ timeadjust/plugin_timeadjust.cpp, timeadjust/plugin_timeadjust.h,
+ timeadjust/timeadjustdialog.cpp, timeadjust/timeadjustdialog.h:
+ CCMAIL: kde-imaging@kde.org I forgot to change the clock on my
+ digital camera to summer time, so I had a bunch of images with
+ wrong time info... So I did of course develop a KIPI plugin to
+ fix this ;-)
+
+ So now we have the first KIPI-only plugin, lets celebrate and get
+ the rest of KIPI in shape soon.
+
+ Cheers Jesper
+
+2004-05-13 16:02 gateau
+
+ * Makefile.am, configure.in.in, acquireimages/Makefile.am,
+ batchprocessimages/Makefile.am, calendar/Makefile.am,
+ cdarchiving/Makefile.am, findimages/Makefile.am,
+ helloworld/Makefile.am, imagesgallery/Makefile.am,
+ jpeglossless/Makefile.am, mpegencoder/Makefile.am,
+ printwizard/Makefile.am, rawconverter/Makefile.am,
+ sendimages/Makefile.am, slideshow/Makefile.am: Changed the way
+ KIPI libs and includes are detected so that the whole
+ kdeextragear-libs-1 can be build without having to install
+ libkipi first. Thanks to David Faure for his amazing autotool
+ skills :-) CCMAIL: kde-imaging@kde.org
+
+ Don't prevent the build if imlib is not found, just disable
+ compilation of the slideshow plugin.
+
+2004-05-13 13:49 vkrause
+
+ * configure.in.in: Fix quoting.
+
+2004-05-13 12:27 mlaurent
+
+ * rawconverter/: Makefile.am, batchdialog.cpp, dmessagebox.cpp,
+ plugin_rawconverter.cpp, plugin_rawconverter.h,
+ previewwidget.cpp, processcontroller.cpp, singledialog.cpp:
+ Includemoc fix compile
+
+2004-05-13 06:56 cgilles
+
+ * rawconverter/: kipidcrawclient.man.gz,
+ kipiplugin_rawconverter.desktop: Fix
+
+2004-05-13 06:54 cgilles
+
+ * rawconverter/: Makefile.am, digikamdcrawclient.man.gz,
+ digikamplugin_rawconverter.desktop, plugin_rawconverter.cpp,
+ processcontroller.cpp: Fix Digikam name to Kipi
+
+2004-05-13 06:45 cgilles
+
+ * rawconverter/Makefile.am: Fix MakeFiles.am for a good i18n export
+
+2004-05-12 12:56 mlaurent
+
+ * batchprocessimages/: batchprocessimagesdialog.cpp,
+ batchprocessimageslist.cpp, batchprocessimageslist.h,
+ borderimagesdialog.cpp, borderoptionsdialog.cpp,
+ colorimagesdialog.cpp, coloroptionsdialog.cpp,
+ convertimagesdialog.cpp, convertoptionsdialog.cpp,
+ effectimagesdialog.cpp, effectoptionsdialog.cpp,
+ filterimagesdialog.cpp, filteroptionsdialog.cpp,
+ imagepreview.cpp, outputdialog.cpp,
+ plugin_batchprocessimages.cpp, recompressimagesdialog.cpp,
+ recompressoptionsdialog.cpp, renameimagesdialog.cpp,
+ renameimagesoptionsdialog.cpp, resizeimagesdialog.cpp,
+ resizeoptionsdialog.cpp: Includemoc.... Includemoc....
+ Includemoc....
+
+ .....
+
+2004-05-12 10:14 blackie
+
+ * Makefile.am, batchprocessimages/Makefile.am,
+ batchprocessimages/batchprocessimagesdialog.cpp,
+ batchprocessimages/batchprocessimagesdialog.h,
+ batchprocessimages/borderimagesdialog.cpp,
+ batchprocessimages/borderimagesdialog.h,
+ batchprocessimages/colorimagesdialog.cpp,
+ batchprocessimages/colorimagesdialog.h,
+ batchprocessimages/convertimagesdialog.cpp,
+ batchprocessimages/convertimagesdialog.h,
+ batchprocessimages/digikamplugin_batchprocessimages.desktop,
+ batchprocessimages/digikamplugin_batchprocessimages.rc,
+ batchprocessimages/effectimagesdialog.cpp,
+ batchprocessimages/effectimagesdialog.h,
+ batchprocessimages/filterimagesdialog.cpp,
+ batchprocessimages/filterimagesdialog.h,
+ batchprocessimages/kipiplugin_batchprocessimages.desktop,
+ batchprocessimages/plugin_batchprocessimages.cpp,
+ batchprocessimages/plugin_batchprocessimages.h,
+ batchprocessimages/recompressimagesdialog.cpp,
+ batchprocessimages/recompressimagesdialog.h,
+ batchprocessimages/renameimagesdialog.cpp,
+ batchprocessimages/renameimagesdialog.h,
+ batchprocessimages/resizeimagesdialog.cpp,
+ batchprocessimages/resizeimagesdialog.h,
+ batchprocessimages/data/Makefile.am: CCMAIL: kde-imaging@kde.org
+ Implemented the KIPI::Features so plugins can query the features
+ of the host application. Also added a desktop entry called
+ X-KIPI-ReqFeatures, so plugins will not be loaded at all if a
+ hostapplication does not honor all those features.
+
+ Also started porting the batchprocessimages, and ones again the
+ problem is the destination directory.
+
+2004-05-10 15:25 cgilles
+
+ * NEWS, README, TODO: Sync with Digikamplugins SF.net CVS module
+
+2004-05-10 15:17 cgilles
+
+ * slideshow/: Makefile.am, slideshow.cpp, slideshow.h,
+ slideshowgl.cpp, slideshowgl.h: Added openGL depency. Patch for
+ mouse navigation. Sync from Digikamplugins SF.net CVS module.
+
+2004-05-10 15:15 cgilles
+
+ * configure.in.in: Added patch for OpenGL detection in according
+ with Digikamplugins SF.net CVS module. Added Imlib1 depency.
+
+2004-05-10 10:12 mlaurent
+
+ * acquireimages/acquireimagedialog.cpp,
+ acquireimages/plugin_acquireimages.cpp,
+ acquireimages/screenshotdialog.cpp, calendar/calpainter.cpp,
+ calendar/calselect.cpp, calendar/caltemplate.cpp,
+ calendar/calwizard.cpp, calendar/monthwidget.cpp,
+ calendar/plugin_calendar.cpp, cdarchiving/cdarchivingdialog.cpp,
+ cdarchiving/plugin_cdarchiving.cpp,
+ imagesgallery/listimageserrordialog.cpp,
+ imagesgallery/plugin_imagesgallery.cpp,
+ jpeglossless/messagebox.cpp,
+ jpeglossless/plugin_jpeglossless.cpp,
+ jpeglossless/progressdlg.cpp, mpegencoder/checkbinprog.cpp,
+ mpegencoder/optionsdialog.cpp,
+ mpegencoder/plugin_mpegencoder.cpp, printwizard/cropframe.cpp,
+ printwizard/frmprintwizard.cpp,
+ printwizard/plugin_printwizard.cpp,
+ sendimages/listimageserrordialog.cpp,
+ sendimages/plugin_sendimages.cpp,
+ sendimages/sendimagesdialog.cpp: Includemoc includemoc... I hope
+ that people will understand that it's important to include moc...
+
+2004-05-09 17:42 gateau
+
+ * AUTHORS, COPYING, ChangeLog, INSTALL, NEWS, README,
+ configure.in.in: Added files necessary to create a tarball.
+
+2004-05-09 17:42 gateau
+
+ * acquireimages/Makefile.am, calendar/Makefile.am,
+ cdarchiving/Makefile.am, findimages/Makefile.am,
+ helloworld/Makefile.am, imagesgallery/Makefile.am,
+ jpeglossless/Makefile.am, mpegencoder/Makefile.am,
+ printwizard/Makefile.am, rawconverter/Makefile.am,
+ sendimages/Makefile.am, slideshow/Makefile.am: Use the dynamic
+ version of kipi. This is necessary to be able to release
+ kipi-plugins as a separate tarball from libkipi. Unfortunately
+ this means you need to "make install" libkipi to build the
+ plugins. CCMAIL:kde-imaging@kde.org
+
+2004-05-09 17:36 gateau
+
+ * printwizard/.cvsignore: Added frmprintwizardbase
+
+2004-05-08 11:19 blackie
+
+ * calendar/: calpainter.cpp, calpainter.h, calsettings.cpp,
+ calsettings.h, calwizard.cpp, calwizard.h, monthwidget.cpp,
+ monthwidget.h: handle images which are rotated in the host
+ application. This included that I had to make the application
+ much more KURL clean.
+
+2004-05-07 19:22 blackie
+
+ * Makefile.am, acquireimages/acquireimagedialog.cpp,
+ acquireimages/plugin_acquireimages.cpp,
+ batchprocessimages/plugin_batchprocessimages.cpp,
+ cdarchiving/cdarchiving.cpp, cdarchiving/cdarchivingdialog.cpp,
+ cdarchiving/plugin_cdarchiving.cpp,
+ findimages/finddupplicateimages.cpp,
+ findimages/plugin_findimages.cpp,
+ helloworld/plugin_helloworld.cpp,
+ imagesgallery/imagesgallery.cpp,
+ imagesgallery/plugin_imagesgallery.cpp,
+ imagesgallery/resizeimage.cpp, jpeglossless/actions.h,
+ jpeglossless/actionthread.cpp, jpeglossless/actionthread.h,
+ jpeglossless/plugin_jpeglossless.cpp,
+ jpeglossless/plugin_jpeglossless.h, jpeglossless/utils.cpp,
+ mpegencoder/plugin_mpegencoder.cpp,
+ printwizard/frmprintwizard.cpp,
+ printwizard/plugin_printwizard.cpp,
+ sendimages/plugin_sendimages.cpp, slideshow/plugin_slideshow.cpp,
+ slideshow/slideshowgl.cpp: CCMAIL: kde-imaging@kde.org
+ Implemented jpeglossless.
+
+ The following changes where made to the KIPI interface: - We now
+ have two debug areas 51000 (general) and 51001 (loading
+ information). Thus debug output should now be done as: kdDebug(
+ 51000 ) << ...
+
+ - new virtual function: KIPI::Interface::refreshImages( const
+ KURL::List& ); This function should be called from plugins when
+ images has changed on disk
+
+ - New virtual functions in interface: KIPI::ImageInfo::angle()
+ and KIPI::ImageInfo::setAngle() When the host application
+ displays an image rotated, after having being loaded from disk,
+ the angle() method should return the angle.
+
+2004-05-07 12:22 cgilles
+
+ * slideshow/: slideshow.cpp, slideshowgl.cpp: Bugfix in according
+ with Digikamplugins SF.net repository
+
+2004-05-07 11:59 blackie
+
+ * Makefile.am, acquireimages/acquireimagedialog.cpp,
+ acquireimages/acquireimagedialog.h: some porting of the
+ acquireimage plugin - still not complete
+
+2004-05-07 11:56 cgilles
+
+ * batchprocessimages/resizeimagesdialog.cpp: Bufix in 'Proportional
+ (2 dim.) option in according with DigikamPlugins SF.net
+ repository
+
+2004-05-06 12:18 gateau
+
+ * mpegencoder/kimg2mpg.cpp: Do not add the final '/', it seems to
+ confuse images2mpg
+
+2004-05-05 23:45 blackie
+
+ * mpegencoder/kimg2mpg.cpp: strip file: of before calling encoder,
+ someone please check if this now works I dont seem to have right
+ tools installed. Cheers Jesper CCMAIL: kde-imaging@kde.org
+
+2004-05-05 23:23 blackie
+
+ * acquireimages/: acquireimagedialog.cpp, plugin_acquireimages.cpp,
+ plugin_acquireimages.h: a bit more work on porting, we still have
+ some details to discuss here
+
+2004-05-04 13:36 blackie
+
+ * batchprocessimages/: .cvsignore, Makefile.am,
+ batchprocessimagesdialog.cpp, batchprocessimagesdialog.h,
+ batchprocessimagesitem.cpp, batchprocessimagesitem.h,
+ batchprocessimageslist.cpp, batchprocessimageslist.h,
+ borderimagesdialog.cpp, borderimagesdialog.h,
+ borderoptionsdialog.cpp, borderoptionsdialog.h,
+ colorimagesdialog.cpp, colorimagesdialog.h,
+ coloroptionsdialog.cpp, coloroptionsdialog.h,
+ convertimagesdialog.cpp, convertimagesdialog.h,
+ convertoptionsdialog.cpp, convertoptionsdialog.h,
+ digikamplugin_batchprocessimages.desktop,
+ digikamplugin_batchprocessimages.rc, effectimagesdialog.cpp,
+ effectimagesdialog.h, effectoptionsdialog.cpp,
+ effectoptionsdialog.h, filterimagesdialog.cpp,
+ filterimagesdialog.h, filteroptionsdialog.cpp,
+ filteroptionsdialog.h, hi32-action-borderimages.png,
+ hi32-action-colorimages.png, hi32-action-convertimages.png,
+ hi32-action-effectimages.png, hi32-action-filterimages.png,
+ hi32-action-recompressimages.png, hi32-action-renameimages.png,
+ hi32-action-resizeimages.png, imagepreview.cpp, imagepreview.h,
+ outputdialog.cpp, outputdialog.h, plugin_batchprocessimages.cpp,
+ plugin_batchprocessimages.h, recompressimagesdialog.cpp,
+ recompressimagesdialog.h, recompressoptionsdialog.cpp,
+ recompressoptionsdialog.h, renameimagesdialog.cpp,
+ renameimagesdialog.h, renameimagesoptionsdialog.cpp,
+ renameimagesoptionsdialog.h, resizeimagesdialog.cpp,
+ resizeimagesdialog.h, resizeoptionsdialog.cpp,
+ resizeoptionsdialog.h, data/.cvsignore, data/Makefile.am,
+ data/handcursor.png: added new files from Gilles
+
+2004-05-03 15:43 cgilles
+
+ * mpegencoder/kimg2mpg.cpp: Fix
+
+2004-05-03 15:39 cgilles
+
+ * cdarchiving/cdarchivingdialog.cpp,
+ findimages/finddupplicatedialog.cpp,
+ findimages/plugin_findimages.cpp, findimages/plugin_findimages.h,
+ imagesgallery/imgallerydialog.cpp: Fix frame border in preview
+ image in according with Digikamplugins SF.net module
+
+2004-05-03 15:32 cgilles
+
+ * mpegencoder/kimg2mpg.cpp: Fix frame style in according with
+ Digikamplugins SF.net module
+
+2004-05-03 15:30 cgilles
+
+ * sendimages/sendimagesdialog.cpp: In according with Digikamplugins
+ SF.net CVS module : Fix frame border Fix plurial i18n form.
+
+2004-05-03 00:36 adridg
+
+ * cdarchiving/cdarchiving.h: Needed for pid_t
+
+2004-05-02 23:04 gateau
+
+ * calendar/monthwidget.cpp: Make use of KIPI::ImageCollectionDialog
+ CCMAIL: kde-imaging@kde.org
+
+2004-05-02 22:56 blackie
+
+ * sendimages/: Makefile.am, digikamplugin_sendimages.desktop,
+ digikamplugin_sendimages.rc, kipiplugin_sendimages.desktop,
+ plugin_sendimages.cpp, plugin_sendimages.h, sendimagesdialog.cpp,
+ sendimagesdialog.h: CCMAIL: kde-imaging@kde.org Done porting
+ sendimages plugin.
+
+2004-05-02 16:08 blackie
+
+ * Makefile.am, acquireimages/plugin_acquireimages.h,
+ calendar/plugin_calendar.h, cdarchiving/plugin_cdarchiving.h,
+ findimages/plugin_findimages.h, helloworld/plugin_helloworld.h,
+ imagesgallery/plugin_imagesgallery.h,
+ jpeglossless/plugin_jpeglossless.h,
+ mpegencoder/plugin_mpegencoder.h,
+ printwizard/plugin_printwizard.h,
+ rawconverter/plugin_rawconverter.h, slideshow/plugin_slideshow.h:
+ CCMAIL: kde-imaging@kde.org
+
+ If you implement application for loading KIPI plugins, then
+ please read carefully, there are a number of changes that you
+ need to make to your application.
+
+ For this check in I implemented the comments editor. This
+ resulted in a number of changes to other parts:
+
+ First, KimDaBa should not show this plugin, as it has better way
+ built in for setting comments - likewise other tools may not want
+ to show it because they might not have any way to support
+ comments for images.
+
+ Therefore KIPI::PluginLoader::PluginLoader does now as first
+ argument take a QStringList of plugins not to load - the strings
+ written there should be the Name attribute of the desktop file
+ for the given plugin.
+
+ Later today or tomorrow I anticipate to change the plugin loader
+ class even more - currently it has these instance variables with
+ accessor methods for them: List m_pluginList;
+ QStringList m_pluginNames; QStringList m_libraryNames;
+
+ I need to add some extra information for each plugin, so I'd
+ rather have all the information in a class like:
+
+ class PluginInfo { QString name; QString comment; QString
+ path; KIPI::Plugin* plugin; // etc } This will result in just
+ one list of PluginInfo's that the host apps will be able to get
+ to, rather than a number of accessor methods as it is now.
+
+ Let me know if you have any objections.
+
+ Once I've fixed the above I'll make sure that the name is set
+ during loading, so that we do not have to specify the name twice
+ - which is why the KIPI::Plugin::id() was removed again (I added
+ it a week ago)
+
+ Finally, the comments editor plugin needed to set the
+ description, which is why the ImageInfoShared classes that host
+ apps implements has been changed to include a setComment(),
+ setName(), clearAttributes() and addAttributes() methods.
+
+ Cheers Jesper
+
+2004-04-30 09:57 cgilles
+
+ * sendimages/sendimagesdialog.cpp: Fix i18n messages in according
+ with SF.net Digikam CVS
+
+2004-04-29 15:50 blackie
+
+ * sendimages/: .cvsignore, Makefile.am,
+ digikamplugin_sendimages.desktop, digikamplugin_sendimages.rc,
+ listimageserrordialog.cpp, listimageserrordialog.h,
+ plugin_sendimages.cpp, plugin_sendimages.h, sendimagesdialog.cpp,
+ sendimagesdialog.h: unported plugins added
+
+2004-04-26 10:31 gateau
+
+ * imagesgallery/: imagesgallery.cpp, imagesgallery.h: Make it build
+ on KDE 3.1
+
+2004-04-26 10:21 gateau
+
+ * calendar/calselect.cpp, cdarchiving/plugin_cdarchiving.cpp:
+ Removed Digikam include
+
+2004-04-26 00:51 gateau
+
+ * Makefile.am, imagesgallery/Makefile.am,
+ imagesgallery/imagesgallery.cpp, imagesgallery/imagesgallery.h,
+ imagesgallery/imgallerydialog.cpp,
+ imagesgallery/imgallerydialog.h,
+ imagesgallery/plugin_imagesgallery.cpp,
+ imagesgallery/plugin_imagesgallery.h: Here is a rough port of the
+ Digikam Image Gallery plugin.
+
+2004-04-25 22:23 blackie
+
+ * Makefile.am, printwizard/plugin_printwizard.cpp: more porting
+ plus removed KIPI::Interface::currentView(), it was suggested by
+ me, but I dont use it myself, so lets throw it out
+
+2004-04-25 20:19 gateau
+
+ * calendar/monthwidget.cpp, cdarchiving/cdarchiving.cpp,
+ cdarchiving/cdarchivingdialog.cpp,
+ helloworld/plugin_helloworld.cpp: No more 'root()' method
+
+2004-04-25 20:13 blackie
+
+ * acquireimages/plugin_acquireimages.cpp,
+ calendar/plugin_calendar.cpp, mpegencoder/plugin_mpegencoder.cpp,
+ rawconverter/plugin_rawconverter.cpp,
+ rawconverter/plugin_rawconverter.h,
+ slideshow/plugin_slideshow.cpp: tried to categories the plugins,
+ but that needs more work
+
+2004-04-25 17:58 blackie
+
+ * acquireimages/plugin_acquireimages.h, calendar/plugin_calendar.h,
+ cdarchiving/plugin_cdarchiving.h, findimages/plugin_findimages.h,
+ helloworld/plugin_helloworld.h,
+ imagesgallery/plugin_imagesgallery.h,
+ jpeglossless/plugin_jpeglossless.h,
+ mpegencoder/plugin_mpegencoder.h,
+ printwizard/plugin_printwizard.h,
+ rawconverter/plugin_rawconverter.h, slideshow/plugin_slideshow.h:
+ added an id() to the plugin class, so it is possible to write
+ code in the host apps for handling certain plugins special. I'd
+ for example like to put the print plugin in teh file menu
+
+2004-04-25 17:41 blackie
+
+ * calendar/monthwidget.cpp, cdarchiving/cdarchiving.cpp,
+ cdarchiving/cdarchivingdialog.cpp,
+ cdarchiving/cdarchivingdialog.h,
+ helloworld/plugin_helloworld.cpp,
+ mpegencoder/plugin_mpegencoder.cpp,
+ printwizard/plugin_printwizard.cpp: added reference counting to
+ ImageCollection
+
+2004-04-25 16:42 blackie
+
+ * cdarchiving/cdarchivingdialog.cpp: added reference counting to
+ ImageInfo
+
+2004-04-25 15:26 blackie
+
+ * acquireimages/Makefile.am, calendar/Makefile.am,
+ cdarchiving/Makefile.am, findimages/Makefile.am,
+ helloworld/Makefile.am, imagesgallery/Makefile.am,
+ jpeglossless/Makefile.am, mpegencoder/Makefile.am,
+ printwizard/Makefile.am, rawconverter/Makefile.am: made it all
+ compile without a make install inbetween
+
+2004-04-25 15:15 gateau
+
+ * .cvsignore, acquireimages/.cvsignore, calendar/.cvsignore,
+ cdarchiving/autorun/.cvsignore, findimages/.cvsignore,
+ helloworld/.cvsignore, jpeglossless/.cvsignore,
+ mpegencoder/.cvsignore, printwizard/.cvsignore,
+ rawconverter/.cvsignore, slideshow/.cvsignore: Added Makefile to
+ .cvsignore where it was missing
+
+2004-04-24 20:20 blackie
+
+ * Makefile.am, acquireimages/.cvsignore, acquireimages/Makefile.am,
+ acquireimages/acquireimagedialog.cpp,
+ acquireimages/acquireimagedialog.h,
+ acquireimages/kipiplugin_acquireimages.desktop,
+ acquireimages/plugin_acquireimages.cpp,
+ acquireimages/plugin_acquireimages.h,
+ acquireimages/screenshotdialog.cpp,
+ acquireimages/screenshotdialog.h, calendar/plugin_calendar.cpp,
+ calendar/plugin_calendar.h, cdarchiving/.cvsignore,
+ cdarchiving/Makefile.am, cdarchiving/cdarchiving.cpp,
+ cdarchiving/cdarchiving.h, cdarchiving/cdarchivingdialog.cpp,
+ cdarchiving/cdarchivingdialog.h, cdarchiving/image_broken.png,
+ cdarchiving/kipiplugin_cdarchiving.desktop,
+ cdarchiving/plugin_cdarchiving.cpp,
+ cdarchiving/plugin_cdarchiving.h, cdarchiving/autorun/.cvsignore,
+ cdarchiving/autorun/Makefile.am,
+ cdarchiving/autorun/ShellExecute.bat,
+ cdarchiving/autorun/cdalbums.ico, cdarchiving/autorun/index.htm,
+ findimages/.cvsignore, findimages/Makefile.am,
+ findimages/actions.h, findimages/displaycompare.cpp,
+ findimages/displaycompare.h, findimages/finddupplicatedialog.cpp,
+ findimages/finddupplicatedialog.h,
+ findimages/finddupplicateimages.cpp,
+ findimages/finddupplicateimages.h,
+ findimages/hi32-action-findcomments.png,
+ findimages/hi32-action-finddupplicateimages.png,
+ findimages/kipiplugin_findimages.desktop,
+ findimages/plugin_findimages.cpp, findimages/plugin_findimages.h,
+ helloworld/plugin_helloworld.cpp, helloworld/plugin_helloworld.h,
+ imagesgallery/.cvsignore, imagesgallery/Makefile.am,
+ imagesgallery/gohome.png, imagesgallery/imagesgallery.cpp,
+ imagesgallery/imagesgallery.h, imagesgallery/imgallerydialog.cpp,
+ imagesgallery/imgallerydialog.h,
+ imagesgallery/kipiplugin_imagesgallery.desktop,
+ imagesgallery/listimageserrordialog.cpp,
+ imagesgallery/listimageserrordialog.h,
+ imagesgallery/plugin_imagesgallery.cpp,
+ imagesgallery/plugin_imagesgallery.h,
+ imagesgallery/resizeimage.cpp, imagesgallery/resizeimage.h,
+ imagesgallery/up.png, imagesgallery/valid-html401.png,
+ jpeglossless/.cvsignore, jpeglossless/Makefile.am,
+ jpeglossless/actions.h, jpeglossless/actionthread.cpp,
+ jpeglossless/actionthread.h, jpeglossless/convert2grayscale.cpp,
+ jpeglossless/convert2grayscale.h,
+ jpeglossless/hi32-action-flip_image.png,
+ jpeglossless/hi32-action-grayscaleconvert.png,
+ jpeglossless/imageflip.cpp, jpeglossless/imageflip.h,
+ jpeglossless/imagerotate.cpp, jpeglossless/imagerotate.h,
+ jpeglossless/jinclude.h, jpeglossless/jpegint.h,
+ jpeglossless/kipiplugin_jpeglossless.desktop,
+ jpeglossless/messagebox.cpp, jpeglossless/messagebox.h,
+ jpeglossless/mtqueue.h, jpeglossless/plugin_jpeglossless.cpp,
+ jpeglossless/plugin_jpeglossless.h, jpeglossless/progressdlg.cpp,
+ jpeglossless/progressdlg.h, jpeglossless/transupp.c,
+ jpeglossless/transupp.h, jpeglossless/utils.cpp,
+ jpeglossless/utils.h, mpegencoder/images2mpg.man,
+ mpegencoder/images2mpg.man.gz,
+ mpegencoder/plugin_mpegencoder.cpp,
+ mpegencoder/plugin_mpegencoder.h,
+ printwizard/plugin_printwizard.cpp,
+ printwizard/plugin_printwizard.h, rawconverter/.cvsignore,
+ rawconverter/Makefile.am, rawconverter/batchdialog.cpp,
+ rawconverter/batchdialog.h, rawconverter/clistviewitem.h,
+ rawconverter/cspinbox.h, rawconverter/dcrawprocess.cpp,
+ rawconverter/digikamdcrawclient.man.gz,
+ rawconverter/digikamplugin_rawconverter.desktop,
+ rawconverter/dmessagebox.cpp, rawconverter/dmessagebox.h,
+ rawconverter/hi32-action-rawconverter.png,
+ rawconverter/plugin_rawconverter.cpp,
+ rawconverter/plugin_rawconverter.h,
+ rawconverter/previewwidget.cpp, rawconverter/previewwidget.h,
+ rawconverter/processcontroller.cpp,
+ rawconverter/processcontroller.h, rawconverter/singledialog.cpp,
+ rawconverter/singledialog.h, slideshow/.cvsignore,
+ slideshow/Makefile.am, slideshow/hi22-action-slideshow.png,
+ slideshow/imlibiface.cpp, slideshow/imlibiface.h,
+ slideshow/kipiplugin_slideshow.desktop,
+ slideshow/plugin_slideshow.cpp, slideshow/plugin_slideshow.h,
+ slideshow/slideshow.cpp, slideshow/slideshow.h,
+ slideshow/slideshowconfig.cpp, slideshow/slideshowconfig.h,
+ slideshow/slideshowgl.cpp, slideshow/slideshowgl.h: more porting,
+ now added all plugins except two that Renchi wants to work more
+ on before they are being ported. Note that not all added plugins
+ has yet been ported, if a directory is not in Makefile.am, then
+ it has not yet been ported. I have, however, done some general
+ porting on all directories.
+
+2004-04-24 01:23 gateau
+
+ * calendar/plugin_calendar.cpp, calendar/plugin_calendar.h,
+ mpegencoder/plugin_mpegencoder.cpp,
+ mpegencoder/plugin_mpegencoder.h: KIPI::Category ->
+ KIPI::Plugin::Category
+
+2004-04-24 01:10 gateau
+
+ * helloworld/plugin_helloworld.cpp, helloworld/plugin_helloworld.h,
+ printwizard/plugin_printwizard.cpp,
+ printwizard/plugin_printwizard.h: KIPI::Category ->
+ KIPI::Plugin::Category
+
+2004-04-23 22:41 blackie
+
+ * .cvsignore, Makefile.am, calendar/.cvsignore,
+ calendar/Makefile.am, calendar/calpainter.cpp,
+ calendar/calpainter.h, calendar/calprint.h,
+ calendar/calselect.cpp, calendar/calselect.h,
+ calendar/calsettings.cpp, calendar/calsettings.h,
+ calendar/caltemplate.cpp, calendar/caltemplate.h,
+ calendar/calwidget.cpp, calendar/calwidget.h,
+ calendar/calwizard.cpp, calendar/calwizard.h,
+ calendar/kipiplugin_calendar.desktop, calendar/main.cpp,
+ calendar/monthwidget.cpp, calendar/monthwidget.h,
+ calendar/plugin_calendar.cpp, calendar/plugin_calendar.h,
+ helloworld/.cvsignore, helloworld/Makefile.am,
+ helloworld/kipiplugin_helloworld.desktop,
+ helloworld/plugin_helloworld.cpp, helloworld/plugin_helloworld.h,
+ mpegencoder/.cvsignore, mpegencoder/Makefile.am,
+ mpegencoder/checkbinprog.cpp, mpegencoder/checkbinprog.h,
+ mpegencoder/images2mpg, mpegencoder/images2mpg.man,
+ mpegencoder/kimg2mpg.cpp, mpegencoder/kimg2mpg.h,
+ mpegencoder/kipiplugin_mpegencoder.desktop,
+ mpegencoder/kshowdebuggingoutput.cpp,
+ mpegencoder/kshowdebuggingoutput.h,
+ mpegencoder/optionsdialog.cpp, mpegencoder/optionsdialog.h,
+ mpegencoder/plugin_mpegencoder.cpp,
+ mpegencoder/plugin_mpegencoder.h, printwizard/.cvsignore,
+ printwizard/Makefile.am, printwizard/cropframe.cpp,
+ printwizard/cropframe.h, printwizard/frmprintwizard.cpp,
+ printwizard/frmprintwizard.h, printwizard/frmprintwizardbase.ui,
+ printwizard/kipiplugin_printwizard.desktop,
+ printwizard/plugin_printwizard.cpp,
+ printwizard/plugin_printwizard.h, printwizard/tphoto.cpp,
+ printwizard/tphoto.h, printwizard/utils.cpp, printwizard/utils.h:
+ started porting digikam plugins
+
diff --git a/kipi-plugins/INSTALL b/kipi-plugins/INSTALL
new file mode 100644
index 0000000..129bc0f
--- /dev/null
+++ b/kipi-plugins/INSTALL
@@ -0,0 +1,184 @@
+Requirements: listed at the end of README
+
+
+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 awhile. 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/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.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ 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/kipi-plugins/Makefile.am b/kipi-plugins/Makefile.am
new file mode 100644
index 0000000..6c04c41
--- /dev/null
+++ b/kipi-plugins/Makefile.am
@@ -0,0 +1,134 @@
+# Do *NOT* indent the content of the ifs, this will break the generated
+# Makefile
+
+# Please keep following list sorted alphabetically
+
+if compile_ACQUIREIMAGES
+ACQUIREIMAGESDIR = acquireimages
+endif
+
+if compile_BATCHPROCESSIMAGES
+BATCHPROCESSIMAGESDIR = batchprocessimages
+endif
+
+if compile_CALENDAR
+CALENDARDIR = calendar
+endif
+
+if compile_CDARCHIVING
+CDARCHIVINGDIR = cdarchiving
+endif
+
+if compile_FINDIMAGES
+FINDIMAGESDIR = findimages
+endif
+
+if compile_FLICKREXPORT
+FLICKREXPORTDIR = flickrexport
+endif
+
+if compile_GALLERYEXPORT
+GALLERYEXPORTDIR = galleryexport
+endif
+
+if compile_GPSSYNC
+GPSSYNCDIR = gpssync
+endif
+
+if compile_HTMLEXPORT
+HTMLEXPORTDIR = htmlexport
+endif
+
+if compile_IMAGEVIEWER
+IMAGEVIEWERDIR = imageviewer
+endif
+
+if compile_IPODEXPORT
+IPODEXPORTDIR = ipodexport
+endif
+
+if compile_JPEGLOSSLESS
+JPEGLOSSLESSDIR = jpeglossless
+endif
+
+if compile_KAMERAKLIENT
+KAMERAKLIENTDIR = kameraklient
+endif
+
+if compile_METADATAEDIT
+METADATAEDITDIR = metadataedit
+endif
+
+if compile_MPEGENCODER
+MPEGENCODERDIR = mpegencoder
+endif
+
+if compile_PICASAWEBEXPORT
+PICASAWEBEXPORTDIR = picasawebexport
+endif
+
+if compile_PRINTWIZARD
+PRINTWIZARDDIR = printwizard
+endif
+
+if compile_RAWCONVERTER
+RAWCONVERTERDIR = rawconverter
+endif
+
+if compile_SENDIMAGES
+SENDIMAGESDIR = sendimages
+endif
+
+if compile_SIMPLEVIEWEREXPORT
+SIMPLEVIEWEREXPORTDIR = simpleviewerexport
+endif
+
+if compile_SLIDESHOW
+SLIDESHOWDIR = slideshow
+endif
+
+if compile_TIMEADJUST
+TIMEADJUSTDIR = timeadjust
+endif
+
+if compile_WALLPAPER
+WALLPAPERDIR = wallpaper
+endif
+
+SUBDIRS = common \
+ $(ACQUIREIMAGESDIR) \
+ $(BATCHPROCESSIMAGESDIR) \
+ $(CALENDARDIR) \
+ $(CDARCHIVINGDIR) \
+ $(FINDIMAGESDIR) \
+ $(FLICKREXPORTDIR) \
+ $(GALLERYEXPORTDIR) \
+ $(GPSSYNCDIR) \
+ $(HTMLEXPORTDIR) \
+ $(IMAGEVIEWERDIR) \
+ $(IPODEXPORTDIR) \
+ $(JPEGLOSSLESSDIR) \
+ $(KAMERAKLIENTDIR) \
+ $(METADATAEDITDIR) \
+ $(MPEGENCODERDIR) \
+ $(PICASAWEBEXPORTDIR) \
+ $(PRINTWIZARDDIR) \
+ $(RAWCONVERTERDIR) \
+ $(SENDIMAGESDIR) \
+ $(SIMPLEVIEWEREXPORTDIR) \
+ $(SLIDESHOWDIR) \
+ $(TIMEADJUSTDIR) \
+ $(WALLPAPERDIR)
+
+rcdir = $(kde_datadir)/kipi
+rc_DATA = tips
+
+# i18n translation tips messages
+messages: rc.cpp
+ $(PREPARETIPS) >> tips.cpp
+ LIST=`find . -name \tips.cpp`; \
+ if test -n "$$LIST"; then \
+ $(XGETTEXT) $$LIST -o $(podir)/kipiplugins.pot; \
+ fi
+ rm -f tips.cpp
+
diff --git a/kipi-plugins/NEWS b/kipi-plugins/NEWS
new file mode 100644
index 0000000..bcf1b5e
--- /dev/null
+++ b/kipi-plugins/NEWS
@@ -0,0 +1,450 @@
+v 0.1.8
+---------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 144713 : utf8 not supported in "rename images" plugin.
+002 ==> 147823 : Batch processing tasks does not do the job.
+003 ==>
+
+v 0.1.7
+---------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 175033 : GPSSync : GPSSync does not get any map just a grey square.
+002 ==> 175304 : MetadataEdit : db does replicate to iptc or exif.
+003 ==> 137359 : MetadataEdit : Unclear wording in kipiplugin_metadataedit.
+004 ==> 146381 : JPEGLossLess : Image rotation splits the image with a small strip appearing on the wrong side.
+005 ==> 155023 : SendImages : Crashs when trying to send images via digiKam.
+006 ==> 170272 : FlickrExport : Undefined signature problem prevents uploading to flickr.
+007 ==> 161114 : SendImages : Resizing and emailing from digikam results in no-more readable files.
+008 ==> 147685 : General : Errors in error and "what's this" messages -- No way to select text in an error box.
+009 ==> 146293 : MetadataEdit : Plugins/Images/metadata: untranslated.
+010 ==> 140345 : BatchProcess : kipiplugins do not work due to trying to save the result into the root directory.
+011 ==> 163395 : SendImages : digiKam and encoding errors in flickr export and mail attachments.
+012 ==> 136941 : BatchProcess : Graphical picture ordering and renaming.
+013 ==> 149394 : General : Recover lost/deleted images from flash memory/camera.
+014 ==> 162441 : PicasaWebExport : Unable to create an album.
+015 ==> 162993 : PicasaWebExport : Picasa album list not refreshed.
+016 ==> 162994 : PicasaWebExport : Picasa album list does not contain "not listed" albums, contains only "public" albums.
+017 ==> 174353 : GPSSync : Kipi-plugin geolocation does not work anymore.
+018 ==> 132982 : BatchProcess : Batch rename limited, should allow renaming by patterns.
+
+v 0.1.6
+---------------------------------------------------------------------------
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 162687 : FlickrExport : Make Flickr Export screen non-modal.
+002 ==> 162683 : FlickrExport : Export to picassaweb doesn't works.
+003 ==> 164152 : FlickrExport : Geotagging when exporting to Flickr.
+004 ==> 166712 : PrintWizard : Choosing the part which is cut off for printing only works for the first photo.
+005 ==> 162994 : PicasaWebExport : Picasa album list does not contain "not listed" albums, contains only "public" albums.
+006 ==> 150912 : PicasaWebExport : Uploader does not upload.
+007 ==> 164908 : PicasaWebExport : Private albums are not listed (and then not usable).
+008 ==> 150979 : PicasaWebExport : Picasa Export-Plugins does not work.
+
+v 0.1.6 - beta1
+---------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+FlickrExport : dialog layout re-written to be more suitable.
+FlickrExport : list of item to upload is now display in dialog.
+FlickrExport : Support RAW files format to upload as JPEG preview.
+PicasaWebExport: Support RAW files format to upload as JPEG preview.
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 149890 : TimeAdjust : Adjust date and time from Exif does not work.
+002 ==> 154273 : RAWConverter : Quality setting for jpegs saved by raw converter is insanely high.
+003 ==> 157190 : GPSSync : Misleading description for geotagging images.
+004 ==> 154289 : FlickrExport : Cannot upload RAW images.
+005 ==> 153758 : FlickrExport : FlickrUploader fails to upload photos whose caption contains
+ accented characters or a trailing space.
+006 ==> 128211 : FlickrExport : "Ok" Button in "Add Photos" shouldn't fire upload directly.
+007 ==> 159081 : FlickrExport : Upload to Flickr not working.
+008 ==> 162096 : FlickrExport : When selecting all photos reverses the order.
+009 ==> 158483 : PicasaWebExport : Plugin cause Digikam crash.
+010 ==> 160453 : PicasaWebExport : Crashes when exporting to Picasaweb.
+011 ==> 155270 : FlickrExport : Tags with non-Latin characters dropped during image export.
+012 ==> 153207 : FlickrExport : Without using application tags: Flickr still reads embedded metadata into tags.
+013 ==> 153206 : FlickrExport : Provide option to remove spaces in tags during export.
+014 ==> 145149 : FlickrExport : Flickr uploading from DigiKam does not cache auth data.
+
+v 0.1.5
+---------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+SimpleViewerExport : plugin is now compatible with SimpleViewer version 1.8.x.
+SimpleViewerExport : plugin now support RAW files format.
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 155231 : GPSSync : Timezones are assumed to be only in hourly increments/decrements of GMT.
+002 ==> 154849 : GPSSync : Updates first find only, does not match other than GMT camera time.
+003 ==> 144070 : GPSSync : Typing coordinates doesn't update the map.
+004 ==> 152526 : GPSSync : Remember last display options like zoom and map/sattelite/hybrid view.
+005 ==> 158176 : SlideShow : Linking errors in slideshow plugin (missing -lXrandr).
+006 ==> 150393 : SimpleViewerExport : XML file is corrupted if exif comment contains a "<".
+007 ==> 134774 : SimpleViewerExport : Exported simpleviewer gallery fails to load images due to wrong xml file name.
+
+v 0.1.5 - RC2
+---------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+PrintWizard : caption can contain more exif info
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 151578 : BatchProcess : Popup window says "Cannot run properly 'convert' program
+ from 'ImageMagick' package" but it seems fine. (really fixed)
+002 ==> 155084 : PrintWizard : Printing comments and EXIF tags.
+003 ==> 155371 : GPSSync : Add search feature to the embedded GPS Sync Google Maps based editor.
+004 ==> 102021 : SlideShow : Pan and Zoom on Slideshow viewing (not a transition) a la iPhoto
+
+v 0.1.5 - RC1
+---------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+General : Added the availability to disable plugins we don't want to build.
+ : This feature is very useful for source based distros (Matej Laitl)
+PrintWizard : Added raw file management, now raw files can be printed.
+SlideShow : Solved minor issue in filename printing (2D slideshow).
+SlideShow : New caching mechanism
+SlideShow : Added Ken Burns effect
+Calendar : Fixed recurring events not showing (only first date was showed)
+ Setting special events only once (before printing), instead of
+ one for every page
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 149666 : General : iPod Export kipi plugin cannot be disabled at compile
+ time when libgpod is present on system.
+002 ==> 151604 : PrintWizard : Print Wizard does not recognize raw images.
+003 ==> 102021 : SlideShow : Pan and Zoom on Slideshow viewing (not a transition)
+ a la iPhoto.
+004 ==> 151578 : BatchProcess : Popup window says "Cannot run properly 'convert' program
+ from 'ImageMagick' package" but it seems fine.
+005 ==> 152210 : BatchProcess : Metadata lost when converting from png to jpeg (IPTC
+ thumbnail too big).
+006 ==> 152215 : GPSSync : GPS correlator starts too many kio_thumbnail processes.
+007 ==> 149491 : GPSSync : GPS correlator GPSSYNC do_not admit GMT+5h30 (India).
+008 ==> 150114 : GPSSync : Max time gap is limited to 999 or 2000 seconds.
+009 ==> 154244 : ImageViewer : SHIFT triggers help dialog.
+
+v 0.1.5 - Beta1
+----------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+General : Added configure options to allow disabling plugins (--disable-XXXX)
+ provided by Matej Laitl (bug #149666)
+
+PrintWizard : Wizard GUI review
+ Added exif management.
+ Prints exif date-time info.
+ Font, color and size of captions.
+ Added an option to to print without margins (full-bleed).
+ Added 10x13.33cm into a4 (provided by Joerg Kuehne)
+ Added full size A4 printing (one photo per A4 page)
+ Added A6 size to get the old configuration for 10x15cm page
+ Changed page size to real 10x15cm instead of A6 (need to set up right page size on kprinter)
+ Added a new page size 13x18cm (need to set up right page size on kprinter)
+ Each photo can be printed more than once
+PicasaWebExport: New plugin to export pictures to Picasa web service (by Vardhman Jain).
+SlideShow : Dropped imlib2 dependency
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 133193 : PrintWizard : Data on the photo.
+002 ==> 111454 : PrintWizard : Print photo's date into one corner like print assistant.
+003 ==> 146457 : PrintWizard : Rotation is not done correctly Exif.
+004 ==> 138838 : NewPlugin : Digikam Picasaweb export plugin.
+005 ==> 103152 : PrintWizard : Improvement suggestions for printing wizard.
+006 ==> 117085 : PrintWizard : Have pictures fit a whole, single sheet.
+007 ==> 100471 : PrintWizard : Can't print the same image more than once on the same page.
+008 ==> 148621 : JPEGLossLess : Image rotation not working properly.
+009 ==> 144388 : JPEGLOssLess : Cache is not updated after rotating pictures.
+010 ==> 144604 : JPEGLossLess : Rotation causes Exif data corruption.
+011 ==> 150063 : JPEGLossLess : Rotating JPEG produces error and truncates original file.
+
+v 0.1.4
+----------------------------------------------------------------------------
+
+Note on release:
+Due to missing files on svn, docbook "pt" and "da" have been removed form this
+final release, apologize for that.
+
+v 0.1.4 beta2
+----------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+HTMLExport : Option to specify whether the original images should be included
+HTMLExport : Support for theme variants
+HTMLExport : New theme: "frames", by Rüdiger Bente
+HTMLExport : New theme: "cleanframes", by Beth and Robert Marmorstein
+HTMLExport : New theme: "classic", simulating the output of the old HTML Gallery plugin
+SlideShow : Skip to next or previous image by a right or left click
+SlideShow : Skip to next or previous image by mouse wheel scrolling
+SlideShow : Images can be sorted/added/removed manually.
+SlideShow : Progress indicator printing doesn't depend on file name printing anymore.
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 140477 : SendImages : Ability to rename images being sent via email.
+002 ==> 143450 : SlideShow : Skip to next or previous image by a right or left click
+003 ==> 138880 : TimeAdjust : digiKam 0.9rc2 - 0.9.1rc1 setting file date to exif doesn't work.
+004 ==> 140890 : TimeAdjust : The preview does not display date and time properly for Japanese locale.
+005 ==> 144185 : TimeAdjust : Adjust date-time tool should remember previous fixed date.
+006 ==> 146799 : SlideShow : digikam 0.9.2 crashes when exiting - slideshow error
+
+v 0.1.4 beta1
+----------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+General : Moved Exiv2Iface class to a new shared library named libkexiv2 used by
+ kipi-plugins and digiKam.
+ImageViewer : initial import of new OpenGL based image viewer.
+RAWConverter : Port plugin to libkdcraw shared library.
+Printwizard : Printwizard can print 8 photos per page (A4)
+MPEGEncoder : Avoid to pass img2mpg script unmanaged file path.
+GPSSync : New plugin to export GPS locations from pictures to Google Maps / Google Earth.
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 139264 : General : Prefer Exif DateTimeOriginal for image date/time (DateTimeDigitized and DateTime only used as fallback)
+002 ==> 139074 : SendImages : Format missmatch at sendimages.cpp ('int' vs. 'size_t').
+003 ==> 140132 : MetadataEdit : Comments should sync to IPTC Caption First.
+006 ==> 138241 : SendImages : A patch that adds support for the Claws Mail MUA.
+007 ==> 140865 : RAWConverter : Plugin does not work (image can not be converted).
+008 ==> 141528 : JPEGLossLess : Remove confirmation dialog for image rotate.
+009 ==> 141530 : JPEGLossLess : Use Rotate left/right instead of degrees.
+010 ==> 142848 : GPSSync : Timezone needs to go to GMT +13.
+011 ==> 140297 : GPSSync : GPS kipi plugin truncates input coordinates, introducing inacuracy.
+012 ==> 143594 : GPSSync : Bad Interpolation in correlate gpssync.
+014 ==> 139793 : GPSSync : KML google export import.
+015 ==> 142259 : GalleruExport: Export to Gallery 2.2-RC-1 fails.
+016 ==> 135945 : FLickrExport : Tags with spaces are exported as multible tags.
+017 ==> 146084 : SlideShow : Slide show interface suggestions.
+018 ==> 145771 : MPEGEncoder : Gnome Desktop crashes and restarts when select Cancel option for Mpeg Slideshow plugin
+
+v 0.1.3
+----------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 137582 : GalleryExport : Add preliminary support for Gallery 2.2 security features
+002 ==> 132220 : SendImages : Solved problems with filenames and commandline with thunderbird and mozilla
+
+v 0.1.3 rc1
+----------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+Slideshow : Show image comments (configurable)
+
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 138410 : General : kipi-plugins-0.1.3-beta1 requires latest libkipi/libkexif.
+002 ==> 106133 : Slideshow : Show image comments in slideshow mode.
+003 ==> 124057 : SendImages : Problems sending jpeg-pictures from digiKam using the "send picture"-feature.
+004 ==> 108147 : Slideshow : Interval below 1 second.
+
+v 0.1.3 beta1
+----------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+New Plugin : MetadataEdit : New kipi plugin to edit EXIF and IPTC pictures metadata (by Gilles Caulier).
+New Plugin : GPSSync : New kipi plugin to sync photo metadata with a GPS device (by Gilles Caulier).
+New Plugin : IpodExport : New kipi plugin to export pictures to an ipod device (by Seb Ruiz).
+
+GalleryExport : Support for multiple galleries.
+
+HTMLExport : New "s0" theme from Petr Vanek
+
+JPEGLossLess : Removed libmagic++ depency.
+JPEGLossLess : Removed libkexif depency. Using Exiv2 instead.
+
+RAWConverter : New core to be compatible with recent dcraw release. A lot
+ of RAW decoding settings have been added.
+RAWConverter : Embedding ouput color space in target image (JPEG/PNG/TIFF).
+RAWConverter : Metadata preservation in target image during Raw conversion (JPEG/PNG).
+RAWConverter : Removing external dcraw depency. Now plugin include a full supported version of
+ dcraw program in core.
+RAWConverter : updated dcraw.c implementation to version 8.41.
+
+SendImages : Added image size limit x mail (Michael H�hstetter)
+
+TimeAdjust : Removed libkexif depency. Using Exiv2 instead.
+TimeAdjust : New option to customize Date and Time to a specific timestamp.
+TimeAdjust : New options sync EXIF/IPTC Creation Date with timestamp.
+
+
+Kipi-plugins BUG FIXING from B.K.O (http://bugs.kde.org):
+
+001 ==> 127101 : BatchProcess : expand sequence number start value in batch rename images.
+002 ==> 94494 : GalleryExport: support for multiple galleries.
+003 ==> 128394 : RAWCanverter : convertion of RAW files fails with dcraw 8.21
+004 ==> 132659 : FlickrExport : "Missing signature" - Flickr API changed and upload of
+ images is no longer possible.
+005 ==> 107905 : RAWConverter : copy exif data from raw to converted images.
+006 ==> 119537 : JPEGLossLess : Exif width and height are not corrected after lossless rotation.
+007 ==> 91545 : Slideshow : plugin does nothing if an album only contains subalbums, but no
+ images directly or is empty.
+008 ==> 134749 : GPS Sync : altitude shown is wrong.
+009 ==> 134298 : SimpleViewer : save settings / keep settings missing!
+010 ==> 134747 : GPS Sync : not optimal correlation.
+011 ==> 135157 : GPS Sync : warning about changes not applied always appear even when already applied.
+012 ==> 135237 : GPS Sync : filenames with multiple periods in them do not show up in the file
+ listing (incorrect extension identification).
+013 ==> 135484 : GPS Sync : thumbnail generation for multible images can cause severe overload.
+014 ==> 135353 : GPS Sync : the name of the plugin is missleading.
+015 ==> 136257 : MetadataEdit : Editing the EXIF-data overwrites all the data for selected files.
+016 ==> 128341 : HTMLExport : kipi html export should not resize images if "resize target images"
+ is not checked.
+017 ==> 127476 : PrintWizard : Printing as very very slow (added a workaround running kjobviewer)
+018 ==> 136941 : BatchProcess : graphical picture ordering and renaming.
+019 ==> 136855 : MetadataEdit : Editing metadata on a few selected imagefiles and clicking forward
+ or apply crashes digiKam.
+020 ==> 135408 : BatchProcess : Window does not fit on screen.
+021 ==> 117399 : BatchProcess : Usability of Target folder.
+022 ==> 137921 : MetadataEdit : wrong country code in IPTC.
+
+v 0.1.2
+----------------------------------------------------------------------------
+
+Compilation fix release.
+
+v 0.1.1
+----------------------------------------------------------------------------
+
+Compilation fix release.
+
+v 0.1.0
+----------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+GalleryExport : added Gallery 2 version support.
+ImageGallery : removed is removed and replaced by HTML export plugin.
+
+Kipi-plugins BUGFIX from B.K.O (http://bugs.kde.org):
+
+001 ==> 117105 : Calendar : Calendar tool should use internationalized country setting.
+002 ==> 101656 : CDArchive : Use irretating filenames foo.jpeg.jpeg for images.
+003 ==> 128125 : CDArchive : Album title from digikam are not converted into html entities.
+004 ==> 123978 : GalleryExport : "Invalid response" error when exporting images to Gallery 1.5.2.
+005 ==> 96352 : GalleryExport : Can not login into Gallery2.
+006 ==> 123141 : GalleryExport : Gallery Export - manage several cookies.
+007 ==> 88887 : HTMLExport : No Exif-rotation in HTML export.
+008 ==> 115474 : HTMLExport : Web export creats duplicate extensions.
+009 ==> 120739 : HTMLExport : Wrong thumbnail for album.
+010 ==> 89068 : HTMLExport : Improvement for the HTML export plugin.
+011 ==> 90943 : HTMLEXPORT : Add CSS functionality.
+012 ==> 95116 : HTMLEXPORT : Incremental local export or other easy web publishing method.
+013 ==> 96009 : HTMLEXPORT : Unnecessary deletion of directories in "export HTML" .
+014 ==> 96363 : HTMLEXPORT : Option to save full/different sized images in gallery.
+015 ==> 107380 : HTMLEXPORT : Split long html pages by number of images per page.
+016 ==> 108696 : HTMLEXPORT : Themable html export.
+017 ==> 109708 : HTMLEXPORT : Number of thumbnails per row should be in the same tab as size of thumbnail.
+018 ==> 109709 : HTMLEXPORT : Create target dir when it does not exist.
+019 ==> 109710 : HTMLEXPORT : Make clicking on image going to the next image.
+020 ==> 111136 : HTMLEXPORT : export to non-local directory (fish://) does not work.
+021 ==> 111509 : HTMLEXPORT : Subalbums not supported by HTML export.
+022 ==> 111880 : HTMLEXPORT : New option to add original image (as link in thumbnail).
+023 ==> 112107 : HTMLEXPORT : Avi files in html exports.
+024 ==> 113355 : HTMLEXPORT : Add auto-forwarding (slide show) to HTML-Export.
+025 ==> 127219 : MPEGEncoder : Creation of mpeg slide show fails.
+026 ==> 127532 : MPEGEncoder : 'image2mpg' wrong directory error.
+027 ==> 101455 : RAWConverter : Make it possible to enter numbers with 2 digit precision in RAW converter dialog.
+
+v0.1.0-rc2
+----------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+New Plugin : HTMLExport : new images gallery export supporting XHTML and CSS (by Aurelien Gateau).
+New Plugin : SimpleViewer : new plugin to export to flash web page (by Joern Ahrens)
+
+Kipi-plugins BUGFIX from B.K.O (http://bugs.kde.org):
+
+001 ==> 120242 : HTMLExport : Bad sorting of images in html export.
+002 ==> 112025 : HTMLExport : digiKam overwrites albums previously exported to HTML.
+003 ==> 106152 : HTMLExport : Creates faulty links when choosing picture filenames derived from the EXIF info.
+004 ==> 119933 : HTMLExport : Image gallery has problems with german umlauts in file-/directorynames.
+005 ==> 99418 : HTMLExport : Help menu in progress dialog refers to batch process plugin about instead of image gallery plugins.
+006 ==> 103449 : HTMLExport : Title and name of album are together and album with accents do not function.
+007 ==> 110596 : HTMLExport : Apos entitity is not correct for HTML (it is XML entity).
+008 ==> 116605 : HTMLExport : Crash when exporting to an existing dir an choosing no to overwrite.
+009 ==> 123499 : JPEGLossLess : RAW images are rotated wrong.
+010 ==> 99157 : KameraKlient : Some kameraklient source files miss copyright and license info.
+011 ==> 98286 : PrintWizard : Print Wizard has wrong default paper size.
+012 ==> 101495 : PrintWizard : Raster effect on printout.
+013 ==> 117670 : PrintWizard : Printing is awfully slow.
+014 ==> 108945 : BatchProcess : Batch image filtering overwrite mode: always overwrite doesn't work.
+015 ==> 117397 : BatchProcess : batchplugins 'start' not disabled when target folder is not writeable orwith no image in list.
+016 ==> 114512 : BatchProcess : The checkbox "Remove original" is left disabled after a preview.
+017 ==> 120868 : Calendar : Failed to create PDF callendar
+018 ==> 118936 : calendar : kipi calendar wizard should default to next year.
+019 ==> 109739 : MpegEncoder : yuvscaler error in digikam.
+020 ==> 114514 : MpegEncoder : Do not delete the temporary folder "~/tmp/kde-user/kipi-mpegencoderplugin-PID/" after
+ each encoding process.
+021 ==> 114515 : MpegEncoder : Verify the existence of the MPEG output file path and the existence of the audio input file
+ before launching the encoding process.
+022 ==> 114519 : AcquireImage : Crash when stopping a Final Scan.
+023 ==> 103763 : RAWConverter : Rawconverter (single) should fill a default file name into the save as dialog.
+024 ==> 118407 : RAWConverter : dcrawprocess.cpp does not compileon Solaris
+025 ==> 119562 : SendImages : A patch that adds support for the Sylpheed-Claws mua.
+026 ==> 119867 : Slideshow : Different icon types used by slideshow for for backwards/forwards.
+
+v0.1.0-rc1
+----------------------------------------------------------------------------
+
+Kipi-plugins NEW FEATURES:
+
+New Plugin : FlickrExport : new plugin to upload pictures on Flickr web service (by Vardhman Jain).
+
+SendImages : support for Thunderbird and GmailAgent.
+Calendar : The weekdays are now localized.
+HTMLExport : Export multiple tags to an html-page.
+JPEGLossLess : Rotate or flip your images lossless, while preserving the timestamp.
+RAWConverter : Supports of dcraw>=6.x.
+
+Kipi-plugins BUGFIX from B.K.O (http://bugs.kde.org):
+
+001 ==> 108227 : SendImages : Thunderbird will not open when sending emails in digiKam.
+002 ==> 98269 : CDArchive : Status bar in archive to CD/DVD goes to 100% while creating thumbs.
+003 ==> 89394 : CDArchive : Make CDArchivingplugin work when ImageCollection!=Folder.
+004 ==> 91651 : CDArchive : Running cdarchiving plugin from kimdaba sends all images to the cd, not just the selected images.
+005 ==> 100877 : CDArchive : kimdaba can not create temporary directories for CD-archive.
+006 ==> 110391 : BatchProcess : Batch rename removes tags and comments.
+007 ==> 110659 : BatchProcess : Batch rename function makes copies instead of renaming.
+008 ==> 110698 : TimeAdjust : Adjust time and date does not work.
+009 ==> 110575 : BatchProcess : Crash when renaming images.
+010 ==> 99895 : BatchProcess : Rename ordered by modification date sorts by name.
+011 ==> 104032 : BatchProcess : Renaming images takes a lot memory and time.
+012 ==> 105727 : BatchProcess : digiKam adds to the first picture an additional "_1".
+013 ==> 110508 : BatchProcess : Umlauts-conversion error when renaming images.
+014 ==> 104511 : BatchProcess : Why a destination path for a rename action ? "No valid URL" when blank.
+015 ==> 102219 : HTMLExport : When you export html from a tags gallery links are incorrect.
+016 ==> 98199 : HTMLExport : Missing whitespace in german html-export (headline).
+017 ==> 108537 : JPEGLossLess : Plugin change file date/time. Could this be made optional since I want to keep
+ the original file date/time.
+018 ==> 101110 : MPEGEncoder : Cannot create MPEG from photos using transitions.
+019 ==> 103282 : Slideshow : No exif-rotation.
+
diff --git a/kipi-plugins/README b/kipi-plugins/README
new file mode 100644
index 0000000..96f991b
--- /dev/null
+++ b/kipi-plugins/README
@@ -0,0 +1,140 @@
+KIPIPLUGINS PROJECT
+
+Note: Most of the KipiPlugins have previously been Digikamplugins.
+
+ kipi-plugins is based in part on the work of the Independent
+ JPEG Group.
+
+Please visit this url: http://www.kipi-plugins.org
+
+Summary:
+----------------------------------------------------------------------
+Libkipi and kipi-plugins allows image applications to use a plugin architecture for additional functionalities.
+Currently implemented plugins are:
+
+ 1) RawConverter : A Raw Image Converter for digital cameras
+
+ 2) SlideShow : Slideshow with effects ripped out from kslideshow and 3D effect using OpenGL
+
+ 3) MpegEncoder : An images to MPEG flux encoder for build a video file with many images
+
+ 4) PrintWizard : Print multiple images/index pages in one page
+
+ 5) JpegLossLess : Batch images processing (rotation/flipping) without
+ losing meta information embedded in the image
+ and without recompression of the jpeg data.
+
+ 6) CdArchiving : Albums CD archiving via K3b cd burning program
+
+ 7) AcquireImages : Acquire images interface
+ This plugin include these parts:
+ ScanImages (scanner management using Kooka).
+ ScreenshotImages (Snap Screen based on KSnapshot and adapted to Digikam).
+
+ 8) Calendar : A Calendar construction plugin using Album images
+
+ 9) SendImages : A plugin to send images by e-mail, allowing resizing and recompressing
+ before sending.
+
+10) BatchProcessImages : A batch process images plugin.
+ This plugin includes these parts:
+ RenameImages (Image file names renaming).
+ ConvertImages (Image files format converting).
+ BorderImages (Add border to images).
+ FilterImages (Image enhancements using digital filters).
+ ColorImages (Image color enhancement).
+ EffectImages (Image transformation effects).
+ ResizeImages (Basic and Prepare to print images resizing).
+ RecompressImages (Recompress JPEG, TIFF, PNG, and TGA images).
+
+11) TimeAdjust : Adjust image file Time and Date.
+
+12) WallPaper : Image to KDE Desktop.
+
+13) FindImages : Find duplicate images in albums.
+
+14) GalleryExport : Plugin to export images to a remote Gallery (and Gallery 2) server
+ (http://gallery.sf.net).
+
+15) FlickrExport : Plugin to export images to a remote Flickr web service (http://www.flickr.com)
+
+16) HTMLExport : Plugin to export images collections into XHTML page.
+
+17) SimpleViewerExport : Plugin to export images to SimpleViewer
+ (http://www.airtightinteractive.com/simpleviewer).
+
+18) GPSSync : Plugin to geolocalize pictures.
+
+19) IpodExport (beta) : Plugin to export pictures with an Ipod device.
+
+20) MetadataEdit : Plugin to edit EXIF and IPTC pictures metadata.
+
+21) PicasaWebExport : Plugin to export images to a remote Picasa web service (http://www.picasaweb.com)
+
+Remark : "HelloWorld" plugin is just a tutorial plugin implementation for developpers.
+ : "ImagesGallery" plugin is obsolete and no more maintained at the moment.
+
+
+Contact :
+-----------------------------------------------------------------------
+If you have questions, comments, suggestions to make do email at :
+
+kde-imaging@kde.org
+
+IRC channel from irc.freenode.org server: #kde-imaging
+
+IMPORTANT : the bugreports and wishlist are hosted by the KDE bugs report
+system who can be contacted by the standard Kde help menu of plugins dialog.
+A mail will be automaticly sent to the Kipi mailing list.
+There is no need to contact directly the Kipi mailing list for a bug report
+or a devel wish.
+
+The current Kipi bugs and devel wish reported to the Kde bugs report can be see
+at this url :
+
+http://bugs.kde.org/buglist.cgi?product=kipiplugins&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED
+
+
+Notes :
+------------------------------------------------------------------------
+
+- More specific compilation and installation options can be used with the 'configure' script.
+Check this with './configure --help' command line.
+
+Dependencies :
+-----------------------------------------------------------------------
+
+AutoConf >= 2.5.x http://www.gnu.org/software/autoconf
+AutoMake >= 1.7.x http://www.gnu.org/software/automake
+libqt >= 3.3.x http://www.qtsoftware.com
+libkde >= 3.4.x (>=3.5.x recommended) http://www.kde.org
+libgphoto2 >= 2.x (>=2.2.x recommended) http://www.gphoto.org
+libtiff >= 3.6.x (>=3.8.2 recommended) http://www.remotesensing.org/libtiff
+libkipi >= 0.1.5 http://www.kipi-plugins.org
+libkexiv2 >= 0.1.5 http://www.kipi-plugins.org
+libkdcraw >= 0.1.6 http://www.kipi-plugins.org
+libxslt >= 1.1 http://xmlsoft.org/XSLT
+libgpod >= 0.7.0 http://www.gtkpod.org/libgpod
+libgdk >= 2.0.0 http://library.gnome.org/devel/gdk-pixbuf
+libkcal >= 3.4.x http://pim.kde.org
+ImageMagick >= 5.5.4 (runtime dependency) http://www.imagemagick.org
+MJPEGTools >= 1.6.0 (runtime dependency) http://mjpeg.sourceforge.net
+K3b >= 0.11 (runtime dependency) http://www.k3b.org
+
+Plugin Specific Dependencies (for compiling and for running) :
+-------------------------------------------------------------------------
+
+jpeglossless : imagemagick (runtime dependency)
+slideshow : OpenGL support for libqt
+batchprocessimages : imagemagick (runtime dependency)
+cdarchiving : k3b (runtime dependency)
+kameraklient : libgphoto2
+mpegenconder : mjpegtools (runtime dependency)
+ : mpg123 (runtime dependency)
+ : vorbis-tools (runtime dependency)
+wallpaper : kdebase (runtime dependency)
+rawconverter : libtiff
+acquireimages : libtiff
+htmlexport : libxslt
+ipodexport : libgpod, libgdk
+calendar : libkcal
diff --git a/kipi-plugins/TODO b/kipi-plugins/TODO
new file mode 100644
index 0000000..bfd85cf
--- /dev/null
+++ b/kipi-plugins/TODO
@@ -0,0 +1,54 @@
+----------------------------------------------------------------------------
+* General
+
+ - anaselli: fix kipi-plugins building if libkipi is missed or a wrong
+ release is present
+ - anaselli: add svn2cl management also for prepare_libkipi.rb
+
+ - All dialog less plugins which modify images should only use
+ currentSelection().
+ - All dialog less plugins which do not modify images should use either
+ current* methods.
+
+----------------------------------------------------------------------------
+* SLIDESHOW PLUGIN
+ (SlideShow with snazzy effects)
+
+ - Add preview Slideshow effects in dialogbox similar Kcontrol
+ screensavers settings.
+ - Auto-rotate according to EXIF orientation tag
+
+----------------------------------------------------------------------------
+* MPEGENCODER PLUGIN
+ (MPEG images encoder)
+
+ - Add DIVX support using mencoder program.
+ - Using new C++ implementation with MJPEGTools and IMLIB from Renchi instead
+ images2mpg bash script.
+ - Add file name or image comment in MPEG flux.
+
+----------------------------------------------------------------------------
+
+* PRINTWIZARD PLUGIN
+ (Multiples images printing wizzard)
+
+ - Check for existence of Gimp and disable option if not available.
+
+----------------------------------------------------------------------------
+* CALENDAR PLUGIN
+ (Calendar creation wizzard)
+
+ - Use QSimpleRichText to render the calendar text
+ - Add more options for controlling the appearance.
+ - Work on beautifying the calendar layout.
+
+----------------------------------------------------------------------------
+* SENDIMAGES PLUGIN
+ (E-mail images)
+
+ - Add tarball, zip, bz2, gz generation.
+ - Add support of 'Aethera' and 'Opera' mail agents.
+
+
+
+
diff --git a/kipi-plugins/acquireimages/Makefile.am b/kipi-plugins/acquireimages/Makefile.am
new file mode 100644
index 0000000..ba029c0
--- /dev/null
+++ b/kipi-plugins/acquireimages/Makefile.am
@@ -0,0 +1,23 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(all_includes)
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_acquireimages.la
+kipiplugin_acquireimages_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+# Srcs for the plugin
+kipiplugin_acquireimages_la_SOURCES = plugin_acquireimages.cpp acquireimagedialog.cpp screenshotdialog.cpp
+
+# Libs needed by the plugin
+kipiplugin_acquireimages_la_LIBADD = $(LIB_TIFF) $(LIB_X11) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_acquireimages_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_acquireimages.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_acquireimages.pot
+
+
diff --git a/kipi-plugins/acquireimages/acquireimagedialog.cpp b/kipi-plugins/acquireimages/acquireimagedialog.cpp
new file mode 100644
index 0000000..830b2ad
--- /dev/null
+++ b/kipi-plugins/acquireimages/acquireimagedialog.cpp
@@ -0,0 +1,585 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : Acquire image dialog
+ *
+ * Copyright (C) 2003-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes
+
+extern "C"
+{
+#include <tiffio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+}
+
+// Include files for Qt
+
+#undef Unsorted // x headers suck - make qdir.h work with --enable-final
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qdir.h>
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qstring.h>
+#include <qwhatsthis.h>
+#include <qtextedit.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qcombobox.h>
+#include <qlistbox.h>
+#include <qfile.h>
+#include <qapplication.h>
+#include <qvgroupbox.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kinstance.h>
+#include <kconfig.h>
+#include <klistbox.h>
+#include <klineeditdlg.h>
+#include <ksqueezedtextlabel.h>
+#include <kio/netaccess.h>
+#include <kimageio.h>
+#include <ktempfile.h>
+#include <kdeversion.h>
+#include <kdebug.h>
+#include <kfiletreeview.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+// Include files for libKipi.
+
+#include <libkipi/imageinfo.h>
+
+// Local includes
+
+#include "pluginsversion.h"
+#include "acquireimagedialog.h"
+#include "acquireimagedialog.moc"
+
+namespace KIPIAcquireImagesPlugin
+{
+
+// Used by slotOK() method.
+
+#undef NETACCESS_WIDGET
+#if KDE_VERSION >= 0x30200
+#define NETACCESS_WIDGET , this
+#else
+#define NETACCESS_WIDGET
+#endif
+
+AcquireImageDialog::AcquireImageDialog( KIPI::Interface* interface, QWidget *parent, const QImage &img)
+ : KDialogBase( IconList, i18n("Save Target Image Options"), Help|Ok|Cancel,
+ Ok, parent, "AcquireImageDialog", true, false ), m_interface( interface )
+{
+ KImageIO::registerFormats();
+ m_qimageScanned = img;
+
+ setupImageOptions();
+ setupAlbumsList();
+ readSettings();
+ slotImageFormatChanged(m_imagesFormat->currentText());
+ page_setupImageOptions->setFocus();
+ resize( 600, 400 );
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Acquire images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to acquire images"),
+ "(c) 2003-2008, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+}
+
+AcquireImageDialog::~AcquireImageDialog()
+{
+ delete m_about;
+}
+
+void AcquireImageDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("acquireimages", "kipi-plugins");
+}
+
+void AcquireImageDialog::readSettings(void)
+{
+ // Read all settings from configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("AcquireImages Settings");
+ m_FileName->setText(m_config->readPathEntry("DefaultImageFileName", i18n("image")));
+ m_imageCompression->setValue(m_config->readNumEntry("ImageCompression", 75));
+ m_imagesFormat->setCurrentText(m_config->readEntry("ImageFormat", "TIFF"));
+
+ delete m_config;
+
+ // Get the image files filters from the hosts app.
+
+ m_ImagesFilesSort = m_interface->fileExtensions();
+}
+
+void AcquireImageDialog::writeSettings(void)
+{
+ // Write all settings in configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("AcquireImages Settings");
+ m_config->writePathEntry("DefaultImageFileName", m_FileName->text());
+ m_config->writeEntry("ImageCompression", m_imageCompression->value());
+ m_config->writeEntry("ImageFormat", m_imagesFormat->currentText());
+ m_config->sync();
+ delete m_config;
+}
+
+void AcquireImageDialog::setupImageOptions(void)
+{
+ QString whatsThis;
+
+ page_setupImageOptions = addPage( i18n("Target Image"),
+ i18n("Target Image Options"),
+ BarIcon("image", KIcon::SizeMedium ) );
+
+ QVBoxLayout *vlay = new QVBoxLayout( page_setupImageOptions, 0, spacingHint() );
+
+ //---------------------------------------------
+
+ QGroupBox * groupBox1 = new QGroupBox( page_setupImageOptions );
+ groupBox1->setFlat(false);
+ groupBox1->setTitle(i18n("File Name && Caption"));
+ QWhatsThis::add( groupBox1, i18n("<p>The target image preview with the file name and caption.") );
+ QGridLayout* grid2 = new QGridLayout( groupBox1, 3, 3 , 20, 10);
+
+ m_ImageFileName = new QLabel( i18n("File name (without suffix):"), groupBox1);
+ grid2->addMultiCellWidget(m_ImageFileName, 0, 0, 0, 3);
+
+ m_FileName = new QLineEdit(i18n("acquired_image"), groupBox1);
+ QWhatsThis::add( m_FileName, i18n("<p>Enter here the target image file name without suffix "
+ "(that will be automatically added to the file name according "
+ "to the file-format option.)") );
+ m_ImageFileName->setBuddy(m_FileName);
+ grid2->addMultiCellWidget(m_FileName, 1, 1, 0, 3);
+
+ m_ImageComments = new QLabel( i18n("Caption:"), groupBox1);
+ grid2->addMultiCellWidget(m_ImageComments, 2, 2, 0, 3);
+
+ m_CommentsEdit = new QTextEdit(groupBox1);
+ m_CommentsEdit->setMaximumHeight( 200 );
+ QWhatsThis::add( m_CommentsEdit, i18n("<p>Enter here the target image's caption.") );
+ grid2->addMultiCellWidget(m_CommentsEdit, 3, 3, 0, 2);
+
+ m_preview = new QLabel( groupBox1, "preview" );
+ m_preview->setFixedHeight( 120 );
+ m_preview->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ m_preview->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
+ QWhatsThis::add( m_preview, i18n( "<p>The preview of the target image." ) );
+ m_preview->setScaledContents( false );
+ QImage scanned = m_qimageScanned.smoothScale((m_qimageScanned.width() * 100) / m_qimageScanned.height(), 100);
+ QPixmap pix;
+ pix.convertFromImage(scanned);
+ m_preview->setPixmap(pix);
+ grid2->addMultiCellWidget(m_preview, 3, 3, 3, 3);
+
+ vlay->addWidget( groupBox1 );
+
+ //---------------------------------------------
+
+ QGroupBox * groupBox2 = new QGroupBox( i18n("Saving Options"), page_setupImageOptions );
+ groupBox2->setColumnLayout(0, Qt::Vertical );
+ groupBox2->layout()->setSpacing( 6 );
+ groupBox2->layout()->setMargin( 11 );
+ QWhatsThis::add( groupBox2, i18n("<p>The saving options of the target image.") );
+
+ QVBoxLayout * groupBox2Layout = new QVBoxLayout( groupBox2->layout() );
+ groupBox2Layout->setAlignment( Qt::AlignTop );
+
+ m_imageCompression = new KIntNumInput(75, groupBox2);
+ m_imageCompression->setRange(1, 100, 1, true );
+ m_imageCompression->setLabel( i18n("Image compression:") );
+ whatsThis = i18n("<p>The compression value of target image for JPEG and PNG formats:<p>");
+ whatsThis = whatsThis + i18n("<b>1</b>: very high compression<p>"
+ "<b>25</b>: high compression<p>"
+ "<b>50</b>: medium compression<p>"
+ "<b>75</b>: low compression (default value)<p>"
+ "<b>100</b>: no compression");
+
+ QWhatsThis::add( m_imageCompression, whatsThis);
+ groupBox2Layout->addWidget( m_imageCompression );
+
+ QHBoxLayout *hlay12 = new QHBoxLayout( );
+ groupBox2Layout->addLayout( hlay12 );
+
+ m_imagesFormat = new QComboBox(false, groupBox2);
+ m_imagesFormat->insertItem("JPEG");
+ m_imagesFormat->insertItem("PNG");
+ m_imagesFormat->insertItem("TIFF");
+ m_imagesFormat->insertItem("PPM");
+ m_imagesFormat->insertItem("BMP");
+ m_imagesFormat->setCurrentText ("TIFF");
+ whatsThis = i18n("<p>Select here the target image's file format.<p>");
+ whatsThis = whatsThis + i18n("<b>JPEG</b>: The Joint Photographic Experts' Group "
+ "file format is a good Web file format but it uses lossy data compression.<p>"
+ "<b>PNG</b>: the Portable Network Graphics format is an extensible file format for "
+ "the lossless, portable, well-compressed storage of raster images. PNG provides a "
+ "patent-free replacement for GIF and can also replace many common uses of TIFF. PNG "
+ "is designed to work well in online viewing applications, such as the World Wide Web, "
+ "so it is fully streamable with a progressive display option. Also, PNG can store gamma "
+ "and chromaticity data for improved color matching on heterogeneous platforms.");
+ whatsThis = whatsThis + i18n("<p><b>TIFF</b>: the Tagged Image File Format is a rather old standard "
+ "that is still very popular today. It is a highly flexible and platform-independent "
+ "format which is supported by numerous image processing applications and by virtually all "
+ "prepress software on the market.");
+ whatsThis = whatsThis + i18n("<p><b>PPM</b>: the Portable Pixel Map file format is used as an "
+ "intermediate format for storing color bitmap information. PPM files may be either "
+ "binary or ASCII and store pixel values up to 24 bits in size. This format generates "
+ "the biggest-sized text files for encoding images without losing quality.");
+ whatsThis = whatsThis + i18n("<p><b>BMP</b>: the BitMaP file format is a popular image format from the "
+ "Win32 environment. It efficiently stores mapped or unmapped RGB graphics data with pixels "
+ "1-, 4-, 8-, or 24-bits in size. Data may be stored raw or compressed using a 4-bit or "
+ "8-bit RLE data compression algorithm. BMP is an excellent choice for a simple bitmap "
+ "format which supports a wide range of RGB image data.");
+ QWhatsThis::add( m_imagesFormat, whatsThis );
+
+ m_labelImageFormat = new QLabel( i18n("Image file format:"), groupBox2);
+ hlay12->addWidget( m_labelImageFormat );
+ m_labelImageFormat->setBuddy( m_imagesFormat );
+ hlay12->addStretch( 1 );
+ hlay12->addWidget( m_imagesFormat );
+
+ vlay->addWidget( groupBox2 );
+ vlay->addStretch(1);
+
+ //---------------------------------------------
+
+ connect(m_imagesFormat, SIGNAL(activated(const QString &)),
+ this, SLOT(slotImageFormatChanged(const QString &)));
+}
+
+void AcquireImageDialog::setupAlbumsList(void)
+{
+ QString whatsThis;
+
+ page_setupAlbumsList = addPage( i18n("Selection"),
+ i18n("Album selection"),
+ BarIcon("folder_image", KIcon::SizeMedium ) );
+
+ QVBoxLayout *vlay = new QVBoxLayout( page_setupAlbumsList, 0, spacingHint() );
+
+ //---------------------------------------------
+
+ QVGroupBox * groupBox1 = new QVGroupBox( i18n("Select Folder in Which to Save Target Image"),
+ page_setupAlbumsList );
+
+ m_uploadPath = new KIPI::UploadWidget( m_interface, groupBox1, "m_uploadPath" );
+
+ QWidget* w = new QWidget( groupBox1 );
+ QHBoxLayout* hlay = new QHBoxLayout( w, 6 );
+ hlay->addStretch( 1 );
+
+ m_addNewAlbumButton = new QPushButton (i18n( "&Add New Folder"), w, "PushButton_AddNewAlbum");
+ hlay->addWidget( m_addNewAlbumButton );
+ QWhatsThis::add( m_addNewAlbumButton, i18n( "<p>Add a new folder."));
+
+ vlay->addWidget( groupBox1 );
+
+ //---------------------------------------------
+
+ QGroupBox * groupBox2 = new QGroupBox( i18n("Album Description"), page_setupAlbumsList );
+ groupBox2->setColumnLayout(0, Qt::Vertical );
+ groupBox2->layout()->setSpacing( 6 );
+ groupBox2->layout()->setMargin( 11 );
+ QWhatsThis::add( groupBox2, i18n("<p>The description of the current Album in the selection list.") );
+
+ QVBoxLayout * groupBox2Layout = new QVBoxLayout( groupBox2->layout() );
+ groupBox2Layout->setAlignment( Qt::AlignTop );
+
+ m_AlbumComments = new KSqueezedTextLabel( groupBox2 );
+ m_AlbumComments->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ groupBox2Layout->addWidget( m_AlbumComments );
+
+ m_AlbumCollection = new KSqueezedTextLabel( groupBox2 );
+ m_AlbumCollection->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ groupBox2Layout->addWidget( m_AlbumCollection );
+
+ m_AlbumDate = new KSqueezedTextLabel( groupBox2 );
+ m_AlbumDate->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ groupBox2Layout->addWidget( m_AlbumDate );
+
+ m_AlbumItems = new KSqueezedTextLabel( groupBox2 );
+ m_AlbumItems->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ groupBox2Layout->addWidget( m_AlbumItems );
+
+ vlay->addWidget( groupBox2 );
+
+ if ( !m_interface->hasFeature( KIPI::AlbumsHaveComments) )
+ groupBox2->hide();
+ else
+ vlay->addStretch(1);
+
+ //---------------------------------------------
+
+ connect(m_addNewAlbumButton, SIGNAL(clicked()),
+ m_uploadPath, SLOT(mkdir()));
+
+ connect(m_uploadPath, SIGNAL( folderItemSelected( const KURL & ) ),
+ this, SLOT( slotAlbumSelected( const KURL & )));
+
+ //---------------------------------------------
+
+ slotAlbumSelected( m_uploadPath->path() );
+ }
+
+void AcquireImageDialog::slotAlbumSelected( const KURL &url )
+{
+ QString comments, category, date, items;
+ QValueList<KIPI::ImageCollection> albums = m_interface->allAlbums();
+ QValueList<KIPI::ImageCollection>::Iterator albumIt;
+
+ for( albumIt = albums.begin() ; albumIt != albums.end() ; ++albumIt )
+ {
+ if ( (*albumIt).path() == url )
+ break;
+ }
+
+ if (albumIt != albums.end())
+ {
+ comments = (*albumIt).comment();
+ category = (*albumIt).category();
+ date = (*albumIt).date().toString( Qt::LocalDate );
+ items.setNum((*albumIt).images().count());
+ }
+
+ m_AlbumComments->setText( i18n("Caption: %1").arg(comments) );
+ m_AlbumCollection->setText( i18n("Collection: %1").arg(category) );
+ m_AlbumDate->setText( i18n("Date: %1").arg(date) );
+ m_AlbumItems->setText( i18n("Items: %1").arg( items ) );
+}
+
+void AcquireImageDialog::slotOk()
+{
+ // PENDING( aurelien)
+ // It would be nice if m_uploadPath kept its value between multiple snapshots.
+ KURL url = m_uploadPath->path();
+ url.adjustPath(1);
+ kdDebug(51001) << k_funcinfo << "path:" << url.prettyURL() << endl;
+
+ if (!url.isValid())
+ {
+ KMessageBox::error(this, i18n("You must select a target album for this image."));
+ return;
+ }
+
+ if (m_FileName->text().isEmpty())
+ {
+ KMessageBox::error(this, i18n("You must provide a file name for this image."));
+ return;
+ }
+
+ writeSettings();
+
+ // Get all scanned image information.
+ QString imageFormat = m_imagesFormat->currentText();
+ int imageCompression = m_imageCompression->value();
+ QString Commentsimg = m_CommentsEdit->text();
+
+ // Find an unique url
+ QString fileName = m_FileName->text();
+ QString ext = extension(imageFormat);
+ url.setFileName(fileName + ext);
+
+ if (KIO::NetAccess::exists(url, false NETACCESS_WIDGET))
+ {
+ for (int idx = 1; idx < 100 ; ++idx)
+ {
+ url.setFileName(QString("%1_%2%3").arg(fileName).arg(idx).arg(ext));
+ kdDebug(51001) << "File already exist. Try to fixed target Url to: " << url.prettyURL() << endl;
+
+ if (!KIO::NetAccess::exists(url, false NETACCESS_WIDGET))
+ break;
+ }
+ }
+
+ kdDebug(51001) << k_funcinfo << "Saving image as " << url.prettyURL() << endl;
+
+ // Save file
+ KTempFile tmp;
+ tmp.setAutoDelete(true);
+ QString imagePath;
+ if (url.isLocalFile())
+ {
+ imagePath=url.path();
+ }
+ else
+ {
+ imagePath=tmp.name();
+ }
+
+ bool ok=false;
+ if (imageFormat=="JPEG" || imageFormat=="PNG")
+ {
+ ok = m_qimageScanned.save(imagePath, imageFormat.latin1(), imageCompression);
+ }
+ else if (imageFormat=="TIFF")
+ {
+ ok = QImageToTiff(m_qimageScanned, imagePath);
+ }
+ else
+ {
+ ok = m_qimageScanned.save(imagePath, imageFormat.latin1());
+ }
+
+ if ( !ok )
+ {
+ KMessageBox::error(this, i18n("Cannot write image file \"%1\".").arg(imagePath));
+ return;
+ }
+
+ // Upload the image if necessary
+ if ( !url.isLocalFile())
+ {
+ if (!KIO::NetAccess::upload(imagePath, url NETACCESS_WIDGET))
+ {
+ KMessageBox::error(this, i18n("Could not upload image to \"%1\".").arg(url.prettyURL()));
+ return;
+ }
+ }
+
+ // Save the comments for this image.
+ QString err;
+ ok = m_interface->addImage( url, err );
+ if ( !ok )
+ {
+ KMessageBox::error(this, i18n("<qt>Error when informing the application about the new image. "
+ "The error was: %1</qt>" ).arg( err ) );
+ return;
+ }
+
+ KIPI::ImageInfo info = m_interface->info( url );
+ info.setDescription( Commentsimg );
+
+ m_interface->refreshImages( KURL::List(url) );
+
+ close();
+ delete this;
+}
+
+void AcquireImageDialog::slotImageFormatChanged(const QString &string)
+{
+ if ( string == "JPEG" || string == "PNG" )
+ m_imageCompression->setEnabled(true);
+ else
+ m_imageCompression->setEnabled(false);
+}
+
+QString AcquireImageDialog::extension(const QString& imageFormat)
+{
+ if (imageFormat == "PNG")
+ return ".png";
+
+ if (imageFormat == "JPEG")
+ return ".jpg";
+
+ if (imageFormat == "TIFF")
+ return ".tif";
+
+ if (imageFormat == "BMP")
+ return ".bmp";
+
+ if (imageFormat == "PPM")
+ return ".ppm";
+
+ Q_ASSERT(false);
+ return "";
+}
+
+bool AcquireImageDialog::QImageToTiff(const QImage& image, const QString& dst)
+{
+ TIFF *tif;
+ unsigned char *data;
+ int x, y;
+ QRgb rgb;
+
+ tif = TIFFOpen(QFile::encodeName(dst).data(), "w");
+ if ( tif )
+ {
+ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, image.width());
+ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, image.height());
+ TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
+ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+ TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE);
+ {
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
+ TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, 0));
+
+ data = new unsigned char[image.width()*3];
+ unsigned char *dptr = 0;
+
+ for (y = 0 ; y < image.height() ; ++y)
+ {
+ dptr = data;
+
+ for (x = 0 ; x < image.width() ; ++x)
+ {
+ rgb = *((uint *)image.scanLine(y) + x);
+ *(dptr++) = qRed(rgb);
+ *(dptr++) = qGreen(rgb);
+ *(dptr++) = qBlue(rgb);
+ }
+
+ TIFFWriteScanline(tif, data, y, 0);
+ }
+
+ delete [] data;
+ }
+
+ TIFFClose(tif);
+ return true;
+ }
+
+ return false;
+}
+
+} // NameSpace KIPIAcquireImagesPlugin
diff --git a/kipi-plugins/acquireimages/acquireimagedialog.h b/kipi-plugins/acquireimages/acquireimagedialog.h
new file mode 100644
index 0000000..903ce0c
--- /dev/null
+++ b/kipi-plugins/acquireimages/acquireimagedialog.h
@@ -0,0 +1,131 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : Acquire image dialog
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 ACQUIREIMAGEDIALOG_H
+#define ACQUIREIMAGEDIALOG_H
+
+// Include files for Qt
+
+#include <qimage.h>
+#include <qstring.h>
+#include <qfileinfo.h>
+#include <qguardedptr.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+#include <kio/job.h>
+#include <kurl.h>
+
+// Include files for KIPI
+
+#include <libkipi/interface.h>
+#include <libkipi/uploadwidget.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QPushButton;
+class QLineEdit;
+class QLabel;
+class QTextEdit;
+class QComboBox;
+class QFrame;
+class QPushButton;
+
+class KListBox;
+class KConfig;
+class KIntNumInput;
+class KSqueezedTextLabel;
+
+namespace KIPIAcquireImagesPlugin
+{
+
+class AcquireImageDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ AcquireImageDialog( KIPI::Interface* interface, QWidget *parent=0, const QImage &img=0);
+ ~AcquireImageDialog();
+
+private slots:
+
+ void slotHelp();
+ void slotOk();
+ void slotAlbumSelected( const KURL &url );
+ void slotImageFormatChanged(const QString &string);
+
+private:
+
+ KIPI::Interface *m_interface;
+ QImage m_qimageScanned;
+
+ QPushButton *m_addNewAlbumButton;
+ QPushButton *m_helpButton;
+
+ KConfig *m_config;
+
+ QString m_newDir;
+ QString m_ImagesFilesSort;
+
+ KIPI::UploadWidget* m_uploadPath;
+
+ KIPIPlugins::KPAboutData *m_about;
+
+ KIntNumInput *m_imageCompression;
+
+ QComboBox *m_imagesFormat;
+
+ QLineEdit *m_FileName;
+
+ QTextEdit *m_CommentsEdit;
+
+ QLabel *m_ImageComments;
+ QLabel *m_imageLabel;
+ QLabel *m_labelImageFormat;
+ QLabel *m_ImageFileName;
+ QLabel *m_preview;
+
+ QFrame *page_setupImageOptions;
+ QFrame *page_setupAlbumsList;
+
+ KSqueezedTextLabel *m_AlbumComments;
+ KSqueezedTextLabel *m_AlbumCollection;
+ KSqueezedTextLabel *m_AlbumDate;
+ KSqueezedTextLabel *m_AlbumItems;
+
+private:
+
+ QString extension(const QString& imageFormat);
+ bool QImageToTiff(const QImage& image, const QString& dst);
+ void setupImageOptions(void);
+ void setupAlbumsList(void);
+ void writeSettings(void);
+ void readSettings(void);
+};
+
+} // NameSpace KIPIAcquireImagesPlugin
+
+#endif // ACQUIREIMAGEDIALOG_H
diff --git a/kipi-plugins/acquireimages/kipiplugin_acquireimages.desktop b/kipi-plugins/acquireimages/kipiplugin_acquireimages.desktop
new file mode 100644
index 0000000..7d59fda
--- /dev/null
+++ b/kipi-plugins/acquireimages/kipiplugin_acquireimages.desktop
@@ -0,0 +1,55 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=AcquireImages
+Name[ca]=Obtenció d'imatges
+Name[da]=Hent billeder
+Name[de]=Bilder holen
+Name[el]=ΑνάκτησηΕικόνων
+Name[es]=Obtener imágenes
+Name[et]=Pildihõive
+Name[gl]=Aquisizón de Imaxes
+Name[is]=SkannaMyndir
+Name[it]=AcquisizioneImmagini
+Name[nds]=Biller rankriegen
+Name[nl]=Afbeeldingen ophalen
+Name[pa]=ਚਿੱਤਰ ਲਵੋ
+Name[pl]=Zgrywanie zdjęć
+Name[pt]=Aquisição de Imagens
+Name[sr]=Добави слике
+Name[sr@Latn]=Dobavi slike
+Name[sv]=Hämta bilder
+Name[tg]=АндӯхтаниТасвирҳо
+Name[tr]=ResimTara
+Name[xx]=xxAcquireImagesxx
+Name[zh_CN]=获取图像
+Comment=KIPI Acquire Image Plugin
+Comment[ca]=Connector del KIPI d'obtenció d'imatges
+Comment[cs]=KIPI modul pro získávání obrázků
+Comment[da]=KIPI-plugin: Hent billeder
+Comment[de]=Ein KIPI-Modul zum Holen von Bildern
+Comment[el]=Πρόσθετο ανάκτησης εικόνας KIPI
+Comment[es]=Complemento de KIPI para captura de imágenes
+Comment[et]=KIPI pildihõive plugin
+Comment[fr]=Module externe KIPI pour acquérir des images
+Comment[gl]=Plugin de KIPI para Adquirir Imaxes
+Comment[is]=KIPI íforrit til að skanna inn myndir
+Comment[it]=Plugin di acquisizione di immagini di KIPI
+Comment[ja]=Kipi 画像取り込みプラグイン
+Comment[nds]=Kipi-Moduul för't Rankriegen vun Biller
+Comment[nl]=KIPI-plugin voor het ophalen van afbeeldingen
+Comment[pa]=KIPI ਪ੍ਰਾਪਤੀ ਚਿੱਤਰ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Zgrywanie zdjęć
+Comment[pt]='Plugin' do KIPI para Aquisição de Imagens
+Comment[pt_BR]=Plugin de Aquisição de Imagens KIPI
+Comment[sr]=KIPI прикључак за добављање слика
+Comment[sr@Latn]=KIPI priključak za dobavljanje slika
+Comment[sv]=KIPI-insticksprogram: Hämta bilder
+Comment[tg]=Модули Андӯхтани Тасвирҳои KIPI
+Comment[tr]=KIPI Resim Tarama Eklentisi
+Comment[xx]=xxKIPI Acquire Image Pluginxx
+Comment[zh_CN]=KIPI 图像获取插件
+Icon=
+ServiceTypes=KIPI/Plugin
+Type=Service
+X-KDE-Library=kipiplugin_acquireimages
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/kipi-plugins/acquireimages/plugin_acquireimages.cpp b/kipi-plugins/acquireimages/plugin_acquireimages.cpp
new file mode 100644
index 0000000..46881c7
--- /dev/null
+++ b/kipi-plugins/acquireimages/plugin_acquireimages.cpp
@@ -0,0 +1,169 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a plugin to acquire images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qimage.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kscan.h>
+#include <kapplication.h>
+
+// Local includes
+
+#include "screenshotdialog.h"
+#include "acquireimagedialog.h"
+#include "plugin_acquireimages.h"
+#include "plugin_acquireimages.moc"
+
+typedef KGenericFactory<Plugin_AcquireImages> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_acquireimages,
+ Factory("kipiplugin_acquireimages"))
+
+Plugin_AcquireImages::Plugin_AcquireImages(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "AcquireImages")
+{
+ kdDebug( 51001 ) << "Plugin_AcquireImages plugin loaded" << endl;
+}
+
+void Plugin_AcquireImages::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_action_scanimages = new KAction (i18n("Scan Images..."), // Menu message.
+ "scanner", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "scan_images");
+
+ m_action_screenshotimages = new KAction (i18n("Screenshot..."), // Menu message.
+ "ksnapshot", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "screenshot_images");
+
+ addAction( m_action_scanimages );
+ addAction( m_action_screenshotimages );
+}
+
+Plugin_AcquireImages::~Plugin_AcquireImages()
+{
+}
+
+void Plugin_AcquireImages::slotActivate()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ QString from(sender()->name());
+
+ if (from == "scan_images")
+ {
+ m_scanDialog = KScanDialog::getScanDialog(kapp->activeWindow(), "KIPI Scan Images Plugin");
+
+ if ( m_scanDialog )
+ {
+ m_scanDialog->setMinimumSize(400, 300);
+
+ connect(m_scanDialog, SIGNAL(finalImage(const QImage &, int)),
+ this, SLOT(slotAcquireImageDone(const QImage &)));
+ }
+ else
+ {
+ KMessageBox::sorry(kapp->activeWindow(), i18n("No KDE scan-service available; check your system."),
+ i18n("KIPI's 'Scan Images' Plugin"));
+ kdDebug ( 51000 ) << "No Scan-service available, aborting!" << endl;
+ return;
+ }
+
+ if ( m_scanDialog->setup() )
+ m_scanDialog->show();
+ }
+ else if (from == "screenshot_images")
+ {
+ m_screenshotDialog = new KIPIAcquireImagesPlugin::ScreenGrabDialog(interface,
+ kapp->activeWindow(), "KIPI ScreenshotImagesDialog");
+ m_screenshotDialog->show();
+ }
+ else
+ {
+ kdWarning( 51000 ) << "The impossible happened... unknown flip specified" << endl;
+ return;
+ }
+}
+
+void Plugin_AcquireImages::slotAcquireImageDone(const QImage &img)
+{
+ //FIXME: this is not a cleaned way to test if scan has been interrupted
+ // anyway it prevents a crash
+ QImage * pImg = (QImage*)&img;
+ if (!pImg )
+ {
+ kdError(51000) << "Acquired image is null!" << endl;
+ return;
+ }
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ m_acquireImageDialog = new KIPIAcquireImagesPlugin::AcquireImageDialog( interface, kapp->activeWindow(), img);
+ m_acquireImageDialog->setMinimumWidth(400);
+ m_acquireImageDialog->exec();
+}
+
+KIPI::Category Plugin_AcquireImages::category( KAction* action ) const
+{
+ if ( action == m_action_scanimages )
+ return KIPI::IMPORTPLUGIN;
+ else if ( action == m_action_screenshotimages )
+ return KIPI::IMPORTPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMPORTPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/acquireimages/plugin_acquireimages.h b/kipi-plugins/acquireimages/plugin_acquireimages.h
new file mode 100644
index 0000000..e5469d3
--- /dev/null
+++ b/kipi-plugins/acquireimages/plugin_acquireimages.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a plugin to acquire images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_ACQUIREIMAGES_H
+#define PLUGIN_ACQUIREIMAGES_H
+
+// LibKIPI includes.
+
+#include <libkipi/plugin.h>
+
+class KScanDialog;
+class KAction;
+
+class AcquireImageDialog;
+class ScreenGrabDialog;
+
+class Plugin_AcquireImages : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_AcquireImages(QObject *parent, const char* name, const QStringList &args);
+ virtual ~Plugin_AcquireImages();
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+public slots:
+
+ void slotActivate();
+ void slotAcquireImageDone(const QImage &img);
+
+private:
+
+ KAction *m_action_scanimages;
+ KAction *m_action_screenshotimages;
+ KScanDialog *m_scanDialog;
+
+ KIPIAcquireImagesPlugin::AcquireImageDialog *m_acquireImageDialog;
+ KIPIAcquireImagesPlugin::ScreenGrabDialog *m_screenshotDialog;
+};
+
+#endif /* PLUGIN_ACQUIREIMAGES_H */
diff --git a/kipi-plugins/acquireimages/screenshotdialog.cpp b/kipi-plugins/acquireimages/screenshotdialog.cpp
new file mode 100644
index 0000000..5374a90
--- /dev/null
+++ b/kipi-plugins/acquireimages/screenshotdialog.cpp
@@ -0,0 +1,311 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : Screenshot batch dialog
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) Richard J. Moore 1997-2002 from KSnapshot
+ * Copyright (C) Matthias Ettrich 2000 from KSnapshot
+ * Copyright (C) Aaron J. Seigo 2002 from KSnapshot
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// C Ansi includes
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// Include files for Qt
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qfileinfo.h>
+#include <qapplication.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qframe.h>
+#include <qwidgetlist.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <knotifyclient.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+
+// Local includes
+
+#include "pluginsversion.h"
+#include "screenshotdialog.h"
+#include "acquireimagedialog.h"
+#include "screenshotdialog.moc"
+
+namespace KIPIAcquireImagesPlugin
+{
+
+ScreenGrabDialog::ScreenGrabDialog( KIPI::Interface* interface, QWidget *parent, const char *name)
+ : KDialogBase(parent, name, false, i18n("Screenshot"),
+ Help|User1|Close, Close, false, i18n("&New Snapshot")),
+ m_interface( interface )
+{
+ m_inSelect = false;
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout *layout = new QVBoxLayout(box);
+
+ //---------------------------------------------
+
+ QLabel *label1 = new QLabel(i18n("This dialog will grab either your desktop or a single\n"
+ "application window. If you grab a single window your mouse\n"
+ "cursor will change into crosshairs; then, simply select the\n"
+ "window with your mouse."), box);
+ layout->addWidget(label1);
+
+ //---------------------------------------------
+
+ m_desktopCB = new QCheckBox(i18n("Grab the entire desktop"), box);
+ QWhatsThis::add( m_desktopCB, i18n( "<p>If you enable this option, the entire desktop will be grabbed; "
+ "otherwise, only the active windows." ) );
+ layout->addWidget(m_desktopCB);
+
+ //---------------------------------------------
+
+ m_hideCB = new QCheckBox(i18n("Hide all host application windows"), box);
+ QWhatsThis::add( m_hideCB, i18n( "<p>If you enable this option, all host application windows will be hidden "
+ "during the grab operation." ) );
+ layout->addWidget(m_hideCB);
+
+ //---------------------------------------------
+
+ QLabel *label2 = new QLabel(i18n("Delay:"), box);
+ layout->addWidget(label2);
+ m_delay = new KIntNumInput(box);
+ QWhatsThis::add( m_delay, i18n( "<p>The delay in seconds before the grab operation is started.") );
+ m_delay->setRange(0, 60);
+ layout->addWidget(m_delay);
+ layout->addStretch(1);
+
+ //---------------------------------------------
+
+ m_grabber = new QWidget( 0, 0, WStyle_Customize | WX11BypassWM );
+ m_grabber->move( -4000, -4000 );
+ m_grabber->installEventFilter( this );
+
+ //---------------------------------------------
+
+ connect(this, SIGNAL(user1Clicked()),
+ this, SLOT(slotGrab()));
+
+ connect(this, SIGNAL(closeClicked()),
+ this, SLOT(slotClose()));
+
+ connect( &m_grabTimer, SIGNAL(timeout()),
+ this, SLOT(slotPerformGrab()));
+
+ //---------------------------------------------
+
+ // Read all settings from configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("ScreenshotImages Settings");
+
+ if (m_config->readEntry("GrabDesktop", "true") == "true")
+ m_desktopCB->setChecked( true );
+ else
+ m_desktopCB->setChecked( false );
+
+ if (m_config->readEntry("HideHostWin", "true") == "true")
+ m_hideCB->setChecked( true );
+ else
+ m_hideCB->setChecked( false );
+
+ m_delay->setValue(m_config->readNumEntry("Delay", 1));
+
+ delete m_config;
+
+ // About data and help button.
+
+ KAboutData* about = new KAboutData("kipiplugins",
+ I18N_NOOP("Acquire images"),
+ kipiplugins_version,
+ I18N_NOOP("A Kipi plugin to acquire images"),
+ KAboutData::License_GPL,
+ "(c) 2003-2008, Gilles Caulier",
+ 0,
+ "http://extragear.kde.org/apps/kipi");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+}
+
+ScreenGrabDialog::~ScreenGrabDialog()
+{
+}
+
+void ScreenGrabDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("acquireimages", "kipi-plugins");
+}
+
+void ScreenGrabDialog::slotClose( void )
+{
+ // Write all settings in configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("ScreenshotImages Settings");
+ m_config->writeEntry("GrabDesktop", m_desktopCB->isChecked());
+ m_config->writeEntry("HideHostWin", m_hideCB->isChecked());
+ m_config->writeEntry("Delay", m_delay->value());
+ m_config->sync();
+ delete m_config;
+
+ close();
+ delete this;
+}
+
+void ScreenGrabDialog::slotGrab()
+{
+ hide();
+
+ // Hiding the Host windows
+ m_hiddenWindows.clear();
+ if (m_hideCB->isChecked())
+ {
+ QWidgetList *list = QApplication::topLevelWidgets();
+ QWidgetListIt it( *list );
+ QWidget * w;
+ while ( (w=it.current()) != 0 )
+ {
+ ++it;
+ if ( w->isVisible())
+ {
+ m_hiddenWindows.append( w );
+ w->hide();
+ }
+ }
+ delete list;
+ }
+
+ kapp->processEvents();
+ QApplication::syncX();
+
+ if ( m_delay->value() != 0 )
+ m_grabTimer.start( m_delay->value() * 1000, true );
+ else
+ {
+ m_grabber->show();
+ m_grabber->grabMouse( crossCursor );
+ }
+}
+
+void ScreenGrabDialog::slotPerformGrab()
+{
+ m_grabber->releaseMouse();
+ m_grabber->hide();
+ m_grabTimer.stop();
+
+ if ( m_desktopCB->isChecked() == false )
+ {
+ Window root;
+ Window child;
+ uint mask;
+ int rootX, rootY, winX, winY;
+ XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
+ &rootX, &rootY, &winX, &winY,
+ &mask);
+
+ int x, y;
+ unsigned int w, h;
+ unsigned int border;
+ unsigned int depth;
+ XGetGeometry( qt_xdisplay(), child, &root, &x, &y,
+ &w, &h, &border, &depth );
+
+ m_snapshot = QPixmap::grabWindow( qt_xrootwin(), x, y, w, h );
+ }
+ else
+ m_snapshot = QPixmap::grabWindow( qt_xrootwin() );
+
+ if (m_snapshot.isNull())
+ {
+ KMessageBox::sorry(this, i18n("Unable to take snapshot."),
+ i18n("Screenshot Error"));
+
+ endGrab();
+ return;
+ }
+
+ QApplication::restoreOverrideCursor();
+ KNotifyClient::beep();
+
+ m_screenshotImage = m_snapshot.convertToImage();
+ m_acquireImageDialog = new AcquireImageDialog( m_interface, this, m_screenshotImage);
+ m_acquireImageDialog->setMinimumWidth(400);
+ m_acquireImageDialog->exec();
+
+ endGrab();
+}
+
+void ScreenGrabDialog::endGrab(void)
+{
+ // Restore the Host windows
+
+ if (m_hideCB->isChecked())
+ {
+ for( QValueList< QWidget* >::ConstIterator it = m_hiddenWindows.begin();
+ it != m_hiddenWindows.end();
+ ++it )
+ (*it)->show();
+ QApplication::syncX();
+ }
+
+ show();
+}
+
+bool ScreenGrabDialog::eventFilter( QObject* o, QEvent* e)
+{
+ if ( o == m_grabber && e->type() == QEvent::MouseButtonPress )
+ {
+ QMouseEvent* me = (QMouseEvent*) e;
+
+ if ( QWidget::mouseGrabber() != m_grabber )
+ return false;
+
+ if ( me->button() == LeftButton )
+ slotPerformGrab();
+ }
+
+ return false;
+}
+
+} // NameSpace KIPIAcquireImagesPlugin
diff --git a/kipi-plugins/acquireimages/screenshotdialog.h b/kipi-plugins/acquireimages/screenshotdialog.h
new file mode 100644
index 0000000..8cb3ebd
--- /dev/null
+++ b/kipi-plugins/acquireimages/screenshotdialog.h
@@ -0,0 +1,115 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : Screenshot batch dialog
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) Richard J. Moore 1997-2002 from KSnapshot
+ * Copyright (C) Matthias Ettrich 2000 from KSnapshot
+ * Copyright (C) Aaron J. Seigo 2002 from KSnapshot
+ *
+ * This program is free software; you can redistribute 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 SCREENSHOOTDIALOG_H
+#define SCREENSHOOTDIALOG_H
+
+// Include files for Qt
+
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+// Include files for X11
+
+extern "C"
+{
+#include <X11/X.h>
+#include <X11/Xlib.h>
+}
+
+// Include files for libKipi.
+
+#include <libkipi/interface.h>
+
+class QWidget;
+class QCheckBox;
+class QPushButton;
+
+class KConfig;
+class KIntNumInput;
+
+namespace KIPIAcquireImagesPlugin
+{
+
+class AcquireImageDialog;
+
+class ScreenGrabDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ ScreenGrabDialog( KIPI::Interface* interface,
+ QWidget *parent=0, const char *name=0);
+ ~ScreenGrabDialog();
+
+private slots:
+
+ void slotHelp();
+ void slotClose(void);
+ void slotGrab(void);
+ void slotPerformGrab(void);
+
+private:
+
+ bool eventFilter( QObject* o, QEvent* e);
+ void endGrab(void);
+
+private:
+
+ KIPI::Interface *m_interface;
+
+ bool m_inSelect;
+
+ QCheckBox *m_desktopCB;
+ QCheckBox *m_hideCB;
+
+ KIntNumInput *m_delay;
+
+ AcquireImageDialog *m_acquireImageDialog;
+
+ QImage m_screenshotImage;
+
+ KConfig *m_config;
+
+ QWidget *m_grabber;
+
+ QTimer m_grabTimer;
+
+ QPixmap m_snapshot;
+
+ QPushButton *m_helpButton;
+
+ QValueList< QWidget* > m_hiddenWindows;
+};
+
+} // NameSpace KIPIAcquireImagesPlugin
+
+#endif // SCREENSHOOTDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/Makefile.am b/kipi-plugins/batchprocessimages/Makefile.am
new file mode 100644
index 0000000..6899f56
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/Makefile.am
@@ -0,0 +1,39 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(LIBKEXIV2_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+SUBDIRS = data
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_batchprocessimages.la
+kipiplugin_batchprocessimages_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP)
+# Srcs for the plugin
+kipiplugin_batchprocessimages_la_SOURCES = plugin_batchprocessimages.cpp batchprocessimagesitem.cpp \
+ outputdialog.cpp imagepreview.cpp renameimagesdialog.cpp \
+ borderimagesdialog.cpp borderoptionsdialog.cpp \
+ convertimagesdialog.cpp convertoptionsdialog.cpp \
+ filterimagesdialog.cpp filteroptionsdialog.cpp \
+ colorimagesdialog.cpp coloroptionsdialog.cpp \
+ effectimagesdialog.cpp effectoptionsdialog.cpp \
+ recompressimagesdialog.cpp recompressoptionsdialog.cpp \
+ resizeimagesdialog.cpp resizeoptionsdialog.cpp \
+ batchprocessimagesdialog.cpp \
+ batchprocessimageslist.cpp \
+ renameimagesbase.ui renameimageswidget.cpp
+
+# Libs needed by the plugin
+kipiplugin_batchprocessimages_la_LIBADD = $(LIBKIPI_LIBS) $(LIBKEXIV2_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_batchprocessimages_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_batchprocessimages.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_batchprocessimages.pot
+
+kipibatchprocessimagesicondir = $(kde_datadir)/kipiplugin_batchprocessimages/icons
+kipibatchprocessimagesicon_ICON = AUTO
+
+
diff --git a/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp b/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp
new file mode 100644
index 0000000..e1706a6
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/batchprocessimagesdialog.cpp
@@ -0,0 +1,1092 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// Include files for Qt
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qdir.h>
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qwhatsthis.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qprocess.h>
+#include <qcolor.h>
+#include <qpainter.h>
+#include <qpalette.h>
+#include <qimage.h>
+#include <qevent.h>
+#include <qdragobject.h>
+#include <qfileinfo.h>
+#include <qhgroupbox.h>
+#include <qvgroupbox.h>
+#include <qframe.h>
+#include <qwmatrix.h>
+
+// Include files for KDE
+
+#include <kstandarddirs.h>
+#include <kcolorbutton.h>
+#include <klocale.h>
+#include <kprogress.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kinstance.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <klistview.h>
+#include <kimageio.h>
+#include <kprocess.h>
+#include <klineeditdlg.h>
+#include <kio/jobclasses.h>
+#include <kio/netaccess.h>
+#include <kio/global.h>
+#include <kio/previewjob.h>
+#include <kbuttonbox.h>
+#include <kdiroperator.h>
+#include <kdeversion.h>
+#include <kurlrequester.h>
+#include <klineedit.h>
+
+// KIPI includes
+
+#include <libkipi/uploadwidget.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes
+
+#include "pluginsversion.h"
+#include "outputdialog.h"
+#include "imagepreview.h"
+#include "batchprocessimagesdialog.h"
+#include "batchprocessimagesdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+BatchProcessImagesDialog::BatchProcessImagesDialog( KURL::List urlList, KIPI::Interface* interface,
+ QString caption, QWidget *parent )
+ : KDialogBase( KDialogBase::Plain, caption, Help|User1|Cancel,
+ Cancel, parent, "BatchProcessImagesDialog", false, false, i18n("&Start")),
+ m_selectedImageFiles( urlList), m_interface( interface )
+{
+ // Init. Tmp folder
+
+ KStandardDirs dir;
+ m_tmpFolder = dir.saveLocation("tmp", "kipi-batchprocessimagesplugin-" +
+ QString::number(getpid()) );
+
+ m_convertStatus = NO_PROCESS;
+ m_progressStatus = 0;
+ m_ProcessusProc = 0;
+ m_PreviewProc = 0;
+
+ KImageIO::registerFormats();
+
+ QWidget* box = plainPage();
+ QVBoxLayout *dvlay = new QVBoxLayout(box, 0, KDialog::spacingHint());
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay = new QHBoxLayout( dvlay );
+ groupBox1 = new QGroupBox( 0, Qt::Vertical, box );
+ groupBox1->layout()->setSpacing(KDialog::spacingHint());
+ groupBox1->layout()->setMargin(KDialog::marginHint());
+ QGridLayout* grid = new QGridLayout( groupBox1->layout(), 2, 3);
+ m_labelType = new QLabel( groupBox1 );
+ grid->addMultiCellWidget(m_labelType, 0, 0, 0, 0);
+
+ m_Type = new QComboBox(false, groupBox1);
+ grid->addMultiCellWidget(m_Type, 0, 0, 1, 1);
+
+ m_optionsButton = new QPushButton (groupBox1, "OptionButton");
+ m_optionsButton->setText(i18n("Options"));
+ QWhatsThis::add( m_optionsButton, i18n("<p>You can choose here the options to use "
+ "for the current process."));
+ grid->addMultiCellWidget(m_optionsButton, 0, 0, 2, 2);
+
+ m_smallPreview = new QCheckBox(i18n("Small preview"), groupBox1);
+ QWhatsThis::add( m_smallPreview, i18n("<p>If you enable this option, "
+ "all preview effects will be calculated on a small zone "
+ "of the image (300x300 pixels in the top left corner). "
+ "Enable this option if you have a slow computer.") );
+ m_smallPreview->setChecked( true );
+ grid->addMultiCellWidget(m_smallPreview, 1, 1, 0, 1);
+
+ m_previewButton = new QPushButton (groupBox1, "PreviewButton");
+ m_previewButton->setText(i18n("&Preview"));
+ QWhatsThis::add( m_previewButton, i18n("<p>This button builds a process "
+ "preview for the currently selected image on the list."));
+ grid->addMultiCellWidget(m_previewButton, 1, 1, 2, 2);
+
+ hlay->addWidget( groupBox1 );
+
+ //---------------------------------------------
+
+ groupBox2 = new QGroupBox( 2, Qt::Horizontal, i18n("File Operations"), box );
+
+ m_labelOverWrite = new QLabel (i18n("Overwrite mode:"), groupBox2);
+ m_overWriteMode = new QComboBox( false, groupBox2 );
+ m_overWriteMode->insertItem(i18n("Ask"));
+ m_overWriteMode->insertItem(i18n("Always Overwrite"));
+ m_overWriteMode->insertItem(i18n("Rename"));
+ m_overWriteMode->insertItem(i18n("Skip"));
+ m_overWriteMode->setCurrentText (i18n("Rename"));
+ QWhatsThis::add( m_overWriteMode, i18n("<p>Select here the overwrite mode used if your target's image "
+ "files already exist.") );
+
+ m_removeOriginal = new QCheckBox(i18n("Remove original"), groupBox2);
+ QWhatsThis::add( m_removeOriginal, i18n("<p>If you enable this option, "
+ "all original image files will be removed after processing.") );
+ m_removeOriginal->setChecked( false );
+
+ hlay->addWidget( groupBox2 );
+
+ //---------------------------------------------
+
+ groupBox3 = new QHGroupBox( i18n("Target Folder"), box );
+
+ m_destinationURL = new KURLRequester(groupBox3);
+ m_destinationURL->setMode(KFile::Directory | KFile::LocalOnly);
+ KIPI::ImageCollection album = interface->currentAlbum();
+ if (album.isValid())
+ {
+ QString url;
+ if (album.isDirectory())
+ {
+ url = album.uploadPath().path();
+ }
+ else
+ {
+ url = QDir::homeDirPath();
+ }
+ m_destinationURL->lineEdit()->setText(url);
+ }
+ QWhatsThis::add( m_destinationURL, i18n("<p>Here you can select the target folder which "
+ "will used by the process."));
+
+ dvlay->addWidget( groupBox3 );
+
+ //---------------------------------------------
+
+ groupBox4 = new QHGroupBox( box );
+ QWidget* box41 = new QWidget( groupBox4 );
+ QHBoxLayout* lay2 = new QHBoxLayout( box41, 0, spacingHint() );
+ m_listFiles = new BatchProcessImagesList( box41 );
+ lay2->addWidget( m_listFiles );
+
+ m_listFiles->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
+
+ QVBoxLayout* lay3 = new QVBoxLayout( lay2 );
+ m_addImagesButton = new QPushButton ( i18n( "&Add..." ), box41 );
+ lay3->addWidget( m_addImagesButton );
+ QWhatsThis::add( m_addImagesButton, i18n("<p>Add images to the list.") );
+
+ m_remImagesButton = new QPushButton ( i18n( "&Remove" ), box41 );
+ lay3->addWidget( m_remImagesButton );
+ QWhatsThis::add( m_remImagesButton, i18n("<p>Remove selected image from the list.") );
+
+ m_imageLabel = new QLabel( box41 );
+ m_imageLabel->setFixedHeight( 80 );
+ m_imageLabel->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ m_imageLabel->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
+ lay3->addWidget( m_imageLabel );
+ QWhatsThis::add( m_imageLabel, i18n( "<p>The preview of the selected image on the list." ) );
+ lay3->addStretch( 1 );
+
+ dvlay->addWidget( groupBox4 );
+
+ //---------------------------------------------
+
+ m_progress = new KProgress( box, "Progress" );
+ m_progress->setTotalSteps(100);
+ m_progress->setValue(0);
+ QWhatsThis::add( m_progress, i18n("<p>This is the current percentage of the task completed.") );
+
+ dvlay->addWidget( m_progress );
+
+ //---------------------------------------------
+
+ connect(m_listFiles, SIGNAL(doubleClicked(QListViewItem *)),
+ this, SLOT(slotListDoubleClicked(QListViewItem *)));
+
+ connect(this, SIGNAL(user1Clicked()),
+ this, SLOT(slotProcessStart()));
+
+ connect(m_optionsButton, SIGNAL(clicked()),
+ this, SLOT(slotOptionsClicked()));
+
+ connect(m_previewButton, SIGNAL(clicked()),
+ this, SLOT(slotPreview()));
+
+ connect(m_Type, SIGNAL(activated(int)),
+ this, SLOT(slotTypeChanged(int)));
+
+ connect(m_listFiles, SIGNAL( addedDropItems(QStringList) ),
+ this, SLOT( slotAddDropItems(QStringList)));
+
+ connect(m_listFiles, SIGNAL( currentChanged( QListViewItem * ) ),
+ this, SLOT( slotImageSelected( QListViewItem * )));
+
+ connect(m_addImagesButton, SIGNAL(clicked()),
+ this, SLOT(slotImagesFilesButtonAdd()));
+
+ connect(m_remImagesButton, SIGNAL(clicked()),
+ this, SLOT(slotImagesFilesButtonRem()));
+
+ // Get the image files filters from the hosts app.
+
+ m_ImagesFilesSort = m_interface->fileExtensions();
+
+ dvlay->activate();
+}
+
+BatchProcessImagesDialog::~BatchProcessImagesDialog()
+{
+}
+
+void BatchProcessImagesDialog::slotImagesFilesButtonAdd( void )
+{
+ QStringList ImageFilesList;
+
+ KURL::List urls = KIPI::ImageDialog::getImageURLs( this, m_interface );
+
+ for ( KURL::List::Iterator it = urls.begin() ; it != urls.end() ; ++it )
+ ImageFilesList << (*it).path(); // PENDING(blackie) handle remote URLS
+
+ if ( urls.isEmpty() ) return;
+
+ slotAddDropItems(ImageFilesList);
+}
+
+void BatchProcessImagesDialog::slotImagesFilesButtonRem( void )
+{
+ BatchProcessImagesItem *pitem = static_cast<BatchProcessImagesItem*>( m_listFiles->currentItem() );
+
+ if ( pitem )
+ {
+ m_listFiles->takeItem(pitem);
+ m_listFiles->setSelected( m_listFiles->currentItem(), true );
+ m_selectedImageFiles.remove(m_selectedImageFiles.find(pitem->pathSrc()));
+ delete pitem;
+ m_nbItem = m_selectedImageFiles.count();
+
+ if (m_nbItem == 0)
+ groupBox4->setTitle(i18n("Image Files List"));
+ else
+ groupBox4->setTitle(i18n("Image File List (1 item)", "Image File List (%n items)", m_nbItem));
+ }
+}
+
+void BatchProcessImagesDialog::slotImageSelected( QListViewItem * item )
+{
+ if ( !item || m_listFiles->childCount() == 0 )
+ {
+ m_imageLabel->clear();
+ return;
+ }
+
+ BatchProcessImagesItem *pitem = static_cast<BatchProcessImagesItem*>( item );
+ if ( !pitem ) return;
+
+ m_imageLabel->clear();
+
+ QString IdemIndexed = "file:" + pitem->pathSrc();
+
+ KURL url(IdemIndexed);
+
+ KIO::PreviewJob* m_thumbJob = KIO::filePreview( url, m_imageLabel->height() );
+
+ connect(m_thumbJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ this, SLOT(slotGotPreview(const KFileItem*, const QPixmap&)));
+}
+
+void BatchProcessImagesDialog::slotGotPreview(const KFileItem* url, const QPixmap &pixmap)
+{
+ QPixmap pix( pixmap );
+
+ // Rotate the thumbnail compared to the angle the host application dictate
+ KIPI::ImageInfo info = m_interface->info( url->url() );
+ if ( info.angle() != 0 )
+ {
+ QImage img = pix.convertToImage();
+ QWMatrix matrix;
+
+ matrix.rotate( info.angle() );
+ img = img.xForm( matrix );
+ pix.convertFromImage( img );
+ }
+
+ m_imageLabel->setPixmap(pix);
+}
+
+void BatchProcessImagesDialog::slotAddDropItems(QStringList filesPath)
+{
+ if (filesPath.isEmpty()) return;
+
+ for ( QStringList::Iterator it = filesPath.begin() ; it != filesPath.end() ; ++it )
+ {
+ QString currentDropFile = *it;
+
+ // Check if the new item already exist in the list.
+
+ bool findItem = false;
+
+ for ( KURL::List::Iterator it2 = m_selectedImageFiles.begin() ; it2 != m_selectedImageFiles.end() ; ++it2 )
+ {
+ QString currentFile = (*it2).path(); // PENDING(blackie) Handle URL's
+
+ if ( currentFile == currentDropFile )
+ findItem = true;
+ }
+
+ if (findItem == false)
+ m_selectedImageFiles.append(currentDropFile);
+ }
+
+ listImageFiles();
+}
+
+void BatchProcessImagesDialog::closeEvent ( QCloseEvent *e )
+{
+ if (!e) return;
+
+ if ( m_PreviewProc != 0 )
+ if ( m_PreviewProc->isRunning() ) m_PreviewProc->kill(SIGTERM);
+
+ if ( m_ProcessusProc != 0 )
+ if ( m_ProcessusProc->isRunning() ) m_ProcessusProc->kill(SIGTERM);
+
+ e->accept();
+}
+
+void BatchProcessImagesDialog::slotProcessStart( void )
+{
+ if ( m_selectedImageFiles.isEmpty() == true )
+ return;
+
+ if ( m_removeOriginal->isChecked() == true )
+ {
+ if ( KMessageBox::warningContinueCancel(this,
+ i18n("All original image files will be removed from the source Album.\nDo you want to continue?"),
+ i18n("Delete Original Image Files"), KStdGuiItem::cont(),
+ "KIPIplugin-BatchProcessImages-AlwaysRemomveOriginalFiles") != KMessageBox::Continue )
+ return;
+ }
+
+ m_convertStatus = UNDER_PROCESS;
+ disconnect( this, SIGNAL(user1Clicked()), this, SLOT(slotProcessStart()));
+ showButtonCancel( false );
+ setButtonText( User1, i18n("&Stop") );
+ connect(this, SIGNAL(user1Clicked()), this, SLOT(slotProcessStop()));
+
+ m_labelType->setEnabled(false);
+ m_Type->setEnabled(false);
+ m_optionsButton->setEnabled(false);
+ m_previewButton->setEnabled(false);
+ m_smallPreview->setEnabled(false);
+
+ m_labelOverWrite->setEnabled(false);
+ m_overWriteMode->setEnabled(false);
+ m_removeOriginal->setEnabled(false);
+
+ m_destinationURL->setEnabled(false);
+ m_addImagesButton->setEnabled(false);
+ m_remImagesButton->setEnabled(false);
+
+ m_listFile2Process_iterator = new QListViewItemIterator( m_listFiles );
+ startProcess();
+}
+
+bool BatchProcessImagesDialog::startProcess(void)
+{
+ if ( m_convertStatus == STOP_PROCESS )
+ {
+ endProcess();
+ return true;
+ }
+
+ QString targetAlbum = m_destinationURL->url();
+
+ //TODO check if it is valid also for remote URL's
+ // this is a workarond for bug 117397
+ QFileInfo dirInfo(targetAlbum + "/");
+ if (!dirInfo.isDir () || !dirInfo.isWritable())
+ {
+ KMessageBox::error(this, i18n("You must specify a writable path for your output file."));
+ endProcess();
+ return true;
+ }
+
+ BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() );
+ m_listFiles->setCurrentItem(item);
+
+ if ( prepareStartProcess(item, targetAlbum) == false ) // If there is a problem during the
+ { // preparation -> pass to the next item!
+ ++*m_listFile2Process_iterator;
+ ++m_progressStatus;
+ m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem));
+ item = static_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() );
+ m_listFiles->setCurrentItem(item);
+
+ if ( m_listFile2Process_iterator->current() )
+ {
+ startProcess();
+ return true;
+ }
+ else
+ {
+ endProcess();
+ return true;
+ }
+ }
+
+ KURL desturl(targetAlbum + "/" + item->nameDest());
+
+#if KDE_VERSION >= 0x30200
+ if ( KIO::NetAccess::exists( desturl, false, kapp->activeWindow() ) == true )
+#else
+ if ( KIO::NetAccess::exists( desturl ) == true )
+#endif
+ {
+ switch (overwriteMode())
+ {
+ case OVERWRITE_ASK:
+ {
+ int ValRet = KMessageBox::warningYesNoCancel(this,
+ i18n("The destination file \"%1\" already exists;\n"
+ "do you want overwrite it?").arg(item->nameDest()),
+ i18n("Overwrite Destination Image File"), KStdGuiItem::cont());
+
+ if ( ValRet == KMessageBox::No )
+ {
+ item->changeResult(i18n("Skipped."));
+ item->changeError(i18n("destination image file already exists (skipped by user)."));
+ ++*m_listFile2Process_iterator;
+ ++m_progressStatus;
+ m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem));
+
+ if ( m_listFile2Process_iterator->current() )
+ {
+ startProcess();
+ return true;
+ }
+ else
+ {
+ endProcess();
+ return true;
+ }
+ }
+ else if ( ValRet == KMessageBox::Cancel )
+ {
+ processAborted(false);
+ return false;
+ }
+ else
+ {
+ item->setDidOverWrite( true );
+ }
+
+ break;
+ }
+
+ case OVERWRITE_RENAME:
+ {
+ QFileInfo *Target = new QFileInfo(targetAlbum + "/" + item->nameDest());
+ QString newFileName = RenameTargetImageFile(Target);
+
+ if ( newFileName.isNull() )
+ {
+ item->changeResult(i18n("Failed."));
+ item->changeError(i18n("destination image file already exists and cannot be renamed."));
+ ++*m_listFile2Process_iterator;
+ ++m_progressStatus;
+ m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem));
+
+ if ( m_listFile2Process_iterator->current() )
+ {
+ startProcess();
+ return true;
+ }
+ else
+ {
+ endProcess();
+ return true;
+ }
+ }
+ else
+ {
+ QFileInfo *newTarget = new QFileInfo(newFileName);
+ item->changeNameDest(newTarget->fileName());
+ }
+
+ break;
+ }
+
+ case OVERWRITE_SKIP:
+ {
+ item->changeResult(i18n("Skipped."));
+ item->changeError(i18n("destination image file already exists (skipped automatically)."));
+ ++*m_listFile2Process_iterator;
+ ++m_progressStatus;
+ m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem));
+
+ if ( m_listFile2Process_iterator->current() )
+ {
+ startProcess();
+ return true;
+ }
+ else
+ {
+ endProcess();
+ return true;
+ }
+ break;
+ }
+
+ case OVERWRITE_OVER: // In this case do nothing : 'convert' default mode...
+ item->setDidOverWrite( true );
+ break;
+
+ default:
+ {
+ endProcess();
+ return true;
+ break;
+ }
+ }
+ }
+
+ m_commandLine = QString();
+ m_ProcessusProc = new KProcess;
+ m_commandLine.append(makeProcess(m_ProcessusProc, item, targetAlbum));
+
+ item->changeOutputMess(m_commandLine + "\n\n");
+
+ connect(m_ProcessusProc, SIGNAL(processExited(KProcess *)),
+ this, SLOT(slotProcessDone(KProcess*)));
+
+ connect(m_ProcessusProc, SIGNAL(receivedStdout(KProcess *, char*, int)),
+ this, SLOT(slotReadStd(KProcess*, char*, int)));
+
+ connect(m_ProcessusProc, SIGNAL(receivedStderr(KProcess *, char*, int)),
+ this, SLOT(slotReadStd(KProcess*, char*, int)));
+
+ bool result = m_ProcessusProc->start(KProcess::NotifyOnExit, KProcess::All);
+ if(!result)
+ {
+ KMessageBox::error(this, i18n("Cannot start 'convert' program from 'ImageMagick' package;\n"
+ "please check your installation."));
+ return false;
+ }
+
+ return true;
+}
+
+void BatchProcessImagesDialog::slotReadStd(KProcess* /*proc*/, char *buffer, int buflen)
+{
+ BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() );
+ item->changeOutputMess( QString::fromLocal8Bit(buffer, buflen) );
+}
+
+void BatchProcessImagesDialog::slotProcessDone(KProcess* proc)
+{
+ if ( m_convertStatus == PROCESS_DONE )
+ {
+ // processAborted() has already been called. No need to show the warning.
+ return;
+ }
+
+ BatchProcessImagesItem *item = dynamic_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() );
+ m_listFiles->ensureItemVisible(m_listFiles->currentItem());
+
+ if ( !m_ProcessusProc->normalExit() )
+ {
+ int code = KMessageBox::warningContinueCancel( this,
+ i18n("The 'convert' program from 'ImageMagick' package has been stopped abnormally"),
+ i18n("Error running 'convert'") );
+
+ if ( code == KMessageBox::Cancel )
+ {
+ processAborted(true);
+ }
+ else
+ {
+ item->changeResult(i18n("Failed."));
+ item->changeError(i18n("'convert' program from 'ImageMagick' package has been stopped abnormally."));
+ ++*m_listFile2Process_iterator;
+ ++m_progressStatus;
+ m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem));
+
+ if ( m_listFile2Process_iterator->current() )
+ startProcess();
+ else
+ endProcess();
+ }
+ return;
+ }
+
+ int ValRet = proc->exitStatus();
+ kdWarning() << "Convert exit (" << ValRet << ")" << endl;
+
+ switch (ValRet)
+ {
+ case 0: // Process finished successfully !
+ {
+ item->changeResult(i18n("OK"));
+ item->changeError(i18n("no processing error"));
+ processDone();
+
+ // Save the comments for the converted image
+ KURL src;
+ src.setPath( item->pathSrc() );
+ KURL dest = m_destinationURL->url();
+ dest.addPath( item->nameDest() );
+ QString errmsg;
+
+ KURL::List urlList;
+ urlList.append(src);
+ urlList.append(dest);
+ m_interface->refreshImages( urlList );
+
+ if ( !item->overWrote() )
+ {
+ // Do not add an entry if there was an image at the location already.
+ bool ok = m_interface->addImage( dest, errmsg );
+
+ if ( !ok )
+ {
+ int code = KMessageBox::warningContinueCancel( this,
+ i18n("<qt>Error adding image to application; error message was: "
+ "<b>%1</b></qt>").arg( errmsg ),
+ i18n("Error Adding Image to Application") );
+
+ if ( code == KMessageBox::Cancel )
+ {
+ slotProcessStop();
+ break;
+ }
+ else
+ item->changeResult(i18n("Failed."));
+ }
+ }
+
+ if ( src != dest )
+ {
+ KIPI::ImageInfo srcInfo = m_interface->info( src );
+ KIPI::ImageInfo destInfo = m_interface->info( dest );
+ destInfo.cloneData( srcInfo );
+ }
+
+ if ( m_removeOriginal->isChecked() && src != dest )
+ {
+ KURL deleteImage(item->pathSrc());
+
+#if KDE_VERSION >= 0x30200
+ if ( KIO::NetAccess::del( deleteImage, kapp->activeWindow() ) == false )
+#else
+ if ( KIO::NetAccess::del( deleteImage ) == false )
+#endif
+ {
+ item->changeResult(i18n("Warning:"));
+ item->changeError(i18n("cannot remove original image file."));
+ }
+ else
+ m_interface->delImage( item->pathSrc() );
+ }
+ break;
+ }
+ case 15: // process aborted !
+ {
+ processAborted(true);
+ break;
+ }
+ default : // Processing error !
+ {
+ item->changeResult(i18n("Failed."));
+ item->changeError(i18n("cannot process original image file."));
+ break;
+ }
+ }
+
+ ++*m_listFile2Process_iterator;
+ ++m_progressStatus;
+ m_progress->setValue((int)((float)m_progressStatus *(float)100 / (float)m_nbItem));
+
+ if ( m_listFile2Process_iterator->current() )
+ startProcess();
+ else
+ endProcess();
+}
+
+void BatchProcessImagesDialog::slotListDoubleClicked(QListViewItem *itemClicked)
+{
+ BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( itemClicked );
+
+ if (m_convertStatus == PROCESS_DONE)
+ {
+ OutputDialog *infoDialog = new OutputDialog(this,
+ i18n("Image processing error"),
+ item->outputMess(),
+ i18n("Image \"%1\": %2\n\nThe output messages are:\n")
+ .arg(item->nameSrc()).arg(item->error())
+ );
+ infoDialog->exec();
+ }
+}
+
+void BatchProcessImagesDialog::slotPreview(void)
+{
+ kdWarning() << "BatchProcessImagesDialog::slotPreview" << endl;
+
+ if ( m_listFiles->currentItem() == 0 )
+ {
+ KMessageBox::error(this, i18n("You must select an item from the list to calculate the preview."));
+ return;
+ }
+
+ BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFiles->currentItem() );
+
+ m_listFiles->setEnabled(false);
+ m_labelType->setEnabled(false);
+ m_Type->setEnabled(false);
+ m_optionsButton->setEnabled(false);
+ m_previewButton->setEnabled(false);
+ m_labelOverWrite->setEnabled(false);
+ m_overWriteMode->setEnabled(false);
+ m_removeOriginal->setEnabled(false);
+ m_smallPreview->setEnabled(false);
+ m_destinationURL->setEnabled(false);
+ m_addImagesButton->setEnabled(false);
+ m_remImagesButton->setEnabled(false);
+
+ disconnect( this, SIGNAL(user1Clicked()),
+ this, SLOT(slotProcessStart()));
+
+ showButtonCancel( false );
+ setButtonText( User1, i18n("&Stop") );
+
+ connect(this, SIGNAL(user1Clicked()),
+ this, SLOT(slotPreviewStop()));
+
+ m_previewOutput = "";
+ m_PreviewProc = new KProcess;
+
+ m_previewOutput.append(makeProcess(m_PreviewProc, item, QString(), true));
+
+ *m_PreviewProc << m_tmpFolder + "/" + QString::number(getpid()) + "preview.PNG";
+ m_previewOutput.append( " " + m_tmpFolder + "/" + QString::number(getpid()) + "preview.PNG\n\n");
+
+ connect(m_PreviewProc, SIGNAL(processExited(KProcess *)),
+ this, SLOT(slotPreviewProcessDone(KProcess*)));
+
+ connect(m_PreviewProc, SIGNAL(receivedStdout(KProcess *, char*, int)),
+ this, SLOT(slotPreviewReadStd(KProcess*, char*, int)));
+
+ connect(m_PreviewProc, SIGNAL(receivedStderr(KProcess *, char*, int)),
+ this, SLOT(slotPreviewReadStd(KProcess*, char*, int)));
+
+ bool result = m_PreviewProc->start(KProcess::NotifyOnExit, KProcess::All);
+ if(!result)
+ {
+ KMessageBox::error(this, i18n("Cannot start 'convert' program from 'ImageMagick' package;\n"
+ "please check your installation."));
+ m_previewButton->setEnabled(true);
+ return;
+ }
+}
+
+void BatchProcessImagesDialog::slotPreviewReadStd(KProcess* /*proc*/, char *buffer, int buflen)
+{
+ m_previewOutput.append( QString::fromLocal8Bit(buffer, buflen) );
+}
+
+void BatchProcessImagesDialog::slotPreviewProcessDone(KProcess* proc)
+{
+ if (!m_PreviewProc->normalExit())
+ {
+ KMessageBox::error(this, i18n("Cannot run properly 'convert' program from 'ImageMagick' package."));
+ m_previewButton->setEnabled(true);
+ return;
+ }
+
+ BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFiles->currentItem() );
+ int ValRet = proc->exitStatus();
+
+ kdWarning() << "Convert exit (" << ValRet << ")" << endl;
+
+ if ( ValRet == 0 )
+ {
+ QString cropTitle = "";
+
+ if ( m_smallPreview->isChecked() )
+ cropTitle = i18n(" - small preview");
+
+ ImagePreview *previewDialog = new ImagePreview(
+ item->pathSrc(),
+ m_tmpFolder + "/" + QString::number(getpid()) + "preview.PNG",
+ m_tmpFolder,
+ m_smallPreview->isChecked(),
+ false,
+ m_Type->currentText() + cropTitle,
+ item->nameSrc(),
+ this);
+ previewDialog->exec();
+
+ KURL deletePreviewImage(m_tmpFolder + "/" + QString::number(getpid()) + "preview.PNG");
+
+#if KDE_VERSION >= 0x30200
+ KIO::NetAccess::del( deletePreviewImage, kapp->activeWindow() );
+#else
+ KIO::NetAccess::del( deletePreviewImage );
+#endif
+ }
+ else
+ {
+ OutputDialog *infoDialog = new OutputDialog(this,
+ i18n("Preview processing error"),
+ m_previewOutput,
+ i18n("Cannot process preview for image \"%1\"."
+ "\nThe output messages are:\n")
+ .arg(item->nameSrc())
+ );
+ infoDialog->exec();
+ }
+
+ endPreview();
+}
+
+void BatchProcessImagesDialog::slotPreviewStop( void )
+{
+ // Try to kill the current preview process !
+ if ( m_PreviewProc->isRunning() == true ) m_PreviewProc->kill(SIGTERM);
+
+ endPreview();
+}
+
+void BatchProcessImagesDialog::slotProcessStop( void )
+{
+ // Try to kill the current process !
+ if ( m_ProcessusProc->isRunning() == true ) m_ProcessusProc->kill(SIGTERM);
+
+ // If kill operation failed, Stop the process at the next image !
+ if ( m_convertStatus == UNDER_PROCESS ) m_convertStatus = STOP_PROCESS;
+
+ processAborted(true);
+}
+
+void BatchProcessImagesDialog::slotOk()
+{
+ close();
+ saveSettings();
+ delete this;
+}
+
+void BatchProcessImagesDialog::listImageFiles(void)
+{
+ m_nbItem = m_selectedImageFiles.count();
+
+ if (m_nbItem == 0) groupBox4->setTitle(i18n("Image File List"));
+ else
+ groupBox4->setTitle(i18n("Image File List (1 item)", "Image File List (%n items)", m_nbItem));
+
+ if (m_selectedImageFiles.isEmpty()) return;
+
+ for ( KURL::List::Iterator it = m_selectedImageFiles.begin() ; it != m_selectedImageFiles.end() ; ++it )
+ {
+ QString currentFile = (*it).path(); // PENDING(blackie) Handle URLS
+ QFileInfo *fi = new QFileInfo(currentFile);
+
+ // Check if the new item already exist in the list.
+
+ bool findItem = false;
+
+ QListViewItemIterator it2( m_listFiles );
+
+ while ( it2.current() )
+ {
+ BatchProcessImagesItem *pitem = static_cast<BatchProcessImagesItem*>(it2.current());
+
+ if ( pitem->pathSrc() == currentFile.section('/', 0, -1) )
+ findItem = true;
+
+ ++it2;
+ }
+
+ if (findItem == false)
+ {
+ QString oldFileName = fi->fileName();
+ QString newFileName = oldFileName2NewFileName(oldFileName);
+
+ new BatchProcessImagesItem(m_listFiles,
+ currentFile.section('/', 0, -1),
+ oldFileName,
+ newFileName,
+ ""
+ );
+ }
+
+ delete fi;
+ }
+
+ m_listFiles->setCurrentItem( m_listFiles->firstChild());
+ m_listFiles->setSelected( m_listFiles->currentItem(), true );
+ slotImageSelected(m_listFiles->currentItem());
+ m_listFiles->ensureItemVisible(m_listFiles->currentItem());
+}
+
+void BatchProcessImagesDialog::endPreview(void)
+{
+ m_listFiles->setEnabled(true);
+ m_labelType->setEnabled(true);
+ m_Type->setEnabled(true);
+ m_previewButton->setEnabled(true);
+ m_labelOverWrite->setEnabled(true);
+ m_overWriteMode->setEnabled(true);
+ m_destinationURL->setEnabled(true);
+ m_addImagesButton->setEnabled(true);
+ m_remImagesButton->setEnabled(true);
+ m_smallPreview->setEnabled(true);
+ m_removeOriginal->setEnabled(true);
+ showButtonCancel( true );
+
+ m_optionsButton->setEnabled(true); // Default status if 'slotTypeChanged' isn't re-implemented.
+ slotTypeChanged(m_Type->currentItem());
+
+ setButtonText( User1, i18n("&Start") );
+
+ disconnect(this, SIGNAL(user1Clicked()),
+ this, SLOT(slotPreviewStop()));
+
+ connect(this, SIGNAL(user1Clicked()),
+ this, SLOT(slotProcessStart()));
+}
+
+int BatchProcessImagesDialog::overwriteMode(void)
+{
+ QString OverWrite = m_overWriteMode->currentText();
+
+ if (OverWrite == i18n("Ask"))
+ return OVERWRITE_ASK;
+
+ if (OverWrite == i18n("Rename"))
+ return OVERWRITE_RENAME;
+
+ if (OverWrite == i18n("Skip"))
+ return OVERWRITE_SKIP;
+
+ if (OverWrite == i18n("Always Overwrite"))
+ return OVERWRITE_OVER;
+
+ return OVERWRITE_ASK;
+}
+
+void BatchProcessImagesDialog::processAborted(bool removeFlag)
+{
+ kdWarning() << "BatchProcessImagesDialog::processAborted" << endl;
+
+ BatchProcessImagesItem *item = static_cast<BatchProcessImagesItem*>( m_listFile2Process_iterator->current() );
+ m_listFiles->ensureItemVisible(m_listFiles->currentItem());
+
+ item->changeResult(i18n("Aborted."));
+ item->changeError(i18n("process aborted by user"));
+
+ if (removeFlag == true) // Try to delete de destination !
+ {
+ KURL deleteImage = m_destinationURL->url();
+ deleteImage.addPath(item->nameDest());
+
+#if KDE_VERSION >= 0x30200
+ if ( KIO::NetAccess::exists( deleteImage, false, kapp->activeWindow() ) == true )
+ KIO::NetAccess::del( deleteImage, kapp->activeWindow() );
+#else
+ if ( KIO::NetAccess::exists( deleteImage ) == true )
+ KIO::NetAccess::del( deleteImage );
+#endif
+ }
+
+ endProcess();
+}
+
+void BatchProcessImagesDialog::endProcess(void)
+{
+ m_convertStatus = PROCESS_DONE;
+ setButtonText( User1, i18n("&Close") );
+
+ disconnect(this, SIGNAL(user1Clicked()),
+ this, SLOT(slotProcessStop()));
+
+ connect(this, SIGNAL(user1Clicked()),
+ this, SLOT(slotOk()));
+}
+
+QString BatchProcessImagesDialog::RenameTargetImageFile(QFileInfo *fi)
+{
+ QString Temp;
+ int Enumerator = 0;
+ KURL NewDestUrl;
+
+ do
+ {
+ ++Enumerator;
+ Temp = Temp.setNum( Enumerator );
+ NewDestUrl = fi->filePath().left( fi->filePath().findRev('.', -1)) + "_" + Temp
+ + "." + fi->filePath().section('.', -1 );
+ }
+ while ( Enumerator < 100 &&
+#if KDE_VERSION >= 0x30200
+ KIO::NetAccess::exists( NewDestUrl, true, kapp->activeWindow() )
+#else
+ KIO::NetAccess::exists( NewDestUrl )
+#endif
+ == true );
+
+ if (Enumerator == 100) return QString();
+
+ return (NewDestUrl.path());
+}
+
+QString BatchProcessImagesDialog::extractArguments(KProcess *proc)
+{
+ QString retArguments;
+ QValueList<QCString> argumentsList = proc->args();
+
+ for ( QValueList<QCString>::iterator it = argumentsList.begin() ; it != argumentsList.end() ; ++it )
+ retArguments.append(*it + " ");
+
+ return (retArguments);
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/batchprocessimagesdialog.h b/kipi-plugins/batchprocessimages/batchprocessimagesdialog.h
new file mode 100644
index 0000000..6792781
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/batchprocessimagesdialog.h
@@ -0,0 +1,246 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 BATCHPROCESSIMAGESDIALOG_H
+#define BATCHPROCESSIMAGESDIALOG_H
+
+#define OVERWRITE_ASK 0
+#define OVERWRITE_RENAME 1
+#define OVERWRITE_SKIP 2
+#define OVERWRITE_OVER 3
+
+#define NO_PROCESS 0
+#define UNDER_PROCESS 1
+#define PROCESS_DONE 2
+#define STOP_PROCESS 3
+
+// Include files for Qt
+
+#include <qstring.h>
+#include <qpushbutton.h>
+#include <qguardedptr.h>
+
+// Include files for KDE
+
+#include <kio/job.h>
+#include <kdialogbase.h>
+#include <kdebug.h>
+#include <kurl.h>
+
+// Include files for KIPI
+
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "batchprocessimagesitem.h"
+#include "batchprocessimageslist.h"
+
+class QLabel;
+class QComboBox;
+class QCheckBox;
+class QFileInfo;
+class QPushButton;
+class QListViewItemIterator;
+class QListViewItem;
+class QGroupBox;
+
+class KProcess;
+class KConfig;
+class KProgress;
+class KURL;
+class KURLRequester;
+class KFileItem;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+ // Don't forget to add the 'm_Type' and 'm_labelType' implementation in the constructor of
+ // children dialog class.
+
+ BatchProcessImagesDialog( KURL::List urlList, KIPI::Interface* interface, QString caption, QWidget *parent=0 );
+ ~BatchProcessImagesDialog();
+
+protected slots:
+ void slotProcessStop(void);
+
+private slots:
+
+ // --------------------------------------------------------------------------------------------------------
+ // Standards slots
+
+ void closeEvent ( QCloseEvent *e );
+ void slotOk( void );
+
+ void slotProcessStart(void);
+ void slotProcessDone(KProcess* proc);
+ void slotReadStd(KProcess* proc, char *buffer, int buflen);
+
+ void slotPreview(void);
+ void slotPreviewProcessDone(KProcess* proc);
+ void slotPreviewReadStd(KProcess* proc, char *buffer, int buflen);
+ void slotPreviewStop( void );
+
+ void slotListDoubleClicked(QListViewItem *itemClicked);
+
+ void slotAddDropItems(QStringList filesPath);
+
+ void slotImageSelected( QListViewItem * item );
+ void slotGotPreview(const KFileItem* , const QPixmap &pixmap);
+
+ void slotImagesFilesButtonAdd( void );
+ void slotImagesFilesButtonRem( void );
+
+ // --------------------------------------------------------------------------------------------------------
+ // Standards virtuals slots for re-implementation
+
+ virtual void slotHelp(void){}; // Called when 'Help' menu option is actived.
+ virtual void slotOptionsClicked(void){}; // Called when 'Options' button is clicked.
+ virtual void slotTypeChanged(int){}; // Called when the current type option is changed.
+
+ protected:
+
+ // --------------------------------------------------------------------------------------------------------
+ // Standards widgets in the dialog
+
+ QLabel *m_labelOverWrite;
+ QLabel *m_labelType;
+ QLabel *m_imageLabel;
+
+ QComboBox *m_overWriteMode;
+ QComboBox *m_Type;
+
+ KURLRequester *m_destinationURL;
+
+ BatchProcessImagesList *m_listFiles;
+ KProgress *m_progress;
+
+ QCheckBox *m_removeOriginal;
+ QCheckBox *m_smallPreview;
+
+ QGroupBox *groupBox1;
+ QGroupBox *groupBox2;
+ QGroupBox *groupBox3;
+ QGroupBox *groupBox4;
+ QGroupBox *groupBox41;
+
+ QPushButton *m_optionsButton;
+ QPushButton *m_previewButton;
+ QPushButton *m_addImagesButton;
+ QPushButton *m_remImagesButton;
+ QPushButton *m_helpButton;
+
+ KConfig *m_config;
+
+ int m_convertStatus;
+ int m_progressStatus;
+ int m_nbItem;
+
+ KProcess *m_ProcessusProc;
+ KProcess *m_PreviewProc;
+
+ QListViewItemIterator *m_listFile2Process_iterator;
+
+ QString whatsThis;
+ QString m_ImagesFilesSort;
+ QString m_newDir;
+ QString m_commandLine;
+ QString m_tmpFolder;
+ QString m_previewOutput;
+ KURL::List m_selectedImageFiles;
+
+ KIPI::Interface *m_interface;
+
+ // --------------------------------------------------------------------------------------------------------
+ // Standards fonctions
+
+ // Fonctions for ImageMAgick call implementations.
+
+ void processAborted(bool removeFlag=false); // Called when ImageMagick process is stopped by user.
+ void endPreview(void); // Called when preview process is done or stopped by user.
+
+ // Called for to parse the files overwriting mode selected by user.
+
+ int overwriteMode(void);
+
+ // Called for rename the target current image file name if already exist.
+
+ QString RenameTargetImageFile(QFileInfo *fi);
+
+ // Extract the arguments from a KProcess an merge that in a QString. Used by makeProcess for to
+ // show the command line arguments (debugging).
+
+ QString extractArguments(KProcess *proc);
+
+ // --------------------------------------------------------------------------------------------------------
+ // Standards virtuals fonctions for re-implementation.
+
+ // Called when ImageMagick process is started or for another re-implementation without
+ // ImageMagick calls (like 'RenameImages' plugin).
+
+ virtual bool startProcess(void);
+
+ // Called when ImageMagick process is done or stopped by user or for another re-implementation without
+ // ImageMagick calls (like 'RenameImages' plugin).
+
+ virtual void endProcess(void);
+
+ // Fonctions for ImageMagick implementation calls only.
+
+ // Called by 'startProcess' fonction at start. You can checking here some things about the current
+ // 'item' before the 'startprocess' fonction execution.
+
+ virtual bool prepareStartProcess(BatchProcessImagesItem */*item*/, const QString& /*albumDest*/) { return true; };
+
+ // Called for to contruct the ImageMagick command line used for to process or preview the image traitements.
+ // If 'albumDest' = 0L ==> preview process.
+
+ virtual QString makeProcess(KProcess* /*proc*/, BatchProcessImagesItem */*item*/,
+ const QString& /*albumDest*/ = QString::null,
+ bool /*previewMode*/ = false)
+ { return QString::null; };
+
+ virtual void processDone(){};
+
+ // Fonctions used for to read and to save the settings in the configuration file.
+
+ virtual void readSettings(void){};
+ virtual void saveSettings(void){};
+
+ // Called for add or update the list of images to process in the dialog.
+
+ virtual void listImageFiles(void);
+
+ // Called by 'listImageFiles' for renamed if necessary the target image file name.
+
+ virtual QString oldFileName2NewFileName(QString fileName)
+ { return (fileName); };
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // BATCHPROCESSIMAGESDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp b/kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp
new file mode 100644
index 0000000..caed54f
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/batchprocessimagesitem.cpp
@@ -0,0 +1,115 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qpainter.h>
+#include <qlistview.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+
+// Local includes
+
+#include "batchprocessimagesitem.h"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+BatchProcessImagesItem::BatchProcessImagesItem(QListView * parent, QString const & pathSrc,
+ QString const & nameSrc, QString const & nameDest, QString const & result)
+ : KListViewItem( parent, "", nameSrc, nameDest, result),
+ _pathSrc(pathSrc), _nameSrc(nameSrc), _nameDest(nameDest), _result(result),
+ _overwrote( false ),
+ _reverseSort( false )
+{
+ setText(0, pathSrc.section('/', -2, -2));
+}
+
+BatchProcessImagesItem::~BatchProcessImagesItem()
+{
+}
+
+QString BatchProcessImagesItem::pathSrc() { return _pathSrc; }
+QString BatchProcessImagesItem::nameSrc() { return _nameSrc; }
+QString BatchProcessImagesItem::nameDest() { return _nameDest; }
+QString BatchProcessImagesItem::result() { return _result; }
+QString BatchProcessImagesItem::error() { return _error; }
+QString BatchProcessImagesItem::outputMess() { return _outputMess; }
+
+void BatchProcessImagesItem::changeResult(QString text) { setText(3, text); }
+void BatchProcessImagesItem::changeError(QString text) { _error = text; }
+void BatchProcessImagesItem::changeNameDest(QString text) { _nameDest = text; setText(2, _nameDest); }
+void BatchProcessImagesItem::changeOutputMess(QString text) { _outputMess.append(text); }
+
+void BatchProcessImagesItem::paintCell (QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
+{
+ QColorGroup _cg( cg );
+
+ if (text(3) != i18n("OK") && !text(3).isEmpty() )
+ {
+ _cg.setColor( QColorGroup::Text, Qt::red );
+ KListViewItem::paintCell( p, _cg, column, width, alignment );
+ return;
+ }
+ if (text(3) == i18n("OK") )
+ {
+ _cg.setColor( QColorGroup::Text, Qt::darkGreen );
+ KListViewItem::paintCell( p, _cg, column, width, alignment );
+ return;
+ }
+
+ KListViewItem::paintCell( p, cg, column, width, alignment );
+}
+
+bool BatchProcessImagesItem::overWrote()
+{
+ return _overwrote;
+}
+
+void BatchProcessImagesItem::setDidOverWrite( bool b )
+{
+ _overwrote = b;
+}
+
+void BatchProcessImagesItem::setKey(const QString& val, bool reverseSort)
+{
+ _key = val;
+ _reverseSort = reverseSort;
+}
+
+QString BatchProcessImagesItem::key(int column, bool ) const
+{
+ if (_key.isNull())
+ return text(column);
+
+ return _key;
+}
+
+int BatchProcessImagesItem::compare(QListViewItem * i, int col, bool ascending) const
+{
+ int weight = _reverseSort ? -1 : 1;
+ return weight * key(col, ascending).localeAwareCompare(i->key( col, ascending));
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/batchprocessimagesitem.h b/kipi-plugins/batchprocessimages/batchprocessimagesitem.h
new file mode 100644
index 0000000..686ac89
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/batchprocessimagesitem.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 BATCHPROCESSIMAGESITEM_H
+#define BATCHPROCESSIMAGESITEM_H
+
+// Include files for Qt
+
+#include <qstring.h>
+#include <qobject.h>
+
+// Include files for KDE
+
+#include <klistview.h>
+
+class QPainter;
+class QListView;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesItem : public KListViewItem
+{
+public:
+
+ BatchProcessImagesItem(QListView * parent, QString const & pathSrc, QString const & nameSrc,
+ QString const & nameDest, QString const & result);
+
+ ~BatchProcessImagesItem();
+
+ QString pathSrc();
+ QString nameSrc();
+ QString nameDest();
+ QString result();
+ QString error();
+ QString outputMess();
+ bool overWrote();
+ void setDidOverWrite( bool b );
+
+ void changeResult(QString text);
+ void changeError(QString text);
+ void changeNameDest(QString text);
+ void changeOutputMess(QString text);
+
+ void paintCell (QPainter *p, const QColorGroup &cg, int column, int width, int alignment);
+
+ void setKey(const QString& val, bool reverseSort);
+ QString key(int column, bool ascending) const;
+ int compare (QListViewItem * i, int col, bool ascending) const;
+
+private:
+ QString _pathSrc;
+ QString _nameSrc;
+ QString _nameDest;
+ QString _result;
+ QString _error;
+ QString _outputMess;
+ bool _overwrote;
+ QString _key;
+ bool _reverseSort;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // BATCHPROCESSIMAGESITEM_H
diff --git a/kipi-plugins/batchprocessimages/batchprocessimageslist.cpp b/kipi-plugins/batchprocessimages/batchprocessimageslist.cpp
new file mode 100644
index 0000000..fd0e3fd
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/batchprocessimageslist.cpp
@@ -0,0 +1,113 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qevent.h>
+#include <qdragobject.h>
+#include <qstrlist.h>
+#include <qfileinfo.h>
+#include <qwhatsthis.h>
+#include <qlistview.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+
+// Local include files
+
+#include "batchprocessimageslist.h"
+#include "batchprocessimageslist.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+BatchProcessImagesList::BatchProcessImagesList(QWidget *parent, const char *name)
+ : KListView(parent, name)
+{
+ setAcceptDrops(true);
+ setDropVisualizer(false);
+ addColumn(i18n("Source Album"));
+ addColumn(i18n("Source Image"));
+ addColumn(i18n("Target Image"));
+ addColumn(i18n("Result"));
+ setSorting(3);
+ setItemMargin(3);
+ setResizeMode(QListView::LastColumn);
+ setSelectionMode(QListView::Single);
+ setAllColumnsShowFocus ( true );
+ QWhatsThis::add( this, i18n("<p>You can see here the operations' results "
+ "during the process. Double-click on an item for more "
+ "information once the process has ended. "
+ "<p>You can use the \"Add\" button or drag-and-drop "
+ "to add some new items to the list. "
+ "<p>If the items are taken from different Albums "
+ "the process' results will be merged to the target Album.") );
+}
+
+void BatchProcessImagesList::dragEnterEvent(QDragEnterEvent *e)
+{
+ e->accept(QUriDrag::canDecode(e));
+}
+
+bool BatchProcessImagesList::acceptDrag(QDropEvent* e) const
+{
+ return ( QUriDrag::canDecode(e) );
+}
+
+void BatchProcessImagesList::contentsDropEvent(QDropEvent* e)
+{
+ droppedImagesItems(e);
+}
+
+void BatchProcessImagesList::dropEvent(QDropEvent *e)
+{
+ droppedImagesItems(e);
+}
+
+void BatchProcessImagesList::droppedImagesItems(QDropEvent *e)
+{
+ QStrList strList;
+ QStringList FilesPath;
+
+ if ( !QUriDrag::decode(e, strList) ) return;
+
+ QStrList stringList;
+ QStrListIterator it(strList);
+ char *str;
+
+ while ( (str = it.current()) != 0 )
+ {
+ QString filePath = QUriDrag::uriToLocalFile(str);
+ QFileInfo fileInfo(filePath);
+
+ if (fileInfo.isFile() && fileInfo.exists())
+ FilesPath.append(fileInfo.filePath());
+
+ ++it;
+ }
+
+ if (FilesPath.isEmpty() == false)
+ emit addedDropItems(FilesPath);
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/batchprocessimageslist.h b/kipi-plugins/batchprocessimages/batchprocessimageslist.h
new file mode 100644
index 0000000..4c078c6
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/batchprocessimageslist.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 BATCHPROCESSIMAGE_H
+#define BATCHPROCESSIMAGE_H
+
+// Include files for Qt
+
+#include <qobject.h>
+
+// Include files for KDE
+
+#include <klistview.h>
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesList : public KListView
+{
+Q_OBJECT
+
+public:
+ BatchProcessImagesList(QWidget *parent=0, const char *name=0);
+
+signals:
+ void addedDropItems(QStringList filesPath);
+
+protected:
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dropEvent(QDropEvent* e);
+ bool acceptDrag(QDropEvent* e) const;
+ void contentsDropEvent(QDropEvent* e);
+ void droppedImagesItems(QDropEvent *e);
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif
diff --git a/kipi-plugins/batchprocessimages/borderimagesdialog.cpp b/kipi-plugins/batchprocessimages/borderimagesdialog.cpp
new file mode 100644
index 0000000..8ce5894
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/borderimagesdialog.cpp
@@ -0,0 +1,338 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kprocess.h>
+#include <kcolorbutton.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+// Local includes
+
+#include "pluginsversion.h"
+#include "kpaboutdata.h"
+#include "outputdialog.h"
+#include "imagepreview.h"
+#include "borderoptionsdialog.h"
+#include "borderimagesdialog.h"
+#include "borderimagesdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+BorderImagesDialog::BorderImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent )
+ : BatchProcessImagesDialog( urlList, interface, i18n("Batch-Bordering Images"), parent )
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch Image-bordering"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for batch bordering images\n"
+ "This plugin use the \"convert\" program from \"ImageMagick\" package."),
+ "(c) 2003-2008, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ //---------------------------------------------
+
+ m_nbItem = m_selectedImageFiles.count();
+
+ //---------------------------------------------
+
+ groupBox1->setTitle( i18n("Images Bordering Options") );
+
+ m_labelType->setText( i18n("Border:") );
+
+ m_Type->insertItem(i18n("Solid"));
+
+ // Niepce is Real name. This is the first guy in the world to have build a camera.
+ m_Type->insertItem("Niepce");
+
+ m_Type->insertItem(i18n("Raise"));
+ m_Type->insertItem(i18n("Frame"));
+ m_Type->setCurrentText(i18n("Niepce"));
+ whatsThis = i18n("<p>Select here the border type for your images:<p>"
+ "<b>Solid</b>: just surround the images with a line.<p>"
+ "<b>Niepce</b>: surround the images with a fine line and a large border "
+ "(ideal for black and white pictures).<p>"
+ "<b>Raise</b>: creating a 3D effect around the images.<p>"
+ "<b>Frame</b>: surround the images with an ornamental border.<p>");
+
+ QWhatsThis::add( m_Type, whatsThis );
+
+ //---------------------------------------------
+
+ readSettings();
+ listImageFiles();
+}
+
+BorderImagesDialog::~BorderImagesDialog()
+{
+ delete m_about;
+}
+
+void BorderImagesDialog::slotHelp( void )
+{
+ KApplication::kApplication()->invokeHelp("borderimages", "kipi-plugins");
+}
+
+void BorderImagesDialog::slotOptionsClicked(void)
+{
+ int Type = m_Type->currentItem();
+ BorderOptionsDialog *optionsDialog = new BorderOptionsDialog(this, Type);
+
+ if ( Type == 0 ) // Solid
+ {
+ optionsDialog->m_solidBorderWidth->setValue(m_solidWidth);
+ optionsDialog->m_button_solidBorderColor->setColor(m_solidColor);
+ }
+ if ( Type == 1 ) // Niepce
+ {
+ optionsDialog->m_lineNiepceBorderWidth->setValue(m_lineNiepceWidth);
+ optionsDialog->m_button_lineNiepceBorderColor->setColor(m_lineNiepceColor);
+ optionsDialog->m_NiepceBorderWidth->setValue(m_NiepceWidth);
+ optionsDialog->m_button_NiepceBorderColor->setColor(m_NiepceColor);
+ }
+ if ( Type == 2 ) // Raise
+ {
+ optionsDialog->m_raiseBorderWidth->setValue(m_raiseWidth);
+ }
+ if ( Type == 3 ) // Frame
+ {
+ optionsDialog->m_frameBorderWidth->setValue(m_frameWidth);
+ optionsDialog->m_frameBevelBorderWidth->setValue(m_bevelWidth);
+ optionsDialog->m_button_frameBorderColor->setColor(m_frameColor);
+ }
+
+ if ( optionsDialog->exec() == KMessageBox::Ok )
+ {
+ if ( Type == 0 ) // Solid
+ {
+ m_solidWidth = optionsDialog->m_solidBorderWidth->value();
+ m_solidColor = optionsDialog->m_button_solidBorderColor->color();
+ }
+ if ( Type == 1 ) // Niepce
+ {
+ m_lineNiepceWidth = optionsDialog->m_lineNiepceBorderWidth->value();
+ m_lineNiepceColor = optionsDialog->m_button_lineNiepceBorderColor->color();
+ m_NiepceWidth = optionsDialog->m_NiepceBorderWidth->value();
+ m_NiepceColor = optionsDialog->m_button_NiepceBorderColor->color();
+ }
+ if ( Type == 2 ) // Raise
+ {
+ m_raiseWidth = optionsDialog->m_raiseBorderWidth->value();
+ }
+ if ( Type == 3 ) // Frame
+ {
+ m_frameWidth = optionsDialog->m_frameBorderWidth->value();
+ m_bevelWidth = optionsDialog->m_frameBevelBorderWidth->value();
+ m_frameColor = optionsDialog->m_button_frameBorderColor->color();
+ }
+ }
+
+ delete optionsDialog;
+}
+
+void BorderImagesDialog::readSettings(void)
+{
+ // Read all settings from configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("BorderImages Settings");
+
+ m_Type->setCurrentItem(m_config->readNumEntry("BorderType", 1)); // Niepce per default.
+ QColor *ColorBlack = new QColor( 0, 0, 0 );
+ QColor *ColorWhite = new QColor( 255, 255, 255 );
+ m_solidWidth = m_config->readNumEntry("SolidWidth", 25);
+ m_solidColor = m_config->readColorEntry("SolidColor", ColorBlack);
+
+ m_lineNiepceWidth = m_config->readNumEntry("LineNiepceWidth", 10);
+ m_lineNiepceColor = m_config->readColorEntry("LineNiepceColor", ColorBlack);
+ m_NiepceWidth = m_config->readNumEntry("NiepceWidth", 100);
+ m_NiepceColor = m_config->readColorEntry("NiepceColor", ColorWhite);
+
+ m_raiseWidth = m_config->readNumEntry("RaiseWidth", 50);
+
+ m_frameWidth = m_config->readNumEntry("FrameWidth", 25);
+ m_bevelWidth = m_config->readNumEntry("BevelWidth", 10);
+ m_frameColor = m_config->readColorEntry("FrameColor", ColorBlack);
+
+ if (m_config->readEntry("SmallPreview", "true") == "true")
+ m_smallPreview->setChecked( true );
+ else
+ m_smallPreview->setChecked( false );
+
+ m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default...
+
+ if (m_config->readEntry("RemoveOriginal", "false") == "true")
+ m_removeOriginal->setChecked( true );
+ else
+ m_removeOriginal->setChecked( false );
+
+ delete ColorWhite;
+ delete ColorBlack;
+ delete m_config;
+}
+
+void BorderImagesDialog::saveSettings(void)
+{
+ // Write all settings in configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("BorderImages Settings");
+ m_config->writeEntry("BorderType", m_Type->currentItem());
+
+ m_config->writeEntry("SolidWidth", m_solidWidth);
+ m_config->writeEntry("SolidColor", m_solidColor);
+
+ m_config->writeEntry("LineNiepceWidth", m_lineNiepceWidth);
+ m_config->writeEntry("LineNiepceColor", m_lineNiepceColor);
+ m_config->writeEntry("NiepceWidth", m_NiepceWidth);
+ m_config->writeEntry("NiepceColor", m_NiepceColor);
+
+ m_config->writeEntry("RaiseWidth", m_raiseWidth);
+
+ m_config->writeEntry("FrameWidth", m_frameWidth);
+ m_config->writeEntry("BevelWidth", m_bevelWidth);
+ m_config->writeEntry("FrameColor", m_frameColor);
+
+ m_config->writeEntry("SmallPreview", m_smallPreview->isChecked());
+ m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem());
+ m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked());
+
+ m_config->sync();
+
+ delete m_config;
+}
+
+QString BorderImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode)
+{
+ *proc << "convert";
+
+ if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled !
+ {
+ *m_PreviewProc << "-crop" << "300x300+0+0";
+ m_previewOutput.append( " -crop 300x300+0+0 ");
+ }
+
+ if (m_Type->currentItem() == 0) // Solid
+ {
+ *proc << "-border";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_solidWidth ) + "x";
+ Temp2.append(Temp.setNum( m_solidWidth ));
+ *proc << Temp2;
+ *proc << "-bordercolor";
+ Temp2 = "rgb(" + Temp.setNum(m_solidColor.red()) + ",";
+ Temp2.append(Temp.setNum(m_solidColor.green()) + ",");
+ Temp2.append(Temp.setNum(m_solidColor.blue()) + ")");
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 1) // Niepce
+ {
+ QString Temp, Temp2;
+
+ *proc << "-border";
+ Temp2 = Temp.setNum( m_lineNiepceWidth ) + "x";
+ Temp2.append(Temp.setNum( m_lineNiepceWidth ));
+ *proc << Temp2;
+
+ *proc << "-bordercolor";
+ Temp2 = "rgb(" + Temp.setNum(m_NiepceColor.red()) + ",";
+ Temp2.append(Temp.setNum(m_NiepceColor.green()) + ",");
+ Temp2.append(Temp.setNum(m_NiepceColor.blue()) + ")");
+ *proc << Temp2;
+
+ *proc << "-border";
+ Temp2 = Temp.setNum( m_NiepceWidth ) + "x";
+ Temp2.append(Temp.setNum( m_NiepceWidth ));
+ *proc << Temp2;
+
+ *proc << "-bordercolor";
+ Temp2 = "rgb(" + Temp.setNum(m_lineNiepceColor.red()) + ",";
+ Temp2.append(Temp.setNum(m_lineNiepceColor.green()) + ",");
+ Temp2.append(Temp.setNum(m_lineNiepceColor.blue()) + ")");
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 2) // Raise
+ {
+ *proc << "-raise";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_raiseWidth ) + "x";
+ Temp2.append(Temp.setNum( m_raiseWidth ));
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 3) // Frame
+ {
+ *proc << "-frame";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_frameWidth ) + "x";
+ Temp2.append(Temp.setNum( m_frameWidth ) + "+");
+ Temp2.append(Temp.setNum( m_bevelWidth ) + "+");
+ Temp2.append(Temp.setNum( m_bevelWidth ) );
+ *proc << Temp2;
+ *proc << "-mattecolor";
+ Temp2 = "rgb(" + Temp.setNum(m_frameColor.red()) + ",";
+ Temp2.append(Temp.setNum(m_frameColor.green()) + ",");
+ Temp2.append(Temp.setNum(m_frameColor.blue()) + ")");
+ *proc << Temp2;
+ }
+
+ *proc << "-verbose";
+
+ *proc << item->pathSrc();
+
+ if ( !previewMode ) // No preview mode !
+ *proc << albumDest + "/" + item->nameDest();
+
+ return(extractArguments(proc));
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/borderimagesdialog.h b/kipi-plugins/batchprocessimages/borderimagesdialog.h
new file mode 100644
index 0000000..f0cd7aa
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/borderimagesdialog.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 BORDERIMAGESDIALOG_H
+#define BORDERIMAGESDIALOG_H
+
+// Local includes
+
+#include "batchprocessimagesdialog.h"
+#include "kpaboutdata.h"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesItem;
+
+class BorderImagesDialog : public BatchProcessImagesDialog
+{
+Q_OBJECT
+
+ public:
+
+ BorderImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 );
+ ~BorderImagesDialog();
+
+ private slots:
+
+ void slotHelp(void);
+ void slotOptionsClicked(void);
+
+ protected:
+
+ int m_solidWidth;
+ QColor m_solidColor;
+
+ int m_lineNiepceWidth;
+ QColor m_lineNiepceColor;
+ int m_NiepceWidth;
+ QColor m_NiepceColor;
+
+ int m_raiseWidth;
+
+ int m_frameWidth;
+ int m_bevelWidth;
+ QColor m_frameColor;
+
+ QString makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode);
+
+ void readSettings(void);
+ void saveSettings(void);
+
+ private:
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // BORDERIMAGESDIALOG_H
+
diff --git a/kipi-plugins/batchprocessimages/borderoptionsdialog.cpp b/kipi-plugins/batchprocessimages/borderoptionsdialog.cpp
new file mode 100644
index 0000000..bc69173
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/borderoptionsdialog.cpp
@@ -0,0 +1,160 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qwidget.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qstring.h>
+#include <qcombobox.h>
+#include <qcolor.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kcolorbutton.h>
+
+// Local includes
+
+#include "borderoptionsdialog.h"
+#include "borderoptionsdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+BorderOptionsDialog::BorderOptionsDialog(QWidget *parent, int BorderType)
+ : KDialogBase( parent, "BorderOptionsDialog", true,
+ i18n("Border Options"), Ok|Cancel, Ok, false)
+{
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() );
+ QString whatsThis;
+
+ if (BorderType == 0) // Solid
+ {
+ QLabel *m_label_solidBorderWidth = new QLabel (i18n("Border width:"), box);
+ dvlay->addWidget( m_label_solidBorderWidth );
+ m_solidBorderWidth = new KIntNumInput(25, box);
+ m_solidBorderWidth->setRange(1, 1000, 1, true );
+ QWhatsThis::add( m_solidBorderWidth, i18n("<p>Select here the border width in pixels.") );
+ m_label_solidBorderWidth->setBuddy( m_solidBorderWidth );
+ dvlay->addWidget( m_solidBorderWidth );
+
+ QLabel *m_label_solidColor = new QLabel(i18n("Border color:"), box);
+ dvlay->addWidget( m_label_solidColor );
+ QColor solidBorderColor = QColor( 0, 0, 0 ); // Black per default.
+ m_button_solidBorderColor = new KColorButton( solidBorderColor, box );
+ QWhatsThis::add( m_button_solidBorderColor, i18n( "<p>You can select here the border color." ));
+ dvlay->addWidget( m_button_solidBorderColor );
+ }
+
+ if (BorderType == 1) // Niepce
+ {
+ QLabel *m_label_lineNiepceBorderWidth = new QLabel (i18n("Line border width:"), box);
+ dvlay->addWidget( m_label_lineNiepceBorderWidth );
+ m_lineNiepceBorderWidth = new KIntNumInput(10, box);
+ m_lineNiepceBorderWidth->setRange(1, 500, 1, true );
+ QWhatsThis::add( m_lineNiepceBorderWidth, i18n("<p>Select here the line border width in pixels.") );
+ m_label_lineNiepceBorderWidth->setBuddy( m_lineNiepceBorderWidth );
+ dvlay->addWidget( m_lineNiepceBorderWidth );
+
+ QLabel *m_label_lineNiepceColor = new QLabel(i18n("Line border color:"), box);
+ dvlay->addWidget( m_label_lineNiepceColor );
+ QColor lineNiepceBorderColor = QColor( 0, 0, 0 ); // Black per default.
+ m_button_lineNiepceBorderColor = new KColorButton( lineNiepceBorderColor, box );
+ QWhatsThis::add( m_button_lineNiepceBorderColor, i18n( "<p>You can select here the line border color." ));
+ dvlay->addWidget( m_button_lineNiepceBorderColor );
+
+ QLabel *m_label_NiepceBorderWidth = new QLabel (i18n("Border width:"), box);
+ dvlay->addWidget( m_label_NiepceBorderWidth );
+ m_NiepceBorderWidth = new KIntNumInput(100, box);
+ m_NiepceBorderWidth->setRange(1, 500, 1, true );
+ QWhatsThis::add( m_NiepceBorderWidth, i18n("<p>Select here the border width in pixels.") );
+ m_label_NiepceBorderWidth->setBuddy( m_NiepceBorderWidth );
+ dvlay->addWidget( m_NiepceBorderWidth );
+
+ QLabel *m_label_NiepceColor = new QLabel(i18n("Border color:"), box);
+ dvlay->addWidget( m_label_NiepceColor );
+ QColor NiepceBorderColor = QColor( 255, 255, 255 ); // White per default.
+ m_button_NiepceBorderColor = new KColorButton( NiepceBorderColor, box );
+ QWhatsThis::add( m_button_NiepceBorderColor, i18n( "<p>You can select here the border color." ));
+ dvlay->addWidget( m_button_NiepceBorderColor );
+ }
+
+ if (BorderType == 2) // Raise
+ {
+ QLabel *m_label_raiseBorderWidth = new QLabel (i18n("Border width:"), box);
+ dvlay->addWidget( m_label_raiseBorderWidth );
+ m_raiseBorderWidth = new KIntNumInput(50, box);
+ m_raiseBorderWidth->setRange(1, 500, 1, true );
+ QWhatsThis::add( m_raiseBorderWidth, i18n("<p>Select here the border width in pixels.") );
+ m_label_raiseBorderWidth->setBuddy( m_raiseBorderWidth );
+ dvlay->addWidget( m_raiseBorderWidth );
+ }
+
+ if (BorderType == 3) // Frame
+ {
+ QLabel *m_label_frameBorderWidth = new QLabel (i18n("Border width:"), box);
+ dvlay->addWidget( m_label_frameBorderWidth );
+ m_frameBorderWidth = new KIntNumInput(25, box);
+ m_frameBorderWidth->setRange(0, 500, 1, true );
+ QWhatsThis::add( m_frameBorderWidth, i18n("<p>Select here the border width in pixels.") );
+ m_label_frameBorderWidth->setBuddy( m_frameBorderWidth );
+ dvlay->addWidget( m_frameBorderWidth );
+
+ QLabel *m_label_frameBevelBorderWidth = new QLabel (i18n("Bevel width:"), box);
+ dvlay->addWidget( m_label_frameBevelBorderWidth );
+ m_frameBevelBorderWidth = new KIntNumInput(10, box);
+ m_frameBevelBorderWidth->setRange(0, 250, 1, true );
+ QWhatsThis::add( m_frameBevelBorderWidth, i18n("<p>Select here the bevel width in pixels. "
+ "This value must be <= Border width / 2") );
+ m_label_frameBevelBorderWidth->setBuddy( m_frameBevelBorderWidth );
+ dvlay->addWidget( m_frameBevelBorderWidth );
+
+ QLabel *m_label_frameColor = new QLabel(i18n("Border color:"), box);
+ dvlay->addWidget( m_label_frameColor );
+ QColor frameBorderColor = QColor( 0, 0, 0 ); // Black per default.
+ m_button_frameBorderColor = new KColorButton( frameBorderColor, box );
+ QWhatsThis::add( m_button_frameBorderColor, i18n( "<p>You can select here the border color." ));
+ dvlay->addWidget( m_button_frameBorderColor );
+
+ connect(m_frameBorderWidth, SIGNAL(valueChanged(int)), this, SLOT(slotFrameBorderWidthChanged(int)));
+ }
+}
+
+BorderOptionsDialog::~BorderOptionsDialog()
+{
+}
+
+void BorderOptionsDialog::slotFrameBorderWidthChanged (int value)
+{
+ m_frameBevelBorderWidth->setMaxValue((int)(value / 2));
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/borderoptionsdialog.h b/kipi-plugins/batchprocessimages/borderoptionsdialog.h
new file mode 100644
index 0000000..3f2f514
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/borderoptionsdialog.h
@@ -0,0 +1,64 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 BORDEROPTIONSDIALOG_H
+#define BORDEROPTIONSDIALOG_H
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+class KIntNumInput;
+class KColorButton;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BorderOptionsDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+ BorderOptionsDialog(QWidget *parent=0, int BorderType = 0);
+ ~BorderOptionsDialog();
+
+ KIntNumInput *m_solidBorderWidth;
+ KColorButton *m_button_solidBorderColor;
+
+ KIntNumInput *m_lineNiepceBorderWidth;
+ KColorButton *m_button_lineNiepceBorderColor;
+ KIntNumInput *m_NiepceBorderWidth;
+ KColorButton *m_button_NiepceBorderColor;
+
+ KIntNumInput *m_raiseBorderWidth;
+
+ KIntNumInput *m_frameBorderWidth;
+ KIntNumInput *m_frameBevelBorderWidth;
+ KColorButton *m_button_frameBorderColor;
+
+ private slots:
+ void slotFrameBorderWidthChanged (int value);
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // BORDEROPTIONSDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/colorimagesdialog.cpp b/kipi-plugins/batchprocessimages/colorimagesdialog.cpp
new file mode 100644
index 0000000..33be98e
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/colorimagesdialog.cpp
@@ -0,0 +1,325 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kprocess.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+// Local includes
+
+#include "pluginsversion.h"
+#include "kpaboutdata.h"
+#include "coloroptionsdialog.h"
+#include "outputdialog.h"
+#include "imagepreview.h"
+#include "colorimagesdialog.h"
+#include "colorimagesdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+ColorImagesDialog::ColorImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent )
+ : BatchProcessImagesDialog( urlList, interface, i18n("Batch Image-Color Processing"), parent )
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch image-color enhancement"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for batch image-color enhancement\n"
+ "This plugin use the \"convert\" program from \"ImageMagick\" package."),
+ "(c) 2003-2007, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ //---------------------------------------------
+
+ m_nbItem = m_selectedImageFiles.count();
+
+ //---------------------------------------------
+
+ groupBox1->setTitle( i18n("Image Coloring Options") );
+
+ m_labelType->setText( i18n("Filter:") );
+
+ m_Type->insertItem(i18n("Decrease Contrast"));
+ m_Type->insertItem(i18n("Depth")); // 1
+ m_Type->insertItem(i18n("Equalize"));
+ m_Type->insertItem(i18n("Fuzz")); // 3
+ m_Type->insertItem(i18n("Gray Scales"));
+ m_Type->insertItem(i18n("Increase Contrast"));
+ m_Type->insertItem(i18n("Monochrome"));
+ m_Type->insertItem(i18n("Negate"));
+ m_Type->insertItem(i18n("Normalize"));
+ m_Type->insertItem(i18n("Segment")); // 9
+ m_Type->insertItem(i18n("Trim"));
+ m_Type->setCurrentText(i18n("Normalize"));
+ whatsThis = i18n("<p>Select here the color enhancement type for your images:<p>"
+ "<b>Decrease contrast</b>: reduce the image contrast. The algorithm "
+ "reduces the intensity difference between the lighter and darker elements "
+ "of the image.<p>"
+ "<b>Depth</b>: change the color depth of the image.<p>"
+ "<b>Equalize</b>: perform histogram equalization to the image.<p>"
+ "<b>Fuzz</b>: merging colors within a distance, i.e. consider them to be equal.<p>"
+ "<b>Gray scales</b>: convert color images to grayscale images.<p>"
+ "<b>Increase contrast</b>: enhance the image contrast. The algorithm enhances "
+ "the intensity differences between the lighter and darker elements of the image.<p>"
+ "<b>Monochrome</b>: transform the image to black and white.<p>"
+ "<b>Negate</b>: replace every pixel with its complementary color. The red, green, "
+ "and blue intensities of an image are negated. White becomes black, yellow becomes "
+ "blue, etc.<p>"
+ "<b>Normalize</b>: transform image to span the full range of color values. "
+ "This is a contrast enhancement technique. The algorithm enhances the contrast "
+ "of a colored image by adjusting the pixels color to span the entire range of "
+ "colors available.<p>"
+ "<b>Segment</b>: segment an image by analyzing the histograms of the color "
+ "components and identifying units that are homogeneous with the fuzzy c-means "
+ "technique.<p>"
+ "<b>Trim</b>: trim an image (fuzz reverse technic). The algorithm remove edges "
+ "that are the background color from the image.<p>");
+
+ QWhatsThis::add( m_Type, whatsThis );
+
+ //---------------------------------------------
+
+ readSettings();
+ listImageFiles();
+ slotTypeChanged(m_Type->currentItem());
+}
+
+ColorImagesDialog::~ColorImagesDialog()
+{
+ delete m_about;
+}
+
+void ColorImagesDialog::slotHelp( void )
+{
+ KApplication::kApplication()->invokeHelp("colorimages",
+ "kipi-plugins");
+}
+
+void ColorImagesDialog::slotTypeChanged(int type)
+{
+ if ( type == 1 || // Depth
+ type == 3 || // Fuzz
+ type == 9 // Segment
+ )
+ m_optionsButton->setEnabled(true);
+ else
+ m_optionsButton->setEnabled(false);
+}
+
+void ColorImagesDialog::slotOptionsClicked(void)
+{
+ int Type = m_Type->currentItem();
+ ColorOptionsDialog *optionsDialog = new ColorOptionsDialog(this, Type);
+
+ if ( Type == 1) // Depth
+ optionsDialog->m_depthValue->setCurrentText(m_depthValue);
+
+ if ( Type == 3) // Fuzz
+ optionsDialog->m_fuzzDistance->setValue(m_fuzzDistance);
+
+ if ( Type == 9) // Segment
+ {
+ optionsDialog->m_segmentCluster->setValue(m_segmentCluster);
+ optionsDialog->m_segmentSmooth->setValue(m_segmentSmooth);
+ }
+
+ if ( optionsDialog->exec() == KMessageBox::Ok )
+ {
+ if ( Type == 1) // Depth
+ m_depthValue = optionsDialog->m_depthValue->currentText();
+
+ if ( Type == 3) // Fuzz
+ m_fuzzDistance = optionsDialog->m_fuzzDistance->value();
+
+ if ( Type == 9) // Segment
+ {
+ m_segmentCluster = optionsDialog->m_segmentCluster->value();
+ m_segmentSmooth = optionsDialog->m_segmentSmooth->value();
+ }
+ }
+
+ delete optionsDialog;
+}
+
+void ColorImagesDialog::readSettings(void)
+{
+ // Read all settings from configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("ColorImages Settings");
+
+ m_Type->setCurrentItem(m_config->readNumEntry("ColorType", 8)); // Normalize per default.
+ m_depthValue = m_config->readEntry("DepthValue", "32");
+ m_fuzzDistance = m_config->readNumEntry("FuzzDistance", 3);
+ m_segmentCluster = m_config->readNumEntry("SegmentCluster", 3);
+ m_segmentSmooth = m_config->readNumEntry("SegmentSmooth", 3);
+
+ if (m_config->readEntry("SmallPreview", "true") == "true")
+ m_smallPreview->setChecked( true );
+ else
+ m_smallPreview->setChecked( false );
+
+ m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default...
+
+ if (m_config->readEntry("RemoveOriginal", "false") == "true")
+ m_removeOriginal->setChecked( true );
+ else
+ m_removeOriginal->setChecked( false );
+
+ delete m_config;
+}
+
+void ColorImagesDialog::saveSettings(void)
+{
+ // Write all settings in configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("ColorImages Settings");
+
+ m_config->writeEntry("ColorType", m_Type->currentItem());
+ m_config->writeEntry("DepthValue", m_depthValue);
+ m_config->writeEntry("FuzzDistance", m_fuzzDistance);
+ m_config->writeEntry("SegmentCluster", m_segmentCluster);
+ m_config->writeEntry("SegmentSmooth", m_segmentSmooth);
+
+ m_config->writeEntry("SmallPreview", m_smallPreview->isChecked());
+ m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem());
+ m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked());
+
+ m_config->sync();
+
+ delete m_config;
+}
+
+QString ColorImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode)
+{
+ *proc << "convert";
+
+ if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled !
+ {
+ *m_PreviewProc << "-crop" << "300x300+0+0";
+ m_previewOutput.append( " -crop 300x300+0+0 ");
+ }
+
+ if (m_Type->currentItem() == 0) // Decrease contrast"
+ {
+ *proc << "-contrast";
+ }
+
+ if (m_Type->currentItem() == 1) // Depth
+ {
+ *proc << "-depth" << m_depthValue;
+ }
+
+ if (m_Type->currentItem() == 2) // Equalize
+ {
+ *proc << "-equalize";
+ }
+
+ if (m_Type->currentItem() == 3) // Fuzz
+ {
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_fuzzDistance );
+ *proc << "-fuzz" << Temp2;
+ }
+
+ if (m_Type->currentItem() == 4) // Gray scales
+ {
+ *proc << "-type";
+ *proc << "Grayscale";
+ }
+
+ if (m_Type->currentItem() == 5) // Increase contrast
+ {
+ *proc << "+contrast";
+ }
+
+ if (m_Type->currentItem() == 6) // Monochrome
+ {
+ *proc << "-monochrome";
+ }
+
+ if (m_Type->currentItem() == 7) // Negate
+ {
+ *proc << "-negate";
+ }
+
+ if (m_Type->currentItem() == 8) // Normalize
+ {
+ *proc << "-normalize";
+ }
+
+ if (m_Type->currentItem() == 9) // Segment
+ {
+ *proc << "-segment";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_segmentCluster ) + "x";
+ Temp2.append (Temp.setNum( m_segmentSmooth ));
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 10) // Trim
+ {
+ *proc << "-trim";
+ }
+
+ *proc << "-verbose";
+
+ *proc << item->pathSrc();
+
+ if ( !previewMode ) // No preview mode !
+ {
+ *proc << albumDest + "/" + item->nameDest();
+ }
+
+ return(extractArguments(proc));
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/colorimagesdialog.h b/kipi-plugins/batchprocessimages/colorimagesdialog.h
new file mode 100644
index 0000000..2feeb4c
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/colorimagesdialog.h
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 COLORIMAGESDIALOG_H
+#define COLORIMAGESDIALOG_H
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "batchprocessimagesdialog.h"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesItem;
+
+class ColorImagesDialog : public BatchProcessImagesDialog
+{
+Q_OBJECT
+
+ public:
+
+ ColorImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 );
+ ~ColorImagesDialog();
+
+ private slots:
+
+ void slotHelp(void);
+ void slotOptionsClicked(void);
+ void slotTypeChanged(int type);
+
+ protected:
+
+ QString m_depthValue;
+ int m_fuzzDistance;
+ int m_segmentCluster;
+ int m_segmentSmooth;
+
+ QString makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode);
+
+ void readSettings(void);
+ void saveSettings(void);
+
+ private:
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // COLORIMAGESDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/coloroptionsdialog.cpp b/kipi-plugins/batchprocessimages/coloroptionsdialog.cpp
new file mode 100644
index 0000000..bd08870
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/coloroptionsdialog.cpp
@@ -0,0 +1,112 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qwidget.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qcombobox.h>
+#include <qcolor.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kcolorbutton.h>
+
+// Local includes
+
+#include "coloroptionsdialog.h"
+#include "coloroptionsdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+ColorOptionsDialog::ColorOptionsDialog(QWidget *parent, int ColorType)
+ : KDialogBase( parent, "ColorOptionsDialog", true,
+ i18n("Color Options"), Ok|Cancel, Ok, false)
+{
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() );
+ QString whatsThis;
+
+ if (ColorType == 1) // Depth
+ {
+ QLabel *m_label_depthValue = new QLabel (i18n("Depth value:"), box);
+ dvlay->addWidget( m_label_depthValue );
+ m_depthValue = new QComboBox( false, box );
+ m_depthValue->insertItem("8");
+ m_depthValue->insertItem("16");
+ m_depthValue->insertItem("32");
+ QWhatsThis::add( m_depthValue, i18n("<p>Select here the image depth in bits.") );
+ m_label_depthValue->setBuddy( m_depthValue );
+ dvlay->addWidget( m_depthValue );
+ }
+
+ if (ColorType == 3) // Fuzz
+ {
+ QLabel *m_label_fuzzDistance = new QLabel (i18n("Distance:"), box);
+ dvlay->addWidget( m_label_fuzzDistance );
+ m_fuzzDistance = new KIntNumInput(3, box);
+ m_fuzzDistance->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_fuzzDistance, i18n("<p>Select here the fuzz distance in "
+ "absolute intensity units.") );
+ m_label_fuzzDistance->setBuddy( m_fuzzDistance );
+ dvlay->addWidget( m_fuzzDistance );
+ }
+
+ if (ColorType == 9) // Segment
+ {
+ QLabel *m_label_segmentCluster = new QLabel (i18n("Cluster threshold:"), box);
+ dvlay->addWidget( m_label_segmentCluster );
+ m_segmentCluster = new KIntNumInput(3, box);
+ m_segmentCluster->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_segmentCluster, i18n("<p>Select here the value which represents the minimum "
+ "number of pixels contained in a hexahedra before it can "
+ "be considered valid.") );
+ m_label_segmentCluster->setBuddy( m_segmentCluster );
+ dvlay->addWidget( m_segmentCluster );
+
+ QLabel *m_label_segmentSmooth = new QLabel (i18n("Smooth threshold:"), box);
+ dvlay->addWidget( m_label_segmentSmooth );
+ m_segmentSmooth = new KIntNumInput(3, box);
+ m_segmentSmooth->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_segmentSmooth, i18n("<p>Select here the value which eliminates noise in the "
+ "second derivative of the histogram. As the value is increased, "
+ "you can expect a smoother second derivative.") );
+ m_label_segmentSmooth->setBuddy( m_segmentSmooth );
+ dvlay->addWidget( m_segmentSmooth );
+ }
+}
+
+ColorOptionsDialog::~ColorOptionsDialog()
+{
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/coloroptionsdialog.h b/kipi-plugins/batchprocessimages/coloroptionsdialog.h
new file mode 100644
index 0000000..7445d7f
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/coloroptionsdialog.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 COLOROPTIONSDIALOG_H
+#define COLOROPTIONSDIALOG_H
+
+// Include files for Qt
+
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+class QComboBox;
+
+class KIntNumInput;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class ColorOptionsDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+ ColorOptionsDialog(QWidget *parent=0, int ColorType = 0);
+ ~ColorOptionsDialog();
+
+ QComboBox *m_depthValue;
+
+ KIntNumInput *m_fuzzDistance;
+
+ KIntNumInput *m_segmentCluster;
+ KIntNumInput *m_segmentSmooth;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // COLOROPTIONSDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/convertimagesdialog.cpp b/kipi-plugins/batchprocessimages/convertimagesdialog.cpp
new file mode 100644
index 0000000..6947f2f
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/convertimagesdialog.cpp
@@ -0,0 +1,376 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kprocess.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kurlrequester.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes
+
+#include "pluginsversion.h"
+#include "kpaboutdata.h"
+#include "convertoptionsdialog.h"
+#include "outputdialog.h"
+#include "convertimagesdialog.h"
+#include "convertimagesdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+ConvertImagesDialog::ConvertImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent )
+ : BatchProcessImagesDialog( urlList, interface, i18n("Batch Convert Images"), parent )
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch convert images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for batch converting images\n"
+ "This plugin uses the \"convert\" program from \"ImageMagick\" package."),
+ "(c) 2003-2007, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ //---------------------------------------------
+
+ groupBox1->setTitle( i18n("Image Conversion Options") );
+
+ m_labelType->setText( i18n("Format:") );
+
+ m_Type->insertItem("JPEG");
+ m_Type->insertItem("PNG");
+ m_Type->insertItem("TIFF");
+ m_Type->insertItem("PPM");
+ m_Type->insertItem("BMP");
+ m_Type->insertItem("TGA");
+ m_Type->insertItem("EPS");
+ m_Type->setCurrentText("JPEG");
+ whatsThis = i18n("<p>Select here the target image file format.<p>");
+ whatsThis = whatsThis + i18n("<b>JPEG</b>: The Joint Photographic Experts Group's file format is a "
+ "good Web file format but it uses lossy data compression.<p>"
+ "<b>PNG</b>: the Portable Network Graphics format is an extensible file "
+ "format for the lossless, portable, well-compressed storage of raster images. "
+ "PNG provides a patent-free replacement for GIF and can also replace many common "
+ "uses of TIFF. PNG is designed to work well in online viewing applications, such "
+ "as the World Wide Web, so it is fully streamable with a progressive display "
+ "option. Also, PNG can store gamma and chromaticity data for improved color "
+ "matching on heterogeneous platforms.");
+ whatsThis = whatsThis + i18n("<p><b>TIFF</b>: the Tag Image File Format is a rather old standard that is "
+ "still very popular today. It is a highly flexible and platform-independent "
+ "format which is supported by numerous image processing applications and "
+ "virtually all prepress software on the market.");
+ whatsThis = whatsThis + i18n("<p><b>PPM</b>: the Portable Pixel Map file format is used as an "
+ "intermediate format for storing color bitmap information. PPM files "
+ "may be either binary or ASCII and store pixel values up to 24 bits in size. "
+ "This format generate the largest-sized text files to encode images without "
+ "losing quality");
+ whatsThis = whatsThis + i18n("<p><b>BMP</b>: the BitMaP file format is a popular image format from Win32 "
+ "environment. It efficiently stores mapped or unmapped RGB graphics data with "
+ "pixels 1-, 4-, 8-, or 24-bits in size. Data may be stored raw or compressed "
+ "using a 4-bit or 8-bit RLE data compression algorithm. BMP is an excellent "
+ "choice for a simple bitmap format which supports a wide range of RGB image "
+ "data.");
+ whatsThis = whatsThis + i18n("<p><b>TGA</b>: the TarGA image file format is one of the most widely used "
+ "bitmap file formats for storage of 24 and 32 bits truecolor images. "
+ "TGA supports colormaps, alpha channel, gamma value, postage stamp image, "
+ "textual information, and developer-definable data.");
+ whatsThis = whatsThis + i18n("<p><b>EPS</b>: the Adobe Encapsulated PostScript image file format "
+ "is a PostScript language program describing the appearance of a single page. "
+ "Usually, the purpose of the EPS file is to be embedded inside another PostScript "
+ "language page description.");
+
+ QWhatsThis::add( m_Type, whatsThis );
+
+ m_previewButton->hide();
+ m_smallPreview->hide();
+
+ //---------------------------------------------
+
+ readSettings();
+ slotTypeChanged(m_Type->currentItem());
+}
+
+ConvertImagesDialog::~ConvertImagesDialog()
+{
+ delete m_about;
+}
+
+void ConvertImagesDialog::slotHelp( void )
+{
+ KApplication::kApplication()->invokeHelp("convertimages", "kipi-plugins");
+}
+
+void ConvertImagesDialog::slotTypeChanged(int type)
+{
+ if ( type == 3 || type == 4 || type == 6 ) // PPM || BMP || EPS
+ m_optionsButton->setEnabled(false);
+ else
+ m_optionsButton->setEnabled(true);
+
+ m_listFiles->clear();
+ listImageFiles();
+}
+
+void ConvertImagesDialog::slotOptionsClicked(void)
+{
+ int Type = m_Type->currentItem();
+ ConvertOptionsDialog *optionsDialog = new ConvertOptionsDialog(this, Type);
+
+ if (Type == 0) // JPEG
+ {
+ optionsDialog->m_JPEGPNGCompression->setValue(m_JPEGPNGCompression);
+ optionsDialog->m_compressLossLess->setChecked(m_compressLossLess);
+ }
+ if (Type == 1) // PNG
+ optionsDialog->m_JPEGPNGCompression->setValue(m_JPEGPNGCompression);
+ if (Type == 2) // TIFF
+ optionsDialog->m_TIFFCompressionAlgo->setCurrentText(m_TIFFCompressionAlgo);
+ if (Type == 5) // TGA
+ optionsDialog->m_TGACompressionAlgo->setCurrentText(m_TGACompressionAlgo);
+
+ if ( optionsDialog->exec() == KMessageBox::Ok )
+ {
+ if (Type == 0) // JPEG
+ {
+ m_JPEGPNGCompression = optionsDialog->m_JPEGPNGCompression->value();
+ m_compressLossLess = optionsDialog->m_compressLossLess->isChecked();
+ }
+ if (Type == 1) // PNG
+ m_JPEGPNGCompression = optionsDialog->m_JPEGPNGCompression->value();
+ if (Type == 2) // TIFF
+ m_TIFFCompressionAlgo = optionsDialog->m_TIFFCompressionAlgo->currentText();
+ if (Type == 5) // TGA
+ m_TGACompressionAlgo = optionsDialog->m_TGACompressionAlgo->currentText();
+ }
+
+ delete optionsDialog;
+}
+
+void ConvertImagesDialog::readSettings(void)
+{
+ // Read all settings from configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("ConvertImages Settings");
+
+ m_Type->setCurrentItem(m_config->readNumEntry("ImagesFormat", 0)); // JPEG per default
+ if ( m_config->readEntry("CompressLossLess", "false") == "true")
+ m_compressLossLess = true;
+ else
+ m_compressLossLess = false;
+
+ m_JPEGPNGCompression = m_config->readNumEntry("JPEGPNGCompression", 75);
+ m_TIFFCompressionAlgo = m_config->readEntry("TIFFCompressionAlgo", i18n("None"));
+ m_TGACompressionAlgo = m_config->readEntry("TGACompressionAlgo", i18n("None"));
+
+ m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default...
+
+ if (m_config->readEntry("RemoveOriginal", "false") == "true")
+ m_removeOriginal->setChecked( true );
+ else
+ m_removeOriginal->setChecked( false );
+
+ delete m_config;
+}
+
+void ConvertImagesDialog::saveSettings(void)
+{
+ // Write all settings in configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("ConvertImages Settings");
+
+ m_config->writeEntry("ImagesFormat", m_Type->currentItem());
+ m_config->writeEntry("JPEGPNGCompression", m_JPEGPNGCompression);
+ m_config->writeEntry("CompressLossLess", m_compressLossLess);
+ m_config->writeEntry("TIFFCompressionAlgo", m_TIFFCompressionAlgo);
+ m_config->writeEntry("TGACompressionAlgo", m_TGACompressionAlgo);
+
+ m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem());
+ m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked());
+ m_config->sync();
+
+ delete m_config;
+}
+
+QString ConvertImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode)
+{
+ *proc << "convert";
+
+ if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled !
+ {
+ *m_PreviewProc << "-crop" << "300x300+0+0";
+ m_previewOutput.append( " -crop 300x300+0+0 ");
+ }
+
+ if (m_Type->currentItem() == 0) // JPEG
+ {
+ if (m_compressLossLess == true)
+ {
+ *proc << "-compress" << "Lossless";
+ }
+ else
+ {
+ *proc << "-quality";
+ QString Temp;
+ *proc << Temp.setNum( m_JPEGPNGCompression );
+ }
+ }
+
+ if (m_Type->currentItem() == 1) // PNG
+ {
+ *proc << "-quality";
+ QString Temp;
+ *proc << Temp.setNum( m_JPEGPNGCompression );
+ }
+
+ if (m_Type->currentItem() == 2) // TIFF
+ {
+ *proc << "-compress";
+
+ if (m_TIFFCompressionAlgo == i18n("None"))
+ {
+ *proc << "None";
+ }
+ else
+ {
+ *proc << m_TIFFCompressionAlgo;
+ }
+ }
+
+ if (m_Type->currentItem() == 5) // TGA
+ {
+ *proc << "-compress";
+
+ if (m_TGACompressionAlgo == i18n("None"))
+ {
+ *proc << "None";
+ }
+ else
+ {
+ *proc << m_TGACompressionAlgo;
+ }
+ }
+
+ *proc << "-verbose";
+
+ *proc << item->pathSrc() + "[0]";
+
+ if ( !previewMode ) // No preview mode !
+ {
+ *proc << albumDest + "/" + item->nameDest();
+ }
+
+ return(extractArguments(proc));
+}
+
+void ConvertImagesDialog::processDone()
+{
+ if (m_Type->currentItem() == 0)
+ {
+ // JPEG file, we remove IPTC preview.
+
+ BatchProcessImagesItem *item = dynamic_cast<BatchProcessImagesItem*>(
+ m_listFile2Process_iterator->current() );
+ if (item)
+ {
+ QString src = item->pathSrc();
+ QString tgt = m_destinationURL->url() + "/" + item->nameDest();
+ QFileInfo fi(tgt);
+
+ kdDebug() << src << endl;
+ kdDebug() << tgt << fi.size()<< endl;
+
+ KExiv2Iface::KExiv2 metaSrc(src);
+
+ // Update Iptc preview.
+ // NOTE: see B.K.O #130525. a JPEG segment is limited to 64K. If the IPTC byte array is
+ // bigger than 64K duing of image preview tag size, the target JPEG image will be
+ // broken. Note that IPTC image preview tag is limited to 256K!!!
+ // There is no limitation with TIFF and PNG about IPTC byte array size.
+
+ metaSrc.removeIptcTag("Iptc.Application2.Preview");
+ metaSrc.removeIptcTag("Iptc.Application2.PreviewFormat");
+ metaSrc.removeIptcTag("Iptc.Application2.PreviewVersion");
+
+ KExiv2Iface::KExiv2 metaTgt(tgt);
+ metaTgt.setIptc(metaSrc.getIptc());
+ metaTgt.applyChanges();
+ }
+ }
+
+ BatchProcessImagesDialog::processDone();
+}
+
+QString ConvertImagesDialog::oldFileName2NewFileName(QString fileName)
+{
+ QString Temp;
+
+ Temp = fileName.left( fileName.findRev('.', -1) ); // The source file name without extension.
+ Temp = Temp + "." + ImageFileExt(m_Type->currentText()); // Added new file extension.
+
+ return Temp;
+}
+
+QString ConvertImagesDialog::ImageFileExt(QString Ext)
+{
+ if ( Ext == "TIFF" || Ext == "tiff" )
+ return ("tif");
+ else if ( Ext == "JPEG" || Ext == "jpeg" || Ext == "JPE" || Ext == "jpe" )
+ return ("jpg");
+ else
+ return (Ext.lower());
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/convertimagesdialog.h b/kipi-plugins/batchprocessimages/convertimagesdialog.h
new file mode 100644
index 0000000..cc96fd8
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/convertimagesdialog.h
@@ -0,0 +1,77 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CONVERTIMAGESDIALOG_H
+#define CONVERTIMAGESDIALOG_H
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "batchprocessimagesdialog.h"
+
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesItem;
+
+class ConvertImagesDialog : public BatchProcessImagesDialog
+{
+Q_OBJECT
+
+ public:
+
+ ConvertImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 );
+ ~ConvertImagesDialog();
+
+ private slots:
+
+ void slotHelp(void);
+ void slotOptionsClicked(void);
+ void slotTypeChanged(int type);
+
+ protected:
+
+ int m_JPEGPNGCompression;
+ bool m_compressLossLess;
+ QString m_TIFFCompressionAlgo;
+ QString m_TGACompressionAlgo;
+
+ QString makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode);
+
+ void processDone();
+
+ void readSettings(void);
+ void saveSettings(void);
+
+ QString oldFileName2NewFileName(QString fileName);
+ QString ImageFileExt(QString Ext);
+
+ private:
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // CONVERTIMAGESDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/convertoptionsdialog.cpp b/kipi-plugins/batchprocessimages/convertoptionsdialog.cpp
new file mode 100644
index 0000000..46ece4b
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/convertoptionsdialog.cpp
@@ -0,0 +1,121 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qwidget.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <knuminput.h>
+
+// Local includes
+
+#include "convertoptionsdialog.h"
+#include "convertoptionsdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+ConvertOptionsDialog::ConvertOptionsDialog(QWidget *parent, int ImageFormatType)
+ : KDialogBase( parent, "ConvertOptionsDialog", true,
+ i18n("Image File Format Options"), Ok|Cancel, Ok, false)
+{
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() );
+ QString whatsThis;
+
+ if (ImageFormatType == 0 || ImageFormatType == 1) // JPEG || PNG
+ {
+ m_label_imageCompression = new QLabel (i18n("Image compression level:"), box);
+ dvlay->addWidget( m_label_imageCompression );
+ m_JPEGPNGCompression = new KIntNumInput(75, box);
+ m_JPEGPNGCompression->setRange(1, 100, 1, true );
+ whatsThis = i18n("<p>The compression value for the target images:<p>");
+ whatsThis = whatsThis + i18n("<b>1</b>: very high compression<p>"
+ "<b>25</b>: high compression<p>"
+ "<b>50</b>: medium compression<p>"
+ "<b>75</b>: low compression (default value)<p>"
+ "<b>100</b>: no compression");
+
+ QWhatsThis::add( m_JPEGPNGCompression, whatsThis);
+ m_label_imageCompression->setBuddy( m_JPEGPNGCompression );
+ dvlay->addWidget( m_JPEGPNGCompression );
+
+ if (ImageFormatType == 0) // JPEG
+ {
+ m_compressLossLess = new QCheckBox( i18n("Use lossless compression"), box);
+ QWhatsThis::add( m_compressLossLess, i18n("<p>If this option is enabled, "
+ "all JPEG operations will use a lossless compression."));
+ dvlay->addWidget( m_compressLossLess );
+
+ connect(m_compressLossLess, SIGNAL( toggled(bool) ), this, SLOT( slotCompressLossLessEnabled(bool) ) );
+ }
+ }
+
+ if (ImageFormatType == 2) // TIFF
+ {
+ QLabel *m_label_imageCompression = new QLabel (i18n("Image compression algorithm:"), box);
+ dvlay->addWidget( m_label_imageCompression );
+ m_TIFFCompressionAlgo = new QComboBox( false, box );
+ m_TIFFCompressionAlgo->insertItem("LZW");
+ m_TIFFCompressionAlgo->insertItem("JPEG");
+ m_TIFFCompressionAlgo->insertItem(i18n("None"));
+ QWhatsThis::add( m_TIFFCompressionAlgo, i18n("<p>Select here the compression algorithm.") );
+ m_label_imageCompression->setBuddy( m_TIFFCompressionAlgo );
+ dvlay->addWidget( m_TIFFCompressionAlgo );
+ }
+
+ if (ImageFormatType == 5) // TGA
+ {
+ QLabel *m_label_imageCompression = new QLabel (i18n("Image compression algorithm:"), box);
+ dvlay->addWidget( m_label_imageCompression );
+ m_TGACompressionAlgo = new QComboBox( false, box );
+ m_TGACompressionAlgo->insertItem("RLE");
+ m_TGACompressionAlgo->insertItem(i18n("None"));
+ QWhatsThis::add( m_TGACompressionAlgo, i18n("<p>Select here the compression algorithm.") );
+ m_label_imageCompression->setBuddy( m_TGACompressionAlgo );
+ dvlay->addWidget( m_TGACompressionAlgo );
+ }
+}
+
+ConvertOptionsDialog::~ConvertOptionsDialog()
+{
+}
+
+void ConvertOptionsDialog::slotCompressLossLessEnabled(bool val)
+{
+ m_JPEGPNGCompression->setEnabled( !val );
+ m_label_imageCompression->setEnabled( !val );
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/convertoptionsdialog.h b/kipi-plugins/batchprocessimages/convertoptionsdialog.h
new file mode 100644
index 0000000..e7275a2
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/convertoptionsdialog.h
@@ -0,0 +1,63 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CONVERTOPTIONSDIALOG_H
+#define CONVERTOPTIONSDIALOG_H
+
+// Include files for Qt
+
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+class QLabel;
+class QCheckBox;
+class QComboBox;
+
+class KIntNumInput;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class ConvertOptionsDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+ ConvertOptionsDialog(QWidget *parent=0, int ImageFormatType = 0);
+ ~ConvertOptionsDialog();
+
+ QLabel *m_label_imageCompression;
+ KIntNumInput *m_JPEGPNGCompression;
+ QCheckBox *m_compressLossLess;
+ QComboBox *m_TIFFCompressionAlgo;
+ QComboBox *m_TGACompressionAlgo;
+
+ public slots:
+ void slotCompressLossLessEnabled(bool val);
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // CONVERTOPTIONSDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/data/Makefile.am b/kipi-plugins/batchprocessimages/data/Makefile.am
new file mode 100644
index 0000000..299f95a
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/data/Makefile.am
@@ -0,0 +1,2 @@
+kipibatchprocessimagespicdir = $(kde_datadir)/kipiplugin_batchprocessimages/data
+kipibatchprocessimagespic_DATA = handcursor.png
diff --git a/kipi-plugins/batchprocessimages/data/handcursor.png b/kipi-plugins/batchprocessimages/data/handcursor.png
new file mode 100644
index 0000000..e19e2ef
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/data/handcursor.png
Binary files differ
diff --git a/kipi-plugins/batchprocessimages/effectimagesdialog.cpp b/kipi-plugins/batchprocessimages/effectimagesdialog.cpp
new file mode 100644
index 0000000..4c857ba
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/effectimagesdialog.cpp
@@ -0,0 +1,442 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kprocess.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "effectoptionsdialog.h"
+#include "outputdialog.h"
+#include "imagepreview.h"
+#include "effectimagesdialog.h"
+#include "effectimagesdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+EffectImagesDialog::EffectImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent )
+ : BatchProcessImagesDialog( urlList, interface, i18n("Batch Image Effects"), parent )
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch image effects"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for batch image-effect transformations\n"
+ "This plugin uses the \"convert\" program from \"ImageMagick\" package."),
+ "(c) 2003-2007, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ //---------------------------------------------
+
+ m_nbItem = m_selectedImageFiles.count();
+
+ //---------------------------------------------
+
+ groupBox1->setTitle( i18n("Image Effect Options") );
+
+ m_labelType->setText( i18n("Effect:") );
+
+ m_Type->insertItem(i18n("Adaptive Threshold")); // 0
+ m_Type->insertItem(i18n("Charcoal"));
+ m_Type->insertItem(i18n("Detect Edges"));
+ m_Type->insertItem(i18n("Emboss"));
+ m_Type->insertItem(i18n("Implode"));
+ m_Type->insertItem(i18n("Paint")); // 5
+ m_Type->insertItem(i18n("Shade Light"));
+ m_Type->insertItem(i18n("Solarize"));
+ m_Type->insertItem(i18n("Spread"));
+ m_Type->insertItem(i18n("Swirl"));
+ m_Type->insertItem(i18n("Wave")); // 10
+ m_Type->setCurrentText(i18n("Emboss"));
+ whatsThis = i18n("<p>Select here the effect type for your images:<p>"
+ "<b>Adaptive threshold</b>: perform local adaptive thresholding. The algorithm "
+ "selects an individual threshold for each pixel based on the range of intensity "
+ "values in its local neighborhood. This allows for thresholding of an image whose "
+ "global intensity histogram does not contain distinctive peaks.<p>"
+ "<b>Charcoal</b>: simulate a charcoal drawing.<p>"
+ "<b>Detect edges</b>: detect edges within an image.<p>"
+ "<b>Emboss</b>: returns a grayscale image with a three-dimensional effect. The "
+ "algorithm convolves the image with a Gaussian operator of the given radius and "
+ "standard deviation.<p>"
+ "<b>Implode</b>: implode image pixels about the center.<p>"
+ "<b>Paint</b>: applies a special effect filter that simulates an oil painting.<p>"
+ "<b>Shade light</b>: shines a distant light on an image to create a three-dimensional "
+ "effect.<p>"
+ "<b>Solarize</b>: negate all pixels above the threshold level. This algorithm produces a "
+ "solarization effect seen when exposing a photographic film to light during the development "
+ "process.<p>"
+ "<b>Spread</b>: this is a special-effect method that randomly displaces each pixel in a "
+ "block defined by the radius parameter.<p>"
+ "<b>Swirl</b>: swirls the pixels about the center of the image. <p>"
+ "<b>Wave</b>: creates a \"ripple\" effect in the image by shifting the pixels vertically "
+ "along a sine wave.<p>");
+
+ QWhatsThis::add( m_Type, whatsThis );
+
+ //---------------------------------------------
+
+ readSettings();
+ listImageFiles();
+}
+
+EffectImagesDialog::~EffectImagesDialog()
+{
+ delete m_about;
+}
+
+void EffectImagesDialog::slotHelp( void )
+{
+ KApplication::kApplication()->invokeHelp("effectimages",
+ "kipi-plugins");
+}
+
+void EffectImagesDialog::slotOptionsClicked(void)
+{
+ int Type = m_Type->currentItem();
+ EffectOptionsDialog *optionsDialog = new EffectOptionsDialog(this, Type);
+
+ if ( Type == 0) // Adaptive threshold
+ {
+ optionsDialog->m_latWidth->setValue(m_latWidth);
+ optionsDialog->m_latHeight->setValue(m_latHeight);
+ optionsDialog->m_latOffset->setValue(m_latOffset);
+ }
+
+ if ( Type == 1) // Charcoal
+ {
+ optionsDialog->m_charcoalRadius->setValue(m_charcoalRadius);
+ optionsDialog->m_charcoalDeviation->setValue(m_charcoalDeviation);
+ }
+
+ if ( Type == 2) // Detect edges
+ optionsDialog->m_edgeRadius->setValue(m_edgeRadius);
+
+ if ( Type == 3) // Emboss
+ {
+ optionsDialog->m_embossRadius->setValue(m_embossRadius);
+ optionsDialog->m_embossDeviation->setValue(m_embossDeviation);
+ }
+
+ if ( Type == 4) // Implode
+ optionsDialog->m_implodeFactor->setValue(m_implodeFactor);
+
+ if ( Type == 5) // Paint
+ optionsDialog->m_paintRadius->setValue(m_paintRadius);
+
+ if ( Type == 6) // Shade light
+ {
+ optionsDialog->m_shadeAzimuth->setValue(m_shadeAzimuth);
+ optionsDialog->m_shadeElevation->setValue(m_shadeElevation);
+ }
+
+ if ( Type == 7) // Solarize
+ optionsDialog->m_solarizeFactor->setValue(m_solarizeFactor);
+
+ if ( Type == 8) // Spread
+ optionsDialog->m_spreadRadius->setValue(m_spreadRadius);
+
+ if ( Type == 9) // Swirl
+ optionsDialog->m_swirlDegrees->setValue(m_swirlDegrees);
+
+ if ( Type == 10) // Wave
+ {
+ optionsDialog->m_waveAmplitude->setValue(m_waveAmplitude);
+ optionsDialog->m_waveLenght->setValue(m_waveLenght);
+ }
+
+ if ( optionsDialog->exec() == KMessageBox::Ok )
+ {
+ if ( Type == 0) // Adaptive threshold
+ {
+ m_latWidth = optionsDialog->m_latWidth->value();
+ m_latHeight = optionsDialog->m_latHeight->value();
+ m_latOffset = optionsDialog->m_latOffset->value();
+ }
+
+ if ( Type == 1) // Charcoal
+ {
+ m_charcoalRadius = optionsDialog->m_charcoalRadius->value();
+ m_charcoalDeviation = optionsDialog->m_charcoalDeviation->value();
+ }
+
+ if ( Type == 2) // Detect edges
+ m_edgeRadius = optionsDialog->m_edgeRadius->value();
+
+ if ( Type == 3) // Emboss
+ {
+ m_embossRadius = optionsDialog->m_embossRadius->value();
+ m_embossDeviation = optionsDialog->m_embossDeviation->value();
+ }
+
+ if ( Type == 4) // Implode
+ m_implodeFactor = optionsDialog->m_implodeFactor->value();
+
+ if ( Type == 5) // Paint
+ m_paintRadius = optionsDialog->m_paintRadius->value();
+
+ if ( Type == 6) // Shade light
+ {
+ m_shadeAzimuth = optionsDialog->m_shadeAzimuth->value();
+ m_shadeElevation = optionsDialog->m_shadeElevation->value();
+ }
+
+ if ( Type == 7) // Solarize
+ m_solarizeFactor = optionsDialog->m_solarizeFactor->value();
+
+ if ( Type == 8) // Spread
+ m_spreadRadius = optionsDialog->m_spreadRadius->value();
+
+ if ( Type == 9) // Swirl
+ m_swirlDegrees = optionsDialog->m_swirlDegrees->value();
+
+ if ( Type == 10) // Wave
+ {
+ m_waveAmplitude = optionsDialog->m_waveAmplitude->value();
+ m_waveLenght = optionsDialog->m_waveLenght->value();
+ }
+ }
+
+ delete optionsDialog;
+}
+
+void EffectImagesDialog::readSettings(void)
+{
+m_config = new KConfig("kipirc");
+ m_config->setGroup("EffectImages Settings");
+
+ m_Type->setCurrentItem(m_config->readNumEntry("EffectType", 3)); // Emboss per default.
+ m_latWidth = m_config->readNumEntry("LatWidth", 50);
+ m_latHeight = m_config->readNumEntry("LatHeight", 50);
+ m_latOffset = m_config->readNumEntry("LatOffset", 1);
+ m_charcoalRadius = m_config->readNumEntry("CharcoalRadius", 3);
+ m_charcoalDeviation = m_config->readNumEntry("CharcoalDeviation", 3);
+ m_edgeRadius = m_config->readNumEntry("EdgeRadius", 3);
+ m_embossRadius = m_config->readNumEntry("EmbossRadius", 3);
+ m_embossDeviation = m_config->readNumEntry("EmbossDeviation", 3);
+ m_implodeFactor = m_config->readNumEntry("ImplodeFactor", 1);
+ m_paintRadius = m_config->readNumEntry("PaintRadius", 3);
+ m_shadeAzimuth = m_config->readNumEntry("ShadeAzimuth", 40);
+ m_shadeElevation = m_config->readNumEntry("ShadeElevation", 40);
+ m_solarizeFactor = m_config->readNumEntry("SolarizeFactor", 10);
+ m_spreadRadius = m_config->readNumEntry("SpreadRadius", 3);
+ m_swirlDegrees = m_config->readNumEntry("SwirlDegrees", 45);
+ m_waveAmplitude = m_config->readNumEntry("WaveAmplitude", 50);
+ m_waveLenght = m_config->readNumEntry("WaveLenght", 100);
+
+ if (m_config->readEntry("SmallPreview", "true") == "true")
+ m_smallPreview->setChecked( true );
+ else
+ m_smallPreview->setChecked( false );
+
+ m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default...
+
+ if (m_config->readEntry("RemoveOriginal", "false") == "true")
+ m_removeOriginal->setChecked( true );
+ else
+ m_removeOriginal->setChecked( false );
+
+ delete m_config;
+}
+
+void EffectImagesDialog::saveSettings(void)
+{
+ // Write all settings in configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("EffectImages Settings");
+ m_config->writeEntry("EffectType", m_Type->currentItem());
+
+ m_config->writeEntry("LatWidth", m_latWidth);
+ m_config->writeEntry("LatHeight", m_latHeight);
+ m_config->writeEntry("LatOffset", m_latOffset);
+ m_config->writeEntry("CharcoalRadius", m_charcoalRadius);
+ m_config->writeEntry("CharcoalDeviation", m_charcoalDeviation);
+ m_config->writeEntry("EdgeRadius", m_edgeRadius);
+ m_config->writeEntry("EmbossRadius", m_embossRadius);
+ m_config->writeEntry("EmbossDeviation", m_embossDeviation);
+ m_config->writeEntry("ImplodeFactor", m_implodeFactor);
+ m_config->writeEntry("PaintRadius", m_paintRadius);
+ m_config->writeEntry("ShadeAzimuth", m_shadeAzimuth);
+ m_config->writeEntry("ShadeElevation", m_shadeElevation);
+ m_config->writeEntry("SolarizeFactor", m_solarizeFactor);
+ m_config->writeEntry("SpreadRadius", m_spreadRadius);
+ m_config->writeEntry("SwirlDegrees", m_swirlDegrees);
+ m_config->writeEntry("WaveAmplitude", m_waveAmplitude);
+ m_config->writeEntry("WaveLenght", m_waveLenght);
+
+ m_config->writeEntry("SmallPreview", m_smallPreview->isChecked());
+ m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem());
+ m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked());
+
+ m_config->sync();
+
+ delete m_config;
+}
+
+QString EffectImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode)
+{
+ *proc << "convert";
+
+ if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled !
+ {
+ *m_PreviewProc << "-crop" << "300x300+0+0";
+ m_previewOutput.append( " -crop 300x300+0+0 ");
+ }
+
+ if (m_Type->currentItem() == 0) // Adaptive threshold
+ {
+ *proc << "-lat";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_latWidth ) + "x";
+ Temp2.append ( Temp.setNum( m_latHeight ) + "+" );
+ Temp2.append ( Temp.setNum( m_latOffset ) );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 1) // Charcoal
+ {
+ *proc << "-charcoal";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_charcoalRadius ) + "x";
+ Temp2.append ( Temp.setNum( m_charcoalDeviation ) );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 2) // Detect edges
+ {
+ *proc << "-edge";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_edgeRadius );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 3) // Emboss
+ {
+ *proc << "-emboss";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_embossRadius ) + "x";
+ Temp2.append ( Temp.setNum( m_embossDeviation ) );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 4) // Implode
+ {
+ *proc << "-implode";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_implodeFactor );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 5) // Paint
+ {
+ *proc << "-paint";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_paintRadius );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 6) // Shade light
+ {
+ *proc << "-shade";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_shadeAzimuth ) + "x";
+ Temp2.append ( Temp.setNum( m_shadeElevation ) );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 7) // Solarize
+ {
+ *proc << "-solarize";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_solarizeFactor );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 8) // Spread
+ {
+ *proc << "-spread";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_spreadRadius );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 9) // Swirl
+ {
+ *proc << "-swirl";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_swirlDegrees );
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 10) // Wave
+ {
+ *proc << "-wave";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_waveAmplitude ) + "x";
+ Temp2.append ( Temp.setNum( m_waveLenght ) );
+ *proc << Temp2;
+ }
+
+ *proc << "-verbose";
+
+ *proc << item->pathSrc();
+
+ if ( !previewMode ) // No preview mode !
+ {
+ *proc << albumDest + "/" + item->nameDest();
+ }
+
+ return(extractArguments(proc));
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/effectimagesdialog.h b/kipi-plugins/batchprocessimages/effectimagesdialog.h
new file mode 100644
index 0000000..26ab5e9
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/effectimagesdialog.h
@@ -0,0 +1,83 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 EFFECTIMAGESDIALOG_H
+#define EFFECTIMAGESDIALOG_H
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "batchprocessimagesdialog.h"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesItem;
+
+class EffectImagesDialog : public BatchProcessImagesDialog
+{
+Q_OBJECT
+
+ public:
+
+ EffectImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 );
+ ~EffectImagesDialog();
+
+ private slots:
+
+ void slotHelp(void);
+ void slotOptionsClicked(void);
+
+ protected:
+
+ int m_latWidth;
+ int m_latHeight;
+ int m_latOffset;
+ int m_charcoalRadius;
+ int m_charcoalDeviation;
+ int m_edgeRadius;
+ int m_embossRadius;
+ int m_embossDeviation;
+ int m_implodeFactor;
+ int m_paintRadius;
+ int m_shadeAzimuth;
+ int m_shadeElevation;
+ int m_solarizeFactor;
+ int m_spreadRadius;
+ int m_swirlDegrees;
+ int m_waveAmplitude;
+ int m_waveLenght;
+
+ QString makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode);
+
+ void readSettings(void);
+ void saveSettings(void);
+
+ private:
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // EFFECTIMAGESDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/effectoptionsdialog.cpp b/kipi-plugins/batchprocessimages/effectoptionsdialog.cpp
new file mode 100644
index 0000000..e56a740
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/effectoptionsdialog.cpp
@@ -0,0 +1,257 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qwidget.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qcombobox.h>
+#include <qcolor.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kcolorbutton.h>
+
+// Local includes
+
+#include "effectoptionsdialog.h"
+#include "effectoptionsdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+EffectOptionsDialog::EffectOptionsDialog(QWidget *parent, int EffectType)
+ : KDialogBase( parent, "EffectOptionsDialog", true,
+ i18n("Effect Options"), Ok|Cancel, Ok, false)
+{
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() );
+ QString whatsThis;
+
+ if (EffectType == 0) // Adaptive threshold
+ {
+ QLabel *m_label_latWidth = new QLabel (i18n("Width:"), box);
+ dvlay->addWidget( m_label_latWidth );
+ m_latWidth = new KIntNumInput(50, box);
+ m_latWidth->setRange(0, 200, 1, true );
+ QWhatsThis::add( m_latWidth, i18n("<p>Select here the value which represents the width "
+ "of the local neighborhood.") );
+ m_label_latWidth->setBuddy( m_latWidth );
+ dvlay->addWidget( m_latWidth );
+
+ QLabel *m_label_latHeight = new QLabel (i18n("Height:"), box);
+ dvlay->addWidget( m_label_latHeight );
+ m_latHeight = new KIntNumInput(50, box);
+ m_latHeight->setRange(0, 200, 1, true );
+ QWhatsThis::add( m_latHeight, i18n("<p>Select here the value which represents the height of "
+ "the local neighborhood.") );
+ m_label_latHeight->setBuddy( m_latHeight );
+ dvlay->addWidget( m_latHeight );
+
+ QLabel *m_label_latOffset = new QLabel (i18n("Offset:"), box);
+ dvlay->addWidget( m_label_latOffset );
+ m_latOffset = new KIntNumInput(1, box);
+ m_latOffset->setRange(0, 200, 1, true );
+ QWhatsThis::add( m_latOffset, i18n("<p>Select here the value which represents the mean offset.") );
+ m_label_latOffset->setBuddy( m_latOffset );
+ dvlay->addWidget( m_latOffset );
+ }
+
+ if (EffectType == 1) // Charcoal
+ {
+ QLabel *m_label_charcoalRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_charcoalRadius );
+ m_charcoalRadius = new KIntNumInput(3, box);
+ m_charcoalRadius->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_charcoalRadius, i18n("<p>Select here the value which represents the "
+ "radius of the pixel neighborhood.") );
+ m_label_charcoalRadius->setBuddy( m_charcoalRadius );
+ dvlay->addWidget( m_charcoalRadius );
+
+ QLabel *m_label_charcoalDeviation = new QLabel (i18n("Deviation:"), box);
+ dvlay->addWidget( m_label_charcoalDeviation );
+ m_charcoalDeviation = new KIntNumInput(3, box);
+ m_charcoalDeviation->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_charcoalDeviation, i18n("<p>Select here the value which represents the "
+ "standard deviation of the Gaussian, in pixels.") );
+ m_label_charcoalDeviation->setBuddy( m_charcoalDeviation );
+ dvlay->addWidget( m_charcoalDeviation );
+ }
+
+ if (EffectType == 2) // Detect edges
+ {
+ QLabel *m_label_edgeRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_edgeRadius );
+ m_edgeRadius = new KIntNumInput(3, box);
+ m_edgeRadius->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_edgeRadius, i18n("<p>Select here the value which represents the radius of "
+ "the pixel neighborhood. Radius defines the radius of the "
+ "convolution filter. If you use a radius of 0 the algorithm selects "
+ "a suitable radius.") );
+ m_label_edgeRadius->setBuddy( m_edgeRadius );
+ dvlay->addWidget( m_edgeRadius );
+ }
+
+ if (EffectType == 3) // Emboss
+ {
+ QLabel *m_label_embossRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_embossRadius );
+ m_embossRadius = new KIntNumInput(3, box);
+ m_embossRadius->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_embossRadius, i18n("<p>Select here the value which represents the radius of the "
+ "pixel neighborhood. For reasonable results, radius should be "
+ "larger than deviation. If you use a radius of 0 the algorithm "
+ "selects a suitable radius.") );
+ m_label_embossRadius->setBuddy( m_embossRadius );
+ dvlay->addWidget( m_embossRadius );
+
+ QLabel *m_label_embossDeviation = new QLabel (i18n("Deviation:"), box);
+ dvlay->addWidget( m_label_embossDeviation );
+ m_embossDeviation = new KIntNumInput(3, box);
+ m_embossDeviation->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_embossDeviation, i18n("<p>Select here the value which represents the standard "
+ "deviation of the Gaussian, in pixels.") );
+ m_label_embossDeviation->setBuddy( m_embossDeviation );
+ dvlay->addWidget( m_embossDeviation );
+ }
+
+ if (EffectType == 4) // Implode
+ {
+ QLabel *m_label_implodeFactor = new QLabel (i18n("Factor:"), box);
+ dvlay->addWidget( m_label_implodeFactor );
+ m_implodeFactor = new KIntNumInput(1, box);
+ m_implodeFactor->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_implodeFactor, i18n("<p>Select here the value which represents the extent of "
+ "the implosion.") );
+ m_label_implodeFactor->setBuddy( m_implodeFactor );
+ dvlay->addWidget( m_implodeFactor );
+ }
+
+ if (EffectType == 5) // Paint
+ {
+ QLabel *m_label_paintRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_paintRadius );
+ m_paintRadius = new KIntNumInput(3, box);
+ m_paintRadius->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_paintRadius, i18n("<p>Select here the value which represents the radius of "
+ "the circular neighborhood. Each pixel is replaced by the "
+ "most frequent color occurring in a circular region defined "
+ "by the radius.") );
+ m_label_paintRadius->setBuddy( m_paintRadius );
+ dvlay->addWidget( m_paintRadius );
+ }
+
+ if (EffectType == 6) // Shade light
+ {
+ QLabel *m_label_shadeAzimuth = new QLabel (i18n("Azimuth:"), box);
+ dvlay->addWidget( m_label_shadeAzimuth );
+ m_shadeAzimuth = new KIntNumInput(40, box);
+ m_shadeAzimuth->setRange(0, 360, 1, true );
+ QWhatsThis::add( m_shadeAzimuth, i18n("<p>Select here the value which represents the azimuth of "
+ "the light source direction. The azimuth is measured in degrees "
+ "above the x axis.") );
+ m_label_shadeAzimuth->setBuddy( m_shadeAzimuth );
+ dvlay->addWidget( m_shadeAzimuth );
+
+ QLabel *m_label_shadeElevation = new QLabel (i18n("Elevation:"), box);
+ dvlay->addWidget( m_label_shadeElevation );
+ m_shadeElevation = new KIntNumInput(40, box);
+ m_shadeElevation->setRange(0, 500, 1, true );
+ QWhatsThis::add( m_shadeElevation, i18n("<p>Select here the value which represents the elevation of "
+ "the light source direction. The elevation is measured in "
+ "pixels above the Z axis.") );
+ m_label_shadeElevation->setBuddy( m_shadeElevation );
+ dvlay->addWidget( m_shadeElevation );
+ }
+
+ if (EffectType == 7) // Solarize
+ {
+ QLabel *m_label_solarizeFactor = new QLabel (i18n("Factor:"), box);
+ dvlay->addWidget( m_label_solarizeFactor );
+ m_solarizeFactor = new KIntNumInput(3, box);
+ m_solarizeFactor->setRange(0, 99, 1, true );
+ QWhatsThis::add( m_solarizeFactor, i18n("<p>Select here the value which represents the percent-"
+ "threshold of the solarize intensity.") );
+ m_label_solarizeFactor->setBuddy( m_solarizeFactor );
+ dvlay->addWidget( m_solarizeFactor );
+ }
+
+ if (EffectType == 8) // Spread
+ {
+ QLabel *m_label_spreadRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_spreadRadius );
+ m_spreadRadius = new KIntNumInput(10, box);
+ m_spreadRadius->setRange(0, 200, 1, true );
+ QWhatsThis::add( m_spreadRadius, i18n("<p>Select here the value which represents the random "
+ "pixel in a neighborhood of this extent.") );
+ m_label_spreadRadius->setBuddy( m_spreadRadius );
+ dvlay->addWidget( m_spreadRadius );
+ }
+
+ if (EffectType == 9) // Swirl
+ {
+ QLabel *m_label_swirlDegrees = new QLabel (i18n("Degrees:"), box);
+ dvlay->addWidget( m_label_swirlDegrees );
+ m_swirlDegrees = new KIntNumInput(45, box);
+ m_swirlDegrees->setRange(0, 360, 1, true );
+ QWhatsThis::add( m_swirlDegrees, i18n("<p>Select here the value which represents the tightness of "
+ "the swirling effect. You get a more dramatic effect as the "
+ "degrees move from 1 to 360.") );
+ m_label_swirlDegrees->setBuddy( m_swirlDegrees );
+ dvlay->addWidget( m_swirlDegrees );
+ }
+
+ if (EffectType == 10) // Wave
+ {
+ QLabel *m_label_waveAmplitude = new QLabel (i18n("Amplitude:"), box);
+ dvlay->addWidget( m_label_waveAmplitude );
+ m_waveAmplitude = new KIntNumInput(50, box);
+ m_waveAmplitude->setRange(0, 200, 1, true );
+ QWhatsThis::add( m_waveAmplitude, i18n("<p>Select here the value which represents the amplitude of "
+ "the sine wave.") );
+ m_label_waveAmplitude->setBuddy( m_waveAmplitude );
+ dvlay->addWidget( m_waveAmplitude );
+
+ QLabel *m_label_waveLenght = new QLabel (i18n("Length:"), box);
+ dvlay->addWidget( m_label_waveLenght );
+ m_waveLenght = new KIntNumInput(100, box);
+ m_waveLenght->setRange(0, 200, 1, true );
+ QWhatsThis::add( m_waveLenght, i18n("<p>Select here the value which represents the wave length "
+ "of the sine wave.") );
+ m_label_waveLenght->setBuddy( m_waveLenght );
+ dvlay->addWidget( m_waveLenght );
+ }
+}
+
+EffectOptionsDialog::~EffectOptionsDialog()
+{
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/effectoptionsdialog.h b/kipi-plugins/batchprocessimages/effectoptionsdialog.h
new file mode 100644
index 0000000..673fc91
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/effectoptionsdialog.h
@@ -0,0 +1,78 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 EFFECTOPTIONSDIALOG_H
+#define EFFECTOPTIONSDIALOG_H
+
+// Include files for Qt
+
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+class KIntNumInput;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class EffectOptionsDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+ EffectOptionsDialog(QWidget *parent=0, int EffectType = 0);
+ ~EffectOptionsDialog();
+
+ KIntNumInput *m_latWidth;
+ KIntNumInput *m_latHeight;
+ KIntNumInput *m_latOffset;
+
+ KIntNumInput *m_charcoalRadius;
+ KIntNumInput *m_charcoalDeviation;
+
+ KIntNumInput *m_edgeRadius;
+
+ KIntNumInput *m_embossRadius;
+ KIntNumInput *m_embossDeviation;
+
+ KIntNumInput *m_implodeFactor;
+
+ KIntNumInput *m_paintRadius;
+
+ KIntNumInput *m_shadeAzimuth;
+ KIntNumInput *m_shadeElevation;
+
+ KIntNumInput *m_solarizeFactor;
+
+ KIntNumInput *m_spreadRadius;
+
+ KIntNumInput *m_swirlDegrees;
+
+ KIntNumInput *m_waveAmplitude;
+ KIntNumInput *m_waveLenght;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // EFFECTOPTIONSDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/filterimagesdialog.cpp b/kipi-plugins/batchprocessimages/filterimagesdialog.cpp
new file mode 100644
index 0000000..220b383
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/filterimagesdialog.cpp
@@ -0,0 +1,365 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kprocess.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "filteroptionsdialog.h"
+#include "outputdialog.h"
+#include "imagepreview.h"
+#include "filterimagesdialog.h"
+#include "filterimagesdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+FilterImagesDialog::FilterImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent )
+ : BatchProcessImagesDialog( urlList, interface, i18n("Batch Image Filtering"), parent )
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch image filtering"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to batch filter images\n"
+ "This plugin uses the \"convert\" program from \"ImageMagick\" package."),
+ "(c) 2003-2007, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ //---------------------------------------------
+
+ m_nbItem = m_selectedImageFiles.count();
+
+ //---------------------------------------------
+
+ groupBox1->setTitle( i18n("Image Filtering Options") );
+
+ m_labelType->setText( i18n("Filter:") );
+
+ m_Type->insertItem(i18n("Add Noise")); // 0
+ m_Type->insertItem(i18n("Antialias"));
+ m_Type->insertItem(i18n("Blur"));
+ m_Type->insertItem(i18n("Despeckle"));
+ m_Type->insertItem(i18n("Enhance")); // 4
+ m_Type->insertItem(i18n("Median"));
+ m_Type->insertItem(i18n("Noise Reduction"));
+ m_Type->insertItem(i18n("Sharpen"));
+ m_Type->insertItem(i18n("Unsharp")); // 8
+ m_Type->setCurrentText(i18n("Sharpen"));
+ whatsThis = i18n("<p>Select here the filter type for your images:<p>"
+ "<b>Add noise</b>: add artificial noise to an image.<p>"
+ "<b>Antialias</b>: remove pixel aliasing.<p>"
+ "<b>Blur</b>: blur the image with a Gaussian operator.<p>"
+ "<b>Despeckle</b>: reduces the speckle noise in an image while perserving the "
+ "edges of the original image.<p>"
+ "<b>Enhance</b>: apply a digital filter to enhance a noisy image.<p>"
+ "<b>Median</b>: apply a median filter to an image.<p>"
+ "<b>Noise reduction</b>: reduce noise in an image. <p>"
+ "<b>Sharpen</b>: sharpen the image with a Gaussian operator.<p>"
+ "<b>Unsharp</b>: sharpen the image with an unsharp mask operator.<p>");
+
+ QWhatsThis::add( m_Type, whatsThis );
+
+ //---------------------------------------------
+
+ readSettings();
+ listImageFiles();
+ slotTypeChanged(m_Type->currentItem());
+}
+
+FilterImagesDialog::~FilterImagesDialog()
+{
+ delete m_about;
+}
+
+void FilterImagesDialog::slotHelp( void )
+{
+ KApplication::kApplication()->invokeHelp("filterimages", "kipi-plugins");
+}
+
+void FilterImagesDialog::slotTypeChanged(int type)
+{
+ if ( type == 1 || // Antialias
+ type == 3 || // Despeckle
+ type == 4 ) // Enhance
+ m_optionsButton->setEnabled(false);
+ else
+ m_optionsButton->setEnabled(true);
+}
+
+void FilterImagesDialog::slotOptionsClicked(void)
+{
+ int Type = m_Type->currentItem();
+ FilterOptionsDialog *optionsDialog = new FilterOptionsDialog(this, Type);
+
+ if ( Type == 0) // Add noise
+ optionsDialog->m_noiseType->setCurrentText(m_noiseType);
+
+ if ( Type == 2) // Blur
+ {
+ optionsDialog->m_blurRadius->setValue(m_blurRadius);
+ optionsDialog->m_blurDeviation->setValue(m_blurDeviation);
+ }
+
+ if ( Type == 5) // Median
+ optionsDialog->m_medianRadius->setValue(m_medianRadius);
+
+ if ( Type == 6) // Noise reduction
+ optionsDialog->m_noiseRadius->setValue(m_noiseRadius);
+
+ if ( Type == 7) // Sharpen
+ {
+ optionsDialog->m_sharpenRadius->setValue(m_sharpenRadius);
+ optionsDialog->m_sharpenDeviation->setValue(m_sharpenDeviation);
+ }
+
+ if ( Type == 8) // Unsharp
+ {
+ optionsDialog->m_unsharpenRadius->setValue(m_unsharpenRadius);
+ optionsDialog->m_unsharpenDeviation->setValue(m_unsharpenDeviation);
+ optionsDialog->m_unsharpenPercent->setValue(m_unsharpenPercent);
+ optionsDialog->m_unsharpenThreshold->setValue(m_unsharpenThreshold);
+ }
+
+ if ( optionsDialog->exec() == KMessageBox::Ok )
+ {
+ if ( Type == 0) // Add noise
+ m_noiseType = optionsDialog->m_noiseType->currentText();
+
+ if ( Type == 2) // Blur
+ {
+ m_blurRadius = optionsDialog->m_blurRadius->value();
+ m_blurDeviation = optionsDialog->m_blurDeviation->value();
+ }
+
+ if ( Type == 5) // Median
+ m_medianRadius = optionsDialog->m_medianRadius->value();
+
+ if ( Type == 6) // Noise reduction
+ m_noiseRadius = optionsDialog->m_noiseRadius->value();
+
+ if ( Type == 7) // Sharpen
+ {
+ m_sharpenRadius = optionsDialog->m_sharpenRadius->value();
+ m_sharpenDeviation = optionsDialog->m_sharpenDeviation->value();
+ }
+
+ if ( Type == 8) // Unsharp
+ {
+ m_unsharpenRadius = optionsDialog->m_unsharpenRadius->value();
+ m_unsharpenDeviation = optionsDialog->m_unsharpenDeviation->value();
+ m_unsharpenPercent = optionsDialog->m_unsharpenPercent->value();
+ m_unsharpenThreshold = optionsDialog->m_unsharpenThreshold->value();
+ }
+ }
+
+ delete optionsDialog;
+}
+
+void FilterImagesDialog::readSettings(void)
+{
+ // Read all settings from configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("FilterImages Settings");
+
+ m_Type->setCurrentItem(m_config->readNumEntry("FilterType", 7)); // Sharpen per default
+ m_noiseType = m_config->readEntry("NoiseType", i18n("Gaussian"));
+ m_blurRadius = m_config->readNumEntry("BlurRadius", 3);
+ m_blurDeviation = m_config->readNumEntry("BlurDeviation", 1);
+ m_medianRadius = m_config->readNumEntry("MedianRadius", 3);
+ m_noiseRadius = m_config->readNumEntry("NoiseRadius", 3);
+ m_sharpenRadius = m_config->readNumEntry("SharpenRadius", 3);
+ m_sharpenDeviation = m_config->readNumEntry("SharpenDeviation", 1);
+ m_unsharpenRadius = m_config->readNumEntry("UnsharpenRadius", 3);
+ m_unsharpenDeviation = m_config->readNumEntry("UnsharpenDeviation", 1);
+ m_unsharpenPercent = m_config->readNumEntry("UnsharpenPercent", 3);
+ m_unsharpenThreshold = m_config->readNumEntry("UnsharpenThreshold", 1);
+
+ if (m_config->readEntry("SmallPreview", "true") == "true")
+ m_smallPreview->setChecked( true );
+ else
+ m_smallPreview->setChecked( false );
+
+ m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default...
+
+ if (m_config->readEntry("RemoveOriginal", "false") == "true")
+ m_removeOriginal->setChecked( true );
+ else
+ m_removeOriginal->setChecked( false );
+
+ delete m_config;
+}
+
+void FilterImagesDialog::saveSettings(void)
+{
+ // Write all settings in configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("FilterImages Settings");
+
+ m_config->writeEntry("FilterType", m_Type->currentItem());
+ m_config->writeEntry("NoiseType", m_noiseType);
+ m_config->writeEntry("BlurRadius", m_blurRadius);
+ m_config->writeEntry("BlurDeviation", m_blurDeviation);
+ m_config->writeEntry("MedianRadius", m_medianRadius);
+ m_config->writeEntry("NoiseRadius", m_noiseRadius);
+ m_config->writeEntry("SharpenRadius", m_sharpenRadius);
+ m_config->writeEntry("SharpenDeviation", m_sharpenDeviation);
+ m_config->writeEntry("UnsharpenRadius", m_unsharpenRadius);
+ m_config->writeEntry("UnsharpenDeviation", m_unsharpenDeviation);
+ m_config->writeEntry("UnsharpenPercent", m_unsharpenPercent);
+ m_config->writeEntry("UnsharpenThreshold", m_unsharpenThreshold);
+
+ m_config->writeEntry("SmallPreview", m_smallPreview->isChecked());
+ m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem());
+ m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked());
+
+ m_config->sync();
+
+ delete m_config;
+}
+
+QString FilterImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode)
+{
+ *proc << "convert";
+
+ if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled !
+ {
+ *m_PreviewProc << "-crop" << "300x300+0+0";
+ m_previewOutput.append( " -crop 300x300+0+0 ");
+ }
+
+ if (m_Type->currentItem() == 0) // Add noise
+ {
+ QString Temp;
+ if ( m_noiseType == i18n("Uniform") ) Temp = "Uniform";
+ if ( m_noiseType == i18n("Gaussian") ) Temp = "Gaussian";
+ if ( m_noiseType == i18n("Multiplicative") ) Temp = "Multiplicative";
+ if ( m_noiseType == i18n("Impulse") ) Temp = "Impulse";
+ if ( m_noiseType == i18n("Laplacian") ) Temp = "Laplacian";
+ if ( m_noiseType == i18n("Poisson") ) Temp = "Poisson";
+ *proc << "+noise" << Temp;
+ }
+
+ if (m_Type->currentItem() == 1) // Antialias
+ {
+ *proc << "-antialias";
+ }
+
+ if (m_Type->currentItem() == 2) // Blur
+ {
+ *proc << "-blur";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_blurRadius ) + "x";
+ Temp2.append(Temp.setNum( m_blurDeviation ));
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 3) // Despeckle
+ {
+ *proc << "-despeckle";
+ }
+
+ if (m_Type->currentItem() == 4) // Enhance
+ {
+ *proc << "-enhance";
+ }
+
+ if (m_Type->currentItem() == 5) // Median
+ {
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_medianRadius );
+ *proc << "-median" << Temp2;
+ }
+
+ if (m_Type->currentItem() == 6) // Noise reduction
+ {
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_noiseRadius );
+ *proc << "-noise" << Temp2;
+ }
+
+ if (m_Type->currentItem() == 7) // Sharpen
+ {
+ *proc << "-sharpen";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_sharpenRadius ) + "x";
+ Temp2.append(Temp.setNum( m_sharpenDeviation ));
+ *proc << Temp2;
+ }
+
+ if (m_Type->currentItem() == 8) // Unsharp
+ {
+ *proc << "-unsharp";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_unsharpenRadius ) + "x";
+ Temp2.append(Temp.setNum( m_unsharpenDeviation ));
+ Temp2.append( "+" + Temp.setNum( m_unsharpenPercent ));
+ Temp2.append( "+" + Temp.setNum( m_unsharpenThreshold ));
+ *proc << Temp2;
+ }
+
+ *proc << "-verbose";
+
+ *proc << item->pathSrc();
+
+ if ( !previewMode ) // No preview mode !
+ {
+ *proc << albumDest + "/" + item->nameDest();
+ }
+
+ return(extractArguments(proc));
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/filterimagesdialog.h b/kipi-plugins/batchprocessimages/filterimagesdialog.h
new file mode 100644
index 0000000..7b1285e
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/filterimagesdialog.h
@@ -0,0 +1,78 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 FILTERIMAGESDIALOG_H
+#define FILTERIMAGESDIALOG_H
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "batchprocessimagesdialog.h"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesItem;
+
+class FilterImagesDialog : public BatchProcessImagesDialog
+{
+Q_OBJECT
+
+ public:
+
+ FilterImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 );
+ ~FilterImagesDialog();
+
+ private slots:
+
+ void slotHelp(void);
+ void slotOptionsClicked(void);
+ void slotTypeChanged(int type);
+
+ protected:
+
+ QString m_noiseType;
+ int m_blurRadius;
+ int m_blurDeviation;
+ int m_medianRadius;
+ int m_noiseRadius;
+ int m_sharpenRadius;
+ int m_sharpenDeviation;
+ int m_unsharpenRadius;
+ int m_unsharpenDeviation;
+ int m_unsharpenPercent;
+ int m_unsharpenThreshold;
+
+ QString makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode);
+
+ void readSettings(void);
+ void saveSettings(void);
+
+ private:
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // FILTERIMAGESDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/filteroptionsdialog.cpp b/kipi-plugins/batchprocessimages/filteroptionsdialog.cpp
new file mode 100644
index 0000000..f7f195c
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/filteroptionsdialog.cpp
@@ -0,0 +1,201 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qwidget.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qcombobox.h>
+#include <qcolor.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kcolorbutton.h>
+
+// Local includes
+
+#include "filteroptionsdialog.h"
+#include "filteroptionsdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+FilterOptionsDialog::FilterOptionsDialog(QWidget *parent, int FilterType)
+ : KDialogBase( parent, "FilterOptionsDialog", true,
+ i18n("Filter Options"), Ok|Cancel, Ok, false)
+{
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() );
+ QString whatsThis;
+
+ if (FilterType == 0) // Add noise
+ {
+ QLabel *m_label_noiseType = new QLabel (i18n("Noise algorithm:"), box);
+ dvlay->addWidget( m_label_noiseType );
+ m_noiseType = new QComboBox( false, box );
+ m_noiseType->insertItem(i18n("Uniform"));
+ m_noiseType->insertItem(i18n("Gaussian"));
+ m_noiseType->insertItem(i18n("Multiplicative"));
+ m_noiseType->insertItem(i18n("Impulse"));
+ m_noiseType->insertItem(i18n("Laplacian"));
+ m_noiseType->insertItem(i18n("Poisson"));
+ QWhatsThis::add( m_noiseType, i18n("<p>Select here the algorithm method which will used "
+ "to add random noise to the images.") );
+ m_label_noiseType->setBuddy( m_noiseType );
+ dvlay->addWidget( m_noiseType );
+ }
+
+ if (FilterType == 2) // Blur
+ {
+ QLabel *m_label_blurRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_blurRadius );
+ m_blurRadius = new KIntNumInput(3, box);
+ m_blurRadius->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_blurRadius, i18n("<p>Select here the blur radius of the Gaussian, in pixels, "
+ "not counting the center pixel. For reasonable results, the "
+ "radius should be larger than deviation. If you use a radius of 0 "
+ "the blur operations selects a suitable radius.") );
+ m_label_blurRadius->setBuddy( m_blurRadius );
+ dvlay->addWidget( m_blurRadius );
+
+ QLabel *m_label_blurDeviation = new QLabel (i18n("Deviation:"), box);
+ dvlay->addWidget( m_label_blurDeviation );
+ m_blurDeviation = new KIntNumInput(1, box);
+ m_blurDeviation->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_blurDeviation, i18n("<p>Select here the standard deviation of the blur Gaussian, "
+ "in pixels.") );
+ m_label_blurDeviation->setBuddy( m_blurDeviation );
+ dvlay->addWidget( m_blurDeviation );
+ }
+
+ if (FilterType == 5) // Median
+ {
+ QLabel *m_label_medianRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_medianRadius );
+ m_medianRadius = new KIntNumInput(3, box);
+ m_medianRadius->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_medianRadius, i18n("<p>Select here the median radius of the pixel neighborhood. "
+ "The algorithm applies a digital filter that improves the quality "
+ "of noisy images. Each pixel is replaced by the median in a "
+ "set of neighboring pixels as defined by the radius.") );
+ m_label_medianRadius->setBuddy( m_medianRadius );
+ dvlay->addWidget( m_medianRadius );
+ }
+
+
+ if (FilterType == 6) // Noise reduction
+ {
+ QLabel *m_label_noiseRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_noiseRadius );
+ m_noiseRadius = new KIntNumInput(3, box);
+ m_noiseRadius->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_noiseRadius, i18n("<p>Select here the noise reduction radius value, in pixels. "
+ "The algorithm smooths the contours of an image while still "
+ "preserving edge information. The algorithm works by replacing "
+ "each pixel with its neighbor closest in value. A neighbor is "
+ "defined by the radius. If you use a radius of 0 the algorithm "
+ "selects a suitable radius.") );
+ m_label_noiseRadius->setBuddy( m_noiseRadius );
+ dvlay->addWidget( m_noiseRadius );
+ }
+
+ if (FilterType == 7) // Sharpen
+ {
+ QLabel *m_label_sharpenRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_sharpenRadius );
+ m_sharpenRadius = new KIntNumInput(3, box);
+ m_sharpenRadius->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_sharpenRadius, i18n("<p>Select here the radius of the sharpen Gaussian, in "
+ "pixels, not counting the center pixel. For reasonable "
+ "results, the radius should be larger than deviation. "
+ "if you use a radius of 0 the sharpen operation selects a "
+ "suitable radius.") );
+ m_label_sharpenRadius->setBuddy( m_sharpenRadius );
+ dvlay->addWidget( m_sharpenRadius );
+
+ QLabel *m_label_sharpenDeviation = new QLabel (i18n("Deviation:"), box);
+ dvlay->addWidget( m_label_sharpenDeviation );
+ m_sharpenDeviation = new KIntNumInput(1, box);
+ m_sharpenDeviation->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_sharpenDeviation, i18n("<p>Select here the sharpen deviation value of the "
+ "Laplacian in pixels.") );
+ m_label_sharpenDeviation->setBuddy( m_sharpenDeviation );
+ dvlay->addWidget( m_sharpenDeviation );
+ }
+
+ if (FilterType == 8) // Unsharp
+ {
+ QLabel *m_label_unsharpenRadius = new QLabel (i18n("Radius:"), box);
+ dvlay->addWidget( m_label_unsharpenRadius );
+ m_unsharpenRadius = new KIntNumInput(3, box);
+ m_unsharpenRadius->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_unsharpenRadius, i18n("<p>Select here the radius of the unsharpen Gaussian, "
+ "in pixels, not counting the center pixel. The algorithm "
+ "convolve the image with a Gaussian operator of the given "
+ "radius and standard deviation. For reasonable results, "
+ "radius should be larger than sigma. If you use a radius of 0 "
+ "the algorithm selects a suitable radius.") );
+ m_label_unsharpenRadius->setBuddy( m_unsharpenRadius );
+ dvlay->addWidget( m_unsharpenRadius );
+
+ QLabel *m_label_unsharpenDeviation = new QLabel (i18n("Deviation:"), box);
+ dvlay->addWidget( m_label_unsharpenDeviation );
+ m_unsharpenDeviation = new KIntNumInput(1, box);
+ m_unsharpenDeviation->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_unsharpenDeviation, i18n("<p>Select here the unsharpen deviation value of the "
+ "Gaussian, in pixels.") );
+ m_label_unsharpenDeviation->setBuddy( m_unsharpenDeviation );
+ dvlay->addWidget( m_unsharpenDeviation );
+
+ QLabel *m_label_unsharpenPercent = new QLabel (i18n("Percent:"), box);
+ dvlay->addWidget( m_label_unsharpenPercent );
+ m_unsharpenPercent = new KIntNumInput(3, box);
+ m_unsharpenPercent->setRange(1, 100, 1, true );
+ QWhatsThis::add( m_unsharpenPercent, i18n("<p>Select here the percentage difference between original "
+ "and blurred image which should be added to original.") );
+ m_label_unsharpenPercent->setBuddy( m_unsharpenPercent );
+ dvlay->addWidget( m_unsharpenPercent );
+
+ QLabel *m_label_unsharpenThreshold = new QLabel (i18n("Threshold:"), box);
+ dvlay->addWidget( m_label_unsharpenThreshold );
+ m_unsharpenThreshold = new KIntNumInput(1, box);
+ m_unsharpenThreshold->setRange(0, 20, 1, true );
+ QWhatsThis::add( m_unsharpenThreshold, i18n("<p>Select here the unsharpen threshold value, in "
+ "pixels, needed to apply the diffence amount."));
+ m_label_unsharpenThreshold->setBuddy( m_unsharpenThreshold );
+ dvlay->addWidget( m_unsharpenThreshold );
+ }
+}
+
+FilterOptionsDialog::~FilterOptionsDialog()
+{
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/filteroptionsdialog.h b/kipi-plugins/batchprocessimages/filteroptionsdialog.h
new file mode 100644
index 0000000..1446c06
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/filteroptionsdialog.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 FILTEROPTIONSDIALOG_H
+#define FILTEROPTIONSDIALOG_H
+
+// Include files for Qt
+
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+class QComboBox;
+
+class KIntNumInput;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class FilterOptionsDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+ FilterOptionsDialog(QWidget *parent=0, int FilterType = 0);
+ ~FilterOptionsDialog();
+
+ QComboBox *m_noiseType;
+
+ KIntNumInput *m_blurRadius;
+ KIntNumInput *m_blurDeviation;
+
+ KIntNumInput *m_medianRadius;
+
+ KIntNumInput *m_noiseRadius;
+
+ KIntNumInput *m_sharpenRadius;
+ KIntNumInput *m_sharpenDeviation;
+
+ KIntNumInput *m_unsharpenRadius;
+ KIntNumInput *m_unsharpenDeviation;
+ KIntNumInput *m_unsharpenPercent;
+ KIntNumInput *m_unsharpenThreshold;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // FILTEROPTIONSDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/hi32-action-borderimages.png b/kipi-plugins/batchprocessimages/hi32-action-borderimages.png
new file mode 100644
index 0000000..c17d8b1
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/hi32-action-borderimages.png
Binary files differ
diff --git a/kipi-plugins/batchprocessimages/hi32-action-colorimages.png b/kipi-plugins/batchprocessimages/hi32-action-colorimages.png
new file mode 100644
index 0000000..e41c17d
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/hi32-action-colorimages.png
Binary files differ
diff --git a/kipi-plugins/batchprocessimages/hi32-action-convertimages.png b/kipi-plugins/batchprocessimages/hi32-action-convertimages.png
new file mode 100644
index 0000000..b4007d4
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/hi32-action-convertimages.png
Binary files differ
diff --git a/kipi-plugins/batchprocessimages/hi32-action-effectimages.png b/kipi-plugins/batchprocessimages/hi32-action-effectimages.png
new file mode 100644
index 0000000..238eb9c
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/hi32-action-effectimages.png
Binary files differ
diff --git a/kipi-plugins/batchprocessimages/hi32-action-filterimages.png b/kipi-plugins/batchprocessimages/hi32-action-filterimages.png
new file mode 100644
index 0000000..06ab0b2
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/hi32-action-filterimages.png
Binary files differ
diff --git a/kipi-plugins/batchprocessimages/hi32-action-recompressimages.png b/kipi-plugins/batchprocessimages/hi32-action-recompressimages.png
new file mode 100644
index 0000000..0512188
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/hi32-action-recompressimages.png
Binary files differ
diff --git a/kipi-plugins/batchprocessimages/hi32-action-renameimages.png b/kipi-plugins/batchprocessimages/hi32-action-renameimages.png
new file mode 100644
index 0000000..d82054d
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/hi32-action-renameimages.png
Binary files differ
diff --git a/kipi-plugins/batchprocessimages/hi32-action-resizeimages.png b/kipi-plugins/batchprocessimages/hi32-action-resizeimages.png
new file mode 100644
index 0000000..cfc2d21
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/hi32-action-resizeimages.png
Binary files differ
diff --git a/kipi-plugins/batchprocessimages/imagepreview.cpp b/kipi-plugins/batchprocessimages/imagepreview.cpp
new file mode 100644
index 0000000..21a2db1
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/imagepreview.cpp
@@ -0,0 +1,386 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// C++ includes.
+
+#include <cstdlib>
+
+// Qt includes
+
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qslider.h>
+#include <qlcdnumber.h>
+#include <qpainter.h>
+#include <qwhatsthis.h>
+#include <qapplication.h>
+#include <qcursor.h>
+
+// KDE includes
+
+#include <kprocess.h>
+#include <kmessagebox.h>
+#include <kurl.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kio/netaccess.h>
+#include <kio/global.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kdeversion.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "imagepreview.h"
+#include "imagepreview.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+int INIT_ZOOM_FACTOR;
+
+ImagePreview::ImagePreview(const QString &fileOrig, const QString &fileDest, const QString &tmpPath,
+ bool cropActionOrig, bool cropActionDest, const QString &EffectName,
+ const QString &FileName, QWidget *parent)
+ : KDialogBase( parent, "PreviewDialog", true, i18n("Batch Process Preview (%1 - %2)").arg(EffectName)
+ .arg(FileName), Help|Ok, Ok, true)
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch process images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("An interface to preview the \"Batch Process Images\" "
+ "Kipi plugin.\n"
+ "This plugin uses the \"convert\" program from \"ImageMagick\" "
+ "package."),
+ "(c) 2003-2004, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbooks"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ //---------------------------------------------
+
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ resize(700, 400);
+
+ if ( cropActionOrig == true || cropActionDest == true )
+ INIT_ZOOM_FACTOR = 20;
+ else
+ INIT_ZOOM_FACTOR = 5;
+
+ QVBoxLayout* ml = new QVBoxLayout( box, 10 );
+
+ //---------------------------------------------
+
+ QHBoxLayout* h1 = new QHBoxLayout( ml );
+ QVBoxLayout* v1 = new QVBoxLayout( h1 );
+ h1->addSpacing( 5 );
+ QGridLayout* g1 = new QGridLayout( v1, 1, 2 );
+
+ QGroupBox * groupBoxZoomFactor = new QGroupBox( 2, Qt::Horizontal, i18n("Zoom Factor"), box );
+ LCDZoomFactorValue = new QLCDNumber (4, groupBoxZoomFactor, "ZoomFactorLCDvalue");
+ LCDZoomFactorValue->setSegmentStyle ( QLCDNumber::Flat );
+ LCDZoomFactorValue->display( QString::number(INIT_ZOOM_FACTOR * 5) );
+ QWhatsThis::add( LCDZoomFactorValue, i18n("<p>The zoom factor value, as a percentage."));
+
+ ZoomFactorSlider = new QSlider (1, 20, 1, INIT_ZOOM_FACTOR, Qt::Horizontal,
+ groupBoxZoomFactor, "ZoomFactorSlider");
+ ZoomFactorSlider->setTracking ( false );
+ ZoomFactorSlider->setTickInterval ( 5 );
+ QWhatsThis::add( ZoomFactorSlider, i18n("<p>Moving this slider changes the zoom factor value."));
+ g1->addWidget( groupBoxZoomFactor, 0, 0);
+
+ QGridLayout* g2 = new QGridLayout( v1, 1, 2 );
+ QGroupBox * groupBox1 = new QGroupBox( 1, Qt::Horizontal, i18n("Original Image"), box );
+ m_previewOrig = new PixmapView(cropActionOrig, groupBox1);
+ QWhatsThis::add( m_previewOrig, i18n("<p>This is the original image preview. You can use the mouse "
+ "wheel to change the zoom factor. Click in and use the mouse "
+ "to move the image."));
+ g2->addWidget( groupBox1 , 0, 0);
+
+ QGroupBox * groupBox2 = new QGroupBox( 1, Qt::Horizontal, i18n("Destination Image"), box );
+ m_previewDest = new PixmapView(cropActionDest, groupBox2);
+ QWhatsThis::add( m_previewDest, i18n("<p>This is the destination image preview. You can use the "
+ "mouse wheel to change the zoom factor. Click in and use the "
+ "mouse to move the image."));
+ g2->setColStretch(0,1);
+ g2->setColStretch(1,1);
+ g2->addWidget( groupBox2 , 0, 1);
+
+ connect( ZoomFactorSlider, SIGNAL(valueChanged(int)),
+ this, SLOT(slotZoomFactorValueChanged(int)) );
+
+ connect( m_previewOrig, SIGNAL(wheelEvent(int)),
+ this, SLOT(slotWheelChanged(int)) );
+
+ connect( m_previewDest, SIGNAL(wheelEvent(int)),
+ this, SLOT(slotWheelChanged(int)) );
+
+ m_previewOrig->setImage(fileOrig, tmpPath);
+ m_previewDest->setImage(fileDest, tmpPath);
+}
+
+ImagePreview::~ImagePreview()
+{
+ delete m_about;
+}
+
+void ImagePreview::slotHelp( void )
+{
+ KApplication::kApplication()->invokeHelp("", "kipi-plugins");
+}
+
+void ImagePreview::slotWheelChanged( int delta )
+{
+ if ( delta > 0 )
+ ZoomFactorSlider->setValue ( ZoomFactorSlider->value() - 1 );
+ else
+ ZoomFactorSlider->setValue ( ZoomFactorSlider->value() + 1 );
+
+ slotZoomFactorValueChanged( ZoomFactorSlider->value() );
+}
+
+void ImagePreview::slotZoomFactorValueChanged( int ZoomFactorValue )
+{
+ LCDZoomFactorValue->display( QString::number(ZoomFactorValue * 5) );
+
+ m_previewOrig->resizeImage( ZoomFactorValue * 5 );
+ m_previewDest->resizeImage( ZoomFactorValue * 5 );
+}
+
+PixmapView::PixmapView(bool cropAction, QWidget *parent, const char *name)
+ : QScrollView(parent, name)
+{
+ m_cropAction = cropAction;
+ m_pix = NULL;
+ m_validPreview = false;
+ setMinimumSize(QSize(300,300));
+ horizontalScrollBar()->setLineStep( 1 );
+ horizontalScrollBar()->setPageStep( 1 );
+ verticalScrollBar()->setLineStep( 1 );
+ verticalScrollBar()->setPageStep( 1 );
+ KGlobal::dirs()->addResourceType("kipi_handcursor", KGlobal::dirs()->kde_default("data")
+ + "kipi/data");
+ m_handCursor = new QCursor( KGlobal::dirs()->findResourceDir("kipi_handcursor", "handcursor.png")
+ + "handcursor.png" );
+}
+
+PixmapView::~PixmapView()
+{
+ if(m_pix) delete m_pix;
+}
+
+void PixmapView::setImage(const QString &ImagePath, const QString &tmpPath)
+{
+
+ m_previewFileName = tmpPath + "/" + QString::number(getpid()) + "-"
+ + QString::number(random()) + "PreviewImage.PNG";
+
+ if (m_cropAction == true)
+ PreviewCal(ImagePath, tmpPath);
+ else
+ {
+ if ( m_img.load(ImagePath) == false )
+ PreviewCal(ImagePath, tmpPath);
+ else
+ {
+ if(!m_pix) m_pix = new QPixmap(m_img.width(), m_img.height());
+ m_w = m_img.width();
+ m_h = m_img.height();
+ m_validPreview = true;
+ resizeImage( INIT_ZOOM_FACTOR *5 );
+ horizontalScrollBar()->setLineStep(1);
+ verticalScrollBar()->setLineStep(1);
+ }
+ }
+}
+
+void PixmapView::PreviewCal(const QString &ImagePath, const QString &/*tmpPath*/)
+{
+ m_pix = new QPixmap(300, 300);
+ QPainter p;
+ p.begin(m_pix);
+ p.fillRect(0, 0, m_pix->width(), m_pix->height(), Qt::white);
+ p.setPen(Qt::green);
+ p.drawText(0, 0, m_pix->width(), m_pix->height(), Qt::AlignCenter,
+ i18n("Preview\nimage\nprocessing\nin\nprogress..."));
+ p.end();
+
+ m_previewOutput ="convert";
+ m_PreviewProc = new KProcess;
+ *m_PreviewProc << "convert";
+ *m_PreviewProc << "-verbose";
+
+ if (m_cropAction == true)
+ {
+ *m_PreviewProc << "-crop" << "300x300+0+0";
+ m_previewOutput.append( " -crop 300x300+0+0 " );
+ }
+
+ *m_PreviewProc << ImagePath;
+ *m_PreviewProc << m_previewFileName;
+ m_previewOutput.append( " -verbose " + ImagePath + " " + m_previewFileName + "\n\n");
+
+ connect(m_PreviewProc, SIGNAL(processExited(KProcess *)),
+ this, SLOT(PreviewProcessDone(KProcess*)));
+
+ connect(m_PreviewProc, SIGNAL(receivedStdout(KProcess *, char*, int)),
+ this, SLOT(slotPreviewReadStd(KProcess*, char*, int)));
+
+ connect(m_PreviewProc, SIGNAL(receivedStderr(KProcess *, char*, int)),
+ this, SLOT(slotPreviewReadStd(KProcess*, char*, int)));
+
+ bool result = m_PreviewProc->start(KProcess::NotifyOnExit, KProcess::All);
+ if(!result)
+ {
+ KMessageBox::error(this, i18n("Cannot start 'convert' program from 'ImageMagick' package;\n"
+ "please check your installation."));
+ return;
+ }
+}
+
+void PixmapView::slotPreviewReadStd(KProcess* /*proc*/, char *buffer, int buflen)
+{
+ m_previewOutput.append( QString::fromLocal8Bit(buffer, buflen) );
+}
+
+void PixmapView::PreviewProcessDone(KProcess* proc)
+{
+ int ValRet = proc->exitStatus();
+ kdDebug (51000) << "Convert exit (" << ValRet << ")" << endl;
+
+ if ( ValRet == 0 )
+ {
+ if ( m_img.load( m_previewFileName ) == true )
+ {
+ if(!m_pix) m_pix = new QPixmap(300, 300);
+ m_w = m_img.width();
+ m_h = m_img.height();
+ m_validPreview = true;
+ resizeImage( INIT_ZOOM_FACTOR * 5 );
+ horizontalScrollBar()->setLineStep(1);
+ verticalScrollBar()->setLineStep(1);
+ KURL deletePreviewImage( m_previewFileName );
+
+#if KDE_VERSION >= 0x30200
+ KIO::NetAccess::del( deletePreviewImage, kapp->activeWindow() );
+#else
+ KIO::NetAccess::del( deletePreviewImage );
+#endif
+ }
+ else
+ {
+ m_pix = new QPixmap(visibleWidth(), visibleHeight());
+ QPainter p;
+ p.begin(m_pix);
+ p.fillRect(0, 0, m_pix->width(), m_pix->height(), Qt::white);
+ p.setPen(Qt::red);
+ p.drawText(0, 0, m_pix->width(), m_pix->height(), Qt::AlignCenter,
+ i18n("Cannot\nprocess\npreview\nimage."));
+ p.end();
+ repaintContents();
+ m_validPreview = false;
+ }
+ }
+}
+
+void PixmapView::resizeImage(int ZoomFactor)
+{
+ if ( m_validPreview == false) return;
+
+ int w = m_w - (int)((float)m_w * (100-(float)ZoomFactor) / 100);
+ int h = m_h - (int)((float)m_h * (100-(float)ZoomFactor) / 100);
+
+ QImage imgTmp = m_img.scale(w, h);
+ m_pix->convertFromImage(imgTmp);
+ resizeContents(w, h);
+ repaintContents(false);
+}
+
+void PixmapView::drawContents(QPainter *p, int x, int y, int w, int h)
+{
+ if(!m_pix) return;
+ else p->drawPixmap(x, y, *m_pix, x, y, w, h);
+}
+
+void PixmapView::contentsWheelEvent( QWheelEvent * e )
+{
+ emit wheelEvent(e->delta());
+}
+
+void PixmapView::contentsMousePressEvent ( QMouseEvent * e )
+{
+ if ( e->button() == Qt::LeftButton )
+ {
+ m_xpos = e->x();
+ m_ypos = e->y();
+ setCursor ( *m_handCursor );
+ }
+}
+
+void PixmapView::contentsMouseReleaseEvent ( QMouseEvent * /*e*/ )
+{
+ setCursor ( KCursor::arrowCursor() );
+}
+
+void PixmapView::contentsMouseMoveEvent( QMouseEvent * e )
+{
+ if ( e->state() == Qt::LeftButton )
+ {
+ uint newxpos = e->x();
+ uint newypos = e->y();
+
+ scrollBy (-(newxpos - m_xpos), -(newypos - m_ypos));
+
+ m_xpos = newxpos - (newxpos-m_xpos);
+ m_ypos = newypos - (newypos-m_ypos);
+ }
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/imagepreview.h b/kipi-plugins/batchprocessimages/imagepreview.h
new file mode 100644
index 0000000..27e7204
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/imagepreview.h
@@ -0,0 +1,142 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IMAGEPREVIEW_H
+#define IMAGEPREVIEW_H
+
+// Include files for Qt
+
+#include <qscrollview.h>
+#include <qimage.h>
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QPixmap;
+class QCursor;
+class QLCDNumber;
+class QSlider;
+class QPushButton;
+
+class KProcess;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class PixmapView : public QScrollView
+{
+Q_OBJECT
+
+public:
+
+ PixmapView(bool cropAction, QWidget *parent=0, const char *name=0);
+ ~PixmapView();
+
+ void setImage(const QString &ImagePath, const QString &tmpPath);
+ void resizeImage(int ZoomFactor);
+
+private slots:
+
+ void slotPreviewReadStd(KProcess* proc, char *buffer, int buflen);
+ void PreviewProcessDone(KProcess* proc);
+ void contentsWheelEvent( QWheelEvent * e );
+ void contentsMousePressEvent ( QMouseEvent * e );
+ void contentsMouseReleaseEvent ( QMouseEvent * e );
+ void contentsMouseMoveEvent( QMouseEvent * e );
+
+signals:
+
+ void wheelEvent( int delta );
+
+protected:
+
+ QPixmap *m_pix;
+
+ QImage m_img;
+
+ int m_w;
+ int m_h;
+ int m_xpos;
+ int m_ypos;
+
+ KProcess *m_PreviewProc;
+
+ QString m_previewOutput;
+ QString m_previewFileName;
+
+ bool m_validPreview;
+ bool m_cropAction;
+
+ QCursor *m_handCursor;
+
+ void drawContents(QPainter *p, int x, int y, int w, int h);
+ void PreviewCal(const QString &ImagePath, const QString &tmpPath);
+
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class ImagePreview : public KDialogBase
+{
+Q_OBJECT
+
+public:
+
+ ImagePreview(const QString &fileOrig, const QString &fileDest, const QString &tmpPath,
+ bool cropActionOrig, bool cropActionDest, const QString &EffectName,
+ const QString &FileName, QWidget *parent=0);
+ ~ImagePreview();
+
+private slots:
+
+ void slotZoomFactorValueChanged( int ZoomFactorValue );
+ void slotWheelChanged( int delta );
+ void slotHelp(void);
+
+protected:
+
+ PixmapView *m_previewOrig;
+ PixmapView *m_previewDest;
+
+ QLCDNumber *LCDZoomFactorValue;
+
+ QSlider *ZoomFactorSlider;
+
+ QPushButton *m_helpButton;
+
+private:
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // IMAGEPREVIEW_H
+
diff --git a/kipi-plugins/batchprocessimages/kipiplugin_batchprocessimages.desktop b/kipi-plugins/batchprocessimages/kipiplugin_batchprocessimages.desktop
new file mode 100644
index 0000000..8c811b4
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/kipiplugin_batchprocessimages.desktop
@@ -0,0 +1,57 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=BatchProcessImages
+Name[ca]=Procés d'imatges per lots
+Name[cs]=Dávkové zpracování obrázků
+Name[da]=Behandl billeder i baggrunden
+Name[de]=Bilder-Stapelverarbeitung
+Name[el]=ΟμαδικήΕπεξεργασίαΕικόνων
+Name[es]=Proceso de imágenes por bloques
+Name[et]=Piltide pakktöötlus
+Name[fi]=Eräajo
+Name[gl]=Procesamento de Lotes de Imaxes
+Name[is]=MagnvinnaMyndir
+Name[it]=ElaborazioneNonInterattivaDelleImmagini
+Name[nds]=Bild-Stapelverarbeiden
+Name[nl]=AfbeeldingenVerwerken
+Name[pl]=Grupowe przetwarzanie zdjęć
+Name[pt]=Processamento em Lote de Imagens
+Name[sr]=Пакетна обрада слика
+Name[sr@Latn]=Paketna obrada slika
+Name[sv]=Behandla bilder i bakgrunden
+Name[tg]=ПардозишиГурӯҳиТасвирҳо
+Name[tr]=ÇokluResimİşleme
+Name[xx]=xxBatchProcessImagesxx
+Name[zh_CN]=批处理图像
+Comment=KIPI Batch Processing Images Plugin
+Comment[ca]=Connector del KIPI pel processat per lots d'imatges
+Comment[cs]=KIPI modul dávkového zpracování obrázků
+Comment[da]=KIPI-plugin: Behandl billeder i baggrunden
+Comment[de]=Ein KIPI-Modul zum Bearbeiten von Bildern im Stapelmodus
+Comment[el]=Πρόσθετο ομαδικής επεξεργασίας εικόνων KIPI
+Comment[es]=Complemento de KIPI para el procesado de imágenes por lotes
+Comment[et]=KIPI piltide pakktöötluse plugin
+Comment[fi]=Kipi-liitännäinen usean kuvan peräkkäistä käsittelyä varten
+Comment[fr]=Module externe KIPI pour traiter des images par lots
+Comment[gl]=Plugin de KIPI para Procesar Imaxes por Lotes
+Comment[is]=KIPI íforrit til magnvinnslu mynda
+Comment[it]=Plugin di elaborazione non interattiva delle immagini di KIPI
+Comment[ja]=Kipi 画像一括処理プラグイン
+Comment[nds]=Kipi-Moduul för't Stapelverarbeiden vun Biller
+Comment[nl]=KIPI-plugin voor het verwerken van een serie afbeeldingen
+Comment[pa]=KIPI ਬੈਂਚ ਕਾਰਵਾਈ ਚਿੱਤਰ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Grupowe przetwarzanie zdjęć
+Comment[pt]='Plugin' do KIPI de Processamento de Imagens em Lote
+Comment[pt_BR]=Plugin de Processamento de Imagens em Lote do KIPI
+Comment[sr]=KIPI прикључак за пакетну обраду слика
+Comment[sr@Latn]=KIPI priključak za paketnu obradu slika
+Comment[sv]=KIPI-insticksprogram: Behandla bilder i bakgrunden
+Comment[tg]=Модули пардозиши тасвирҳои KIPI
+Comment[tr]=KIPI Çoklu Resim İşleme Eklentisi
+Comment[xx]=xxKIPI Batch Processing Images Pluginxx
+Comment[zh_CN]=KIPI 批处理图像插件
+Icon=
+ServiceTypes=KIPI/Plugin
+Type=Service
+X-KDE-Library=kipiplugin_batchprocessimages
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/kipi-plugins/batchprocessimages/outputdialog.cpp b/kipi-plugins/batchprocessimages/outputdialog.cpp
new file mode 100644
index 0000000..3ba2a60
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/outputdialog.cpp
@@ -0,0 +1,112 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes
+
+#include <qtextview.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qframe.h>
+
+// KDElib includes
+
+#include <klocale.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+
+// Local includes
+
+#include "pluginsversion.h"
+#include "outputdialog.h"
+#include "outputdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+OutputDialog::OutputDialog(QWidget* parent, QString caption, QString Messages, QString Header )
+ : KDialogBase( parent, "OutputDialog", true, caption, Help|User1|Ok, Ok, false,
+ i18n("Copy to Clip&board"))
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch processes images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("An interface to show the output of the \"Batch Process "
+ "Images\" Kipi plugin.\n"
+ "This plugin uses the \"convert\" program from \"ImageMagick\" "
+ "package."),
+ "(c) 2003-2007, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbooks"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ //---------------------------------------------
+
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() );
+
+ //---------------------------------------------
+
+ QLabel *labelHeader = new QLabel( Header, box);
+ dvlay->addWidget( labelHeader );
+
+ debugView = new QTextView( box );
+ debugView->append( Messages );
+ dvlay->addWidget( debugView );
+
+ connect(this, SIGNAL(user1Clicked()),
+ this, SLOT(slotCopyToCliboard()));
+
+ resize( 600, 400 );
+}
+
+OutputDialog::~OutputDialog()
+{
+ delete m_about;
+}
+
+void OutputDialog::slotHelp( void )
+{
+ KApplication::kApplication()->invokeHelp("",
+ "kipi-plugins");
+}
+
+void OutputDialog::slotCopyToCliboard( void )
+{
+ debugView->selectAll(true);
+ debugView->copy();
+ debugView->selectAll(false);
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/outputdialog.h b/kipi-plugins/batchprocessimages/outputdialog.h
new file mode 100644
index 0000000..f849439
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/outputdialog.h
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 OUTPUTDIALOG_H
+#define OUTPUTDIALOG_H
+
+// Include files for Qt
+
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QTextView;
+class QPushButton;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class OutputDialog : public KDialogBase
+{
+Q_OBJECT
+
+public:
+
+ OutputDialog( QWidget* parent=0, QString caption=QString::null,
+ QString Messages=QString::null, QString Header=QString::null );
+ ~OutputDialog();
+
+private slots:
+
+ void slotHelp(void);
+ void slotCopyToCliboard( void );
+
+private:
+
+ QPushButton *m_helpButton;
+ QTextView *debugView;
+
+ KIPIPlugins::KPAboutData *m_about;
+
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // OUTPUTDIALOG_H
+
diff --git a/kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp b/kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp
new file mode 100644
index 0000000..084fb03
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/plugin_batchprocessimages.cpp
@@ -0,0 +1,313 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// Qt Includes
+
+#include <qimage.h>
+
+// KDE includes
+
+#include <klocale.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+
+// KIPI includes
+
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "borderimagesdialog.h"
+#include "colorimagesdialog.h"
+#include "convertimagesdialog.h"
+#include "effectimagesdialog.h"
+#include "filterimagesdialog.h"
+#include "renameimagesdialog.h"
+#include "recompressimagesdialog.h"
+#include "resizeimagesdialog.h"
+#include "plugin_batchprocessimages.h"
+#include "plugin_batchprocessimages.moc"
+
+typedef KGenericFactory<Plugin_BatchProcessImages> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_batchprocessimages,
+ Factory("kipiplugin_batchprocessimages"))
+
+Plugin_BatchProcessImages::Plugin_BatchProcessImages(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "BatchProcessImages")
+{
+ kdDebug( 51001 ) << "Plugin_BatchProcessImages plugin loaded" << endl;
+
+}
+
+void Plugin_BatchProcessImages::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_action_borderimages = new KAction (i18n("Border Images..."), // Menu message.
+ "borderimages", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "batch_border_images");
+
+ m_action_colorimages = new KAction (i18n("Color Images..."), // Menu message.
+ "colorimages", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "batch_color_images");
+
+ m_action_convertimages = new KAction (i18n("Convert Images..."), // Menu message.
+ "convertimages", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "batch_convert_images");
+
+ m_action_effectimages = new KAction (i18n("Image Effects..."), // Menu message.
+ "effectimages", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "batch_effect_images");
+
+ m_action_filterimages = new KAction (i18n("Filter Images..."), // Menu message.
+ "filterimages", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "batch_filter_images");
+
+ m_action_renameimages = new KAction (i18n("Rename Images..."), // Menu message.
+ "renameimages", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "batch_rename_images");
+
+ m_action_recompressimages = new KAction (i18n("Recompress Images..."), // Menu message.
+ "recompressimages", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "batch_recompress_images");
+
+ m_action_resizeimages = new KAction (i18n("Resize Images..."), // Menu message.
+ "resizeimages", // Menu icon.
+ 0, // default shortcut.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "batch_resize_images");
+
+ addAction( m_action_borderimages );
+ addAction( m_action_colorimages );
+ addAction( m_action_convertimages );
+ addAction( m_action_effectimages );
+ addAction( m_action_filterimages );
+ addAction( m_action_renameimages );
+ addAction( m_action_recompressimages );
+ addAction( m_action_resizeimages );
+
+ KIPI::Interface* interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection images = interface->currentAlbum();
+ bool enable = images.isValid() && !images.images().isEmpty();
+
+ m_action_borderimages->setEnabled( enable );
+ m_action_colorimages->setEnabled( enable );
+ m_action_convertimages->setEnabled( enable );
+ m_action_effectimages->setEnabled( enable );
+ m_action_filterimages->setEnabled( enable );
+ m_action_renameimages->setEnabled( enable );
+ m_action_recompressimages->setEnabled( enable );
+ m_action_resizeimages->setEnabled( enable );
+
+ connect( interface, SIGNAL( currentAlbumChanged( bool ) ),
+ m_action_borderimages, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( currentAlbumChanged( bool ) ),
+ m_action_colorimages, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( currentAlbumChanged( bool ) ),
+ m_action_convertimages, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( currentAlbumChanged( bool ) ),
+ m_action_effectimages, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( currentAlbumChanged( bool ) ),
+ m_action_filterimages, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( currentAlbumChanged( bool ) ),
+ m_action_renameimages, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( currentAlbumChanged( bool ) ),
+ m_action_recompressimages, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( currentAlbumChanged( bool ) ),
+ m_action_resizeimages, SLOT( setEnabled( bool ) ) );
+}
+
+Plugin_BatchProcessImages::~Plugin_BatchProcessImages()
+{
+}
+
+void Plugin_BatchProcessImages::slotActivate()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection images = interface->currentSelection();
+
+ if ( !images.isValid() )
+ return;
+
+ if ( images.images().isEmpty() )
+ images = interface->currentAlbum();
+
+ if ( !images.isValid() )
+ return;
+
+ if ( images.images().isEmpty() )
+ {
+ KMessageBox::sorry(kapp->activeWindow(),
+ i18n("Please select an album or a selection of images."));
+ return;
+ }
+
+ KURL::List urlList = images.images();
+
+ QString from(sender()->name());
+
+ if (from == "batch_convert_images")
+ {
+ m_ConvertImagesDialog = new KIPIBatchProcessImagesPlugin::ConvertImagesDialog( urlList,
+ interface, kapp->activeWindow());
+ m_ConvertImagesDialog->show();
+ }
+ else if (from == "batch_rename_images")
+ {
+ KIPIBatchProcessImagesPlugin::RenameImagesDialog
+ dlg(urlList, interface, kapp->activeWindow());
+ dlg.exec();
+ }
+ else if (from == "batch_border_images")
+ {
+ m_BorderImagesDialog = new KIPIBatchProcessImagesPlugin::BorderImagesDialog( urlList,
+ interface, kapp->activeWindow());
+ m_BorderImagesDialog->show();
+ }
+ else if (from == "batch_color_images")
+ {
+ m_ColorImagesDialog = new KIPIBatchProcessImagesPlugin::ColorImagesDialog( urlList,
+ interface, kapp->activeWindow());
+ m_ColorImagesDialog->show();
+ }
+ else if (from == "batch_filter_images")
+ {
+ m_FilterImagesDialog = new KIPIBatchProcessImagesPlugin::FilterImagesDialog( urlList,
+ interface, kapp->activeWindow());
+ m_FilterImagesDialog->show();
+ }
+ else if (from == "batch_effect_images")
+ {
+ m_EffectImagesDialog = new KIPIBatchProcessImagesPlugin::EffectImagesDialog( urlList,
+ interface, kapp->activeWindow());
+ m_EffectImagesDialog->show();
+ }
+ else if (from == "batch_recompress_images")
+ {
+ m_RecompressImagesDialog = new KIPIBatchProcessImagesPlugin::RecompressImagesDialog( urlList,
+ interface, kapp->activeWindow());
+ m_RecompressImagesDialog->show();
+ }
+ else if (from == "batch_resize_images")
+ {
+ m_ResizeImagesDialog = new KIPIBatchProcessImagesPlugin::ResizeImagesDialog( urlList,
+ interface, kapp->activeWindow());
+ m_ResizeImagesDialog->show();
+ }
+ else
+ {
+ kdWarning( 51000 ) << "The impossible happened... unknown batch action specified" << endl;
+ return;
+ }
+}
+
+KIPI::Category Plugin_BatchProcessImages::category( KAction* action ) const
+{
+ if ( action == m_action_borderimages )
+ return KIPI::BATCHPLUGIN;
+ else if ( action == m_action_colorimages )
+ return KIPI::BATCHPLUGIN;
+ else if ( action == m_action_convertimages )
+ return KIPI::BATCHPLUGIN;
+ else if ( action == m_action_effectimages )
+ return KIPI::BATCHPLUGIN;
+ else if ( action == m_action_filterimages )
+ return KIPI::BATCHPLUGIN;
+ else if ( action == m_action_renameimages )
+ return KIPI::BATCHPLUGIN;
+ else if ( action == m_action_recompressimages )
+ return KIPI::BATCHPLUGIN;
+ else if ( action == m_action_resizeimages )
+ return KIPI::BATCHPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::BATCHPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/batchprocessimages/plugin_batchprocessimages.h b/kipi-plugins/batchprocessimages/plugin_batchprocessimages.h
new file mode 100644
index 0000000..ff78a8f
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/plugin_batchprocessimages.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_BATCHPROCESSIMAGES_H
+#define PLUGIN_BATCHPROCESSIMAGES_H
+
+// Include files for Qt
+
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+class KIPIBatchProcessImagesPlugin::BorderImagesDialog;
+class KIPIBatchProcessImagesPlugin::ColorImagesDialog;
+class KIPIBatchProcessImagesPlugin::ConvertImagesDialog;
+class KIPIBatchProcessImagesPlugin::EffectImagesDialog;
+class KIPIBatchProcessImagesPlugin::FilterImagesDialog;
+class KIPIBatchProcessImagesPlugin::RenameImagesDialog;
+class KIPIBatchProcessImagesPlugin::RecompressImagesDialog;
+class KIPIBatchProcessImagesPlugin::ResizeImagesDialog;
+
+class Plugin_BatchProcessImages : public KIPI::Plugin
+{
+Q_OBJECT
+
+public:
+ Plugin_BatchProcessImages(QObject *parent, const char* name, const QStringList &args);
+ virtual ~Plugin_BatchProcessImages();
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* );
+
+public slots:
+ void slotActivate();
+
+private:
+ KAction *m_action_borderimages;
+ KAction *m_action_colorimages;
+ KAction *m_action_convertimages;
+ KAction *m_action_effectimages;
+ KAction *m_action_filterimages;
+ KAction *m_action_renameimages;
+ KAction *m_action_recompressimages;
+ KAction *m_action_resizeimages;
+
+
+ KIPIBatchProcessImagesPlugin::BorderImagesDialog *m_BorderImagesDialog;
+ KIPIBatchProcessImagesPlugin::ColorImagesDialog *m_ColorImagesDialog;
+ KIPIBatchProcessImagesPlugin::ConvertImagesDialog *m_ConvertImagesDialog;
+ KIPIBatchProcessImagesPlugin::EffectImagesDialog *m_EffectImagesDialog;
+ KIPIBatchProcessImagesPlugin::FilterImagesDialog *m_FilterImagesDialog;
+ KIPIBatchProcessImagesPlugin::RenameImagesDialog *m_RenameImagesDialog;
+ KIPIBatchProcessImagesPlugin::RecompressImagesDialog *m_RecompressImagesDialog;
+ KIPIBatchProcessImagesPlugin::ResizeImagesDialog *m_ResizeImagesDialog;
+};
+
+
+#endif /* PLUGIN_BATCHPROCESSIMAGES_H */
diff --git a/kipi-plugins/batchprocessimages/recompressimagesdialog.cpp b/kipi-plugins/batchprocessimages/recompressimagesdialog.cpp
new file mode 100644
index 0000000..7f70474
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/recompressimagesdialog.cpp
@@ -0,0 +1,272 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kprocess.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "recompressoptionsdialog.h"
+#include "outputdialog.h"
+#include "recompressimagesdialog.h"
+#include "recompressimagesdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+RecompressImagesDialog::RecompressImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent )
+ : BatchProcessImagesDialog( urlList, interface, i18n("Batch Recompress Images"), parent )
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch recompress images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to batch recompress images\n"
+ "This plugin uses the \"convert\" program from \"ImageMagick\" package."),
+ "(c) 2003-2007, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ //---------------------------------------------
+
+ m_nbItem = m_selectedImageFiles.count();
+
+ //---------------------------------------------
+
+ groupBox1->setTitle( i18n("Image Recompression Options") );
+
+ m_labelType->hide();
+ m_Type->hide();
+ m_previewButton->hide();
+ m_smallPreview->hide();
+
+ //---------------------------------------------
+
+ readSettings();
+ listImageFiles();
+}
+
+RecompressImagesDialog::~RecompressImagesDialog()
+{
+ delete m_about;
+}
+
+void RecompressImagesDialog::slotHelp( void )
+{
+ KApplication::kApplication()->invokeHelp("recompressimages", "kipi-plugins");
+}
+
+void RecompressImagesDialog::slotOptionsClicked(void)
+{
+ RecompressOptionsDialog *optionsDialog = new RecompressOptionsDialog(this);
+
+ optionsDialog->m_JPEGCompression->setValue(m_JPEGCompression);
+ optionsDialog->m_compressLossLess->setChecked(m_compressLossLess);
+ optionsDialog->m_PNGCompression->setValue(m_PNGCompression);
+ optionsDialog->m_TIFFCompressionAlgo->setCurrentText(m_TIFFCompressionAlgo);
+ optionsDialog->m_TGACompressionAlgo->setCurrentText(m_TGACompressionAlgo);
+
+ if ( optionsDialog->exec() == KMessageBox::Ok )
+ {
+ m_JPEGCompression = optionsDialog->m_JPEGCompression->value();
+ m_compressLossLess = optionsDialog->m_compressLossLess->isChecked();
+ m_PNGCompression = optionsDialog->m_PNGCompression->value();
+ m_TIFFCompressionAlgo = optionsDialog->m_TIFFCompressionAlgo->currentText();
+ m_TGACompressionAlgo = optionsDialog->m_TGACompressionAlgo->currentText();
+ }
+
+ delete optionsDialog;
+}
+
+void RecompressImagesDialog::readSettings(void)
+{
+ // Read all settings from configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("RecompressImages Settings");
+
+ m_JPEGCompression = m_config->readNumEntry("JPEGCompression", 75);
+
+ if ( m_config->readEntry("CompressLossLess", "false") == "true")
+ m_compressLossLess = true;
+ else
+ m_compressLossLess = false;
+
+ m_PNGCompression = m_config->readNumEntry("PNGCompression", 75);
+ m_TIFFCompressionAlgo = m_config->readEntry("TIFFCompressionAlgo", i18n("None"));
+ m_TGACompressionAlgo = m_config->readEntry("TGACompressionAlgo", i18n("None"));
+
+ m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default...
+
+ if (m_config->readEntry("RemoveOriginal", "false") == "true")
+ m_removeOriginal->setChecked( true );
+ else
+ m_removeOriginal->setChecked( false );
+
+ delete m_config;
+}
+
+void RecompressImagesDialog::saveSettings(void)
+{
+ // Write all settings in configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("RecompressImages Settings");
+
+ m_config->writeEntry("JPEGCompression", m_JPEGCompression);
+ m_config->writeEntry("PNGCompression", m_PNGCompression);
+ m_config->writeEntry("CompressLossLess", m_compressLossLess);
+ m_config->writeEntry("TIFFCompressionAlgo", m_TIFFCompressionAlgo);
+ m_config->writeEntry("TGACompressionAlgo", m_TGACompressionAlgo);
+
+ m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem());
+ m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked());
+
+ m_config->sync();
+
+ delete m_config;
+}
+
+QString RecompressImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode)
+{
+ *proc << "convert";
+
+ if ( previewMode && m_smallPreview->isChecked() ) // Preview mode and small preview enabled !
+ {
+ *m_PreviewProc << "-crop" << "300x300+0+0";
+ m_previewOutput.append( " -crop 300x300+0+0 ");
+ }
+
+ QString imageExt = item->nameSrc().section('.', -1 );
+
+ if (imageExt == "JPEG" || imageExt == "jpeg" || imageExt == "JPG" || imageExt == "jpg")
+ {
+ if (m_compressLossLess == true)
+ {
+ *proc << "-compress" << "Lossless";
+ }
+ else
+ {
+ *proc << "-quality";
+ QString Temp;
+ *proc << Temp.setNum( m_JPEGCompression );
+ }
+ }
+
+ else if (imageExt == "PNG" || imageExt == "png")
+ {
+ *proc << "-quality";
+ QString Temp;
+ *proc << Temp.setNum( m_PNGCompression );
+ }
+
+ else if (imageExt == "TIFF" || imageExt == "tiff" || imageExt == "TIF" || imageExt == "tif")
+ {
+ *proc << "-compress";
+
+ if (m_TIFFCompressionAlgo == i18n("None"))
+ {
+ *proc << "None";
+ }
+ else
+ {
+ *proc << m_TIFFCompressionAlgo;
+ }
+ }
+
+ else if (imageExt == "TGA" || imageExt == "tga")
+ {
+ *proc << "-compress";
+
+ if (m_TGACompressionAlgo == i18n("None"))
+ {
+ *proc << "None";
+ }
+ else
+ {
+ *proc << m_TGACompressionAlgo;
+ }
+ }
+
+ *proc << "-verbose";
+
+ *proc << item->pathSrc();
+
+ if ( !previewMode ) // No preview mode !
+ {
+ *proc << albumDest + "/" + item->nameDest();
+ }
+
+ return(extractArguments(proc));
+}
+
+bool RecompressImagesDialog::prepareStartProcess(BatchProcessImagesItem *item,
+ const QString& /*albumDest*/)
+{
+ QString imageExt = item->nameSrc().section('.', -1 );
+
+ if (imageExt != "JPEG" && imageExt != "jpeg" &&
+ imageExt != "JPG" && imageExt != "jpg" &&
+ imageExt != "JPE" && imageExt != "jpe" &&
+ imageExt != "PNG" && imageExt != "png" &&
+ imageExt != "TIFF" && imageExt != "tiff" &&
+ imageExt != "TIF" && imageExt != "tif" &&
+ imageExt != "TGA" && imageExt != "tga")
+ {
+ item->changeResult(i18n("Skipped."));
+ item->changeError(i18n("image file format unsupported."));
+ return false;
+ }
+
+ return true;
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/recompressimagesdialog.h b/kipi-plugins/batchprocessimages/recompressimagesdialog.h
new file mode 100644
index 0000000..087aa45
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/recompressimagesdialog.h
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 RECOMPRESSIMAGESDIALOG_H
+#define RECOMPRESSIMAGESDIALOG_H
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "batchprocessimagesdialog.h"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesItem;
+
+class RecompressImagesDialog : public BatchProcessImagesDialog
+{
+Q_OBJECT
+
+ public:
+
+ RecompressImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 );
+ ~RecompressImagesDialog();
+
+ private slots:
+
+ void slotOptionsClicked(void);
+ void slotHelp(void);
+
+ protected:
+
+ int m_JPEGCompression;
+ int m_PNGCompression;
+ bool m_compressLossLess;
+ QString m_TIFFCompressionAlgo;
+ QString m_TGACompressionAlgo;
+
+ QString makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode);
+
+ void readSettings(void);
+ void saveSettings(void);
+
+ bool prepareStartProcess(BatchProcessImagesItem *item,
+ const QString& albumDest);
+
+ private:
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // RECOMPRESSIMAGESDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp b/kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp
new file mode 100644
index 0000000..fc81e26
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/recompressoptionsdialog.cpp
@@ -0,0 +1,140 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qwidget.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <knuminput.h>
+
+// Local includes
+
+#include "recompressoptionsdialog.h"
+#include "recompressoptionsdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+RecompressOptionsDialog::RecompressOptionsDialog(QWidget *parent)
+ : KDialogBase( parent, "RecompressOptionsDialog", true,
+ i18n("Recompression Options"), Ok|Cancel, Ok, false)
+{
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() );
+ QString whatsThis;
+
+ // JPEG file format.
+
+ QGroupBox * groupBox1 = new QGroupBox( 2, Qt::Horizontal, i18n("JPEG File Format"), box );
+
+ m_label_JPEGimageCompression = new QLabel (i18n("Image compression level:"), groupBox1);
+ m_JPEGCompression = new KIntNumInput(75, groupBox1);
+ m_JPEGCompression->setRange(1, 100, 1, true );
+ whatsThis = i18n("<p>The compression value for JPEG target images:<p>");
+ whatsThis = whatsThis + i18n("<b>1</b>: very high compression<p>"
+ "<b>25</b>: high compression<p>"
+ "<b>50</b>: medium compression<p>"
+ "<b>75</b>: low compression (default value)<p>"
+ "<b>100</b>: no compression");
+
+ QWhatsThis::add( m_JPEGCompression, whatsThis);
+ m_label_JPEGimageCompression->setBuddy( m_JPEGCompression );
+
+ m_compressLossLess = new QCheckBox( i18n("Use lossless compression"), groupBox1);
+ QWhatsThis::add( m_compressLossLess, i18n("<p>If this option is enabled, "
+ "all JPEG operations will use lossless compression."));
+
+ connect(m_compressLossLess, SIGNAL( toggled(bool) ),
+ this, SLOT( slotCompressLossLessEnabled(bool) ) );
+
+ dvlay->addWidget( groupBox1 );
+
+ // PNG File format.
+
+ QGroupBox * groupBox2 = new QGroupBox( 2, Qt::Horizontal, i18n("PNG File Format"), box );
+
+ m_label_PNGimageCompression = new QLabel (i18n("Image compression level:"), groupBox2);
+ m_PNGCompression = new KIntNumInput(75, groupBox2);
+ m_PNGCompression->setRange(1, 100, 1, true );
+ whatsThis = i18n("<p>The compression value for PNG target images:<p>");
+ whatsThis = whatsThis + i18n("<b>1</b>: very high compression<p>"
+ "<b>25</b>: high compression<p>"
+ "<b>50</b>: medium compression<p>"
+ "<b>75</b>: low compression (default value)<p>"
+ "<b>100</b>: no compression");
+
+ QWhatsThis::add( m_PNGCompression, whatsThis);
+ m_label_PNGimageCompression->setBuddy( m_PNGCompression );
+
+ dvlay->addWidget( groupBox2 );
+
+ // TIFF File format.
+
+ QGroupBox * groupBox3 = new QGroupBox( 2, Qt::Horizontal, i18n("TIFF File Format"), box );
+
+ m_label_TIFFimageCompression = new QLabel (i18n("Image compression algorithm:"), groupBox3);
+ m_TIFFCompressionAlgo = new QComboBox( false, groupBox3 );
+ m_TIFFCompressionAlgo->insertItem("LZW");
+ m_TIFFCompressionAlgo->insertItem("JPEG");
+ m_TIFFCompressionAlgo->insertItem(i18n("None"));
+ QWhatsThis::add( m_TIFFCompressionAlgo, i18n("<p>Select here the TIFF compression algorithm.") );
+ m_label_TIFFimageCompression->setBuddy( m_TIFFCompressionAlgo );
+
+ dvlay->addWidget( groupBox3 );
+
+ // TGA File format.
+
+ QGroupBox * groupBox4 = new QGroupBox( 2, Qt::Horizontal, i18n("TGA File Format"), box );
+
+ m_label_TGAimageCompression = new QLabel (i18n("Image compression algorithm:"), groupBox4);
+ m_TGACompressionAlgo = new QComboBox( false, groupBox4 );
+ m_TGACompressionAlgo->insertItem("RLE");
+ m_TGACompressionAlgo->insertItem(i18n("None"));
+ QWhatsThis::add( m_TGACompressionAlgo, i18n("<p>Select here the TGA compression algorithm.") );
+ m_label_TGAimageCompression->setBuddy( m_TGACompressionAlgo );
+
+ dvlay->addWidget( groupBox4 );
+}
+
+RecompressOptionsDialog::~RecompressOptionsDialog()
+{
+}
+
+void RecompressOptionsDialog::slotCompressLossLessEnabled(bool val)
+{
+ m_JPEGCompression->setEnabled( !val );
+ m_label_JPEGimageCompression->setEnabled( !val );
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/recompressoptionsdialog.h b/kipi-plugins/batchprocessimages/recompressoptionsdialog.h
new file mode 100644
index 0000000..4e5828c
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/recompressoptionsdialog.h
@@ -0,0 +1,67 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 RECOMPRESSOPTIONSDIALOG_H
+#define RECOMPRESSOPTIONSDIALOG_H
+
+// Include files for Qt
+
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+class QLabel;
+class QCheckBox;
+class QComboBox;
+
+class KIntNumInput;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class RecompressOptionsDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+ RecompressOptionsDialog(QWidget *parent=0);
+ ~RecompressOptionsDialog();
+
+ QLabel *m_label_JPEGimageCompression;
+ QLabel *m_label_PNGimageCompression;
+ QLabel *m_label_TIFFimageCompression;
+ QLabel *m_label_TGAimageCompression;
+ KIntNumInput *m_JPEGCompression;
+ KIntNumInput *m_PNGCompression;
+ QCheckBox *m_compressLossLess;
+ QComboBox *m_TIFFCompressionAlgo;
+ QComboBox *m_TGACompressionAlgo;
+
+ public slots:
+ void slotCompressLossLessEnabled(bool val);
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // RECOMPRESSOPTIONSDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/renameimagesbase.ui b/kipi-plugins/batchprocessimages/renameimagesbase.ui
new file mode 100644
index 0000000..a85fae5
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/renameimagesbase.ui
@@ -0,0 +1,359 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KIPIBatchProcessImagesPlugin::RenameImagesBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>RenameImagesBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>570</width>
+ <height>556</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>RenameImagesBase</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_templateGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>Template for renaming files</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>m_seqLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Sequence number start value:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>m_prefixEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>m_prefixLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Prefix string:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_addFileNameCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Add original file name</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_addFileDateCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Add file date</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="4" column="1">
+ <property name="name">
+ <cstring>m_formatDateEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="4" column="0">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>12</width>
+ <height>14</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_formatDateCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Date format:</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_seqSpin</cstring>
+ </property>
+ <property name="maxValue">
+ <number>999999</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>261</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_addRemoveBox</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop|AlignHCenter</set>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>m_addButton</cstring>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>m_removeButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ <widget class="KListView" row="0" column="0" rowspan="10" colspan="1">
+ <column>
+ <property name="text">
+ <string>Album</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Source Image</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Target Image</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Result</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_listView</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>LastColumn</enum>
+ </property>
+ <property name="dragEnabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer row="9" column="1">
+ <property name="name">
+ <cstring>spacer25</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>175</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="8" column="1">
+ <property name="name">
+ <cstring>m_reverseList</cstring>
+ </property>
+ <property name="text">
+ <string>Reverse List</string>
+ </property>
+ </widget>
+ <spacer row="6" column="1">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>19</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="7" column="1">
+ <property name="name">
+ <cstring>m_sortButton</cstring>
+ </property>
+ <property name="text">
+ <string>Sort List</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="5" column="1">
+ <property name="name">
+ <cstring>m_moveDown</cstring>
+ </property>
+ <property name="text">
+ <string>Move &amp;Down</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="4" column="1">
+ <property name="name">
+ <cstring>m_moveUp</cstring>
+ </property>
+ <property name="text">
+ <string>Move &amp;Up</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="1">
+ <property name="name">
+ <cstring>m_pixLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>96</width>
+ <height>96</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer3_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>19</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="6"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/kipi-plugins/batchprocessimages/renameimagesdialog.cpp b/kipi-plugins/batchprocessimages/renameimagesdialog.cpp
new file mode 100644
index 0000000..059bb4d
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/renameimagesdialog.cpp
@@ -0,0 +1,94 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005 by Owen Hirst <n8rider@sbcglobal.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+// KDE includes.
+
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "renameimageswidget.h"
+#include "renameimagesdialog.h"
+#include "renameimagesdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+RenameImagesDialog::RenameImagesDialog(const KURL::List& images,
+ KIPI::Interface* interface,
+ QWidget* parent)
+ : KDialogBase( KDialogBase::Plain, "Rename Images", Help|User1|Close,
+ Close, parent, "RenameImages",
+ false, false, i18n("&Start"))
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch-rename images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to batch-rename images"),
+ "(c) 2003-2007, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ QPushButton* helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ helpButton->setPopup( helpMenu->menu() );
+
+ // gui
+
+ QWidget* box = plainPage();
+ QVBoxLayout* lay = new QVBoxLayout(box);
+ m_widget = new RenameImagesWidget(box, interface, images);
+ lay->addWidget(m_widget);
+
+ connect(this, SIGNAL(user1Clicked()),
+ m_widget, SLOT(slotStart()));
+
+ adjustSize();
+}
+
+RenameImagesDialog::~RenameImagesDialog()
+{
+ delete m_about;
+}
+
+void RenameImagesDialog::slotHelp(void)
+{
+ kapp->invokeHelp("renameimages", "kipi-plugins");
+}
+
+} // namespace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/renameimagesdialog.h b/kipi-plugins/batchprocessimages/renameimagesdialog.h
new file mode 100644
index 0000000..696dea5
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/renameimagesdialog.h
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005 by Owen Hirst <n8rider@sbcglobal.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 RENAMEIMAGESDLG_H
+#define RENAMEIMAGESDLG_H
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <kurl.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+namespace KIPI
+{
+class Interface;
+}
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class RenameImagesWidget;
+
+class RenameImagesDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ RenameImagesDialog(const KURL::List& images,
+ KIPI::Interface* interface,
+ QWidget* parent);
+ ~RenameImagesDialog();
+
+private:
+
+ RenameImagesWidget* m_widget;
+
+ KIPIPlugins::KPAboutData* m_about;
+
+private slots:
+
+ void slotHelp();
+};
+
+}
+
+#endif /* RENAMEIMAGESDIALOG_H */
diff --git a/kipi-plugins/batchprocessimages/renameimageswidget.cpp b/kipi-plugins/batchprocessimages/renameimageswidget.cpp
new file mode 100644
index 0000000..f295239
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/renameimageswidget.cpp
@@ -0,0 +1,553 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005 by Owen Hirst <n8rider@sbcglobal.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+}
+
+// C++ includes.
+
+#include <cstdio>
+#include <ctime>
+
+// Qt includes.
+
+#include <qlistview.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qtimer.h>
+#include <qprogressdialog.h>
+#include <qgroupbox.h>
+#include <qpopupmenu.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kio/previewjob.h>
+#include <kio/renamedlg.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+
+// Libkipi includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imageinfo.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "batchprocessimagesitem.h"
+#include "renameimageswidget.h"
+#include "renameimageswidget.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+RenameImagesWidget::RenameImagesWidget(QWidget *parent,
+ KIPI::Interface* interface,
+ const KURL::List& urlList)
+ : RenameImagesBase(parent),
+ m_interface(interface),
+ m_urlList(urlList)
+{
+ m_listView->setSorting(-1);
+#if KDE_IS_VERSION(3,4,0)
+ // next can be done directly into designer but it seems not to compile
+ // under kde < 3.4.0
+ m_listView->setShadeSortColumn( FALSE );
+#endif
+
+ readSettings();
+
+ QPopupMenu* sortMenu = new QPopupMenu(this);
+ sortMenu->insertItem(i18n("Sort by Name"), BYNAME);
+ sortMenu->insertItem(i18n("Sort by Size"), BYSIZE);
+ sortMenu->insertItem(i18n("Sort by Date"), BYDATE);
+ m_sortButton->setPopup(sortMenu);
+
+ connect(m_listView, SIGNAL(doubleClicked(QListViewItem*)),
+ SLOT(slotListViewDoubleClicked(QListViewItem*)));
+ connect(m_listView, SIGNAL(selectionChanged(QListViewItem*)),
+ SLOT(slotImageSelected(QListViewItem*)));
+
+ connect(m_prefixEdit, SIGNAL(textChanged(const QString&)),
+ SLOT(slotOptionsChanged()));
+ connect(m_seqSpin, SIGNAL(valueChanged(int)),
+ SLOT(slotOptionsChanged()));
+ connect(m_addFileNameCheck, SIGNAL(toggled(bool)),
+ SLOT(slotOptionsChanged()));
+ connect(m_addFileDateCheck, SIGNAL(toggled(bool)),
+ SLOT(slotOptionsChanged()));
+ connect(m_formatDateCheck, SIGNAL(toggled(bool)),
+ SLOT(slotOptionsChanged()));
+ connect(m_formatDateEdit, SIGNAL(textChanged(const QString&)),
+ SLOT(slotOptionsChanged()));
+
+ connect(m_addButton, SIGNAL(clicked()),
+ SLOT(slotAddImages()));
+ connect(m_removeButton, SIGNAL(clicked()),
+ SLOT(slotRemoveImage()));
+
+ connect(sortMenu, SIGNAL(activated(int)),
+ SLOT(sortList(int)) );
+
+ connect(m_reverseList, SIGNAL(clicked()),
+ SLOT(reverseList()) );
+
+ connect(m_moveUp, SIGNAL(clicked()),
+ SLOT(moveCurrentItemUp()) );
+
+ connect(m_moveDown, SIGNAL(clicked()),
+ SLOT(moveCurrentItemDown()) );
+
+ m_timer = new QTimer(this);
+ m_progress = new QProgressDialog(this, 0, true);
+ connect(m_timer, SIGNAL(timeout()),
+ SLOT(slotNext()));
+ connect(m_progress, SIGNAL(canceled()),
+ SLOT(slotAbort()));
+
+ for (KURL::List::iterator it = m_urlList.begin();
+ it != m_urlList.end(); ++it)
+ {
+ new BatchProcessImagesItem(m_listView,
+ (*it).path().section('/', 0, -1),
+ (*it).filename(),
+ QString(),
+ QString());
+ }
+
+ updateListing();
+}
+
+RenameImagesWidget::~RenameImagesWidget()
+{
+ delete m_timer;
+ delete m_progress;
+
+ saveSettings();
+}
+
+void RenameImagesWidget::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("RenameImages Settings");
+
+ m_prefixEdit->setText(config.readEntry("PrefixString", ""));
+ m_seqSpin->setValue(config.readNumEntry("FirstRenameValue", 1));
+
+ m_addFileNameCheck->setChecked(config.readBoolEntry("AddOriginalFileName", false));
+ m_addFileDateCheck->setChecked(config.readBoolEntry("AddImageFileDate", false));
+ m_formatDateCheck->setChecked(config.readBoolEntry("FormatDate", false));
+ m_formatDateEdit->setText(config.readEntry("FormatDateString", "%Y-%m-%d"));
+
+ slotOptionsChanged();
+}
+
+void RenameImagesWidget::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("RenameImages Settings");
+
+ config.writeEntry("PrefixString", m_prefixEdit->text());
+ config.writeEntry("FirstRenameValue", m_seqSpin->value());
+
+ config.writeEntry("AddOriginalFileName", m_addFileNameCheck->isChecked());
+ config.writeEntry("AddImageFileDate", m_addFileDateCheck->isChecked());
+ config.writeEntry("FormatDate", m_formatDateCheck->isChecked());
+ config.writeEntry("FormatDateString", m_formatDateEdit->text());
+
+ config.sync();
+}
+
+void RenameImagesWidget::slotOptionsChanged()
+{
+ m_formatDateCheck->setEnabled(m_addFileDateCheck->isChecked());
+ m_formatDateEdit->setEnabled(m_formatDateCheck->isEnabled() &&
+ m_formatDateCheck->isChecked());
+
+ updateListing();
+}
+
+void RenameImagesWidget::slotListViewDoubleClicked(QListViewItem*)
+{
+ // TODO: Implement
+}
+
+void RenameImagesWidget::slotImageSelected(QListViewItem* item)
+{
+ if (!item)
+ {
+ m_removeButton->setEnabled(false);
+ return;
+ }
+
+ m_removeButton->setEnabled(true);
+ m_pixLabel->clear();
+
+ BatchProcessImagesItem* it = static_cast<BatchProcessImagesItem*>(item);
+ KIO::PreviewJob* thumbJob = KIO::filePreview(KURL(it->pathSrc()),
+ m_pixLabel->height() );
+
+ connect(thumbJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ SLOT(slotGotPreview(const KFileItem*, const QPixmap&)));
+}
+
+
+void RenameImagesWidget::sortList(int intSortOrder)
+{
+ SortOrder sortOrder = static_cast<SortOrder>(intSortOrder);
+
+ for (QListViewItem* it = m_listView->firstChild(); it;
+ it = it->nextSibling())
+ {
+ BatchProcessImagesItem* item = static_cast<BatchProcessImagesItem*>(it);
+
+ switch (sortOrder)
+ {
+ case(BYNAME):
+ {
+ item->setKey(item->text(1), false);
+ break;
+ }
+ case(BYSIZE):
+ {
+ QFileInfo fi(item->pathSrc());
+ item->setKey(QString::number(fi.size()), false);
+ break;
+ }
+ case(BYDATE):
+ {
+ KURL url(item->pathSrc());
+ KIPI::ImageInfo info = m_interface->info(url);
+ item->setKey(info.time().toString(Qt::ISODate), false);
+ break;
+ }
+ }
+ };
+
+ // Update list order. We need to set the sorting column temporarily
+ // otherwise sort() won't do anything
+ m_listView->setSorting(1);
+ m_listView->sort();
+ m_listView->setSorting(-1);
+
+ updateListing();
+}
+
+
+void RenameImagesWidget::reverseList()
+{
+ if (m_listView->childCount() < 2) return;
+
+ QListViewItem* lastItem = m_listView->lastItem();
+
+ while (m_listView->firstChild() != lastItem) {
+ m_listView->firstChild()->moveItem(lastItem);
+ }
+
+ updateListing();
+}
+
+
+void RenameImagesWidget::moveCurrentItemUp() {
+ QListViewItem* currentItem = m_listView->currentItem();
+ if (!currentItem) return;
+
+ for (QListViewItem* previousItem = m_listView->firstChild(); previousItem;
+ previousItem = previousItem->nextSibling())
+ {
+ if (previousItem->nextSibling() == currentItem) {
+ previousItem->moveItem(currentItem);
+ break;
+ }
+ }
+
+ updateListing();
+}
+
+
+void RenameImagesWidget::moveCurrentItemDown() {
+ QListViewItem* currentItem = m_listView->currentItem();
+ if (!currentItem) return;
+
+ QListViewItem* nextItem = currentItem->nextSibling();
+ if (nextItem) {
+ currentItem->moveItem(nextItem);
+ }
+
+ updateListing();
+}
+
+
+void RenameImagesWidget::updateListing()
+{
+ int pos = 0;
+ for (QListViewItem* it = m_listView->firstChild(); it;
+ it = it->nextSibling())
+ {
+ BatchProcessImagesItem* item = static_cast<BatchProcessImagesItem*>(it);
+ item->changeNameDest(oldToNewName(item, pos));
+ item->changeResult(QString());
+ item->changeError(QString());
+ item->changeOutputMess(QString());
+ pos++;
+ }
+}
+
+QString RenameImagesWidget::oldToNewName(BatchProcessImagesItem* item,
+ int itemPosition)
+{
+ KURL url;
+ url.setPath(item->pathSrc());
+
+ QFileInfo fi(item->pathSrc());
+
+ KIPI::ImageInfo info = m_interface->info(url);
+
+ QString newName = m_prefixEdit->text();
+
+ if (m_addFileNameCheck->isChecked())
+ {
+ newName += fi.baseName();
+ newName += "_";
+ }
+
+ if (m_addFileDateCheck->isChecked())
+ {
+ QString format = m_formatDateEdit->text();
+ format = format.simplifyWhiteSpace();
+ format.replace("%%","%");
+ format.replace("%s","");
+ format.replace("/", "");
+
+ time_t time = info.time().toTime_t();
+ struct tm* time_tm = ::localtime(&time);
+ char s[100];
+ ::strftime(s, 100, QFile::encodeName(format), time_tm);
+
+ newName += QString::fromLatin1(s);
+ newName += "_";
+ }
+
+ int count = m_listView->childCount();
+ int numDigits = 1;
+ while (count > 0)
+ {
+ numDigits++;
+ count = count / 10;
+ }
+
+ QString format;
+ format.sprintf("0%dd", numDigits);
+ format = "%" + format;
+
+ QString seq;
+ seq.sprintf(format.latin1(), itemPosition + m_seqSpin->value());
+ newName += seq;
+
+ newName += QString::fromLatin1(".") + fi.extension();
+
+ return newName;
+}
+
+void RenameImagesWidget::slotGotPreview(const KFileItem*, const QPixmap& pix)
+{
+ m_pixLabel->setPixmap(pix);
+}
+
+void RenameImagesWidget::slotStart()
+{
+ m_timer->start(0, true);
+
+ m_listView->setSelected(m_listView->firstChild(), true);
+ m_listView->ensureItemVisible(m_listView->firstChild());
+
+ m_progress->setTotalSteps(m_listView->childCount());
+ m_progress->setProgress(0);
+ m_progress->show();
+
+ m_overwriteAll = false;
+ m_autoSkip = false;
+}
+
+void RenameImagesWidget::slotAbort()
+{
+ m_timer->stop();
+ m_progress->reset();
+ m_progress->hide();
+}
+
+void RenameImagesWidget::slotNext()
+{
+ QListViewItem* it = m_listView->selectedItem();
+ if (!it)
+ {
+ slotAbort();
+ return;
+ }
+
+ BatchProcessImagesItem* item = static_cast<BatchProcessImagesItem*>(it);
+ KURL src;
+ src.setPath(item->pathSrc());
+ KURL dst = src.upURL();
+ dst.addPath(item->text(2));
+
+ bool skip = false;
+ bool overwrite = false;
+
+ if (!m_overwriteAll)
+ {
+ struct stat info;
+ while (::stat(QFile::encodeName(dst.path()), &info) == 0)
+ {
+ if (m_autoSkip)
+ {
+ skip = true;
+ break;
+ }
+
+ KIO::RenameDlg dlg(this, i18n("Rename File"), src.path(), dst.path(),
+ KIO::RenameDlg_Mode(KIO::M_MULTI |
+ KIO::M_OVERWRITE |
+ KIO::M_SKIP));
+ int result = dlg.exec();
+ dst = dlg.newDestURL();
+
+ switch (result)
+ {
+ case KIO::R_CANCEL:
+ {
+ slotAbort();
+ return;
+ }
+ case KIO::R_SKIP:
+ {
+ skip = true;
+ break;
+ }
+ case KIO::R_AUTO_SKIP:
+ {
+ m_autoSkip = true;
+ skip = true;
+ break;
+ }
+ case KIO::R_OVERWRITE:
+ {
+ overwrite = true;
+ break;
+ }
+ case KIO::R_OVERWRITE_ALL:
+ {
+ m_overwriteAll = true;
+ overwrite = true;
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (skip || overwrite)
+ break;
+ }
+ }
+
+ if (skip)
+ {
+ item->changeResult(i18n("Skipped"));
+ }
+ else
+ {
+ // Get the src info
+ KIPI::ImageInfo srcInfo = m_interface->info(src);
+
+ if (::rename(QFile::encodeName(src.path()),
+ QFile::encodeName(dst.path())) == 0)
+ {
+ srcInfo.setTitle(dst.filename());
+
+ item->changeResult(i18n("OK"));
+ }
+ else
+ {
+ item->changeResult(i18n("Failed"));
+ }
+ }
+
+ m_progress->setProgress(m_progress->progress() + 1);
+
+ if (it->nextSibling())
+ {
+ m_listView->setSelected(it->nextSibling(), true);
+ m_listView->ensureItemVisible(it->nextSibling());
+ m_timer->start(0, true);
+ }
+}
+
+void RenameImagesWidget::slotAddImages()
+{
+ KURL::List urls = KIPI::ImageDialog::getImageURLs(this, m_interface);
+
+ for (KURL::List::iterator it = urls.begin(); it != urls.end(); ++it)
+ {
+ if (m_urlList.contains(*it))
+ continue;
+
+ new BatchProcessImagesItem(m_listView,
+ (*it).path().section('/', 0, -1),
+ (*it).filename(),
+ QString(),
+ QString());
+ m_urlList.append(*it);
+ }
+
+ updateListing();
+}
+
+void RenameImagesWidget::slotRemoveImage()
+{
+ if (!m_listView->selectedItem())
+ return;
+
+ BatchProcessImagesItem* item =
+ static_cast<BatchProcessImagesItem*>(m_listView->selectedItem());
+ delete item;
+
+ m_pixLabel->clear();
+
+ updateListing();
+}
+
+} // namespace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/renameimageswidget.h b/kipi-plugins/batchprocessimages/renameimageswidget.h
new file mode 100644
index 0000000..9c64013
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/renameimageswidget.h
@@ -0,0 +1,107 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005 by Owen Hirst <n8rider@sbcglobal.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 RENAMEIMAGESWIDGET_H
+#define RENAMEIMAGESWIDGET_H
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "renameimagesbase.h"
+
+class KFileItem;
+class QTimer;
+class QProgressDialog;
+
+namespace KIPI
+{
+class Interface;
+}
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesItem;
+
+class RenameImagesWidget : public RenameImagesBase
+{
+ Q_OBJECT
+
+public:
+
+ enum SortOrder
+ {
+ BYNAME = 0,
+ BYSIZE,
+ BYDATE
+ };
+
+ RenameImagesWidget(QWidget *parent, KIPI::Interface* interface,
+ const KURL::List& urlList);
+ ~RenameImagesWidget();
+
+private:
+
+ void readSettings();
+ void saveSettings();
+ void reListImages();
+ void updateListing();
+ QString oldToNewName(BatchProcessImagesItem* item,
+ int itemPosition);
+
+ KIPI::Interface* m_interface;
+ KURL::List m_urlList;
+ QTimer* m_timer;
+ QProgressDialog* m_progress;
+ bool m_overwriteAll;
+ bool m_autoSkip;
+
+public slots:
+
+ void slotStart();
+ void slotAbort();
+ void slotNext();
+
+private slots:
+
+ void slotListViewDoubleClicked(QListViewItem*);
+ void slotImageSelected(QListViewItem*);
+ void slotOptionsChanged();
+ void slotGotPreview(const KFileItem*, const QPixmap&);
+
+ void slotAddImages();
+ void slotRemoveImage();
+
+ void sortList(int);
+ void reverseList();
+
+ void moveCurrentItemUp();
+ void moveCurrentItemDown();
+};
+
+}
+
+#endif /* RENAMEIMAGESWIDGET_H */
diff --git a/kipi-plugins/batchprocessimages/resizeimagesdialog.cpp b/kipi-plugins/batchprocessimages/resizeimagesdialog.cpp
new file mode 100644
index 0000000..36b912d
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/resizeimagesdialog.cpp
@@ -0,0 +1,575 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qimage.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kprocess.h>
+#include <kcolorbutton.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "resizeoptionsdialog.h"
+#include "outputdialog.h"
+#include "resizeimagesdialog.h"
+#include "resizeimagesdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+ResizeImagesDialog::ResizeImagesDialog( KURL::List urlList, KIPI::Interface* interface, QWidget *parent )
+ : BatchProcessImagesDialog( urlList, interface, i18n("Batch Resize Images"), parent )
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Batch resize images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to batch-resize images\n"
+ "This plugin uses the \"convert\" program from \"ImageMagick\" package."),
+ "(c) 2003-2007, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ //---------------------------------------------
+
+ m_nbItem = m_selectedImageFiles.count();
+
+ //---------------------------------------------
+
+ groupBox1->setTitle( i18n("Image Resizing Options") );
+
+ m_labelType->setText( i18n("Type:") );
+
+ m_Type->insertItem(i18n("Proportional (1 dim.)")); // 0
+ m_Type->insertItem(i18n("Proportional (2 dim.)")); // 1
+ m_Type->insertItem(i18n("Non-Proportional")); // 2
+ m_Type->insertItem(i18n("Prepare to Print")); // 3
+ m_Type->setCurrentText(i18n("Proportional (1 dim.)"));
+ whatsThis = i18n("<p>Select here the image-resize type.");
+ whatsThis = whatsThis + i18n("<p><b>Proportional (1 dim.)</b>: standard auto-resizing using one dimension. "
+ "The width or the height of the images will be automatically "
+ "selected, depending on the images' orientations. "
+ "The images' aspect ratios are preserved.");
+ whatsThis = whatsThis + i18n("<p><b>Proportional (2 dim.)</b>: auto-resizing using two dimensions. "
+ "The images' aspect ratio are preserved. You can use this, for example, "
+ "to adapt your images' sizes to your screen size.");
+ whatsThis = whatsThis + i18n("<p><b>Non proportional</b>: non-proportional resizing using two dimensions. "
+ "The images' aspect ratios are not preserved.");
+ whatsThis = whatsThis + i18n("<p><b>Prepare to print</b>: prepare the image for photographic printing. "
+ "The user can set the print resolution and the photographic paper size. "
+ "The target images will be adapted to the specified dimensions "
+ "(included the background size, margin size, and background color).");
+
+ QWhatsThis::add( m_Type, whatsThis );
+
+ m_previewButton->hide();
+ m_smallPreview->hide();
+
+ //---------------------------------------------
+
+ readSettings();
+ listImageFiles();
+}
+
+ResizeImagesDialog::~ResizeImagesDialog()
+{
+ delete m_about;
+}
+
+void ResizeImagesDialog::slotHelp( void )
+{
+ KApplication::kApplication()->invokeHelp("resizeimages", "kipi-plugins");
+}
+
+void ResizeImagesDialog::slotOptionsClicked(void)
+{
+ int Type = m_Type->currentItem();
+ ResizeOptionsDialog *optionsDialog = new ResizeOptionsDialog(this, Type);
+
+ if (Type == 0) // Proportional (1 dim.)
+ {
+ optionsDialog->m_quality->setValue(m_quality);
+ optionsDialog->m_size->setValue(m_size);
+ optionsDialog->m_resizeFilter->setCurrentText(m_resizeFilter);
+ }
+ if (Type == 1) // Proportional (2 dim.)
+ {
+ optionsDialog->m_quality->setValue(m_quality);
+ optionsDialog->m_Width->setValue(m_Width);
+ optionsDialog->m_Height->setValue(m_Height);
+ optionsDialog->m_button_bgColor->setColor(m_bgColor);
+ optionsDialog->m_resizeFilter->setCurrentText(m_resizeFilter);
+ optionsDialog->m_Border->setValue(m_Border);
+ }
+ if (Type == 2) // Non-proportional
+ {
+ optionsDialog->m_quality->setValue(m_quality);
+ optionsDialog->m_fixedWidth->setValue(m_fixedWidth);
+ optionsDialog->m_fixedHeight->setValue(m_fixedHeight);
+ optionsDialog->m_resizeFilter->setCurrentText(m_resizeFilter);
+ }
+ if (Type == 3) // Prepare to print
+ {
+ optionsDialog->m_quality->setValue(m_quality);
+ optionsDialog->m_paperSize->setCurrentText(m_paperSize);
+ optionsDialog->m_printDpi->setCurrentText(m_printDpi);
+ optionsDialog->m_customXSize->setValue(m_customXSize);
+ optionsDialog->m_customYSize->setValue(m_customYSize);
+ optionsDialog->m_customDpi->setValue(m_customDpi);
+ optionsDialog->m_button_backgroundColor->setColor(m_backgroundColor);
+ optionsDialog->m_resizeFilter->setCurrentText(m_resizeFilter);
+ optionsDialog->m_marging->setValue(m_marging);
+ optionsDialog->m_customSettings->setChecked(m_customSettings);
+ }
+
+ if ( optionsDialog->exec() == KMessageBox::Ok )
+ {
+ if (Type == 0) // Proportional (1 dim.)
+ {
+ m_quality = optionsDialog->m_quality->value();
+ m_size = optionsDialog->m_size->value();
+ m_resizeFilter = optionsDialog->m_resizeFilter->currentText();
+ }
+ if (Type == 1) // Proportional (2 dim.)
+ {
+ m_quality = optionsDialog->m_quality->value();
+ m_Width = optionsDialog->m_Width->value();
+ m_Height = optionsDialog->m_Height->value();
+ m_bgColor = optionsDialog->m_button_bgColor->color();
+ m_resizeFilter = optionsDialog->m_resizeFilter->currentText();
+ m_Border = optionsDialog->m_Border->value();
+ }
+ if (Type == 2) // Non-proportional
+ {
+ m_quality = optionsDialog->m_quality->value();
+ m_fixedWidth = optionsDialog->m_fixedWidth->value();
+ m_fixedHeight = optionsDialog->m_fixedHeight->value();
+ m_resizeFilter = optionsDialog->m_resizeFilter->currentText();
+ }
+ if (Type == 3) // Prepare to print
+ {
+ m_quality = optionsDialog->m_quality->value();
+ m_paperSize = optionsDialog->m_paperSize->currentText();
+ m_printDpi = optionsDialog->m_printDpi->currentText();
+ m_customXSize = optionsDialog->m_customXSize->value();
+ m_customYSize = optionsDialog->m_customYSize->value();
+ m_customDpi = optionsDialog->m_customDpi->value();
+ m_backgroundColor = optionsDialog->m_button_backgroundColor->color();
+ m_resizeFilter = optionsDialog->m_resizeFilter->currentText();
+ m_marging = optionsDialog->m_marging->value();
+ m_customSettings = optionsDialog->m_customSettings->isChecked();
+ }
+ }
+
+ delete optionsDialog;
+}
+
+void ResizeImagesDialog::readSettings(void)
+{
+ // Read all settings from configuration file.
+
+ QColor *ColorWhite = new QColor( 255, 255, 255 );
+ QColor *ColorBlack = new QColor( 0, 0, 0 );
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("ResizeImages Settings");
+
+ m_Type->setCurrentItem(m_config->readNumEntry("ResiseType", 3)); // Prepare to print per default.
+ m_size = m_config->readNumEntry("Size", 640);
+ m_resizeFilter = m_config->readEntry("ResizeFilter", "Lanczos");
+
+ m_paperSize = m_config->readEntry("PaperSize", "10x15");
+ m_printDpi = m_config->readEntry("PrintDpi", "300");
+ m_customXSize = m_config->readNumEntry("CustomXSize", 10);
+ m_customYSize = m_config->readNumEntry("CustomYSize", 15);
+ m_customDpi = m_config->readNumEntry("CustomDpi", 300);
+ m_backgroundColor = m_config->readColorEntry("BackgroundColor", ColorWhite);
+ m_marging = m_config->readNumEntry("MargingSize", 10);
+
+
+ m_quality = m_config->readNumEntry("Quality", 75);
+ m_Width = m_config->readNumEntry("Width", 1024);
+ m_Height = m_config->readNumEntry("Height", 768);
+ m_Border = m_config->readNumEntry("Border", 100);
+ m_bgColor = m_config->readColorEntry("BgColor", ColorBlack);
+
+ m_fixedWidth = m_config->readNumEntry("FixedWidth", 640);
+ m_fixedHeight = m_config->readNumEntry("FixedHeight", 480);
+
+ if ( m_config->readEntry("CustomSettings", "false") == "true")
+ m_customSettings = true;
+ else
+ m_customSettings = false;
+
+ m_overWriteMode->setCurrentItem(m_config->readNumEntry("OverWriteMode", 2)); // 'Rename' per default...
+
+ if (m_config->readEntry("RemoveOriginal", "false") == "true")
+ m_removeOriginal->setChecked( true );
+ else
+ m_removeOriginal->setChecked( false );
+
+ delete ColorWhite;
+ delete ColorBlack;
+ delete m_config;
+}
+
+void ResizeImagesDialog::saveSettings(void)
+{
+ // Write all settings in configuration file.
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("ResizeImages Settings");
+ m_config->writeEntry("ResiseType", m_Type->currentItem());
+ m_config->writeEntry("Size", m_size);
+ m_config->writeEntry("ResizeFilter", m_resizeFilter);
+
+ m_config->writeEntry("PaperSize", m_paperSize);
+ m_config->writeEntry("PrintDpi", m_printDpi);
+ m_config->writeEntry("CustomXSize", m_customXSize);
+ m_config->writeEntry("CustomYSize", m_customYSize);
+ m_config->writeEntry("CustomDpi", m_customDpi);
+ m_config->writeEntry("BackgroundColor", m_backgroundColor);
+ m_config->writeEntry("MargingSize", m_marging);
+ m_config->writeEntry("CustomSettings", m_customSettings);
+
+ m_config->writeEntry("Quality", m_quality);
+ m_config->writeEntry("Width", m_Width);
+ m_config->writeEntry("Height", m_Height);
+ m_config->writeEntry("Border", m_Border);
+ m_config->writeEntry("BgColor", m_bgColor);
+
+ m_config->writeEntry("FixedWidth", m_fixedWidth);
+ m_config->writeEntry("FixedHeight", m_fixedHeight);
+
+ m_config->writeEntry("OverWriteMode", m_overWriteMode->currentItem());
+ m_config->writeEntry("RemoveOriginal", m_removeOriginal->isChecked());
+
+ m_config->sync();
+
+ delete m_config;
+}
+
+QString ResizeImagesDialog::makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool )
+{
+ QImage img;
+
+ img.load( item->pathSrc() );
+
+ // Get image information.
+
+ int w = img.width();
+ int h = img.height();
+
+ int Type = m_Type->currentItem();
+ bool IncDec;
+ int MargingSize;
+
+ if (Type == 0) // Proportional (1 dim.)
+ {
+ *proc << "convert";
+ IncDec = ResizeImage( w, h, m_size);
+
+ *proc << "-resize";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( w ) + "x";
+ Temp2.append(Temp.setNum( h ));
+ *proc << Temp2;
+
+ *proc << "-quality";
+ QString Temp3;
+ Temp3.setNum(m_quality);
+ *proc << Temp3;
+
+ if ( IncDec == true ) // If the image is increased, enabled the filter.
+ {
+ *proc << "-filter" << m_resizeFilter;
+ }
+
+ *proc << "-verbose";
+ *proc << item->pathSrc() + "[0]";
+ *proc << albumDest + "/" + item->nameDest();
+ }
+
+ if (Type == 1) // Proportional (2 dim.)
+ {
+ QString targetBackgroundSize;
+ int ResizeCoeff;
+ *proc << "composite";
+
+ // Get the target image resizing dimensions with using the target size.
+
+ if ( m_Width < m_Height ) // Vertically resizing
+ {
+ if ( w < h ) // Original size vertically oriented.
+ ResizeCoeff = m_Height;
+ else // Original size horizontally oriented.
+ ResizeCoeff = m_Width;
+ }
+ else // Horizontally resizing
+ {
+ if ( w < h ) // Original size vertically oriented.
+ ResizeCoeff = m_Height;
+ else // Original size horizontally oriented.
+ ResizeCoeff = m_Width;
+ }
+
+ IncDec = ResizeImage( w, h, ResizeCoeff - m_Border);
+ targetBackgroundSize = QString::number(m_Width) + "x" + QString::number(m_Height);
+
+ *proc << "-verbose" << "-gravity" << "Center";
+
+ *proc << "-resize";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( w ) + "x";
+ Temp2.append(Temp.setNum( h ));
+ *proc << Temp2;
+
+ *proc << "-quality";
+ QString Temp3;
+ Temp3.setNum(m_quality);
+ *proc << Temp3;
+
+ if ( IncDec == true ) // If the image is increased, enabled the filter.
+ {
+ *proc << "-filter" << m_resizeFilter;
+ }
+
+ *proc << item->pathSrc() + "[0]";
+
+ // ImageMagick composite program do not preserve exif data from original.
+ // Need to use "-profile" option for that.
+
+ *proc << "-profile" << item->pathSrc();
+
+ Temp2 = "xc:rgb(" + Temp.setNum(m_bgColor.red()) + ",";
+ Temp2.append(Temp.setNum(m_bgColor.green()) + ",");
+ Temp2.append(Temp.setNum(m_bgColor.blue()) + ")");
+ *proc << Temp2;
+
+ *proc << "-resize" << targetBackgroundSize + "!";
+
+ *proc << albumDest + "/" + item->nameDest();
+ }
+
+ if (Type == 2) // Non-proportional
+ {
+ *proc << "convert";
+
+ *proc << "-resize";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( m_fixedWidth ) + "x";
+ Temp2.append(Temp.setNum( m_fixedHeight ) + "!");
+ *proc << Temp2;
+
+ if ( m_fixedWidth > w || m_fixedHeight > h ) // If the image is increased, enabled the filter.
+ {
+ *proc << "-filter" << m_resizeFilter;
+ }
+
+ *proc << "-quality";
+ QString Temp3;
+ Temp3.setNum(m_quality);
+ *proc << Temp3;
+
+ *proc << "-verbose";
+ *proc << item->pathSrc() + "[0]";
+ *proc << albumDest + "/" + item->nameDest();
+ }
+
+ if (Type == 3) // Prepare to print
+ {
+ if ( m_customSettings == true )
+ {
+ MargingSize = (int)((float)(m_marging * m_customDpi) / (float)(25.4));
+
+ if (w < h) // (w < h) because all paper dimensions are vertically gived !
+ {
+ m_xPixels = (int)( (float)(m_customXSize * m_customDpi) / (float)(2.54) );
+ m_yPixels = (int)( (float)(m_customYSize * m_customDpi) / (float)(2.54) );
+ }
+ else
+ {
+ m_yPixels = (int)( (float)(m_customXSize * m_customDpi) / (float)(2.54) );
+ m_xPixels = (int)( (float)(m_customYSize * m_customDpi) / (float)(2.54) );
+ }
+ }
+ else
+ {
+ QString Temp = m_printDpi;
+ int Dpi = Temp.toInt();
+ MargingSize = (int)((float)(m_marging * Dpi) / (float)(25.4));
+
+ if (w < h) // (w < h) because all paper dimensions are vertically given !
+ {
+ Temp = m_paperSize.left(m_paperSize.find('x'));
+ m_xPixels = (int)( (float)(Temp.toInt() * Dpi) / (float)(2.54) );
+ Temp = m_paperSize.right(m_paperSize.find('x'));
+ m_yPixels = (int)( (float)(Temp.toInt() * Dpi) / (float)(2.54) );
+ }
+ else
+ {
+ Temp = m_paperSize.left(m_paperSize.find('x'));
+ m_yPixels = (int)( (float)(Temp.toInt() * Dpi) / (float)(2.54) );
+ Temp = m_paperSize.right(m_paperSize.find('x'));
+ m_xPixels = (int)( (float)(Temp.toInt() * Dpi) / (float)(2.54) );
+ }
+ }
+
+ QString targetBackgroundSize;
+ int ResizeCoeff;
+ float RFactor;
+ *proc << "composite";
+
+ // Get the target image resizing dimensions with using the target paper size.
+
+ if (m_xPixels < m_yPixels)
+ {
+ RFactor = (float)m_xPixels / (float)w;
+ if (RFactor > 1.0) RFactor = (float)m_yPixels / (float)h;
+ ResizeCoeff = (int)((float)h * RFactor);
+ }
+ else
+ {
+ RFactor = (float)m_yPixels / (float)h;
+ if (RFactor > 1.0) RFactor = (float)m_xPixels / (float)w;
+ ResizeCoeff = (int)((float)w * RFactor);
+ }
+
+ IncDec = ResizeImage( w, h, ResizeCoeff - MargingSize);
+ targetBackgroundSize = QString::number(m_xPixels) + "x" + QString::number(m_yPixels);
+
+ *proc << "-verbose" << "-gravity" << "Center";
+
+ *proc << "-resize";
+ QString Temp, Temp2;
+ Temp2 = Temp.setNum( w ) + "x";
+ Temp2.append(Temp.setNum( h ));
+ *proc << Temp2;
+
+ *proc << "-quality";
+ QString Temp3;
+ Temp3.setNum(m_quality);
+ *proc << Temp3;
+
+ if ( IncDec == true ) // If the image is increased, enabled the filter.
+ {
+ *proc << "-filter" << m_resizeFilter;
+ }
+
+ *proc << item->pathSrc();
+
+ Temp2 = "xc:rgb(" + Temp.setNum(m_backgroundColor.red()) + ",";
+ Temp2.append(Temp.setNum(m_backgroundColor.green()) + ",");
+ Temp2.append(Temp.setNum(m_backgroundColor.blue()) + ")");
+ *proc << Temp2;
+
+ // ImageMagick composite program do not preserve exif data from original.
+ // Need to use "-profile" option for that.
+
+ *proc << "-profile" << item->pathSrc();
+
+ *proc << "-resize" << targetBackgroundSize + "!";
+
+ *proc << "-quality";
+ QString Temp4;
+ Temp4.setNum(m_quality);
+ *proc << Temp4;
+
+ *proc << albumDest + "/" + item->nameDest();
+ }
+
+ return(extractArguments(proc));
+}
+
+bool ResizeImagesDialog::prepareStartProcess(BatchProcessImagesItem *item,
+ const QString& /*albumDest*/)
+{
+ QImage img;
+
+ if ( img.load( item->pathSrc() ) == false )
+ {
+ item->changeResult(i18n("Skipped."));
+ item->changeError(i18n("image file format unsupported."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ResizeImagesDialog::ResizeImage( int &w, int &h, int SizeFactor)
+{
+ bool valRet;
+
+ if ( w > h )
+ {
+ h = (int)( (double)( h * SizeFactor ) / w );
+
+ if ( h == 0 ) h = 1;
+
+ if ( w < SizeFactor ) valRet = true;
+ else valRet = false;
+
+ w = SizeFactor;
+ }
+ else
+ {
+ w = (int)( (double)( w * SizeFactor ) / h );
+
+ if ( w == 0 ) w = 1;
+
+ if ( h < SizeFactor ) valRet = true;
+ else valRet = false;
+
+ h = SizeFactor;
+ }
+
+ return (valRet); // Return true is image increased, else true.
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/resizeimagesdialog.h b/kipi-plugins/batchprocessimages/resizeimagesdialog.h
new file mode 100644
index 0000000..93cdfd3
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/resizeimagesdialog.h
@@ -0,0 +1,92 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 RESIZEIMAGESDIALOG_H
+#define RESIZEIMAGESDIALOG_H
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "batchprocessimagesdialog.h"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class BatchProcessImagesItem;
+
+class ResizeImagesDialog : public BatchProcessImagesDialog
+{
+Q_OBJECT
+
+ public:
+
+ ResizeImagesDialog( KURL::List images, KIPI::Interface* interface, QWidget *parent=0 );
+ ~ResizeImagesDialog();
+
+ private slots:
+
+ void slotHelp(void);
+ void slotOptionsClicked(void);
+
+ protected:
+
+ QString m_resizeFilter;
+ QString m_paperSize;
+ QString m_printDpi;
+
+ QColor m_backgroundColor;
+ QColor m_bgColor;
+
+ bool m_customSettings;
+
+ int m_customXSize;
+ int m_customYSize;
+ int m_marging;
+ int m_customDpi;
+ int m_size;
+ int m_xPixels;
+ int m_yPixels;
+ int m_Width;
+ int m_Height;
+ int m_Border;
+ int m_fixedWidth;
+ int m_fixedHeight;
+ int m_quality;
+
+ QString makeProcess(KProcess* proc, BatchProcessImagesItem *item,
+ const QString& albumDest, bool previewMode);
+
+ void readSettings(void);
+ void saveSettings(void);
+ bool prepareStartProcess(BatchProcessImagesItem *item,
+ const QString& albumDest);
+
+ bool ResizeImage( int &w, int &h, int SizeFactor);
+
+ private:
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // RESIZEIMAGESDIALOG_H
diff --git a/kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp b/kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp
new file mode 100644
index 0000000..031cd8e
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/resizeoptionsdialog.cpp
@@ -0,0 +1,373 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qwidget.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qcolor.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kcolorbutton.h>
+#include <kmessagebox.h>
+
+// Local includes
+
+#include "resizeoptionsdialog.h"
+#include "resizeoptionsdialog.moc"
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+ResizeOptionsDialog::ResizeOptionsDialog(QWidget *parent, int ResizeType)
+ : KDialogBase( parent, "ResizeOptionsDialog", true,
+ i18n("Image-Resize Options"), Ok|Cancel, Ok, false)
+{
+ m_Type = ResizeType;
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout *dvlay = new QVBoxLayout( box, 10, spacingHint() );
+ QString whatsThis;
+
+ if (m_Type == 0) // Proportional (1 dim.)
+ {
+ QGroupBox * groupBox1 = new QGroupBox( 1, Qt::Horizontal, i18n("Resize Options"), box );
+
+ m_size = new KIntNumInput(640, groupBox1);
+ m_size->setRange(10, 10000, 1, true );
+ m_size->setLabel( i18n("New size (pixels):") );
+ QWhatsThis::add( m_size, i18n("<p>The new images' size in pixels.") );
+
+ m_quality = new KIntNumInput(75, groupBox1);
+ m_quality->setRange(0, 100, 1, true);
+ m_quality->setLabel( i18n("Image quality (percent):") );
+ QWhatsThis::add( m_quality, i18n("<p>Quality for JPEG images.") );
+
+ m_label_resizeFilter = new QLabel (i18n("Filter name:"), groupBox1);
+
+ m_resizeFilter = new QComboBox( false, groupBox1 );
+ m_resizeFilter->insertItem(i18n("Filter name","Bessel"));
+ m_resizeFilter->insertItem(i18n("Filter name","Blackman"));
+ m_resizeFilter->insertItem(i18n("Filter name","Box"));
+ m_resizeFilter->insertItem(i18n("Filter name","Catrom"));
+ m_resizeFilter->insertItem(i18n("Filter name","Cubic"));
+ m_resizeFilter->insertItem(i18n("Filter name","Gaussian"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hermite"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hanning"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hamming"));
+ m_resizeFilter->insertItem(i18n("Filter name","Lanczos"));
+ m_resizeFilter->insertItem(i18n("Filter name","Mitchell"));
+ m_resizeFilter->insertItem(i18n("Filter name","Point"));
+ m_resizeFilter->insertItem(i18n("Filter name","Quadratic"));
+ m_resizeFilter->insertItem(i18n("Filter name","Sinc"));
+ m_resizeFilter->insertItem(i18n("Filter name","Triangle"));
+ QWhatsThis::add( m_resizeFilter, i18n("<p>Select here the filter name for the resize-image process. "
+ "This filter will be used like a kernel convolution process "
+ "during the increased image size rendering. The default filter "
+ "is 'Lanczos'.") );
+ m_label_resizeFilter->setBuddy( m_resizeFilter );
+
+ dvlay->addWidget( groupBox1 );
+
+ m_label_size = new QLabel ( i18n("Note: the images will be resized to\n"
+ "this size. The width or the height of the\n"
+ "images will be automatically\n"
+ "selected in depending of the images orientation.\n"
+ "The images' aspect ratios are preserved."), box);
+ dvlay->addWidget( m_label_size );
+ }
+
+ if (m_Type == 1) // Proportional (2 dim.)
+ {
+ QGroupBox * groupBox1 = new QGroupBox( 2, Qt::Horizontal, i18n("Size Settings"), box );
+
+ m_label_Width = new QLabel (i18n("Width (pixels):"), groupBox1);
+ m_Width = new KIntNumInput(1024, groupBox1);
+ m_Width->setRange(100, 10000, 1, true );
+ QWhatsThis::add( m_Width, i18n("<p>The new images' width in pixels."));
+ m_label_Width->setBuddy( m_Width );
+
+ m_label_Height = new QLabel (i18n("Height (pixels):"), groupBox1);
+ m_Height = new KIntNumInput(768, groupBox1);
+ m_Height->setRange(100, 10000, 1, true );
+ QWhatsThis::add( m_Height, i18n("<p>The new images' height in pixels."));
+ m_label_Height->setBuddy( m_Height );
+
+ m_label_quality = new QLabel (i18n("Image quality (percent):"), groupBox1);
+ m_quality = new KIntNumInput(75, groupBox1);
+ m_quality->setRange(0, 100, 1, true);
+ QWhatsThis::add( m_quality, i18n("<p>Quality for JPEG images.") );
+ m_label_quality->setBuddy(m_quality);
+
+ dvlay->addWidget( groupBox1 );
+
+ QGroupBox * groupBox2 = new QGroupBox( 2, Qt::Horizontal, i18n("Rendering Settings"), box );
+
+ m_label_bgColor = new QLabel(i18n("Background color:"), groupBox2);
+ QColor bgColor = QColor( 0, 0, 0 ); // Black per default.
+ m_button_bgColor = new KColorButton( bgColor, groupBox2 );
+ QWhatsThis::add( m_button_bgColor, i18n( "<p>You can select here the background color to "
+ "be used when adapting the images' sizes." ));
+ m_label_bgColor->setBuddy( m_button_bgColor );
+
+ m_label_resizeFilter = new QLabel (i18n("Filter name:"), groupBox2);
+ m_resizeFilter = new QComboBox( false, groupBox2 );
+ m_resizeFilter->insertItem(i18n("Filter name","Bessel"));
+ m_resizeFilter->insertItem(i18n("Filter name","Blackman"));
+ m_resizeFilter->insertItem(i18n("Filter name","Box"));
+ m_resizeFilter->insertItem(i18n("Filter name","Catrom"));
+ m_resizeFilter->insertItem(i18n("Filter name","Cubic"));
+ m_resizeFilter->insertItem(i18n("Filter name","Gaussian"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hermite"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hanning"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hamming"));
+ m_resizeFilter->insertItem(i18n("Filter name","Lanczos"));
+ m_resizeFilter->insertItem(i18n("Filter name","Mitchell"));
+ m_resizeFilter->insertItem(i18n("Filter name","Point"));
+ m_resizeFilter->insertItem(i18n("Filter name","Quadratic"));
+ m_resizeFilter->insertItem(i18n("Filter name","Sinc"));
+ m_resizeFilter->insertItem(i18n("Filter name","Triangle"));
+ QWhatsThis::add( m_resizeFilter, i18n("<p>Select here the filter name for the resize-image process. "
+ "This filter will be used like a kernel convolution process "
+ "during the increased image size rendering. The default filter "
+ "is 'Lanczos'.") );
+ m_label_resizeFilter->setBuddy( m_resizeFilter );
+
+ m_label_border = new QLabel (i18n("Border size (pixels):"), groupBox2);
+ m_Border = new KIntNumInput(100, groupBox2);
+ m_Border->setRange(0, 1000, 1, true );
+ QWhatsThis::add( m_Border, i18n("<p>The border size around the images in pixels."));
+ m_label_border->setBuddy( m_Border );
+
+ dvlay->addWidget( groupBox2 );
+ }
+
+ if (m_Type == 2) // Non proportional
+ {
+ QGroupBox * groupBox1 = new QGroupBox( 1, Qt::Horizontal, i18n("Resize Options"), box );
+
+ m_fixedWidth = new KIntNumInput(640, groupBox1);
+ m_fixedWidth->setRange(10, 10000, 1, true );
+ m_fixedWidth->setLabel( i18n("New width (pixels):") );
+ QWhatsThis::add( m_fixedWidth, i18n("<p>The new images' width in pixels.") );
+
+ m_fixedHeight = new KIntNumInput(480, groupBox1);
+ m_fixedHeight->setRange(10, 10000, 1, true );
+ m_fixedHeight->setLabel( i18n("New height (pixels):") );
+ QWhatsThis::add( m_fixedHeight, i18n("<p>The new images' height in pixels.") );
+
+ m_quality = new KIntNumInput(75, groupBox1);
+ m_quality->setRange(0, 100, 1, true);
+ m_quality->setLabel( i18n("Image quality (percent):") );
+ QWhatsThis::add( m_quality, i18n("<p>Quality for JPEG images.") );
+
+ m_label_resizeFilter = new QLabel (i18n("Filter name:"), groupBox1);
+
+ m_resizeFilter = new QComboBox( false, groupBox1 );
+ m_resizeFilter->insertItem(i18n("Filter name","Bessel"));
+ m_resizeFilter->insertItem(i18n("Filter name","Blackman"));
+ m_resizeFilter->insertItem(i18n("Filter name","Box"));
+ m_resizeFilter->insertItem(i18n("Filter name","Catrom"));
+ m_resizeFilter->insertItem(i18n("Filter name","Cubic"));
+ m_resizeFilter->insertItem(i18n("Filter name","Gaussian"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hermite"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hanning"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hamming"));
+ m_resizeFilter->insertItem(i18n("Filter name","Lanczos"));
+ m_resizeFilter->insertItem(i18n("Filter name","Mitchell"));
+ m_resizeFilter->insertItem(i18n("Filter name","Point"));
+ m_resizeFilter->insertItem(i18n("Filter name","Quadratic"));
+ m_resizeFilter->insertItem(i18n("Filter name","Sinc"));
+ m_resizeFilter->insertItem(i18n("Filter name","Triangle"));
+ QWhatsThis::add( m_resizeFilter, i18n("<p>Select here the filter name for the resize-image process. "
+ "This filter will be used like a kernel convolution process "
+ "during the increased image size rendering. The default filter "
+ "is 'Lanczos'.") );
+ m_label_resizeFilter->setBuddy( m_resizeFilter );
+
+ dvlay->addWidget( groupBox1 );
+ }
+
+ if (m_Type == 3) // Prepare to print
+ {
+ m_customSettings = new QCheckBox( i18n("Use custom settings"), box);
+ QWhatsThis::add( m_customSettings, i18n("<p>If this option is enabled, "
+ "all printing settings can be customized."));
+ dvlay->addWidget( m_customSettings );
+
+ QGroupBox * groupBox1 = new QGroupBox( 2, Qt::Horizontal, i18n("Printing Standard Settings"), box );
+
+ m_label_paperSize = new QLabel (i18n("Paper size (cm):"), groupBox1);
+ m_paperSize = new QComboBox( false, groupBox1 );
+ m_paperSize->insertItem("9x13");
+ m_paperSize->insertItem("10x15");
+ m_paperSize->insertItem("13x19");
+ m_paperSize->insertItem("15x21");
+ m_paperSize->insertItem("18x24");
+ m_paperSize->insertItem("20x30");
+ m_paperSize->insertItem("21x30");
+ m_paperSize->insertItem("30x40");
+ m_paperSize->insertItem("30x45");
+ m_paperSize->insertItem("40x50");
+ m_paperSize->insertItem("50x75");
+ QWhatsThis::add( m_paperSize, i18n("<p>The standard photographic paper sizes in centimeters."));
+ m_label_paperSize->setBuddy( m_paperSize );
+
+ m_label_printDpi = new QLabel (i18n("Print resolution (dpi):"), groupBox1);
+ m_printDpi = new QComboBox( false, groupBox1 );
+ m_printDpi->insertItem("75");
+ m_printDpi->insertItem("150");
+ m_printDpi->insertItem("300");
+ m_printDpi->insertItem("600");
+ m_printDpi->insertItem("1200");
+ m_printDpi->insertItem("1400");
+ m_printDpi->insertItem("2400");
+ QWhatsThis::add( m_printDpi, i18n("<p>The standard print resolutions in dots per inch."));
+ m_label_printDpi->setBuddy( m_printDpi );
+
+ dvlay->addWidget( groupBox1 );
+
+ QGroupBox * groupBox2 = new QGroupBox( 2, Qt::Horizontal, i18n("Printing Custom Settings"), box );
+
+ m_label_customXSize = new QLabel (i18n("Paper width (cm):"), groupBox2);
+ m_customXSize = new KIntNumInput(10, groupBox2);
+ m_customXSize->setRange(1, 100, 1, true );
+ QWhatsThis::add( m_customXSize, i18n("<p>The customized width of the photographic paper size "
+ "in centimeters."));
+ m_label_customXSize->setBuddy( m_customXSize );
+
+ m_label_customYSize = new QLabel (i18n("Paper height (cm):"), groupBox2);
+ m_customYSize = new KIntNumInput(15, groupBox2);
+ m_customYSize->setRange(1, 100, 1, true );
+ QWhatsThis::add( m_customYSize, i18n("<p>The customized height of the photographic paper size "
+ "in centimeters."));
+ m_label_customYSize->setBuddy( m_customYSize );
+
+ m_label_customDpi = new QLabel (i18n("Print resolution (dpi):"), groupBox2);
+ m_customDpi = new KIntNumInput(300, groupBox2);
+ m_customDpi->setRange(10, 5000, 10, true );
+ QWhatsThis::add( m_customDpi, i18n("<p>The customized print resolution in dots per inch."));
+ m_label_customDpi->setBuddy( m_customDpi );
+
+ dvlay->addWidget( groupBox2 );
+
+ QGroupBox * groupBox3 = new QGroupBox( 2, Qt::Horizontal, i18n("Rendering Settings"), box );
+
+ m_label_backgroundColor = new QLabel(i18n("Background color:"), groupBox3);
+ QColor backgroundColor = QColor( 255, 255, 255 ); // White per default.
+ m_button_backgroundColor = new KColorButton( backgroundColor, groupBox3 );
+ QWhatsThis::add( m_button_backgroundColor, i18n( "<p>You can select here the background color to "
+ "be used when adapting the images' sizes." ));
+ m_label_backgroundColor->setBuddy( m_button_backgroundColor );
+
+ m_label_resizeFilter = new QLabel (i18n("Filter name:"), groupBox3);
+ m_resizeFilter = new QComboBox( false, groupBox3 );
+ m_resizeFilter->insertItem(i18n("Filter name","Bessel"));
+ m_resizeFilter->insertItem(i18n("Filter name","Blackman"));
+ m_resizeFilter->insertItem(i18n("Filter name","Box"));
+ m_resizeFilter->insertItem(i18n("Filter name","Catrom"));
+ m_resizeFilter->insertItem(i18n("Filter name","Cubic"));
+ m_resizeFilter->insertItem(i18n("Filter name","Gaussian"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hermite"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hanning"));
+ m_resizeFilter->insertItem(i18n("Filter name","Hamming"));
+ m_resizeFilter->insertItem(i18n("Filter name","Lanczos"));
+ m_resizeFilter->insertItem(i18n("Filter name","Mitchell"));
+ m_resizeFilter->insertItem(i18n("Filter name","Point"));
+ m_resizeFilter->insertItem(i18n("Filter name","Quadratic"));
+ m_resizeFilter->insertItem(i18n("Filter name","Sinc"));
+ m_resizeFilter->insertItem(i18n("Filter name","Triangle"));
+ QWhatsThis::add( m_resizeFilter, i18n("<p>Select here the filter name for the resize-image process. "
+ "This filter will be used like a kernel convolution process "
+ "during the increased image size rendering. The default filter "
+ "is 'Lanczos'.") );
+ m_label_resizeFilter->setBuddy( m_resizeFilter );
+
+ m_label_marging = new QLabel (i18n("Margin size (mm):"), groupBox3);
+ m_marging = new KIntNumInput(1, groupBox3);
+ m_marging->setRange(0, 80, 1, true );
+ QWhatsThis::add( m_marging, i18n("<p>The margin around the images in millimeters."));
+ m_label_marging->setBuddy( m_marging );
+
+ m_label_quality = new QLabel (i18n("Image quality (percent):"), groupBox3);
+ m_quality = new KIntNumInput(75, groupBox3);
+ m_quality->setRange(0, 100, 1, true);
+ QWhatsThis::add( m_quality, i18n("<p>Quality for JPEG images.") );
+ m_label_quality->setBuddy(m_quality);
+
+ dvlay->addWidget( groupBox3 );
+
+ connect(m_customSettings, SIGNAL( toggled(bool) ),
+ this, SLOT( slotCustomSettingsEnabled(bool) ) );
+
+ slotCustomSettingsEnabled(false);
+ }
+}
+
+ResizeOptionsDialog::~ResizeOptionsDialog()
+{
+}
+
+void ResizeOptionsDialog::slotCustomSettingsEnabled(bool val)
+{
+ m_label_paperSize->setEnabled( !val );
+ m_paperSize->setEnabled( !val );
+ m_label_printDpi->setEnabled( !val );
+ m_printDpi->setEnabled( !val );
+
+ m_label_customXSize->setEnabled( val );
+ m_customXSize->setEnabled( val );
+ m_label_customYSize->setEnabled( val );
+ m_customYSize->setEnabled( val );
+ m_label_customDpi->setEnabled( val );
+ m_customDpi->setEnabled( val );
+}
+
+void ResizeOptionsDialog::slotOk()
+{
+ if (m_Type == 3) // Prepare to print
+ {
+ if (m_customSettings->isChecked() == true)
+ {
+ if (m_customXSize > m_customYSize)
+ {
+ KMessageBox::sorry(this, i18n("You must enter a custom height greater than the custom width: "
+ "the photographic paper must be vertically orientated."));
+ return;
+ }
+ }
+ }
+
+ accept();
+}
+
+} // NameSpace KIPIBatchProcessImagesPlugin
diff --git a/kipi-plugins/batchprocessimages/resizeoptionsdialog.h b/kipi-plugins/batchprocessimages/resizeoptionsdialog.h
new file mode 100644
index 0000000..09a98ed
--- /dev/null
+++ b/kipi-plugins/batchprocessimages/resizeoptionsdialog.h
@@ -0,0 +1,101 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-01
+ * Description : a kipi plugin to batch process images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 RESIZEOPTIONSDIALOG_H
+#define RESIZEOPTIONSDIALOG_H
+
+// Include files for Qt
+
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+class QLabel;
+class QComboBox;
+class QCheckBox;
+
+class KIntNumInput;
+class KColorButton;
+
+namespace KIPIBatchProcessImagesPlugin
+{
+
+class ResizeOptionsDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+
+ ResizeOptionsDialog(QWidget *parent=0, int ResizeType = 0);
+ ~ResizeOptionsDialog();
+
+ QLabel *m_label_size;
+ QLabel *m_label_resizeFilter;
+ QLabel *m_label_paperSize;
+ QLabel *m_label_printDpi;
+ QLabel *m_label_customXSize;
+ QLabel *m_label_customYSize;
+ QLabel *m_label_customDpi;
+ QLabel *m_label_backgroundColor;
+ QLabel *m_label_marging;
+ QLabel *m_label_Width;
+ QLabel *m_label_Height;
+ QLabel *m_label_bgColor;
+ QLabel *m_label_border;
+ QLabel *m_label_quality;
+
+ KIntNumInput *m_size;
+ KIntNumInput *m_customXSize;
+ KIntNumInput *m_customYSize;
+ KIntNumInput *m_customDpi;
+ KIntNumInput *m_marging;
+ KIntNumInput *m_Width;
+ KIntNumInput *m_Height;
+ KIntNumInput *m_Border;
+ KIntNumInput *m_fixedWidth;
+ KIntNumInput *m_fixedHeight;
+ KIntNumInput *m_quality;
+
+ QCheckBox *m_customSettings;
+
+ KColorButton *m_button_backgroundColor;
+ KColorButton *m_button_bgColor;
+
+ QComboBox *m_resizeFilter;
+ QComboBox *m_paperSize;
+ QComboBox *m_printDpi;
+
+ protected slots:
+
+ void slotCustomSettingsEnabled(bool val);
+ void slotOk();
+
+ protected:
+
+ int m_Type;
+};
+
+} // NameSpace KIPIBatchProcessImagesPlugin
+
+#endif // RESIZEOPTIONSDIALOG_H
diff --git a/kipi-plugins/calendar/Makefile.am b/kipi-plugins/calendar/Makefile.am
new file mode 100644
index 0000000..4094a88
--- /dev/null
+++ b/kipi-plugins/calendar/Makefile.am
@@ -0,0 +1,21 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_calendar.la
+kipiplugin_calendar_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+kipiplugin_calendar_la_SOURCES = plugin_calendar.cpp calwizard.cpp \
+ caltemplate.cpp calsettings.cpp calwidget.cpp calpainter.cpp calselect.cpp \
+ monthwidget.cpp calformatter.cpp calevents.cpp caleventsbase.ui
+
+kipiplugin_calendar_la_LIBADD = $(LIB_KDEPRINT) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_calendar_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins -lkcal
+
+kde_services_DATA = kipiplugin_calendar.desktop
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_calendar.pot
+
+noinst_HEADERS = calformatter.h calevents.h
diff --git a/kipi-plugins/calendar/calevents.cpp b/kipi-plugins/calendar/calevents.cpp
new file mode 100644
index 0000000..b34dfb4
--- /dev/null
+++ b/kipi-plugins/calendar/calevents.cpp
@@ -0,0 +1,79 @@
+/* ============================================================
+ * File : calevents.cpp
+ * Author: Maciek Borowka <maciek_AT_borowka.net>
+ * Date : 2005-11-23
+ * Description : The implementation of a new "create calendar"
+ * wizard page.
+ *
+ * Copyright 2005 by Maciek Borowka
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+#include <qpushbutton.h>
+
+#include <kiconloader.h>
+#include <kfiledialog.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "calevents.h"
+
+namespace KIPICalendarPlugin {
+
+CalEvents::CalEvents(QWidget *parent, const char *name)
+ : CalEventsBase(parent, name)
+{
+ KIconLoader * icons = new KIconLoader( QString( "MenuDlg" ) );
+ ohBtn->setPixmap( icons->loadIcon( QString( "fileopen" ), KIcon::Toolbar ) );
+ fhBtn->setPixmap( icons->loadIcon( QString( "fileopen" ), KIcon::Toolbar ) );
+}
+
+
+CalEvents::~CalEvents()
+{
+}
+
+
+void CalEvents::ohChooseSlot()
+{
+ QString temp;
+
+ temp = KFileDialog::getOpenFileName(ohFileEdit->text(),
+ QString( "*.ics" ),
+ this,
+ i18n("Select 'Official Holidays' calendar file") );
+ if( temp.isEmpty() )
+ return;
+
+ ohFileEdit->setText( temp );
+}
+
+void CalEvents::fhChooseSlot()
+{
+ QString temp;
+
+ temp = KFileDialog::getOpenFileName(fhFileEdit->text(),
+ QString( "*.ics" ),
+ this,
+ i18n("Select 'Family Holidays' calendar file") );
+ if( temp.isEmpty() )
+ return;
+
+ fhFileEdit->setText( temp );
+}
+
+}
+
+#include "calevents.moc"
diff --git a/kipi-plugins/calendar/calevents.h b/kipi-plugins/calendar/calevents.h
new file mode 100644
index 0000000..621574a
--- /dev/null
+++ b/kipi-plugins/calendar/calevents.h
@@ -0,0 +1,50 @@
+/* ============================================================
+ * File : calevents.h
+ * Author: Maciek Borowka <maciek_AT_borowka.net>
+ * Date : 2005-11-23
+ * Description : The declaration of a new "create calendar"
+ * wizard page.
+ *
+ * Copyright 2005 by Maciek Borowka
+ *
+ * This program is free software; you can redistribute 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 KIPICALENDARPLUGINCALEVENTS_H
+#define KIPICALENDARPLUGINCALEVENTS_H
+
+#include <qwidget.h>
+
+#include "caleventsbase.h"
+
+namespace KIPICalendarPlugin {
+
+/**
+@author Maciek Borowka
+*/
+class CalEvents : public CalEventsBase
+{
+Q_OBJECT
+public:
+ CalEvents(QWidget *parent = 0, const char *name = 0);
+
+ ~CalEvents();
+
+public slots:
+ virtual void ohChooseSlot();
+ virtual void fhChooseSlot();
+};
+
+}
+
+#endif
diff --git a/kipi-plugins/calendar/caleventsbase.ui b/kipi-plugins/calendar/caleventsbase.ui
new file mode 100644
index 0000000..99267b0
--- /dev/null
+++ b/kipi-plugins/calendar/caleventsbase.ui
@@ -0,0 +1,210 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>CalEventsBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>427</width>
+ <height>455</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>CalEventBaseWidget</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Select an optional calendar file with the official holidays</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>ohFileEdit</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>ohBtn</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>You can download a calendar for your country from http://www.icalshare.com/ or other sites.
+This is fully optional. All the events from this calendar will be printed red.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Select an optional calendar file with your "family holidays"</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>fhFileEdit</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>fhBtn</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <italic>1</italic>
+ </font>
+ </property>
+ <property name="text">
+ <string>You can create such a calendar using KOrganizer or any other calendar program.
+This is fully optional. All the events from this calendar will be printed green.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>41</width>
+ <height>140</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>fhBtn</sender>
+ <signal>clicked()</signal>
+ <receiver>Form1</receiver>
+ <slot>fhChooseSlot()</slot>
+ </connection>
+ <connection>
+ <sender>ohBtn</sender>
+ <signal>clicked()</signal>
+ <receiver>Form1</receiver>
+ <slot>ohChooseSlot()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>fhChooseSlot()</slot>
+ <slot>ohChooseSlot()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kipi-plugins/calendar/calformatter.cpp b/kipi-plugins/calendar/calformatter.cpp
new file mode 100644
index 0000000..fa02c2c
--- /dev/null
+++ b/kipi-plugins/calendar/calformatter.cpp
@@ -0,0 +1,218 @@
+/* ============================================================
+ * File : calformatter.cpp
+ * Author: Maciek Borowka <maciek_AT_borowka.net>
+ * Date : 2005-11-23
+ * Description : The implementation of a class that decides which
+ * cell of the calendar should be painted with which color.
+ *
+ * Copyright 2005 by Maciek Borowka
+ * Revised by Orgad Shaneh, 2007
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+#include <qdatetime.h>
+#include <qcolor.h>
+#include <qmap.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kcalendarsystem.h>
+#include <libkcal/calendarlocal.h>
+
+#include "calformatter.h"
+
+
+namespace KIPICalendarPlugin {
+
+
+class CalFormatter::Data
+{
+public:
+ class Day {
+ public:
+ Day(){};
+ Day(QColor c, QString d): color(c), description(d) {};
+
+ QColor color;
+ QString description;
+ };
+
+
+ QString ohFile;
+ QString fhFile;
+
+ QMap<QDate, Day> oh;//official holidays
+ QMap<QDate, Day> fh;//family holidays
+
+ Data()
+ {
+
+//you define a holiday that way:
+oh[QDate(2005, 1, 1)] = Day(Qt::red, "New year!");
+//oh[QDate(2005, 1, 4)] = Day(Qt::red, "Fete Nat");
+
+
+fh[QDate(2005,1,3)] = Day(Qt::green, "Adam");
+//fh[QDate(2005, 1, 14)] = Day(Qt::green, "Maciek");
+
+
+ };
+
+};
+
+CalFormatter::CalFormatter() : initialized(false)
+{
+
+}
+
+
+CalFormatter::~CalFormatter()
+{
+}
+
+void CalFormatter::init(int year, const QString & ohFile, const QString & fhFile)
+{
+ if (initialized)
+ return;
+
+ d = new Data();
+ year_ = year;
+ d->ohFile = ohFile;
+ d->fhFile = fhFile;
+
+ kdDebug(51000) << "Loading calendar from file" << endl;
+ KCal::CalendarLocal * calendar;
+
+ if (not(ohFile.isEmpty())) {
+ calendar = new KCal::CalendarLocal("UTC");
+ if (calendar->load(ohFile)) {
+ QDate dtFirst, dtLast;
+ KGlobal::locale()->calendar()->setYMD(dtFirst, year_, 1, 1);
+ KGlobal::locale()->calendar()->setYMD(dtLast, year_ + 1, 1, 1);
+ dtLast = dtLast.addDays(-1);
+
+ KCal::Event::List list = calendar->rawEvents(dtFirst, dtLast);
+ KCal::Event::List::iterator it;
+ KCal::Recurrence *recur;
+
+ QDateTime dtCurrent;
+ int counter = 0;
+ for ( it = list.begin(); it != list.end(); ++it )
+ {
+ kdDebug(51000) << (*it)->summary() << endl << "--------" << endl;
+ counter++;
+ if ((*it)->doesRecur())
+ {
+ recur = (*it)->recurrence();
+ for (dtCurrent = recur->getNextDateTime(dtFirst.addDays(-1)); (dtCurrent <= dtLast) && dtCurrent.isValid(); dtCurrent = recur->getNextDateTime(dtCurrent))
+ {
+ kdDebug(51000) << dtCurrent.toString() << endl;
+ d->oh[dtCurrent.date()] = CalFormatter::Data::Day(Qt::red, (*it)->summary());
+ }
+
+ }
+ else
+ d->oh[(*it)->dtStart().date()] = CalFormatter::Data::Day(Qt::red, (*it)->summary());
+ }
+ kdDebug(51000) << "Loaded " << counter << " events for year " << year_ << endl;
+ }
+ delete calendar;
+ }
+
+ if (not(fhFile.isEmpty())) {
+ calendar = new KCal::CalendarLocal("UTC");
+ if (calendar->load(fhFile)) {
+
+ KCal::Event::List list = calendar->rawEvents(QDate(year_,1,1), QDate(year_,12,31));
+ KCal::Event::List::iterator it;
+
+ QString eventDate;
+ int counter = 0;
+ for ( it = list.begin(); it != list.end(); ++it )
+ {
+ counter++;
+ d->fh[(*it)->dtStart().date()] = CalFormatter::Data::Day(Qt::red, (*it)->summary());
+ //kdDebug(51000) << eventDate << "----" << (*it)->summary() << endl;
+ }
+ kdDebug(51000) << "Loaded " << counter << " events for year " << year_ << endl;
+ }
+ delete calendar;
+ }
+}
+
+bool CalFormatter::isPrayDay(int month, int day)
+{
+ QDate dt;
+ KGlobal::locale()->calendar()->setYMD(dt, year_, month, day);
+ return (dt.dayOfWeek() == KGlobal::locale()->calendar()->weekDayOfPray());
+}
+
+/*!
+ Returns true if special formatting is to be applied to the particular day
+ */
+bool KIPICalendarPlugin::CalFormatter::isSpecial(int month, int day)
+{
+ QDate dt;
+ KGlobal::locale()->calendar()->setYMD(dt, year_, month, day);
+
+ return (isPrayDay(month,day) || d->oh.contains(dt) || d->fh.contains(dt));
+}
+
+
+/*!
+ Returns the color to be used for painting of the day info
+ */
+QColor KIPICalendarPlugin::CalFormatter::getDayColor(int month, int day)
+{
+ QDate dt;
+ KGlobal::locale()->calendar()->setYMD(dt, year_, month, day);
+
+ if (isPrayDay(month, day))
+ return Qt::red;
+
+ if (d->oh.contains(dt))
+ return Qt::red;
+
+ if (d->fh.contains(dt))
+ return Qt::green;
+
+ //default
+ return Qt::black;
+}
+
+
+/*!
+ Returns the description of the day to be painted on the calendar.
+ */
+QString KIPICalendarPlugin::CalFormatter::getDayDescr(int month, int day)
+{
+ QDate dt;
+ KGlobal::locale()->calendar()->setYMD(dt, year_, month, day);
+
+ QString ret;
+
+ if (d->oh.contains(dt))
+ ret = d->oh[dt].description;
+
+ if (d->fh.contains(dt)) {
+ if (ret.isNull())
+ return d->fh[dt].description;
+ else
+ return ret.append(";").append(d->fh[dt].description);
+ }
+
+ return ret;
+}
+}
diff --git a/kipi-plugins/calendar/calformatter.h b/kipi-plugins/calendar/calformatter.h
new file mode 100644
index 0000000..d66e652
--- /dev/null
+++ b/kipi-plugins/calendar/calformatter.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ * File : calformatter.h
+ * Author: Maciek Borowka <maciek_AT_borowka.net>
+ * Date : 2005-11-23
+ * Description : The declaration of a class that decides which
+ * cell of the calendar should be painted with which color.
+ *
+ * Copyright 2005 by Maciek Borowka
+ *
+ * This program is free software; you can redistribute 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 KIPICALENDARPLUGINCALFORMATTER_H
+#define KIPICALENDARPLUGINCALFORMATTER_H
+
+#include <qobject.h>
+
+namespace KIPICalendarPlugin {
+
+/**
+@author Maciek Borowka
+*/
+class CalFormatter : public QObject
+{
+Q_OBJECT
+public:
+
+ CalFormatter();
+ ~CalFormatter();
+
+ bool isSpecial(int month, int day);
+
+ QColor getDayColor(int month, int day);
+ QString getDayDescr(int month, int day);
+
+ void init(int year, const QString & ohFile, const QString & fhFile);
+
+protected:
+ int year_;
+
+ bool isPrayDay(int month, int day);
+
+ bool initialized;
+
+ class Data;
+ Data *d;
+};
+
+}
+
+#endif
diff --git a/kipi-plugins/calendar/calpainter.cpp b/kipi-plugins/calendar/calpainter.cpp
new file mode 100644
index 0000000..998cb85
--- /dev/null
+++ b/kipi-plugins/calendar/calpainter.cpp
@@ -0,0 +1,625 @@
+/* ============================================================
+ * File : calpainter.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-02
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qpainter.h>
+#include <qrect.h>
+#include <qpaintdevice.h>
+#include <qdatetime.h>
+#include <qpaintdevicemetrics.h>
+#include <qstring.h>
+#include <qimage.h>
+#include <qtimer.h>
+#include <qwmatrix.h>
+
+// KDE includes.
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdeversion.h>
+#include <kcalendarsystem.h>
+#include <kdebug.h>
+
+// Local includes.
+
+#include "calpainter.h"
+#include "calsettings.h"
+#include "calformatter.h"
+
+namespace KIPICalendarPlugin
+{
+
+CalPainter::CalPainter(QPaintDevice *pd)
+{
+ pd_ = pd;
+}
+
+CalPainter::~CalPainter()
+{
+}
+
+void CalPainter::setYearMonth(int year, int month)
+{
+ year_ = year;
+ month_ = month;
+}
+
+
+void CalPainter::paint(bool useDeviceMetrics)
+{
+ if (!pd_) return;
+
+ QPainter *painter = new QPainter();
+ painter->begin(pd_);
+
+ int width = 0;
+ int height = 0;
+
+ CalParams& params = CalSettings::instance()->calParams;
+ if (!useDeviceMetrics) {
+ width = params.width;
+ height = params.height;
+ }
+ else {
+ QPaintDeviceMetrics metrics( painter->device());
+ width = metrics.width();
+ height = metrics.height();
+ }
+
+ // --------------------------------------------------
+
+ int days[42];
+ int startDayOffset = KGlobal::locale()->weekStartDay();
+
+ for (int i=0; i<42; i++)
+ days[i] = -1;
+
+ QDate d;
+ KGlobal::locale()->calendar()->setYMD(d, year_, month_, 1);
+ int s = d.dayOfWeek();
+
+ if (s+7-startDayOffset >= 7)
+ s=s-7;
+
+ for (int i=s; i<(s+KGlobal::locale()->calendar()->daysInMonth(d)); i++) {
+ days[i + (7-startDayOffset)] = i-s+1;
+ }
+
+ // -----------------------------------------------
+
+ QRect rCal, rImage, rCalHeader;
+ int cellSizeX;
+ int cellSizeY;
+
+ switch (params.imgPos) {
+
+ case(CalParams::Top): {
+
+ rImage = QRect(0,0,0,0);
+ rImage.setWidth(width);
+ rImage.setHeight((int)(height *
+ (params.ratio)/(params.ratio + 100)));
+
+ int remainingHeight = height - rImage.height();
+ cellSizeX = (width - 20)/7;
+ cellSizeY = remainingHeight/8;
+
+ rCal = QRect(0,0,0,0);
+ rCal.setWidth(cellSizeX*7);
+ rCal.setHeight((int)(cellSizeY*7));
+
+ rCalHeader = QRect(0,0,0,0);
+ rCalHeader.setWidth(rCal.width());
+ rCalHeader.setHeight((int)(cellSizeY));
+ rCalHeader.moveTop(rImage.bottom());
+
+ rCalHeader.moveLeft(width/2 - rCalHeader.width()/2);
+ rCal.moveTopLeft(rCalHeader.bottomLeft());
+
+ break;
+
+ }
+
+ case(CalParams::Left): {
+
+ rImage = QRect(0,0,0,0);
+ rImage.setHeight(height);
+ rImage.setWidth((int)(width *
+ (params.ratio)/(params.ratio + 100)));
+
+ int remainingWidth = width - rImage.width();
+ cellSizeX = remainingWidth/8;
+ cellSizeY = (height - 20)/7;
+
+ rCal = QRect(0,0,0,0);
+ rCal.setWidth(cellSizeX*7);
+ rCal.setHeight(cellSizeY*7);
+
+ rCalHeader = QRect(0,0,0,0);
+ rCalHeader.setWidth(rCal.width());
+ rCalHeader.setHeight(cellSizeY);
+ rCalHeader.moveLeft(rImage.right() + cellSizeX);
+ rCalHeader.moveTop(height/2 -
+ (rCalHeader.height()+rCal.height()/2));
+
+ rCal.moveTopLeft(rCalHeader.bottomLeft());
+
+ break;
+ }
+
+ case(CalParams::Right): {
+
+ rImage = QRect(0,0,0,0);
+ rImage.setHeight(height);
+ rImage.setWidth((int)(width *
+ (params.ratio)/(params.ratio + 100)));
+
+ int remainingWidth = width - rImage.width();
+ cellSizeX = remainingWidth/8;
+ cellSizeY = (height - 20)/7;
+
+ rCal = QRect(0,0,0,0);
+ rCal.setWidth(cellSizeX*7);
+ rCal.setHeight(cellSizeY*7);
+
+ rCalHeader = QRect(0,0,0,0);
+ rCalHeader.setWidth(rCal.width());
+ rCalHeader.setHeight(cellSizeY);
+ rCalHeader.moveTop(height/2 -
+ (rCalHeader.height()+rCal.height()/2));
+ rCal.moveTop(rCalHeader.bottom());
+
+ rImage.moveLeft(width - rImage.width());
+
+ break;
+ }
+
+ default:
+ return;
+ }
+
+ int fontPixels = (int)((float)cellSizeX/3.0);
+ params.baseFont.setPixelSize(fontPixels);
+
+ // ---------------------------------------------------------------
+
+ painter->fillRect(0,0,width, height, Qt::white);
+ painter->fillRect(rImage, Qt::black);
+ painter->setFont(params.baseFont);
+
+ // ---------------------------------------------------------------
+
+ painter->save();
+ QFont f(params.baseFont);
+ f.setBold(true);
+ f.setPixelSize(f.pixelSize() + 5);
+ painter->setFont(f);
+ painter->drawText(rCalHeader, Qt::AlignLeft|Qt::AlignVCenter,
+ QString::number(year_));
+#if KDE_IS_VERSION(3,2,0)
+ painter->drawText(rCalHeader, Qt::AlignRight|Qt::AlignVCenter,
+ KGlobal::locale()->calendar()->monthName(month_, year_));
+#else
+ painter->drawText(rCalHeader, Qt::AlignRight|Qt::AlignVCenter,
+ KGlobal::locale()->monthName(month_));
+#endif
+ painter->restore();
+
+ // ---------------------------------------------------------------
+
+ int sx, sy;
+ QRect r, rsmall;
+
+ r.setWidth(cellSizeX);
+ r.setHeight(cellSizeY);
+
+ int index = 0;
+
+ painter->save();
+
+ painter->setPen(Qt::red);
+ sy = rCal.top();
+ for (int i=0; i<7; i++)
+ {
+ int dayname = i + startDayOffset;
+ if (dayname > 7)
+ dayname = dayname-7;
+
+ sx = cellSizeX * i + rCal.left();
+ r.moveTopLeft(QPoint(sx,sy));
+ rsmall = r;
+ rsmall.setWidth(r.width() - 2);
+ rsmall.setHeight(r.height() - 2);
+#if KDE_IS_VERSION(3,2,0)
+ painter->drawText(rsmall, Qt::AlignRight|Qt::AlignBottom,
+ KGlobal::locale()->calendar()->weekDayName(dayname, true));
+#else
+ painter->drawText(rsmall, Qt::AlignRight|Qt::AlignBottom,
+ KGlobal::locale()->weekDayName(dayname, true));
+#endif
+
+ }
+
+ painter->restore();
+
+ for (int j=0; j<6; j++) {
+ sy = cellSizeY * (j + 1) + rCal.top();
+ for (int i=0; i<7; i++) {
+ sx = cellSizeX * i + rCal.left();
+ r.moveTopLeft(QPoint(sx,sy));
+ rsmall = r;
+ rsmall.setWidth(r.width() - 2);
+ rsmall.setHeight(r.height() - 2);
+ if (days[index] != -1)
+ painter->drawText(rsmall, Qt::AlignRight|Qt::AlignBottom,
+ QString::number(days[index]));
+ index++;
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ if (params.drawLines) {
+
+ sx = rCal.left();
+ for (int j=0; j<8; j++) {
+ sy = cellSizeY * j + rCal.top();
+ painter->drawLine(sx,sy,rCal.right(),sy);
+ }
+
+ sy = rCal.top();
+ for (int i=0; i<8; i++) {
+ sx = cellSizeX * i + rCal.left();
+ painter->drawLine(sx,sy,sx,rCal.bottom());
+ }
+
+ }
+
+
+ painter->end();
+ delete painter;
+}
+
+CalBlockPainter::CalBlockPainter(QObject *parent, int year, int month,
+ const KURL& imagePath, int angle, CalFormatter *formatter, QPainter *painter)
+ : QObject(parent), painter_(painter)
+{
+ int width = 0;
+ int height = 0;
+
+ CalParams& params = CalSettings::instance()->calParams;
+
+ QPaintDeviceMetrics metrics( painter->device());
+ width = metrics.width();
+ height = metrics.height();
+
+ // --------------------------------------------------
+
+ int days[42];
+ int startDayOffset = KGlobal::locale()->weekStartDay();
+
+ for (int i=0; i<42; i++)
+ days[i] = -1;
+
+ QDate d;
+ KGlobal::locale()->calendar()->setYMD(d, year, month, 1);
+ int s = d.dayOfWeek();
+
+ if (s+7-startDayOffset >= 7)
+ s=s-7;
+
+ for (int i=s; i<(s+KGlobal::locale()->calendar()->daysInMonth(d)); i++) {
+ days[i+(7-startDayOffset)] = i-s+1;
+ }
+
+ // -----------------------------------------------
+
+ QRect rCal, rImage, rCalHeader;
+ int cellSizeX;
+ int cellSizeY;
+
+ switch (params.imgPos) {
+
+ case(CalParams::Top): {
+
+ rImage = QRect(0,0,0,0);
+ rImage.setWidth(width);
+ rImage.setHeight((int)(height *
+ (params.ratio)/(params.ratio + 100)));
+
+ int remainingHeight = height - rImage.height();
+ cellSizeX = (width - 20)/7;
+ cellSizeY = remainingHeight/8;
+
+ rCal = QRect(0,0,0,0);
+ rCal.setWidth(cellSizeX*7);
+ rCal.setHeight((int)(cellSizeY*7));
+
+ rCalHeader = QRect(0,0,0,0);
+ rCalHeader.setWidth(rCal.width());
+ rCalHeader.setHeight((int)(cellSizeY));
+ rCalHeader.moveTop(rImage.bottom());
+
+ rCalHeader.moveLeft(width/2 - rCalHeader.width()/2);
+ rCal.moveTopLeft(rCalHeader.bottomLeft());
+
+ break;
+
+ }
+
+ case(CalParams::Left): {
+
+ rImage = QRect(0,0,0,0);
+ rImage.setHeight(height);
+ rImage.setWidth((int)(width *
+ (params.ratio)/(params.ratio + 100)));
+
+ int remainingWidth = width - rImage.width();
+ cellSizeX = remainingWidth/8;
+ cellSizeY = (height - 20)/7;
+
+ rCal = QRect(0,0,0,0);
+ rCal.setWidth(cellSizeX*7);
+ rCal.setHeight(cellSizeY*7);
+
+ rCalHeader = QRect(0,0,0,0);
+ rCalHeader.setWidth(rCal.width());
+ rCalHeader.setHeight(cellSizeY);
+ rCalHeader.moveLeft(rImage.right() + cellSizeX);
+ rCalHeader.moveTop(height/2 -
+ (rCalHeader.height()+rCal.height()/2));
+
+ rCal.moveTopLeft(rCalHeader.bottomLeft());
+
+ break;
+ }
+
+ case(CalParams::Right): {
+
+ rImage = QRect(0,0,0,0);
+ rImage.setHeight(height);
+ rImage.setWidth((int)(width *
+ (params.ratio)/(params.ratio + 100)));
+
+ int remainingWidth = width - rImage.width();
+ cellSizeX = remainingWidth/8;
+ cellSizeY = (height - 20)/7;
+
+ rCal = QRect(0,0,0,0);
+ rCal.setWidth(cellSizeX*7);
+ rCal.setHeight(cellSizeY*7);
+
+ rCalHeader = QRect(0,0,0,0);
+ rCalHeader.setWidth(rCal.width());
+ rCalHeader.setHeight(cellSizeY);
+ rCalHeader.moveTop(height/2 -
+ (rCalHeader.height()+rCal.height()/2));
+ rCal.moveTop(rCalHeader.bottom());
+
+ rImage.moveLeft(width - rImage.width());
+
+ break;
+ }
+
+ default:
+ return;
+ }
+
+ int fontPixels = (int)((float)cellSizeX/3.0);
+ params.baseFont.setPixelSize(fontPixels);
+
+ // ---------------------------------------------------------------
+
+ painter->fillRect(0,0,width, height, Qt::white);
+ painter->setFont(params.baseFont);
+
+ // ---------------------------------------------------------------
+
+ painter->save();
+ QFont f(params.baseFont);
+ f.setBold(true);
+ f.setPixelSize(f.pixelSize() + 5);
+ painter->setFont(f);
+ painter->drawText(rCalHeader, Qt::AlignLeft|Qt::AlignVCenter,
+ QString::number(year));
+#if KDE_IS_VERSION(3,2,0)
+ painter->drawText(rCalHeader, Qt::AlignRight|Qt::AlignVCenter,
+ KGlobal::locale()->calendar()->monthName(month, year));
+#else
+ painter->drawText(rCalHeader, Qt::AlignRight|Qt::AlignVCenter,
+ KGlobal::locale()->monthName(month));
+#endif
+ painter->restore();
+
+ // ---------------------------------------------------------------
+
+ int sx, sy;
+ QRect r, rsmall, rSpecial;
+
+ r.setWidth(cellSizeX);
+ r.setHeight(cellSizeY);
+
+ int index = 0;
+
+ painter->save();
+
+ painter->setPen(Qt::red);
+ sy = rCal.top();
+ for (int i=0; i<7; i++) {
+
+ int dayname = i + startDayOffset;
+ if (dayname > 7)
+ dayname = dayname-7;
+
+ sx = cellSizeX * i + rCal.left();
+ r.moveTopLeft(QPoint(sx,sy));
+ rsmall = r;
+ rsmall.setWidth(r.width() - 2);
+ rsmall.setHeight(r.height() - 2);
+#if KDE_IS_VERSION(3,2,0)
+ painter->drawText(rsmall, Qt::AlignRight|Qt::AlignBottom,
+ KGlobal::locale()->calendar()->weekDayName(dayname, true));
+#else
+ painter->drawText(rsmall, Qt::AlignRight|Qt::AlignBottom,
+ KGlobal::locale()->weekDayName(dayname, true));
+#endif
+ }
+
+ painter->restore();
+
+ for (int j=0; j<6; j++) {
+ sy = cellSizeY * (j + 1) + rCal.top();
+ for (int i=0; i<7; i++) {
+ sx = cellSizeX * i + rCal.left();
+ r.moveTopLeft(QPoint(sx,sy));
+ rsmall = r;
+ rsmall.setWidth(r.width() - 2);
+ rsmall.setHeight(r.height() - 2);
+ if (days[index] != -1) {
+ if (formatter->isSpecial(month, days[index])) {
+
+ painter->save();
+ painter->setPen( formatter->getDayColor(month, days[index]) );
+ painter->drawText(rsmall, Qt::AlignRight|Qt::AlignBottom,
+ QString::number(days[index]));
+
+ QString descr = formatter->getDayDescr(month, days[index]);
+ kdDebug(51000) << "Painting special info: '" << descr << "' for date " << days[index] << "/" << month << endl;
+ rSpecial = rsmall;
+ rSpecial.moveBy(2,0);
+ QFont f(params.baseFont);
+ f.setPixelSize(f.pixelSize() / 3);
+ painter->setFont(f);
+
+ painter->drawText(rSpecial, Qt::AlignLeft|Qt::AlignTop, descr);
+
+ painter->restore();
+ }
+ else
+ {
+ painter->drawText(rsmall, Qt::AlignRight|Qt::AlignBottom,
+ QString::number(days[index]));
+ }
+ }
+ index++;
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ if (params.drawLines) {
+
+ sx = rCal.left();
+ for (int j=0; j<8; j++) {
+ sy = cellSizeY * j + rCal.top();
+ painter->drawLine(sx,sy,rCal.right(),sy);
+ }
+
+ sy = rCal.top();
+ for (int i=0; i<8; i++) {
+ sx = cellSizeX * i + rCal.left();
+ painter->drawLine(sx,sy,sx,rCal.bottom());
+ }
+
+ }
+
+ // ---------------------------------------------------------------
+
+ QImage img = QImage(imagePath.path()); // PENDING(blackie) handle general URLS.
+ if (!img.isNull()) {
+ if ( angle != 0 ) {
+ QWMatrix matrix;
+ matrix.rotate( angle );
+ img = img.xForm( matrix );
+ }
+
+ image_ = new QImage(img.smoothScale(rImage.width(), rImage.height(),
+ QImage::ScaleMin));
+ // Center the image
+ int x = rImage.x() + rImage.width()/2 - image_->width()/2;
+ int y = rImage.y() + rImage.height()/2 - image_->height()/2;
+
+ // Print in 10 pixel strips
+ int blockSize = 10;
+ numBlocks_ = image_->height()/blockSize;
+
+ blocks_ = new struct Block[numBlocks_];
+ struct Block* pb = blocks_;
+ struct Block* pbNext;
+
+ pb->x = x;
+ pb->y = y;
+ pb->sx = 0;
+ pb->sy = 0;
+ pb->w = image_->width();
+ pb->h = blockSize;
+
+ for (int j=1; j<numBlocks_; j++) {
+ pbNext = pb + 1;
+ pbNext->x = x;
+ pbNext->y = pb->y + blockSize;
+ pbNext->sx = 0;
+ pbNext->sy = pb->sy + blockSize;
+ pbNext->w = pb->w;
+ pbNext->h = blockSize;
+ pb = pbNext;
+ }
+
+ pb->h = image_->height() - pb->y;
+
+ currBlock_ = 0;
+ QTimer::singleShot(10, this, SLOT(slotPaintNextBlock()));
+
+ }
+ else {
+ image_ = 0;
+ blocks_ = 0;
+ painter->fillRect(rImage, Qt::blue);
+ }
+}
+
+CalBlockPainter::~CalBlockPainter()
+{
+ if (blocks_) delete [] blocks_;
+ if (image_) delete image_;
+}
+
+void CalBlockPainter::slotPaintNextBlock()
+{
+ struct Block& b = blocks_[currBlock_];
+ painter_->drawImage(b.x, b.y, *image_, b.sx, b.sy,
+ b.w, b.h);
+ currBlock_++;
+ if (currBlock_ < numBlocks_) {
+ QTimer::singleShot(10, this, SLOT(slotPaintNextBlock()));
+ emit signalProgress(currBlock_+1, numBlocks_);
+ }
+ else {
+ emit signalCompleted();
+ delete this;
+ }
+
+}
+
+} // NameSpace KIPICalendarPlugin
+
+#include "calpainter.moc"
diff --git a/kipi-plugins/calendar/calpainter.h b/kipi-plugins/calendar/calpainter.h
new file mode 100644
index 0000000..3d0a89a
--- /dev/null
+++ b/kipi-plugins/calendar/calpainter.h
@@ -0,0 +1,104 @@
+/* ============================================================
+ * File : calpainter.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-02
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CALPAINTER_H
+#define CALPAINTER_H
+
+// Qt includes.
+
+#include <qobject.h>
+#include <qvaluelist.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes
+
+#include "calformatter.h"
+
+
+class QPaintDevice;
+class QPainter;
+class QString;
+class QTimer;
+class QImage;
+
+namespace KIPICalendarPlugin
+{
+
+class CalPainter
+{
+public:
+
+ CalPainter(QPaintDevice *pd);
+ ~CalPainter();
+
+ void setYearMonth(int year, int month);
+ void paint(bool useDeviceMetrics=false);
+
+private:
+
+ QPaintDevice *pd_;
+ int year_;
+ int month_;
+};
+
+class CalBlockPainter : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ CalBlockPainter(QObject *parent, int year, int month,
+ const KURL& imagePath, int angle, CalFormatter* formatter, QPainter *painter);
+ ~CalBlockPainter();
+
+signals:
+
+ void signalCompleted();
+ void signalProgress(int progress, int total);
+
+private:
+
+ struct Block {
+ int x, y;
+ int sx, sy;
+ int w, h;
+ };
+
+ struct Block *blocks_;
+ int numBlocks_;
+ int currBlock_;
+ QTimer *timer_;
+ QPainter *painter_;
+ QImage *image_;
+
+private slots:
+
+ void slotPaintNextBlock();
+
+};
+
+} // NameSpace KIPICalendarPlugin
+
+#endif /* CALPAINTER_H */
+
diff --git a/kipi-plugins/calendar/calprint.h b/kipi-plugins/calendar/calprint.h
new file mode 100644
index 0000000..19349dc
--- /dev/null
+++ b/kipi-plugins/calendar/calprint.h
@@ -0,0 +1,28 @@
+/* ============================================================
+ * File : calprint.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-04
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CALPRINT_H
+#define CALPRINT_H
+
+#include <qwidget.h>
+
+
+#endif /* CALPRINT_H */
diff --git a/kipi-plugins/calendar/calselect.cpp b/kipi-plugins/calendar/calselect.cpp
new file mode 100644
index 0000000..ea0d17c
--- /dev/null
+++ b/kipi-plugins/calendar/calselect.cpp
@@ -0,0 +1,166 @@
+/* ============================================================
+ * File : calselect.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qhgroupbox.h>
+#include <qlayout.h>
+#include <qspinbox.h>
+#include <qdatetime.h>
+#include <qlabel.h>
+#include <qframe.h>
+#include <qpixmap.h>
+
+// KDE includes.
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kcalendarsystem.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "calselect.h"
+#include "calsettings.h"
+#include "monthwidget.h"
+
+#define MAX_MONTHS (13)
+
+namespace KIPICalendarPlugin
+{
+
+CalSelect::CalSelect(KIPI::Interface* interface, QWidget *parent, const char* name)
+ : QWidget(parent, name)
+{
+ mwVector_ = new QPtrVector<MonthWidget>(MAX_MONTHS);
+ monthBoxLayout_ = NULL;
+ setupView( interface );
+}
+
+CalSelect::~CalSelect()
+{
+ delete mwVector_;
+}
+
+void CalSelect::setupView( KIPI::Interface* interface )
+{
+ QVBoxLayout *mainLayout = new QVBoxLayout(this, 6, 11);
+
+ // ----------------------------------------------------------------
+
+ setCaption(i18n("Create Calendar"));
+ QHGroupBox *yearBox = new QHGroupBox(i18n("Select Year"), this);
+ yearBox->layout()->addItem(new QSpacerItem(5,5,
+ QSizePolicy::Expanding,
+ QSizePolicy::Minimum));
+ yearSpin_ = new QSpinBox(KGlobal::locale()->calendar()->minValidYear(),
+ KGlobal::locale()->calendar()->maxValidYear(),
+ 1,yearBox);
+ yearSpin_->setValue(KGlobal::locale()->calendar()->year(QDate::currentDate()));
+ slotYearChanged(yearSpin_->value());
+
+ connect(yearSpin_, SIGNAL(valueChanged(int)),
+ SLOT(slotYearChanged(int)));
+
+ mainLayout->addWidget(yearBox);
+
+ // ----------------------------------------------------------------
+
+ QGroupBox *monthBox = new QGroupBox(i18n("Select Images"), this);
+ monthBox->setColumnLayout(0, Qt::Vertical );
+ monthBox->layout()->setSpacing( 6 );
+ monthBox->layout()->setMargin( 11 );
+
+ monthBoxLayout_ = new QGridLayout(monthBox->layout());
+ monthBoxLayout_->setAlignment( Qt::AlignCenter );
+
+ KURL::List urlList;
+ KIPI::ImageCollection images = interface->currentSelection();
+ if ( images.isValid() && !images.images().isEmpty())
+ urlList = images.images();
+
+ QDate d;
+ KGlobal::locale()->calendar()->setYMD(d, yearSpin_->value(), 1, 1);
+ unsigned int months = KGlobal::locale()->calendar()->monthsInYear(d);
+ // span the monthWidgets over 2 rows. inRow should usually be 6 or 7 (for 12 or 13 months)
+ int inRow = (months / 2) + ((months % 2) != 0);
+ MonthWidget *w;
+
+ for (unsigned int i=0; i<MAX_MONTHS; i++) {
+ w = new MonthWidget( interface, monthBox, i+1);
+ if (i < urlList.count())
+ w->setImage(urlList[i]);
+ if (i<months)
+ monthBoxLayout_->addWidget(w, i / inRow, i % inRow);
+ else
+ w->hide();
+ mwVector_->insert(i, w);
+ }
+
+ QLabel* tLabel =
+ new QLabel(i18n("Left click on Months to Select Images. "
+ "Right click to Clear Month.\n"
+ "You can also drag and drop images onto the Months"),
+ monthBox);
+
+ monthBoxLayout_->addMultiCellWidget(tLabel, 2, 2, 0, 5);
+
+ mainLayout->addWidget(monthBox);
+
+ // ----------------------------------------------------------------
+
+ mainLayout->addItem(new QSpacerItem(5,5,QSizePolicy::Minimum,
+ QSizePolicy::Expanding));
+}
+
+void CalSelect::slotYearChanged(int year)
+{
+ int i, months;
+ QDate d, oldD;
+ KGlobal::locale()->calendar()->setYMD(d, year, 1, 1);
+ KGlobal::locale()->calendar()->setYMD(oldD, CalSettings::instance()->getYear(), 1, 1);
+ months = KGlobal::locale()->calendar()->monthsInYear(d);
+
+ if ((KGlobal::locale()->calendar()->monthsInYear(oldD) != months) && !mwVector_->isEmpty())
+ {
+ // hide the last months that are not present on the current year
+ for (i=months; (i<KGlobal::locale()->calendar()->monthsInYear(oldD)) && (i<(int)mwVector_->count()); i++)
+ mwVector_->at(i)->hide();
+
+ // span the monthWidgets over 2 rows. inRow should usually be 6 or 7 (for 12 or 13 months)
+ int inRow = (months / 2) + ((months % 2) != 0);
+ // remove all the monthWidgets, then readd the needed ones
+ for (i=0; i<KGlobal::locale()->calendar()->monthsInYear(oldD); i++) {
+ monthBoxLayout_->remove(mwVector_->at(i));
+ }
+ for (i=0; (i<months) && (i<(int)mwVector_->count()); i++) {
+ monthBoxLayout_->addWidget(mwVector_->at(i), i / inRow, i % inRow);
+ if (mwVector_->at(i)->isHidden())
+ mwVector_->at(i)->show();
+ mwVector_->at(i)->update();
+ }
+ }
+ CalSettings::instance()->setYear(year);
+}
+
+} // NameSpace KIPICalendarPlugin
+
+#include "calselect.moc"
diff --git a/kipi-plugins/calendar/calselect.h b/kipi-plugins/calendar/calselect.h
new file mode 100644
index 0000000..2038392
--- /dev/null
+++ b/kipi-plugins/calendar/calselect.h
@@ -0,0 +1,66 @@
+/* ============================================================
+ * File : calselect.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CALSELECT_H
+#define CALSELECT_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qptrvector.h>
+
+// LibKIPi includes.
+
+#include <libkipi/interface.h>
+
+class QSpinBox;
+
+namespace KIPICalendarPlugin
+{
+
+class MonthWidget;
+
+class CalSelect : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ CalSelect( KIPI::Interface* interface, QWidget *parent, const char* name=0);
+ ~CalSelect();
+
+private:
+
+ void setupView( KIPI::Interface* interface );
+
+ QPtrVector<MonthWidget> *mwVector_;
+ QSpinBox *yearSpin_;
+ QGridLayout *monthBoxLayout_;
+
+private slots:
+
+ void slotYearChanged(int year);
+
+};
+
+} // NameSpace KIPICalendarPlugin
+
+#endif /* CALSELECT_H */
diff --git a/kipi-plugins/calendar/calsettings.cpp b/kipi-plugins/calendar/calsettings.cpp
new file mode 100644
index 0000000..2c5f112
--- /dev/null
+++ b/kipi-plugins/calendar/calsettings.cpp
@@ -0,0 +1,74 @@
+/* ============================================================
+ * File : calsettings.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-04
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kcalendarsystem.h>
+
+// Local includes.
+
+#include "calsettings.h"
+
+namespace KIPICalendarPlugin
+{
+
+CalSettings* CalSettings::instance_ = 0;
+
+CalSettings::CalSettings()
+{
+ instance_ = this;
+ year_ = KGlobal::locale()->calendar()->minValidYear() + 1;
+}
+
+CalSettings::~CalSettings()
+{
+ instance_ = 0;
+}
+
+CalSettings* CalSettings::instance()
+{
+ return instance_;
+}
+
+void CalSettings::setYear(int year)
+{
+ year_ = year;
+}
+
+int CalSettings::getYear() const
+{
+ return year_;
+}
+
+void CalSettings::setImage(int month, const KURL& path)
+{
+ monthMap_.insert(month, path, true);
+}
+
+KURL CalSettings::getImage(int month) const
+{
+ return monthMap_.contains(month) ? monthMap_[month] : KURL();
+}
+
+} // NameSpace KIPICalendarPlugin
+
diff --git a/kipi-plugins/calendar/calsettings.h b/kipi-plugins/calendar/calsettings.h
new file mode 100644
index 0000000..6b6dd70
--- /dev/null
+++ b/kipi-plugins/calendar/calsettings.h
@@ -0,0 +1,88 @@
+/* ============================================================
+ * File : calsettings.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-04
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CALSETTINGS_H
+#define CALSETTINGS_H
+
+// Qt includes.
+
+#include <qmap.h>
+#include <qstring.h>
+#include <qfont.h>
+
+// KDE includes.
+
+#include <kprinter.h>
+#include <kurl.h>
+
+namespace KIPICalendarPlugin
+{
+
+class CalParams
+{
+public:
+
+ enum ImagePosition
+ {
+ Top = 0,
+ Left,
+ Right
+ };
+
+ KPrinter::PageSize pageSize;
+ int paperWidth;
+ int paperHeight;
+ int width;
+ int height;
+ bool drawLines;
+ float ratio;
+ ImagePosition imgPos;
+ QFont baseFont;
+};
+
+class CalSettings
+{
+public:
+
+ CalSettings();
+ ~CalSettings();
+
+ void setYear(int year);
+ int getYear() const;
+ void setImage(int month, const KURL& url);
+ KURL getImage(int month) const;
+
+ CalParams calParams;
+
+ static CalSettings* instance();
+
+private:
+
+ static CalSettings* instance_;
+
+ QMap<int,KURL> monthMap_;
+ int year_;
+
+};
+
+} // NameSpace KIPICalendarPlugin
+
+#endif /* CALSETTINGS_H */
diff --git a/kipi-plugins/calendar/caltemplate.cpp b/kipi-plugins/calendar/caltemplate.cpp
new file mode 100644
index 0000000..238e2a5
--- /dev/null
+++ b/kipi-plugins/calendar/caltemplate.cpp
@@ -0,0 +1,259 @@
+/* ============================================================
+ * File : caltemplate.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-04
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qvariant.h>
+#include <qframe.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qbuttongroup.h>
+#include <qvbuttongroup.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+#include <qslider.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qfontdatabase.h>
+#include <qpaintdevicemetrics.h>
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qprinter.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "caltemplate.h"
+#include "calwidget.h"
+#include "calsettings.h"
+#include "calpainter.h"
+
+namespace KIPICalendarPlugin
+{
+
+CalTemplate::CalTemplate(QWidget* parent, const char* name)
+ : QWidget(parent, name)
+{
+ QGridLayout *mainLayout = new QGridLayout(this, 1, 1, 5, 5);
+
+ // ----------------------------------------------------------------
+
+ previewSize_ = 300;
+
+ QGroupBox *boxPreview_ = new QGroupBox( i18n("Preview"), this );
+ boxPreview_->setColumnLayout(0, Qt::Vertical);
+ boxPreview_->layout()->setMargin( 5 );
+
+ QVBoxLayout *previewLayout = new QVBoxLayout(boxPreview_->layout());
+ calWidget_ = new CalWidget(boxPreview_);
+ previewLayout->addWidget(calWidget_, 0, Qt::AlignCenter);
+
+ mainLayout->addWidget( boxPreview_, 0, 0 );
+
+ // ---------------------------------------------------------------
+
+ QGroupBox *gbox = new QGroupBox( i18n("Settings"), this );
+ gbox->setColumnLayout(0, Qt::Vertical );
+ gbox->layout()->setSpacing( 11 );
+ gbox->layout()->setMargin( 6 );
+ QVBoxLayout* gboxLayout = new QVBoxLayout( gbox->layout() );
+
+ // ---------------------------------------------------------------
+
+ QHBoxLayout *hlayout = new QHBoxLayout( 0, 0, 5 );
+ hlayout->addWidget( new QLabel(i18n("Paper size:"), gbox) );
+
+ comboPaperSize_ = new QComboBox(false, gbox);
+ hlayout->addWidget(comboPaperSize_);
+ gboxLayout->addLayout( hlayout );
+
+ QStringList paperSizes;
+ paperSizes << "A4";
+ paperSizes << "US Letter";
+ comboPaperSize_->insertStringList(paperSizes);
+
+ connect(comboPaperSize_, SIGNAL(activated(int)),
+ SLOT(slotParamsChanged()));
+
+ // ---------------------------------------------------------------
+
+ btnGroupImagePos_ = new QVButtonGroup(i18n("Image Position"), gbox);
+ btnGroupImagePos_->setRadioButtonExclusive(true);
+
+ // Insert the buttons in the order Top, Left, Right so that they
+ // get the corresponding ids
+ QRadioButton* radioBtn = new QRadioButton(i18n("Top"), btnGroupImagePos_);
+ radioBtn->setChecked(true);
+ Q_ASSERT(btnGroupImagePos_->id( radioBtn ) == CalParams::Top);
+
+ radioBtn = new QRadioButton(i18n("Left"), btnGroupImagePos_);
+ Q_ASSERT(btnGroupImagePos_->id( radioBtn ) == CalParams::Left);
+
+ radioBtn = new QRadioButton(i18n("Right"), btnGroupImagePos_);
+ Q_ASSERT(btnGroupImagePos_->id( radioBtn ) == CalParams::Right);
+
+ gboxLayout->addWidget( btnGroupImagePos_ );
+
+ connect(btnGroupImagePos_, SIGNAL(clicked(int)),
+ SLOT(slotParamsChanged()));
+
+ // ---------------------------------------------------------------
+
+ checkBoxDrawLines_ = new QCheckBox(i18n("Draw lines in calendar"), gbox);
+ gboxLayout->addWidget( checkBoxDrawLines_ );
+ checkBoxDrawLines_->setChecked(true);
+
+ connect(checkBoxDrawLines_, SIGNAL(toggled(bool)),
+ SLOT(slotParamsChanged()));
+
+ // ---------------------------------------------------------------
+
+ hlayout = new QHBoxLayout( 0, 0, 5 );
+
+ hlayout->addWidget(new QLabel(i18n("Image to text ratio:"), gbox));
+
+ sliderRatio_ = new QSlider(50,300,5,100,Qt::Horizontal,gbox);
+ hlayout->addWidget( sliderRatio_ );
+
+ gboxLayout->addLayout( hlayout );
+
+ connect(sliderRatio_, SIGNAL(valueChanged(int)),
+ SLOT(slotParamsChanged()));
+
+ // ---------------------------------------------------------------
+
+ hlayout = new QHBoxLayout( 0, 0, 5 );
+
+ hlayout->addWidget(new QLabel(i18n("Font:"), gbox));
+
+ comboFont_ = new QComboBox(false, gbox);
+ hlayout->addWidget( comboFont_ );
+
+ QFontDatabase fontDB;
+ QStringList families(fontDB.families());
+ QStringList smoothScalableFamilies;
+ for (QStringList::iterator it=families.begin(); it != families.end();
+ ++it)
+ {
+ smoothScalableFamilies.append(*it);
+ }
+ comboFont_->insertStringList(smoothScalableFamilies);
+
+ // fetch and set the default font selected in the combo.
+ QFont f;
+ comboFont_->setCurrentText( f.family() );
+
+
+ gboxLayout->addLayout( hlayout );
+
+ connect(comboFont_, SIGNAL(activated(int)),
+ SLOT(slotParamsChanged()));
+
+
+ // ---------------------------------------------------------------
+
+ gboxLayout->addItem(new QSpacerItem(5,10,QSizePolicy::Minimum,
+ QSizePolicy::Expanding));
+
+ mainLayout->addWidget( gbox, 0, 1 );
+
+ // ---------------------------------------------------------------
+
+ timer_ = new QTimer(this);
+
+ connect(timer_, SIGNAL(timeout()),
+ SLOT(slotUpdatePreview()));
+
+ timer_->start(0,true);
+}
+
+CalTemplate::~CalTemplate()
+{
+ delete timer_;
+}
+
+
+void CalTemplate::slotParamsChanged()
+{
+ timer_->start(10, true);
+}
+
+void CalTemplate::slotUpdatePreview()
+{
+ if (timer_->isActive()) return;
+
+ CalParams& params = CalSettings::instance()->calParams;
+
+ QString paperSize = comboPaperSize_->currentText();
+ if (paperSize == "A4") {
+ params.paperWidth = 210;
+ params.paperHeight = 297;
+ params.pageSize = KPrinter::A4;
+ }
+ else if (paperSize == "US Letter") {
+ params.paperWidth = 216;
+ params.paperHeight = 279;
+ params.pageSize = KPrinter::Letter;
+ }
+
+ const int imgPos = btnGroupImagePos_->selectedId();
+
+ if (imgPos == CalParams::Top) {
+ params.imgPos = CalParams::Top;
+
+ float zoom = QMIN((float)previewSize_/params.paperWidth,
+ (float)previewSize_/params.paperHeight);
+ params.width = (int)(params.paperWidth * zoom);
+ params.height = (int)(params.paperHeight * zoom);
+
+ }
+ else if (imgPos == CalParams::Left) {
+ params.imgPos = CalParams::Left;
+
+ float zoom = QMIN((float)previewSize_/params.paperWidth,
+ (float)previewSize_/params.paperHeight);
+ params.width = (int)(params.paperHeight * zoom);
+ params.height = (int)(params.paperWidth * zoom);
+
+ }
+ else {
+ params.imgPos = CalParams::Right;
+
+ float zoom = QMIN((float)previewSize_/params.paperWidth,
+ (float)previewSize_/params.paperHeight);
+ params.width = (int)(params.paperHeight * zoom);
+ params.height = (int)(params.paperWidth * zoom);
+ }
+
+ params.drawLines = checkBoxDrawLines_->isChecked();
+ params.ratio = sliderRatio_->value();
+ params.baseFont = QFont(comboFont_->currentText());
+ calWidget_->recreate();
+}
+
+} // NameSpace KIPICalendarPlugin
+
+#include "caltemplate.moc"
diff --git a/kipi-plugins/calendar/caltemplate.h b/kipi-plugins/calendar/caltemplate.h
new file mode 100644
index 0000000..36b56ec
--- /dev/null
+++ b/kipi-plugins/calendar/caltemplate.h
@@ -0,0 +1,75 @@
+/* ============================================================
+ * File : caltemplate.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-04
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CALTEMPLATE_H
+#define CALTEMPLATE_H
+
+// Qt includes.
+
+#include <qwidget.h>
+
+class QFrame;
+class QComboBox;
+class QVButtonGroup;
+class QRadioButton;
+class QCheckBox;
+class QSlider;
+class QSpinBox;
+class QLabel;
+class QTimer;
+
+namespace KIPICalendarPlugin
+{
+
+class CalWidget;
+
+class CalTemplate : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ CalTemplate(QWidget* parent, const char* name=0);
+ ~CalTemplate();
+
+private:
+
+ QComboBox* comboPaperSize_;
+ QVButtonGroup* btnGroupImagePos_;
+ QCheckBox* checkBoxDrawLines_;
+ QSlider* sliderSpacing_;
+ QSlider* sliderRatio_;
+ QComboBox* comboFont_;
+
+ CalWidget* calWidget_;
+ QTimer* timer_;
+ int previewSize_;
+
+private slots:
+
+ void slotParamsChanged();
+ void slotUpdatePreview();
+
+};
+
+} // NameSpace KIPICalendarPlugin
+
+#endif // CALTEMPLATE_H
diff --git a/kipi-plugins/calendar/calwidget.cpp b/kipi-plugins/calendar/calwidget.cpp
new file mode 100644
index 0000000..ff9017c
--- /dev/null
+++ b/kipi-plugins/calendar/calwidget.cpp
@@ -0,0 +1,88 @@
+/* ============================================================
+ * File : calwidget.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-01
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <iostream>
+
+// Qt includes.
+
+#include <qdatetime.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qpainter.h>
+
+// KDE includes.
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kcalendarsystem.h>
+
+// Local includes.
+
+#include "calwidget.h"
+#include "calpainter.h"
+#include "calsettings.h"
+
+namespace KIPICalendarPlugin
+{
+
+CalWidget::CalWidget(QWidget *parent)
+ : QWidget(parent,0,Qt::WRepaintNoErase|Qt::WResizeNoErase)
+{
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ calPainter_ = 0;
+ pix_ = new QPixmap();
+}
+
+CalWidget::~CalWidget()
+{
+ delete pix_;
+ if (calPainter_)
+ delete calPainter_;
+}
+
+void CalWidget::paintEvent(QPaintEvent *e)
+{
+ if (!e || pix_->isNull()) return;
+
+ bitBlt(this, 0, 0, pix_, 0, 0, width(), height(), Qt::CopyROP);
+}
+
+void CalWidget::recreate()
+{
+ CalParams& params = CalSettings::instance()->calParams;
+
+ setFixedSize(QSize(params.width,params.height));
+ resize(QSize(params.width,params.height));
+ pix_->resize(params.width,params.height);
+
+ if (!calPainter_)
+ calPainter_ = new CalPainter(pix_);
+
+ calPainter_->setYearMonth(KGlobal::locale()->calendar()->year(QDate::currentDate()),
+ KGlobal::locale()->calendar()->month(QDate::currentDate()));
+ calPainter_->paint();
+ update();
+}
+
+} // NameSpace KIPICalendarPlugin
+
diff --git a/kipi-plugins/calendar/calwidget.h b/kipi-plugins/calendar/calwidget.h
new file mode 100644
index 0000000..1448090
--- /dev/null
+++ b/kipi-plugins/calendar/calwidget.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ * File : calwidget.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-01
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CALWIDGET_H
+#define CALWIDGET_H
+
+// Qt includes.
+
+#include <qwidget.h>
+
+class QPaintEvent;
+class QPixmap;
+
+namespace KIPICalendarPlugin
+{
+
+class CalPainter;
+
+class CalWidget : public QWidget
+{
+public:
+
+ CalWidget(QWidget *parent);
+ ~CalWidget();
+
+ void recreate();
+
+protected:
+
+ void paintEvent(QPaintEvent *e);
+
+private:
+
+ CalPainter *calPainter_;
+ QPixmap *pix_;
+
+};
+
+} // NameSpace KIPICalendarPlugin
+
+#endif /* CALWIDGET_H */
diff --git a/kipi-plugins/calendar/calwizard.cpp b/kipi-plugins/calendar/calwizard.cpp
new file mode 100644
index 0000000..1f02b6f
--- /dev/null
+++ b/kipi-plugins/calendar/calwizard.cpp
@@ -0,0 +1,348 @@
+/* ============================================================
+ * File : calwizard.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Tom Albers <tomalbers@kde.nl>
+ * Date : 2003-11-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2006 by Tom Albers <tomalbers@kde.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qlabel.h>
+#include <qdatetime.h>
+#include <qstringlist.h>
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qprogressbar.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qframe.h>
+#include <qpixmap.h>
+#include <qvbox.h>
+
+// KDE includes.
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kprinter.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kdeversion.h>
+#include <kcalendarsystem.h>
+#include <klineedit.h>
+
+// LibKipi includes.
+
+#include <libkipi/interface.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "caltemplate.h"
+#include "calselect.h"
+#include "calsettings.h"
+#include "calpainter.h"
+#include "calwizard.h"
+#include "calwizard.moc"
+#include "calevents.h"
+
+namespace KIPICalendarPlugin
+{
+
+CalWizard::CalWizard( KIPI::Interface* interface, QWidget *parent )
+ : KWizard(parent, 0, false, Qt::WDestructiveClose),
+ interface_( interface )
+{
+ cSettings_ = new CalSettings();
+
+ // ---------------------------------------------------------------
+
+ wTemplate_ = new CalTemplate(this, "wTemplate");
+ addPage(wTemplate_, i18n("Create Template for Calendar"));
+ setHelpEnabled(wTemplate_, true);
+
+ // ---------------------------------------------------------------
+
+ wEvents_ = new CalEvents(this, "wEvents");
+ addPage(wEvents_, i18n("Choose the events to show on the Calendar"));
+ setHelpEnabled(wEvents_, true);
+
+ // ---------------------------------------------------------------
+
+ wSelect_ = new CalSelect( interface, this, "wSelect");
+ addPage(wSelect_, i18n("Select Year & Images"));
+ setHelpEnabled(wSelect_, true);
+
+ // ---------------------------------------------------------------
+
+ wPrint_ = new QVBox(this, "wPrint");
+
+ wPrintLabel_ = new QLabel(wPrint_, "wPrint");
+ wPrintLabel_->setIndent(20);
+
+ wPrint_->setStretchFactor(wPrintLabel_, 2);
+
+ addPage(wPrint_, i18n("Print"));
+ setHelpEnabled(wPrint_, true);
+
+ // ---------------------------------------------------------------
+
+ wFinish_ = new QWidget(this, "wFinish");
+
+ QVBoxLayout *wFinishLayout = new QVBoxLayout(wFinish_, 6, 11);
+
+ wFinishLabel_ = new QLabel(wFinish_);
+ wFinishLayout->addWidget(wFinishLabel_);
+
+ QHBoxLayout *hboxlayout = new QHBoxLayout(0, 5, 5);
+ hboxlayout->addWidget(new QLabel(i18n("Current Page"), wFinish_));
+ wFinishProgressCurrent_ = new QProgressBar(wFinish_);
+ hboxlayout->addWidget(wFinishProgressCurrent_);
+ wFinishLayout->addLayout(hboxlayout);
+
+ hboxlayout = new QHBoxLayout(0, 5, 5);
+ hboxlayout->addWidget(new QLabel(i18n("Total Pages"), wFinish_));
+ wFinishProgressTotal_ = new QProgressBar(wFinish_);
+ hboxlayout->addWidget(wFinishProgressTotal_);
+ wFinishLayout->addLayout(hboxlayout);
+
+ wFinishLayout->addStretch();
+
+ addPage(wFinish_, i18n("Printing"));
+ setHelpEnabled(wFinish_, true);
+
+ // ---------------------------------------------------------------
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Calendar"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to create a calendar"),
+ "(c) 2003-2004, Renchi Raju, (c) 2006 Tom Albers");
+
+ m_about->addAuthor("Tom Albers", I18N_NOOP("Author and maintainer"),
+ "tomalbers@kde.nl");
+
+ m_about->addAuthor("Renchi Raju", I18N_NOOP("Former Author and maintainer"),
+ "renchi@pooh.tam.uiuc.edu");
+
+ m_helpButton = helpButton();
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ // ------------------------------------------
+
+ printer_ = 0;
+ painter_ = 0;
+
+ formatter_ = new CalFormatter();
+
+ connect(this, SIGNAL(selected(const QString&)),
+ SLOT(slotPageSelected(const QString&)));
+
+ setCaption(i18n("Create Calendar"));
+}
+
+CalWizard::~CalWizard()
+{
+ if (!cb_.isNull()) delete cb_;
+
+ if (painter_) delete painter_;
+ if (printer_) delete printer_;
+ delete cSettings_;
+
+ delete m_about;
+
+ delete formatter_;
+}
+
+void CalWizard::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("calendar", "kipi-plugins");
+}
+
+void CalWizard::slotPageSelected(const QString&)
+{
+
+ if (currentPage() == wPrint_) {
+
+ totPages_ = 0;
+ currPage_ = 0;
+ monthNumbers_.clear();
+ monthImages_.clear();
+ KURL image;
+ QString month;
+ QStringList printList;
+ QDate d;
+ KGlobal::locale()->calendar()->setYMD(d, cSettings_->getYear(), 1, 1);
+ for (int i=1; i<=KGlobal::locale()->calendar()->monthsInYear(d); i++) {
+#if KDE_IS_VERSION(3,2,0)
+ month = KGlobal::locale()->calendar()->monthName(i, cSettings_->getYear(), false);
+#else
+ month = KGlobal::locale()->monthName(i);
+#endif
+ image = cSettings_->getImage(i);
+ if (!image.isEmpty()) {
+ monthNumbers_.append(i);
+ monthImages_.append(image);
+ printList.append(month);
+ }
+ }
+
+ if (!monthNumbers_.empty()) {
+ QString year = QString::number(cSettings_->getYear());
+
+ QString extra;
+ if ((KGlobal::locale()->calendar()->month(QDate::currentDate()) >= 6 &&
+ KGlobal::locale()->calendar()->year(QDate::currentDate()) == cSettings_->getYear()) ||
+ KGlobal::locale()->calendar()->year(QDate::currentDate()) > cSettings_->getYear())
+ extra = "<br><br><b>"+i18n("Please note that you are making a "
+ "calendar for<br>the current year or a year in the "
+ "past.")+"</b>";
+
+ KApplication::startServiceByName("KJobViewer");
+ QString extra2 = i18n("<br><br>You can see KJobViewer is already started. "
+ "After the plugin has prepared the calendar, it is passed to "
+ "the PDF printer. In the KJobViewer you can see the progress "
+ "of that part of the generation of the calendar.");
+
+ wPrintLabel_->setText(i18n("Click Next to start Printing<br><br>"
+ "Following months will be printed for year %1:").arg(year)
+ + QString("<br>")
+ + printList.join(" - ") + extra + extra2);
+ wPrintLabel_->setTextFormat(Qt::RichText);
+
+ setNextEnabled(wPrint_, true);
+ }
+ else {
+ wPrintLabel_->setText(i18n("No valid images selected for months<br>"
+ "Click Back to select images"));
+ setNextEnabled(wPrint_, false);
+ }
+ }
+
+ else if (currentPage() == wFinish_) {
+
+ wFinishLabel_->clear();
+ wFinishProgressTotal_->reset();
+ wFinishProgressCurrent_->reset();
+
+ setBackEnabled(wFinish_, false);
+ setFinishEnabled(wFinish_, false);
+
+ // Set printer settings ---------------------------------------
+
+ if (!printer_)
+ printer_ = new KPrinter(false);
+#if KDE_IS_VERSION(3,2,0)
+ printer_->setUsePrinterResolution(true);
+#endif
+
+ // TODO: Let user choose resolutions
+ //, QPrinter::HighResolution);
+
+ CalParams& params = cSettings_->calParams;
+
+ // Orientation
+ switch (params.imgPos) {
+ case(CalParams::Top): {
+ printer_->setOrientation(KPrinter::Portrait);
+ break;
+ }
+ default:
+ printer_->setOrientation(KPrinter::Landscape);
+ }
+
+ // PageSize
+ printer_->setPageSize(params.pageSize);
+
+ if (printer_->setup(this)) {
+
+ // Start printing --------------------------------------------
+
+ painter_ = new QPainter(printer_);
+ totPages_ = monthImages_.count();
+ currPage_ = -1;
+ formatter_->init(cSettings_->getYear(), wEvents_->ohFileEdit->text(), wEvents_->fhFileEdit->text());
+ slotPrintOnePage();
+
+ }
+ else {
+ wFinishLabel_->setText(i18n("Printing Cancelled"));
+ setBackEnabled(wFinish_, true);
+ }
+
+ }
+
+}
+
+void CalWizard::slotPrintOnePage()
+{
+ if (monthNumbers_.empty()) {
+ wFinishProgressTotal_->setProgress(totPages_,totPages_);
+ painter_->end();
+ delete painter_;
+ painter_ = 0;
+ setBackEnabled(wFinish_, true);
+ setFinishEnabled(wFinish_, true);
+ wFinishLabel_->setText(i18n("Printing Complete"));
+ return;
+ }
+
+ int month(monthNumbers_.first());
+ KURL image(monthImages_.first());
+ monthNumbers_.pop_front();
+ monthImages_.pop_front();
+
+ QString yearName = QString::number(cSettings_->getYear());
+
+#if KDE_IS_VERSION(3,2,0)
+ wFinishLabel_->setText(i18n("Printing Calendar Page for %1 of %2")
+ .arg(KGlobal::locale()->calendar()->monthName(month, cSettings_->getYear(), false))
+ .arg(yearName));
+#else
+ wFinishLabel_->setText(i18n("Printing Calendar Page for %1 of %2")
+ .arg(KGlobal::locale()->monthName(month)).
+ .arg(yearName));
+#endif
+
+ currPage_++;
+ if (currPage_ != 0)
+ printer_->newPage();
+ wFinishProgressTotal_->setProgress(currPage_,totPages_);
+
+ int angle = interface_->info( image ).angle();
+
+ cb_ = new CalBlockPainter(this, cSettings_->getYear(), month,
+ image, angle, formatter_, painter_);
+
+ connect(cb_, SIGNAL(signalCompleted()),
+ SLOT(slotPrintOnePage()));
+ connect(cb_, SIGNAL(signalProgress(int,int)),
+ wFinishProgressCurrent_, SLOT(setProgress(int,int)));
+}
+
+} // NameSpace KIPICalendarPlugin
+
diff --git a/kipi-plugins/calendar/calwizard.h b/kipi-plugins/calendar/calwizard.h
new file mode 100644
index 0000000..439292a
--- /dev/null
+++ b/kipi-plugins/calendar/calwizard.h
@@ -0,0 +1,107 @@
+/* ============================================================
+ * File : calwizard.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CALWIZARD_H
+#define CALWIZARD_H
+
+// Qt includes.
+
+#include <qstringlist.h>
+#include <qguardedptr.h>
+
+// KDE includes.
+
+#include <kwizard.h>
+
+// LibKIPI includes.
+
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QLabel;
+class QVBox;
+class QPainter;
+class QProgressBar;
+class QPushButton;
+
+class KPrinter;
+
+namespace KIPICalendarPlugin
+{
+
+class CalTemplate;
+class CalSelect;
+class CalSettings;
+class CalEvents;
+class CalFormatter;
+class CalBlockPainter;
+
+class CalWizard : public KWizard
+{
+ Q_OBJECT
+
+public:
+
+ CalWizard( KIPI::Interface* interface, QWidget *parent=0L );
+ ~CalWizard();
+
+private:
+
+ CalSettings *cSettings_;
+ CalTemplate *wTemplate_;
+ CalSelect *wSelect_;
+ CalEvents *wEvents_;
+ QVBox *wPrint_;
+ QLabel *wPrintLabel_;
+ QWidget *wFinish_;
+ QLabel *wFinishLabel_;
+ QProgressBar *wFinishProgressTotal_;
+ QProgressBar *wFinishProgressCurrent_;
+
+ QPushButton *m_helpButton;
+
+ KPrinter *printer_;
+ QPainter *painter_;
+
+ CalFormatter *formatter_;
+
+ QValueList<int> monthNumbers_;
+ KURL::List monthImages_;
+ int totPages_;
+ int currPage_;
+ QGuardedPtr<CalBlockPainter> cb_;
+ KIPI::Interface* interface_;
+
+ KIPIPlugins::KPAboutData *m_about;
+
+private slots:
+
+ void slotPageSelected(const QString& name);
+ void slotPrintOnePage();
+ void slotHelp();
+};
+
+} // NameSpace KIPICalendarPlugin
+
+#endif /* CALWIZARD_H */
diff --git a/kipi-plugins/calendar/kipiplugin_calendar.desktop b/kipi-plugins/calendar/kipiplugin_calendar.desktop
new file mode 100644
index 0000000..a330ba4
--- /dev/null
+++ b/kipi-plugins/calendar/kipiplugin_calendar.desktop
@@ -0,0 +1,62 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Calendar
+Name[br]=Deiziadur
+Name[ca]=Calendari
+Name[cs]=Kalendář
+Name[cy]=Calendr
+Name[da]=Kalender
+Name[de]=Kalender
+Name[el]=Ημερολόγιο
+Name[es]=Calendario
+Name[et]=Kalender
+Name[fi]=Kalenteri
+Name[ga]=Féilire
+Name[gl]=Calendário
+Name[is]=Dagatal
+Name[it]=Calendario
+Name[nds]=Kalenner
+Name[nl]=Kalender
+Name[pa]=ਕੈਲੰਡਰ
+Name[pl]=Kalendarz
+Name[pt]=Calendário
+Name[sr]=Календар
+Name[sr@Latn]=Kalendar
+Name[sv]=Kalender
+Name[tg]=Календар
+Name[th]=สร้างปฏิทิน
+Name[tr]=Takvim
+Name[xx]=xxCalendarxx
+Name[zh_CN]=日历
+Comment=KIPI Calendar Creation Wizard Plugin
+Comment[ca]=Connector del KIPI per a ajudar a crear un calendari
+Comment[cs]=KIPI modul průvodce vytvořením kalendáře
+Comment[da]=KIPI-plugin: Guide til at oprette kalender
+Comment[de]=Ein KIPI-Modul zum Erstellen eines Kalenders
+Comment[el]=Πρόσθετο μάγου δημιουργίας ημερολογίου του KIPI
+Comment[es]=Complemento de KIPI para creación de calendarios
+Comment[et]=KIPI kalendri loomise nõustaja plugin
+Comment[fr]=Module externe KIPI pour créer un calendrier
+Comment[gl]=Plugin de KIPI para Asisténcia na Criazón de Calendários
+Comment[is]=KIPI íforrit til að gera dagatal
+Comment[it]=Plugin assistente per la creazione di calendari di KIPI
+Comment[ja]=Kipi カレンダー作成プラグイン
+Comment[nds]=Kipi-Moduul mit en Hölper för't Opstellen vun en Kalenner
+Comment[nl]=KIPI-plugin voor het maken van een kalender
+Comment[pa]=KIPI ਕੈਲੰਡਰ ਬਣਾਉਣ ਸਹਾਇਕ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Asystent tworzenia kalendarzy
+Comment[pt]='Plugin' do KIPI de Assistência na Criação de Calendários
+Comment[pt_BR]=Plugin de Assistente para Criação de Calendário do KIPI
+Comment[sr]=KIPI прикључак чаробњака за прављење календара
+Comment[sr@Latn]=KIPI priključak čarobnjaka za pravljenje kalendara
+Comment[sv]=KIPI-insticksprogram: Guide för att skapa kalender
+Comment[tg]=Модули KIPI барои сохтани мавзӯъи календар
+Comment[th]=ปลั๊กอินช่วยสร้างปฏิทินของ KIPI
+Comment[tr]=KIPI Takvim Oluşturma Sihirbazı Eklentisi
+Comment[xx]=xxKIPI Calendar Creation Wizard Pluginxx
+Comment[zh_CN]=KIPI 日历创建向导插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_calendar
+X-KIPI-MergeMenu=false
+author=Renchi Raju, renchi@pooh.tam.uiuc.edu
diff --git a/kipi-plugins/calendar/monthwidget.cpp b/kipi-plugins/calendar/monthwidget.cpp
new file mode 100644
index 0000000..abe2c87
--- /dev/null
+++ b/kipi-plugins/calendar/monthwidget.cpp
@@ -0,0 +1,195 @@
+/* ============================================================
+ * File : monthwidget.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Tom Albers <tomalbers@kde.nl>
+ * Date : 2003-11-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2006 by Tom Albers <tomalbers@kde.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qdatetime.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qevent.h>
+#include <qdragobject.h>
+#include <qstrlist.h>
+#include <qimage.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <kurldrag.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+#include <kimageio.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kio/previewjob.h>
+#include <kdeversion.h>
+#include <kcalendarsystem.h>
+
+// LibKipi includes.
+
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "monthwidget.h"
+#include "calsettings.h"
+
+namespace KIPICalendarPlugin
+{
+
+MonthWidget::MonthWidget( KIPI::Interface* interface, QWidget *parent, int month)
+ : QFrame(parent), interface_( interface )
+{
+ setAcceptDrops(true);
+ month_ = month;
+ imagePath_ = QString("");
+ pixmap_ = new QPixmap(SmallIcon("file_broken",
+ KIcon::SizeMedium,
+ KIcon::DisabledState));
+ setFixedSize(QSize(70,90));
+ setFrameStyle(QFrame::Panel|QFrame::Raised);
+}
+
+MonthWidget::~MonthWidget()
+{
+ if (pixmap_) delete pixmap_;
+}
+
+KURL MonthWidget::imagePath()
+{
+ return imagePath_;
+}
+
+void MonthWidget::drawContents(QPainter *p)
+{
+
+#if KDE_IS_VERSION(3,2,0)
+ QString name = KGlobal::locale()->calendar()->monthName(month_, CalSettings::instance()->getYear(), true);
+#else
+ QString name = KGlobal::locale()->monthName(month_, true);
+#endif
+
+ QRect cr;
+
+ cr = contentsRect();
+ cr.setBottom(70);
+ p->drawPixmap(cr.width()/2 - pixmap_->width()/2,
+ cr.height()/2 - pixmap_->height()/2,
+ *pixmap_);
+
+ cr = contentsRect();
+ cr.setTop(70);
+ p->drawText(cr,Qt::AlignHCenter,name);
+}
+
+void MonthWidget::dragEnterEvent(QDragEnterEvent* event)
+{
+ event->accept(QUriDrag::canDecode(event));
+}
+
+void MonthWidget::setImage( const KURL &url )
+{
+ if (!url.isValid())
+ return;
+
+ // check if the file is an image
+ if ( ! QImageIO::imageFormat( url.path() ) )
+ {
+ kdWarning( 51001 ) << "Unknown image format for: "
+ << url.prettyURL() << endl;
+ return;
+ }
+
+ imagePath_ = url;
+ CalSettings::instance()->setImage(month_, imagePath_);
+
+ KIconLoader* iconLoader = KApplication::kApplication()->iconLoader();
+ QPixmap pix = iconLoader->loadIcon("image", KIcon::NoGroup, 64 );
+ if ( pixmap_ )
+ delete pixmap_;
+ pixmap_ = new QPixmap( pix );
+ update();
+
+ KURL::List urls;
+ urls << url;
+
+ KIO::PreviewJob* thumbJob_ =
+ KIO::filePreview( urls,64);
+ connect(thumbJob_, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ SLOT(slotGotThumbnaiL(const KFileItem*, const QPixmap&)));
+}
+
+void MonthWidget::dropEvent(QDropEvent* event)
+{
+ KURL::List srcURLs;
+ if ( !KURLDrag::decode(event, srcURLs) )
+ return;
+
+ if ( srcURLs.isEmpty() )
+ return;
+
+ KURL url = srcURLs.first();
+ setImage( url );
+}
+
+void MonthWidget::slotGotThumbnaiL(const KFileItem* , const QPixmap& pix)
+{
+ if ( pixmap_ )
+ delete pixmap_;
+ QPixmap image = pix;
+ int angle = interface_->info( imagePath_ ).angle();
+ if ( angle != 0 ) {
+ QWMatrix matrix;
+ matrix.rotate( angle );
+ image = image.xForm( matrix );
+ }
+
+ pixmap_ = new QPixmap(image);
+ update();
+}
+
+void MonthWidget::mouseReleaseEvent(QMouseEvent* e)
+{
+ if (!contentsRect().contains(e->pos())) return;
+
+ if (e->button() == Qt::LeftButton)
+ {
+ KURL url = KIPI::ImageDialog::getImageURL(this, interface_);
+ setImage(url);
+ }
+ else if (e->button() == Qt::RightButton) {
+ imagePath_ = QString("");
+ CalSettings::instance()->setImage(month_,imagePath_);
+ delete pixmap_;
+ pixmap_ = new QPixmap(SmallIcon("file_broken",
+ KIcon::SizeMedium,
+ KIcon::DisabledState));
+ update();
+ }
+}
+
+} // NameSpace KIPICalendarPlugin
+
+#include "monthwidget.moc"
diff --git a/kipi-plugins/calendar/monthwidget.h b/kipi-plugins/calendar/monthwidget.h
new file mode 100644
index 0000000..1a79d24
--- /dev/null
+++ b/kipi-plugins/calendar/monthwidget.h
@@ -0,0 +1,77 @@
+/* ============================================================
+ * File : monthwidget.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 MONTHWIDGET_H
+#define MONTHWIDGET_H
+
+// Qt includes.
+
+#include <qframe.h>
+
+// LibKipi includes
+
+#include <libkipi/interface.h>
+
+class QPainter;
+class QPixmap;
+class QDragEnterEvent;
+class QDropEvent;
+class QMouseEvent;
+
+class KURL;
+class KFileItem;
+
+namespace KIPICalendarPlugin
+{
+
+class MonthWidget : public QFrame
+{
+ Q_OBJECT
+
+public:
+
+ MonthWidget( KIPI::Interface* interface, QWidget *parent, int month);
+ ~MonthWidget();
+
+ KURL imagePath();
+ void setImage( const KURL& url );
+
+protected:
+
+ void drawContents(QPainter *p);
+ void dragEnterEvent(QDragEnterEvent* event);
+ void dropEvent(QDropEvent* event);
+ void mouseReleaseEvent(QMouseEvent* e);
+
+private:
+
+ int month_;
+ KURL imagePath_;
+ QPixmap *pixmap_;
+ KIPI::Interface* interface_;
+private slots:
+
+ void slotGotThumbnaiL(const KFileItem* url, const QPixmap& pix);
+};
+
+} // NameSpace KIPICalendarPlugin
+
+#endif /* MONTHWIDGET_H */
diff --git a/kipi-plugins/calendar/plugin_calendar.cpp b/kipi-plugins/calendar/plugin_calendar.cpp
new file mode 100644
index 0000000..8ca7113
--- /dev/null
+++ b/kipi-plugins/calendar/plugin_calendar.cpp
@@ -0,0 +1,98 @@
+/* ============================================================
+ * File : plugin_jpeglossless.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qprogressdialog.h>
+#include <qtimer.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kurl.h>
+#include <kapplication.h>
+
+// Local includes.
+
+#include "plugin_calendar.h"
+#include "calwizard.h"
+
+typedef KGenericFactory<Plugin_Calendar> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_calendar,
+ Factory("kipiplugin_calendar"))
+
+Plugin_Calendar::Plugin_Calendar(QObject *parent,
+ const char*,
+ const QStringList &)
+ : KIPI::Plugin(Factory::instance(), parent, "Calendar")
+{
+ kdDebug( 51001 ) << "Loaded Plugin_Calendar" << endl;
+}
+
+void Plugin_Calendar::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_calendarAction = new KAction(i18n("Create Calendar..."),
+ "date",
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "calendar");
+
+ addAction( m_calendarAction );
+}
+
+Plugin_Calendar::~Plugin_Calendar()
+{
+}
+
+void Plugin_Calendar::slotActivate()
+{
+ KIPI::Interface* interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPICalendarPlugin::CalWizard* w = new KIPICalendarPlugin::CalWizard( interface, kapp->activeWindow() );
+ w->show();
+}
+
+KIPI::Category Plugin_Calendar::category( KAction* action ) const
+{
+ if ( action == m_calendarAction )
+ return KIPI::TOOLSPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::TOOLSPLUGIN; // no warning from compiler, please
+}
+
+#include "plugin_calendar.moc"
diff --git a/kipi-plugins/calendar/plugin_calendar.h b/kipi-plugins/calendar/plugin_calendar.h
new file mode 100644
index 0000000..e11abae
--- /dev/null
+++ b/kipi-plugins/calendar/plugin_calendar.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ * File : plugin_calendar.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-11-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_CALENDAR_H
+#define PLUGIN_CALENDAR_H
+
+// Lib KIPI includes.
+
+#include <libkipi/plugin.h>
+
+class QProgressDialog;
+class QTimer;
+
+class KAction;
+
+class Plugin_Calendar : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_Calendar(QObject *parent,
+ const char* name,
+ const QStringList &args);
+ ~Plugin_Calendar();
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+private:
+
+ KAction* m_calendarAction;
+
+private slots:
+
+ void slotActivate();
+};
+
+#endif /* PLUGIN_CALENDAR_H */
diff --git a/kipi-plugins/cdarchiving/Makefile.am b/kipi-plugins/cdarchiving/Makefile.am
new file mode 100644
index 0000000..936a2cc
--- /dev/null
+++ b/kipi-plugins/cdarchiving/Makefile.am
@@ -0,0 +1,30 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+SUBDIRS = autorun
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_cdarchiving.la
+kipiplugin_cdarchiving_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+
+# Srcs for the plugin
+kipiplugin_cdarchiving_la_SOURCES = plugin_cdarchiving.cpp cdarchivingdialog.cpp cdarchiving.cpp
+
+# Libs needed by the plugin
+kipiplugin_cdarchiving_la_LIBADD = $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_cdarchiving_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_cdarchiving.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_cdarchiving.pot
+
+kipiimagebrokenpicdir = $(kde_datadir)/kipi/data
+kipiimagebrokenpic_DATA = image_broken.png
+
+kipiHTML401picdir = $(kde_datadir)/kipi
+kipiHTML401pic_DATA = valid-html401.png gohome.png up.png
diff --git a/kipi-plugins/cdarchiving/actions.h b/kipi-plugins/cdarchiving/actions.h
new file mode 100644
index 0000000..bf00289
--- /dev/null
+++ b/kipi-plugins/cdarchiving/actions.h
@@ -0,0 +1,66 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// ACTIONS.H
+//
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef ACTIONS_H
+#define ACTIONS_H
+
+namespace KIPICDArchivingPlugin
+{
+
+enum Action
+{
+ Initialize = 0,
+ Progress,
+ Error,
+ ResizeImages,
+ BuildHTMLiface,
+ BuildAlbumHTMLPage,
+ BuildAutoRuniface,
+ BuildK3bProject
+};
+
+
+class EventData
+{
+public:
+ EventData()
+ {
+ starting = false;
+ success = false;
+ }
+
+ Action action;
+
+ QString albumName;
+ QString fileName;
+ QString message;
+
+ bool starting;
+ bool success;
+
+ int total;
+};
+
+} // NameSpace KIPICDArchivingPlugin
+
+#endif // ACTIONS_H
diff --git a/kipi-plugins/cdarchiving/autorun/Makefile.am b/kipi-plugins/cdarchiving/autorun/Makefile.am
new file mode 100644
index 0000000..d28f136
--- /dev/null
+++ b/kipi-plugins/cdarchiving/autorun/Makefile.am
@@ -0,0 +1,6 @@
+kipidatadir = $(kde_datadir)/kipi/data
+kipidata_DATA = index.htm
+
+kipiautorundir = $(kde_datadir)/kipi/data/autorun
+kipiautorun_DATA = cdalbums.ico ShellExecute.bat
+
diff --git a/kipi-plugins/cdarchiving/autorun/ShellExecute.bat b/kipi-plugins/cdarchiving/autorun/ShellExecute.bat
new file mode 100644
index 0000000..5105c02
--- /dev/null
+++ b/kipi-plugins/cdarchiving/autorun/ShellExecute.bat
@@ -0,0 +1 @@
+start %1
diff --git a/kipi-plugins/cdarchiving/autorun/cdalbums.ico b/kipi-plugins/cdarchiving/autorun/cdalbums.ico
new file mode 100644
index 0000000..b6edecf
--- /dev/null
+++ b/kipi-plugins/cdarchiving/autorun/cdalbums.ico
Binary files differ
diff --git a/kipi-plugins/cdarchiving/autorun/index.htm b/kipi-plugins/cdarchiving/autorun/index.htm
new file mode 100644
index 0000000..2225ac4
--- /dev/null
+++ b/kipi-plugins/cdarchiving/autorun/index.htm
@@ -0,0 +1,5 @@
+<html><head>
+<title></title>
+</head><body>
+<meta http-equiv="Refresh" content="0; URL=HTMLInterface/index.htm">
+</body></html>
diff --git a/kipi-plugins/cdarchiving/cdarchiving.cpp b/kipi-plugins/cdarchiving/cdarchiving.cpp
new file mode 100644
index 0000000..1d93aad
--- /dev/null
+++ b/kipi-plugins/cdarchiving/cdarchiving.cpp
@@ -0,0 +1,1942 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// CDARCHIVING.CPP
+//
+// Copyright (C) 2003-2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2003-2004 by Gregory Kokanosky <gregory dot kokanosky at free.fr>
+// for images navigation mode.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// C Ansi includes
+
+extern "C"
+{
+#include <sys/types.h>
+}
+
+// Include files for Qt
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qfont.h>
+#include <qimage.h>
+#include <qregexp.h>
+#include <qtextcodec.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+
+// Include files for KDE
+
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kcharsets.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <kglobal.h>
+#include <kimageio.h>
+#include <kinstance.h>
+#include <kio/global.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <krun.h>
+#include <kstandarddirs.h>
+
+// Local includes
+
+#include "actions.h"
+#include "cdarchiving.h"
+#include "cdarchivingdialog.h"
+#include "plugin_cdarchiving.h"
+
+namespace KIPICDArchivingPlugin
+{
+
+CDArchiving::CDArchiving( KIPI::Interface* interface, QObject *parent, KAction *action_cdarchiving )
+ : QObject(parent)
+{
+ KImageIO::registerFormats();
+ const KAboutData *data = KApplication::kApplication()->aboutData();
+ m_hostName = QString::QString( data->appName() );
+
+ m_hostURL = data->homepage();
+
+ if (m_hostURL.isEmpty())
+ {
+ m_hostName = "Kipi";
+ m_hostURL = "http://extragear.kde.org/apps/kipi";
+ }
+
+ m_actionCDArchiving = action_cdarchiving;
+ m_interface = interface;
+ m_parent = parent;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+CDArchiving::~CDArchiving()
+{
+ delete m_configDlg;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::writeSettings(void)
+{
+ KConfig config("kipirc");
+ config.setGroup("CDArchiving Settings");
+
+ // Albums selection dialogbox setup tab
+
+ config.writeEntry("MediaFormat", m_configDlg->getMediaFormat());
+
+ // HTML interface Look dialogbox setup tab
+
+ config.writeEntry("UseHTMLInterface", m_configDlg->getUseHTMLInterface());
+ config.writeEntry("UseAutoRun", m_configDlg->getUseAutoRunWin32());
+ config.writeEntry("MainPageTitle", m_configDlg->getMainTitle());
+ config.writeEntry("ImagesPerRow", m_configDlg->getImagesPerRow());
+ config.writeEntry("FontName", m_configDlg->getFontName());
+ config.writeEntry("FontSize", m_configDlg->getFontSize());
+ config.writeEntry("FontColor", m_configDlg->getForegroundColor());
+ config.writeEntry("BackgroundColor", m_configDlg->getBackgroundColor());
+ config.writeEntry("ThumbnailsSize", m_configDlg->getThumbnailsSize());
+ config.writeEntry("ThumbnailsFormat", m_configDlg->getImageFormat());
+ config.writeEntry("BordersImagesSize", m_configDlg->getBordersImagesSize());
+ config.writeEntry("BordersImagesColor", m_configDlg->getBordersImagesColor());
+
+ // CD Informations setup tab
+
+ config.writeEntry("VolumeID", m_configDlg->getVolumeID());
+ config.writeEntry("VolumeSetID", m_configDlg->getVolumeSetID());
+ config.writeEntry("SystemID", m_configDlg->getSystemID());
+ config.writeEntry("ApplicationID", m_configDlg->getApplicationID());
+ config.writeEntry("Publisher", m_configDlg->getPublisher());
+ config.writeEntry("Preparer", m_configDlg->getPreparer());
+
+ // Misc dialogbox setup tab
+
+ config.writeEntry("K3bBinPath", m_configDlg->getK3bBinPathName());
+ config.writeEntry("K3bParameters", m_configDlg->getK3bParameters());
+ config.writeEntry("UseOnTheFly", m_configDlg->getUseOnTheFly());
+ config.writeEntry("UseCheckCD", m_configDlg->getUseCheckCD());
+ config.writeEntry("UseStartWrintingProcess", m_configDlg->getUseStartBurningProcess());
+
+ config.sync();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::readSettings(void)
+{
+ KConfig config("kipirc");
+ config.setGroup("CDArchiving Settings");
+
+ // Albums selection dialogbox setup tab
+
+ m_configDlg->setMediaFormat( config.readEntry("MediaFormat", i18n("CD (650Mb)")) );
+
+ // HTML interface Look dialogbox setup tab
+
+ m_configDlg->setUseHTMLInterface( config.readBoolEntry("UseHTMLInterface", "true") );
+ m_configDlg->setUseAutoRunWin32( config.readBoolEntry("UseAutoRun", "true") );
+ m_configDlg->setMainTitle( config.readEntry("MainPageTitle", i18n("KIPI Albums Archiving")) );
+ m_configDlg->setImagesPerRow( config.readEntry("ImagesPerRow", "4").toInt() );
+ m_configDlg->setFontName( config.readEntry("FontName", "Helvetica") );
+ m_configDlg->setFontSize( config.readEntry("FontSize", "14").toInt() );
+ QColor ColorFont( 208, 255, 208 );
+ m_configDlg->setForegroundColor( config.readColorEntry("FontColor", &ColorFont));
+ QColor ColorBackground( 51, 51, 51 );
+ m_configDlg->setBackgroundColor( config.readColorEntry("BackgroundColor", &ColorBackground));
+ m_configDlg->setThumbnailsSize( config.readEntry("ThumbnailsSize", "140").toInt() );
+ m_configDlg->setImageFormat( config.readEntry("ThumbnailsFormat", "JPEG") );
+ m_configDlg->setBordersImagesSize( config.readEntry("BordersImagesSize", "1").toInt() );
+ QColor ColorBordersImages( 208, 255, 208 );
+ m_configDlg->setBordersImagesColor( config.readColorEntry("BordersImagesColor", &ColorBordersImages));
+
+ // CD Informations setup tab
+
+ m_configDlg->setVolumeID( config.readEntry("VolumeID", i18n("CD Albums")) );
+ m_configDlg->setVolumeSetID( config.readEntry("VolumeSetIDeTitle", i18n("KIPI Album CD archiving")) );
+ m_configDlg->setSystemID( config.readEntry("SystemID", i18n("LINUX")) );
+ m_configDlg->setApplicationID( config.readEntry("ApplicationID", i18n("K3b CD-DVD Burning application")) );
+ m_configDlg->setPublisher( config.readEntry("Publisher", m_hostName + " [" + m_hostURL + "]") );
+ m_configDlg->setPreparer( config.readEntry("Preparer", i18n("KIPI CD-Archiving plugin")) );
+
+ // Misc dialogbox setup tab
+
+ m_configDlg->setK3bBinPathName( config.readEntry("K3bBinPath", "k3b") );
+ m_configDlg->setK3bParameters( config.readEntry("K3bParameters", "--nofork") );
+ m_configDlg->setUseUseOnTheFly( config.readBoolEntry("UseOnTheFly", "true") );
+ m_configDlg->setUseCheckCD( config.readBoolEntry("UseCheckCD", "true") );
+ m_configDlg->setUseStartBurningProcess( config.readBoolEntry("UseStartWrintingProcess", "false") );
+
+ // Get the image files filters from the hosts app.
+
+ m_imagesFileFilter = m_interface->fileExtensions();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CDArchiving::showDialog()
+{
+ KStandardDirs dir;
+ m_tmpFolder = dir.saveLocation("tmp", "kipi-cdarchivingplugin-" + QString::number(getpid()) + "/");
+
+ m_HTMLInterfaceFolder = "";
+ m_HTMLInterfaceIndex = "";
+ m_HTMLInterfaceAutoRunInf = "";
+ m_HTMLInterfaceAutoRunFolder = "";
+
+ m_configDlg = new CDArchivingDialog( m_interface, kapp->activeWindow() );
+ readSettings();
+
+ if ( m_configDlg->exec() == QDialog::Accepted )
+ {
+ writeSettings();
+ return true;
+ }
+
+ return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CDArchiving::prepare(void)
+{
+ QValueList<KIPI::ImageCollection> albumsList;
+ KIPICDArchivingPlugin::EventData *d;
+
+ m_cancelled = false;
+ m_StreamMainPageAlbumPreview = "";
+
+ // Get config from setup dialog.
+ albumsList = m_configDlg->getSelectedAlbums();
+ m_useHTMLInterface = m_configDlg->getUseHTMLInterface();
+ m_useAutoRunWin32 = m_configDlg->getUseAutoRunWin32();
+ m_K3bBinPathName = m_configDlg->getK3bBinPathName();
+ m_K3bParameters = m_configDlg->getK3bParameters();
+ m_useStartBurningProcess = m_configDlg->getUseStartBurningProcess();
+ m_imagesPerRow = m_configDlg->getImagesPerRow();
+ m_imageFormat = m_configDlg->getImageFormat();
+ m_mainTitle = m_configDlg->getMainTitle();
+ m_backgroundColor = m_configDlg->getBackgroundColor();
+ m_foregroundColor = m_configDlg->getForegroundColor();
+ m_bordersImagesColor = m_configDlg->getBordersImagesColor();
+ m_fontName = m_configDlg->getFontName();
+ m_fontSize = m_configDlg->getFontSize();
+ m_bordersImagesSize = m_configDlg->getBordersImagesSize();
+ m_thumbnailsSize = m_configDlg->getThumbnailsSize();
+ m_mediaFormat = m_configDlg->getMediaFormat();
+ m_useOnTheFly = m_configDlg->getUseOnTheFly();
+ m_useCheckCD = m_configDlg->getUseCheckCD();
+ m_volumeID = m_configDlg->getVolumeID();
+ m_volumeSetID = m_configDlg->getVolumeSetID();
+ m_systemID = m_configDlg->getSystemID();
+ m_applicationID = m_configDlg->getApplicationID();
+ m_publisher = m_configDlg->getPublisher();
+ m_preparer = m_configDlg->getPreparer();
+ m_albumListSize = albumsList.count();
+ m_albumsList = albumsList;
+
+ // Estimate the number of actions for the KIPI progress dialog.
+
+ int nbActions = 1;
+ int num_images = 0;
+
+ if ( m_useHTMLInterface == true )
+ {
+ QValueList<KIPI::ImageCollection>::Iterator it;
+ for (it = albumsList.begin(); it != albumsList.end(); ++it)
+ {
+ KIPI::ImageCollection col = (KIPI::ImageCollection)(*it);
+ num_images += col.images().count();
+ }
+ nbActions = nbActions + m_albumListSize + num_images + 1;
+
+ if ( m_useAutoRunWin32 == true )
+ ++nbActions;
+ }
+
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Initialize;
+ d->starting = true;
+ d->success = false;
+ d->total = nbActions;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ return(true);
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::stop()
+{
+ m_cancelled = true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::run()
+{
+ KIPICDArchivingPlugin::EventData *d;
+
+ // Making HTML interface.
+
+ if ( m_useHTMLInterface == true )
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildHTMLiface;
+ d->starting = true;
+ d->success = false;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ if ( buildHTMLInterface() == true )
+ {
+ m_HTMLInterfaceFolder = m_tmpFolder + "/HTMLInterface";
+ QString dir;
+ KGlobal::dirs()->addResourceType("kipi_autorun",
+ KGlobal::dirs()->kde_default("data") + "kipi/data");
+ dir = KGlobal::dirs()->findResourceDir("kipi_autorun", "index.htm");
+ m_HTMLInterfaceIndex = dir + "index.htm";
+
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildHTMLiface;
+ d->success = true;
+ d->starting = false;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ // Making AutoRun options.
+
+ if ( m_useAutoRunWin32 == true )
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildAutoRuniface;
+ d->starting = true;
+ d->success = false;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ CreateAutoRunInfFile();
+ m_HTMLInterfaceAutoRunInf = m_tmpFolder + "/autorun.inf";
+ m_HTMLInterfaceAutoRunFolder = dir + "/autorun";
+
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildAutoRuniface;
+ d->starting = false;
+ d->success = true;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ }
+ }
+ }
+
+ // Making K3b project file.
+
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildK3bProject;
+ d->starting = true;
+ d->success = false;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ if ( BuildK3bXMLprojectfile(m_HTMLInterfaceFolder, m_HTMLInterfaceIndex,
+ m_HTMLInterfaceAutoRunInf, m_HTMLInterfaceAutoRunFolder) == false )
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildK3bProject;
+ d->starting = false;
+ d->success = false;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ return;
+ }
+ else
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildK3bProject;
+ d->starting = false;
+ d->success = true;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::invokeK3b()
+{
+ if (m_cancelled) return;
+
+ m_Proc = new KProcess();
+
+ *m_Proc << m_K3bBinPathName << m_K3bParameters;
+ *m_Proc << m_tmpFolder + "/KIPICDArchiving.xml";
+
+ QString K3bCommandLine = m_K3bBinPathName + " " +
+ m_K3bParameters + " " +
+ m_tmpFolder + "/KIPICDArchiving.xml";
+ kdDebug(51000) << "K3b is started : " << K3bCommandLine.ascii() << endl;
+
+ connect(m_Proc, SIGNAL(processExited(KProcess *)),
+ this, SLOT(slotK3bDone(KProcess*)));
+
+ if ( !m_Proc->start(KProcess::NotifyOnExit, KProcess::All ) )
+ {
+ KIPICDArchivingPlugin::EventData *d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Error;
+ d->starting = false;
+ d->success = false;
+ d->message = i18n("Cannot start K3b program : fork failed.");
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ return;
+ }
+
+ m_actionCDArchiving->setEnabled(false);
+
+ if ( m_useStartBurningProcess == true )
+ {
+ QTimer::singleShot(10000,
+ this, SLOT(slotK3bStartBurningProcess()));
+ m_k3bPid = m_Proc->pid();
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::slotK3bStartBurningProcess(void)
+{
+ QString temp, cmd;
+ temp.setNum(m_k3bPid);
+ cmd = "dcop k3b-" + temp + " K3bProject-0 burn";
+
+ KRun::runCommand(cmd);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::slotK3bDone(KProcess*)
+{
+ kdDebug(51000) << "K3b is done !!! Removing temporary folder..." << endl;
+
+ KIPICDArchivingPlugin::EventData *d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Progress;
+ d->starting = true;
+ d->success = true;
+ d->message = i18n("K3b is done; removing temporary folder....");
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ if (DeleteDir(m_tmpFolder) == false)
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Error;
+ d->starting = false;
+ d->success = false;
+ d->message = i18n("Cannot remove temporary folder '%1'.").arg(m_tmpFolder);
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ }
+
+ m_actionCDArchiving->setEnabled(true);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CDArchiving::buildHTMLInterface (void)
+{
+ QString Path;
+ KIPICDArchivingPlugin::EventData *d;
+ KURL MainUrl;
+
+ // Create the main target folder.
+
+ QDir TargetDir;
+ QString MainTPath= m_tmpFolder + "/HTMLInterface";
+
+ if (TargetDir.exists (MainTPath) == true)
+ {
+ if (DeleteDir (MainTPath) == false)
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Error;
+ d->starting = false;
+ d->success = false;
+ d->message = i18n("Cannot remove folder '%1'.").arg(MainTPath);
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ return false;
+ }
+ }
+
+ if (TargetDir.mkdir( MainTPath ) == false)
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Error;
+ d->starting = false;
+ d->success = false;
+ d->message = i18n("Could not create folder '%1'.").arg(MainTPath);
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ return false;
+ }
+
+ // Build all Albums interface HTML.
+
+ // Adding go home icon if there is more than
+ KGlobal::dirs()->addResourceType("kipi_data", KGlobal::dirs()->kde_default("data") + "kipi");
+ QString dir = KGlobal::dirs()->findResourceDir("kipi_data", "gohome.png");
+ dir = dir + "gohome.png";
+ KURL srcURL(dir);
+ KURL destURL( MainTPath + "/gohome.png");
+ KIO::file_copy(srcURL, destURL, -1, true, false, false);
+
+ // Adding up icon
+ KGlobal::dirs()->addResourceType("kipi_data", KGlobal::dirs()->kde_default("data") + "kipi");
+ dir = KGlobal::dirs()->findResourceDir("kipi_data", "up.png");
+ dir = dir + "up.png";
+ srcURL = dir;
+ destURL = MainTPath + QString::fromLatin1("/up.png");
+ KIO::file_copy(srcURL, destURL, -1, true, false, false);
+
+ //clear the temporary list for unique names
+ m_collection_name_list.clear();
+ for (QValueList<KIPI::ImageCollection>::iterator it = m_albumsList.begin();
+ it != m_albumsList.end(); ++it)
+ {
+ KIPI::ImageCollection album = *it;
+ kdDebug( 51000 ) << "HTML Interface for Album: " << album.name() << endl;
+
+ m_AlbumTitle = makeFileNameUnique(m_collection_name_list, webifyFileName(album.name())); //webifyFileName(album.name());
+ m_AlbumComments = m_interface->hasFeature(KIPI::AlbumsHaveComments) ?
+ album.comment() : QString();
+ m_AlbumCollection = m_interface->hasFeature(KIPI::AlbumsHaveCategory) ?
+ album.category() : QString();
+ m_AlbumDate = m_interface->hasFeature(KIPI::AlbumsHaveCreationDate) ?
+ album.date().toString() : QString();
+
+ // Create the target sub folder for the current album.
+ QString SubTPath = m_tmpFolder + "/HTMLInterface/" + m_AlbumTitle;
+ KURL SubURL = SubTPath + "/index.htm";
+ if (TargetDir.mkdir( SubTPath ) == false)
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Error;
+ d->starting = false;
+ d->success = false;
+ d->message = i18n("Could not create folder '%1'.").arg(SubTPath);
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ return false;
+ }
+
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildAlbumHTMLPage;
+ d->starting = true;
+ d->success = false;
+ d->albumName = m_AlbumTitle;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ if ( createHtml( album, SubURL, m_imageFormat ) == false)
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildAlbumHTMLPage;
+ d->starting = false;
+ d->success = false;
+ d->albumName = m_AlbumTitle;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ if (DeleteDir (MainTPath) == false)
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Error;
+ d->starting = false;
+ d->success = false;
+ d->message = i18n("Cannot remove folder '%1'.").arg(MainTPath);
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ return false;
+ }
+
+ return false;
+ }
+
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::BuildAlbumHTMLPage;
+ d->starting = false;
+ d->success = true;
+ d->albumName = m_AlbumTitle;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ }
+
+ // Create the main interface HTML page.
+
+ MainUrl = m_tmpFolder + "/HTMLInterface/" + "index.htm";
+ QFile MainPageFile( MainUrl.path() );
+
+ if ( MainPageFile.open(IO_WriteOnly) )
+ {
+ QTextStream stream(&MainPageFile);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ createHead(stream);
+ createBodyMainPage(stream, MainUrl);
+ MainPageFile.close();
+ }
+ else
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Error;
+ d->starting = false;
+ d->success = false;
+ d->message = i18n("Could not open file '%1'.").arg(MainUrl.path(+1));
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ return false;
+ }
+
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CDArchiving::createDirectory(QDir thumb_dir, QString imgGalleryDir, QString dirName)
+{
+
+ if (!thumb_dir.exists())
+ {
+ thumb_dir.setPath( imgGalleryDir );
+
+ if (!(thumb_dir.mkdir(dirName, false)))
+ {
+ KIPICDArchivingPlugin::EventData *d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Error;
+ d->starting = false;
+ d->success = false;
+ d->message = i18n("Could not create folder '%1' in '%2'.")
+ .arg(dirName).arg(imgGalleryDir);
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ return false;
+ }
+ else
+ {
+ thumb_dir.setPath( imgGalleryDir + "/" + dirName + "/" );
+ return true;
+ }
+ }
+ else
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::createHead(QTextStream& stream)
+{
+ QString chsetName = QTextCodec::codecForLocale()->mimeName();
+
+ stream << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"
+ << endl;
+ stream << "<html>" << endl;
+ stream << "<head>" << endl;
+ stream << "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">" << endl;
+ stream << "<meta name=\"Generator\" content=\"Albums HTML interface for CD archiving generated by "
+ << m_hostName << " [" << m_hostURL << "]\">" << endl;
+ stream << "<meta name=\"date\" content=\"" + KGlobal::locale()->formatDate(QDate::currentDate())
+ + "\">" << endl;
+ stream << "<title>" << m_mainTitle << "</title>" << endl;
+ createCSSSection(stream);
+ stream << "</head>" << endl;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::createCSSSection(QTextStream& stream)
+{
+ QString backgroundColor = m_backgroundColor.name();
+ QString foregroundColor = m_foregroundColor.name();
+ QString bordersImagesColor = m_bordersImagesColor.name();
+
+ // Adding a touch of style
+
+ stream << "<style type='text/css'>\n";
+ stream << "BODY {color: " << foregroundColor << "; background: " << backgroundColor << ";" << endl;
+ stream << " font-family: " << m_fontName << ", sans-serif;" << endl;
+ stream << " font-size: " << m_fontSize << "pt; margin: 8%; }" << endl;
+ stream << "H1 {color: " << foregroundColor << ";}" << endl;
+ stream << "TABLE {text-align: center; margin-left: auto; margin-right: auto;}" << endl;
+ stream << "TD { color: " << foregroundColor << "; padding: 1em}" << endl;
+ stream << "IMG { border: 0px ; }" << endl;
+ stream << "IMG.photo { border: " << m_bordersImagesSize << "px solid "
+ << bordersImagesColor << "; }" << endl;
+ stream << "</style>" << endl;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+QString CDArchiving::extension(const QString& imageFormat)
+{
+ if (imageFormat == "PNG")
+ return ".png";
+
+ if (imageFormat == "JPEG")
+ return ".jpg";
+
+ Q_ASSERT(false);
+ return "";
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::createBody(QTextStream& stream,
+ const KIPI::ImageCollection& album,
+ const KURL& targetURL,
+ const QString& imageFormat)
+{
+ KURL::List images = album.images();
+ int numOfImages = images.count();
+
+ const QString imgGalleryDir = targetURL.directory();
+ const QString today(KGlobal::locale()->formatDate(QDate::currentDate()));
+
+ stream << "<body>\n" << endl;
+
+ stream << "<p><a href=\"../index.htm\"><img src=\"../gohome.png\" border=\"0\" title=\""
+ << i18n("Album list") << "\" alt=\"" << i18n("Album list") << "\"></a></p>" << endl;
+
+
+ // Page Top -------------------------------------------------------------------------
+
+ stream << "<h1>" << i18n("Album ") << "&quot;" << m_AlbumTitle << "&quot;"
+ << "</h1>" << endl;
+
+ stream << "<table width=\"100%\" border=1 cellpadding=0 cellspacing=0 "
+ "style=\"page-break-before: always\">\n" << endl;
+
+ stream << "<col width=\"20%\"><col width=\"80%\">" << endl;
+ stream << "<tr valign=top><td align=left>\n" << endl;
+
+ if (m_interface->hasFeature(KIPI::AlbumsHaveComments))
+ stream << i18n("<i>Caption:</i>") << "<br>\n" << endl;
+
+ if (m_interface->hasFeature(KIPI::AlbumsHaveCategory))
+ stream << i18n("<i>Collection:</i>") << "<br>\n" << endl;
+
+ if (m_interface->hasFeature(KIPI::AlbumsHaveCreationDate))
+ stream << i18n("<i>Date:</i>") << "<br>\n" << endl;
+
+ stream << i18n("<i>Images:</i>") << "\n" << endl;
+
+ stream << "</td><td align=left>\n" << endl;
+
+ if (m_interface->hasFeature(KIPI::AlbumsHaveComments))
+ stream << EscapeSgmlText(QTextCodec::codecForLocale(),
+ m_AlbumComments, true, true)
+ << "<br>\n" << endl;
+
+ if (m_interface->hasFeature(KIPI::AlbumsHaveCategory))
+ stream << m_AlbumCollection << "<br>\n" << endl;
+
+ if (m_interface->hasFeature(KIPI::AlbumsHaveCreationDate))
+ stream << m_AlbumDate << "<br>\n" << endl;
+
+ stream << numOfImages << "\n" << endl;
+
+ stream << "</td></tr></table>\n" << endl;
+
+ // Page Center -----------------------------------------------------------------------
+ stream << "<table>" << endl;
+
+ // Table with images
+ int imgIndex = 0;
+ EventData* d = 0;
+
+ // preliminary unique name generation
+ QStringList fileNameList;
+ for ( KURL::List::iterator urlIt = images.begin() ;
+ !m_cancelled && (urlIt != images.end());
+ ++urlIt)
+ {
+ QFileInfo imInfo( (*urlIt).fileName());
+ QString imgName = makeFileNameUnique(fileNameList, webifyFileName(imInfo.baseName(TRUE)));
+ }
+ for ( KURL::List::iterator urlIt = images.begin() ;
+ !m_cancelled && (urlIt != images.end());
+ ++urlIt, ++imgIndex)
+ {
+ // Row Start
+ if ((imgIndex % m_imagesPerRow) == 0)
+ {
+ stream << "<tr>" << endl;
+ }
+
+ QString imgName = fileNameList[imgIndex];
+ QString imgPath = (*urlIt).path();
+ QFileInfo imgInfo(imgPath);
+ QImage imgProp = QImage(imgPath);
+
+ stream << "<td align='center'>\n<a href=\"pages/"
+ << webifyFileName(imgName) << ".htm\">";
+ kdDebug(51000) << "Creating thumbnail for " << imgName << endl;
+
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::ResizeImages;
+ d->starting = true;
+ d->success = false;
+ d->fileName = imgName;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ int valRet = createThumb((*urlIt).fileName(), (*urlIt).directory(), imgName,
+ imgGalleryDir, imageFormat);
+
+ if ( valRet != -1 )
+ {
+ QString thumbPath("thumbs/" + webifyFileName(imgName)
+ + extension(imageFormat));
+ stream << "<img class=\"photo\" src=\"" << thumbPath
+ << "\" width=\"" << m_imgWidth
+ << "\" "
+ << "height=\"" << m_imgHeight
+ << "\" alt=\"" << imgPath;
+
+ QString sep = "\" title=\"";
+
+ stream << sep << imgName;
+ sep = ", ";
+
+ stream << sep << imgProp.width() << "&nbsp;x&nbsp;" << imgProp.height();
+ sep = ", ";
+
+ stream << sep << (imgInfo.size() / 1024) << "&nbsp;" << i18n("KB");
+ sep = ", ";
+
+ QString imgPageComment = m_interface->info(*urlIt).description();
+
+ if ( !imgPageComment.isEmpty() )
+ {
+ stream << sep
+ << EscapeSgmlText(QTextCodec::codecForLocale(),
+ imgPageComment, true, true);
+ }
+
+ stream << "\">" << endl;
+
+ QString prevImgName = "";
+ QString nextImgName = "";
+
+ if (imgIndex != 0)
+ prevImgName = images[imgIndex].fileName();
+
+ if (imgIndex < numOfImages-1)
+ nextImgName = images[imgIndex].fileName();
+
+
+ createPage(imgGalleryDir, (*urlIt), imgName,
+ (imgIndex > 0) ? images[imgIndex-1] : KURL(),
+ (imgIndex > 0) ? fileNameList[imgIndex-1] : QString(""),
+ (imgIndex < (int)(images.count()-1)) ? images[imgIndex+1] : KURL(),
+ (imgIndex < (int)(fileNameList.count()-1)) ?
+ fileNameList[imgIndex+1] : QString(""),
+ imgPageComment);
+
+ // For each first image of current Album we add a preview in main HTML page.
+
+ if ( imgIndex == 0)
+ {
+ QString Temp, Temp2;
+ Temp2 = "<a href=\"./" + m_AlbumTitle + "/" + "index.htm" + "\">";
+ m_StreamMainPageAlbumPreview.append ( Temp2 );
+ Temp2 = "<img class=\"photo\" src=\"./" + m_AlbumTitle + "/"
+ + thumbPath + "\" width=\"" + Temp.setNum(m_imgWidth) + "\" ";
+ m_StreamMainPageAlbumPreview.append ( Temp2 );
+ Temp2 = "height=\"" + Temp.setNum(m_imgHeight) + "\" alt=\"" + thumbPath + "\" ";
+ m_StreamMainPageAlbumPreview.append ( Temp2 );
+ Temp2 = "title=\"" + m_AlbumTitle + " [ " + Temp.setNum(numOfImages)
+ + i18n(" images") + " ]\"></a>\n";
+ m_StreamMainPageAlbumPreview.append ( Temp2 );
+ Temp2 = "<a href=\"./" + m_AlbumTitle + "/" + "index.htm" + "\">"
+ + m_AlbumTitle + "</a>" + " [ " + Temp.setNum(numOfImages) + i18n(" images")
+ + " ]" + "<br>\n";
+ m_StreamMainPageAlbumPreview.append ( Temp2 );
+ }
+ }
+
+ if ( valRet == -1 || valRet == 0 )
+ {
+ kdDebug(51000) << "Creating thumbnail for " << imgName
+ << "failed !" << endl;
+
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::ResizeImages;
+ d->starting = false;
+ d->success = false;
+ d->fileName = imgName;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ }
+ else
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::ResizeImages;
+ d->starting = false;
+ d->success = true;
+ d->fileName = imgName;
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ }
+
+ stream << "</a>" << endl;
+
+ stream << "<div>" << imgName << "</div>" << endl;
+
+ stream << "<div>" << imgProp.width() << " x " << imgProp.height() << "</div>" << endl;
+ stream << "<div>(" << (imgInfo.size() / 1024) << " " << i18n("KB") << ") " << "</div>" << endl;
+
+ stream << "</td>" << endl;
+
+ // Row End
+ if ( ((imgIndex+1) % m_imagesPerRow) == 0 ||
+ ((imgIndex+1) == (int)(images.count())) )
+ {
+ stream << "</tr>" << endl;
+ }
+ }
+
+ // Close the HTML and page creation info if necessary.
+
+ stream << "</table>\n<hr>\n" << endl;
+
+ QString Temp;
+ KGlobal::dirs()->addResourceType("kipi_data", KGlobal::dirs()->kde_default("data") + "kipi");
+ QString dir = KGlobal::dirs()->findResourceDir("kipi_data", "valid-html401.png");
+ dir = dir + "valid-html401.png";
+
+ KURL srcURL(dir);
+ KURL destURL(imgGalleryDir + QString::fromLatin1("/thumbs/valid-html401.png"));
+ KIO::file_copy(srcURL, destURL, -1, true, false, false);
+
+ stream << "<p>" << endl;
+ Temp = i18n("Valid HTML 4.01.");
+ stream << "<img src=\"thumbs/valid-html401.png\" alt=\"" << Temp
+ << "\" height=\"31\" width=\"88\" title=\"" << Temp << "\" />" << endl;
+
+ Temp = i18n("Album archive created with "
+ "<a href=\"%1\">%2</a> on %3").arg(m_hostURL).arg(m_hostName).arg(today);
+
+ stream << Temp << endl;
+ stream << "</p>" << endl;
+ stream << "</body>\n</html>\n" << endl;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::createBodyMainPage(QTextStream& stream, KURL& url)
+{
+ QString Temp;
+ const QString today(KGlobal::locale()->formatDate(QDate::currentDate()));
+
+ Temp = m_mainTitle;
+ stream << "<body>\n<h1>" << Temp << "</h1><p>\n" << endl;
+
+ Temp = i18n("<i>Album list:</i>");
+ stream << Temp << "<br>" << endl;
+ stream << "<hr>" << endl;
+
+ stream << "<p> " << m_StreamMainPageAlbumPreview << "</p>" << endl;
+
+ stream << "<hr>" << endl;
+
+ KGlobal::dirs()->addResourceType("kipi_data", KGlobal::dirs()->kde_default("data") + "kipi");
+ QString dir = KGlobal::dirs()->findResourceDir("kipi_data", "valid-html401.png");
+ dir = dir + "valid-html401.png";
+
+ KURL srcURL(dir);
+ KURL destURL(url.directory() + QString::fromLatin1("/valid-html401.png"));
+ KIO::file_copy(srcURL, destURL, -1, true, false, false);
+
+ stream << "<p>" << endl;
+ Temp = i18n("Valid HTML 4.01.");
+ stream << "<img src=\"valid-html401.png\" alt=\"" << Temp << "\" height=\"31\" width=\"88\" title=\""
+ << Temp << "\" />" << endl;
+
+ Temp = i18n("Album archive created with "
+ "<a href=\"%1\">%2</a> on %3").arg(m_hostURL).arg(m_hostName).arg(today);
+ stream << Temp << endl;
+ stream << "</p>" << endl;
+ stream << "</body>\n</html>\n" << endl;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CDArchiving::createHtml( const KIPI::ImageCollection& album,
+ const KURL& targetURL,
+ const QString& imageFormat )
+{
+ if (m_cancelled)
+ return false;
+
+ // Sort the images files formats running with thumbnails construction.
+
+ const QString imgGalleryDir = targetURL.directory();
+
+ // Create the "thumbs" subdirectory
+
+ QDir thumb_dir( imgGalleryDir + QString::fromLatin1("/thumbs/"));
+
+ if (createDirectory(thumb_dir, imgGalleryDir, "thumbs") == false)
+ return false;
+
+ QDir pages_dir( imgGalleryDir + QString::fromLatin1("/pages/"));
+
+ if (createDirectory(pages_dir, imgGalleryDir, "pages") == false)
+ return false;
+
+ // Create HTML page.
+
+ QFile file( targetURL.path() );
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ QTextStream stream(&file);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ createHead(stream);
+ createBody(stream, album, targetURL, imageFormat);
+ file.close();
+ return true;
+ }
+ else
+ {
+ KIPICDArchivingPlugin::EventData *d;
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Error;
+ d->starting = false;
+ d->success = false;
+ d->message = i18n("Could not open file '%1'.").arg(targetURL.path(+1));
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ return false;
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CDArchiving::createPage(const QString& imgGalleryDir,
+ const KURL& imgURL,
+ const QString& uniqueImgName,
+ const KURL& prevImgURL,
+ const QString& prevUniqueImgName,
+ const KURL& nextImgURL,
+ const QString& nextUniqueImgName,
+ const QString& comment)
+{
+
+ const QDir pagesDir(imgGalleryDir + QString::fromLatin1("/pages/"));
+ const QDir thumbsDir(imgGalleryDir + QString::fromLatin1("/thumbs/"));
+ const QFileInfo fi (imgURL.fileName());
+ const QString imgName = uniqueImgName + "." + fi.extension(FALSE);
+ kdDebug( 51000 ) << "CreatePage: FileName: " << imgURL.fileName() << endl;
+ kdDebug( 51000 ) << "CreatePage: uniqueFileName: " << imgName << endl;
+ kdDebug( 51000 ) << "CreatePage: uniquePrevFileName: " << prevUniqueImgName << endl;
+ kdDebug( 51000 ) << "CreatePage: uniqueNextFileName: " << nextUniqueImgName << endl;
+
+
+ // Html pages filenames
+
+ const QString pageFilename = pagesDir.path() +
+ QString::fromLatin1("/") +
+ webifyFileName(uniqueImgName)+
+ QString::fromLatin1(".htm");
+ const QString nextPageFilename = webifyFileName(nextUniqueImgName) +
+ QString::fromLatin1(".htm");
+ const QString prevPageFilename = webifyFileName(prevUniqueImgName) +
+ QString::fromLatin1(".htm");
+
+ // Thumbs filenames
+
+ const QString prevThumb = QString::fromLatin1("../thumbs/") +
+ webifyFileName(prevUniqueImgName) +
+ extension(m_imageFormat);
+
+ const QString nextThumb = QString::fromLatin1("../thumbs/") +
+ webifyFileName(nextUniqueImgName) +
+ extension(m_imageFormat);
+
+ QFile file( pageFilename );
+
+ if ( pagesDir.exists() && file.open(IO_WriteOnly) )
+ {
+ QTextStream stream(&file);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+
+ QString chsetName = QTextCodec::codecForLocale()->mimeName();
+ stream << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\""
+ " \"http://www.w3.org/TR/html4/loose.dtd\">" << endl;
+ stream << "<html>" << endl;
+ stream << "<head>" << endl;
+ stream << "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">" << endl;
+
+ stream << "<meta name=\"Generator\" content=\"Albums Images gallery generated by "
+ << m_hostName << " [" << m_hostURL << "]\">" << endl;
+
+ stream << "<meta name=\"date\" content=\""
+ << KGlobal::locale()->formatDate(QDate::currentDate())
+ << "\">" << endl;
+ stream << "<title>" << m_mainTitle << " : "<< imgName/*imgURL.fileName()*/ <<"</title>" << endl;
+
+ createCSSSection(stream);
+
+ stream << "</head>" << endl;
+ stream<<"<body>" << endl;;
+ stream << "<div align=\"center\">"<< endl;
+
+ QImage imgProp;
+ int prevW = 0;
+ int prevH = 0;
+ int nextW = 0;
+ int nextH = 0;
+
+ if (imgProp.load(prevImgURL.path()))
+ {
+ prevW = imgProp.width();
+ prevH = imgProp.height();
+ }
+
+ if (imgProp.load(nextImgURL.path()))
+ {
+ nextW = imgProp.width();
+ nextH = imgProp.height();
+ }
+
+ // Navigation thumbs need to be 64x64 at most
+
+ if ( prevW < prevH )
+ {
+ prevH = (NAV_THUMB_MAX_SIZE * prevH) / prevW;
+ prevW = NAV_THUMB_MAX_SIZE;
+ }
+ else if ( prevW==prevH )
+ {
+ prevH = NAV_THUMB_MAX_SIZE;
+ prevW = NAV_THUMB_MAX_SIZE;
+ }
+ else
+ {
+ prevW = (NAV_THUMB_MAX_SIZE * prevW) / prevH;
+ prevH = NAV_THUMB_MAX_SIZE;
+ }
+
+ if ( nextW < nextH )
+ {
+ nextH = (NAV_THUMB_MAX_SIZE * nextH) / nextW;
+ nextW = NAV_THUMB_MAX_SIZE;
+ }
+ else if ( nextW==nextH )
+ {
+ nextH = NAV_THUMB_MAX_SIZE ;
+ nextW = NAV_THUMB_MAX_SIZE;
+ }
+ else
+ {
+ nextW = (NAV_THUMB_MAX_SIZE * nextW) / nextH;
+ nextH = NAV_THUMB_MAX_SIZE;
+ }
+
+ if ( prevImgURL.isValid() )
+ {
+ stream << "<a href=\"" << prevPageFilename << "\"><img class=\"photo\" src=\""
+ << prevThumb<<"\" alt=\"" << i18n("Previous") << "\" title=\"" << i18n("Previous")
+ << "\" height=\"" << prevH << "\" width=\"" << prevW << "\"></a>&nbsp; | &nbsp;" << endl;
+ }
+
+ stream << "<a href=\"../index.htm\"><img src=\"../../up.png\" border=\"0\" title=\""
+ << i18n("Album index") << "\" alt=\"" << i18n("Album index") << "\"></a>" << endl;
+ stream << "&nbsp; | &nbsp;<a href=\"../../index.htm\"><img src=\"../../gohome.png\" border=\"0\" title=\""
+ << i18n("Album list") << "\" alt=\"" << i18n("Album list") << "\"></a>" << endl;
+
+ if ( nextImgURL.isValid() )
+ {
+ stream << "&nbsp; | &nbsp;<a href=\"" << nextPageFilename<<"\"><img class=\"photo\" src=\""
+ << nextThumb << "\" alt=\"" << i18n("Next") << "\" title=\"" << i18n("Next")
+ << "\" height=\"" << nextH << "\" width=\"" << nextW << "\"></a>" << endl;
+ }
+
+ stream << "<br><hr><br>" << endl;
+
+ // Add comment if it exists
+
+ if ( !comment.isEmpty() )
+ {
+ stream << "<div align=\"center\">"
+ << EscapeSgmlText(QTextCodec::codecForLocale(), comment, true, true)
+ << "</div>" << endl;
+ }
+
+ stream <<"<br>" << endl;
+
+ stream << "<img class=\"photo\" src=\"../../../" << m_AlbumTitle << "/" << imgName
+ << "\" alt=\"" << imgName;
+
+ // Add info about image if requested
+
+ QString sep="\" title=\"";
+ QFileInfo imgInfo;
+
+ stream << sep << imgName;
+ sep = ", ";
+
+ imgProp.load( imgURL.path() );
+ stream << sep << imgProp.width() << "&nbsp;x&nbsp;" << imgProp.height();
+ sep = ", ";
+
+ imgInfo.setFile( imgURL.path() );
+ stream << sep << (imgInfo.size() / 1024) << "&nbsp;" << i18n("KB");
+
+ stream << "\"><br><br></div>" << endl;
+
+ // Footer
+
+ QString valid = i18n("Valid HTML 4.01.");
+ const QString today(KGlobal::locale()->formatDate(QDate::currentDate()));
+
+ stream << "<div align=\"center\"><hr><img src=\"../thumbs/valid-html401.png\" alt=\""
+ << valid << "\" height=\"31\" width=\"88\" title=\"" << valid << "\" />" << endl;
+
+ valid = i18n("Image gallery created with "
+ "<a href=\"%1\">%2</a> on %3").arg(m_hostURL).arg(m_hostName).arg(today);
+
+ stream << valid << "</div>" << endl;
+
+ stream << "</body></html>" << endl;
+ file.close();
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int CDArchiving::createThumb( const QString& imgName, const QString& sourceDirName,
+ const QString& uniqueFileName,
+ const QString& imgGalleryDir, const QString& imageFormat)
+{
+ const QString pixPath = sourceDirName + "/" + imgName;
+
+ // Create the thumbnails for the HTML interface.
+
+ const QString ImageNameFormat = webifyFileName(uniqueFileName) + extension(imageFormat);
+ const QString thumbDir = imgGalleryDir + QString::fromLatin1("/thumbs/");
+ int extent = m_thumbnailsSize;
+
+ m_imgWidth = 120; // Setting the size of the images is
+ m_imgHeight = 90; // required to generate faster 'loading' pages
+
+ return (ResizeImage(pixPath, thumbDir, imageFormat, ImageNameFormat,
+ &m_imgWidth, &m_imgHeight, extent, false, 16, false, 100));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int CDArchiving::ResizeImage( const QString Path, const QString Directory, const QString ImageFormat,
+ const QString ImageNameFormat, int *Width, int *Height, int SizeFactor,
+ bool ColorDepthChange, int ColorDepthValue, bool CompressionSet,
+ int ImageCompression)
+{
+ QImage img;
+ bool ValRet;
+ bool usingBrokenImage = false;
+
+ ValRet = img.load(Path);
+
+ if ( ValRet == false ) // Cannot load the src image.
+ {
+ KGlobal::dirs()->addResourceType("kipi_imagebroken", KGlobal::dirs()->kde_default("data") + "kipi/data");
+ QString dir = KGlobal::dirs()->findResourceDir("kipi_imagebroken", "image_broken.png");
+ dir = dir + "image_broken.png";
+ kdDebug ( 51000 ) << "Loading " << Path.ascii() << " failed ! Using " << dir.ascii()
+ << " instead..." << endl;
+ ValRet = img.load(dir); // Try broken image icon...
+ usingBrokenImage = true;
+ }
+
+ if ( ValRet == true )
+ {
+ int w = img.width();
+ int h = img.height();
+
+ if (SizeFactor != -1) // Use original image size ?
+ {
+ // scale to pixie size
+ // kdDebug( 51000 ) << "w: " << w << " h: " << h << endl;
+ // Resizing if to big
+
+ if ( w > SizeFactor || h > SizeFactor )
+ {
+ if ( w > h )
+ {
+ h = (int)( (double)( h * SizeFactor ) / w );
+
+ if ( h == 0 ) h = 1;
+
+ w = SizeFactor;
+ Q_ASSERT( h <= SizeFactor );
+ }
+ else
+ {
+ w = (int)( (double)( w * SizeFactor ) / h );
+
+ if ( w == 0 ) w = 1;
+
+ h = SizeFactor;
+ Q_ASSERT( w <= SizeFactor );
+ }
+
+ const QImage scaleImg(img.smoothScale( w, h ));
+
+ if ( scaleImg.width() != w || scaleImg.height() != h )
+ {
+ kdDebug( 51000 ) << "Resizing failed. Aborting." << endl;
+ return -1;
+ }
+
+ img = scaleImg;
+ }
+
+ if ( ColorDepthChange == true )
+ {
+ const QImage depthImg(img.convertDepth( ColorDepthValue ));
+ img = depthImg;
+ }
+ }
+
+ kdDebug( 51000 ) << "Saving resized image to: " << Directory + ImageFormat << endl;
+
+ if ( CompressionSet == true )
+ {
+ if ( !img.save(Directory + ImageNameFormat, ImageFormat.latin1(), ImageCompression) )
+ {
+ kdDebug( 51000 ) << "Saving failed with specific compression value. Aborting." << endl;
+ return -1;
+ }
+ }
+ else
+ {
+ if ( !img.save(Directory + ImageNameFormat, ImageFormat.latin1(), -1) )
+ {
+ kdDebug( 51000 ) << "Saving failed with no compression value. Aborting." << endl;
+ return -1;
+ }
+ }
+
+ *Width = w;
+ *Height = h;
+
+ if ( usingBrokenImage == true )
+ return 0;
+ else
+ return 1;
+ }
+
+ return -1;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CDArchiving::BuildK3bXMLprojectfile (QString HTMLinterfaceFolder, QString IndexHtm,
+ QString AutoRunInf, QString AutorunFolder)
+{
+ QString Temp;
+ KIPICDArchivingPlugin::EventData *d;
+ QFile XMLK3bProjectFile;
+
+ // open the K3b XML project file.
+
+ XMLK3bProjectFile.setName ( m_tmpFolder + "/KIPICDArchiving.xml" );
+
+ if ( XMLK3bProjectFile.open ( IO_WriteOnly | IO_Truncate ) == false )
+ return false;
+
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Progress;
+ d->starting = true;
+ d->success = false;
+ d->message = i18n("Creating project header...");
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+
+ // Build K3b XML project File.
+
+ QTextStream stream( &XMLK3bProjectFile );
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+
+ // XML Header.
+
+ Temp = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+
+ stream << Temp;
+
+ if (m_mediaFormat == i18n("DVD (4,7Gb)"))
+ Temp = "<!DOCTYPE k3b_dvd_project>\n"
+ "<k3b_dvd_project>\n"; // Build a Data DVD project file.
+ else
+ Temp = "<!DOCTYPE k3b_data_project>\n"
+ "<k3b_data_project>\n"; // Build a Data CD project file.
+
+ stream << Temp;
+
+ // General section.
+
+ Temp = "<general>\n"
+ "<writing_mode>auto</writing_mode>\n" // Let K3b selected the good mode.
+ "<dummy activated=\"no\" />\n"; // Simulation always disactived.
+
+ stream << Temp;
+
+ if (m_useOnTheFly == false) // Burning CD On The Fly ?
+ Temp = "<on_the_fly activated=\"no\" />\n";
+ else
+ Temp = "<on_the_fly activated=\"yes\" />\n";
+
+ stream << Temp;
+
+ Temp = "<only_create_images activated=\"no\" />\n" // Always desactived.
+ "<remove_images activated=\"yes\" />\n" // Always actived.
+ "</general>\n";
+
+ stream << Temp;
+
+ // Option section.
+
+ Temp = "<options>\n"
+ "<rock_ridge activated=\"yes\" />\n" // Always actived for Linux.
+ "<joliet activated=\"yes\" />\n"; // Always actived for Win32.
+
+ stream << Temp;
+
+ if (m_mediaFormat == i18n("DVD (4,7Gb)"))
+ Temp = "<udf activated=\"yes\" />\n"; // Need this option for DVDR/RW.
+ else
+ Temp = "<udf activated=\"no\" />\n"; // Don't need this option for CDR/RW
+
+ stream << Temp;
+
+ Temp = "<iso_allow_lowercase activated=\"no\" />\n"
+ "<iso_allow_period_at_begin activated=\"no\" />\n"
+ "<iso_allow_31_char activated=\"yes\" />\n"
+ "<iso_omit_version_numbers activated=\"no\" />\n"
+ "<iso_omit_trailing_period activated=\"no\" />\n"
+ "<iso_max_filename_length activated=\"no\" />\n"
+ "<iso_relaxed_filenames activated=\"no\" />\n"
+ "<iso_no_iso_translate activated=\"no\" />\n"
+ "<iso_allow_multidot activated=\"no\" />\n"
+ "<iso_untranslated_filenames activated=\"no\" />\n"
+ "<follow_symbolic_links activated=\"no\" />\n" // Always desactived.
+ "<create_trans_tbl activated=\"no\" />\n"
+ "<hide_trans_tbl activated=\"no\" />\n"
+ "<iso_level>2</iso_level>\n" // Always ISO level 2.
+ "<discard_symlinks activated=\"no\" />\n" // Always desactived.
+ "<discard_broken_symlinks activated=\"no\" />\n" // Always desactived.
+ "<preserve_file_permissions activated=\"yes\" />\n" // Actived : backup.
+ "<force_input_charset activated=\"no\" />\n" // Disabled.
+ "<input_charset>iso8859-1</input_charset>\n" // Disabled (see before).
+ "<whitespace_treatment>noChange</whitespace_treatment>\n"
+ "<whitespace_replace_string>_</whitespace_replace_string>\n"
+ "<data_track_mode>auto</data_track_mode>\n" // Let K3b selected the good mode.
+ "<multisession>none</multisession>\n"; // Always 1 session for backup CD.
+
+ stream << Temp;
+
+ if (m_useCheckCD == false) // Checking CD after burning process ?
+ Temp = "<verify_data activated=\"no\" />\n";
+ else
+ Temp = "<verify_data activated=\"yes\" />\n";
+
+ stream << Temp;
+
+ Temp = "</options>\n";
+
+ stream << Temp;
+
+ // Header section.
+
+ Temp = "<header>\n"
+ "<volume_id>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), m_volumeID, true, true)
+ + "</volume_id>\n"
+ "<volume_set_id>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), m_volumeSetID, true, true)
+ + "</volume_set_id>\n"
+ "<volume_set_size>1</volume_set_size>\n"
+ "<volume_set_number>1</volume_set_number>\n"
+ "<system_id>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), m_systemID, true, true)
+ + "</system_id>\n"
+ "<application_id>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), m_applicationID, true, true)
+ + "</application_id>\n"
+ "<publisher>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), m_publisher, true, true)
+ + "</publisher>\n"
+ "<preparer>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), m_preparer, true, true)
+ + "</preparer>\n"
+ "</header>\n";
+
+ stream << Temp;
+
+ // Files and folders section.
+
+ Temp = "<files>\n";
+
+ stream << Temp;
+
+ if ( IndexHtm.isEmpty() == false ) // index.htm file in CD root.
+ {
+ Temp = "<file name=\"index.htm\" >\n"
+ "<url>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), IndexHtm, true, true)
+ + "</url>\n"
+ "</file>\n";
+
+ stream << Temp;
+ }
+
+ if ( AutoRunInf.isEmpty() == false ) // Autorun.inf file in CD root.
+ {
+ Temp = "<file name=\"autorun.inf\" >\n"
+ "<url>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), AutoRunInf, true, true)
+ + "</url>\n"
+ "</file>\n";
+
+ stream << Temp;
+ }
+
+ // Add Autorun folder name and files.
+
+ if ( AutorunFolder.isEmpty() == false )
+ AddFolderTreeToK3bXMLProjectFile(AutorunFolder, &stream);
+
+ // Add HTMLInterface folders name and files.
+
+ if ( HTMLinterfaceFolder.isEmpty() == false )
+ AddFolderTreeToK3bXMLProjectFile(HTMLinterfaceFolder, &stream);
+
+ //clear the temporary list for unique names
+ m_collection_name_list.clear();
+
+ for (QValueList<KIPI::ImageCollection>::iterator it = m_albumsList.begin();
+ !m_cancelled && (it != m_albumsList.end()); ++it)
+
+ {
+ d = new KIPICDArchivingPlugin::EventData;
+ d->action = KIPICDArchivingPlugin::Progress;
+ d->starting = true;
+ d->success = false;
+ d->message = i18n("Adding Album '%1' into project...").arg( (*it).name() );
+ QApplication::sendEvent(m_parent, new QCustomEvent(QEvent::User, d));
+ usleep(1000);
+ addCollectionToK3bXMLProjectFile( *it, &stream);
+ }
+
+ Temp = "</files>\n";
+
+ stream << Temp;
+
+ if (m_mediaFormat == i18n("DVD (4,7Gb)"))
+ Temp = "</k3b_dvd_project>\n"; // Close the Data DVD project file.
+ else
+ Temp = "</k3b_data_project>\n"; // Close the Data CD project file.
+
+ stream << Temp;
+
+ // Close K3b XML project File.
+
+ XMLK3bProjectFile.close();
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CDArchiving::AddFolderTreeToK3bXMLProjectFile (QString dirname, QTextStream* stream)
+{
+ QString Temp;
+
+ QDir dir(dirname);
+ dir.setFilter ( QDir::Dirs | QDir::Files | QDir::NoSymLinks );
+
+ Temp = "<directory name=\""
+ + EscapeSgmlText(QTextCodec::codecForLocale(), dir.dirName(), true, true)
+ + "\" >\n";
+ *stream << Temp;
+
+ kdDebug( 51000 ) << "Directory: " << dir.dirName().latin1 () << endl;
+
+ const QFileInfoList* fileinfolist = dir.entryInfoList();
+ QFileInfoListIterator it_files(*fileinfolist);
+ QFileInfoListIterator it_folders(*fileinfolist);
+ QFileInfo* fi_files;
+ QFileInfo* fi_folders;
+
+ while ( (fi_files = it_files.current()) && !m_cancelled ) // Check all files in folder.
+ {
+ if ( fi_files->fileName() == "." || fi_files->fileName() == ".." )
+ {
+ ++it_files;
+ continue;
+ }
+
+ if ( fi_files->isFile() )
+ {
+ kdDebug( 51000 ) << " Filename: " << fi_files->fileName().latin1() << endl;
+
+ Temp = "<file name=\""
+ + EscapeSgmlText(QTextCodec::codecForLocale(), fi_files->fileName(), true, true)
+ + "\" >\n"
+ "<url>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), fi_files->absFilePath(), true, true)
+ + "</url>\n"
+ "</file>\n";
+
+ *stream << Temp;
+ }
+
+ ++it_files;
+ }
+
+ while ( (fi_folders = it_folders.current()) && !m_cancelled ) // Check all sub-folders in folder.
+ {
+ if ( fi_folders->fileName() == "." || fi_folders->fileName() == ".." )
+ {
+ ++it_folders;
+ continue;
+ }
+
+ if ( fi_folders->isDir() )
+ {
+ kdDebug( 51000 ) << " folder: " << fi_folders->fileName().latin1() << endl;
+
+ AddFolderTreeToK3bXMLProjectFile ( fi_folders->absFilePath(), stream );
+ }
+
+ ++it_folders;
+ }
+
+ Temp = "</directory>\n";
+ *stream << Temp;
+
+ return true;
+}
+
+bool CDArchiving::addCollectionToK3bXMLProjectFile(const KIPI::ImageCollection& collection,
+ QTextStream* stream)
+{
+ kdDebug( 51000 ) << "Adding Collection: " << collection.name() << endl;
+
+ QString Temp;
+ QString collection_name;
+ if (m_useHTMLInterface)
+ collection_name = makeFileNameUnique(m_collection_name_list, webifyFileName(collection.name()));
+ else
+ collection_name = makeFileNameUnique(m_collection_name_list, collection.name());
+ kdDebug( 51000 ) << "num of unique collections: "<< m_collection_name_list.size() << endl;
+
+ Temp = "<directory name=\""
+ + EscapeSgmlText(QTextCodec::codecForLocale(), collection_name, true, true)
+ + "\" >\n";
+ *stream << Temp;
+
+ KURL::List images = collection.images();
+ kdDebug( 51000 ) << " Files: " << images.size() << endl;
+ QStringList fileNameList;
+ QString fName;
+ for (KURL::List::iterator it = images.begin();
+ (it != images.end()) && !m_cancelled;
+ ++it)
+ {
+
+ kdDebug( 51000 ) << " Filename: " << (*it).fileName() << endl;
+ QFileInfo fInfo((*it).fileName());
+ if (m_useHTMLInterface)
+ fName = makeFileNameUnique(fileNameList, webifyFileName(fInfo.baseName(TRUE)))
+ + "." + fInfo.extension( FALSE );
+ else
+ fName = makeFileNameUnique(fileNameList, fInfo.baseName(TRUE))
+ + "." + fInfo.extension( FALSE );
+ kdDebug( 51000 ) << " Unique filename: " << fName << endl;
+ kdDebug( 51000 ) << "num of unique files: "<< fileNameList.size() << endl;
+
+ Temp = "<file name=\""
+ + EscapeSgmlText(QTextCodec::codecForLocale(), fName, true, true)
+ + "\" >\n"
+ "<url>"
+ + EscapeSgmlText(QTextCodec::codecForLocale(), (*it).path(), true, true)
+ + "</url>\n"
+ "</file>\n";
+
+ *stream << Temp;
+ }
+
+ Temp = "</directory>\n";
+ *stream << Temp;
+
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool CDArchiving::CreateAutoRunInfFile(void)
+{
+ QString Temp;
+ QFile AutoRunInf;
+
+ AutoRunInf.setName ( m_tmpFolder + "/autorun.inf" );
+
+ if ( AutoRunInf.open ( IO_WriteOnly | IO_Truncate ) == false )
+ return false;
+
+ QTextStream stream( &AutoRunInf );
+
+ Temp = "[autorun]\r\n"
+ "OPEN=autorun\\ShellExecute.bat HTMLInterface\\index.htm\r\n"
+ "ICON=autorun\\cdalbums.ico\r\n";
+
+ stream << Temp;
+
+ Temp = "LABEL=" + m_volumeID + "\r\n";
+ stream << Temp;
+
+ AutoRunInf.close();
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void CDArchiving::removeTmpFiles(void)
+{
+ DeleteDir(m_tmpFolder);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// This code can be multithreaded (in opposite to KIO::netaccess::delete().
+
+bool CDArchiving::DeleteDir(QString dirname)
+{
+ if ( !dirname.isEmpty() )
+ {
+ QDir dir;
+
+ if (dir.exists ( dirname ) == true)
+ {
+ if (deldir(dirname) == false)
+ return false;
+
+ if (dir.rmdir( dirname ) == false )
+ return false;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// This code can be multithreaded (in opposite to KIO::netaccess::delete().
+
+bool CDArchiving::deldir(QString dirname)
+{
+ QDir dir(dirname);
+ dir.setFilter ( QDir::Dirs | QDir::Files | QDir::NoSymLinks );
+
+ const QFileInfoList* fileinfolist = dir.entryInfoList();
+ QFileInfoListIterator it(*fileinfolist);
+ QFileInfo* fi;
+
+ while ( (fi = it.current() ) )
+ {
+ if (fi->fileName() == "." || fi->fileName() == ".." )
+ {
+ ++it;
+ continue;
+ }
+
+ if ( fi->isDir() )
+ {
+ if (deldir( fi->absFilePath() ) == false)
+ return false;
+ if (dir.rmdir( fi->absFilePath() ) == false)
+ return false;
+ }
+ else
+ if ( fi->isFile() )
+ if (dir.remove(fi->absFilePath() ) == false)
+ return false;
+
+ ++it;
+ }
+
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// Source code from Koffice 1.3
+
+QString CDArchiving::EscapeSgmlText(const QTextCodec* codec,
+ const QString& strIn,
+ const bool quot /* = false */ ,
+ const bool apos /* = false */ )
+{
+ QString strReturn;
+ QChar ch;
+
+ for (uint i = 0 ; i < strIn.length() ; ++i)
+ {
+ ch=strIn[i];
+ switch (ch.unicode())
+ {
+ case 38: // &
+ {
+ strReturn += "&amp;";
+ break;
+ }
+ case 60: // <
+ {
+ strReturn += "&lt;";
+ break;
+ }
+ case 62: // >
+ {
+ strReturn += "&gt;";
+ break;
+ }
+ case 34: // "
+ {
+ if (quot)
+ strReturn += "&quot;";
+ else
+ strReturn += ch;
+ break;
+ }
+ case 39: // '
+ {
+ // NOTE: HTML does not define &apos; by default (only XML/XHTML does)
+ if (apos)
+ strReturn += "&apos;";
+ else
+ strReturn += ch;
+ break;
+ }
+ default:
+ {
+ // verify that the character ch can be expressed in the
+ // encoding in which we will write the HTML file.
+ if (codec)
+ {
+ if (!codec->canEncode(ch))
+ {
+ strReturn += QString("&#%1;").arg(ch.unicode());
+ break;
+ }
+ }
+ strReturn += ch;
+ break;
+ }
+ }
+ }
+
+ return strReturn;
+}
+
+
+/**
+ * Produce a web-friendly file name
+ */
+
+QString CDArchiving::webifyFileName(QString fileName)
+{
+ fileName=fileName.lower();
+
+ // Remove potentially troublesome chars
+ fileName=fileName.replace(QRegExp("[^-0-9a-zA-Z]+"), "_");
+
+ return fileName;
+}
+
+/**
+ * Make sure a file name is unique in list
+ */
+QString CDArchiving::makeFileNameUnique(QStringList& list, QString fileName)
+{
+ // Make sure the file name is unique
+ QString fileNameBase=fileName;
+ int count=1;
+ while (list.findIndex(fileName)!=-1)
+ {
+ fileName=fileNameBase + "-" + QString::number(count);
+ ++count;
+ };
+
+ list += fileName;
+
+ return fileName;
+}
+
+
+} // NameSpace KIPICDArchivingPlugin
+
+#include "cdarchiving.moc"
diff --git a/kipi-plugins/cdarchiving/cdarchiving.h b/kipi-plugins/cdarchiving/cdarchiving.h
new file mode 100644
index 0000000..d87bb9d
--- /dev/null
+++ b/kipi-plugins/cdarchiving/cdarchiving.h
@@ -0,0 +1,220 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// CDARCHIVING.H
+//
+// Copyright (C) 2003-2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2003-2004 by Gregory Kokanosky <gregory dot kokanosky at free.fr>
+// for images navigation mode.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CDARCHIVING_H
+#define CDARCHIVING_H
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// Qt includes
+
+#include <qcolor.h>
+#include <qdatetime.h>
+#include <qdir.h>
+#include <qobject.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+// KDE includes
+
+#include <kaction.h>
+#include <kurl.h>
+
+// KIPI includes
+
+#include <libkipi/imagecollection.h>
+#include <libkipi/interface.h>
+
+class KProcess;
+
+namespace KIPICDArchivingPlugin
+{
+
+class CDArchivingDialog;
+
+const int NAV_THUMB_MAX_SIZE = 64;
+
+// First field is the URL, represented with KURL::prettyURL. We can't use KURL
+// directly because operator<(KURL,KURL) is not defined in KDE 3.1
+
+class CDArchiving : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ CDArchiving( KIPI::Interface* interface, QObject *parent=0,
+ KAction *action_cdarchiving=0 );
+ ~CDArchiving();
+
+ bool prepare(void);
+ bool showDialog();
+
+ void invokeK3b();
+ void removeTmpFiles(void);
+
+ void run(void);
+ void stop(void);
+
+
+public slots:
+
+ void slotK3bDone(KProcess*);
+ void slotK3bStartBurningProcess(void);
+
+private:
+
+ CDArchivingDialog *m_configDlg;
+
+ KAction *m_actionCDArchiving;
+
+ KIPI::Interface *m_interface;
+
+ KProcess *m_Proc;
+
+ KURL m_albumUrl; // Current album Url use in the thread.
+ KURL::List m_albumUrlList; // Urls of Albums list from setup dialog.
+
+ QColor m_backgroundColor;
+ QColor m_bordersImagesColor;
+ QColor m_foregroundColor;
+
+ QObject *m_parent;
+
+ QString m_AlbumCollection;
+ QString m_AlbumComments;
+ QString m_AlbumDate;
+ QString m_AlbumTitle;
+ QString m_HTMLInterfaceAutoRunFolder;
+ QString m_HTMLInterfaceAutoRunInf;
+ QString m_HTMLInterfaceFolder;
+ QString m_HTMLInterfaceIndex;
+ QString m_K3bBinPathName;
+ QString m_K3bParameters;
+ QString m_StreamMainPageAlbumPreview;
+ QString m_applicationID;
+ QString m_bordersImagesSize;
+ QString m_fontName;
+ QString m_fontSize;
+ QString m_hostName;
+ QString m_hostURL;
+ QString m_imageFormat;
+ QString m_imagesFileFilter;
+ QString m_mainTitle;
+ QString m_mediaFormat;
+ QString m_preparer;
+ QString m_publisher;
+ QString m_systemID;
+ QString m_tmpFolder;
+ QString m_volumeID;
+ QString m_volumeSetID;
+
+ QStringList m_collection_name_list;
+
+ QValueList<KIPI::ImageCollection> m_albumsList;
+
+ bool m_cancelled;
+ bool m_copyFiles;
+ bool m_useAutoRunWin32;
+ bool m_useCheckCD;
+ bool m_useHTMLInterface;
+ bool m_useOnTheFly;
+ bool m_useStartBurningProcess;
+
+ int m_albumListSize;
+ int m_imagesPerRow;
+ int m_imgHeight;
+ int m_imgWidth;
+ int m_targetImgHeight;
+ int m_targetImgWidth;
+ int m_thumbnailsSize;
+
+ pid_t m_k3bPid;
+
+private:
+
+ bool buildHTMLInterface (void);
+
+ bool createDirectory(QDir thumb_dir, QString imgGalleryDir, QString dirName);
+
+ void createHead(QTextStream& stream);
+ void createCSSSection(QTextStream& stream);
+
+ void createBody(QTextStream& stream,
+ const KIPI::ImageCollection& album,
+ const KURL& targetURL,
+ const QString& imageFormat);
+
+ int createThumb( const QString& imgName, const QString& sourceDirName, const QString& uniqueFileName,
+ const QString& imgGalleryDir, const QString& imageFormat);
+
+ int ResizeImage( const QString Path, const QString Directory, const QString ImageFormat,
+ const QString ImageNameFormat, int *Width, int *Height, int SizeFactor,
+ bool ColorDepthChange, int ColorDepthValue, bool CompressionSet, int ImageCompression);
+
+ bool createHtml( const KIPI::ImageCollection& album,
+ const KURL& targetURL,
+ const QString& imageFormat );
+
+ bool createPage(const QString& imgGalleryDir,
+ const KURL& imgURL,
+ const QString& uniqueImgName,
+ const KURL& prevImgURL,
+ const QString& prevUniqueImgName,
+ const KURL& nextImgURL,
+ const QString& nextUniqueImgName,
+ const QString& comment);
+
+ void createBodyMainPage(QTextStream& stream, KURL& url);
+
+ static QString extension(const QString& imageFormat);
+
+ bool BuildK3bXMLprojectfile (QString HTMLinterfaceFolder, QString IndexHtm,
+ QString AutoRunInf, QString AutorunFolder);
+
+ bool AddFolderTreeToK3bXMLProjectFile (QString dirname, QTextStream* stream);
+ bool addCollectionToK3bXMLProjectFile(const KIPI::ImageCollection& collection, QTextStream* stream);
+ bool CreateAutoRunInfFile(void);
+ bool DeleteDir(QString dirname);
+ bool deldir(QString dirname);
+
+ QString EscapeSgmlText(const QTextCodec* codec, const QString& strIn,
+ const bool quot = false, const bool apos = false );
+
+ void writeSettings(void);
+ void readSettings(void);
+
+ QString webifyFileName(QString fileName);
+ QString makeFileNameUnique(QStringList& list, QString fileName);
+
+};
+
+} // NameSpace KIPICDArchivingPlugin
+
+#endif // CDARCHIVING_H
diff --git a/kipi-plugins/cdarchiving/cdarchivingdialog.cpp b/kipi-plugins/cdarchiving/cdarchivingdialog.cpp
new file mode 100644
index 0000000..7a61cda
--- /dev/null
+++ b/kipi-plugins/cdarchiving/cdarchivingdialog.cpp
@@ -0,0 +1,902 @@
+/* ============================================================
+ * Author: Gilles Caulier <caulier dot gilles at gmail dot com>
+ * from digiKam project.
+ * Date : 2003-10-01
+ * Description : a kipi plugin to export image collections
+ * on CD/DVD.
+ *
+ * Copyright 2003-2005 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2003-2004 by Gregory Kokanosky
+ * <gregory dot kokanosky at free.fr>
+ * for HTML interface navigation mode
+ * Copyright 2005 by Owen Hirst <n8rider at sbcglobal.net>
+ * about bugfix.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Qt includes
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qfileinfo.h>
+#include <qgroupbox.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qprogressdialog.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+#include <qvbox.h>
+#include <qwhatsthis.h>
+
+// KDE includes
+
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kbuttonbox.h>
+#include <kcolorbutton.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdirsize.h>
+#include <kfontdialog.h>
+#include <kglobalsettings.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kpopupmenu.h>
+#include <ksqueezedtextlabel.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+#include <kurlrequester.h>
+
+// KIPI includes
+
+#include <libkipi/imagecollection.h>
+#include <libkipi/imagecollectionselector.h>
+#include <libkipi/imageinfo.h>
+
+// Local includes
+
+#include "cdarchivingdialog.h"
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+
+
+namespace KIPICDArchivingPlugin
+{
+
+KIO::filesize_t TargetMediaSize;
+
+CDArchivingDialog::CDArchivingDialog( KIPI::Interface* interface, QWidget *parent)
+ : KDialogBase( IconList, i18n("Configure Archive to CD"), Help|Ok|Cancel, Ok,
+ parent, "CDArchivingDialog", true, false ), m_interface( interface )
+{
+ setCaption(i18n("Create CD/DVD Archive"));
+ setupSelection();
+ setupLookPage();
+ setupCDInfos();
+ setupBurning();
+ page_setupSelection->setFocus();
+ resize(650, 450);
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("CD/DVD Archiving"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("An Album CD/DVD Archiving Kipi plugin.\n"
+ "This plugin use K3b CD/DVD burning software available at\n"
+ "http://www.k3b.org"),
+ "(c) 2003-2005, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author"),
+ "caulier dot gilles at gmail dot com");
+
+ m_about->addAuthor("Angelo Naselli", I18N_NOOP("Contributor"),
+ "anaselli at linux.it");
+
+ m_about->addAuthor("Gregory Kokanosky", I18N_NOOP("Image navigation mode patches"),
+ "gregory dot kokanosky at free.fr");
+
+ m_about->addAuthor("Owen Hirst", I18N_NOOP("Bugfix"),
+ "n8rider at sbcglobal.net");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+}
+
+CDArchivingDialog::~CDArchivingDialog()
+{
+ delete m_about;
+}
+
+void CDArchivingDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("cdarchiving", "kipi-plugins");
+}
+
+void CDArchivingDialog::setupSelection(void)
+{
+ page_setupSelection = addPage(i18n("Selection"), i18n("Album Selection"),
+ BarIcon("folder_image", KIcon::SizeMedium));
+
+ QVBoxLayout *layout = new QVBoxLayout(page_setupSelection, 0, spacingHint() );
+ m_imageCollectionSelector = new KIPI::ImageCollectionSelector(page_setupSelection, m_interface);
+ layout->addWidget(m_imageCollectionSelector);
+
+ //---------------------------------------------
+
+ QGroupBox * groupBox3 = new QGroupBox( 2, Qt::Horizontal,
+ i18n("Target Media Information"),
+ page_setupSelection );
+ groupBox3->layout()->setSpacing( 6 );
+ groupBox3->layout()->setMargin( 11 );
+ QWhatsThis::add( groupBox3, i18n("<p>Information about the backup medium.") );
+
+ m_mediaSize = new QLabel( groupBox3 );
+ m_mediaSize->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+
+ m_mediaFormat = new QComboBox(false, groupBox3);
+ m_mediaFormat->insertItem(i18n("CD (650Mb)"));
+ m_mediaFormat->insertItem(i18n("CD (700Mb)"));
+ m_mediaFormat->insertItem(i18n("CD (880Mb)"));
+ m_mediaFormat->insertItem(i18n("DVD (4,7Gb)"));
+ m_mediaFormat->setCurrentText (i18n("CD (650Mb)"));
+ mediaFormatActived(m_mediaFormat->currentText());
+ QWhatsThis::add( m_mediaFormat, i18n("<p>Select here the backup media format."));
+
+ layout->addWidget( groupBox3 );
+
+ //---------------------------------------------
+
+ connect( m_mediaFormat, SIGNAL( highlighted( const QString & ) ),
+ this, SLOT( mediaFormatActived( const QString & ) ) );
+
+ connect( m_imageCollectionSelector, SIGNAL( selectionChanged() ),
+ this, SLOT( slotAlbumSelected() ) );
+}
+
+void CDArchivingDialog::setupLookPage(void)
+{
+ QString whatsThis;
+ page_setupLook = addPage( i18n("HTML Interface"), i18n("HTML Interface Look"),
+ BarIcon("html", KIcon::SizeMedium ) );
+
+ QVBoxLayout *vlay = new QVBoxLayout( page_setupLook, 0, spacingHint() );
+
+ //---------------------------------------------
+
+ m_useHTMLInterface = new QCheckBox( i18n("Build CD HTML interface"), page_setupLook);
+ m_useHTMLInterface->setChecked( true );
+ vlay->addWidget( m_useHTMLInterface );
+ QWhatsThis::add( m_useHTMLInterface,
+ i18n("<p>This option adds a HTML interface to browse the CD's contents.") );
+
+ //---------------------------------------------
+
+ m_useAutoRunWin32 = new QCheckBox( i18n("Add \"autorun\" functionality"), page_setupLook);
+ m_useAutoRunWin32->setChecked( true );
+ vlay->addWidget( m_useAutoRunWin32 );
+ QWhatsThis::add( m_useAutoRunWin32,
+ i18n("<p>This option adds MS Windows(tm) autorunning capability to the CD.") );
+
+ //---------------------------------------------
+
+ m_labelTitle = new QLabel( i18n("Archive title:"), page_setupLook);
+ vlay->addWidget( m_labelTitle );
+
+ m_title = new QLineEdit(i18n("Album Archiving"), page_setupLook);
+ vlay->addWidget( m_title );
+ m_labelTitle->setBuddy(m_title);
+ QWhatsThis::add( m_title, i18n("<p>Enter here the title of the CD archive.") );
+
+ //---------------------------------------------
+
+ m_imagesPerRow = new KIntNumInput(4, page_setupLook);
+ m_imagesPerRow->setRange(1, 8, 1, true );
+ m_imagesPerRow->setLabel( i18n("I&mages per row:") );
+ QWhatsThis::add( m_imagesPerRow, i18n("<p>Enter here the number of images per row on the album page. "
+ "A good value is '4'.") );
+ vlay->addWidget( m_imagesPerRow );
+
+ QGridLayout *grid = new QGridLayout( 2, 2 );
+ vlay->addLayout( grid );
+
+ //---------------------------------------------
+
+ m_thumbnailsSize = new KIntNumInput(140, page_setupLook);
+ m_thumbnailsSize->setRange(10, 1000, 1, true );
+ m_thumbnailsSize->setLabel( i18n("Thumbnail size:") );
+ vlay->addWidget( m_thumbnailsSize );
+ QWhatsThis::add( m_thumbnailsSize, i18n("<p>The new size of thumbnails in pixels") );
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay3 = new QHBoxLayout( spacingHint() );
+ vlay->addLayout( hlay3 );
+ m_imageFormat = new QComboBox(false, page_setupLook);
+ m_imageFormat->insertItem("JPEG");
+ m_imageFormat->insertItem("PNG");
+ m_imageFormat->setCurrentText ("JPEG");
+ whatsThis = i18n("<p>Select here the image file format for thumbnails.<p>");
+ whatsThis = whatsThis + i18n("<b>JPEG</b>: The Joint Photographic Experts Group's file format is a "
+ "good Web file format but it uses lossy data compression.<p>"
+ "<b>PNG</b>: the Portable Network Graphics format is an extensible file format for "
+ "the lossless, portable, well-compressed storage of raster images. PNG provides a "
+ "patent-free replacement for GIF and can also replace many common uses of TIFF. "
+ "PNG is designed to work well in online viewing applications, such as the World "
+ "Wide Web, so it is fully streamable with a progressive display option. Also, "
+ "PNG can store gamma and chromaticity data for improved color matching on "
+ "heterogeneous platforms.");
+ QWhatsThis::add( m_imageFormat, whatsThis );
+
+ m_labelThumbsFileFormat = new QLabel( i18n("Thumbnail file format:"), page_setupLook);
+ hlay3->addWidget( m_labelThumbsFileFormat );
+ m_labelThumbsFileFormat->setBuddy( m_imageFormat );
+ hlay3->addStretch( 1 );
+ hlay3->addWidget( m_imageFormat );
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay11 = new QHBoxLayout( );
+ vlay->addLayout( hlay11 );
+
+ m_fontName = new QComboBox( false, page_setupLook );
+ QStringList standardFonts;
+ KFontChooser::getFontList(standardFonts, 0);
+ m_fontName->insertStringList( standardFonts );
+ m_fontName->setCurrentText( KGlobalSettings::generalFont().family());
+ QWhatsThis::add( m_fontName, i18n("<p>Select here the font name used for the pages.") );
+
+ m_labelFontName = new QLabel( i18n("Fon&t name:"), page_setupLook );
+ m_labelFontName->setBuddy( m_fontName );
+ hlay11->addWidget( m_labelFontName );
+ hlay11->addStretch( 1 );
+ hlay11->addWidget( m_fontName );
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay12 = new QHBoxLayout( );
+ vlay->addLayout( hlay12 );
+
+ m_fontSize = new QSpinBox( 6, 15, 1, page_setupLook );
+ m_fontSize->setValue( 14 );
+ QWhatsThis::add( m_fontSize, i18n("<p>Select here the font size used for the pages.") );
+
+ m_labelFontSize = new QLabel( i18n("Font si&ze:"), page_setupLook );
+ m_labelFontSize->setBuddy( m_fontSize );
+ hlay12->addWidget( m_labelFontSize );
+ hlay12->addStretch( 1 );
+ hlay12->addWidget( m_fontSize );
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay1 = new QHBoxLayout( spacingHint() );
+ vlay->addLayout( hlay1 );
+
+ m_foregroundColor = new KColorButton(page_setupLook);
+ m_foregroundColor->setColor(QColor("#d0ffd0"));
+ QWhatsThis::add( m_foregroundColor, i18n("<p>Select here the foreground color used for the pages.") );
+
+ m_labelForegroundColor = new QLabel( i18n("&Foreground color:"), page_setupLook);
+ m_labelForegroundColor->setBuddy( m_foregroundColor );
+ hlay1->addWidget( m_labelForegroundColor );
+ hlay1->addStretch( 1 );
+ hlay1->addWidget(m_foregroundColor);
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay2 = new QHBoxLayout( spacingHint() );
+ vlay->addLayout( hlay2 );
+
+ m_backgroundColor = new KColorButton(page_setupLook);
+ m_backgroundColor->setColor(QColor("#333333"));
+ QWhatsThis::add( m_backgroundColor, i18n("<p>Select here the background color used for the pages.") );
+
+ m_labelBackgroundColor = new QLabel( i18n("&Background color:"), page_setupLook);
+ hlay2->addWidget( m_labelBackgroundColor );
+ m_labelBackgroundColor->setBuddy( m_backgroundColor );
+ hlay2->addStretch( 1 );
+ hlay2->addWidget(m_backgroundColor);
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay13 = new QHBoxLayout( );
+ vlay->addLayout( hlay13 );
+
+ m_bordersImagesSize = new QSpinBox( 1, 20, 1, page_setupLook );
+ m_bordersImagesSize->setValue( 1 );
+ QWhatsThis::add( m_bordersImagesSize, i18n("<p>Select here the image border's size in pixels.") );
+
+ m_labelImageBorderSize = new QLabel( i18n("Image border s&ize:"), page_setupLook );
+ m_labelImageBorderSize->setBuddy( m_bordersImagesSize );
+ hlay13->addWidget( m_labelImageBorderSize );
+ hlay13->addStretch( 1 );
+ hlay13->addWidget( m_bordersImagesSize );
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay4 = new QHBoxLayout( spacingHint() );
+ vlay->addLayout( hlay4 );
+
+ m_bordersImagesColor = new KColorButton(page_setupLook);
+ m_bordersImagesColor->setColor(QColor("#d0ffd0"));
+ QWhatsThis::add( m_bordersImagesColor, i18n("<p>Select here the color used "
+ "for the image borders.") );
+
+ m_labelImageBorderSizeColor = new QLabel( i18n("Image bo&rder color:"), page_setupLook);
+ hlay4->addWidget( m_labelImageBorderSizeColor );
+ m_labelImageBorderSizeColor->setBuddy( m_bordersImagesColor );
+ hlay4->addStretch( 1 );
+ hlay4->addWidget(m_bordersImagesColor);
+
+ //---------------------------------------------
+
+ vlay->addStretch(1);
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_useAutoRunWin32, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_labelTitle, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_labelThumbsFileFormat, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_labelFontName, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_labelFontSize, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_labelForegroundColor, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_labelBackgroundColor, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_title, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_imagesPerRow, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_fontSize, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_fontName, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_imageFormat, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_thumbnailsSize, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_foregroundColor, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_backgroundColor, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_bordersImagesSize, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_labelImageBorderSize, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_bordersImagesColor, SLOT(setEnabled(bool)));
+
+ connect(m_useHTMLInterface, SIGNAL(toggled(bool)),
+ m_labelImageBorderSizeColor, SLOT(setEnabled(bool)));
+
+}
+
+void CDArchivingDialog::setupCDInfos(void)
+{
+ page_CDInfos = addPage( i18n("Volume Descriptor"), i18n("Media Volume Descriptor"),
+ BarIcon("cd", KIcon::SizeMedium ) );
+
+ QVBoxLayout *vlay = new QVBoxLayout( page_CDInfos, 0, spacingHint() );
+
+ QLabel *label;
+
+ //---------------------------------------------
+
+ label = new QLabel( i18n("Volume name:"), page_CDInfos);
+ vlay->addWidget( label );
+
+ m_volume_id = new QLineEdit(i18n("CD Album"), page_CDInfos);
+ vlay->addWidget( m_volume_id );
+ m_labelTitle->setBuddy(m_volume_id);
+ m_volume_id->setMaxLength(32);
+ QWhatsThis::add( m_volume_id, i18n("<p>Enter here the media volume name (32 characters max.)") );
+
+ //---------------------------------------------
+
+ label = new QLabel( i18n("Volume set name:"), page_CDInfos);
+ vlay->addWidget( label );
+
+ m_volume_set_id = new QLineEdit(i18n("Album CD archive"), page_CDInfos);
+ vlay->addWidget( m_volume_set_id );
+ m_labelTitle->setBuddy(m_volume_set_id);
+ m_volume_set_id->setMaxLength(128);
+ QWhatsThis::add( m_volume_set_id,
+ i18n("<p>Enter here the media volume global name (128 characters max.)") );
+
+ //---------------------------------------------
+
+ label = new QLabel( i18n("System:"), page_CDInfos);
+ vlay->addWidget( label );
+
+ m_system_id = new QLineEdit(i18n("LINUX"), page_CDInfos);
+ vlay->addWidget( m_system_id );
+ m_labelTitle->setBuddy(m_system_id);
+ m_system_id->setMaxLength(32);
+ QWhatsThis::add( m_system_id,
+ i18n("<p>Enter here the media burning system name (32 characters max.)") );
+
+ //---------------------------------------------
+
+ label = new QLabel( i18n("Application:"), page_CDInfos);
+ vlay->addWidget( label );
+
+ m_application_id = new QLineEdit(i18n("K3b CD-DVD Burning application"), page_CDInfos);
+ vlay->addWidget( m_application_id );
+ m_labelTitle->setBuddy(m_application_id);
+ m_application_id->setMaxLength(128);
+ QWhatsThis::add( m_application_id,
+ i18n("<p>Enter here the media burning application name (128 characters max.).") );
+
+
+ //---------------------------------------------
+
+ label = new QLabel( i18n("Publisher:"), page_CDInfos);
+ vlay->addWidget( label );
+
+ m_publisher = new QLineEdit(i18n("KIPI [KDE Images Program Interface]"), page_CDInfos);
+ vlay->addWidget( m_publisher );
+ m_labelTitle->setBuddy(m_publisher);
+ m_publisher->setMaxLength(128);
+ QWhatsThis::add( m_publisher,
+ i18n("<p>Enter here the media publisher name (128 characters max.).") );
+
+ //---------------------------------------------
+
+ label = new QLabel( i18n("Preparer:"), page_CDInfos);
+ vlay->addWidget( label );
+
+ m_preparer = new QLineEdit(i18n("KIPI CD Archiving plugin"), page_CDInfos);
+ vlay->addWidget( m_preparer );
+ m_labelTitle->setBuddy(m_preparer);
+ m_preparer->setMaxLength(128);
+ QWhatsThis::add( m_preparer, i18n("<p>Enter here the media preparer name (128 characters max.).") );
+
+ vlay->addStretch(1);
+}
+
+void CDArchivingDialog::setupBurning(void)
+{
+ page_burning = addPage( i18n("Media Burning"),
+ i18n("CD/DVD Burning Setup"),
+ BarIcon("cdwriter_unmount", KIcon::SizeMedium ) );
+
+ QVBoxLayout *vlay = new QVBoxLayout( page_burning, 0, spacingHint() );
+
+ QLabel *label;
+
+ //---------------------------------------------
+
+ label = new QLabel(i18n("&K3b binary path:"), page_burning);
+ vlay->addWidget( label );
+
+ m_K3bBinPath = new KURLRequester( "k3b", page_burning);
+ label->setBuddy( m_K3bBinPath );
+ vlay->addWidget(m_K3bBinPath);
+
+ connect( m_K3bBinPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(UrlChanged(const QString&)));
+
+ QWhatsThis::add( m_K3bBinPath, i18n("<p>The path name to the K3b binary program.") );
+
+ //---------------------------------------------
+
+ label = new QLabel( i18n("Application parameters:"), page_burning);
+ vlay->addWidget( label );
+
+ m_K3bParameters = new QLineEdit("--nofork", page_burning);
+ vlay->addWidget( m_K3bParameters );
+ m_labelTitle->setBuddy(m_K3bParameters);
+ m_K3bParameters->setMaxLength(128);
+ QWhatsThis::add( m_K3bParameters,
+ i18n("<p>Enter parameters which will be used when starting the "
+ "burning application. Newer versions of K3b might need "
+ "--nofork, older versions might not need it. "
+ "(128 characters max.).") );
+
+ //---------------------------------------------
+
+ QGroupBox * groupBoxAdvancedOptions = new QGroupBox( i18n("Advanced Burning Options"), page_burning );
+ groupBoxAdvancedOptions->setColumnLayout(0, Qt::Vertical );
+ groupBoxAdvancedOptions->layout()->setSpacing( 6 );
+ groupBoxAdvancedOptions->layout()->setMargin( 11 );
+
+ QVBoxLayout * groupBoxAOLayout = new QVBoxLayout( groupBoxAdvancedOptions->layout() );
+ groupBoxAOLayout->setAlignment( Qt::AlignTop );
+
+ m_burnOnTheFly = new QCheckBox( i18n("Media burning On-The-Fly"), groupBoxAdvancedOptions);
+ m_burnOnTheFly->setChecked( false );
+ QWhatsThis::add( m_burnOnTheFly, i18n("<p>This option uses the \"On-The-Fly\" "
+ "media burning capability; this does not use a media image.") );
+ groupBoxAOLayout->addWidget( m_burnOnTheFly );
+
+ m_checkCDBurn = new QCheckBox( i18n("Check media"), groupBoxAdvancedOptions);
+ m_checkCDBurn->setChecked( false );
+ QWhatsThis::add( m_checkCDBurn, i18n("<p>This option verifies the media after the burning process. "
+ "You must use K3b release >= 0.10.0") );
+ groupBoxAOLayout->addWidget( m_checkCDBurn );
+
+ m_startBurningProcess = new QCheckBox( i18n("Start burning process automatically"), groupBoxAdvancedOptions);
+ m_startBurningProcess->setChecked( false );
+ m_startBurningProcess->hide();
+ QWhatsThis::add( m_startBurningProcess, i18n("<p>This option start automatically the burning process "
+ "when K3b is loaded.") );
+ groupBoxAOLayout->addWidget( m_startBurningProcess );
+
+ vlay->addWidget( groupBoxAdvancedOptions );
+
+ vlay->addStretch(1);
+}
+
+void CDArchivingDialog::slotAlbumSelected()
+{
+ QValueList<KIPI::ImageCollection> ListAlbums(m_imageCollectionSelector->selectedImageCollections());
+ double size = 0;
+
+ for ( QValueList<KIPI::ImageCollection>::Iterator it = ListAlbums.begin(); it != ListAlbums.end(); ++it )
+ {
+ KURL::List images = (*it).images();
+
+ for ( KURL::List::Iterator urlIt = images.begin() ; urlIt != images.end() ; ++urlIt )
+ {
+ KIPI::ImageInfo info = m_interface->info( *urlIt );
+ size += info.size();
+ }
+ }
+
+ TargetMediaSize = (int)(size/1024.0);
+
+ ShowMediaCapacity();
+}
+
+
+void CDArchivingDialog::mediaFormatActived (const QString & item )
+{
+ QString Color;
+
+ if (item == i18n("CD (650Mb)"))
+ MaxMediaSize = 665600;
+
+ if (item == i18n("CD (700Mb)"))
+ MaxMediaSize = 716800;
+
+ if (item == i18n("CD (880Mb)"))
+ MaxMediaSize = 901120;
+
+ if (item == i18n("DVD (4,7Gb)"))
+ MaxMediaSize = 4928307;
+
+ ShowMediaCapacity();
+}
+
+void CDArchivingDialog::ShowMediaCapacity(void)
+{
+ QString Color = "<font color=\"blue\">";;
+
+ if (TargetMediaSize >= MaxMediaSize - (MaxMediaSize*0.1))
+ Color = "<font color=\"orange\">";
+
+ if (TargetMediaSize >= MaxMediaSize)
+ Color = "<font color=\"red\">";
+
+ m_mediaSize->setText( i18n("Total size: ") + Color +
+ i18n("<b>%1</b></font> / <b>%2</b>").arg(KIO::convertSizeFromKB(TargetMediaSize))
+ .arg(KIO::convertSizeFromKB (MaxMediaSize)) );
+}
+
+void CDArchivingDialog::slotOk()
+{
+ m_selectedAlbums = m_imageCollectionSelector->selectedImageCollections();
+
+ if (m_selectedAlbums.size() == 0)
+ {
+ KMessageBox::sorry(this, i18n("You must selected at least one Album to archive."));
+ return;
+ }
+
+ QFile fileK3b(getK3bBinPathName());
+
+ if ( !KStandardDirs::findExe( getK3bBinPathName() ))
+ {
+ KMessageBox::sorry(this, i18n("K3b binary path is not valid. Please check it."));
+ return;
+ }
+
+ if (TargetMediaSize >= MaxMediaSize)
+ {
+ KMessageBox::sorry(this, i18n("Target media size is too big. Please change your album selection."));
+ return;
+ }
+
+ accept();
+}
+
+void CDArchivingDialog::UrlChanged(const QString &url )
+{
+ enableButtonOK( !url.isEmpty());
+}
+
+QString CDArchivingDialog::getK3bBinPathName() const
+{
+ return m_K3bBinPath->url();
+}
+
+QString CDArchivingDialog::getK3bParameters() const
+{
+ return m_K3bParameters->text();
+}
+
+void CDArchivingDialog::setK3bBinPathName(const QString &Value)
+{
+ m_K3bBinPath->setURL( Value );
+}
+
+void CDArchivingDialog::setK3bParameters(const QString &Value)
+{
+ m_K3bParameters->setText( Value );
+}
+
+int CDArchivingDialog::getImagesPerRow() const
+{
+ return m_imagesPerRow->value();
+}
+
+void CDArchivingDialog::setImagesPerRow(int Value)
+{
+ m_imagesPerRow->setValue(Value);
+}
+
+int CDArchivingDialog::getThumbnailsSize() const
+{
+ return m_thumbnailsSize->value();
+}
+
+void CDArchivingDialog::setThumbnailsSize(int Value)
+{
+ m_thumbnailsSize->setValue( Value );
+}
+
+const QString CDArchivingDialog::getFontName() const
+{
+ return m_fontName->currentText();
+}
+
+void CDArchivingDialog::setFontName(QString Value)
+{
+ m_fontName->setCurrentText (Value);
+}
+
+const QString CDArchivingDialog::getFontSize() const
+{
+ return m_fontSize->text();
+}
+
+void CDArchivingDialog::setFontSize(int Value)
+{
+ m_fontSize->setValue( Value );
+}
+
+const QColor CDArchivingDialog::getBackgroundColor() const
+{
+ return m_backgroundColor->color();
+}
+
+void CDArchivingDialog::setBackgroundColor(QColor Value)
+{
+ m_backgroundColor->setColor( Value );
+}
+
+const QColor CDArchivingDialog::getForegroundColor() const
+{
+ return m_foregroundColor->color();
+}
+
+void CDArchivingDialog::setForegroundColor(QColor Value)
+{
+ m_foregroundColor->setColor( Value );
+}
+
+const QString CDArchivingDialog::getImageFormat() const
+{
+ return m_imageFormat->currentText();
+}
+
+void CDArchivingDialog::setImageFormat(QString Value)
+{
+ return m_imageFormat->setCurrentText( Value );
+}
+
+const QString CDArchivingDialog::getMainTitle() const
+{
+ return m_title->text();
+}
+
+void CDArchivingDialog::setMainTitle(QString Value)
+{
+ return m_title->setText( Value );
+}
+
+bool CDArchivingDialog::getUseHTMLInterface() const
+{
+ return m_useHTMLInterface->isChecked();
+}
+
+void CDArchivingDialog::setUseHTMLInterface(bool Value)
+{
+ m_useHTMLInterface->setChecked(Value);
+}
+
+bool CDArchivingDialog::getUseAutoRunWin32() const
+{
+ return m_useAutoRunWin32->isChecked();
+}
+
+void CDArchivingDialog::setUseAutoRunWin32(bool Value)
+{
+ m_useAutoRunWin32->setChecked(Value);
+}
+
+const QString CDArchivingDialog::getVolumeID() const
+{
+ return m_volume_id->text();
+}
+
+void CDArchivingDialog::setVolumeID(QString Value)
+{
+ return m_volume_id->setText( Value );
+}
+
+const QString CDArchivingDialog::getVolumeSetID() const
+{
+ return m_volume_set_id->text();
+}
+
+void CDArchivingDialog::setVolumeSetID(QString Value)
+{
+ return m_volume_set_id->setText( Value );
+}
+
+const QString CDArchivingDialog::getSystemID() const
+{
+ return m_system_id->text();
+}
+
+void CDArchivingDialog::setSystemID(QString Value)
+{
+ return m_system_id->setText( Value );
+}
+
+const QString CDArchivingDialog::getApplicationID() const
+{
+ return m_application_id->text();
+}
+
+void CDArchivingDialog::setApplicationID(QString Value)
+{
+ return m_application_id->setText( Value );
+}
+
+const QString CDArchivingDialog::getPublisher() const
+{
+ return m_publisher->text();
+}
+
+void CDArchivingDialog::setPublisher(QString Value)
+{
+ return m_publisher->setText( Value );
+}
+
+const QString CDArchivingDialog::getPreparer() const
+{
+ return m_preparer->text();
+}
+
+void CDArchivingDialog::setPreparer(QString Value)
+{
+ return m_preparer->setText( Value );
+}
+
+const QString CDArchivingDialog::getMediaFormat() const
+{
+ return m_mediaFormat->currentText();
+}
+
+void CDArchivingDialog::setMediaFormat(QString Value)
+{
+ return m_mediaFormat->setCurrentText( Value );
+}
+
+bool CDArchivingDialog::getUseOnTheFly() const
+{
+ return m_burnOnTheFly->isChecked();
+}
+
+void CDArchivingDialog::setUseUseOnTheFly(bool Value)
+{
+ m_burnOnTheFly->setChecked(Value);
+}
+
+bool CDArchivingDialog::getUseCheckCD() const
+{
+ return m_checkCDBurn->isChecked();
+}
+
+void CDArchivingDialog::setUseCheckCD(bool Value)
+{
+ m_checkCDBurn->setChecked(Value);
+}
+
+bool CDArchivingDialog::getUseStartBurningProcess() const
+{
+ return m_startBurningProcess->isChecked();
+}
+
+void CDArchivingDialog::setUseStartBurningProcess(bool Value)
+{
+ m_startBurningProcess->setChecked(Value);
+}
+
+const QColor CDArchivingDialog::getBordersImagesColor() const
+{
+ return m_bordersImagesColor->color();
+}
+
+void CDArchivingDialog::setBordersImagesColor(QColor Value)
+{
+ m_bordersImagesColor->setColor( Value );
+}
+
+const QString CDArchivingDialog::getBordersImagesSize() const
+{
+ return m_bordersImagesSize->text();
+}
+
+void CDArchivingDialog::setBordersImagesSize(int Value)
+{
+ m_bordersImagesSize->setValue( Value );
+}
+
+} // NameSpace KIPICDArchivingPlugin
+
+#include "cdarchivingdialog.moc"
diff --git a/kipi-plugins/cdarchiving/cdarchivingdialog.h b/kipi-plugins/cdarchiving/cdarchivingdialog.h
new file mode 100644
index 0000000..f29aefe
--- /dev/null
+++ b/kipi-plugins/cdarchiving/cdarchivingdialog.h
@@ -0,0 +1,249 @@
+/* ============================================================
+ * Author: Gilles Caulier <caulier dot gilles at gmail dot com>
+ * from digiKam project.
+ * Date : 2003-10-01
+ * Description : a kipi plugin to export image collections
+ * on CD/DVD.
+ *
+ * Copyright 2003-2005 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2003-2004 by Gregory Kokanosky
+ * <gregory dot kokanosky at free.fr>
+ * for HTML interface navigation mode
+ * Copyright 2005 by Owen Hirst <n8rider at sbcglobal.net>
+ * about bugfix.
+ *
+ * This program is free software; you can redistribute 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 CDARCHIVINGDIALOG_H
+#define CDARCHIVINGDIALOG_H
+
+// Qt includes
+
+#include <qguardedptr.h>
+
+// KDE includes
+
+#include <kdialogbase.h>
+#include <kio/global.h>
+
+// KIPI includes
+
+#include "kpaboutdata.h"
+#include <libkipi/interface.h>
+
+class KColorButton;
+class KFileItem;
+class KFilePreview;
+class KIntNumInput;
+class KListView;
+class KSqueezedTextLabel;
+class KURL;
+class KURLRequester;
+
+class QCheckBox;
+class QLineEdit;
+class QProgressDialog;
+class QPushButton;
+class QSpinBox;
+class QString;
+
+
+namespace KIPI
+{
+class ImageCollectionSelector;
+}
+
+namespace KIPICDArchivingPlugin
+{
+
+class CDArchivingDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ CDArchivingDialog( KIPI::Interface* interface, QWidget *parent=0);
+ ~CDArchivingDialog();
+
+ QString getK3bBinPathName() const;
+ QString getK3bParameters() const;
+
+ void setK3bBinPathName(const QString &Value);
+ void setK3bParameters(const QString &Value);
+
+ int getImagesPerRow() const;
+ void setImagesPerRow(int Value);
+
+ int getThumbnailsSize() const;
+ void setThumbnailsSize(int Value);
+
+ const QString getFontName() const;
+ void setFontName(QString Value);
+
+ const QString getFontSize() const;
+ void setFontSize(int Value);
+
+ const QString getBordersImagesSize() const;
+ void setBordersImagesSize(int Value);
+
+ const QColor getBackgroundColor() const;
+ void setBackgroundColor(QColor Value);
+
+ const QColor getForegroundColor() const;
+ void setForegroundColor(QColor Value);
+
+ const QColor getBordersImagesColor() const;
+ void setBordersImagesColor(QColor Value);
+
+ const QString getImageFormat() const;
+ void setImageFormat(QString Value);
+
+ const QString getMainTitle() const;
+ void setMainTitle(QString Value);
+
+ bool getUseHTMLInterface() const;
+ void setUseHTMLInterface(bool Value);
+
+ bool getUseAutoRunWin32() const;
+ void setUseAutoRunWin32(bool Value);
+
+ const QString getVolumeID() const;
+ void setVolumeID(QString Value);
+
+ const QString getVolumeSetID() const;
+ void setVolumeSetID(QString Value);
+
+ const QString getSystemID() const;
+ void setSystemID(QString Value);
+
+ const QString getApplicationID() const;
+ void setApplicationID(QString Value);
+
+ const QString getPublisher() const;
+ void setPublisher(QString Value);
+
+ const QString getPreparer() const;
+ void setPreparer(QString Value);
+
+ const QString getMediaFormat() const;
+ void setMediaFormat(QString Value);
+
+ bool getUseOnTheFly() const;
+ void setUseUseOnTheFly(bool Value);
+
+ bool getUseCheckCD() const;
+ void setUseCheckCD(bool Value);
+
+ bool getUseStartBurningProcess() const;
+ void setUseStartBurningProcess(bool Value);
+
+ QValueList<KIPI::ImageCollection> getSelectedAlbums() const
+ {
+ return m_selectedAlbums;
+ }
+
+ void ShowMediaCapacity(void);
+
+protected slots:
+
+ void slotHelp();
+ void slotAlbumSelected(void);
+ void mediaFormatActived( const QString& item );
+ void slotOk();
+ void UrlChanged(const QString &url );
+
+private:
+
+ KColorButton *m_backgroundColor;
+ KColorButton *m_bordersImagesColor;
+ KColorButton *m_foregroundColor;
+
+ KIO::filesize_t MaxMediaSize;
+
+ KIPI::ImageCollectionSelector *m_imageCollectionSelector;
+
+ KIPI::Interface *m_interface;
+
+ KIPIPlugins::KPAboutData *m_about;
+
+ KIntNumInput *m_imagesPerRow;
+ KIntNumInput *m_thumbnailsSize;
+
+ KListView *m_AlbumsList;
+
+ KSqueezedTextLabel *m_AlbumCollection;
+ KSqueezedTextLabel *m_AlbumComments;
+ KSqueezedTextLabel *m_AlbumDate;
+ KSqueezedTextLabel *m_AlbumItems;
+ KSqueezedTextLabel *m_AlbumSize;
+
+ KURLRequester *m_K3bBinPath;
+
+ QCheckBox *m_burnOnTheFly;
+ QCheckBox *m_checkCDBurn;
+ QCheckBox *m_startBurningProcess;
+ QCheckBox *m_useAutoRunWin32;
+ QCheckBox *m_useHTMLInterface;
+ QComboBox *m_fontName;
+ QComboBox *m_imageFormat;
+ QComboBox *m_mediaFormat;
+
+ QFrame *page_CDInfos;
+ QFrame *page_burning;
+ QFrame *page_setupLook;
+ QFrame *page_setupSelection;
+
+ QLabel *m_albumPreview;
+ QLabel *m_labelBackgroundColor;
+ QLabel *m_labelFontName;
+ QLabel *m_labelFontSize;
+ QLabel *m_labelForegroundColor;
+ QLabel *m_labelImageBorderSize;
+ QLabel *m_labelImageBorderSizeColor;
+ QLabel *m_labelThumbsFileFormat;
+ QLabel *m_labelTitle;
+ QLabel *m_mediaSize;
+
+ QLineEdit *m_K3bParameters;
+ QLineEdit *m_application_id;
+ QLineEdit *m_preparer;
+ QLineEdit *m_publisher;
+ QLineEdit *m_system_id;
+ QLineEdit *m_title;
+ QLineEdit *m_volume_id;
+ QLineEdit *m_volume_set_id;
+
+ QProgressDialog *m_progressDlg;
+
+ QPushButton *m_helpButton;
+
+ QSpinBox *m_bordersImagesSize;
+ QSpinBox *m_fontSize;
+
+ QString m_ImagesFilesSort;
+ QString m_TempFolder;
+
+ QValueList<KIPI::ImageCollection> m_selectedAlbums;
+
+private:
+
+ void setupBurning(void);
+ void setupCDInfos(void);
+ void setupLookPage(void);
+ void setupSelection(void);
+};
+
+} // NameSpace KIPICDArchivingPlugin
+
+#endif /* CDARCHIVINGDIALOG_H */
diff --git a/kipi-plugins/cdarchiving/gohome.png b/kipi-plugins/cdarchiving/gohome.png
new file mode 100644
index 0000000..acf3e4a
--- /dev/null
+++ b/kipi-plugins/cdarchiving/gohome.png
Binary files differ
diff --git a/kipi-plugins/cdarchiving/image_broken.png b/kipi-plugins/cdarchiving/image_broken.png
new file mode 100644
index 0000000..5f525f8
--- /dev/null
+++ b/kipi-plugins/cdarchiving/image_broken.png
Binary files differ
diff --git a/kipi-plugins/cdarchiving/kipiplugin_cdarchiving.desktop b/kipi-plugins/cdarchiving/kipiplugin_cdarchiving.desktop
new file mode 100644
index 0000000..c9d66e0
--- /dev/null
+++ b/kipi-plugins/cdarchiving/kipiplugin_cdarchiving.desktop
@@ -0,0 +1,57 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=CDArchiving
+Name[ca]=Arxivat de CD
+Name[cs]=Archivace na CD
+Name[da]=Cd-arkivering
+Name[de]=Archivierung auf CD
+Name[el]=ΑρχειοθέτησηCD
+Name[es]=Archivador en CD
+Name[et]=CD-le arhiveerimine
+Name[fi]=CD-arkistointi
+Name[gl]=Arquivado en CD
+Name[it]=ArchiviazioneSuCD
+Name[nds]=CD-Archiveren
+Name[nl]=CD-archievering
+Name[pa]=CD ਭੰਡਾਰ
+Name[pl]=Archiwizacja na CD
+Name[pt]=Arquivo em CD
+Name[sr]=CD Архивирање
+Name[sr@Latn]=CD Arhiviranje
+Name[sv]=Cd-arkivering
+Name[tg]=БойгонииCD
+Name[tr]=CDArşivleme
+Name[xx]=xxCDArchivingxx
+Name[zh_CN]=CD 存档
+Comment=KIPI Albums CD and DVD Archiving Plugin
+Comment[ca]=Connector del KIPI per arxivar àlbums en CD i DVD
+Comment[cs]=KIPI modul archivace alb na CD a DVD
+Comment[da]=KIPI-plugin: Arkivering af albummer på cd eller dvd
+Comment[de]=Ein KIPI-Modul zum Archivieren von Bilderalben auf CD und DVD
+Comment[el]=Πρόσθετο αρχειοθέτησης άλμπουμ CD και DVD του KIPI
+Comment[es]=Complemento de KIPI para archivar álbumes en CD y DVD
+Comment[et]=KIPI albumite CD-le ja DVD-le arhiveerimise plugin
+Comment[fi]=Kipi-liitännäinen cd/dvd-levyille arkistointiin
+Comment[fr]=Module externe KIPI pour archiver des albums sur CD/DVD
+Comment[gl]=Plugin de Arquivado de Albuns en CD e DVD de KIPI
+Comment[is]=KIPI íforrit til gera CD og DVD diska
+Comment[it]=Plugin di archiviazione degli album su CD e DVD di KIPI
+Comment[ja]=Kipi アルバム CD/DVD アーカイブプラグイン
+Comment[nds]=KIPI-Moduul för't Archiveren op CD un DVD
+Comment[nl]=KIPI-plugin voor het maken van een cd/dvd-archief
+Comment[pa]=KIPI ਐਲਬਮ CD ਅਤੇ DVD ਪੁਰਾਲੇਖ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Archiwizacja albumów na CD i DVD
+Comment[pt]='Plugin' de Arquivo em CD e DVD de Álbuns do KIPI
+Comment[pt_BR]=Plugin para Arquivamento de Álbuns de CD e DVD do KIPI
+Comment[sr]=KIPI прикључак за архивирање албума на CD и DVD
+Comment[sr@Latn]=KIPI priključak za arhiviranje albuma na CD i DVD
+Comment[sv]=KIPI-insticksprogram: Arkivering av album på cd eller dvd
+Comment[tg]=Модули бойгонии албомҳои CD ва DVD
+Comment[tr]=KIPI Albümler CD ve DVD Arşivleme Eklentisi
+Comment[xx]=xxKIPI Albums CD and DVD Archiving Pluginxx
+Comment[zh_CN]=KIPI 相册 CD 和 DVD 存档插件
+Icon=
+ServiceTypes=KIPI/Plugin
+Type=Service
+X-KDE-Library=kipiplugin_cdarchiving
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/kipi-plugins/cdarchiving/plugin_cdarchiving.cpp b/kipi-plugins/cdarchiving/plugin_cdarchiving.cpp
new file mode 100644
index 0000000..90f0452
--- /dev/null
+++ b/kipi-plugins/cdarchiving/plugin_cdarchiving.cpp
@@ -0,0 +1,350 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// PLUGIN_CDARCHIVING.CPP
+//
+// Copyright (C) 2003-2004 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// KDE includes
+
+#include <kaction.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <kgenericfactory.h>
+#include <kinstance.h>
+#include <klibloader.h>
+#include <klocale.h>
+
+// LibKipi includes
+
+#include <libkipi/batchprogressdialog.h>
+
+// Local includes
+
+#include "actions.h"
+#include "cdarchiving.h"
+#include "plugin_cdarchiving.h"
+
+typedef KGenericFactory<Plugin_CDArchiving> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_cdarchiving,
+ Factory("kipiplugin_cdarchiving"))
+
+// -----------------------------------------------------------
+Plugin_CDArchiving::Plugin_CDArchiving(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "CDArchiving")
+{
+ kdDebug( 51001 ) << "Plugin_CDArchiving plugin loaded" << endl;
+}
+
+void Plugin_CDArchiving::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_action_cdarchiving = new KAction (i18n("Archive to CD/DVD..."), // Menu message.
+ "cd", // Menu icon.
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "cd_archiving");
+
+ addAction( m_action_cdarchiving );
+ m_cdarchiving = 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Plugin_CDArchiving::~Plugin_CDArchiving()
+{
+ // No need to delete m_cdarchiving as its a QObject child of this
+ // and will be deleted automatically
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_CDArchiving::slotActivate()
+{
+ m_progressDlg = 0;
+
+ KIPI::Interface* interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ m_cdarchiving = new KIPICDArchivingPlugin::CDArchiving(
+ interface,
+ this, m_action_cdarchiving);
+
+ if ( m_cdarchiving->showDialog() )
+ {
+ m_cdarchiving->prepare();
+ m_cdarchiving->run();
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_CDArchiving::slotCancel()
+{
+ m_cdarchiving->stop();
+ m_cdarchiving->removeTmpFiles();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_CDArchiving::customEvent(QCustomEvent *event)
+{
+ if (!event) return;
+
+ if (!m_progressDlg)
+ {
+ m_progressDlg = new KIPI::BatchProgressDialog(kapp->activeWindow(), i18n("Archive to CD/DVD"));
+
+ connect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+
+ m_current = 0;
+ m_progressDlg->show();
+ }
+
+ KIPICDArchivingPlugin::EventData *d = (KIPICDArchivingPlugin::EventData*) event->data();
+
+ if (!d) return;
+
+ if (d->starting)
+ {
+ QString text;
+
+ switch (d->action)
+ {
+ case(KIPICDArchivingPlugin::Initialize):
+ {
+ text = i18n("Initialising...");
+ m_total = d->total;
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildHTMLiface):
+ {
+ text = i18n("Making main HTML interface...");
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildAlbumHTMLPage):
+ {
+ text = i18n("Making HTML pages for Album '%1'...").arg(d->albumName);
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildAutoRuniface):
+ {
+ text = i18n("Making AutoRun interface...");
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::ResizeImages):
+ {
+ text = i18n("Creating thumbnail for '%1'...").arg(d->fileName);
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildK3bProject):
+ {
+ text = i18n("Making K3b project...");
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::Progress):
+ {
+ text = d->message;
+ break;
+ }
+
+ default:
+ {
+ kdWarning( 51000 ) << "Plugin_CDArchiving: Unknown 'Starting' event: " << d->action << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::StartingMessage);
+ }
+ else
+ {
+ QString text;
+
+ if (d->success)
+ {
+ switch (d->action)
+ {
+ case(KIPICDArchivingPlugin::BuildHTMLiface):
+ {
+ ++m_current;
+ text = i18n("Main HTML interface creation completed.");
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildAlbumHTMLPage):
+ {
+ ++m_current;
+ text = i18n("HTML page creation for Album '%1' completed.").arg(d->albumName);
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::ResizeImages):
+ {
+ ++m_current;
+ text = i18n("Creating thumbnail for '%1' done.").arg(d->fileName);
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildAutoRuniface):
+ {
+ ++m_current;
+ text = i18n("AutoRun interface creation completed.");
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildK3bProject):
+ {
+ ++m_current;
+ text = i18n("K3b project creation completed.");
+ break;
+ }
+
+ default:
+ {
+ kdWarning( 51000 ) << "Plugin_CDArchiving: Unknown 'Success' event: " << d->action << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::SuccessMessage);
+ }
+ else
+ {
+ switch (d->action)
+ {
+ case(KIPICDArchivingPlugin::ResizeImages):
+ {
+ text = i18n("Failed to create thumbnail for '%1'").arg(d->fileName);
+ m_progressDlg->addedAction(text, KIPI::WarningMessage);
+ m_progressDlg->setProgress(m_current, m_total);
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildHTMLiface):
+ {
+ ++m_current;
+ text = i18n("Failed to create HTML interface: %1")
+ .arg(d->message);
+ m_progressDlg->addedAction(text, KIPI::ErrorMessage);
+ m_progressDlg->setProgress(m_current, m_total);
+ slotCancel();
+ return;
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildAlbumHTMLPage):
+ {
+ text = i18n("Failed to create HTML pages for Album '%1'")
+ .arg(d->albumName);
+ m_progressDlg->addedAction(text, KIPI::ErrorMessage);
+ m_progressDlg->setProgress(m_current, m_total);
+ slotCancel();
+ return;
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::BuildK3bProject):
+ {
+ ++m_current;
+ text = i18n("Failed to create K3b project.");
+ m_progressDlg->addedAction(text, KIPI::ErrorMessage);
+ m_progressDlg->setProgress(m_current, m_total);
+ slotCancel();
+ return;
+ break;
+ }
+
+ case(KIPICDArchivingPlugin::Error):
+ {
+ text = d->message;
+ m_progressDlg->addedAction(text, KIPI::ErrorMessage);
+ m_progressDlg->setProgress(m_current, m_total);
+ slotCancel();
+ return;
+ break;
+ }
+
+ default:
+ {
+ kdWarning( 51000 ) << "Plugin_CDArchiving: Unknown 'Failed' event: " << d->action << endl;
+ }
+ }
+ }
+
+ m_progressDlg->setProgress(m_current, m_total);
+
+ if ( d->action == KIPICDArchivingPlugin::BuildK3bProject )
+ {
+ m_current = 0;
+
+#if KDE_VERSION >= 0x30200
+ m_progressDlg->setButtonCancel( KStdGuiItem::close() );
+#else
+ m_progressDlg->setButtonCancelText( i18n("&Close") );
+#endif
+
+ disconnect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+
+ // Invoke K3b program.
+
+ m_progressDlg->addedAction(i18n("Starting K3b program..."),
+ KIPI::StartingMessage);
+ m_cdarchiving->invokeK3b();
+ }
+ }
+
+ kapp->processEvents();
+ delete d;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KIPI::Category Plugin_CDArchiving::category( KAction* action ) const
+{
+ if ( action == m_action_cdarchiving )
+ return KIPI::EXPORTPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::EXPORTPLUGIN; // no warning from compiler, please
+}
+
+
+#include "plugin_cdarchiving.moc"
diff --git a/kipi-plugins/cdarchiving/plugin_cdarchiving.h b/kipi-plugins/cdarchiving/plugin_cdarchiving.h
new file mode 100644
index 0000000..f5c1a00
--- /dev/null
+++ b/kipi-plugins/cdarchiving/plugin_cdarchiving.h
@@ -0,0 +1,72 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// PLUGIN_CDARCHIVING.H
+//
+// Copyright (C) 2003-2004 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef PLUGIN_CDARCHIVING_H
+#define PLUGIN_CDARCHIVING_H
+
+// LibKIPI includes.
+
+#include <libkipi/plugin.h>
+
+class QCustomEvent;
+
+class KAction;
+
+namespace KIPI
+{
+class BatchProgressDialog;
+}
+
+namespace KIPICDArchivingPlugin
+{
+class CDArchiving;
+class BatchProgressDialog;
+}
+
+class Plugin_CDArchiving : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+ Plugin_CDArchiving(QObject *parent, const char* name, const QStringList &args);
+ virtual ~Plugin_CDArchiving();
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+public slots:
+ void slotActivate();
+ void slotCancel();
+
+private:
+ int m_current;
+ int m_total;
+
+ KIPI::BatchProgressDialog *m_progressDlg;
+
+ KIPICDArchivingPlugin::CDArchiving *m_cdarchiving;
+ KAction *m_action_cdarchiving;
+
+ void customEvent(QCustomEvent *event);
+};
+
+
+#endif /* PLUGIN_CDARCHIVING_H */
diff --git a/kipi-plugins/cdarchiving/up.png b/kipi-plugins/cdarchiving/up.png
new file mode 100644
index 0000000..89f77e6
--- /dev/null
+++ b/kipi-plugins/cdarchiving/up.png
Binary files differ
diff --git a/kipi-plugins/cdarchiving/valid-html401.png b/kipi-plugins/cdarchiving/valid-html401.png
new file mode 100644
index 0000000..3855210
--- /dev/null
+++ b/kipi-plugins/cdarchiving/valid-html401.png
Binary files differ
diff --git a/kipi-plugins/common/Makefile.am b/kipi-plugins/common/Makefile.am
new file mode 100644
index 0000000..74c13d5
--- /dev/null
+++ b/kipi-plugins/common/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = libkipiplugins
+
diff --git a/kipi-plugins/common/include/kpaboutdata.h b/kipi-plugins/common/include/kpaboutdata.h
new file mode 100644
index 0000000..89f986f
--- /dev/null
+++ b/kipi-plugins/common/include/kpaboutdata.h
@@ -0,0 +1,51 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// KPABOUTDATA.H
+//
+// Copyright (C) 2006 Angelo Naselli <anaselli at linux dot it>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef __KIPI_ABOUT_DATA__
+#define __KIPI_ABOUT_DATA__
+
+#include <kaboutdata.h>
+
+#include <libkipi/libkipi_export.h>
+
+namespace KIPIPlugins
+{
+
+ class LIBKIPI_EXPORT KPAboutData : public KAboutData
+ {
+ private:
+ QString KipiPluginsVersionString;
+
+ public:
+
+ KPAboutData(const char *pluginName,
+ const char *pluginVersion=0,
+ int licenseType=License_Unknown,
+ const char *pluginDescription=0,
+ const char *copyrightStatement="Copyright 2003-2007, kipi-plugins team");
+
+ };
+
+} // namespace KIPIPlugins
+
+#endif //__KIPI_ABOUT_DATA__
+
diff --git a/kipi-plugins/common/include/pluginsversion.h b/kipi-plugins/common/include/pluginsversion.h
new file mode 100644
index 0000000..5d4162c
--- /dev/null
+++ b/kipi-plugins/common/include/pluginsversion.h
@@ -0,0 +1,27 @@
+/* ============================================================
+ * Authors: Gilles Caulier <caulier dot gilles at free.fr>
+ * Date : 2006-14-09
+ * Description : Kipi-Plugins release ID header.
+ *
+ * Copyright 2006-2008 by Gilles Caulier <caulier dot gilles at free.fr>
+ *
+ * This program is free software; you can redistribute 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 KIPIPLUGINS_VERSION_H
+#define KIPIPLUGINS_VERSION_H
+
+static const char kipiplugins_version[] = "0.1.6";
+
+#endif // KIPIPLUGINS_VERSION_H
+
diff --git a/kipi-plugins/common/libkipiplugins/Makefile.am b/kipi-plugins/common/libkipiplugins/Makefile.am
new file mode 100644
index 0000000..718c336
--- /dev/null
+++ b/kipi-plugins/common/libkipiplugins/Makefile.am
@@ -0,0 +1,14 @@
+METASOURCES = AUTO
+
+KDE_CXXFLAGS = $(USE_EXCEPTIONS)
+
+lib_LTLIBRARIES = libkipiplugins.la
+
+libkipiplugins_la_SOURCES = kpaboutdata.cpp
+
+libkipiplugins_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -version-info 0:1:0 -no-undefined
+
+libkipiplugins_la_LIBADD = $(LIB_KDECORE) $(LIB_QT)
+
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(all_includes)
+
diff --git a/kipi-plugins/common/libkipiplugins/kpaboutdata.cpp b/kipi-plugins/common/libkipiplugins/kpaboutdata.cpp
new file mode 100644
index 0000000..dad65dc
--- /dev/null
+++ b/kipi-plugins/common/libkipiplugins/kpaboutdata.cpp
@@ -0,0 +1,69 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// KPABOUTDATA.CPP
+//
+// Copyright (C) 2006 Angelo Naselli <anaselli at linux dot it>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <qglobal.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <kdeversion.h>
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "kdebug.h"
+
+namespace KIPIPlugins
+{
+
+ KPAboutData::KPAboutData(const char *pluginName,
+ const char *pluginVersion,
+ int licenseType,
+ const char *pluginDescription,
+ const char *copyrightStatement) : KAboutData ("kipi-plugins", pluginName,
+ pluginVersion,
+ 0, licenseType,
+ copyrightStatement,
+ pluginDescription,
+ "http://www.kipi-plugins.org")
+ {
+#if KDE_IS_VERSION(3,4,0)
+ // setProgramLogo is defined from kde 3.4.0 on
+ QString directory;
+ KGlobal::dirs()->addResourceType("kipi_plugins_logo", KGlobal::dirs()->kde_default("data") + "kipi/data");
+ directory = KGlobal::dirs()->findResourceDir("kipi_plugins_logo", "kipi-plugins_logo.png");
+
+ // set the kipiplugins logo inside the about dialog
+ setProgramLogo(QImage(directory + "kipi-plugins_logo.png"));
+#endif
+ // set the plugin description into long text description
+ setOtherText(pluginDescription);
+
+ // put the plugin name and version with kipi-plugins and kipi-plugins version
+ KipiPluginsVersionString = QString(pluginName) + " " + QString(pluginVersion) +
+ " - Kipi-plugins " + QString(kipiplugins_version) ;
+
+ kdDebug( 51001 ) << "Kipi-plugins - " << KipiPluginsVersionString.ascii() << endl;
+
+ // and set the string into the short description
+ setShortDescription(KipiPluginsVersionString.ascii());
+ }
+
+}
diff --git a/kipi-plugins/configure.in.bot b/kipi-plugins/configure.in.bot
new file mode 100644
index 0000000..f559da8
--- /dev/null
+++ b/kipi-plugins/configure.in.bot
@@ -0,0 +1,158 @@
+dnl Put here things to be done at the very end - telling users
+dnl about additional packages to install.
+
+echo ""
+echo "-- Kipi-Plugins configure results -------------------"
+
+# mandatory dependencies
+
+if test "x$have_libkipi" != "xyes"; then
+ echo "-- libkipi found.................. NO"
+ echo ""
+ echo "Kipi-Plugins needs libkipi >= 0.1.5. You need to install libkipi first"
+ echo "libkipi website is at http://www.kipi-plugins.org"
+ echo ""
+ all_tests=bad
+else
+ echo "-- libkipi found.................. YES"
+fi
+
+if test "x$have_libkexiv2" != "xyes"; then
+ echo "-- libkexiv2 library found........ NO"
+ echo ""
+ echo "Kipi-Plugins needs libkexiv2 library >= 0.1.5. You need to install libkexiv2 first"
+ echo "libkexiv2 website is at http://www.kipi-plugins.org"
+ echo ""
+ all_tests=bad
+else
+ echo "-- libkexiv2 library found........ YES"
+fi
+
+if test "x$have_libkdcraw" != "xyes"; then
+ echo "-- libkdcraw library found........ NO"
+ echo ""
+ echo "Kipi-Plugins needs libkdcraw library >= 0.1.4. You need to install libkdcraw first"
+ echo "libkdcraw website is at http://www.kipi-plugins.org"
+ echo ""
+ all_tests=bad
+else
+ echo "-- libkdcraw library found........ YES"
+fi
+
+# optional dependencies
+
+if test "x$build_gphoto" != "xno"; then
+ if test "x$have_gphoto" != "xyes"; then
+ echo "-- gphoto2 found.................. NO"
+ echo ""
+ echo "KameraKlient plugin needs gPhoto2. This plugin will not be compiled!"
+ echo "To complile this plugins, please install gPhoto2, e.g. from"
+ echo "http://www.gphoto.org/download.html"
+ echo ""
+ all_tests=bad
+ else
+ echo "-- gphoto2 found.................. YES"
+ fi
+else
+ echo "-- gphoto2................. NOT NEEDED"
+fi
+
+if test "x$build_tiff" != "xno"; then
+ if test "x$have_tiff" != "xyes"; then
+ echo "-- libtiff found.................. NO"
+ echo ""
+ echo "AcquireImages/JpegLossless/RawConverter plugins needs libtiff. These plugins will not be compiled!"
+ echo "To complile these plugins, please install libtiff development package."
+ echo "libtiff website is at http://www.remotesensing.org/libtiff"
+ echo ""
+ all_tests=bad
+ else
+ echo "-- libtiff library found.......... YES"
+ fi
+else
+ echo "-- libtiff library......... NOT NEEDED"
+fi
+
+if test "x$build_libkcal" != "xno"; then
+ if test "x$have_libkcal" != "xyes"; then
+ echo "-- libkcal found.................. NO"
+ echo ""
+ echo "Calendar plugin needs libkcal. This plugin will not be compiled!"
+ echo "To complile this plugin, please install libkcal development package."
+ echo "libkcal is part of kde-pim package, http://pim.kde.org"
+ echo ""
+ all_tests=bad
+ else
+ echo "-- libkcal found.................. YES"
+ fi
+else
+ echo "-- libkcal................. NOT NEEDED"
+fi
+
+if test "x$build_opengl" != "xno"; then
+ if test "x$have_opengl" != "xyes"; then
+ echo "-- OpenGL found................... NO"
+ echo ""
+ echo "SlideShow plugin needs OpenGL support. This plugin will not be compiled!"
+ echo "To complile this plugin, please install OpenGL support."
+ echo ""
+ all_tests=bad
+ else
+ echo "-- OpenGL found................... YES"
+ fi
+else
+ echo "-- OpenGL.................. NOT NEEDED"
+fi
+
+if test "x$build_xslt" != "xno"; then
+ if test "x$have_xslt" != "xyes"; then
+ echo "-- libxslt found.................. NO"
+ echo ""
+ echo "HtmlExport plugin needs XSLT library. This plugin will not be compiled!"
+ echo "To complile this plugin, please install libxslt development package."
+ echo "libxslt website is at http://xmlsoft.org/XSLT"
+ echo ""
+ all_tests=bad
+ else
+ echo "-- libxslt found.................. YES"
+ fi
+else
+ echo "-- libxslt library......... NOT NEEDED"
+fi
+
+if test "x$build_libgpod" != "xno"; then
+ if test "x$have_libgpod" != "xyes"; then
+ echo "-- libgpod found.................. NO"
+ echo ""
+ echo "iPodExport plugin needs the libgpod library, version 0.4.2 or greater. This plugin will not be compiled!"
+ echo "To complile this plugin, please install libgpod development package."
+ echo "libgpod website is at http://gtkpod.org/libgpod.html"
+ echo ""
+ all_tests=bad
+ else
+ echo "-- libgpod found.................. YES"
+ fi
+else
+ echo "-- libgpod library......... NOT NEEDED"
+fi
+
+echo ""
+
+if test -n "$enabled_kipi_plugins"; then
+ echo "-- Enabled kipi plugins:"
+ for plugin in $enabled_kipi_plugins; do
+ eval echo "+ \$kipi_plug_name_$plugin \($plugin\)"
+ done
+ echo ""
+fi
+if test -n "$disabled_kipi_plugins"; then
+ echo "-- Disabled kipi plugins:"
+ for plugin in $disabled_kipi_plugins; do
+ eval echo -n "- \$kipi_plug_name_$plugin \($plugin\)"
+ if eval test x\$enable_$plugin != xno; then
+ eval echo \" - dependencies: \$kipi_plug_deps_$plugin\"
+ else
+ echo "" # add newline
+ fi
+ done
+fi
diff --git a/kipi-plugins/configure.in.in b/kipi-plugins/configure.in.in
new file mode 100644
index 0000000..085a52b
--- /dev/null
+++ b/kipi-plugins/configure.in.in
@@ -0,0 +1,476 @@
+# ----------------------------------------------------------
+#
+# pkg-config check
+#
+# ----------------------------------------------------------
+
+AC_ARG_VAR(PKGCONFIGFOUND, [Path to pkg-config])
+AC_CHECK_PROG(PKGCONFIGFOUND, pkg-config,[yes])
+
+# ----------------------------------------------------------
+#
+# common header files path for kipi-plugins
+#
+# ----------------------------------------------------------
+
+KIPI_PLUGINS_COMMON_INCLUDE="-I\$(top_srcdir)/kipi-plugins/common/include"
+AC_SUBST(KIPI_PLUGINS_COMMON_INCLUDE)
+
+KIPI_PLUGINS_COMMON_LDFLAGS="-L\$(top_builddir)/kipi-plugins/common/libkipiplugins"
+AC_SUBST(KIPI_PLUGINS_COMMON_LDFLAGS)
+
+# -----------------------------------------------------------------
+#
+# enable hidden visibility only if kde >= 3.3.2 and kdelibs has
+# been compiled with visibility enabled
+#
+# -----------------------------------------------------------------
+
+AC_LANG_PUSH(C++)
+kipiplugins_save_cppflags=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $all_includes"
+AC_MSG_CHECKING([if hidden visibility should be enabled])
+AC_COMPILE_IFELSE(
+ [
+ #include <kdeversion.h>
+ #include <kdemacros.h>
+ int other_func( void )
+ {
+ #if KDE_IS_VERSION(3,3,2)
+ #else
+ iam dying;
+ #endif
+ #ifdef __KDE_HAVE_GCC_VISIBILITY
+ #else
+ no, iam really dead;
+ #endif
+ return 0;
+ }
+ ],
+ [ AC_MSG_RESULT([yes])
+ kipiplugins_enable_hidden_visibility="yes" ],
+ [ AC_MSG_RESULT([no]) ]
+)
+CPPFLAGS=$kipiplugins_save_cppflags
+AC_LANG_POP(C++)
+
+if test "x$kipiplugins_enable_hidden_visibility" = "xyes"; then
+ KDE_ENABLE_HIDDEN_VISIBILITY
+fi
+
+# ----------------------------------------------------------
+#
+# General kipi-plugin tests
+#
+# ----------------------------------------------------------
+
+AC_MSG_CHECKING([for libkipi in our sources])
+if test -d $srcdir/libkipi; then
+ have_libkipi=yes
+ LIBKIPI_CFLAGS='-I$(top_builddir)/libkipi -I$(top_srcdir)/libkipi'
+ LIBKIPI_LIBS='$(top_builddir)/libkipi/libkipi/libkipi.la'
+ LIBKIPI_LIBS_DEP='$(LIBKIPI_LIBS)'
+ AC_MSG_RESULT([found])
+ AC_SUBST(LIBKIPI_CFLAGS)
+ AC_SUBST(LIBKIPI_LIBS)
+ AC_SUBST(LIBKIPI_LIBS_DEP)
+ AC_MSG_RESULT([found])
+else
+ AC_MSG_RESULT([not found in sources])
+ if test "$PKGCONFIGFOUND" = "yes" ; then
+ # check for libkipi
+ have_libkipi=no
+
+ KDE_PKG_CHECK_MODULES(LIBKIPI, libkipi >= 0.1.5,
+ have_libkipi=yes, have_libkipi=no)
+
+ if test "x$have_libkipi" = "xno"; then
+ LIBKIPI_CFLAGS=""
+ LIBKIPI_LIBS=""
+ fi
+ else
+ LIBKIPI_CFLAGS=""
+ LIBKIPI_LIBS=""
+ fi
+ AC_SUBST(LIBKIPI_CFLAGS)
+ AC_SUBST(LIBKIPI_LIBS)
+fi
+
+if test "x$have_libkipi" != "xyes"; then
+ AC_MSG_ERROR([libkipi library is required by kipi-plugins.])
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kipi-plugins"
+fi
+
+# --------------------------------------------------------------------
+#
+# Check for libkexiv2
+#
+# --------------------------------------------------------------------
+
+AC_MSG_CHECKING([for libkexiv2 in our sources])
+if test -d $srcdir/libkexiv2; then
+ have_libkexiv2=yes
+ LIBKEXIV2_CFLAGS='-I$(top_srcdir)/libkexiv2'
+ LIBKEXIV2_LIBS='$(top_builddir)/libkexiv2/libkexiv2/libkexiv2.la'
+ LIBKEXIV2_LIBS_DEP='$(LIBKEXIV2_LIBS)'
+ AC_MSG_RESULT([found])
+ AC_SUBST(LIBKEXIV2_CFLAGS)
+ AC_SUBST(LIBKEXIV2_LIBS)
+ AC_SUBST(LIBKEXIV2_LIBS_DEP)
+else
+ AC_MSG_RESULT([not found in sources])
+ if test "$PKGCONFIGFOUND" = "yes" ; then
+ # check for libkexiv2
+ have_libkexiv2=no
+
+ KDE_PKG_CHECK_MODULES(LIBKEXIV2, libkexiv2 >= 0.1.5,
+ have_libkexiv2=yes, have_libkexiv2=no)
+
+ if test "x$have_libkexiv2" = "xno"; then
+ LIBKEXIV2_CFLAGS=""
+ LIBKEXIV2_LIBS=""
+ fi
+ else
+ LIBKEXIV2_CFLAGS=""
+ LIBKEXIV2_LIBS=""
+ fi
+ AC_SUBST(LIBKEXIV2_CFLAGS)
+ AC_SUBST(LIBKEXIV2_LIBS)
+fi
+
+if test x$have_libkexiv2 != xyes; then
+ AC_MSG_ERROR([libkexiv2 library is required by kipi-plugins.])
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kipi-plugins"
+fi
+
+# --------------------------------------------------------------------
+#
+# Check for libkdcraw
+#
+# --------------------------------------------------------------------
+
+AC_MSG_CHECKING([for libkdcraw in our sources])
+if test -d $srcdir/libkdcraw; then
+ have_libkdcraw=yes
+ LIBKDCRAW_CFLAGS='-I$(top_builddir)/libkdcraw -I$(top_srcdir)/libkdcraw'
+ LIBKDCRAW_LIBS='$(top_builddir)/libkdcraw/libkdcraw/libkdcraw.la'
+ LIBKDCRAW_LIBS_DEP='$(LIBKDCRAW_LIBS)'
+ AC_MSG_RESULT([found])
+ AC_SUBST(LIBKDCRAW_CFLAGS)
+ AC_SUBST(LIBKDCRAW_LIBS)
+ AC_SUBST(LIBKDCRAW_LIBS_DEP)
+ AC_MSG_RESULT([found])
+else
+ AC_MSG_RESULT([not found in sources])
+ if test "$PKGCONFIGFOUND" = "yes" ; then
+ # check for libkdcraw
+ have_libkdcraw=no
+
+ KDE_PKG_CHECK_MODULES(LIBKDCRAW, libkdcraw >= 0.1.4,
+ have_libkdcraw=yes, have_libkdcraw=no)
+
+ if test "x$have_libkdcraw" = "xno"; then
+ LIBKDCRAW_CFLAGS=""
+ LIBKDCRAW_LIBS=""
+ fi
+ else
+ LIBKDCRAW_CFLAGS=""
+ LIBKDCRAW_LIBS=""
+ fi
+ AC_SUBST(LIBKDCRAW_CFLAGS)
+ AC_SUBST(LIBKDCRAW_LIBS)
+fi
+
+if test x$have_libkdcraw != xyes; then
+ AC_MSG_ERROR([libkdcraw library is required by kipi-plugins.])
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kipi-plugins"
+fi
+
+#------------------------------------------------------------------
+#
+# Ability to fine-tune what plugins to build
+#
+#------------------------------------------------------------------
+
+# Following macro sets up individual kipi-plugins. It generates AC_ARG_ENABLE.
+# Third argument, plugin_dependencies is an optional space-separated list of dependencies.
+# In case the plugin is enabled, it sets build_${dependency}=yes (for every dependency)
+# KIPI_PLUGIN_PRE(plugin_directory, plugin_name[, plugin_depencencies])
+AC_DEFUN([KIPI_PLUGIN_PRE], [
+ AC_ARG_ENABLE([$1],
+ AC_HELP_STRING([--disable-$1], [$2 kipi plugin.] m4_if([$3], [], [], [[ Requires $3.]]) [ [[enable]]]),
+ [enable_$1="$enableval"],
+ [enable_$1="check"],
+ )
+ if test "${enable_$1}" != "yes" -a "${enable_$1}" != "no"; then
+ enable_$1="check"
+ fi
+ kipi_plug_deps_$1="$3"
+ kipi_plug_name_$1="$2"
+ if test "$enable_$1" != "no" -a -n "$3"; then
+ for dep in $3; do
+ eval build_${dep}="yes" # we must use eval because we use shell variable inside variable name
+ done
+ fi
+])
+
+# Add entry for every new conditional dependency here
+build_gphoto=no
+build_libgpod=no
+build_libkcal=no
+build_tiff=no
+build_xslt=no
+build_opengl=no
+
+# Please keep this list sorted and add all new plugins
+KIPI_PLUGIN_PRE([acquireimages], [Acquire Images], [tiff])
+KIPI_PLUGIN_PRE([batchprocessimages], [Batch Process Images])
+KIPI_PLUGIN_PRE([calendar], [Calendar], [libkcal])
+KIPI_PLUGIN_PRE([cdarchiving], [CD Archiving])
+KIPI_PLUGIN_PRE([findimages], [Find Images])
+KIPI_PLUGIN_PRE([flickrexport], [Flickr Exporter])
+KIPI_PLUGIN_PRE([galleryexport], [Remote Gallery Export])
+KIPI_PLUGIN_PRE([gpssync], [GPS Synchronization])
+KIPI_PLUGIN_PRE([htmlexport], [HTML Gallery], [xslt])
+#KIPI_PLUGIN_PRE([imagesgallery], [Images Gallery]) # ???
+KIPI_PLUGIN_PRE([imageviewer], [Viewer], [opengl])
+KIPI_PLUGIN_PRE([ipodexport], [iPod Export], [libgpod])
+KIPI_PLUGIN_PRE([jpeglossless], [JPEG Lossless]) # Does it depend on tiff?
+KIPI_PLUGIN_PRE([kameraklient], [Kamera Klient], [gphoto])
+KIPI_PLUGIN_PRE([metadataedit], [Metadata Editor])
+KIPI_PLUGIN_PRE([mpegencoder], [MPEG Encoder])
+KIPI_PLUGIN_PRE([picasawebexport], [Picasaweb Exporter])
+KIPI_PLUGIN_PRE([printwizard], [Print Wizard])
+KIPI_PLUGIN_PRE([rawconverter], [RAW converter], [tiff])
+KIPI_PLUGIN_PRE([sendimages], [Send Images])
+KIPI_PLUGIN_PRE([simpleviewerexport], [Simple Viewer])
+KIPI_PLUGIN_PRE([slideshow], [Slideshow], [opengl])
+#KIPI_PLUGIN_PRE([sync], [Sync]) # ???
+KIPI_PLUGIN_PRE([timeadjust], [Date & Time Adjust])
+KIPI_PLUGIN_PRE([wallpaper], [Wallpaper])
+
+#------------------------------------------------------------------
+#
+# Check for libtiff
+#
+#------------------------------------------------------------------
+
+have_tiff=no
+
+if test "x$build_tiff" != "xno"; then
+ AC_CHECK_LIB(tiff, TIFFWriteScanline,
+ have_tiff=yes,
+ AC_MSG_WARN([TIFF library not found]),
+ $all_libraries -ljpeg -lz -lm)
+
+ if test "x$have_tiff" = "xyes"; then
+ KDE_CHECK_HEADER(tiffio.h, have_tiff=yes, have_tiff=no)
+ fi
+
+ if test "x$have_tiff" != "xyes"; then
+ AC_WARN([TIFF library not found, some plugins will not be compiled.])
+ else
+ LIB_TIFF="-ltiff"
+ AC_SUBST(LIB_TIFF)
+ fi
+fi
+
+#---------------------------------------------------------
+#
+# gphoto2 detection - KameraKlient plugin
+#
+#---------------------------------------------------------
+
+have_gphoto=no
+
+if test "x$build_gphoto" != "xno"; then
+ AC_PATH_PROG(GPHOTO_CONFIG,gphoto2-config)
+ AC_PATH_PROG(GPHOTO_PORT_CONFIG,gphoto2-port-config)
+ if test -n "${GPHOTO_CONFIG}"; then
+ GPHOTO_CFLAGS="`$GPHOTO_CONFIG --cflags`"
+ AC_SUBST(GPHOTO_CFLAGS)
+ LIB_GPHOTO="`$GPHOTO_CONFIG --libs` `$GPHOTO_PORT_CONFIG --libs`"
+ AC_SUBST(LIB_GPHOTO)
+ have_gphoto=yes
+ else
+ AC_MSG_WARN([gPhoto2 not found, some plugins will not be compiled.])
+ fi
+fi
+
+#---------------------------------------------------------
+#
+# xslt detection - HTML export plugin
+#
+#---------------------------------------------------------
+
+have_xslt=no
+
+if test "x$build_xslt" != "xno"; then
+ AC_PATH_PROG(XSLT_CONFIG,xslt-config)
+ if test -n "${XSLT_CONFIG}"; then
+ LIBXSLT_CFLAGS="`$XSLT_CONFIG --cflags`"
+ AC_SUBST(LIBXSLT_CFLAGS)
+ LIBXSLT_LIBS="`$XSLT_CONFIG --libs`"
+ AC_SUBST(LIBXSLT_LIBS)
+ have_xslt=yes
+ else
+ AC_MSG_WARN([libxslt library not found, some plugins will not be compiled])
+ fi
+fi
+
+#------------------------------------------------------------------
+#
+# Check for libgpod - ipod export plugin
+#
+#------------------------------------------------------------------
+
+have_libgpod=no
+
+if test "x$build_libgpod" != "xno"; then
+ if test "$PKGCONFIGFOUND" = "yes" ; then
+
+ KDE_PKG_CHECK_MODULES(LIBGPOD, libgpod-1.0 >= 0.4.2 gobject-2.0, have_libgpod=yes,have_libgpod=no)
+
+ if test "x$have_libgpod" = "xyes"; then
+ AC_DEFINE(HAVE_LIBGPOD, 1, [have libgpod])
+ ac_cppflags_save=$CPPFLAGS
+ ac_cflags_save=$CFLAGS
+ ac_ldflags_save=$LDFLAGS
+
+ CPPFLAGS="$CPPFLAGS $LIBGPOD_INCLUDES"
+ CFLAGS="$CFLAGS $LIBGPOD_CFLAGS"
+ LDFLAGS="$LDFLAGS $LIBGPOD_LIBS"
+ else
+ AC_MSG_WARN([libgpod is required for the iPod export plugin.])
+ fi
+ fi
+fi
+
+#------------------------------------------------------------------
+#
+# Check for libkcal - iCalendar support library
+#
+#------------------------------------------------------------------
+
+have_libkcal=no
+
+if test "x$build_libkcal" != "xno"; then
+ KDE_CHECK_HEADERS(libkcal/calendarlocal.h, have_libkcal=yes, have_libkcal=no)
+ if test "x$have_libkcal" != "xyes"; then
+ AC_WARN([libkcal not found, some plugins will not be compiled.])
+ else
+ LIB_KCAL="-llibkcal"
+ AC_SUBST(LIB_KCAL)
+ fi
+fi
+
+# ----------------------------------------------------------
+#
+# Qt OpenGl check (fudged from Amarok) - Slideshow plugin
+#
+# ----------------------------------------------------------
+
+have_opengl=no
+
+if test "x$build_opengl" != "xno"; then
+ AC_MSG_CHECKING(for Qt with OpenGL support)
+ AC_CACHE_VAL(ac_cv_kde_qt_has_opengl,
+ [
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+
+ save_CXXFLAGS="$CXXFLAGS"
+ save_LIBS="$LIBS"
+ save_LDFLAGS="$LDFLAGS"
+
+ CXXFLAGS="$CXXFLAGS -I$qt_incdir $all_includes"
+ LDFLAGS="$LDFLAGS -L$qt_libdir $all_libraries $USER_LDFLAGS $KDE_MT_LDFLAGS"
+ LIBS="$LIBS $LIBQT $KDE_MT_LIBS"
+
+ AC_TRY_LINK([
+ #include <qgl.h>
+ ],
+ [
+ (void)new QGLWidget((QWidget*)0, "qgl");
+ ],
+ ac_cv_kde_qt_has_opengl=yes,
+ ac_cv_kde_qt_has_opengl=no)
+
+ CXXFLAGS="$save_CXXFLAGS"
+ LIBS="$save_LIBS"
+ LDFLAGS="$save_LDFLAGS"
+ AC_LANG_RESTORE
+ ])
+ AC_MSG_RESULT($ac_cv_kde_qt_has_opengl)
+
+ if test x$ac_cv_kde_qt_has_opengl = xyes; then
+ have_opengl="yes"
+ GL_LIBS="-lGL"
+ else
+ have_opengl="no"
+ GL_LIBS=""
+ fi
+
+ AC_SUBST(GL_LIBS)
+fi
+
+# ----------------------------------------------------------
+#
+# Second stage of kipi-plugin fine-tuning.
+#
+# ----------------------------------------------------------
+
+# Following macro checks if particular plugin should be enabled and for
+# its dependencies. (have_$dependency must be either yes or no). Sets
+# AM_CONDITIONAL accordingly. KIPI_PLUGIN_PRE must precede it.
+# KIPI_PLUGIN_POST([plugin_directory])
+AC_DEFUN([KIPI_PLUGIN_POST], [
+ test="test $enable_$1 != no"
+ if test $enable_$1 != no; then
+ for dep in $kipi_plug_deps_$1; do
+ test="${test} -a \$have_${dep} = yes"
+ if eval test \$have_${dep} != "yes"; then # we must use eval cos we use shell variable inside variable name
+ AC_MSG_WARN([$dep could not be found, $kipi_plug_name_$1 ($1) plugin will not be built.])
+ fi
+ done
+ fi
+ if eval $test; then
+ enabled_kipi_plugins="$enabled_kipi_plugins $1"
+ else
+ disabled_kipi_plugins="$disabled_kipi_plugins $1"
+ if test $enable_$1 = yes; then
+ AC_MSG_ERROR([Failing as hard-enabled plugin cannot be compiled.])
+ fi
+ fi
+ AM_CONDITIONAL([compile_]m4_toupper($1), [eval $test])
+])
+
+enabled_kipi_plugins=""
+disabled_kipi_plugins=""
+
+# Please keep this list sorted and add all new plugins
+KIPI_PLUGIN_POST([acquireimages])
+KIPI_PLUGIN_POST([batchprocessimages])
+KIPI_PLUGIN_POST([calendar])
+KIPI_PLUGIN_POST([cdarchiving])
+KIPI_PLUGIN_POST([findimages])
+KIPI_PLUGIN_POST([flickrexport])
+KIPI_PLUGIN_POST([galleryexport])
+KIPI_PLUGIN_POST([gpssync])
+KIPI_PLUGIN_POST([htmlexport])
+#KIPI_PLUGIN_POST([imagesgallery]) # ???
+KIPI_PLUGIN_POST([imageviewer])
+KIPI_PLUGIN_POST([ipodexport])
+KIPI_PLUGIN_POST([jpeglossless])
+KIPI_PLUGIN_POST([kameraklient])
+KIPI_PLUGIN_POST([metadataedit])
+KIPI_PLUGIN_POST([mpegencoder])
+KIPI_PLUGIN_POST([picasawebexport])
+KIPI_PLUGIN_POST([printwizard])
+KIPI_PLUGIN_POST([rawconverter])
+KIPI_PLUGIN_POST([sendimages])
+KIPI_PLUGIN_POST([simpleviewerexport])
+KIPI_PLUGIN_POST([slideshow])
+#KIPI_PLUGIN_POST([sync]) # ???
+KIPI_PLUGIN_POST([timeadjust])
+KIPI_PLUGIN_POST([wallpaper])
diff --git a/kipi-plugins/findimages/Doxyfile b/kipi-plugins/findimages/Doxyfile
new file mode 100644
index 0000000..339dc76
--- /dev/null
+++ b/kipi-plugins/findimages/Doxyfile
@@ -0,0 +1,1228 @@
+# Doxyfile 1.4.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME =
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is YES.
+
+SHOW_DIRECTORIES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the progam writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/kipi-plugins/findimages/Makefile.am b/kipi-plugins/findimages/Makefile.am
new file mode 100644
index 0000000..26f3836
--- /dev/null
+++ b/kipi-plugins/findimages/Makefile.am
@@ -0,0 +1,29 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_findimages.la
+
+kipiplugin_findimages_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+
+# Srcs for the plugin
+kipiplugin_findimages_la_SOURCES = plugin_findimages.cpp displaycompare.cpp \
+ finddupplicateimages.cpp finddupplicatedialog.cpp \
+ fuzzycompare.cpp fastcompare.cpp actions.cpp
+
+# Libs needed by the plugin
+kipiplugin_findimages_la_LIBADD = -lkdefx $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_findimages_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_findimages.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_findimages.pot
+
+kipifindimagesicondir = $(kde_datadir)/kipiplugin_findimages/icons
+kipifindimagesicon_ICON = AUTO
diff --git a/kipi-plugins/findimages/actions.cpp b/kipi-plugins/findimages/actions.cpp
new file mode 100644
index 0000000..e578a92
--- /dev/null
+++ b/kipi-plugins/findimages/actions.cpp
@@ -0,0 +1,52 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2006 Jesper Pedersen <blackie at 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include "actions.h"
+
+/**
+ * \brief Send a status message to the main thread.
+ * The worker thread communicates status messages to the main thread by posting events to it, just as it should.
+ * There is just one problem: When the main thread gets a message it needs to update a listbox, which is
+ * rather expensive, The worker thread thus easily floods the main thread.
+ * The result of this flooding is that the GUI doesn't update very well, and as a consequence looks crappy.
+ *
+ * To overcome this problem, we will only send status messages at most every 50 msec.
+ */
+void KIPIFindDupplicateImagesPlugin::sendMessage( QObject* receiver, const Action& action, const QString & fileName,
+ int total, bool starting, bool succes )
+{
+ static QTime time;
+ static int count = 0;
+ if (starting)
+ ++count;
+
+ if ( time.elapsed() > 50 || action == KIPIFindDupplicateImagesPlugin::Progress ||
+ (!starting && !succes ) /*error messages*/ ) {
+ KIPIFindDupplicateImagesPlugin::EventData *d = new KIPIFindDupplicateImagesPlugin::EventData;
+ d->action = action;
+ d->fileName = fileName;
+ d->total = total;
+ d->count = count;
+ d->starting = starting;
+ d->success = succes;
+ QApplication::postEvent( receiver, new QCustomEvent(QEvent::User, d));
+ time.restart();
+ }
+}
diff --git a/kipi-plugins/findimages/actions.h b/kipi-plugins/findimages/actions.h
new file mode 100644
index 0000000..e95b333
--- /dev/null
+++ b/kipi-plugins/findimages/actions.h
@@ -0,0 +1,69 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// ACTIONS.H
+//
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.org>
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ACTIONS_H
+#define ACTIONS_H
+#include <qstring.h>
+#include <qdatetime.h>
+#include <qapplication.h>
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+
+enum Action
+{
+ Similar = 0,
+ Exact,
+ Matrix,
+ FastParsing,
+ Progress
+};
+
+
+
+class EventData
+{
+public:
+ EventData()
+ {
+ starting = false;
+ success = false;
+ }
+
+ QString fileName;
+ QString errString;
+ int count;
+ int total;
+ bool starting;
+ bool success;
+ Action action;
+};
+
+
+void sendMessage( QObject* receiver, const Action& action, const QString & fileName,
+ int total, bool starting, bool succes );
+
+
+} // NameSpace KIPIFindDupplicateImagesPlugin
+
+#endif // ACTIONS_H
diff --git a/kipi-plugins/findimages/compareoperation.h b/kipi-plugins/findimages/compareoperation.h
new file mode 100644
index 0000000..b677714
--- /dev/null
+++ b/kipi-plugins/findimages/compareoperation.h
@@ -0,0 +1,40 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2006 Jesper Pedersen <blackie at 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef COMPAREOPERATION_H
+#define COMPAREOPERATION_H
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+class CompareOperation
+{
+public:
+ CompareOperation() :m_stopRequested( false ) {}
+ virtual QDict < QPtrVector < QFile > > compare( const QStringList& fileList ) = 0;
+ void stopPlease() { m_stopRequested = true; }
+
+protected:
+ bool m_stopRequested;
+};
+
+}
+
+#endif /* COMPAREOPERATION_H */
+
diff --git a/kipi-plugins/findimages/displaycompare.cpp b/kipi-plugins/findimages/displaycompare.cpp
new file mode 100644
index 0000000..70196a4
--- /dev/null
+++ b/kipi-plugins/findimages/displaycompare.cpp
@@ -0,0 +1,463 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// DISPLAYCOMPARE.CPP
+//
+// Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// Include files for Qt
+
+#include <qptrvector.h>
+#include <qdict.h>
+#include <qfile.h>
+#include <qlistbox.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qlistview.h>
+#include <qcheckbox.h>
+#include <qheader.h>
+#include <qlayout.h>
+#include <qfileinfo.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qwhatsthis.h>
+#include <qpushbutton.h>
+#include <qframe.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+#include <klistview.h>
+#include <ksqueezedtextlabel.h>
+#include <kapplication.h>
+#include <kurl.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kio/netaccess.h>
+#include <kio/global.h>
+#include <kimageio.h>
+#include <kio/previewjob.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+
+// Include files for KIPI
+
+#include <libkipi/version.h>
+
+// Local include files
+
+#include "pluginsversion.h"
+#include "kpaboutdata.h"
+#include "displaycompare.h"
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+class FindOriginalItem : public QCheckListItem
+{
+public:
+ FindOriginalItem(QListView * parent, QString const & name, QString const & fullpath,
+ QString const & album, QString const & comments)
+ : QCheckListItem( parent, name, QCheckListItem::CheckBox), _name(name),
+ _fullpath(fullpath), _album (album), _comments (comments)
+ {}
+
+ QString name() { return _name; }
+ QString fullpath() { return _fullpath; }
+ QString album() { return _album; }
+ QString comments() { return _comments; }
+
+private:
+ QString _name;
+ QString _fullpath;
+ QString _album;
+ QString _comments;
+};
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+class FindDuplicateItem : public QCheckListItem
+{
+public:
+ FindDuplicateItem(QListView * parent, QString const & name, QString const & fullpath,
+ QString const & album, QString const & comments)
+ : QCheckListItem( parent, name, QCheckListItem::CheckBox), _name(name),
+ _fullpath(fullpath), _album (album), _comments (comments)
+ {}
+
+ QString name() { return _name; }
+ QString fullpath() { return _fullpath; }
+ QString album() { return _album; }
+ QString comments() { return _comments; }
+
+private:
+ QString _name;
+ QString _fullpath;
+ QString _album;
+ QString _comments;
+};
+
+
+//////////////////////////////////// CONSTRUCTOR ////////////////////////////////////////////
+
+DisplayCompare::DisplayCompare(QWidget* parent, KIPI::Interface* interface,
+ const QDict < QPtrVector < QFile > >& cmp )
+ : KDialogBase( parent, "DisplayCompare", true, 0,
+ Help|User1|Close, Close, false, i18n("Delete")),
+ m_cmp(cmp), m_interface( interface )
+{
+ KImageIO::registerFormats();
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Find Duplicate Images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to find duplicate images\n"
+ "This plugin is based on ShowImg implementation algorithm"),
+ "(c) 2003-2004, Gilles Caulier");
+
+ m_about->addAuthor("Jesper K. Pedersen", I18N_NOOP("Maintainer"),
+ "blackie atkde dot org");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Original author"),
+ "caulier dot gilles at gmail dot com");
+
+ m_about->addAuthor("Richard Groult", I18N_NOOP("Find duplicate images algorithm"),
+ "rgroult at jalix.org");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ // ----------------------------------------------------
+
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout* ml = new QVBoxLayout( box, 10 );
+ QHBoxLayout* h1 = new QHBoxLayout( ml );
+ QVBoxLayout* v1 = new QVBoxLayout( h1 );
+ h1->addSpacing( 5 );
+ QGridLayout* g1 = new QGridLayout( v1, 1, 2 );
+
+ //---------------------------------------------
+
+ GroupBox1 = new QGroupBox( 1, Qt::Horizontal, i18n("Original Files"), box );
+ GroupBox1->layout()->setSpacing( 6 );
+ GroupBox1->layout()->setMargin( 11 );
+
+ OriginalNameLabel = new KSqueezedTextLabel( GroupBox1, "OriginalNameLabel" );
+ OriginalNameLabel->setFrameShape( QLabel::Box );
+ OriginalNameLabel->setAlignment( int( QLabel::AlignCenter ) );
+
+ preview1 = new QLabel( GroupBox1, "preview1" );
+ preview1->setFixedHeight( 120 );
+ preview1->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ preview1->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
+ QWhatsThis::add( preview1, i18n( "<p>The preview of files with duplicates." ) );
+
+ originalInfoLabel1 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel1" );
+ originalInfoLabel1->setAlignment( int( QLabel::AlignCenter ) );
+ originalInfoLabel2 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel2" );
+ originalInfoLabel2->setAlignment( int( QLabel::AlignCenter ) );
+ originalInfoLabel3 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel3" );
+ originalInfoLabel3->setAlignment( int( QLabel::AlignCenter ) );
+ originalInfoLabel4 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel4" );
+ originalInfoLabel4->setAlignment( int( QLabel::AlignCenter ) );
+ originalInfoLabel5 = new KSqueezedTextLabel( GroupBox1, "originalInfoLabel5" );
+ originalInfoLabel5->setAlignment( int( QLabel::AlignCenter ) );
+
+ listName = new KListView( GroupBox1, "listName" );
+ listName->header()->setLabel( 0, i18n( "Files" ) );
+ QWhatsThis::add( listName, i18n( "<p>This list contains all files with many duplicates." ) );
+ listName->addColumn( i18n( "Files" ) );
+ listName->setResizeMode(QListView::AllColumns);
+
+ g1->addWidget( GroupBox1 , 0, 0);
+
+ //---------------------------------------------
+
+ GroupBox2 = new QGroupBox( 1, Qt::Horizontal, i18n("Similar Files"), box );
+ GroupBox2->layout()->setSpacing( 6 );
+ GroupBox2->layout()->setMargin( 11 );
+
+ similarNameLabel = new KSqueezedTextLabel( GroupBox2, "similarNameLabel" );
+ similarNameLabel->setFrameShape( QLabel::Box );
+ similarNameLabel->setAlignment( int( QLabel::AlignCenter ) );
+
+ preview2 = new QLabel( GroupBox2, "preview2" );
+ preview2->setFixedHeight( 120 );
+ preview2->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ preview2->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
+ QWhatsThis::add( preview2, i18n( "<p>The preview of duplicate files." ) );
+
+ similarInfoLabel1 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel1" );
+ similarInfoLabel1->setAlignment( int( QLabel::AlignCenter ) );
+ similarInfoLabel2 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel2" );
+ similarInfoLabel2->setAlignment( int( QLabel::AlignCenter ) );
+ similarInfoLabel3 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel3" );
+ similarInfoLabel3->setAlignment( int( QLabel::AlignCenter ) );
+ similarInfoLabel4 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel4" );
+ similarInfoLabel4->setAlignment( int( QLabel::AlignCenter ) );
+ similarInfoLabel5 = new KSqueezedTextLabel( GroupBox2, "similarInfoLabel5" );
+ similarInfoLabel5->setAlignment( int( QLabel::AlignCenter ) );
+
+ listEq = new KListView( GroupBox2, "listEq" );
+ listEq->header()->setLabel( 0, i18n( "Files" ) );
+ QWhatsThis::add( listEq, i18n( "<p>This list contains all duplicates files." ) );
+ listEq->addColumn( i18n( "Identical To" ) );
+ listEq->setResizeMode(QListView::AllColumns);
+
+ g1->addWidget( GroupBox2 , 0, 1);
+
+ setTabOrder( listName, listEq );
+
+ //---------------------------------------------
+
+ QDictIterator < QPtrVector < QFile > >itres(m_cmp); // iterator for res
+ int n_id = 0;
+
+ while (itres.current ())
+ {
+ QFileInfo fi(itres.currentKey());
+ QString Temp = fi.dirPath();
+ QString albumName = Temp.section('/', -1);
+
+ KURL url;
+ url.setPath(fi.fileName());
+ KIPI::ImageInfo info = m_interface->info(url);
+ QString comments = info.description();
+
+ new FindOriginalItem( listName, fi.fileName(), itres.currentKey(), albumName, comments );
+ ++itres;
+ ++n_id;
+ }
+
+ setCaption(i18n("1 Original Image with Duplicate Images Has Been Found",
+ "%n Original Images with Duplicate Images Have Been Found", n_id));
+
+ // signals and slots connections
+
+ connect(this, SIGNAL(user1Clicked()),
+ this, SLOT(slotDelete()));
+
+ connect(listName, SIGNAL(selectionChanged ( QListViewItem * )),
+ this, SLOT(slotDisplayLeft(QListViewItem *)));
+
+ connect(listEq, SIGNAL(selectionChanged ( QListViewItem * )),
+ this, SLOT(slotDisplayRight(QListViewItem *)));
+
+ resize( 700, 600 );
+ listName->setSelected(listName->firstChild(), true);
+}
+
+
+//////////////////////////////////// DESTRUCTOR /////////////////////////////////////////////
+
+DisplayCompare::~DisplayCompare()
+{
+ delete m_about;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void DisplayCompare::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("findduplicateimages",
+ "kipi-plugins");
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void DisplayCompare::slotDelete( void )
+{
+ FindDuplicateItem *item = (FindDuplicateItem*)listEq->firstChild ();
+ FindDuplicateItem *itemTmp;
+
+ while(item) // Remove duplicate file selected.
+ {
+ if( item->isOn() )
+ {
+ itemTmp = (FindDuplicateItem*)item->nextSibling();
+ KURL deleteImage(item->fullpath());
+
+ if ( KIO::NetAccess::del(deleteImage) == false )
+ KMessageBox::error(this, i18n("Cannot remove duplicate file:\n%1").arg(item->fullpath()));
+ else
+ m_interface->delImage( deleteImage );
+
+ listEq->takeItem (item);
+ item = itemTmp;
+ }
+ else
+ item = (FindDuplicateItem*)item->nextSibling();
+ }
+
+ // Remove originals files selected.
+
+ for (FindOriginalItem* item = (FindOriginalItem*)listName->firstChild(); item;
+ item = (FindOriginalItem*)item->nextSibling())
+ {
+ if ( item->isOn() )
+ {
+ KURL deleteImage(item->fullpath());
+
+ if ( KIO::NetAccess::del(deleteImage) == false )
+ KMessageBox::error(this, i18n("Cannot remove original file:\n%1").arg(item->fullpath()));
+
+ item->setOn( false );
+ }
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void DisplayCompare::slotDisplayLeft(QListViewItem * item)
+{
+ KApplication::setOverrideCursor( waitCursor );
+ listEq->clear();
+ FindOriginalItem *pitem = static_cast<FindOriginalItem*>( item );
+ QPtrVector < QFile > *list = (QPtrVector < QFile > *)m_cmp.find(pitem->fullpath());
+ QImage im(pitem->fullpath());
+
+ if ( !im.isNull() )
+ {
+ OriginalNameLabel->setText(pitem->name());
+ originalInfoLabel1->setText(i18n("Image size: %1x%2 pixels").arg(im.width()).arg(im.height()));
+ originalInfoLabel2->setText(i18n("File size: 1 byte",
+ "File size: %n bytes",QFileInfo(pitem->fullpath()).size()));
+ originalInfoLabel3->setText(i18n("Modified: %1").arg(KLocale(NULL)
+ .formatDateTime(QFileInfo(pitem->fullpath())
+ .lastModified())));
+ originalInfoLabel4->setText(i18n("Album: %1").arg(pitem->album()));
+ originalInfoLabel5->setText(i18n("Comments: %1").arg(pitem->comments()));
+ }
+
+ preview1->clear();
+
+ QString IdemIndexed = "file:" + pitem->fullpath();
+ KURL url(IdemIndexed);
+
+ KIO::PreviewJob* thumbJob1 = KIO::filePreview( url, preview1->height() );
+
+ connect(thumbJob1, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ SLOT(slotGotPreview1(const KFileItem*, const QPixmap&)));
+
+ FindDuplicateItem *last = NULL;
+ QFile *f = NULL;
+ QFileInfo *fi = new QFileInfo();
+ QString fn;
+
+ for (unsigned int i = 0 ; i < list->size () ; ++i)
+ {
+ f = (QFile*)list->at(i);
+ fi->setFile(*f);
+ fn = fi->absFilePath();
+
+ if (fi->exists ())
+ {
+ QString Temp = fi->dirPath();
+ QString albumName = Temp.section('/', -1);
+
+ KURL url;
+ url.setPath(fi->fileName());
+ KIPI::ImageInfo info = m_interface->info(url);
+ QString comments = info.description();
+
+ FindDuplicateItem *item = new FindDuplicateItem( listEq,
+ fi->fileName(),
+ fn,
+ albumName,
+ comments
+ );
+ if (!last)
+ last = item;
+ }
+ }
+
+ preview2->setPixmap(QPixmap());
+ listEq->setSelected(last, true);
+ KApplication::restoreOverrideCursor();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void DisplayCompare::slotGotPreview1(const KFileItem* /*url*/, const QPixmap &pixmap)
+{
+ preview1->setPixmap(pixmap);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void DisplayCompare::slotDisplayRight(QListViewItem * item)
+{
+ KApplication::setOverrideCursor( waitCursor );
+ FindDuplicateItem *pitem = static_cast<FindDuplicateItem*>( item );
+ QImage im(pitem->fullpath());
+
+ if ( !im.isNull() )
+ {
+ similarNameLabel->setText(pitem->name());
+ similarInfoLabel1->setText(i18n("Image size: %1x%2 pixels").arg(im.width()).arg(im.height()));
+ similarInfoLabel2->setText(i18n("File size: 1 byte",
+ "File size: %n bytes", QFileInfo(pitem->fullpath()).size()));
+ similarInfoLabel3->setText(i18n("Modified: %1").arg(KLocale(NULL)
+ .formatDateTime(QFileInfo(pitem->fullpath())
+ .lastModified())));
+ similarInfoLabel4->setText(i18n("Album: %1").arg(pitem->album()));
+ similarInfoLabel5->setText(i18n("Caption: %1").arg(pitem->comments()));
+ }
+
+ preview2->clear();
+
+ QString IdemIndexed = "file:" + pitem->fullpath();
+ KURL url(IdemIndexed);
+
+ KIO::PreviewJob* thumbJob2 = KIO::filePreview( url, preview2->height() );
+
+ connect(thumbJob2, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ SLOT(slotGotPreview2(const KFileItem*, const QPixmap&)));
+
+ KApplication::restoreOverrideCursor();
+ }
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void DisplayCompare::slotGotPreview2(const KFileItem* /*url*/, const QPixmap &pixmap)
+{
+ preview2->setPixmap(pixmap);
+}
+
+} // NameSpace KIPIFindDupplicateImagesPlugin
+
+#include "displaycompare.moc"
diff --git a/kipi-plugins/findimages/displaycompare.h b/kipi-plugins/findimages/displaycompare.h
new file mode 100644
index 0000000..18e4681
--- /dev/null
+++ b/kipi-plugins/findimages/displaycompare.h
@@ -0,0 +1,117 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// DISPLAYCOMPARE.H
+//
+// Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef __DISPLAYCOMPARE_H__
+#define __DISPLAYCOMPARE_H__
+
+// Include files for Qt
+
+#include <qptrvector.h>
+#include <qdict.h>
+#include <qguardedptr.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+// Includes file for libKIPI.
+
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QGroupBox;
+class QLabel;
+class QListView;
+class QListViewItem;
+class QPushButton;
+class QPrtList;
+class QFile;
+
+class KSqueezedTextLabel;
+class KFileItem;
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+
+class DisplayCompare : public KDialogBase
+{
+Q_OBJECT
+
+public:
+
+ DisplayCompare(QWidget* parent, KIPI::Interface* interface, const QDict < QPtrVector < QFile > >& cmp);
+ ~DisplayCompare();
+
+private slots :
+
+ void slotDisplayRight(QListViewItem *);
+ void slotDisplayLeft(QListViewItem *);
+ void slotHelp();
+ void slotDelete( void );
+ void slotGotPreview1(const KFileItem* url, const QPixmap &pixmap);
+ void slotGotPreview2(const KFileItem* url, const QPixmap &pixmap);
+
+private:
+
+ const QDict < QPtrVector < QFile > > m_cmp;
+
+ QGroupBox* GroupBox1;
+ QGroupBox* GroupBox2;
+
+ KSqueezedTextLabel* OriginalNameLabel;
+ KSqueezedTextLabel* originalInfoLabel1;
+ KSqueezedTextLabel* originalInfoLabel2;
+ KSqueezedTextLabel* originalInfoLabel3;
+ KSqueezedTextLabel* originalInfoLabel4;
+ KSqueezedTextLabel* originalInfoLabel5;
+
+ KSqueezedTextLabel* similarNameLabel;
+ KSqueezedTextLabel* similarInfoLabel1;
+ KSqueezedTextLabel* similarInfoLabel2;
+ KSqueezedTextLabel* similarInfoLabel3;
+ KSqueezedTextLabel* similarInfoLabel4;
+ KSqueezedTextLabel* similarInfoLabel5;
+
+ QLabel* preview1;
+ QLabel* preview2;
+
+ QListView* listName;
+ QListView* listEq;
+
+ QPushButton *m_helpButton;
+
+ KIPI::Interface *m_interface;
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIFindDupplicateImagesPlugin
+
+#endif // __DISPLAYCOMPARE_H__
+
diff --git a/kipi-plugins/findimages/fastcompare.cpp b/kipi-plugins/findimages/fastcompare.cpp
new file mode 100644
index 0000000..858a69c
--- /dev/null
+++ b/kipi-plugins/findimages/fastcompare.cpp
@@ -0,0 +1,191 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// FINDDUPPLICATEIMAGES.CPP
+//
+// Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include "fastcompare.h"
+#include "actions.h"
+#include <qstringlist.h>
+#include <qapplication.h>
+#include <kdebug.h>
+#include <qfileinfo.h>
+
+KIPIFindDupplicateImagesPlugin::FastCompare::FastCompare( QObject* parent )
+ :m_parent( parent )
+{
+}
+
+
+QDict < QPtrVector < QFile > > KIPIFindDupplicateImagesPlugin::FastCompare::compare( const QStringList& filesList )
+{
+ QDict < QPtrVector < QFile > > res;
+ QDict < QPtrVector < QFile > >*dict = new QDict < QPtrVector < QFile > >;
+ dict->setAutoDelete(true);
+ QPtrVector < QFile > *list;
+
+ QString size;
+ QFile *file;
+ int nbrF = 0;
+
+ sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::Progress, QString::null, filesList.count()*2, true, false );
+
+ kdDebug( 51000 ) << filesList.count() << " images to parse with Fast method..." << endl;
+
+ for ( QStringList::ConstIterator item = filesList.begin(); item != filesList.end(); ++item )
+ {
+ if ( m_stopRequested )
+ return QDict < QPtrVector < QFile > >();
+
+ QString itemName(*item);
+ nbrF++;
+
+ sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::FastParsing, itemName, 0, true, false );
+
+ // Create a file
+ file = new QFile( itemName );
+
+ // Read the file size
+ size = QString::number(QFileInfo (*file).size ());
+
+ // if not in the table, we do it
+ if ( !dict->find (size) )
+ {
+ list = new QPtrVector < QFile >;
+ list->setAutoDelete(true);
+ dict->insert (size, list);
+ }
+
+ // Read the list
+ list = (QPtrVector < QFile > *)dict->find (size);
+
+ //Add the file
+ list->resize (list->size () + 1);
+ list->insert (list->size () - 1, file);
+
+ //sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::FastParsing, itemName, 0, false, true );
+ }
+
+ // For counting the files comparaison tasks.
+ int count = 0;
+ QDictIterator < QPtrVector < QFile > >itcount (*dict); // Iterator for dict.
+
+ while (itcount.current ())
+ {
+ list = (QPtrVector < QFile > *)itcount.current ();
+
+ if (list->size () != 1)
+ for (unsigned int i = 0; i < list->size (); i++)
+ ++count;
+
+ ++itcount;
+ }
+
+ // Files comparison
+ QDictIterator < QPtrVector < QFile > >it (*dict); // Iterator for dict.
+
+ while (it.current ())
+ {
+ if ( m_stopRequested )
+ return QDict < QPtrVector < QFile > >();
+ QDict < QFile > *fait = new QDict < QFile >;
+ list = (QPtrVector < QFile > *)it.current ();
+
+ if (list->size () != 1)
+ {
+ for (unsigned int i = 0; i < list->size (); i++)
+ {
+ QFile *file1 = (QFile *) (list->at (i));
+
+ sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::Exact,file1->name(),filesList.count() + count, true, false );
+
+ if (!fait->find (file1->name()))
+ {
+ for (unsigned int j = i + 1; j < list->size (); j++)
+ {
+ QFile *file2 = (QFile *) (list->at (j));
+
+ // The files are equals ?
+
+ if (equals (file1, file2))
+ {
+ QPtrVector < QFile > *vect;
+
+ // Add the file.
+
+ if (!res.find (file1->name ()))
+ {
+ vect = new QPtrVector < QFile >;
+ vect->setAutoDelete(true);
+ res.insert (file1->name (), vect);
+ }
+ else
+ vect = (QPtrVector < QFile > *)res.find (file1->name ());
+
+ vect->resize (vect->size () + 1);
+ vect->insert (vect->size () - 1, file2);
+
+ fait->insert(file2->name(), file2);
+ }
+ }
+ }
+
+ // sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::Exact, file1->name(), 0, false, true );
+ }
+ }
+
+ delete(fait);
+ ++it;
+ }
+
+ delete (it);
+
+ return res;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+bool KIPIFindDupplicateImagesPlugin::FastCompare::equals(QFile * f1, QFile * f2)
+{
+ if ( QFileInfo (*f1).size () != QFileInfo (*f2).size () )
+ return false;
+
+ f1->open (IO_ReadOnly);
+ f2->open (IO_ReadOnly);
+
+ QDataStream s1 (f1);
+ QDataStream s2 (f2);
+
+ Q_INT8 b1, b2;
+ bool eq = true;
+
+ while ( !s1.atEnd () && eq )
+ {
+ s1 >> b1;
+ s2 >> b2;
+ eq = (b1 == b2);
+ }
+
+ f1->close ();
+ f2->close ();
+ return eq;
+}
diff --git a/kipi-plugins/findimages/fastcompare.h b/kipi-plugins/findimages/fastcompare.h
new file mode 100644
index 0000000..0222880
--- /dev/null
+++ b/kipi-plugins/findimages/fastcompare.h
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// FINDDUPPLICATEIMAGES.CPP
+//
+// Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef FASTCOMPARE_H
+#define FASTCOMPARE_H
+
+class QStringList;
+class QObject;
+#include <qdict.h>
+#include <qptrvector.h>
+#include <qfile.h>
+#include "actions.h"
+#include "compareoperation.h"
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+
+class FastCompare :public CompareOperation
+{
+public:
+ FastCompare( QObject* parent );
+ virtual QDict < QPtrVector < QFile > > compare( const QStringList& filesList );
+
+protected:
+ bool equals(QFile*, QFile*); // Return true if the 2 files are the sames.
+
+private:
+ QObject* m_parent;
+};
+
+}
+
+#endif /* FASTCOMPARE_H */
+
diff --git a/kipi-plugins/findimages/finddupplicatedialog.cpp b/kipi-plugins/findimages/finddupplicatedialog.cpp
new file mode 100644
index 0000000..cd6cfe5
--- /dev/null
+++ b/kipi-plugins/findimages/finddupplicatedialog.cpp
@@ -0,0 +1,337 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// FINDDUPPLICATEDIALOG.CPP
+//
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// Include files for Qt
+
+#include <qlabel.h>
+#include <qvbox.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qlineedit.h>
+#include <qspinbox.h>
+#include <qlistview.h>
+#include <qheader.h>
+#include <qpushbutton.h>
+#include <qfileinfo.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kfontdialog.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kurlrequester.h>
+#include <kurl.h>
+#include <kdirsize.h>
+#include <klineedit.h>
+#include <knuminput.h>
+#include <kcolorbutton.h>
+#include <kglobalsettings.h>
+#include <kmessagebox.h>
+#include <kbuttonbox.h>
+#include <kapplication.h>
+#include <ksqueezedtextlabel.h>
+#include <kio/global.h>
+#include <klistview.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+
+// Include files for KIPI
+
+#include <libkipi/imagecollection.h>
+#include <libkipi/imagecollectionselector.h>
+
+// Local include files
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "finddupplicatedialog.h"
+#include "finddupplicatedialog.moc"
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+
+FindDuplicateDialog::FindDuplicateDialog( KIPI::Interface* interface, QWidget *parent)
+ : KDialogBase( IconList, i18n("Configure"), Help|Ok|Cancel,
+ Ok, parent, "FindDuplicateDialog", true, false ),
+ m_interface( interface )
+{
+ setCaption(i18n("Find Duplicate Images"));
+ setupSelection();
+ setupPageMethod();
+ page_setupSelection->setFocus();
+ resize( 650, 500 );
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Find Duplicate Images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to find duplicate images\n"
+ "This plugin is based on ShowImg implementation algorithm"),
+ "(c) 2003-2004, Gilles Caulier");
+
+ m_about->addAuthor("Jesper K. Pedersen", I18N_NOOP("Maintainer"),
+ "blackie at kde dot org");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Original author"),
+ "caulier dot gilles at gmail dot com");
+
+ m_about->addAuthor("Richard Groult", I18N_NOOP("Find duplicate images algorithm"),
+ "rgroult at jalix.org");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+FindDuplicateDialog::~FindDuplicateDialog()
+{
+ delete m_about;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::setupSelection(void)
+{
+ page_setupSelection = addPage(i18n("Selection"),
+ i18n("Album's Selection"),
+ BarIcon("folder_image", KIcon::SizeMedium));
+
+ QVBoxLayout *layout = new QVBoxLayout(page_setupSelection, 0, spacingHint() );
+ m_imageCollectionSelector = new KIPI::ImageCollectionSelector(page_setupSelection, m_interface);
+ layout->addWidget(m_imageCollectionSelector);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::setupPageMethod(void)
+{
+ QString whatsThis;
+ page_setupMethod = addPage( i18n("Method & Cache"), i18n("Find-Duplicates Method & Cache Configuration"),
+ BarIcon("run", KIcon::SizeMedium ) );
+
+ QVBoxLayout *vlay = new QVBoxLayout( page_setupMethod, 0, spacingHint() );
+
+ //---------------------------------------------
+
+ QGroupBox * groupBox1 = new QGroupBox( 2, Qt::Horizontal, i18n("Method"), page_setupMethod );
+ groupBox1->layout()->setSpacing( 6 );
+ groupBox1->layout()->setMargin( 11 );
+
+ QLabel *m_labelsearchMethod = new QLabel( i18n("Search method:"), groupBox1 );
+ m_findMethod = new QComboBox(false, groupBox1);
+ m_findMethod->insertItem(i18n("Almost"), MethodAlmost);
+ m_findMethod->insertItem(i18n("Fast"), MethodFast);
+ m_findMethod->setCurrentItem ( MethodAlmost );
+ QWhatsThis::add( m_findMethod, i18n("<p>Select here the search method used to find duplicate "
+ "images in the Albums database.<p>"
+ "<b>Almost</b>: the algorithm calculates an approximate difference between images. "
+ "This method is slower but robust. You can affine the thresholding using the "
+ "\"Approximate Threshold\" parameter.<p>"
+ "<b>Fast</b>: the algorithm compares bit-by-bit the files for fast image parsing. "
+ "This method is faster but is not as robust."));
+ m_labelsearchMethod->setBuddy( m_findMethod );
+
+ (void) new QLabel (i18n("Approximate threshold:"), groupBox1);
+
+ m_approximateThreshold = new KIntNumInput(88, groupBox1);
+ m_approximateThreshold->setRange(60, 100, 1, true );
+ QWhatsThis::add( m_approximateThreshold, i18n("<p>Select here the approximate threshold "
+ "value, as a percentage, for the 'Almost' find-duplicates method. "
+ "This value is used by the algorithm to distinguish two "
+ "similar images. The default value is 88.") );
+ vlay->addWidget( groupBox1 );
+
+ //---------------------------------------------
+
+ QGroupBox * groupBox2 = new QGroupBox( 1, Qt::Horizontal, i18n("Cache Maintenance"), page_setupMethod );
+ new QLabel(i18n("The find-duplicate-images process uses a cache folder for images' fingerprints\n"
+ "to speed up the analysis of items from Albums."), groupBox2);
+
+ QPushButton* updateCache = new QPushButton( groupBox2, "UpdateCache" );
+ updateCache->setText(i18n( "&Update Cache" ));
+ QWhatsThis::add( updateCache, i18n("<p>Update the cache data for the selected Albums.") );
+ QPushButton* purgeCache = new QPushButton( groupBox2, "PurgeCacheAlbumsSelected" );
+ purgeCache->setText(i18n( "&Purge Cache (Albums Selected)" ));
+ QWhatsThis::add( purgeCache, i18n("<p>Purge the cache data for the selected Albums.") );
+ QPushButton* purgeAllCache = new QPushButton( groupBox2, "PurgeAllCache" );
+ purgeAllCache->setText(i18n( "&Purge All Caches" ));
+ QWhatsThis::add( purgeAllCache, i18n("<p>Purge the cache data for all Albums.") );
+ vlay->addWidget( groupBox2 );
+
+ vlay->addStretch(1);
+
+ //---------------------------------------------
+
+ connect(m_findMethod, SIGNAL(activated(int)),
+ this, SLOT(slotfindMethodChanged(int)));
+
+ connect(updateCache, SIGNAL(clicked()),
+ this, SLOT(slotUpdateCache()));
+
+ connect(purgeCache, SIGNAL(clicked()),
+ this, SLOT(slotPurgeCache()));
+
+ connect(purgeAllCache, SIGNAL(clicked()),
+ this, SLOT(slotPurgeAllCache()));
+
+ slotfindMethodChanged(m_findMethod->currentItem());
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("findduplicateimages",
+ "kipi-plugins");
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::slotfindMethodChanged(int index)
+{
+ if ( index == MethodAlmost )
+ m_approximateThreshold->setEnabled(true);
+ else
+ m_approximateThreshold->setEnabled(false);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::slotUpdateCache(void)
+{
+ QValueList<KIPI::ImageCollection> albumsList = getSelectedAlbums();
+ QStringList albumsListPath;
+
+ for( QValueList<KIPI::ImageCollection>::ConstIterator album = albumsList.begin() ;
+ album != albumsList.end() ; ++album )
+ {
+ if ( !albumsListPath.contains( (*album).path().path() ) )
+ albumsListPath.append( (*album).path().path() );
+ }
+
+ if ( albumsListPath.isEmpty() == true )
+ KMessageBox::sorry(this, i18n("You must select at least one Album for the update cache process."));
+ else
+ emit updateCache(albumsListPath);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::slotPurgeCache(void)
+{
+ QValueList<KIPI::ImageCollection> albumsList = getSelectedAlbums();
+
+ QStringList albumsListPath;
+
+ for( QValueList<KIPI::ImageCollection>::ConstIterator album = albumsList.begin() ;
+ album != albumsList.end() ; ++album )
+ {
+ if ( !albumsListPath.contains( (*album).path().path() ) )
+ albumsListPath.append( (*album).path().path() );
+ }
+
+ if ( albumsListPath.isEmpty() == true )
+ KMessageBox::sorry(this, i18n("You must select at least one Album for the purge cache process."));
+ else
+ emit clearCache(albumsListPath);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::slotPurgeAllCache(void)
+{
+ emit clearAllCache();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::slotOk()
+{
+ if (getSelectedAlbums().isEmpty() == true)
+ {
+ KMessageBox::sorry(this, i18n("You must select at least one Album for which to find duplicate images."));
+ return;
+ }
+
+ accept();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+QValueList<KIPI::ImageCollection> FindDuplicateDialog::getSelectedAlbums() const
+{
+ return m_imageCollectionSelector->selectedImageCollections();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+int FindDuplicateDialog::getFindMethod() const
+{
+ return m_findMethod->currentItem();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::setFindMethod(int method)
+{
+ return m_findMethod->setCurrentItem( method );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+const int FindDuplicateDialog::getApproximateThreeshold() const
+{
+ return m_approximateThreshold->value();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateDialog::setApproximateThreeshold(int Value)
+{
+ return m_approximateThreshold->setValue( Value );
+}
+
+} // NameSpace KIPIFindDupplicateImagesPlugin
+
diff --git a/kipi-plugins/findimages/finddupplicatedialog.h b/kipi-plugins/findimages/finddupplicatedialog.h
new file mode 100644
index 0000000..c66e661
--- /dev/null
+++ b/kipi-plugins/findimages/finddupplicatedialog.h
@@ -0,0 +1,122 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// FINDDUPPLICATEDIALOG.H
+//
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef FINDDUPPLICATEDIALOG_H
+#define FINDDUPPLICATEDIALOG_H
+
+// Include files for Qt
+
+#include <qstring.h>
+#include <qguardedptr.h>
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+// Include files for KIPI
+
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QComboBox;
+class QFrame;
+class QPushButton;
+
+class KFileItem;
+class KIntNumInput;
+class KSqueezedTextLabel;
+class KListView;
+
+namespace KIPI
+{
+ class ImageCollectionSelector;
+}
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+class FindDuplicateDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ FindDuplicateDialog( KIPI::Interface* interface, QWidget *parent=0);
+ ~FindDuplicateDialog();
+
+ int getFindMethod() const;
+ void setFindMethod(int method);
+
+ const int getApproximateThreeshold() const;
+ void setApproximateThreeshold(int Value);
+
+ QValueList<KIPI::ImageCollection> getSelectedAlbums() const;
+
+ enum FindDuplicateMethod {
+ MethodAlmost = 0,
+ MethodFast = 1
+ };
+
+ signals:
+
+ void updateCache(QStringList fromDir);
+ void clearCache(QStringList fromDir);
+ void clearAllCache(void);
+
+ protected slots:
+
+ void slotOk();
+ void slotUpdateCache(void);
+ void slotPurgeCache(void);
+ void slotPurgeAllCache(void);
+ void slotfindMethodChanged(int method);
+ void slotHelp();
+
+ private:
+
+ QComboBox *m_findMethod;
+
+ QFrame *page_setupSelection;
+ QFrame *page_setupMethod;
+
+ QPushButton *m_helpButton;
+
+ KIntNumInput *m_approximateThreshold;
+
+ KIPI::Interface *m_interface;
+
+ KIPI::ImageCollectionSelector *m_imageCollectionSelector;
+
+ KIPIPlugins::KPAboutData *m_about;
+
+ private :
+
+ void setupSelection(void);
+ void setupPageMethod(void);
+
+};
+
+} // NameSpace KIPIFindDupplicateImagesPlugin
+
+#endif // FINDDUPPLICATEDIALOG_H
diff --git a/kipi-plugins/findimages/finddupplicateimages.cpp b/kipi-plugins/findimages/finddupplicateimages.cpp
new file mode 100644
index 0000000..bbe7b5f
--- /dev/null
+++ b/kipi-plugins/findimages/finddupplicateimages.cpp
@@ -0,0 +1,436 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// FINDDUPPLICATEIMAGES.CPP
+//
+// Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// Include files for C ansi
+
+extern "C"
+{
+#include <stdlib.h>
+#include <math.h>
+}
+
+// Include files for Qt
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qimage.h>
+#include <qprogressdialog.h>
+#include <qmutex.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kinstance.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kimageeffect.h>
+#include <kdebug.h>
+#include <kprogress.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kio/netaccess.h>
+#include <kio/global.h>
+#include <kimageio.h>
+
+// Local include files
+
+#include "finddupplicateimages.h"
+#include "finddupplicatedialog.h"
+#include "displaycompare.h"
+#include "actions.h"
+#include <qcursor.h>
+#include "imagesimilaritydata.h"
+#include "fuzzycompare.h"
+#include "fastcompare.h"
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+
+
+//////////////////////////////////// CONSTRUCTOR ////////////////////////////////////////////
+
+FindDuplicateImages::FindDuplicateImages( KIPI::Interface* interface, QObject *parent)
+ : QObject(parent), QThread(), m_interface( interface ),
+ m_cacheDir(KGlobal::dirs()->saveLocation("cache", "kipi-findduplicate/")),
+ m_compareOp( 0 )
+{
+ KImageIO::registerFormats();
+ parent_ = parent;
+}
+
+
+//////////////////////////////////// DESTRUCTOR /////////////////////////////////////////////
+
+FindDuplicateImages::~FindDuplicateImages()
+{
+ delete m_findDuplicateDialog;
+ wait();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateImages::writeSettings(void)
+{
+ config = new KConfig("kipirc");
+ config->setGroup("FindDuplicateImages Settings");
+
+ // Method dialogbox setup tab
+
+ config->writeEntry("FindMethod", m_findDuplicateDialog->getFindMethod());
+ config->writeEntry("ApproximateThreeshold", m_findDuplicateDialog->getApproximateThreeshold());
+
+ config->sync();
+ delete config;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateImages::readSettings(void)
+{
+ config = new KConfig("kipirc");
+ config->setGroup("FindDuplicateImages Settings");
+
+ // Method dialogbox setup tab
+
+ m_findDuplicateDialog->setFindMethod( config->readNumEntry("FindMethod", FindDuplicateDialog::MethodAlmost ) );
+ m_findDuplicateDialog->setApproximateThreeshold( config->readNumEntry("ApproximateThreeshold", 88) );
+
+ delete config;
+
+ // Get the image files filters from the hosts app.
+
+ m_imagesFileFilter = m_interface->fileExtensions();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+bool FindDuplicateImages::execDialog()
+{
+ qApp->setOverrideCursor( QCursor(Qt::WaitCursor) );
+ m_findDuplicateDialog = new FindDuplicateDialog( m_interface, kapp->activeWindow() );
+ qApp->restoreOverrideCursor();
+
+ readSettings();
+
+ connect( m_findDuplicateDialog, SIGNAL(updateCache(QStringList)),
+ this, SLOT(slotUpdateCache(QStringList)) );
+
+ connect( m_findDuplicateDialog, SIGNAL(clearCache(QStringList)),
+ this, SLOT(slotClearCache(QStringList)) );
+
+ connect( m_findDuplicateDialog, SIGNAL(clearAllCache()),
+ this, SLOT(slotClearAllCache()) );
+
+ if ( m_findDuplicateDialog->exec() == QDialog::Accepted )
+ {
+ // This is the value for approximate comparison level between 2 images.
+ m_approximateLevel = (float) m_findDuplicateDialog->getApproximateThreeshold() / (float)100;
+
+ writeSettings();
+ return true;
+ }
+
+ return false;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateImages::showResult()
+{
+ if( !m_res.isEmpty() )
+ DisplayCompare((QWidget *)(kapp->activeWindow()), m_interface, m_res).exec();
+ else
+ KMessageBox::information(kapp->activeWindow(), i18n("No identical files found"));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateImages::compareAlbums(void)
+{
+ qApp->setOverrideCursor( QCursor(Qt::WaitCursor) );
+
+ writeSettings();
+
+ // Prepare the data for the threaded operations.
+
+ QValueList<KIPI::ImageCollection> ListAlbums(m_findDuplicateDialog->getSelectedAlbums());
+ filesList.clear();
+
+ for( QValueList<KIPI::ImageCollection>::Iterator it = ListAlbums.begin(); it != ListAlbums.end(); ++it )
+ {
+ KURL::List Files = (*it).images();
+
+ for( KURL::List::Iterator it2 = Files.begin(); it2 != Files.end(); ++it2 )
+ {
+ if ( !filesList.contains( (*it2).path() ) )
+ {
+ filesList.append( (*it2).path() ); // PENDING(blackie) handle remote URLS
+ }
+ }
+
+ kapp->processEvents();
+ }
+
+ if ( m_findDuplicateDialog->getFindMethod() == FindDuplicateDialog::MethodAlmost )
+ {
+ FuzzyCompare *op = new FuzzyCompare( parent_, m_cacheDir );
+ op->setApproximateThreeshold( m_approximateLevel );
+ m_compareOp = op;
+ }
+ else
+ m_compareOp = new FastCompare( parent_ );
+
+ start(); // Starting the thread.
+
+ qApp->restoreOverrideCursor();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// List of threaded operations.
+
+void FindDuplicateImages::run()
+{
+ m_res = m_compareOp->compare(filesList );
+ sendMessage( parent_, KIPIFindDupplicateImagesPlugin::Progress, QString::null, 0, false, true );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+void FindDuplicateImages::slotClearCache(QStringList fromDirs)
+{
+ bool delOk = true;
+
+ for ( QStringList::Iterator it = fromDirs.begin(); it != fromDirs.end(); ++it )
+ {
+ QString deleteImage = m_cacheDir + *it ;
+
+ if ( DeleteDir(deleteImage) == false )
+ delOk = false;
+ }
+
+ if ( delOk == true )
+ KMessageBox::information(m_findDuplicateDialog, i18n("Selected Albums cache purged successfully!"));
+ else
+ KMessageBox::error(m_findDuplicateDialog, i18n("Cannot purge selected Albums cache!"));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void FindDuplicateImages::slotClearAllCache(void)
+{
+ bool delOk = DeleteDir(m_cacheDir);
+
+ if ( delOk == true )
+ KMessageBox::information(m_findDuplicateDialog, i18n("All cache purged successfully!"));
+ else
+ KMessageBox::error(m_findDuplicateDialog, i18n("Cannot purge all cache!"));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+void FindDuplicateImages::slotUpdateCache(QStringList fromDirs)
+{
+ pdCache = new QProgressDialog (m_findDuplicateDialog, "tmppb", true);
+ pdCache->setLabelText(i18n("Updating in progress..."));
+ pdCache->setTotalSteps(2);
+ pdCache->show();
+ pdCache->setProgress(2);
+
+ for ( QStringList::Iterator it = fromDirs.begin(); it != fromDirs.end(); ++it )
+ updateCache(*it);
+
+ pdCache->close();
+ delete(pdCache);
+ KMessageBox::information(m_findDuplicateDialog, i18n("Selected Albums cache updated successfully!"));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+void FindDuplicateImages::updateCache(QString fromDir)
+{
+ // PENDING(blackie) this method doesn't seem to work.
+
+ kdDebug( 51000 ) << fromDir.ascii() << endl;
+ pdCache->setLabelText(i18n("Updating in progress for:\n") + fromDir);
+ QDir d(m_cacheDir + fromDir);
+ int len = m_cacheDir.length()-1; // Remove trailing /
+ bool delDir = false;
+
+ kdDebug( 51000 ) << m_cacheDir + fromDir.latin1() << endl;
+
+ if ( !QFileInfo(fromDir).exists() )
+ delDir = true; // If the source folder have been removed, remove also the cache...
+
+ d.setFilter( QDir::All | QDir::Hidden | QDir::NoSymLinks );
+ const QFileInfoList *list = d.entryInfoList();
+
+ if ( !list )
+ return;
+
+ QFileInfoListIterator it( *list );
+ QFileInfo *fi;
+
+ while ( (fi = it.current()) != 0 )
+ {
+ kapp->processEvents();
+ QString fCache=fi->absFilePath();
+ QString orgFile=fCache.right(fCache.length()-len);
+
+ if ( fi->isDir() && !fromDir.startsWith(orgFile) )
+ {
+ updateCache(orgFile);
+ }
+ else
+ {
+ if ( !QFileInfo(orgFile).exists() && QFileInfo(orgFile).extension(false) != "dat" )
+ {
+ QDir().remove(fCache);
+ QDir().remove(fCache + ".dat");
+ }
+ }
+ ++it;
+ }
+
+ if (delDir)
+ QDir().rmdir(m_cacheDir + fromDir);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+float FindDuplicateImages::image_sim_compare(ImageSimilarityData *a, ImageSimilarityData *b)
+{
+ float sim;
+ int i;
+
+ if ( !a || !b || !a->filled || !b->filled )
+ return 0.0;
+
+ sim = 0.0;
+
+ for( i = 0; i < PAS*PAS; i++ )
+ {
+ sim += (float)abs(a->avg_r[i] - b->avg_r[i]) / 255.0;
+ sim += (float)abs(a->avg_g[i] - b->avg_g[i]) / 255.0;
+ sim += (float)abs(a->avg_b[i] - b->avg_b[i]) / 255.0;
+ }
+
+ sim /= (1024.0 * 3.0);
+ return 1.0 - sim;
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool FindDuplicateImages::DeleteDir(QString dirname)
+{
+ if ( !dirname.isEmpty() )
+ {
+ QDir dir;
+
+ if (dir.exists ( dirname ) == true)
+ {
+ if (deldir(dirname) == false)
+ return false;
+
+ if (dir.rmdir( dirname ) == false )
+ return false;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool FindDuplicateImages::deldir(QString dirname)
+{
+ QDir *dir = new QDir(dirname);
+ dir->setFilter ( QDir::Dirs | QDir::Files | QDir::NoSymLinks );
+
+ const QFileInfoList* fileinfolist = dir->entryInfoList();
+ QFileInfoListIterator it(*fileinfolist);
+ QFileInfo* fi;
+
+ while( (fi = it.current() ) )
+ {
+ if(fi->fileName() == "." || fi->fileName() == ".." )
+ {
+ ++it;
+ continue;
+ }
+
+ if( fi->isDir() )
+ {
+ if (deldir( fi->absFilePath() ) == false)
+ return false;
+ if (dir->rmdir( fi->absFilePath() ) == false)
+ return false;
+ }
+ else
+ if( fi->isFile() )
+ if (dir->remove(fi->absFilePath() ) == false)
+ return false;
+
+ kapp->processEvents();
+ ++it;
+ }
+
+ return true;
+}
+
+} // NameSpace KIPIFindDupplicateImagesPlugin
+
+void KIPIFindDupplicateImagesPlugin::FindDuplicateImages::stopPlease()
+{
+ if ( m_compareOp )
+ m_compareOp->stopPlease();
+}
+
+#include "finddupplicateimages.moc"
diff --git a/kipi-plugins/findimages/finddupplicateimages.h b/kipi-plugins/findimages/finddupplicateimages.h
new file mode 100644
index 0000000..04d35fb
--- /dev/null
+++ b/kipi-plugins/findimages/finddupplicateimages.h
@@ -0,0 +1,103 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// FINDDUPPLICATEIMAGES.H
+//
+// Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef FINDDUPPLICATEIMAGES_H
+#define FINDDUPPLICATEIMAGES_H
+
+// Include files for Qt
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qthread.h>
+#include <qstringlist.h>
+#include <qptrvector.h>
+#include <qdict.h>
+
+// Includes file for libKIPI.
+
+#include <libkipi/interface.h>
+
+class QProgressDialog;
+class QFile;
+class QCustomEvent;
+class QMutex;
+
+class KConfig;
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+
+class ImageSimilarityData;
+class FindDuplicateDialog;
+class CompareOperation;
+
+class FindDuplicateImages : public QObject, public QThread
+{
+ Q_OBJECT
+
+public:
+ FindDuplicateImages( KIPI::Interface* interface, QObject *parent=0);
+ ~FindDuplicateImages();
+
+ virtual void run();
+
+ bool execDialog();
+ void showResult();
+ void compareAlbums();// Launch the dialog box for Albums selection before comparison.
+ void stopPlease();
+
+public slots:
+ void slotUpdateCache(QStringList fromDirs);
+ void slotClearCache(QStringList fromDir);
+ void slotClearAllCache(void);
+
+protected:
+ KConfig *config;
+ QString m_imagesFileFilter;
+ QProgressDialog *pdCache;
+ FindDuplicateDialog *m_findDuplicateDialog;
+ float m_approximateLevel;
+
+ float image_sim_compare(ImageSimilarityData *a, ImageSimilarityData *b);
+ void writeSettings(void);
+ void readSettings(void);
+ void updateCache(QString fromDir);
+ bool DeleteDir(QString dirname);
+ bool deldir(QString dirname);
+
+ QStringList filesList;
+ QObject *parent_;
+ QDict < QPtrVector < QFile > > m_res;
+ KIPI::Interface* m_interface;
+ QString m_cacheDir;
+
+private:
+ CompareOperation* m_compareOp;
+};
+
+} // NameSpace KIPIFindDupplicateImagesPlugin
+
+#endif // FINDDUPPLICATEIMAGES_H
+
diff --git a/kipi-plugins/findimages/fuzzycompare.cpp b/kipi-plugins/findimages/fuzzycompare.cpp
new file mode 100644
index 0000000..50da23b
--- /dev/null
+++ b/kipi-plugins/findimages/fuzzycompare.cpp
@@ -0,0 +1,344 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// FINDDUPPLICATEIMAGES.CPP
+//
+// Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include "fuzzycompare.h"
+#include "actions.h"
+#include <qstringlist.h>
+#include <qapplication.h>
+#include <kdebug.h>
+#include "imagesimilaritydata.h"
+#include <qdatetime.h>
+#include <qfileinfo.h>
+#include "finddupplicateimages.h"
+#include <qimage.h>
+#include <kimageio.h>
+#include <kimageeffect.h>
+#include <kstandarddirs.h>
+#include <math.h>
+
+KIPIFindDupplicateImagesPlugin::FuzzyCompare::FuzzyCompare( QObject* parent, const QString& cacheDir )
+ :m_parent( parent ), m_cacheDir( cacheDir )
+{
+}
+
+QDict < QPtrVector < QFile > > KIPIFindDupplicateImagesPlugin::FuzzyCompare::compare( const QStringList& filesList )
+{
+ sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::Progress, QString::null, filesList.count()*2, true, false );
+
+ kdDebug( 51000 ) << filesList.count() << " images to parse with Almost method..." << endl;
+ QDict < QPtrVector < QFile > > res;
+
+ QPtrVector < ImageSimilarityData > *listRatW = new QPtrVector < ImageSimilarityData >;
+ QPtrVector < ImageSimilarityData > *listRatH = new QPtrVector < ImageSimilarityData >;
+ QPtrVector < ImageSimilarityData > *list;
+ listRatW->setAutoDelete(true);
+ listRatH->setAutoDelete(true);
+
+ QTime debut=QTime::currentTime ();
+ ImageSimilarityData *is;
+
+ for ( QStringList::ConstIterator item = filesList.begin() ; item != filesList.end() ; ++item )
+ {
+ if ( m_stopRequested )
+ return QDict < QPtrVector < QFile > >();
+
+ QString itemName(*item);
+ QFileInfo fi(itemName);
+ QString Temp = fi.dirPath();
+ QString albumName = Temp.section('/', -1);
+
+ sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::Matrix, itemName, 0, true, false );
+
+ if( (is = image_sim_fill_data( itemName )) != NULL )
+ {
+ if ( is->ratio > 1 )
+ list = listRatW;
+ else
+ list = listRatH;
+
+ list->resize (list->size () + 1);
+ list->insert (list->size () - 1, is );
+
+ // sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::Matrix, itemName, 0, false, true );
+ }
+ else
+ sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::Matrix, itemName, 0, false, false );
+ }
+
+ kdDebug( 51000 ) << "Matrix creation time:" << debut.msecsTo(QTime::currentTime()) << endl;
+ debut = QTime::currentTime ();
+
+ QDict < QFile > *fait = new QDict < QFile >;
+ list = listRatW;
+ bool done = false;
+
+ while( list != NULL )
+ {
+ if (list->size () != 1)
+ {
+ for (unsigned int i = 0; i < list->size (); i++)
+ {
+ if ( m_stopRequested )
+ return QDict < QPtrVector < QFile > >();
+
+ // Create the 'ImageSimilarityData' data for the first image.
+ ImageSimilarityData *i1 = list->at(i);
+
+ if (i1 && !fait->find(i1->filename))
+ {
+ sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::Similar, i1->filename, 0, true, false );
+
+ for (unsigned int j = i + 1; j < list->size (); j++)
+ {
+ // Create the 'ImageSimilarityData' data for the second image.
+ ImageSimilarityData *i2 = list->at(j);
+
+ // Real images file comparison calculation.
+ float eq = image_sim_compare_fast(i1, i2, m_approximateLevel);
+
+ if (eq >= m_approximateLevel) // the files are the same !
+ {
+ QPtrVector < QFile > *vect;
+
+ // Add file to the list.
+ if (!res.find (i1->filename))
+ {
+ vect = new QPtrVector < QFile >;
+ vect->setAutoDelete(true);
+ res.insert (i1->filename, vect);
+ }
+ else
+ vect = (QPtrVector < QFile > *)res.find(i1->filename);
+
+ vect->resize (vect->size () + 1);
+ vect->insert (vect->size () - 1, new QFile(i2->filename));
+ fait->insert(i2->filename, new QFile(i2->filename));
+ }
+ }
+ }
+
+ //sendMessage( m_parent, KIPIFindDupplicateImagesPlugin::Similar, i1->filename, 0, false, true );
+ }
+ }
+
+ if(!done)
+ {
+ list = listRatH;
+ done = true;
+ }
+ else
+ list = NULL;
+ }
+
+ kdDebug( 51000 ) << "Comparison time: " << debut.msecsTo(QTime::currentTime()) << endl;
+
+ // End of comparison process.
+
+ delete(fait);
+ delete(listRatH);
+ delete(listRatW);
+
+ return res;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+KIPIFindDupplicateImagesPlugin::ImageSimilarityData* KIPIFindDupplicateImagesPlugin::FuzzyCompare::image_sim_fill_data(QString filename)
+{
+ int w, h;
+ uchar *pix;
+ int has_alpha;
+ int p_step;
+
+ int i,j;
+ int x_inc, y_inc;
+ int xs, ys;
+ const int INC=1;
+
+ QImage *pixbuf;
+ ImageSimilarityData *sd = new ImageSimilarityData();
+ sd->filename=filename;
+
+ QFileInfo info(m_cacheDir + QFileInfo(filename).absFilePath()+".dat");
+
+ if(info.exists())
+ {
+ QFile f(m_cacheDir+QFileInfo(filename).absFilePath()+".dat");
+ if ( f.open(IO_ReadOnly) )
+ {
+ QDataStream s( &f );
+ s >> sd->ratio;
+ for(int i=0 ; i<PAS*PAS ; i++) s >> sd->avg_r[i];
+ for(int i=0 ; i<PAS*PAS ; i++) s >> sd->avg_g[i];
+ for(int i=0 ; i<PAS*PAS ; i++) s >> sd->avg_b[i];
+ f.close();
+ }
+
+ sd->filled = true;
+ return sd;
+ }
+
+ pixbuf = new QImage(filename);
+
+ if ( !sd || !pixbuf )
+ return 0L;
+
+ KImageEffect::equalize(*pixbuf);
+
+ w = pixbuf->width();
+ h = pixbuf->height();
+ pix = pixbuf->bits();
+ has_alpha = pixbuf->hasAlphaBuffer();
+ p_step = has_alpha ? 4 : 3;
+
+ x_inc = w / PAS;
+ y_inc = h / PAS;
+
+ if ( x_inc < 1 || y_inc < 1 )
+ return 0L;
+
+ j = 0;
+
+ for (ys = 0; ys < PAS; ys++)
+ {
+ i = 0;
+
+ for (xs = 0; xs < PAS; xs++)
+ {
+ int x, y;
+ int r, g, b;
+ r = g = b = 0;
+
+ for (y = j; y < j + y_inc; y+=INC)
+ {
+ for (x = i; x < i + x_inc; x+=INC)
+ {
+ r += getRed(pixbuf, x, y);
+ g += getGreen(pixbuf, x, y);
+ b += getBlue(pixbuf, x, y);
+ }
+ }
+
+ r /= x_inc * y_inc;
+ g /= x_inc * y_inc;
+ b /= x_inc * y_inc;
+
+ sd->avg_r[ys * PAS + xs] = r;
+ sd->avg_g[ys * PAS + xs] = g;
+ sd->avg_b[ys * PAS + xs] = b;
+
+ i += x_inc;
+ }
+ j += y_inc;
+ }
+
+ sd->filled = true;
+ sd->ratio=((float)w)/h;
+ delete(pixbuf);
+
+ // Saving the data.
+
+ QFile f(m_cacheDir+QFileInfo(filename).absFilePath()+".dat");
+ KStandardDirs::makeDir(QFileInfo(f).dirPath(true));
+
+ if ( f.open(IO_WriteOnly) )
+ {
+ QDataStream s( &f );
+ s << sd->ratio;
+ for(int i=0 ; i<PAS*PAS ; i++) s << sd->avg_r[i];
+ for(int i=0 ; i<PAS*PAS ; i++) s << sd->avg_g[i];
+ for(int i=0 ; i<PAS*PAS ; i++) s << sd->avg_b[i];
+ f.close();
+ }
+
+ return sd;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+float KIPIFindDupplicateImagesPlugin::FuzzyCompare::image_sim_compare_fast(ImageSimilarityData *a, ImageSimilarityData *b, float min)
+{
+ float sim;
+ int i, j;
+
+ if ( !a || !b || !a->filled || !b->filled )
+ return 0.0;
+
+ if( fabs(a->ratio - b->ratio) > 0.1 )
+ return 0.0;
+
+ min = 1.0 - min;
+ sim = 0.0;
+
+ for ( j = 0; j < PAS*PAS; j+= PAS )
+ {
+ for ( i = j; i < j + PAS; i++ )
+ {
+ sim += (float)abs(a->avg_r[i] - b->avg_r[i]) / 255.0;
+ sim += (float)abs(a->avg_g[i] - b->avg_g[i]) / 255.0;
+ sim += (float)abs(a->avg_b[i] - b->avg_b[i]) / 255.0;
+ }
+
+ // check for abort, if so return 0.0
+
+ if ( j > PAS*PAS/3 && 1-sim/((j+1) * 3.0) < min )
+ return 0.0;
+ }
+
+ sim /= (PAS*PAS * 3.0);
+
+ return 1.0 - sim;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+char KIPIFindDupplicateImagesPlugin::FuzzyCompare::getRed(QImage* im, int x, int y)
+{
+ return qRed(im->pixel(x, y));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+char KIPIFindDupplicateImagesPlugin::FuzzyCompare::getGreen(QImage* im, int x, int y)
+{
+ return qGreen(im->pixel(x, y));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+
+char KIPIFindDupplicateImagesPlugin::FuzzyCompare::getBlue(QImage* im, int x, int y)
+{
+ return qBlue(im->pixel(x, y));
+}
+
+
diff --git a/kipi-plugins/findimages/fuzzycompare.h b/kipi-plugins/findimages/fuzzycompare.h
new file mode 100644
index 0000000..77a264a
--- /dev/null
+++ b/kipi-plugins/findimages/fuzzycompare.h
@@ -0,0 +1,64 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// FUZZYCOMPARE.CPP
+//
+// Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef FUZZYCOMPARE_H
+#define FUZZYCOMPARE_H
+
+class QImage;
+class QObject;
+class QStringList;
+#include <qdict.h>
+#include <qptrvector.h>
+#include <qfile.h>
+#include "compareoperation.h"
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+class FindDuplicateImages;
+class ImageSimilarityData;
+
+class FuzzyCompare :public CompareOperation
+{
+public:
+ FuzzyCompare( QObject* parent, const QString& cacheDir );
+ void setApproximateThreeshold( float approximateLevel ) { m_approximateLevel = approximateLevel; }
+ QDict < QPtrVector < QFile > > compare(const QStringList& filesList );
+
+protected:
+ ImageSimilarityData* image_sim_fill_data(QString filename);
+ float image_sim_compare_fast(ImageSimilarityData *a, ImageSimilarityData *b, float min);
+ char getRed(QImage *im, int x, int y);
+ char getGreen(QImage *im, int x, int y);
+ char getBlue(QImage *im, int x, int y);
+
+private:
+ QObject* m_parent;
+ const QString m_cacheDir;
+ float m_approximateLevel;
+};
+
+}
+
+#endif /* FUZZYCOMPARE_H */
+
diff --git a/kipi-plugins/findimages/hi32-action-finddupplicateimages.png b/kipi-plugins/findimages/hi32-action-finddupplicateimages.png
new file mode 100644
index 0000000..843ff2b
--- /dev/null
+++ b/kipi-plugins/findimages/hi32-action-finddupplicateimages.png
Binary files differ
diff --git a/kipi-plugins/findimages/imagesimilaritydata.h b/kipi-plugins/findimages/imagesimilaritydata.h
new file mode 100644
index 0000000..55c6712
--- /dev/null
+++ b/kipi-plugins/findimages/imagesimilaritydata.h
@@ -0,0 +1,74 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// FINDDUPPLICATEIMAGES.CPP
+//
+// Copyright (C) 2001 Richard Groult <rgroult at jalix.org> (from ShowImg project)
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef IMAGESIMILARITYDATA_H
+#define IMAGESIMILARITYDATA_H
+
+#define PAS 32
+
+extern "C"
+{
+#include <stdlib.h>
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Nota: original source code from ShowImg !
+// A class to store data to look for similarities of 2 images.
+
+namespace KIPIFindDupplicateImagesPlugin
+{
+
+class ImageSimilarityData
+{
+public:
+ ImageSimilarityData()
+ {
+ avg_r = (uchar*)malloc(PAS*PAS*sizeof(uchar));
+ avg_g = (uchar*)malloc(PAS*PAS*sizeof(uchar));
+ avg_b = (uchar*)malloc(PAS*PAS*sizeof(uchar));
+ }
+
+ ~ImageSimilarityData()
+ {
+ free(avg_r);
+ free(avg_g);
+ free(avg_b);
+ }
+
+ QString filename;
+
+ uchar *avg_r;
+ uchar *avg_g;
+ uchar *avg_b;
+
+ int filled;
+ float ratio;
+};
+
+}
+
+
+#endif /* IMAGESIMILARITYDATA_H */
+
diff --git a/kipi-plugins/findimages/kipiplugin_findimages.desktop b/kipi-plugins/findimages/kipiplugin_findimages.desktop
new file mode 100644
index 0000000..b0951c5
--- /dev/null
+++ b/kipi-plugins/findimages/kipiplugin_findimages.desktop
@@ -0,0 +1,59 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=FindImages
+Name[br]=Klask skeudennoù
+Name[ca]=Cerca d'imatges
+Name[cs]=Vyhledání obrázků
+Name[da]=Søg billeder
+Name[de]=Bilder suchen
+Name[el]=ΑναζήτησηΕικόνων
+Name[es]=Encontrar imágenes
+Name[et]=Piltide otsimine
+Name[fi]=Etsi kuvia
+Name[gl]=Procurar Imaxes
+Name[is]=FinnaMyndir
+Name[it]=TrovaImmagini
+Name[nds]=Bildsöök
+Name[nl]=AfbeeldingenZoeken
+Name[pa]=ਚਿੱਤਰ ਖੋਜ
+Name[pl]=Znajdź zdjęcia
+Name[pt]=Procurar Imagens
+Name[sr]=Нађи слике
+Name[sr@Latn]=Nađi slike
+Name[sv]=Sök bilder
+Name[tg]=ҶустуҷӯиТасвирҳо
+Name[tr]=ResimBul
+Name[xx]=xxFindImagesxx
+Name[zh_CN]=查找图像
+Comment=KIPI Plugin for Finding Images
+Comment[br]=Lugent KIPI evit kavout skeudennoù
+Comment[ca]=Connector KIPI per cercar imatges
+Comment[cs]=KIPI modul pro vyhledávání obrázků
+Comment[da]=KIPI-plugin: Søg billeder
+Comment[de]=Ein KIPI-Modul zum Suchen von Bildern
+Comment[el]=Πρόσθετο του KIPI για αναζήτηση εικόνων
+Comment[es]=Complemento de KIPI para encontrar imágenes
+Comment[et]=KIPI piltide otsimise plugin
+Comment[fi]=Kipi-liitännäinen kuvien etsimiseen
+Comment[fr]=Module externe KIPI pour rechercher des images semblables
+Comment[gl]=Plugin de KIPI para Atopar Imaxes
+Comment[is]=KIPI íforrit til að leita að myndum
+Comment[it]=Plugin di KIPI per trovare immagini
+Comment[ja]=Kipi 画像検索プラグイン
+Comment[nds]=KIPI-Moduul för't Söken na Biller
+Comment[nl]=KIPI-plugin voor het zoeken naar afbeeldingen
+Comment[pa]=ਚਿੱਤਰ ਖੋਜ ਲਈ KIPI ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Wyszukiwanie zdjęć
+Comment[pt]='Plugin' do KIPI para Procurar Imagens
+Comment[pt_BR]=Plugin para Encontrar Imagens do KIPI
+Comment[sr]=KIPI прикључак за налажење слика
+Comment[sr@Latn]=KIPI priključak za nalaženje slika
+Comment[sv]=KIPI-insticksprogram för att söka bilder
+Comment[tg]=Модули KIPI барои ҷустуҷӯи тасвирҳо
+Comment[tr]=Resim Bulmak İçin KIPI Eklentisi
+Comment[xx]=xxKIPI Plugin for Finding Imagesxx
+Comment[zh_CN]=KIPI 查找图像插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_findimages
+author=Caulier Gilles, caulier dot gilles at gmail dot com
diff --git a/kipi-plugins/findimages/plugin_findimages.cpp b/kipi-plugins/findimages/plugin_findimages.cpp
new file mode 100644
index 0000000..6fba820
--- /dev/null
+++ b/kipi-plugins/findimages/plugin_findimages.cpp
@@ -0,0 +1,311 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// PLUGIN_FINDIMAGES.CPP
+//
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// Qt includes.
+
+#include <qfileinfo.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kdeversion.h>
+
+// Lib KIPI includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/batchprogressdialog.h>
+
+// Local include files
+
+#include "finddupplicateimages.h"
+#include "actions.h"
+#include "plugin_findimages.h"
+#include <qcursor.h>
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+typedef KGenericFactory<Plugin_FindImages> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_findimages,
+ Factory("kipiplugin_findimages"))
+
+ Plugin_FindImages::Plugin_FindImages(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "FindImages")
+{
+ kdDebug( 51001 ) << "Plugin_FindImages plugin loaded" << endl;
+}
+
+void Plugin_FindImages::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_action_findDuplicateImages = new KAction(i18n("&Find Duplicate Images..."),
+ "finddupplicateimages",
+ 0,
+ this,
+ SLOT(slotFindDuplicateImages()),
+ actionCollection(),
+ "findduplicateimages");
+
+ addAction( m_action_findDuplicateImages );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Plugin_FindImages::~Plugin_FindImages()
+{
+}
+
+
+/////////////////////////////////////// SLOTS ///////////////////////////////////////////////////////
+
+void Plugin_FindImages::slotFindDuplicateImages()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ m_findDuplicateOperation = new KIPIFindDupplicateImagesPlugin::FindDuplicateImages( interface, this);
+
+ if (m_findDuplicateOperation->execDialog())
+ {
+ m_progressDlg = new KIPI::BatchProgressDialog(kapp->activeWindow(), i18n("Find Duplicate Images"));
+
+ connect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+ m_progressDlg->show();
+ m_findDuplicateOperation->compareAlbums();
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_FindImages::slotCancel()
+{
+ m_findDuplicateOperation->stopPlease();
+ m_findDuplicateOperation->wait();
+
+ if (m_progressDlg)
+ {
+ m_progressDlg->reset();
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_FindImages::customEvent(QCustomEvent *event)
+{
+ if (!event) return;
+
+ KIPIFindDupplicateImagesPlugin::EventData *d = (KIPIFindDupplicateImagesPlugin::EventData*) event->data();
+
+ if (!d) return;
+
+ if (d->starting)
+ {
+ QString text;
+
+ switch (d->action)
+ {
+ case(KIPIFindDupplicateImagesPlugin::Similar):
+ {
+ text = i18n("Similar comparison for '%1'").arg(QFileInfo(d->fileName).fileName() );
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::Exact):
+ {
+ m_total = d->total; // Needed because the total can change in this mode !
+ text = i18n("Exact comparison for '%1'").arg(QFileInfo(d->fileName).fileName());
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::Matrix):
+ {
+ text = i18n("Creating fingerprint for '%1'").arg(QFileInfo(d->fileName).fileName());
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::FastParsing):
+ {
+ text = i18n("Fast parsing for '%1'").arg(QFileInfo(d->fileName).fileName());
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::Progress):
+ {
+ m_total = d->total;
+ text = i18n("Checking 1 image...", "Checking %n images...", (int)(d->total/2));
+ break;
+ }
+
+ default:
+ {
+ kdWarning( 51000 ) << "Plugin_FindImages: Unknown starting event: " << d->action << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::StartingMessage);
+ }
+ else
+ {
+ if (!d->success)
+ {
+ QString text;
+
+ switch (d->action)
+ {
+ case(KIPIFindDupplicateImagesPlugin::Matrix):
+ {
+ text = i18n("Failed to create fingerprint for '%1'")
+ .arg(QFileInfo(d->fileName).fileName());
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::Similar):
+ {
+ text = i18n("Failed to find similar images.");
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::Exact):
+ {
+ text = i18n("Failed to find exact image.");
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::Progress):
+ {
+ m_total = d->total;
+ text = i18n("Failed to check images...");
+ break;
+ }
+
+ default:
+ {
+ kdWarning( 51000 ) << "Plugin_FindImages: Unknown failed event: " << d->action << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::WarningMessage);
+ }
+ else
+ {
+ QString text;
+
+ switch (d->action)
+ {
+ case(KIPIFindDupplicateImagesPlugin::Matrix):
+ {
+ text = i18n("Fingerprint created for '%1'")
+ .arg(QFileInfo(d->fileName).fileName());
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::FastParsing):
+ {
+ text = i18n("Fast parsing completed for '%1'")
+ .arg(QFileInfo(d->fileName).fileName());
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::Similar):
+ {
+ text = i18n("Finding similar images for '%1' completed.")
+ .arg(QFileInfo(d->fileName).fileName());
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::Exact):
+ {
+ text = i18n("Finding exact images for '%1' completed.")
+ .arg(QFileInfo(d->fileName).fileName());
+ break;
+ }
+
+ case(KIPIFindDupplicateImagesPlugin::Progress):
+ {
+ m_total = d->count; // We are done, so update m_total to ensure that the bar displays 100%
+ text = i18n("Checking images complete...");
+ break;
+ }
+
+ default:
+ {
+ kdWarning( 51000 ) << "Plugin_FindImages: Unknown success event: " << d->action << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::SuccessMessage);
+ }
+
+
+ if( d->action == KIPIFindDupplicateImagesPlugin::Progress )
+ {
+#if KDE_VERSION >= 0x30200
+ m_progressDlg->setButtonCancel( KStdGuiItem::close() );
+#else
+ m_progressDlg->setButtonCancelText( i18n("&Close") );
+#endif
+
+ disconnect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+
+ m_progressDlg->addedAction(i18n("Displaying results..."),
+ KIPI::StartingMessage);
+
+ m_findDuplicateOperation->showResult();
+ }
+ }
+
+ m_progressDlg->setProgress(d->count, m_total);
+ kapp->processEvents();
+
+ delete d;
+}
+
+KIPI::Category Plugin_FindImages::category( KAction* action ) const
+{
+ if ( action == m_action_findDuplicateImages )
+ return KIPI::COLLECTIONSPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::COLLECTIONSPLUGIN; // no warning from compiler, please
+}
+
+
+#include "plugin_findimages.moc"
diff --git a/kipi-plugins/findimages/plugin_findimages.h b/kipi-plugins/findimages/plugin_findimages.h
new file mode 100644
index 0000000..8bc0344
--- /dev/null
+++ b/kipi-plugins/findimages/plugin_findimages.h
@@ -0,0 +1,75 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// PLUGIN_FINDIMAGES.H
+//
+// Copyright (C) 2004 Gilles Caulier <caulier dot gilles at gmail dot com>
+// Copyright (C) 2004 Richard Groult <rgroult at jalix.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef PLUGIN_FINDIMAGES_H
+#define PLUGIN_FINDIMAGES_H
+
+// LibKipi includes.
+
+#include <libkipi/plugin.h>
+
+class QCustomEvent;
+
+class KActionMenu;
+class KAction;
+
+namespace KIPI
+{
+class BatchProgressDialog;
+}
+
+class FindDuplicateImages;
+
+class Plugin_FindImages : public KIPI::Plugin
+{
+Q_OBJECT
+
+public:
+
+ Plugin_FindImages(QObject *parent, const char* name, const QStringList &args);
+ ~Plugin_FindImages();
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+private:
+
+ KAction *m_action_findDuplicateImages;
+
+protected:
+
+ KIPIFindDupplicateImagesPlugin::FindDuplicateImages *m_findDuplicateOperation;
+
+ KIPI::BatchProgressDialog *m_progressDlg;
+
+ int m_total;
+
+ void customEvent(QCustomEvent *event);
+
+private slots:
+
+ void slotFindDuplicateImages();
+ void slotCancel();
+};
+
+#endif // PLUGIN_FINDIMAGES_H
diff --git a/kipi-plugins/flickrexport/Makefile.am b/kipi-plugins/flickrexport/Makefile.am
new file mode 100644
index 0000000..90d64f4
--- /dev/null
+++ b/kipi-plugins/flickrexport/Makefile.am
@@ -0,0 +1,23 @@
+METASOURCES = AUTO
+
+INCLUDES = $(LIBKEXIV2_CFLAGS) $(LIBKDCRAW_CFLAGS) $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(all_includes)
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_flickrexport.la
+
+kipiplugin_flickrexport_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+
+kipiplugin_flickrexport_la_SOURCES = plugin_flickrexport.cpp imageslist.cpp \
+ flickrwindow.cpp login.cpp flickrtalker.cpp \
+ flickrwidget.cpp mpform.cpp flickralbumdialog.ui \
+ flickrviewitem.cpp
+
+kipiplugin_flickrexport_la_LIBADD = $(LIBKEXIV2_LIBS) $(LIBKDCRAW_LIBS) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_flickrexport_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+kde_services_DATA = kipiplugin_flickrexport.desktop
+
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_flickrexport.pot
diff --git a/kipi-plugins/flickrexport/TODO b/kipi-plugins/flickrexport/TODO
new file mode 100644
index 0000000..98d218c
--- /dev/null
+++ b/kipi-plugins/flickrexport/TODO
@@ -0,0 +1,5 @@
+Could add these things to the plugin.
+ Support for viewing your photos stored at server.
+ Querying Space Limit from the server.
+ Allow fetching feature of images just uploaded, like url etc.
+
diff --git a/kipi-plugins/flickrexport/flickralbumdialog.ui b/kipi-plugins/flickrexport/flickralbumdialog.ui
new file mode 100644
index 0000000..63ac730
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickralbumdialog.ui
@@ -0,0 +1,197 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>KIPIFlickrExportPlugin::FlickrAlbumDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>FlickrAlbumDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>342</width>
+ <height>181</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>New PhotoSet</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>10</number>
+ </property>
+ <property name="spacing">
+ <number>5</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>header</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;h3&gt;Create New PhotoSet &lt;/h3&gt;</string>
+ </property>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>hline1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>titleLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Title (optional):</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>nameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Name (optional):</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>captionLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Caption (optional):</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>titleEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>nameEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>captionEdit</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>hline2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>FlickrAlbumDialog</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>FlickrAlbumDialog</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kipi-plugins/flickrexport/flickritem.h b/kipi-plugins/flickrexport/flickritem.h
new file mode 100644
index 0000000..5179ac8
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickritem.h
@@ -0,0 +1,140 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 FLICKRITEM_H
+#define FLICKRITEM_H
+
+// Qt includes.
+
+#include <qstring.h>
+
+namespace KIPIFlickrExportPlugin
+{
+
+class GPhoto
+{
+
+public:
+
+ GPhoto()
+ {
+// ref_num = -1;
+ }
+
+ bool is_public;
+ bool is_private;
+ bool is_family;
+
+ int ref_num;
+// int album_num;
+
+ QStrList tags;
+ QString title;
+ QString description;
+
+// QString caption;
+// QString thumbName;
+// QString albumURL;
+};
+
+// -------------------------------------------------------------
+
+class FPhotoInfo
+{
+
+public:
+
+ FPhotoInfo()
+ {
+ is_public = false;
+ is_family = false;
+ is_friend = false;
+ }
+
+ bool is_public;
+ bool is_friend;
+ bool is_family;
+
+ QString title;
+ QString description;
+ QStringList tags;
+};
+
+// -------------------------------------------------------------
+
+class GAlbum
+{
+
+public:
+
+ GAlbum()
+ {
+ ref_num = -1;
+ parent_ref_num = -1;
+
+ add = false;
+ write = false;
+ del_item = false;
+ del_alb = false;
+ create_sub = false;
+ }
+
+ bool add;
+ bool write;
+ bool del_item;
+ bool del_alb;
+ bool create_sub;
+
+ int ref_num;
+ int parent_ref_num;
+
+ QString name;
+ QString parentName;
+ QString title;
+ QString summary;
+ QString baseurl;
+};
+
+// -------------------------------------------------------------
+
+class FPhotoSet
+{
+
+public:
+
+ FPhotoSet()
+ {
+ id = "-1";
+ }
+
+ QString id;
+ QString primary; //="2483"
+ QString secret; //="abcdef"
+ QString server;
+ QString photos;
+ QString title;
+ QString description;
+};
+
+} // namespace KIPIFlickrExportPlugin
+
+#endif /* FLICKRITEM_H */
diff --git a/kipi-plugins/flickrexport/flickrtalker.cpp b/kipi-plugins/flickrexport/flickrtalker.cpp
new file mode 100644
index 0000000..f9926fb
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickrtalker.cpp
@@ -0,0 +1,1020 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+// Qt includes.
+
+#include <qcstring.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qimage.h>
+#include <qstringlist.h>
+#include <qlineedit.h>
+#include <qmessagebox.h>
+#include <qdom.h>
+#include <qmap.h>
+#include <qfileinfo.h>
+#include <qprogressdialog.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kstandarddirs.h>
+#include <kmdcodec.h>
+#include <kapp.h>
+#include <kmessagebox.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "mpform.h"
+#include "flickritem.h"
+#include "flickrwindow.h"
+#include "flickrtalker.h"
+#include "flickrtalker.moc"
+
+namespace KIPIFlickrExportPlugin
+{
+
+FlickrTalker::FlickrTalker(QWidget* parent)
+{
+ m_parent = parent;
+ m_job = 0;
+ m_apikey = "49d585bafa0758cb5c58ab67198bf632";
+ m_secret = "34b39925e6273ffd";
+
+ connect(this, SIGNAL(signalAuthenticate()),
+ this, SLOT(slotAuthenticate()));
+}
+
+FlickrTalker::~FlickrTalker()
+{
+ if (m_job)
+ m_job->kill();
+}
+
+/** Compute MD5 signature using url queries keys and values following Flickr notice:
+ http://www.flickr.com/services/api/auth.spec.html
+*/
+QString FlickrTalker::getApiSig(const QString& secret, const KURL& url)
+{
+ QMap<QString, QString> queries = url.queryItems();
+ QString compressed(secret);
+
+ // NOTE: iterator QMap iterator will sort alphabetically items based on key values.
+ for (QMap<QString, QString>::iterator it = queries.begin() ; it != queries.end(); ++it)
+ {
+ compressed.append(it.key());
+ compressed.append(it.data());
+ }
+
+ KMD5 context(compressed.utf8());
+ return context.hexDigest().data();
+}
+
+/**get the Api sig and send it to the server server should return a frob.
+*/
+void FlickrTalker::getFrob()
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ KURL url("http://www.flickr.com/services/rest/");
+ url.addQueryItem("method", "flickr.auth.getFrob");
+ url.addQueryItem("api_key", m_apikey);
+ QString md5 = getApiSig(m_secret, url);
+ url.addQueryItem("api_sig", md5);
+ kdDebug() << "Get frob url: " << url << endl;
+ QByteArray tmp;
+ KIO::TransferJob* job = KIO::http_post(url, tmp, false);
+
+ job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded");
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_GETFROB;
+ m_authProgressDlg->setLabelText(i18n("Getting the Frob"));
+ m_authProgressDlg->setProgress(1, 4);
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy(true);
+}
+
+void FlickrTalker::checkToken(const QString& token)
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ KURL url("http://www.flickr.com/services/rest/");
+ url.addQueryItem("method", "flickr.auth.checkToken");
+ url.addQueryItem("api_key", m_apikey);
+ url.addQueryItem("auth_token", token);
+ QString md5 = getApiSig(m_secret, url);
+ url.addQueryItem("api_sig", md5);
+ kdDebug() << "Check token url: " << url << endl;
+ QByteArray tmp;
+ KIO::TransferJob* job = KIO::http_post(url, tmp, false);
+
+ job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded");
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_CHECKTOKEN;
+ m_authProgressDlg->setLabelText(i18n("Checking if previous token is still valid"));
+ m_authProgressDlg->setProgress(1, 4);
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+}
+
+void FlickrTalker::slotAuthenticate()
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ KURL url("http://www.flickr.com/services/auth/");
+ url.addQueryItem("api_key", m_apikey);
+ url.addQueryItem("frob", m_frob);
+ url.addQueryItem("perms", "write");
+ QString md5 = getApiSig(m_secret, url);
+ url.addQueryItem("api_sig", md5);
+ kdDebug() << "Authenticate url: " << url << endl;
+
+ KApplication::kApplication()->invokeBrowser(url.url());
+ int valueOk = KMessageBox::questionYesNo(kapp->activeWindow(),
+ i18n("Please Follow through the instructions in the browser window and "
+ "return back to press ok if you are authenticated or press No"),
+ i18n("Flickr Service Web Authorization"));
+
+ if( valueOk == KMessageBox::Yes)
+ {
+ getToken();
+ m_authProgressDlg->setLabelText(i18n("Authenticating the User on web"));
+ m_authProgressDlg->setProgress(2, 4);
+ emit signalBusy(false);
+ }
+ else
+ {
+ kdDebug() << "User didn't proceed with getToken Authorization, cannot proceed further, aborting" << endl;
+ cancel();
+ }
+}
+
+void FlickrTalker::getToken()
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ KURL url("http://www.flickr.com/services/rest/");
+ url.addQueryItem("api_key", m_apikey);
+ url.addQueryItem("method", "flickr.auth.getToken");
+ url.addQueryItem("frob", m_frob);
+ QString md5 = getApiSig(m_secret, url);
+ url.addQueryItem("api_sig", md5);
+ kdDebug() << "Get token url: " << url << endl;
+ QByteArray tmp;
+ KIO::TransferJob* job = KIO::http_post(url, tmp, false);
+ job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded");
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_GETTOKEN;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy(true);
+ m_authProgressDlg->setLabelText(i18n("Getting the Token from the server"));
+ m_authProgressDlg->setProgress(3, 4);
+}
+
+void FlickrTalker::listPhotoSets()
+{
+ KURL url("http://www.flickr.com/services/rest/");
+ url.addQueryItem("api_key", m_apikey);
+ url.addQueryItem("method", "flickr.photosets.getList");
+ url.addQueryItem("user_id", m_userId);
+ QString md5 = getApiSig(m_secret, url);
+ url.addQueryItem("api_sig", md5);
+ kdDebug() << "List photo sets url: " << url << endl;
+ QByteArray tmp;
+ KIO::TransferJob* job = KIO::http_post(url, tmp, false);
+ job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_LISTPHOTOSETS;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy(true);
+}
+
+void FlickrTalker::getPhotoProperty(const QString& method, const QStringList& argList)
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ KURL url("http://www.flickr.com/services/rest/");
+ url.addQueryItem("api_key", m_apikey);
+ url.addQueryItem("method", method);
+ url.addQueryItem("frob", m_frob);
+
+ for (QStringList::const_iterator it = argList.begin(); it != argList.end(); ++it)
+ {
+ QStringList str = QStringList::split("=", (*it));
+ url.addQueryItem(str[0], str[1]);
+ }
+
+ QString md5 = getApiSig(m_secret, url);
+ url.addQueryItem("api_sig", md5);
+ kdDebug() << "Get photo property url: " << url << endl;
+ QByteArray tmp;
+ KIO::TransferJob* job = KIO::http_post(url, tmp, false);
+ job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_GETPHOTOPROPERTY;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+
+// m_authProgressDlg->setLabelText("Getting the Token from the server");
+// m_authProgressDlg->setProgress(3,4);
+}
+void FlickrTalker::listPhotos(const QString& /*albumName*/)
+{
+ // TODO
+}
+
+void FlickrTalker::createAlbum(const QString& /*parentAlbumName*/, const QString& /*albumName*/,
+ const QString& /*albumTitle*/, const QString& /*albumCaption*/)
+{
+ //TODO: The equivalent for Album is sets.
+}
+
+bool FlickrTalker::addPhoto(const QString& photoPath, const FPhotoInfo& info,
+ bool rescale, int maxDim, int imageQuality)
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ KURL url("http://www.flickr.com/services/upload/");
+ QString path = photoPath;
+ MPForm form;
+
+ form.addPair("auth_token", m_token);
+ url.addQueryItem("auth_token", m_token);
+
+ form.addPair("api_key", m_apikey);
+ url.addQueryItem("api_key", m_apikey);
+
+ QString ispublic = (info.is_public == 1) ? "1" : "0";
+ form.addPair("is_public", ispublic);
+ url.addQueryItem("is_public", ispublic);
+
+ QString isfamily = (info.is_family == 1) ? "1" : "0";
+ form.addPair("is_family", isfamily);
+ url.addQueryItem("is_family", isfamily);
+
+ QString isfriend = (info.is_friend == 1) ? "1" : "0";
+ form.addPair("is_friend", isfriend);
+ url.addQueryItem("is_friend", isfriend);
+
+ QString tags = info.tags.join(" ");
+ if(tags.length() > 0)
+ {
+ form.addPair("tags", tags);
+ url.addQueryItem("tags", tags);
+ }
+
+ if (!info.title.isEmpty())
+ {
+ form.addPair("title", info.title);
+ url.addQueryItem("title", info.title);
+ }
+
+ if (!info.description.isEmpty())
+ {
+ form.addPair("description", info.description);
+ url.addQueryItem("description", info.description);
+ }
+
+ QString md5 = getApiSig(m_secret, url);
+ form.addPair("api_sig", md5);
+ url.addQueryItem("api_sig", md5);
+ QImage image;
+
+ // Check if RAW file.
+#if KDCRAW_VERSION < 0x000106
+ QString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles());
+#else
+ QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
+#endif
+ QFileInfo fileInfo(photoPath);
+ if (rawFilesExt.upper().contains(fileInfo.extension(false).upper()))
+ KDcrawIface::KDcraw::loadDcrawPreview(image, photoPath);
+ else
+ image.load(photoPath);
+
+ kdDebug() << "Add photo query: " << url << endl;
+
+ if (!image.isNull())
+ {
+ path = locateLocal("tmp", QFileInfo(photoPath).baseName().stripWhiteSpace() + ".jpg");
+
+ if (rescale && (image.width() > maxDim || image.height() > maxDim))
+ image = image.smoothScale(maxDim, maxDim, QImage::ScaleMin);
+
+ image.save(path, "JPEG", imageQuality);
+
+ // Restore all metadata.
+
+ KExiv2Iface::KExiv2 exiv2Iface;
+
+ if (exiv2Iface.load(photoPath))
+ {
+ exiv2Iface.setImageDimensions(image.size());
+
+ // NOTE: see B.K.O #153207: Flickr use IPTC keywords to create Tags in web interface
+ // As IPTC do not support UTF-8, we need to remove it.
+ exiv2Iface.removeIptcTag("Iptc.Application2.Keywords", false);
+
+ exiv2Iface.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+ exiv2Iface.save(path);
+ }
+ else
+ {
+ kdWarning(51000) << "(flickrExport::Image doesn't have metdata)" << endl;
+ }
+
+ kdDebug() << "Resizing and saving to temp file: " << path << endl;
+ }
+
+ if (!form.addFile("photo", path))
+ return false;
+
+ form.finish();
+
+ KIO::TransferJob* job = KIO::http_post(url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType());
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_ADDPHOTO;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy(true);
+ return true;
+}
+
+QString FlickrTalker::getUserName()
+{
+ return m_username;
+}
+
+QString FlickrTalker::getUserId()
+{
+ return m_userId;
+}
+
+void FlickrTalker::cancel()
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ if (m_authProgressDlg && !m_authProgressDlg->isHidden())
+ m_authProgressDlg->hide();
+}
+
+void FlickrTalker::data(KIO::Job*, const QByteArray& data)
+{
+ if (data.isEmpty())
+ return;
+
+ int oldSize = m_buffer.size();
+ m_buffer.resize(m_buffer.size() + data.size());
+ memcpy(m_buffer.data()+oldSize, data.data(), data.size());
+}
+
+void FlickrTalker::slotError(const QString& error)
+{
+ QString transError;
+ int errorNo = atoi(error.latin1());
+
+ switch (errorNo)
+ {
+ case 2:
+ transError = i18n("No photo specified");
+ break;
+ case 3:
+ transError = i18n("General upload failure");
+ break;
+ case 4:
+ transError = i18n("Filesize was zero");
+ break;
+ case 5:
+ transError = i18n("Filetype was not recognised");
+ break;
+ case 6:
+ transError = i18n("User exceeded upload limit");
+ break;
+ case 96:
+ transError = i18n("Invalid signature");
+ break;
+ case 97:
+ transError = i18n("Missing signature");
+ break;
+ case 98:
+ transError = i18n("Login Failed / Invalid auth token");
+ break;
+ case 100:
+ transError = i18n("Invalid API Key");
+ break;
+ case 105:
+ transError = i18n("Service currently unavailable");
+ break;
+ case 108:
+ transError = i18n("Invalid Frob");
+ break;
+ case 111:
+ transError = i18n("Format \"xxx\" not found");
+ break;
+ case 112:
+ transError = i18n("Method \"xxx\" not found");
+ break;
+ case 114:
+ transError = i18n("Invalid SOAP envelope");
+ break;
+ case 115:
+ transError = i18n("Invalid XML-RPC Method Call");
+ break;
+ case 116:
+ transError = i18n("The POST method is now required for all setters");
+ break;
+ default:
+ transError = i18n("Unknown error");
+ break;
+ };
+
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Error Occured: %1\n We can not proceed further").arg(transError));
+
+// kdDebug() << "Not handling the error now will see it later" << endl;
+}
+
+void FlickrTalker::slotResult(KIO::Job *job)
+{
+ m_job = 0;
+ emit signalBusy(false);
+
+ if (job->error())
+ {
+ if (m_state == FE_ADDPHOTO)
+ emit signalAddPhotoFailed( job->errorString());
+ else
+ job->showErrorDialog(m_parent);
+ return;
+ }
+
+ switch(m_state)
+ {
+ case(FE_LOGIN):
+ //parseResponseLogin(m_buffer);
+ break;
+ case(FE_LISTPHOTOSETS):
+ parseResponseListPhotoSets(m_buffer);
+ break;
+ case(FE_GETFROB):
+ parseResponseGetFrob(m_buffer);
+ break;
+ case(FE_GETTOKEN):
+ parseResponseGetToken(m_buffer);
+ break;
+ case(FE_CHECKTOKEN):
+ parseResponseCheckToken(m_buffer);
+ break;
+ case(FE_GETAUTHORIZED):
+ //parseResponseGetToken(m_buffer);
+ break;
+ case(FE_LISTPHOTOS):
+ parseResponseListPhotos(m_buffer);
+ break;
+ case(FE_GETPHOTOPROPERTY):
+ parseResponsePhotoProperty(m_buffer);
+ break;
+ case(FE_ADDPHOTO):
+ parseResponseAddPhoto(m_buffer);
+ break;
+ }
+ /*
+ if (m_state == FE_LOGIN && m_loggedIn)
+ {
+ // listAlbums();
+ }*/
+}
+
+void FlickrTalker::parseResponseGetFrob(const QByteArray& data)
+{
+ bool success = false;
+ QString errorString;
+ QDomDocument doc("mydocument");
+
+ if (!doc.setContent(data))
+ {
+ return;
+ }
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+
+ while(!node.isNull())
+ {
+ if (node.isElement() && node.nodeName() == "frob")
+ {
+ QDomElement e = node.toElement(); // try to convert the node to an element.
+ kdDebug() << "Frob is" << e.text() << endl;
+ m_frob = e.text(); // this is what is obtained from data.
+ success = true;
+ }
+
+ if (node.isElement() && node.nodeName() == "err")
+ {
+ kdDebug() << "Checking Error in response" << endl;
+ errorString = node.toElement().attribute("code");
+ kdDebug() << "Error code=" << errorString << endl;
+ kdDebug() << "Msg=" << node.toElement().attribute("msg") << endl;
+ }
+ node = node.nextSibling();
+ }
+
+ kdDebug() << "GetFrob finished" << endl;
+ m_authProgressDlg->setProgress(2, 4);
+ m_state = FE_GETAUTHORIZED;
+ if(success)
+ emit signalAuthenticate();
+ else
+ emit signalError(errorString);
+}
+
+void FlickrTalker::parseResponseCheckToken(const QByteArray& data)
+{
+ bool success = false;
+ QString errorString;
+ QString username;
+ QString transReturn;
+ QDomDocument doc("checktoken");
+
+ if (!doc.setContent(data))
+ {
+ return;
+ }
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+ QDomElement e;
+
+ while(!node.isNull())
+ {
+ if (node.isElement() && node.nodeName() == "auth")
+ {
+ e = node.toElement(); // try to convert the node to an element.
+ QDomNode details = e.firstChild();
+
+ while(!details.isNull())
+ {
+ if(details.isElement())
+ {
+ e = details.toElement();
+
+ if(details.nodeName() == "token")
+ {
+ kdDebug() << "Token=" << e.text() << endl;
+ m_token = e.text();//this is what is obtained from data.
+ }
+
+ if(details.nodeName() == "perms")
+ {
+ kdDebug() << "Perms=" << e.text() << endl;
+ QString perms = e.text();//this is what is obtained from data.
+
+ if(perms == "write")
+ transReturn = i18n("As in the persmission to", "write");
+ else if(perms == "read")
+ transReturn = i18n("As in the permission to", "read");
+ else if(perms == "delete")
+ transReturn = i18n("As in the permission to", "delete");
+ }
+
+ if(details.nodeName() == "user")
+ {
+ kdDebug() << "nsid=" << e.attribute("nsid") << endl;
+ m_userId = e.attribute("nsid");
+ username = e.attribute("username");
+ m_username = username;
+ kdDebug() << "username=" << e.attribute("username") << endl;
+ kdDebug() << "fullname=" << e.attribute("fullname") << endl;
+ }
+ }
+
+ details = details.nextSibling();
+ }
+
+ m_authProgressDlg->hide();
+ emit signalTokenObtained(m_token);
+ success = true;
+ }
+
+ if (node.isElement() && node.nodeName() == "err")
+ {
+ kdDebug() << "Checking Error in response" << endl;
+ errorString = node.toElement().attribute("code");
+ kdDebug() << "Error code=" << errorString << endl;
+ kdDebug() << "Msg=" << node.toElement().attribute("msg") << endl;
+
+ int valueOk = KMessageBox::questionYesNo(kapp->activeWindow(),
+ i18n("Your token is invalid. Would you like to "
+ "get a new token to proceed ?\n"));
+ if(valueOk == KMessageBox::Yes)
+ {
+ getFrob();
+ return;
+ }
+ else
+ {
+ m_authProgressDlg->hide(); //will popup the result for the checktoken failure below
+ }
+
+ }
+
+ node = node.nextSibling();
+ }
+
+ if(!success)
+ emit signalError(errorString);
+
+ kdDebug() << "CheckToken finished" << endl;
+}
+
+void FlickrTalker::parseResponseGetToken(const QByteArray& data)
+{
+ bool success = false;
+ QString errorString;
+ QDomDocument doc("gettoken");
+ if (!doc.setContent( data ))
+ return;
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+ QDomElement e;
+
+ while(!node.isNull())
+ {
+ if (node.isElement() && node.nodeName() == "auth")
+ {
+ e = node.toElement(); // try to convert the node to an element.
+ QDomNode details = e.firstChild();
+
+ while(!details.isNull())
+ {
+ if(details.isElement())
+ {
+ e = details.toElement();
+
+ if(details.nodeName() == "token")
+ {
+ kdDebug() << "Token=" << e.text() << endl;
+ m_token = e.text(); //this is what is obtained from data.
+ }
+
+ if(details.nodeName() == "perms")
+ {
+ kdDebug() << "Perms=" << e.text() << endl;
+ }
+
+ if(details.nodeName() == "user")
+ {
+ kdDebug() << "nsid=" << e.attribute("nsid") << endl;
+ kdDebug() << "username=" << e.attribute("username") << endl;
+ kdDebug() << "fullname=" << e.attribute("fullname") << endl;
+ m_username = e.attribute("username");
+ m_userId = e.attribute("nsid");
+ }
+ }
+
+ details = details.nextSibling();
+ }
+
+ success = true;
+ }
+ else if (node.isElement() && node.nodeName() == "err")
+ {
+ kdDebug() << "Checking Error in response" << endl;
+ errorString = node.toElement().attribute("code");
+ kdDebug() << "Error code=" << errorString << endl;
+ kdDebug() << "Msg=" << node.toElement().attribute("msg") << endl;
+ //emit signalError(code);
+ }
+
+ node = node.nextSibling();
+ }
+
+ kdDebug() << "GetToken finished" << endl;
+ //emit signalBusy( false );
+ m_authProgressDlg->hide();
+
+ if(success)
+ emit signalTokenObtained(m_token);
+ else
+ emit signalError(errorString);
+}
+void FlickrTalker::parseResponseListPhotoSets(const QByteArray& data)
+{
+ bool success = false;
+ QDomDocument doc("getListPhotoSets");
+ if (!doc.setContent(data))
+ return;
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+ QDomElement e;
+ QString photoSet_id, photoSet_title, photoSet_description;
+ QValueList <FPhotoSet> photoSetList;
+
+ while(!node.isNull())
+ {
+ if (node.isElement() && node.nodeName() == "photosets")
+ {
+ e = node.toElement();
+ QDomNode details = e.firstChild();
+ FPhotoSet fps;
+ QDomNode detailsNode = details;
+
+ while(!detailsNode.isNull())
+ {
+ if(detailsNode.isElement())
+ {
+ e = detailsNode.toElement();
+ if(detailsNode.nodeName() == "photoset")
+ {
+ kdDebug() << "id=" << e.attribute("id") << endl;
+ photoSet_id = e.attribute("id"); //this is what is obtained from data.
+ fps.id = photoSet_id;
+ QDomNode photoSetDetails = detailsNode.firstChild();
+ QDomElement e_detail;
+
+ while(!photoSetDetails.isNull())
+ {
+ e_detail = photoSetDetails.toElement();
+
+ if(photoSetDetails.nodeName() == "title")
+ {
+ kdDebug() << "Title=" << e_detail.text() << endl;
+ photoSet_title = e_detail.text();
+ fps.title = photoSet_title;
+ }
+ else if(photoSetDetails.nodeName() == "description")
+ {
+ kdDebug() << "Description =" << e_detail.text() << endl;
+ photoSet_description = e_detail.text();
+ fps.description = photoSet_description;
+ }
+
+ photoSetDetails = photoSetDetails.nextSibling();
+ }
+ }
+ }
+
+ detailsNode = detailsNode.nextSibling();
+ }
+
+ photoSetList.append(fps);
+ details = details.nextSibling();
+ success = true;
+ }
+
+ if (node.isElement() && node.nodeName() == "err")
+ {
+ kdDebug() << "Checking Error in response" << endl;
+ QString code = node.toElement().attribute("code");
+ kdDebug() << "Error code=" << code << endl;
+ kdDebug() << "Msg=" << node.toElement().attribute("msg") << endl;
+ emit signalError(code);
+ }
+
+ node = node.nextSibling();
+ }
+
+ kdDebug() << "GetPhotoList finished" << endl;
+
+ if (!success)
+ {
+ emit signalListPhotoSetsFailed(i18n("Failed to fetch photoSets List"));
+ }
+ else
+ {
+ emit signalListPhotoSetsSucceeded(photoSetList);
+ }
+}
+
+void FlickrTalker::parseResponseListPhotos(const QByteArray& data)
+{
+ QDomDocument doc("getPhotosList");
+ if (!doc.setContent( data))
+ return;
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+ //QDomElement e;
+ //TODO
+}
+
+void FlickrTalker::parseResponseCreateAlbum(const QByteArray& data)
+{
+ QDomDocument doc("getCreateAlbum");
+ if (!doc.setContent(data))
+ return;
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+
+ //TODO
+}
+
+void FlickrTalker::parseResponseAddPhoto(const QByteArray& data)
+{
+ bool success = false;
+ QString line;
+ QDomDocument doc("AddPhoto Response");
+ if (!doc.setContent(data))
+ return;
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+ QDomElement e;
+
+ while(!node.isNull())
+ {
+ if (node.isElement() && node.nodeName() == "photoid")
+ {
+ e = node.toElement(); // try to convert the node to an element.
+ QDomNode details = e.firstChild();
+ kdDebug() << "Photoid= " << e.text() << endl;
+ success = true;
+ }
+
+ if (node.isElement() && node.nodeName() == "err")
+ {
+ kdDebug() << "Checking Error in response" << endl;
+ QString code = node.toElement().attribute("code");
+ kdDebug() << "Error code=" << code << endl;
+ kdDebug() << "Msg=" << node.toElement().attribute("msg") << endl;
+ emit signalError(code);
+ }
+
+ node = node.nextSibling();
+ }
+
+ kdDebug() << "GetToken finished" << endl;
+
+ if (!success)
+ {
+ emit signalAddPhotoFailed(i18n("Failed to upload photo"));
+ }
+ else
+ {
+ emit signalAddPhotoSucceeded();
+ }
+
+}
+void FlickrTalker::parseResponsePhotoProperty(const QByteArray& data)
+{
+ bool success = false;
+ QString line;
+ QDomDocument doc("Photos Properties");
+ if (!doc.setContent(data))
+ return;
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+ QDomElement e;
+
+ while(!node.isNull())
+ {
+ if (node.isElement() && node.nodeName() == "photoid")
+ {
+ e = node.toElement(); // try to convert the node to an element.
+ QDomNode details = e.firstChild();
+ kdDebug() << "Photoid=" << e.text() << endl;
+ success = true;
+ }
+
+ if (node.isElement() && node.nodeName() == "err")
+ {
+ kdDebug() << "Checking Error in response" << endl;
+ QString code = node.toElement().attribute("code");
+ kdDebug() << "Error code=" << code << endl;
+ kdDebug() << "Msg=" << node.toElement().attribute("msg") << endl;
+ emit signalError(code);
+ }
+
+ node = node.nextSibling();
+ }
+
+ kdDebug() << "GetToken finished" << endl;
+
+ if (!success)
+ {
+ emit signalAddPhotoFailed(i18n("Failed to query photo information"));
+ }
+ else
+ {
+ emit signalAddPhotoSucceeded();
+ }
+}
+
+} // namespace KIPIFlickrExportPlugin
diff --git a/kipi-plugins/flickrexport/flickrtalker.h b/kipi-plugins/flickrexport/flickrtalker.h
new file mode 100644
index 0000000..9b98209
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickrtalker.h
@@ -0,0 +1,151 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 FLICKRTALKER_H
+#define FLICKRTALKER_H
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qobject.h>
+#include <qprogressdialog.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <kio/job.h>
+
+class QProgressDialog;
+
+namespace KIPIFlickrExportPlugin
+{
+
+class GAlbum;
+class GPhoto;
+class FPhotoInfo;
+class FPhotoSet;
+
+class FlickrTalker : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ enum State
+ {
+ FE_LOGIN = 0,
+ FE_LISTPHOTOSETS,
+ FE_LISTPHOTOS,
+ FE_GETPHOTOPROPERTY,
+ FE_ADDPHOTO,
+ FE_GETFROB,
+ FE_CHECKTOKEN,
+ FE_GETTOKEN,
+ FE_GETAUTHORIZED
+ };
+
+public:
+
+ FlickrTalker(QWidget* parent);
+ ~FlickrTalker();
+
+ QString getUserName();
+ QString getUserId();
+ void getFrob();
+ void getToken();
+ void checkToken(const QString& token);
+ void getPhotoProperty(const QString& method, const QStringList& argList);
+ void cancel();
+
+ void listPhotoSets();
+ void listPhotos(const QString& albumName);
+ void createAlbum(const QString& parentAlbumName,
+ const QString& albumName,
+ const QString& albumTitle,
+ const QString& albumCaption);
+
+ bool addPhoto(const QString& photoPath, const FPhotoInfo& info,
+ bool rescale=false, int maxDim=600, int imageQuality=85);
+
+public:
+
+ QProgressDialog *m_authProgressDlg;
+
+signals:
+
+ void signalError(const QString& msg);
+// void signalLoginFailed( const QString& msg );
+ void signalBusy(bool val);
+ void signalAlbums(const QValueList<GAlbum>& albumList);
+ void signalPhotos(const QValueList<GPhoto>& photoList);
+ void signalAddPhotoSucceeded();
+ void signalListPhotoSetsSucceeded(const QValueList <FPhotoSet>& photoSetList);
+ void signalAddPhotoFailed(const QString& msg);
+ void signalListPhotoSetsFailed(const QString& msg);
+ void signalAuthenticate();
+ void signalTokenObtained(const QString& token);
+
+private:
+
+// void parseResponseLogin(const QByteArray& data);
+ void parseResponseListPhotoSets(const QByteArray& data);
+ void parseResponseListPhotos(const QByteArray& data);
+ void parseResponseCreateAlbum(const QByteArray& data);
+ void parseResponseAddPhoto(const QByteArray& data);
+ void parseResponseGetFrob(const QByteArray& data);
+ void parseResponseGetToken(const QByteArray& data);
+ void parseResponseCheckToken(const QByteArray& data);
+ void parseResponsePhotoProperty(const QByteArray& data);
+
+ QString getApiSig(const QString& secret, const KURL& url);
+
+private slots:
+
+ void slotError(const QString& msg);
+ void slotAuthenticate();
+ void data(KIO::Job *job, const QByteArray& data);
+ void slotResult(KIO::Job *job);
+
+private:
+
+ QWidget* m_parent;
+
+// QString m_cookie;
+ QByteArray m_buffer;
+
+ QString m_apikey;
+ QString m_secret;
+ QString m_frob;
+ QString m_token;
+ QString m_username;
+ QString m_userId;
+
+ KIO::Job* m_job;
+
+ State m_state;
+};
+
+} // namespace KIPIFlickrExportPlugin
+
+#endif /* FLICKRTALKER_H */
diff --git a/kipi-plugins/flickrexport/flickrviewitem.cpp b/kipi-plugins/flickrexport/flickrviewitem.cpp
new file mode 100644
index 0000000..50d955a
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickrviewitem.cpp
@@ -0,0 +1,107 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-12-01
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qpainter.h>
+#include <qpixmap.h>
+
+// Local includes.
+
+#include "flickrviewitem.h"
+
+namespace KIPIFlickrExportPlugin
+{
+
+GAlbumViewItem::GAlbumViewItem(QListView* parent, const QString& name, const GAlbum& album)
+ : QListViewItem(parent, name)
+{
+ m_album = album;
+}
+
+GAlbumViewItem::GAlbumViewItem(QListViewItem* parent, const QString& name, const GAlbum& album)
+ : QListViewItem(parent, name)
+{
+ m_album = album;
+}
+
+GAlbumViewItem::~GAlbumViewItem()
+{
+}
+
+void GAlbumViewItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int)
+{
+ if (!p)
+ return;
+
+ QListView *lv = listView();
+ if (!lv)
+ return;
+
+ QFontMetrics fm(p->fontMetrics());
+
+ if (isSelected())
+ p->fillRect(0, 0, width, height(), cg.highlight());
+ else
+ p->fillRect(0, 0, width, height(), cg.base());
+
+ const QPixmap* icon = pixmap(column);
+
+ int iconWidth = 0;
+ if (icon)
+ {
+ iconWidth = icon->width() + lv->itemMargin();
+ int xo = lv->itemMargin();
+ int yo = (height() - icon->height())/2;
+ p->drawPixmap( xo, yo, *icon );
+ }
+
+ if (isSelected())
+ p->setPen( cg.highlightedText() );
+ else
+ p->setPen( cg.text() );
+
+ int r = lv->itemMargin() + iconWidth;
+ int h = lv->fontMetrics().height() + 2;
+ p->drawText(r, 0, width-r, h, Qt::AlignVCenter, m_album.title);
+
+ QFont fn(lv->font());
+ fn.setPointSize(fn.pointSize()-2);
+ fn.setItalic(true);
+ p->setFont(fn);
+ p->setPen(isSelected() ? cg.highlightedText() : Qt::gray);
+ p->drawText(r, h, width-r, h, Qt::AlignVCenter, m_album.name);
+}
+
+void GAlbumViewItem::setup()
+{
+ int h = listView()->fontMetrics().height();
+ int margin = 4;
+ setHeight( QMAX(2*h + margin, 32) );
+}
+
+void GAlbumViewItem::paintFocus(QPainter*, const QColorGroup&, const QRect&)
+{
+}
+
+} // namespace KIPIFlickrExportPlugin
diff --git a/kipi-plugins/flickrexport/flickrviewitem.h b/kipi-plugins/flickrexport/flickrviewitem.h
new file mode 100644
index 0000000..9bd5a21
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickrviewitem.h
@@ -0,0 +1,60 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-12-01
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 FLICKRVIEWITEM_H
+#define FLICKRVIEWITEM_H
+
+// Qt includes.
+
+#include <qlistview.h>
+
+// Local includes.
+
+#include "flickritem.h"
+
+namespace KIPIFlickrExportPlugin
+{
+
+class GAlbumViewItem : public QListViewItem
+{
+
+public:
+
+ GAlbumViewItem(QListView* parent, const QString& name, const GAlbum& album);
+ GAlbumViewItem(QListViewItem* parent, const QString& name, const GAlbum& album);
+ ~GAlbumViewItem();
+
+protected:
+
+ void paintCell(QPainter *p, const QColorGroup& cg, int column, int width, int);
+ void paintFocus(QPainter*, const QColorGroup&, const QRect&);
+ void setup();
+
+private:
+
+ GAlbum m_album;
+};
+
+} // namespace KIPIFlickrExportPlugin
+
+#endif /* FLICKRVIEWITEM_H */
diff --git a/kipi-plugins/flickrexport/flickrwidget.cpp b/kipi-plugins/flickrexport/flickrwidget.cpp
new file mode 100644
index 0000000..45e5afb
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickrwidget.cpp
@@ -0,0 +1,218 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qframe.h>
+#include <qheader.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qgroupbox.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+// KDE includes.
+
+#include <ktabwidget.h>
+#include <klineedit.h>
+#include <kdialog.h>
+#include <kactivelabel.h>
+#include <klocale.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+#include <kseparator.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+
+// Libkipi includes.
+
+#include <libkipi/interface.h>
+
+// Local includes.
+
+#include "imageslist.h"
+#include "flickrwidget.h"
+#include "flickrwidget.moc"
+
+namespace KIPIFlickrExportPlugin
+{
+
+FlickrWidget::FlickrWidget(QWidget* parent, KIPI::Interface *iface)
+ : QWidget(parent)
+{
+ setName("FlickrWidget");
+
+ QVBoxLayout* flickrWidgetLayout = new QVBoxLayout(this, 5, 5);
+
+ m_photoView = 0; //new KHTMLPart(splitter);
+ KSeparator *line = new KSeparator(Horizontal, this);
+ m_tab = new KTabWidget(this);
+ KActiveLabel *headerLabel = new KActiveLabel(this);
+ headerLabel->setFocusPolicy(NoFocus);
+ headerLabel->setLinkUnderline(false);
+ headerLabel->setText(i18n("<qt><b><h2><a href='http://www.flickr.com'>"
+ "<font color=\"#0065DE\">flick</font>"
+ "<font color=\"#FF0084\">r</font></a>"
+ " Export"
+ "</h2></b></qt>"));
+
+ // -------------------------------------------------------------------
+
+ m_imglst = new ImagesList(m_tab, iface);
+ QWidget* settingsBox = new QWidget(m_tab);
+ QVBoxLayout* settingsBoxLayout = new QVBoxLayout(settingsBox);
+
+ //m_newAlbumBtn = new QPushButton(settingsBox, "m_newAlbumBtn");
+ //m_newAlbumBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ //m_newAlbumBtn->setText(i18n("&New Album"));
+
+ QGridLayout* tagsLayout = new QGridLayout(1, 1);
+ QLabel* tagsLabel = new QLabel(i18n("Added Tags: "), settingsBox);
+ m_tagsLineEdit = new KLineEdit(settingsBox);
+ m_exportHostTagsCheckBox = new QCheckBox(settingsBox);
+ m_exportHostTagsCheckBox->setText(i18n("Use Host Application Tags"));
+ m_stripSpaceTagsCheckBox = new QCheckBox(settingsBox);
+ m_stripSpaceTagsCheckBox->setText(i18n("Strip Space From Host Application Tags"));
+ QToolTip::add(m_tagsLineEdit, i18n("Enter here new tags separated by space."));
+
+ tagsLayout->addWidget(tagsLabel, 0, 0);
+ tagsLayout->addWidget(m_tagsLineEdit, 0, 1);
+ tagsLayout->addWidget(m_exportHostTagsCheckBox, 1, 1);
+ tagsLayout->addWidget(m_stripSpaceTagsCheckBox, 2, 1);
+
+ // ------------------------------------------------------------------------
+
+ QGroupBox* optionsBox = new QGroupBox(i18n("Override Default Options"), settingsBox);
+ optionsBox->setColumnLayout(0, Qt::Vertical);
+ optionsBox->layout()->setSpacing(KDialog::spacingHint());
+ optionsBox->layout()->setMargin(KDialog::spacingHint());
+ QGridLayout* optionsBoxLayout = new QGridLayout(optionsBox->layout(), 5, 3);
+
+ m_publicCheckBox = new QCheckBox(optionsBox);
+ m_publicCheckBox->setText(i18n("As in accessible for people", "Public (anyone can see them)"));
+
+ m_familyCheckBox = new QCheckBox(optionsBox);
+ m_familyCheckBox->setText(i18n("Visible to Family"));
+
+ m_friendsCheckBox = new QCheckBox(optionsBox);
+ m_friendsCheckBox->setText(i18n("Visible to Friends"));
+
+ m_resizeCheckBox = new QCheckBox(optionsBox);
+ m_resizeCheckBox->setText(i18n("Resize photos before uploading"));
+ m_resizeCheckBox->setChecked(false);
+
+ m_dimensionSpinBox = new QSpinBox(0, 5000, 10, optionsBox);
+ m_dimensionSpinBox->setValue(600);
+ m_dimensionSpinBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ m_dimensionSpinBox->setEnabled(false);
+
+ QLabel* resizeLabel = new QLabel(i18n("Maximum dimension (pixels):"), optionsBox);
+
+ m_imageQualitySpinBox = new QSpinBox(0, 100, 1, optionsBox);
+ m_imageQualitySpinBox->setValue(85);
+ m_imageQualitySpinBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ // NOTE: The term Compression factor may be to technical to write in the label
+ QLabel* imageQualityLabel = new QLabel(i18n("JPEG Image Quality (higher is better):"), optionsBox);
+
+ optionsBoxLayout->addMultiCellWidget(m_publicCheckBox, 0, 0, 0, 3);
+ optionsBoxLayout->addMultiCellWidget(m_familyCheckBox, 1, 1, 0, 3);
+ optionsBoxLayout->addMultiCellWidget(m_friendsCheckBox, 2, 2, 0, 3);
+ optionsBoxLayout->addMultiCellWidget(imageQualityLabel, 3, 3, 0, 2);
+ optionsBoxLayout->addMultiCellWidget(m_imageQualitySpinBox, 3, 3, 3, 3);
+ optionsBoxLayout->addMultiCellWidget(m_resizeCheckBox, 4, 4, 0, 3);
+ optionsBoxLayout->addMultiCellWidget(resizeLabel, 5, 5, 1, 2);
+ optionsBoxLayout->addMultiCellWidget(m_dimensionSpinBox, 5, 5, 3, 3);
+ optionsBoxLayout->setColSpacing(0, KDialog::spacingHint());
+ optionsBoxLayout->setColStretch(1, 10);
+ optionsBoxLayout->setSpacing(KDialog::spacingHint());
+ optionsBoxLayout->setMargin(0);
+
+ // ------------------------------------------------------------------------
+
+ QGroupBox* accountBox = new QGroupBox(i18n("Account"), settingsBox);
+ accountBox->setColumnLayout(0, Qt::Vertical);
+ accountBox->layout()->setSpacing(KDialog::spacingHint());
+ accountBox->layout()->setMargin(KDialog::spacingHint());
+ QGridLayout* accountBoxLayout = new QGridLayout(accountBox->layout(), 1, 3);
+
+ QLabel *userNameLabel = new QLabel(i18n("User Name: "), accountBox);
+ m_userNameDisplayLabel = new QLabel(accountBox);
+ m_changeUserButton = new QPushButton(accountBox);
+ m_changeUserButton->setText(i18n("Use a different account"));
+ m_changeUserButton->setIconSet(SmallIcon("switchuser"));
+
+ accountBoxLayout->addMultiCellWidget(userNameLabel, 0, 0, 0, 0);
+ accountBoxLayout->addMultiCellWidget(m_userNameDisplayLabel, 0, 0, 1, 1);
+ accountBoxLayout->addMultiCellWidget(m_changeUserButton, 0, 0, 3, 3);
+ accountBoxLayout->setColStretch(2, 10);
+ accountBoxLayout->setSpacing(KDialog::spacingHint());
+ accountBoxLayout->setMargin(0);
+
+ settingsBoxLayout->addLayout(tagsLayout);
+ settingsBoxLayout->addWidget(optionsBox);
+ settingsBoxLayout->addWidget(accountBox);
+ settingsBoxLayout->addStretch(10);
+ settingsBoxLayout->setSpacing(KDialog::spacingHint());
+ settingsBoxLayout->setMargin(KDialog::spacingHint());
+
+ // ------------------------------------------------------------------------
+
+ flickrWidgetLayout->addWidget(headerLabel);
+ flickrWidgetLayout->addWidget(line);
+ flickrWidgetLayout->addWidget(m_tab, 5);
+ flickrWidgetLayout->setSpacing(KDialog::spacingHint());
+ flickrWidgetLayout->setMargin(0);
+
+ m_tab->insertTab(m_imglst, i18n("Files List"), FILELIST);
+ m_tab->insertTab(settingsBox, i18n("Upload Options"), UPLOAD);
+
+ // ------------------------------------------------------------------------
+
+ connect(m_resizeCheckBox, SIGNAL(clicked()),
+ this, SLOT(slotResizeChecked()));
+
+ connect(m_exportHostTagsCheckBox, SIGNAL(clicked()),
+ this, SLOT(slotExportHostTagsChecked()));
+}
+
+FlickrWidget::~FlickrWidget()
+{
+}
+
+void FlickrWidget::slotResizeChecked()
+{
+ m_dimensionSpinBox->setEnabled(m_resizeCheckBox->isChecked());
+}
+
+void FlickrWidget::slotExportHostTagsChecked()
+{
+ m_stripSpaceTagsCheckBox->setEnabled(m_exportHostTagsCheckBox->isChecked());
+}
+
+} // namespace KIPIFlickrExportPlugin
diff --git a/kipi-plugins/flickrexport/flickrwidget.h b/kipi-plugins/flickrexport/flickrwidget.h
new file mode 100644
index 0000000..e451a8a
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickrwidget.h
@@ -0,0 +1,102 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 FLICKRWIDGET_H
+#define FLICKRWIDGET_H
+
+// Qt includes.
+
+#include <qwidget.h>
+
+class QPushButton;
+class QSpinBox;
+class QCheckBox;
+class QRadioButton;
+
+class KTabWidget;
+class KLineEdit;
+class KHTMLPart;
+
+namespace KIPI
+{
+ class Interface;
+}
+
+namespace KIPIFlickrExportPlugin
+{
+
+class ImagesList;
+
+class FlickrWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ enum SettingsTab
+ {
+ FILELIST=0,
+ UPLOAD
+ };
+
+public:
+
+ FlickrWidget(QWidget* parent, KIPI::Interface *iface);
+ ~FlickrWidget();
+
+private slots:
+
+ void slotResizeChecked();
+ void slotExportHostTagsChecked();
+
+private:
+
+// QPushButton* m_newAlbumBtn;
+ QPushButton* m_changeUserButton;
+
+ QCheckBox* m_resizeCheckBox;
+ QCheckBox* m_familyCheckBox;
+ QCheckBox* m_friendsCheckBox;
+ QCheckBox* m_publicCheckBox;
+ QCheckBox* m_exportHostTagsCheckBox;
+ QCheckBox* m_stripSpaceTagsCheckBox;
+
+ QSpinBox* m_dimensionSpinBox;
+ QSpinBox* m_imageQualitySpinBox;
+
+ QLabel* m_userNameDisplayLabel;
+
+ KLineEdit* m_tagsLineEdit;
+
+ KTabWidget* m_tab;
+
+ KHTMLPart* m_photoView;
+
+ ImagesList* m_imglst;
+
+ friend class FlickrWindow;
+};
+
+} // namespace KIPIFlickrExportPlugin
+
+#endif // FLICKRWIDGET_H
diff --git a/kipi-plugins/flickrexport/flickrwindow.cpp b/kipi-plugins/flickrexport/flickrwindow.cpp
new file mode 100644
index 0000000..5f6a345
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickrwindow.cpp
@@ -0,0 +1,588 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-17-06
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qprogressdialog.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qstringlist.h>
+#include <qradiobutton.h>
+
+// KDE includes.
+
+#include <klineedit.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+#include <ktabwidget.h>
+#include <krun.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kdeversion.h>
+#if KDE_IS_VERSION(3,2,0)
+#include <kwallet.h>
+#endif
+
+// Libkipi includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "login.h"
+#include "imageslist.h"
+#include "flickrtalker.h"
+#include "flickritem.h"
+#include "flickrviewitem.h"
+#include "flickrwidget.h"
+#include "flickralbumdialog.h"
+#include "flickrwindow.h"
+#include "flickrwindow.moc"
+
+namespace KIPIFlickrExportPlugin
+{
+
+FlickrWindow::FlickrWindow(KIPI::Interface* interface, const QString &tmpFolder, QWidget *parent)
+ : KDialogBase(parent, 0, false, i18n("Export to Flickr Web Service"),
+ Help|User1|Close, Close, false)
+{
+ m_tmp = tmpFolder;
+ m_interface = interface;
+ m_uploadCount = 0;
+ m_uploadTotal = 0;
+// m_wallet = 0;
+ m_widget = new FlickrWidget(this, interface);
+ m_photoView = m_widget->m_photoView;
+// m_newAlbumBtn = m_widget->m_newAlbumBtn;
+ m_resizeCheckBox = m_widget->m_resizeCheckBox;
+ m_publicCheckBox = m_widget->m_publicCheckBox;
+ m_familyCheckBox = m_widget->m_familyCheckBox;
+ m_friendsCheckBox = m_widget->m_friendsCheckBox;
+ m_dimensionSpinBox = m_widget->m_dimensionSpinBox;
+ m_imageQualitySpinBox = m_widget->m_imageQualitySpinBox;
+ m_tagsLineEdit = m_widget->m_tagsLineEdit;
+ m_exportHostTagsCheckBox = m_widget->m_exportHostTagsCheckBox;
+ m_stripSpaceTagsCheckBox = m_widget->m_stripSpaceTagsCheckBox;
+ m_changeUserButton = m_widget->m_changeUserButton;
+ m_userNameDisplayLabel = m_widget->m_userNameDisplayLabel;
+ m_imglst = m_widget->m_imglst;
+
+ setButtonGuiItem(User1, KGuiItem(i18n("Start Uploading"), SmallIcon("network")));
+ setMainWidget(m_widget);
+ m_widget->setMinimumSize(600, 400);
+
+ connect(m_imglst, SIGNAL(signalImageListChanged(bool)),
+ this, SLOT(slotImageListChanged(bool)));
+
+ //m_startUploadButton->setEnabled(false);
+ //m_albumView->setRootIsDecorated(true);
+ //m_newAlbumBtn->setEnabled(false);
+
+ // --------------------------------------------------------------------------
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Flickr Export"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to export image collection to "
+ "Flickr web service."),
+ "(c) 2005-2008, Vardhman Jain\n"
+ "(c) 2008, Gilles Caulier");
+
+ m_about->addAuthor("Vardhman Jain", I18N_NOOP("Author and maintainer"),
+ "Vardhman at gmail dot com");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Developer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup(helpMenu->menu());
+
+ // --------------------------------------------------------------------------
+
+ m_talker = new FlickrTalker(this);
+
+ connect(m_talker, SIGNAL( signalError( const QString& ) ),
+ m_talker, SLOT( slotError( const QString& ) ));
+
+ connect(m_talker, SIGNAL( signalBusy( bool ) ),
+ this, SLOT( slotBusy( bool ) ));
+
+ connect(m_talker, SIGNAL( signalAddPhotoSucceeded() ),
+ this, SLOT( slotAddPhotoSucceeded() ));
+
+ connect(m_talker, SIGNAL( signalAddPhotoFailed( const QString& ) ),
+ this, SLOT( slotAddPhotoFailed( const QString& ) ));
+
+ connect(m_talker, SIGNAL( signalListPhotoSetsSucceeded( const QValueList<FPhotoSet>& ) ),
+ this, SLOT( slotListPhotoSetsResponse( const QValueList<FPhotoSet>& ) ));
+
+ //connect( m_talker, SIGNAL( signalAlbums( const QValueList<GAlbum>& ) ),
+ // SLOT( slotAlbums( const QValueList<GAlbum>& ) ) );
+
+ //connect( m_talker, SIGNAL( signalPhotos( const QValueList<GPhoto>& ) ),
+ // SLOT( slotPhotos( const QValueList<GPhoto>& ) ) );
+
+ // --------------------------------------------------------------------------
+
+ m_progressDlg = new QProgressDialog(this, 0, true);
+ m_progressDlg->setAutoReset(true);
+ m_progressDlg->setAutoClose(true);
+
+ connect(m_progressDlg, SIGNAL( canceled() ),
+ this, SLOT( slotAddPhotoCancel() ));
+
+ connect(m_changeUserButton, SIGNAL( clicked() ),
+ this, SLOT( slotUserChangeRequest() ));
+
+ connect(m_talker, SIGNAL( signalTokenObtained(const QString&) ),
+ this, SLOT( slotTokenObtained(const QString&) ));
+
+ //connect( m_tagView, SIGNAL( selectionChanged() ),
+ // SLOT( slotTagSelected() ) );
+
+ //connect( m_photoView->browserExtension(), SIGNAL( openURLRequest( const KURL&, const KParts::URLArgs& ) ),
+ // SLOT( slotOpenPhoto( const KURL& ) ) );
+
+ //connect( m_newAlbumBtn, SIGNAL( clicked() ),
+ // SLOT( slotNewAlbum() ) );
+
+ // --------------------------------------------------------------------------
+
+ readSettings();
+
+ m_authProgressDlg = new QProgressDialog(this, 0, true);
+ m_authProgressDlg->setAutoReset(true);
+ m_authProgressDlg->setAutoClose(true);
+
+ connect(m_authProgressDlg, SIGNAL( canceled() ),
+ this, SLOT( slotAuthCancel() ));
+
+ m_talker->m_authProgressDlg = m_authProgressDlg;
+ m_widget->setEnabled(false);
+
+ kdDebug() << "Calling auth methods" << endl;
+
+ if(m_token.length()< 1)
+ m_talker->getFrob();
+ else
+ m_talker->checkToken(m_token);
+}
+
+FlickrWindow::~FlickrWindow()
+{
+#if KDE_IS_VERSION(3,2,0)
+// if (m_wallet)
+// delete m_wallet;
+#endif
+
+ delete m_progressDlg;
+ delete m_authProgressDlg;
+ delete m_talker;
+ delete m_widget;
+ delete m_about;
+}
+
+void FlickrWindow::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("FlickrExport Settings");
+ m_token = config.readEntry("token");
+
+ if (config.readBoolEntry("Resize", false))
+ {
+ m_resizeCheckBox->setChecked(true);
+ m_dimensionSpinBox->setEnabled(true);
+ }
+ else
+ {
+ m_resizeCheckBox->setChecked(false);
+ m_dimensionSpinBox->setEnabled(false);
+ }
+
+ m_dimensionSpinBox->setValue(config.readNumEntry("Maximum Width", 1600));
+ m_imageQualitySpinBox->setValue(config.readNumEntry("Image Quality", 85));
+ m_exportHostTagsCheckBox->setChecked(config.readBoolEntry("Export Host Tags", false));
+ m_stripSpaceTagsCheckBox->setChecked(config.readBoolEntry("Strip Space Host Tags", false));
+ m_stripSpaceTagsCheckBox->setEnabled(m_exportHostTagsCheckBox->isChecked());
+
+ if(!m_interface->hasFeature(KIPI::HostSupportsTags))
+ {
+ m_exportHostTagsCheckBox->setEnabled(false);
+ m_stripSpaceTagsCheckBox->setEnabled(false);
+ }
+
+ m_publicCheckBox->setChecked(config.readBoolEntry("Public Sharing", false));
+ m_familyCheckBox->setChecked(config.readBoolEntry("Family Sharing", false));
+ m_friendsCheckBox->setChecked(config.readBoolEntry("Friends Sharing", false));
+
+ resize(configDialogSize(config, QString("FlickrExport Dialog")));
+}
+
+void FlickrWindow::writeSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("FlickrExport Settings");
+ config.writeEntry("token", m_token);
+ config.writeEntry("Resize", m_resizeCheckBox->isChecked());
+ config.writeEntry("Maximum Width", m_dimensionSpinBox->value());
+ config.writeEntry("Image Quality", m_imageQualitySpinBox->value());
+ config.writeEntry("Export Host Tags", m_exportHostTagsCheckBox->isChecked());
+ config.writeEntry("Strip Space Host Tags", m_stripSpaceTagsCheckBox->isChecked());
+ config.writeEntry("Public Sharing", m_publicCheckBox->isChecked());
+ config.writeEntry("Family Sharing", m_familyCheckBox->isChecked());
+ config.writeEntry("Friends Sharing", m_friendsCheckBox->isChecked());
+ saveDialogSize(config, QString("FlickrExport Dialog"));
+ config.sync();
+}
+
+void FlickrWindow::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("flickrexport", "kipi-plugins");
+}
+
+void FlickrWindow::slotDoLogin()
+{
+}
+
+void FlickrWindow::slotClose()
+{
+ writeSettings();
+ done(Close);
+}
+
+void FlickrWindow::slotTokenObtained(const QString& token)
+{
+ m_token = token;
+ m_username = m_talker->getUserName();
+ m_userId = m_talker->getUserId();
+ kdDebug() << "SlotTokenObtained invoked setting user Display name to " << m_username << endl;
+ m_userNameDisplayLabel->setText(QString("<qt><b>%1</b></qt>").arg(m_username));
+ m_widget->setEnabled(true);
+}
+
+void FlickrWindow::slotBusy(bool val)
+{
+ if (val)
+ {
+ setCursor(QCursor::WaitCursor);
+// m_newAlbumBtn->setEnabled( false );
+// m_addPhotoButton->setEnabled( false );
+ }
+ else
+ {
+ setCursor(QCursor::ArrowCursor);
+// m_newAlbumBtn->setEnabled( loggedIn );
+// m_addPhotoButton->setEnabled( loggedIn && m_albumView->selectedItem() );
+ }
+}
+
+void FlickrWindow::slotError(const QString& msg)
+{
+ //m_talker->slotError(msg);
+ KMessageBox::error( this, msg );
+}
+
+void FlickrWindow::slotUserChangeRequest()
+{
+ kdDebug() << "Slot Change User Request " << endl;
+ m_talker->getFrob();
+// m_addPhotoButton->setEnabled(m_selectImagesButton->isChecked());
+}
+
+/*
+void FlickrWindow::slotAlbums( const QValueList<GAlbum>& albumList )
+{
+ m_albumDict.clear();
+ m_tagView->clear();
+ //m_photoView->begin();
+ //m_photoView->write( "<html></html>" );
+ //m_photoView->end();
+
+ KIconLoader* iconLoader = KApplication::kApplication()->iconLoader();
+ QPixmap pix = iconLoader->loadIcon( "folder", KIcon::NoGroup, 32 );
+
+ typedef QValueList<GAlbum> GAlbumList;
+ GAlbumList::const_iterator iter;
+ for ( iter = albumList.begin(); iter != albumList.end(); ++iter )
+ {
+ const GAlbum& album = *iter;
+
+ if ( album.parent_ref_num == 0 )
+ {
+ GAlbumViewItem* item = new GAlbumViewItem( m_tagView, album.name,
+ album );
+ item->setPixmap( 0, pix );
+ m_albumDict.insert( album.ref_num, item );
+ }
+ else
+ {
+ QListViewItem* parent = m_albumDict.find( album.parent_ref_num );
+ if ( parent )
+ {
+ GAlbumViewItem* item = new GAlbumViewItem( parent, album.name,
+ album);
+ item->setPixmap( 0, pix );
+ m_albumDict.insert( album.ref_num, item );
+ }
+ else
+ {
+ kdWarning() << "Failed to find parent for album "
+ << album.name
+ << "with id " << album.ref_num;
+ }
+ }
+ }
+
+
+ // find and select the last selected album
+ int lastSelectedID = 0;
+ for ( iter = albumList.begin(); iter != albumList.end(); ++iter )
+ {
+ if ((*iter).name == m_lastSelectedAlbum)
+ {
+ lastSelectedID = (*iter).ref_num;
+ break;
+ }
+ }
+
+ if (lastSelectedID > 0)
+ {
+ GAlbumViewItem* lastSelectedItem = m_albumDict.find( lastSelectedID );
+ if (lastSelectedItem)
+ {
+ m_tagView->setSelected( lastSelectedItem, true );
+ m_tagView->ensureItemVisible( lastSelectedItem );
+ }
+ }
+}
+*/
+
+void FlickrWindow::slotAuthCancel()
+{
+ m_talker->cancel();
+ m_authProgressDlg->hide();
+}
+
+/*
+void FlickrWindow::slotPhotos( const QValueList<GPhoto>& photoList)
+{
+ // TODO
+}
+
+void FlickrWindow::slotTagSelected()
+{
+ // TODO
+}
+void FlickrWindow::slotOpenPhoto( const KURL& url )
+{
+ new KRun(url);
+}
+*/
+
+void FlickrWindow::slotListPhotoSetsResponse(const QValueList <FPhotoSet>& /*photoSetList*/)
+{
+ kdDebug() << "SlotListPhotoSetsResponse invoked" << endl;
+ // TODO
+}
+
+void FlickrWindow::slotNewPhotoSet()
+{
+ // TODO
+}
+
+/** This slot is call when 'Start Uploading' button is pressed.
+*/
+void FlickrWindow::slotUser1()
+{
+ kdDebug() << "SlotUploadImages invoked" << endl;
+
+ m_widget->m_tab->setCurrentPage(FlickrWidget::FILELIST);
+ KURL::List urls = m_imglst->imageUrls();
+
+ if (urls.isEmpty())
+ return;
+
+ typedef QPair<KURL, FPhotoInfo> Pair;
+
+ m_uploadQueue.clear();
+
+ for (KURL::List::iterator it = urls.begin(); it != urls.end(); ++it)
+ {
+ KIPI::ImageInfo info = m_interface->info(*it);
+ kdDebug() << "Adding images to the list" << endl;
+ FPhotoInfo temp;
+
+ temp.title = info.title();
+ temp.description = info.description();
+ temp.is_public = m_publicCheckBox->isChecked();
+ temp.is_family = m_familyCheckBox->isChecked();
+ temp.is_friend = m_friendsCheckBox->isChecked();
+ QStringList tagsFromDialog = QStringList::split(" ", m_tagsLineEdit->text(), false);
+
+ QStringList allTags;
+ QStringList::Iterator itTags;
+
+ // Tags from the dialog
+ itTags = tagsFromDialog.begin();
+ while(itTags != tagsFromDialog.end())
+ {
+ allTags.append(*itTags);
+ ++itTags;
+ }
+
+ // Tags from the database
+ QMap <QString, QVariant> attribs = info.attributes();
+ QStringList tagsFromDatabase;
+
+ if(m_exportHostTagsCheckBox->isChecked())
+ {
+ tagsFromDatabase = attribs["tags"].asStringList();
+ if (m_stripSpaceTagsCheckBox->isChecked())
+ {
+ for (QStringList::iterator it = tagsFromDatabase.begin(); it != tagsFromDatabase.end() ; ++it)
+ *it = (*it).stripWhiteSpace().remove(" ");
+ }
+ }
+
+ itTags = tagsFromDatabase.begin();
+
+ while(itTags != tagsFromDatabase.end())
+ {
+ allTags.append(*itTags);
+ ++itTags;
+ }
+
+ itTags = allTags.begin();
+
+ while(itTags != allTags.end())
+ {
+ kdDebug() << "Tags list: " << (*itTags) << endl;
+ ++itTags;
+ }
+
+ temp.tags = allTags;
+ m_uploadQueue.append(Pair(*it, temp));
+ }
+
+ m_uploadTotal = m_uploadQueue.count();
+ m_uploadCount = 0;
+ m_progressDlg->reset();
+ slotAddPhotoNext();
+ kdDebug() << "SlotUploadImages done" << endl;
+}
+
+void FlickrWindow::slotAddPhotoNext()
+{
+ if (m_uploadQueue.isEmpty())
+ {
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+ //slotAlbumSelected();
+ return;
+ }
+
+ typedef QPair<KURL, FPhotoInfo> Pair;
+ Pair pathComments = m_uploadQueue.first();
+ FPhotoInfo info = pathComments.second;
+ bool res = m_talker->addPhoto(pathComments.first.path(), //the file path
+ info,
+ m_resizeCheckBox->isChecked(),
+ m_dimensionSpinBox->value(),
+ m_imageQualitySpinBox->value());
+ if (!res)
+ {
+ slotAddPhotoFailed("");
+ return;
+ }
+
+ m_progressDlg->setLabelText(i18n("Uploading file %1").arg(pathComments.first.filename()));
+
+ if (m_progressDlg->isHidden())
+ m_progressDlg->show();
+}
+
+void FlickrWindow::slotAddPhotoSucceeded()
+{
+ // Remove photo uploaded from the list
+ m_imglst->removeItemByUrl(m_uploadQueue.first().first);
+ m_uploadQueue.pop_front();
+ m_uploadCount++;
+ m_progressDlg->setProgress(m_uploadCount, m_uploadTotal);
+ slotAddPhotoNext();
+}
+
+void FlickrWindow::slotAddPhotoFailed(const QString& msg)
+{
+ if (KMessageBox::warningContinueCancel(this,
+ i18n("Failed to upload photo into Flickr. %1\nDo you want to continue?").arg(msg))
+ != KMessageBox::Continue)
+ {
+ m_uploadQueue.clear();
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+ // refresh the thumbnails
+ //slotTagSelected();
+ }
+ else
+ {
+ m_uploadQueue.pop_front();
+ m_uploadTotal--;
+ m_progressDlg->setProgress(m_uploadCount, m_uploadTotal);
+ slotAddPhotoNext();
+ }
+}
+
+void FlickrWindow::slotAddPhotoCancel()
+{
+ m_uploadQueue.clear();
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+
+ m_talker->cancel();
+
+ // refresh the thumbnails
+ //slotTagSelected();
+}
+
+void FlickrWindow::slotImageListChanged(bool state)
+{
+ enableButton(User1, !state);
+}
+
+} // namespace KIPIFlickrExportPlugin
diff --git a/kipi-plugins/flickrexport/flickrwindow.h b/kipi-plugins/flickrexport/flickrwindow.h
new file mode 100644
index 0000000..a87e9ee
--- /dev/null
+++ b/kipi-plugins/flickrexport/flickrwindow.h
@@ -0,0 +1,167 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-17-06
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 FLICKRWINDOW_H
+#define FLICKRWINDOW_H
+
+// Qt includes.
+
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qintdict.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Libkipi includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QPushButton;
+class QSpinBox;
+class QCheckBox;
+class QProgressDialog;
+
+class KLineEdit;
+class KHTMLPart;
+class KURL;
+
+namespace KIPI
+{
+class Interface;
+}
+
+namespace KWallet
+{
+class Wallet;
+}
+
+namespace KIPIFlickrExportPlugin
+{
+
+class FlickrWidget;
+class FlickrTalker;
+class FPhotoInfo;
+class FPhotoSet;
+class GPhoto;
+class GAlbum;
+class GAlbumViewItem;
+class ImagesList;
+
+class FlickrWindow : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ FlickrWindow(KIPI::Interface *interface, const QString &tmpFolder, QWidget *parent);
+ ~FlickrWindow();
+
+private slots:
+
+ void slotTokenObtained(const QString& token);
+ void slotDoLogin();
+ void slotBusy(bool val);
+ void slotError(const QString& msg);
+
+// void slotLoginFailed( const QString& msg );
+// void slotAlbums( const QValueList<GAlbum>& albumList );
+// void slotPhotos( const QValueList<GPhoto>& photoList );
+// void slotTagSelected();
+// void slotOpenPhoto( const KURL& url );
+
+ void slotNewPhotoSet();
+ void slotUserChangeRequest();
+ void slotListPhotoSetsResponse(const QValueList <FPhotoSet>& photoSetList);
+ void slotAddPhotoNext();
+ void slotAddPhotoSucceeded();
+ void slotAddPhotoFailed(const QString& msg);
+ void slotAddPhotoCancel();
+ void slotAuthCancel();
+ void slotHelp();
+ void slotClose();
+ void slotUser1();
+ void slotImageListChanged(bool);
+
+private:
+
+ void readSettings();
+ void writeSettings();
+
+private:
+
+ unsigned int m_uploadCount;
+ unsigned int m_uploadTotal;
+
+// QPushButton *m_newAlbumBtn;
+ QPushButton *m_changeUserButton;
+
+ QCheckBox *m_resizeCheckBox;
+ QCheckBox *m_publicCheckBox;
+ QCheckBox *m_familyCheckBox;
+ QCheckBox *m_friendsCheckBox;
+ QCheckBox *m_exportHostTagsCheckBox;
+ QCheckBox *m_stripSpaceTagsCheckBox;
+
+ QSpinBox *m_dimensionSpinBox;
+ QSpinBox *m_imageQualitySpinBox;
+
+ QIntDict<GAlbumViewItem> m_albumDict;
+
+ QString m_token;
+ QString m_username;
+ QString m_userId;
+ QString m_lastSelectedAlbum;
+ QString m_tmp;
+
+ QLabel *m_userNameDisplayLabel;
+
+ QProgressDialog *m_progressDlg;
+ QProgressDialog *m_authProgressDlg;
+
+ QValueList< QPair<KURL, FPhotoInfo> > m_uploadQueue;
+
+// KWallet::Wallet *m_wallet;
+ KHTMLPart *m_photoView;
+
+ KLineEdit *m_tagsLineEdit;
+
+ FlickrWidget *m_widget;
+ FlickrTalker *m_talker;
+
+ ImagesList *m_imglst;
+
+ KIPI::Interface *m_interface;
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // namespace KIPIFlickrExportPlugin
+
+#endif /* FLICKRWINDOW_H */
diff --git a/kipi-plugins/flickrexport/imageslist.cpp b/kipi-plugins/flickrexport/imageslist.cpp
new file mode 100644
index 0000000..1127b40
--- /dev/null
+++ b/kipi-plugins/flickrexport/imageslist.cpp
@@ -0,0 +1,342 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2008-05-21
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#define ICONSIZE 64
+
+// QT includes.
+
+#include <qpushbutton.h>
+#include <qpainter.h>
+#include <qfileinfo.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qdragobject.h>
+#include <qimage.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <knuminput.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kio/previewjob.h>
+
+// Libkipi includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+#include <libkipi/imagecollection.h>
+
+// Local includes.
+
+#include "imageslist.h"
+#include "imageslist.moc"
+
+namespace KIPIFlickrExportPlugin
+{
+
+ImagesListViewItem::ImagesListViewItem(QListView *view, const KURL& url)
+ : QListViewItem(view)
+{
+ setThumb(SmallIcon("file_broken", ICONSIZE, KIcon::DisabledState));
+ setUrl(url);
+}
+
+ImagesListViewItem::~ImagesListViewItem()
+{
+}
+
+void ImagesListViewItem::setUrl(const KURL& url)
+{
+ m_url = url;
+ setText(1, m_url.fileName());
+}
+
+KURL ImagesListViewItem::url() const
+{
+ return m_url;
+}
+
+void ImagesListViewItem::setThumb(const QPixmap& pix)
+{
+ QPixmap pixmap(ICONSIZE+2, ICONSIZE+2);
+ pixmap.fill(Qt::color0);
+ QPainter p(&pixmap);
+ p.drawPixmap((pixmap.width()/2) - (pix.width()/2), (pixmap.height()/2) - (pix.height()/2), pix);
+ setPixmap(0, pixmap);
+}
+
+// ---------------------------------------------------------------------------
+
+ImagesListView::ImagesListView(QWidget *parent)
+ : QListView(parent)
+{
+ addColumn(i18n("Thumbnail"));
+ addColumn(i18n("File Name"));
+ QWhatsThis::add(this, i18n("<p>This is the list of images to upload on your Flickr account."));
+ setAcceptDrops(true);
+ setResizeMode(QListView::AllColumns);
+ setAllColumnsShowFocus(true);
+ setSorting(-1);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ setSelectionMode(QListView::Extended);
+}
+
+ImagesListView::~ImagesListView()
+{
+}
+
+void ImagesListView::dragEnterEvent(QDragEnterEvent *e)
+{
+ e->accept(QUriDrag::canDecode(e));
+}
+
+void ImagesListView::dropEvent(QDropEvent *e)
+{
+ QStrList strList;
+ KURL::List urls;
+
+ if (!QUriDrag::decode(e, strList))
+ return;
+
+ QStrList stringList;
+ QStrListIterator it(strList);
+ char *str;
+
+ while ((str = it.current()) != 0)
+ {
+ QString filePath = QUriDrag::uriToLocalFile(str);
+ QFileInfo fileInfo(filePath);
+
+ if (fileInfo.isFile() && fileInfo.exists())
+ urls.append(fileInfo.filePath());
+
+ ++it;
+ }
+
+ if (!urls.isEmpty())
+ emit signalDropedItems(urls);
+}
+
+// ---------------------------------------------------------------------------
+
+class ImagesPagePriv
+{
+public:
+
+ ImagesPagePriv()
+ {
+ listView = 0;
+ addButton = 0;
+ removeButton = 0;
+ iface = 0;
+ }
+
+ QPushButton *addButton;
+ QPushButton *removeButton;
+
+ ImagesListView *listView;
+
+ KIPI::Interface *iface;
+};
+
+ImagesList::ImagesList(QWidget* parent, KIPI::Interface *iface)
+ : QWidget(parent)
+{
+ d = new ImagesPagePriv;
+ d->iface = iface;
+
+ // --------------------------------------------------------
+
+ QGridLayout* grid = new QGridLayout(this, 2, 3);
+ d->listView = new ImagesListView(this);
+
+ // --------------------------------------------------------
+
+ d->addButton = new QPushButton(this);
+ d->removeButton = new QPushButton(this);
+ d->addButton->setText(i18n("&Add"));
+ d->addButton->setIconSet(SmallIcon("add"));
+ d->removeButton->setText(i18n("&Remove"));
+ d->removeButton->setIconSet(SmallIcon("remove"));
+
+ // --------------------------------------------------------
+
+ grid->addMultiCellWidget(d->listView, 0, 2, 0, 2);
+ grid->addMultiCellWidget(d->addButton, 0, 0, 3, 3);
+ grid->addMultiCellWidget(d->removeButton, 1, 1, 3, 3);
+ grid->setColStretch(0, 10);
+ grid->setRowStretch(2, 10);
+ grid->setMargin(KDialog::spacingHint());
+ grid->setSpacing(KDialog::spacingHint());
+
+ // --------------------------------------------------------
+
+ connect(d->addButton, SIGNAL(clicked()),
+ this, SLOT(slotAddItems()));
+
+ connect(d->removeButton, SIGNAL(clicked()),
+ this, SLOT(slotRemoveItems()));
+
+ connect(d->listView, SIGNAL(signalDropedItems(const KURL::List&)),
+ this, SLOT(slotAddImages(const KURL::List&)));
+
+ // --------------------------------------------------------
+
+ KIPI::ImageCollection images = d->iface->currentSelection();
+
+ if (images.isValid())
+ slotAddImages(images.images());
+}
+
+ImagesList::~ImagesList()
+{
+ delete d;
+}
+
+void ImagesList::slotAddImages(const KURL::List& list)
+{
+ if (list.count() == 0) return;
+
+ KURL::List urls;
+
+ for(KURL::List::const_iterator it = list.begin(); it != list.end(); ++it)
+ {
+ KURL imageUrl = *it;
+
+ // Check if the new item already exist in the list.
+
+ bool find = false;
+
+ QListViewItemIterator it(d->listView);
+ while (it.current())
+ {
+ ImagesListViewItem* item = dynamic_cast<ImagesListViewItem*>(*it);
+
+ if (item->url() == imageUrl)
+ find = true;
+
+ ++it;
+ }
+
+ if (!find)
+ {
+ new ImagesListViewItem(d->listView, imageUrl);
+ urls.append(imageUrl);
+ }
+ }
+
+ emit signalImageListChanged(imageUrls().isEmpty());
+
+ KIO::PreviewJob *thumbnailJob = KIO::filePreview(urls, ICONSIZE);
+
+ connect(thumbnailJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ this, SLOT(slotGotThumbnail(const KFileItem*, const QPixmap&)));
+}
+
+void ImagesList::slotGotThumbnail(const KFileItem *item, const QPixmap& pix)
+{
+ QListViewItemIterator it(d->listView);
+
+ while (it.current())
+ {
+ ImagesListViewItem *selItem = dynamic_cast<ImagesListViewItem*>(*it);
+ if (selItem->url() == item->url())
+ {
+ selItem->setPixmap(0, pix);
+ }
+ ++it;
+ }
+}
+
+void ImagesList::slotAddItems()
+{
+ KURL::List urls = KIPI::ImageDialog::getImageURLs(this, d->iface);
+ if (!urls.isEmpty())
+ slotAddImages(urls);
+
+ emit signalImageListChanged(imageUrls().isEmpty());
+}
+
+void ImagesList::slotRemoveItems()
+{
+ bool find;
+ do
+ {
+ find = false;
+ QListViewItemIterator it(d->listView);
+ while (it.current())
+ {
+ ImagesListViewItem* item = dynamic_cast<ImagesListViewItem*>(*it);
+ if (item->isSelected())
+ {
+ delete item;
+ find = true;
+ break;
+ }
+ ++it;
+ }
+ }
+ while(find);
+
+ emit signalImageListChanged(imageUrls().isEmpty());
+}
+
+void ImagesList::removeItemByUrl(const KURL& url)
+{
+ bool find;
+ do
+ {
+ find = false;
+ QListViewItemIterator it(d->listView);
+ while (it.current())
+ {
+ ImagesListViewItem* item = dynamic_cast<ImagesListViewItem*>(*it);
+ if (item->url() == url)
+ {
+ delete item;
+ find = true;
+ break;
+ }
+ ++it;
+ }
+ }
+ while(find);
+
+ emit signalImageListChanged(imageUrls().isEmpty());
+}
+
+KURL::List ImagesList::imageUrls() const
+{
+ KURL::List list;
+ QListViewItemIterator it(d->listView);
+ while (it.current())
+ {
+ ImagesListViewItem* item = dynamic_cast<ImagesListViewItem*>(*it);
+ list.append(item->url());
+ ++it;
+ }
+ return list;
+}
+
+} // namespace KIPIFlickrExportPlugin
diff --git a/kipi-plugins/flickrexport/imageslist.h b/kipi-plugins/flickrexport/imageslist.h
new file mode 100644
index 0000000..66363e8
--- /dev/null
+++ b/kipi-plugins/flickrexport/imageslist.h
@@ -0,0 +1,122 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2008-05-21
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IMAGES_LIST_H
+#define IMAGES_LIST_H
+
+// Qt includes.
+
+#include <qlistview.h>
+#include <qwidget.h>
+#include <qpixmap.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+class KFileItem;
+
+namespace KIPI
+{
+ class Interface;
+}
+
+namespace KIPIFlickrExportPlugin
+{
+
+class ImagesPagePriv;
+
+class ImagesListViewItem : public QListViewItem
+{
+
+public:
+
+ ImagesListViewItem(QListView *view, const KURL& url);
+ ~ImagesListViewItem();
+
+ void setUrl(const KURL& url);
+ KURL url() const;
+
+ void setThumb(const QPixmap& pix);
+
+private:
+
+ KURL m_url;
+};
+
+// ---------------------------------------------------------
+
+class ImagesListView : public QListView
+{
+ Q_OBJECT
+
+public:
+
+ ImagesListView(QWidget *parent);
+ ~ImagesListView();
+
+signals:
+
+ void signalDropedItems(const KURL::List&);
+
+private:
+
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dropEvent(QDropEvent *e);
+};
+
+// ---------------------------------------------------------
+
+class ImagesList : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ ImagesList(QWidget* parent, KIPI::Interface *iface);
+ ~ImagesList();
+
+ KURL::List imageUrls() const;
+ void removeItemByUrl(const KURL& url);
+
+signals:
+
+ void signalImageListChanged(bool);
+
+public slots:
+
+ void slotAddImages(const KURL::List& list);
+
+private slots:
+
+ void slotAddItems();
+ void slotRemoveItems();
+ void slotGotThumbnail(const KFileItem *item, const QPixmap& pix);
+
+private:
+
+ ImagesPagePriv *d;
+};
+
+} // namespace KIPIFlickrExportPlugin
+
+#endif // IMAGES_LIST_H
diff --git a/kipi-plugins/flickrexport/kipiplugin_flickrexport.desktop b/kipi-plugins/flickrexport/kipiplugin_flickrexport.desktop
new file mode 100644
index 0000000..f76ba1a
--- /dev/null
+++ b/kipi-plugins/flickrexport/kipiplugin_flickrexport.desktop
@@ -0,0 +1,55 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Flickr Exporter
+Name[br]=Ezporzher Flickr
+Name[ca]=Exportador a Flickr
+Name[cs]=Export do Flickru
+Name[de]=Flickr-Export
+Name[el]=Εξαγωγέας Flickr
+Name[es]=Exportador Flickr
+Name[et]=Flickri eksport
+Name[fi]=Flicr-vienti
+Name[ga]=Easpórtálaí Flickr
+Name[gl]=Exportazón a Flickr
+Name[is]=Flickr Útflutningur
+Name[it]=Esportazione a Flickr
+Name[nds]=Flickr-Exporteren
+Name[pa]=ਫਲਿਕਰ ਨਿਰਯਾਤਕ
+Name[pl]=Eksporter Flickr
+Name[pt]=Exportação para o Flickr
+Name[sr]=Flickr извозник
+Name[sr@Latn]=Flickr izvoznik
+Name[sv]=Export till Flickr
+Name[tg]=Воридкунандаи ларзиши акс
+Name[xx]=xxFlickr Exporterxx
+Name[zh_CN]=Flickr 导出器
+Comment=KIPI Remote Flickr Export Plugin
+Comment[ca]=Connector del KIPI per exportar remotament al Flickr
+Comment[cs]=KIPI modul exportu do Flickru
+Comment[da]=KIPI Eksternt Flickr eksport plugin
+Comment[de]=Ein KIPI-Modul zum Exportieren von Bildern zu Flickr
+Comment[el]=Πρόσθετο απομακρυσμένης εξαγωγής Flickr του KIPI
+Comment[es]=Complemento de KIPI para exportación Flickr remota
+Comment[et]=KIPI Flickri ekspordiplugin
+Comment[fi]=Kipi-liitännäinen Flicr-vientiä varten
+Comment[fr]=Module externe KIPI pour exporter des images vers le site Flickr
+Comment[gl]=Plugin de KIPI para Exportar a un Flickr Remoto
+Comment[is]=KIPI íforrit til útflutnings á fjarlæga Flickr þjóna
+Comment[it]=Plugin per l'esportazione remota a Flickr di KIPI
+Comment[ja]=Kipi Flickr エクスポートプラグイン
+Comment[nds]=KIPI-Moduul för't Exporteren na Flickr
+Comment[nl]=KIPI-plugin voor het exporteren naar Flickr-galerij
+Comment[pa]=KIPI ਰਿਮੋਟ ਫਲਿਕਰ ਨਿਰਯਾਤ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Eksport do usługi sieciowej Flickr
+Comment[pt]='Plugin' do KIPI de Exportação para o Flickr Remoto
+Comment[pt_BR]=Plugin de Exportação Remota para o Flickr do KIPI
+Comment[sr]=KIPI прикључак за извоз у удаљени Flickr
+Comment[sr@Latn]=KIPI priključak za izvoz u udaljeni Flickr
+Comment[sv]=KIPI-insticksprogram för fjärrexport till Flickr
+Comment[tg]=Модули воридкунандаи ларзиши акси дурдастаи KIPI
+Comment[xx]=xxKIPI Remote Flickr Export Pluginxx
+Comment[zh_CN]=KIPI 远程 Flickr 导出插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_flickrexport
+author=Vardhman Jain, vardhman@gmail.com
diff --git a/kipi-plugins/flickrexport/login.cpp b/kipi-plugins/flickrexport/login.cpp
new file mode 100644
index 0000000..3f58188
--- /dev/null
+++ b/kipi-plugins/flickrexport/login.cpp
@@ -0,0 +1,123 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qlabel.h>
+#include <qframe.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+
+// KDE includes.
+
+#include <klocale.h>
+
+// Local includes.
+
+#include "login.h"
+#include "login.moc"
+
+namespace KIPIFlickrExportPlugin
+{
+
+FlickrLogin::FlickrLogin(QWidget* parent, const QString& header,
+ const QString& _name, const QString& _passwd)
+ : QDialog(parent)
+{
+ setSizeGripEnabled(false);
+
+ QVBoxLayout* vbox = new QVBoxLayout(this, 5, 5, "vbox");
+ m_headerLabel = new QLabel(this);
+ m_headerLabel->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed));
+ m_headerLabel->setText(header);
+
+ QFrame* hline = new QFrame(this, "hline");
+ hline->setFrameShape(QFrame::HLine);
+ hline->setFrameShadow(QFrame::Sunken);
+
+ QGridLayout* centerLayout = new QGridLayout(0, 1, 1, 5, 5);
+
+ m_nameEdit = new QLineEdit(this);
+ m_passwdEdit = new QLineEdit(this);
+ m_passwdEdit->setEchoMode(QLineEdit::Password);
+
+ QLabel* nameLabel = new QLabel(this);
+ nameLabel->setText(i18n("Username:"));
+
+ QLabel* passwdLabel = new QLabel(this);
+ passwdLabel->setText(i18n("Password:"));
+
+ centerLayout->addWidget(m_nameEdit, 0, 1);
+ centerLayout->addWidget(m_passwdEdit, 1, 1);
+ centerLayout->addWidget(nameLabel, 0, 0);
+ centerLayout->addWidget(passwdLabel, 1, 0);
+
+ QHBoxLayout* btnLayout = new QHBoxLayout(0, 0, 5);
+ btnLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
+
+ QPushButton *okBtn = new QPushButton(this);
+ okBtn->setAutoDefault(true);
+ okBtn->setDefault(true);
+ okBtn->setText(i18n("&OK"));
+
+ QPushButton *cancelBtn = new QPushButton(this);
+ cancelBtn->setText(i18n("&Cancel"));
+
+ btnLayout->addWidget( okBtn );
+ btnLayout->addWidget( cancelBtn );
+
+ vbox->addWidget(m_headerLabel);
+ vbox->addWidget(hline);
+ vbox->addLayout(centerLayout);
+ vbox->addLayout(btnLayout);
+
+ resize( QSize(300, 150).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+
+ m_nameEdit->setText(_name);
+ m_passwdEdit->setText(_passwd);
+
+ // ---------------------------------------------------------------
+
+ connect(okBtn, SIGNAL( clicked() ),
+ this, SLOT( accept() ));
+
+ connect(cancelBtn, SIGNAL( clicked() ),
+ this, SLOT( reject() ));
+}
+
+FlickrLogin::~FlickrLogin()
+{
+}
+
+QString FlickrLogin::name() const
+{
+ return m_nameEdit->text();
+}
+
+QString FlickrLogin::password() const
+{
+ return m_passwdEdit->text();
+}
+
+} // namespace KIPIFlickrExportPlugin
diff --git a/kipi-plugins/flickrexport/login.h b/kipi-plugins/flickrexport/login.h
new file mode 100644
index 0000000..84dbaad
--- /dev/null
+++ b/kipi-plugins/flickrexport/login.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 FLICKRLOGIN_H
+#define FLICKRLOGIN_H
+
+// Qt includes.
+
+#include <qdialog.h>
+
+class QLabel;
+class QLineEdit;
+
+namespace KIPIFlickrExportPlugin
+{
+
+class FlickrLogin : public QDialog
+{
+ Q_OBJECT
+
+public:
+
+ FlickrLogin(QWidget* parent, const QString& header,
+ const QString& _name=QString(),
+ const QString& _passwd=QString());
+ ~FlickrLogin();
+
+ QString name() const;
+ QString password() const;
+
+private:
+
+ QLabel *m_headerLabel;
+ QLineEdit *m_nameEdit;
+ QLineEdit *m_passwdEdit;
+};
+
+} // namespace KIPIFlickrExportPlugin
+
+#endif // FLICKRLOGIN_H
diff --git a/kipi-plugins/flickrexport/mpform.cpp b/kipi-plugins/flickrexport/mpform.cpp
new file mode 100644
index 0000000..462b0e4
--- /dev/null
+++ b/kipi-plugins/flickrexport/mpform.cpp
@@ -0,0 +1,163 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstring>
+#include <cstdio>
+
+// Qt includes.
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+
+// KDE includes.
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kurl.h>
+
+// Local includes.
+
+#include "mpform.h"
+
+namespace KIPIFlickrExportPlugin
+{
+
+MPForm::MPForm()
+{
+ m_boundary = "----------";
+ m_boundary += KApplication::randomString(42 + 13).ascii();
+}
+
+MPForm::~MPForm()
+{
+}
+
+void MPForm::reset()
+{
+ m_buffer.resize(0);
+}
+
+void MPForm::finish()
+{
+ QCString str;
+ str += "--";
+ str += m_boundary;
+ str += "--";
+
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << str;
+}
+
+bool MPForm::addPair(const QString& name, const QString& value)
+{
+ QCString str;
+
+ str += "--";
+ str += m_boundary;
+ str += "\r\n";
+ str += "Content-Disposition: form-data; name=\"";
+ str += name.ascii();
+ str += "\"";
+ str += "\r\n\r\n";
+ str += value.utf8();
+ str += "\r\n";
+
+ //uint oldSize = m_buffer.size();
+ //m_buffer.resize(oldSize + str.size());
+ //memcpy(m_buffer.data() + oldSize, str.data(), str.size());
+
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << QString::fromUtf8(str);
+
+ return true;
+}
+
+bool MPForm::addFile(const QString& name,const QString& path)
+{
+ KMimeType::Ptr ptr = KMimeType::findByURL(path);
+ QString mime = ptr->name();
+ if (mime.isEmpty())
+ {
+ // if we ourselves can't determine the mime of the local file,
+ // very unlikely the remote site will be able to identify it
+ return false;
+ }
+
+ QFile imageFile(path);
+ if (!imageFile.open(IO_ReadOnly))
+ return false;
+
+ QByteArray imageData = imageFile.readAll();
+ imageFile.close();
+
+ QCString str;
+
+ str += "--";
+ str += m_boundary;
+ str += "\r\n";
+ str += "Content-Disposition: form-data; name=\"";
+ str += name.ascii();
+ str += "\"; ";
+ str += "filename=\"";
+ str += QFile::encodeName(KURL(path).filename());
+ str += "\"";
+ str += "\r\n";
+ str += "Content-Type: ";
+ str += mime.ascii();
+ str += "\r\n\r\n";
+
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << str;
+
+ int oldSize = m_buffer.size();
+ m_buffer.resize(oldSize + imageData.size() + 2);
+ memcpy(m_buffer.data() + oldSize, imageData.data(), imageData.size());
+ m_buffer[m_buffer.size()-2] = '\r';
+ m_buffer[m_buffer.size()-1] = '\n';
+
+ return true;
+}
+
+QString MPForm::contentType() const
+{
+ return QString("Content-Type: multipart/form-data; boundary=" + m_boundary);
+}
+
+QString MPForm::boundary() const
+{
+ return m_boundary;
+}
+
+QByteArray MPForm::formData() const
+{
+ return m_buffer;
+}
+
+} // namespace KIPIFlickrExportPlugin
diff --git a/kipi-plugins/flickrexport/mpform.h b/kipi-plugins/flickrexport/mpform.h
new file mode 100644
index 0000000..89d958d
--- /dev/null
+++ b/kipi-plugins/flickrexport/mpform.h
@@ -0,0 +1,61 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 MPFORM_H
+#define MPFORM_H
+
+// Qt includes.
+
+#include <qcstring.h>
+#include <qstring.h>
+
+namespace KIPIFlickrExportPlugin
+{
+
+class MPForm
+{
+
+public:
+
+ MPForm();
+ ~MPForm();
+
+ void finish();
+ void reset();
+
+ bool addPair(const QString& name, const QString& value);
+ bool addFile(const QString& name, const QString& path);
+
+ QString contentType() const;
+ QByteArray formData() const;
+ QString boundary() const;
+
+private:
+
+ QByteArray m_buffer;
+ QCString m_boundary;
+};
+
+} // namespace KIPIFlickrExportPlugin
+
+#endif /* MPFORM_H */
diff --git a/kipi-plugins/flickrexport/plugin_flickrexport.cpp b/kipi-plugins/flickrexport/plugin_flickrexport.cpp
new file mode 100644
index 0000000..101aaae
--- /dev/null
+++ b/kipi-plugins/flickrexport/plugin_flickrexport.cpp
@@ -0,0 +1,114 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-17-06
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C ansi includes.
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+
+// libkipi includes.
+
+#include <libkipi/interface.h>
+
+// Local includes.
+
+#include "flickrwindow.h"
+#include "plugin_flickrexport.h"
+#include "plugin_flickrexport.moc"
+
+typedef KGenericFactory<Plugin_FlickrExport> Factory;
+
+K_EXPORT_COMPONENT_FACTORY(kipiplugin_flickrexport, Factory("kipiplugin_flickrexport"))
+
+Plugin_FlickrExport::Plugin_FlickrExport(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin(Factory::instance(), parent, "FlickrExport")
+{
+ kdDebug(51001) << "Plugin_FlickrExport plugin loaded" << endl;
+}
+
+void Plugin_FlickrExport::setup(QWidget* widget)
+{
+ KIPI::Plugin::setup(widget);
+
+ m_action = new KAction(i18n("Export to Flickr..."),
+ "www",
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "flickrexport");
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ m_action->setEnabled(false);
+ return;
+ }
+
+ m_action->setEnabled(true);
+ addAction(m_action);
+}
+
+Plugin_FlickrExport::~Plugin_FlickrExport()
+{
+}
+
+void Plugin_FlickrExport::slotActivate()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KStandardDirs dir;
+ QString Tmp = dir.saveLocation("tmp", "kipi-flickrexportplugin-" + QString::number(getpid()) + "/");
+
+ // We clean it up in the close button
+ m_dlg = new KIPIFlickrExportPlugin::FlickrWindow(interface, Tmp, kapp->activeWindow());
+ m_dlg->show();
+}
+
+KIPI::Category Plugin_FlickrExport::category( KAction* action ) const
+{
+ if (action == m_action)
+ return KIPI::EXPORTPLUGIN;
+
+ kdWarning(51000) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::EXPORTPLUGIN;
+}
diff --git a/kipi-plugins/flickrexport/plugin_flickrexport.h b/kipi-plugins/flickrexport/plugin_flickrexport.h
new file mode 100644
index 0000000..282686d
--- /dev/null
+++ b/kipi-plugins/flickrexport/plugin_flickrexport.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-17-06
+ * Description : a kipi plugin to export images to Flickr web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_FLICKREXPORT_H
+#define PLUGIN_FLICKREXPORT_H
+
+// libKIPI includes.
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+using namespace KIPIFlickrExportPlugin;
+
+class Plugin_FlickrExport : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_FlickrExport(QObject *parent, const char* name, const QStringList &args);
+ ~Plugin_FlickrExport();
+
+ virtual KIPI::Category category(KAction* action) const;
+ virtual void setup(QWidget*);
+
+public slots:
+
+ void slotActivate();
+
+private:
+
+ KAction *m_action;
+ FlickrWindow *m_dlg;
+};
+
+#endif // PLUGIN_FLICKREXPORT_H
diff --git a/kipi-plugins/galleryexport/Makefile.am b/kipi-plugins/galleryexport/Makefile.am
new file mode 100644
index 0000000..838324a
--- /dev/null
+++ b/kipi-plugins/galleryexport/Makefile.am
@@ -0,0 +1,31 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKEXIV2_CFLAGS) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_galleryexport.la
+
+kipiplugin_galleryexport_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP)
+
+kipiplugin_galleryexport_la_SOURCES = plugin_galleryexport.cpp \
+ galleries.cpp gallerylist.cpp galleryconfig.cpp \
+ gallerywindow.cpp gallerytalker.cpp \
+ gallerywidget.cpp gallerympform.cpp galleryalbumdialog.ui \
+ galleryviewitem.cpp
+
+kipiplugin_galleryexport_la_LIBADD = $(LIBKEXIV2_LIBS) \
+ -lkwalletclient $(LIB_KHTML) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_galleryexport_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+kde_services_DATA = kipiplugin_galleryexport.desktop
+
+kipiplugin_galleryexportpicsdir = $(kde_datadir)/kipiplugin_galleryexport/pics
+kipiplugin_galleryexportpics_DATA = gallery.png
+
+#kipiplugin_galleryexporticondir = $(kde_datadir)/kipiplugin_galleryexport/icons
+#kipiplugin_galleryexporticon_ICON = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_galleryexport.pot
+
diff --git a/kipi-plugins/galleryexport/TODO b/kipi-plugins/galleryexport/TODO
new file mode 100644
index 0000000..fcff8e0
--- /dev/null
+++ b/kipi-plugins/galleryexport/TODO
@@ -0,0 +1,13 @@
+Somewhat immediate implementation needed:
+
+* Implement *.ui files for all dialogs that don't want to be kdialog[base] based
+* Return more sensible error strings
+* Implement logging to backtrace problems
+* Abstract the communications layer 100%
+* Rename to websync
+* Add support for other web backends
+
+For the lazy times:
+
+* Polish the html code used to render the thumbnails, better
+ fonts sizes and layout
diff --git a/kipi-plugins/galleryexport/galleries.cpp b/kipi-plugins/galleryexport/galleries.cpp
new file mode 100644
index 0000000..c38baff
--- /dev/null
+++ b/kipi-plugins/galleryexport/galleries.cpp
@@ -0,0 +1,250 @@
+/* ============================================================
+ * File : galleries.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include <qstring.h>
+
+#include <qwidget.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kdeversion.h>
+#if KDE_IS_VERSION(3,2,0)
+#include <kwallet.h>
+#endif
+
+#include "galleries.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+
+Gallery::Gallery(const QString& name, const QString& url,
+ const QString& username, const QString& password,
+ const unsigned int version,
+ const unsigned int galleryId)
+ : mName(name),
+ mUrl(url),
+ mUsername(username),
+ mPassword(password),
+ mVersion(version),
+ mGalleryId(galleryId)
+{
+
+}
+
+Gallery::~Gallery()
+{
+
+}
+
+QString Gallery::name() const { return mName; }
+QString Gallery::url() const { return mUrl; }
+QString Gallery::username() const { return mUsername; }
+QString Gallery::password() const { return mPassword; }
+unsigned int Gallery::version() const { return mVersion; }
+unsigned int Gallery::galleryId() const { return mGalleryId; }
+
+void Gallery::setName(QString name) { mName = name; }
+void Gallery::setUrl(QString url) { mUrl = url; }
+void Gallery::setUsername(QString username) { mUsername = username; }
+void Gallery::setPassword(QString password) { mPassword = password; }
+void Gallery::setVersion(unsigned int version) { mVersion = version; }
+void Gallery::setGalleryId(unsigned int galleryId) { mGalleryId = galleryId; }
+
+
+QListViewItem* Gallery::asQListViewItem(QListView* pParent)
+{
+ QListViewItem* p_lvi = (QListViewItem*) new GalleryQListViewItem(this, pParent);
+ return p_lvi;
+}
+
+
+
+GalleryQListViewItem::GalleryQListViewItem(Gallery* pGallery, QListView* pParent)
+ : QListViewItem(pParent, pGallery->name(), pGallery->url(), pGallery->username()),
+ mpGallery(pGallery)
+{
+}
+
+Gallery* GalleryQListViewItem::GetGallery()
+{
+ return mpGallery;
+}
+
+void GalleryQListViewItem::Refresh()
+{
+ setText(0, mpGallery->name());
+ setText(1, mpGallery->url());
+ setText(2, mpGallery->username());
+}
+
+
+
+Galleries::Galleries()
+ : mpWallet(0),
+ mMaxGalleryId(0)
+{
+}
+
+Galleries::~Galleries()
+{
+ if (mpWallet)
+ delete mpWallet;
+
+ // Todo: clear up mGalleries
+}
+
+void Galleries::Load()
+{
+ static bool bln_loaded = false;
+ if (bln_loaded) return;
+ bln_loaded = true;
+
+ bool bln_use_wallet = false;
+#if KDE_IS_VERSION(3,2,0)
+ mpWallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(),
+ kapp->activeWindow()->winId(),
+ KWallet::Wallet::Synchronous);
+ if (!mpWallet)
+ {
+ kdWarning() << "Failed to open kwallet" << endl;
+ }
+ else
+ {
+ if (!mpWallet->hasFolder("KIPIGallerySyncPlugin"))
+ {
+ if (!mpWallet->createFolder("KIPIGallerySyncPlugin"))
+ kdWarning() << "Failed to create kwallet folder" << endl;
+ }
+
+ if (!mpWallet->setFolder("KIPIGallerySyncPlugin"))
+ kdWarning() << "Failed to set kwallet folder" << endl;
+ else
+ bln_use_wallet = true;
+ }
+#endif
+
+
+ // read config
+ KConfig config("kipirc");
+ config.setGroup("GallerySync Settings");
+ QValueList<int> gallery_ids = config.readIntListEntry("Galleries");
+
+ config.setGroup("GallerySync Galleries");
+ QString name, url, username, password = "";
+ int version;
+ for (QValueList<int>::Iterator it = gallery_ids.begin(); it != gallery_ids.end(); ++it)
+ {
+ unsigned int gallery_id = (*it);
+
+ if (gallery_id > mMaxGalleryId)
+ mMaxGalleryId = gallery_id;
+
+ // Load the gallery with this id.
+ name = config.readEntry(QString("Name%1").arg(gallery_id));
+ url = config.readEntry(QString("URL%1").arg(gallery_id));
+ username = config.readEntry(QString("Username%1").arg(gallery_id));
+ version = config.readNumEntry(QString("Version%1").arg(gallery_id));
+ if (bln_use_wallet)
+ mpWallet->readPassword(QString("Password%1").arg(gallery_id), password);
+
+ Gallery* p_gallery = new Gallery(name, url, username, password, version, gallery_id);
+ mGalleries.append(p_gallery);
+ }
+}
+
+
+void Galleries::Add(Gallery* pGallery)
+{
+ mGalleries.append(pGallery);
+}
+
+void Galleries::Remove(Gallery* pGallery)
+{
+ mGalleries.remove(pGallery);
+
+ // Slight cosmetic thing for gallery numbering.
+ if (mGalleries.isEmpty())
+ mMaxGalleryId = 0;
+}
+
+
+void Galleries::Save()
+{
+ QValueList<int> gallery_ids;
+ KConfig config("kipirc");
+ config.deleteGroup("GallerySync Galleries");
+ config.setGroup("GallerySync Galleries");
+
+ bool bln_use_wallet = false;
+ if (mpWallet)
+ {
+ if (mpWallet->hasFolder("KIPIGallerySyncPlugin"))
+ {
+ if (!mpWallet->removeFolder("KIPIGallerySyncPlugin"))
+ kdWarning() << "Failed to clear kwallet folder" << endl;
+ }
+ if (!mpWallet->createFolder("KIPIGallerySyncPlugin"))
+ kdWarning() << "Failed to create kwallet folder" << endl;
+
+ if (!mpWallet->setFolder("KIPIGallerySyncPlugin"))
+ kdWarning() << "Failed to set kwallet folder" << endl;
+ else
+ bln_use_wallet = true;
+ }
+
+ for (GalleryPtrList::iterator it = mGalleries.begin(); it != mGalleries.end(); ++it)
+ {
+ Gallery* p_gallery = (*it);
+ if (!p_gallery->galleryId())
+ p_gallery->setGalleryId(++mMaxGalleryId);
+ unsigned int gallery_id = p_gallery->galleryId();
+ gallery_ids.append(gallery_id);
+
+ config.writeEntry(QString("Name%1").arg(gallery_id), p_gallery->name());
+ config.writeEntry(QString("URL%1").arg(gallery_id), p_gallery->url());
+ config.writeEntry(QString("Username%1").arg(gallery_id), p_gallery->username());
+ config.writeEntry(QString("Version%1").arg(gallery_id), p_gallery->version());
+ if (bln_use_wallet)
+ mpWallet->writePassword(QString("Password%1").arg(gallery_id), p_gallery->password());
+ }
+
+ config.setGroup("GallerySync Settings");
+ config.writeEntry("Galleries", gallery_ids);
+}
+
+QListView* Galleries::asQListView(QWidget* pParent)
+{
+ Load();
+
+ QListView* p_lv = new QListView (pParent);
+ p_lv->addColumn(i18n("Gallery Name"));
+ p_lv->addColumn(i18n("URL"));
+ p_lv->addColumn(i18n("User"));
+ p_lv->setAllColumnsShowFocus(true);
+
+ for (GalleryPtrList::iterator it = mGalleries.begin(); it != mGalleries.end(); ++it)
+ {
+ (*it)->asQListViewItem(p_lv);
+ }
+
+ return p_lv;
+}
+
+}
diff --git a/kipi-plugins/galleryexport/galleries.h b/kipi-plugins/galleryexport/galleries.h
new file mode 100644
index 0000000..c9a8dd1
--- /dev/null
+++ b/kipi-plugins/galleryexport/galleries.h
@@ -0,0 +1,112 @@
+/* ============================================================
+ * File : galleries.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 GALLERIES_H
+#define GALLERIES_H
+
+#include <qptrlist.h>
+#include <qlistview.h>
+
+namespace KWallet
+{
+class Wallet;
+}
+
+namespace KIPIGalleryExportPlugin
+{
+
+class Gallery
+{
+public:
+
+ Gallery(const QString& name = i18n("New Gallery"),
+ const QString& url = QString("http://www.newgallery.com/"),
+ const QString& username = QString(),
+ const QString& password = QString(),
+ const unsigned int version = 2,
+ const unsigned int galleryId = 0);
+ ~Gallery();
+
+ QString name() const;
+ QString url() const;
+ QString username() const;
+ QString password() const;
+ unsigned int version() const;
+ unsigned int galleryId() const;
+
+ void setName(QString name);
+ void setUrl(QString url);
+ void setUsername(QString username);
+ void setPassword(QString password);
+ void setVersion(unsigned int version);
+ void setGalleryId(unsigned int galleryId);
+
+ QListViewItem* asQListViewItem(QListView* pParent);
+
+private:
+
+ QString mName;
+ QString mUrl;
+ QString mUsername;
+ QString mPassword;
+ unsigned int mVersion;
+
+ unsigned int mGalleryId;
+};
+
+
+/* Simple Stub Class to allow easy access to Galleries from GUI elements */
+class GalleryQListViewItem : public QListViewItem
+{
+public:
+ GalleryQListViewItem(Gallery* pGallery, QListView* pParent);
+
+ Gallery* GetGallery();
+ void Refresh();
+private:
+ Gallery* mpGallery;
+};
+
+
+typedef QPtrList<Gallery> GalleryPtrList;
+
+/* Container class for all Galleries */
+class Galleries
+{
+public:
+ Galleries();
+ ~Galleries();
+
+ void Add(Gallery* pGallery);
+ void Remove(Gallery* pGallery);
+ void Save();
+ QListView* asQListView(QWidget* pParent);
+
+private:
+ void Load();
+
+ KWallet::Wallet* mpWallet;
+
+ GalleryPtrList mGalleries;
+ unsigned int mMaxGalleryId;
+};
+
+
+}
+
+#endif /* GALLERIES_H */
diff --git a/kipi-plugins/galleryexport/gallery.png b/kipi-plugins/galleryexport/gallery.png
new file mode 100644
index 0000000..849eea9
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallery.png
Binary files differ
diff --git a/kipi-plugins/galleryexport/galleryalbumdialog.ui b/kipi-plugins/galleryexport/galleryalbumdialog.ui
new file mode 100644
index 0000000..2dfbf6a
--- /dev/null
+++ b/kipi-plugins/galleryexport/galleryalbumdialog.ui
@@ -0,0 +1,197 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>KIPIGalleryExportPlugin::GalleryAlbumDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>GalleryAlbumDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>342</width>
+ <height>180</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>MyDialog</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>10</number>
+ </property>
+ <property name="spacing">
+ <number>5</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>header</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;h3&gt;Enter New Album Name&lt;/h3&gt;</string>
+ </property>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>hline1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>titleLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Title (optional):</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>nameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Name (optional):</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>captionLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Caption (optional):</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>titleEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>nameEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>captionEdit</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>hline2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>GalleryAlbumDialog</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>GalleryAlbumDialog</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kipi-plugins/galleryexport/galleryconfig.cpp b/kipi-plugins/galleryexport/galleryconfig.cpp
new file mode 100644
index 0000000..65fd7f4
--- /dev/null
+++ b/kipi-plugins/galleryexport/galleryconfig.cpp
@@ -0,0 +1,161 @@
+/* ============================================================
+ * File : galleryconfig.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qlineedit.h>
+#include <qprogressdialog.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+#include <krun.h>
+#include <kdebug.h>
+#include <kconfig.h>
+
+// KIPI include files
+
+#include <libkipi/version.h>
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "galleryconfig.h"
+#include "galleries.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+GalleryEdit::GalleryEdit(QWidget* pParent,
+ Gallery* pGallery,
+ QString title)
+ : KDialogBase(pParent, 0, true, title, Ok|Cancel, Ok, false),
+ mpGallery(pGallery)
+{
+ setButtonGuiItem( Ok, KStdGuiItem::save() );
+
+ QFrame *page = new QFrame (this);
+ QHBoxLayout *tll = new QHBoxLayout(page);
+ page->setMinimumSize (500, 200);
+ setMainWidget(page);
+
+ QVBoxLayout* vbox = new QVBoxLayout();
+ vbox->setSpacing (KDialog::spacingHint());
+ tll->addItem(vbox);
+
+ mpHeaderLabel = new QLabel(page);
+ mpHeaderLabel->setSizePolicy(QSizePolicy(QSizePolicy::Minimum,
+ QSizePolicy::Fixed));
+ mpHeaderLabel->setText(title);
+ vbox->addWidget(mpHeaderLabel);
+
+ QFrame* hline = new QFrame(page, "hline");
+ hline->setFrameShape(QFrame::HLine);
+ hline->setFrameShadow(QFrame::Sunken);
+ hline->setFrameShape(QFrame::HLine);
+ vbox->addWidget(hline);
+
+ QGridLayout* centerLayout = new QGridLayout(0, 1, 1, 5, 5);
+
+ mpNameEdit = new QLineEdit( this );
+ centerLayout->addWidget(mpNameEdit, 0, 1);
+
+ mpUrlEdit = new QLineEdit( this );
+ centerLayout->addWidget(mpUrlEdit, 1, 1);
+
+ mpUsernameEdit = new QLineEdit( this );
+ centerLayout->addWidget(mpUsernameEdit, 2, 1);
+
+ mpPasswordEdit = new QLineEdit( this );
+ mpPasswordEdit->setEchoMode(QLineEdit::Password);
+ centerLayout->addWidget(mpPasswordEdit, 3, 1);
+
+ QLabel* name_label = new QLabel(this);
+ name_label->setText(i18n( "Name:" ));
+ centerLayout->addWidget(name_label, 0, 0);
+
+ QLabel* urlLabel = new QLabel(this);
+ urlLabel->setText(i18n( "URL:" ));
+ centerLayout->addWidget(urlLabel, 1, 0);
+
+ QLabel* nameLabel = new QLabel(this);
+ nameLabel->setText(i18n( "Username:" ));
+ centerLayout->addWidget(nameLabel, 2, 0);
+
+ QLabel* passwdLabel = new QLabel(this);
+ passwdLabel->setText(i18n( "Password:" ));
+ centerLayout->addWidget(passwdLabel, 3, 0);
+
+ //---------------------------------------------
+ mpGalleryVersion = new QCheckBox( i18n("Use &Gallery 2"), this);
+ mpGalleryVersion->setChecked( 2 == pGallery->version() );
+ centerLayout->addWidget( mpGalleryVersion, 4, 1 );
+ //---------------------------------------------
+
+ vbox->addLayout( centerLayout );
+
+ resize( QSize(300, 150).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+
+ mpNameEdit->setText(pGallery->name());
+ mpUrlEdit->setText(pGallery->url());
+ mpUsernameEdit->setText(pGallery->username());
+ mpPasswordEdit->setText(pGallery->password());
+}
+
+GalleryEdit::~GalleryEdit()
+{
+
+}
+
+void GalleryEdit::slotOk(void)
+{
+ if (mpNameEdit->isModified())
+ mpGallery->setName(mpNameEdit->text());
+ if (mpUrlEdit->isModified())
+ mpGallery->setUrl(mpUrlEdit->text());
+ if (mpUsernameEdit->isModified())
+ mpGallery->setUsername(mpUsernameEdit->text());
+ if (mpPasswordEdit->isModified())
+ mpGallery->setPassword(mpPasswordEdit->text());
+ if (mpGalleryVersion->isChecked())
+ mpGallery->setVersion(2);
+ else
+ mpGallery->setVersion(1);
+ accept();
+}
+
+}
+
+#include "galleryconfig.moc"
+
diff --git a/kipi-plugins/galleryexport/galleryconfig.h b/kipi-plugins/galleryexport/galleryconfig.h
new file mode 100644
index 0000000..0aaedcc
--- /dev/null
+++ b/kipi-plugins/galleryexport/galleryconfig.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ * File : galleryconfig.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 GALLERYCONFIG_H
+#define GALLERYCONFIG_H
+
+#include <kdialogbase.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qintdict.h>
+
+namespace KIPIGalleryExportPlugin
+{
+
+class Gallery;
+
+class GalleryEdit : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ GalleryEdit(QWidget* pParent,
+ Gallery* pGallery,
+ QString title);
+ ~GalleryEdit();
+
+private:
+
+ Gallery* mpGallery;
+ QLabel* mpHeaderLabel;
+ QLineEdit* mpNameEdit;
+ QLineEdit* mpUrlEdit;
+ QLineEdit* mpUsernameEdit;
+ QLineEdit* mpPasswordEdit;
+ QCheckBox* mpGalleryVersion;
+
+private slots:
+ void slotOk(void);
+};
+
+}
+
+#endif /* GALLERYCONFIG_H */
diff --git a/kipi-plugins/galleryexport/galleryitem.h b/kipi-plugins/galleryexport/galleryitem.h
new file mode 100644
index 0000000..89661ec
--- /dev/null
+++ b/kipi-plugins/galleryexport/galleryitem.h
@@ -0,0 +1,88 @@
+/* ============================================================
+ * File : galleryitem.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-04
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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 bythe 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 GALLERYITEM_H
+#define GALLERYITEM_H
+
+#include <qstring.h>
+
+namespace KIPIGalleryExportPlugin
+{
+
+class GPhoto
+{
+public:
+
+ GPhoto()
+ {
+ ref_num = -1;
+ }
+
+ int ref_num;
+ int album_num;
+ QString name;
+ QString caption;
+ QString thumbName;
+ QString albumURL;
+};
+
+class GAlbum
+{
+public:
+
+ GAlbum()
+ {
+ ref_num = -1;
+ parent_ref_num = -1;
+
+ add = false;
+ write = false;
+ del_item = false;
+ del_alb = false;
+ create_sub = false;
+ }
+
+ bool operator<(const GAlbum& rhs) const
+ {
+ if (parent_ref_num == rhs.parent_ref_num)
+ return ref_num < rhs.ref_num;
+
+ return parent_ref_num < rhs.parent_ref_num;
+ }
+
+ int ref_num;
+ int parent_ref_num;
+ QString name;
+ QString parentName;
+ QString title;
+ QString summary;
+ QString baseurl;
+
+ bool add;
+ bool write;
+ bool del_item;
+ bool del_alb;
+ bool create_sub;
+};
+
+}
+
+#endif /* GALLERYITEM_H */
diff --git a/kipi-plugins/galleryexport/gallerylist.cpp b/kipi-plugins/galleryexport/gallerylist.cpp
new file mode 100644
index 0000000..36192d5
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerylist.cpp
@@ -0,0 +1,208 @@
+/* ============================================================
+ * File : gallerylist.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qlineedit.h>
+#include <qprogressdialog.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+
+// Local includes.
+
+#include "galleries.h"
+#include "gallerylist.h"
+#include "galleryconfig.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+GalleryList::GalleryList(QWidget *pParent, Galleries* pGalleries, bool blnShowOpen)
+ : KDialogBase(pParent, 0, true, i18n("Remote Galleries"),
+ Ok|Close|User1|User2|User3,
+ Close, false),
+ mpGalleries(pGalleries),
+ mpCurrentGallery(0)
+{
+ if (!blnShowOpen)
+ showButtonOK(false);
+
+ setButtonGuiItem(User3, KStdGuiItem::add());
+ setButtonGuiItem(User2, KStdGuiItem::configure());
+ setButtonGuiItem(User1, KStdGuiItem::remove());
+ setButtonGuiItem(Close, KStdGuiItem::close());
+ setButtonGuiItem(Ok, KStdGuiItem::open());
+
+ enableButton(Ok, false);
+ enableButton(User1, false);
+ enableButton(User2, false);
+
+ QFrame *page = new QFrame(this);
+ QHBoxLayout *tll = new QHBoxLayout(page);
+ page->setMinimumSize(400, 200);
+ setMainWidget(page);
+
+ QHBoxLayout *hb = new QHBoxLayout();
+ hb->setSpacing(KDialog::spacingHint());
+ tll->addItem(hb);
+
+ QLabel *label = new QLabel(page);
+ hb->addWidget(label);
+ label->setPixmap(UserIcon("gallery"));
+ label->setFrameStyle (QFrame::Panel | QFrame::Sunken);
+ label->setAlignment(Qt::AlignTop);
+ QVBoxLayout *vb = new QVBoxLayout();
+ vb->setSpacing (KDialog::spacingHint());
+ tll->addItem(vb);
+
+ mpGalleryList = mpGalleries->asQListView(page);
+ vb->addWidget(mpGalleryList);
+ connect(mpGalleryList, SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
+ connect(mpGalleryList, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)),
+ this, SLOT(doubleClicked(QListViewItem*, const QPoint&, int)));
+}
+
+GalleryList::~GalleryList()
+{
+
+}
+
+Gallery* GalleryList::GetGallery()
+{
+ return mpCurrentGallery;
+}
+
+void GalleryList::selectionChanged()
+{
+ QListViewItem* p_lvi = mpGalleryList->selectedItem();
+ bool bln_selected = (p_lvi ? true : false);
+ enableButton(User1, bln_selected);
+ enableButton(User2, bln_selected);
+ enableButton(Ok, bln_selected);
+
+ if (bln_selected)
+ {
+ GalleryQListViewItem* p_glvi = dynamic_cast<GalleryQListViewItem*>(p_lvi);
+ mpCurrentGallery = p_glvi->GetGallery();
+ }
+ else
+ {
+ mpCurrentGallery = 0;
+ }
+}
+
+void GalleryList::doubleClicked(QListViewItem* pCurrent, const QPoint&, int)
+{
+ if (!pCurrent)
+ return;
+
+ if (actionButton(Ok)->isVisible())
+ {
+ accept();
+ }
+ else
+ {
+ slotUser2();
+ }
+}
+
+//================== Add =====
+void GalleryList::slotUser3(void)
+{
+ Gallery* p_gallery = new Gallery();
+ GalleryEdit dlg(this, p_gallery, i18n("New Remote Gallery"));
+ if (QDialog::Accepted == dlg.exec())
+ {
+ mpGalleries->Add(p_gallery);
+ mpGalleries->Save();
+ p_gallery->asQListViewItem(mpGalleryList);
+ }
+ else
+ {
+ delete p_gallery;
+ }
+}
+
+
+//================== Edit ======
+void GalleryList::slotUser2(void)
+{
+ QListViewItem* p_lvi = mpGalleryList->selectedItem();
+ if (!p_lvi)
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("No gallery selected!"));
+ }
+ else
+ {
+ GalleryQListViewItem* p_glvi = dynamic_cast<GalleryQListViewItem*>(p_lvi);
+ GalleryEdit dlg(this, p_glvi->GetGallery(), i18n("Edit Remote Gallery"));
+ if (QDialog::Accepted == dlg.exec())
+ {
+ p_glvi->Refresh();
+ mpGalleries->Save();
+ }
+ }
+}
+
+
+//================== Remove ======
+void GalleryList::slotUser1(void)
+{
+ QListViewItem* p_lvi = mpGalleryList->selectedItem();
+ if (!p_lvi)
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("No gallery selected!"));
+ }
+ else
+ {
+ if (KMessageBox::Yes ==
+ KMessageBox::warningYesNo(kapp->activeWindow(),
+ i18n("Are you sure you want to remove this gallery? "
+ "All synchronisaton settings will be lost. "
+ "You cannot undo this action."),
+ i18n("Remove Remote Gallery"),
+ KStdGuiItem::yes(), KStdGuiItem::no(),
+ QString::null, KMessageBox::Dangerous))
+ {
+ GalleryQListViewItem* p_glvi = dynamic_cast<GalleryQListViewItem*>(p_lvi);
+ Gallery* p_gallery = p_glvi->GetGallery();
+ delete p_glvi;
+ mpGalleries->Remove(p_gallery);
+ mpGalleries->Save();
+ }
+ }
+}
+
+}
+
+#include "gallerylist.moc"
+
diff --git a/kipi-plugins/galleryexport/gallerylist.h b/kipi-plugins/galleryexport/gallerylist.h
new file mode 100644
index 0000000..f4aacd0
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerylist.h
@@ -0,0 +1,61 @@
+/* ============================================================
+ * File : gallerylist.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 GALLERYLIST_H
+#define GALLERYLIST_H
+
+#include <kdialogbase.h>
+
+#include <qlistview.h>
+
+namespace KIPIGalleryExportPlugin
+{
+
+class Gallery;
+class Galleries;
+
+class GalleryList : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ GalleryList(QWidget *parent, Galleries* pGalleries, bool blnShowOpen = true);
+ ~GalleryList();
+
+ Gallery* GetGallery(void);
+
+private:
+
+ Galleries* mpGalleries;
+ Gallery* mpCurrentGallery;
+ QListView* mpGalleryList;
+
+private slots:
+
+ void selectionChanged();
+ void doubleClicked(QListViewItem*, const QPoint&, int);
+
+ void slotUser1();
+ void slotUser2();
+ void slotUser3();
+};
+
+}
+
+#endif /* GALLERYLIST_H */
diff --git a/kipi-plugins/galleryexport/gallerympform.cpp b/kipi-plugins/galleryexport/gallerympform.cpp
new file mode 100644
index 0000000..f3cf894
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerympform.cpp
@@ -0,0 +1,182 @@
+/* ============================================================
+ * File : gallerympform.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-02
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kurl.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+
+#include <cstring>
+#include <cstdio>
+
+#include "gallerympform.h"
+#include "gallerytalker.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+GalleryMPForm::GalleryMPForm()
+{
+ m_boundary = "----------";
+ m_boundary += KApplication::randomString( 42 + 13 ).ascii();
+
+ if (GalleryTalker::isGallery2())
+ {
+ addPairRaw("g2_controller", "remote:GalleryRemote");
+ QString auth_token = GalleryTalker::getAuthToken();
+ if (!auth_token.isEmpty())
+ addPairRaw("g2_authToken", auth_token);
+ }
+}
+
+GalleryMPForm::~GalleryMPForm()
+{
+}
+
+void GalleryMPForm::reset()
+{
+ m_buffer.resize(0);
+}
+
+void GalleryMPForm::finish()
+{
+ QCString str;
+ str += "--";
+ str += m_boundary;
+ str += "--";
+ str += "\r\n";
+
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << str << '\0';
+}
+
+bool GalleryMPForm::addPair(const QString& name, const QString& value)
+{
+ if (GalleryTalker::isGallery2())
+ return addPairRaw(QString("g2_form[%1]").arg(name), value);
+
+ return addPairRaw(name, value);
+}
+
+bool GalleryMPForm::addPairRaw(const QString& name, const QString& value)
+{
+ QCString str;
+
+ str += "--";
+ str += m_boundary;
+ str += "\r\n";
+ str += "Content-Disposition: form-data; name=\"";
+ str += name.ascii();
+ str += "\"";
+ str += "\r\n\r\n";
+ str += value.ascii();
+ str += "\r\n";
+
+ //uint oldSize = m_buffer.size();
+ //m_buffer.resize(oldSize + str.size());
+ //memcpy(m_buffer.data() + oldSize, str.data(), str.size());
+
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << str;
+
+ return true;
+}
+
+bool GalleryMPForm::addFile(const QString& path, const QString& displayFilename)
+{
+ QString filename = "userfile_name";
+ if (GalleryTalker::isGallery2())
+ filename = "g2_userfile_name";
+
+ if (!addPairRaw(filename, displayFilename))
+ {
+ return false;
+ }
+
+ KMimeType::Ptr ptr = KMimeType::findByURL(path);
+ QString mime = ptr->name();
+ if (mime.isEmpty())
+ {
+ // if we ourselves can't determine the mime of the local file,
+ // very unlikely the remote gallery will be able to identify it
+ return false;
+ }
+
+ QFile imageFile(path);
+ if ( !imageFile.open( IO_ReadOnly ) )
+ return false;
+ QByteArray imageData = imageFile.readAll();
+ imageFile.close();
+
+ QCString str;
+
+ str += "--";
+ str += m_boundary;
+ str += "\r\n";
+ str += "Content-Disposition: form-data; name=\"";
+ if (GalleryTalker::isGallery2())
+ str += "g2_userfile";
+ else
+ str += "userfile";
+ str += "\"; ";
+ str += "filename=\"";
+ str += QFile::encodeName(KURL(path).filename());
+ str += "\"";
+ str += "\r\n";
+ str += "Content-Type: ";
+ str += mime.ascii();
+ str += "\r\n\r\n";
+
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << str;
+
+ int oldSize = m_buffer.size();
+ m_buffer.resize(oldSize + imageData.size() + 2);
+ memcpy(m_buffer.data()+oldSize, imageData.data(), imageData.size());
+ m_buffer[m_buffer.size()-2] = '\r';
+ m_buffer[m_buffer.size()-1] = '\n';
+
+ return true;
+}
+
+QString GalleryMPForm::contentType() const
+{
+ return QString("Content-Type: multipart/form-data; boundary=" + m_boundary);
+}
+
+QString GalleryMPForm::boundary() const
+{
+ return m_boundary;
+}
+
+QByteArray GalleryMPForm::formData() const
+{
+ return m_buffer;
+}
+
+}
diff --git a/kipi-plugins/galleryexport/gallerympform.h b/kipi-plugins/galleryexport/gallerympform.h
new file mode 100644
index 0000000..10c6bfc
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerympform.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ * File : gallerympform.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-02
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GALLERYMPFORM_H
+#define GALLERYMPFORM_H
+
+#include <qcstring.h>
+#include <qstring.h>
+
+class KURL;
+
+namespace KIPIGalleryExportPlugin
+{
+
+class GalleryMPForm
+{
+public:
+
+ GalleryMPForm();
+ ~GalleryMPForm();
+
+ void finish();
+ void reset();
+
+ bool addPair(const QString& name, const QString& value);
+ bool addFile(const QString& path, const QString& displayFilename);
+
+ QString contentType() const;
+ QByteArray formData() const;
+ QString boundary() const;
+
+private:
+
+ bool addPairRaw(const QString& name, const QString& value);
+
+ QByteArray m_buffer;
+ QCString m_boundary;
+};
+
+}
+
+#endif /* GALLERYMPFORM_H */
diff --git a/kipi-plugins/galleryexport/gallerytalker.cpp b/kipi-plugins/galleryexport/gallerytalker.cpp
new file mode 100644
index 0000000..e18a7b0
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerytalker.cpp
@@ -0,0 +1,681 @@
+/* ============================================================
+ * File : gallerytalker.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-30
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <qcstring.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qimage.h>
+#include <qregexp.h>
+
+#include <klocale.h>
+#include <kio/job.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kstandarddirs.h>
+
+#include <cstring>
+#include <cstdio>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+#include "galleryitem.h"
+#include "gallerympform.h"
+#include "gallerytalker.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+GalleryTalker::GalleryTalker( QWidget* parent )
+ : m_parent( parent ), m_job( 0 ), m_loggedIn( false )
+{
+}
+
+GalleryTalker::~GalleryTalker()
+{
+ if (m_job)
+ m_job->kill();
+}
+
+bool GalleryTalker::s_using_gallery2 = true;
+QString GalleryTalker::s_authToken = "";
+
+bool GalleryTalker::loggedIn() const
+{
+ return m_loggedIn;
+}
+
+void GalleryTalker::login( const KURL& url, const QString& name,
+ const QString& passwd )
+{
+ m_url = url;
+
+ GalleryMPForm form;
+
+ form.addPair("cmd", "login");
+ form.addPair("protocol_version", "2.11");
+ form.addPair("uname", name);
+ form.addPair("password", passwd);
+ form.finish();
+
+ KIO::TransferJob* job = KIO::http_post(m_url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType() );
+ job->addMetaData("cookies", "manual");
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ m_state = GE_LOGIN;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+}
+
+void GalleryTalker::listAlbums()
+{
+ GalleryMPForm form;
+
+ QString task = "fetch-albums";
+ if (s_using_gallery2)
+ task = "fetch-albums-prune";
+
+ form.addPair("cmd", task);
+ form.addPair("protocol_version", "2.11");
+ form.finish();
+
+ KIO::TransferJob* job = KIO::http_post(m_url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType() );
+ job->addMetaData("cookies", "manual");
+ job->addMetaData("setcookies", m_cookie);
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ m_state = GE_LISTALBUMS;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+}
+
+void GalleryTalker::listPhotos( const QString& albumName )
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ GalleryMPForm form;
+
+ form.addPair("cmd", "fetch-album-images");
+ form.addPair("protocol_version", "2.11");
+ form.addPair("set_albumName", albumName);
+ form.finish();
+
+ KIO::TransferJob* job = KIO::http_post(m_url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType() );
+ job->addMetaData("cookies", "manual");
+ job->addMetaData("setcookies", m_cookie);
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ m_state = GE_LISTPHOTOS;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+}
+
+void GalleryTalker::createAlbum( const QString& parentAlbumName,
+ const QString& albumName,
+ const QString& albumTitle,
+ const QString& albumCaption )
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ GalleryMPForm form;
+
+ form.addPair("cmd", "new-album");
+ form.addPair("protocol_version", "2.11");
+ form.addPair("set_albumName", parentAlbumName);
+ if (!albumName.isEmpty())
+ form.addPair("newAlbumName", albumName);
+ if (!albumTitle.isEmpty())
+ form.addPair("newAlbumTitle", albumTitle);
+ if (!albumCaption.isEmpty())
+ form.addPair("newAlbumDesc", albumCaption);
+ form.finish();
+
+ KIO::TransferJob* job = KIO::http_post(m_url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType() );
+ job->addMetaData("cookies", "manual");
+ job->addMetaData("setcookies", m_cookie);
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ m_state = GE_CREATEALBUM;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+}
+
+bool GalleryTalker::addPhoto( const QString& albumName,
+ const QString& photoPath,
+ const QString& caption,
+ bool captionIsTitle, bool captionIsDescription,
+ bool rescale, int maxDim )
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ QString path = photoPath;
+ QString display_filename = QFile::encodeName(KURL(path).filename());
+
+ GalleryMPForm form;
+
+ form.addPair("cmd", "add-item");
+ form.addPair("protocol_version", "2.11");
+ form.addPair("set_albumName", albumName);
+
+ if (!caption.isEmpty())
+ {
+ if (captionIsTitle)
+ form.addPair("caption", caption);
+ if (captionIsDescription)
+ form.addPair("extrafield.Description", caption);
+ }
+ QImage image(photoPath);
+
+ if (!image.isNull())
+ {
+ // image file - see if we need to rescale it
+ if (rescale && (image.width() > maxDim || image.height() > maxDim))
+ {
+ image = image.smoothScale(maxDim, maxDim, QImage::ScaleMin);
+ path = locateLocal("tmp", KURL(photoPath).filename());
+ image.save(path, QImageIO::imageFormat(photoPath));
+
+ if ("JPEG" == QString(QImageIO::imageFormat(photoPath)).upper())
+ {
+ KExiv2Iface::KExiv2 exiv2;
+ if (exiv2.load(photoPath))
+ {
+ exiv2.save(path);
+ }
+ }
+ kdDebug() << "Resizing and saving to temp file: "
+ << path << endl;
+ }
+ }
+
+ // The filename bit can perhaps be calculated in addFile()
+ // but not sure of the temporary filename that could be
+ // used for resizing... so I've added it explicitly for now.
+ if (!form.addFile(path, display_filename))
+ return false;
+
+ form.finish();
+
+ KIO::TransferJob* job = KIO::http_post(m_url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType());
+ job->addMetaData("cookies", "manual");
+ job->addMetaData("setcookies", m_cookie);
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ m_state = GE_ADDPHOTO;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+
+ return true;
+}
+
+void GalleryTalker::cancel()
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+}
+
+void GalleryTalker::data(KIO::Job*, const QByteArray& data)
+{
+ if (data.isEmpty())
+ return;
+
+ int oldSize = m_buffer.size();
+ m_buffer.resize(m_buffer.size() + data.size());
+ memcpy(m_buffer.data()+oldSize, data.data(), data.size());
+}
+
+void GalleryTalker::slotResult(KIO::Job *job)
+{
+ m_job = 0;
+ emit signalBusy( false );
+
+ if ( job->error() )
+ {
+ if ( m_state == GE_LOGIN )
+ emit signalLoginFailed( job->errorString() );
+ else if ( m_state == GE_ADDPHOTO )
+ emit signalAddPhotoFailed( job->errorString() );
+ else
+ job->showErrorDialog( m_parent );
+ return;
+ }
+
+ switch(m_state)
+ {
+ case(GE_LOGIN):
+ parseResponseLogin(m_buffer);
+ break;
+ case(GE_LISTALBUMS):
+ parseResponseListAlbums(m_buffer);
+ break;
+ case(GE_LISTPHOTOS):
+ parseResponseListPhotos(m_buffer);
+ break;
+ case(GE_CREATEALBUM):
+ parseResponseCreateAlbum(m_buffer);
+ break;
+ case(GE_ADDPHOTO):
+ parseResponseAddPhoto(m_buffer);
+ break;
+ }
+
+ if (m_state == GE_LOGIN && m_loggedIn)
+ {
+ QStringList cookielist = QStringList::split("\n", job->queryMetaData("setcookies"));
+ m_cookie = "Cookie:";
+ for (QStringList::Iterator it = cookielist.begin(); it != cookielist.end(); ++it)
+ {
+ QRegExp rx("^Set-Cookie: ([^;]+=[^;]+)");
+ if (rx.search(*it) > -1)
+ m_cookie += " " + rx.cap(1) + ";";
+ }
+ listAlbums();
+ }
+}
+
+void GalleryTalker::parseResponseLogin(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+
+ m_loggedIn = false;
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+
+ if (!foundResponse)
+ {
+ foundResponse = line.startsWith("#__GR2PROTO__");
+ }
+ else
+ {
+ QStringList strlist = QStringList::split("=", line);
+ if (strlist.count() == 2)
+ {
+ if (("status" == strlist[0]) && ("0" == strlist[1]))
+ {
+ m_loggedIn = true;
+ }
+ else if ("auth_token" == strlist[0])
+ {
+ s_authToken = strlist[1];
+ }
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalLoginFailed( i18n("Gallery URL probably incorrect"));
+ return;
+ }
+
+ if (!m_loggedIn)
+ {
+ emit signalLoginFailed(i18n("Incorrect username or password specified"));
+ }
+}
+
+void GalleryTalker::parseResponseListAlbums(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+ bool success = false;
+
+ typedef QValueList<GAlbum> GAlbumList;
+ GAlbumList albumList;
+ GAlbumList::iterator iter = albumList.begin();
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+ if (!foundResponse)
+ {
+ foundResponse = line.startsWith("#__GR2PROTO__");
+ }
+ else
+ {
+ QStringList strlist = QStringList::split("=", line);
+ if (strlist.count() == 2)
+ {
+ QString key = strlist[0];
+ QString value = strlist[1];
+
+ if (key == "status")
+ {
+ success = (value == "0");
+ }
+ else if (key.startsWith("album.name"))
+ {
+ GAlbum album;
+ album.name = value;
+ if (s_using_gallery2)
+ album.ref_num = value.toInt();
+ else
+ album.ref_num = key.section(".", 2, 2).toInt();
+ iter = albumList.append(album);
+ }
+ else if (key.startsWith("album.title"))
+ {
+ if (iter != albumList.end())
+ (*iter).title = value;
+ }
+ else if (key.startsWith("album.summary"))
+ {
+ if (iter != albumList.end())
+ (*iter).summary = value;
+ }
+ else if (key.startsWith("album.parent"))
+ {
+ if (iter != albumList.end())
+ (*iter).parent_ref_num = value.toInt();
+ }
+ else if (key.startsWith("album.perms.add"))
+ {
+ if (iter != albumList.end())
+ (*iter).add = (value == "true");
+ }
+ else if (key.startsWith("album.perms.write"))
+ {
+ if (iter != albumList.end())
+ (*iter).write = (value == "true");
+ }
+ else if (key.startsWith("album.perms.del_item"))
+ {
+ if (iter != albumList.end())
+ (*iter).del_item = (value == "true");
+ }
+ else if (key.startsWith("album.perms.del_alb"))
+ {
+ if (iter != albumList.end())
+ (*iter).del_alb = (value == "true");
+ }
+ else if (key.startsWith("album.perms.create_sub"))
+ {
+ if (iter != albumList.end())
+ (*iter).create_sub = (value == "true");
+ }
+ else if (key == "auth_token")
+ {
+ s_authToken = value;
+ }
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalError(i18n("Invalid response received from remote Gallery"));
+ return;
+ }
+
+ if (!success)
+ {
+ emit signalError(i18n("Failed to list albums"));
+ return;
+ }
+
+ // We need parent albums to come first for rest of the code to work
+ qHeapSort(albumList);
+
+ emit signalAlbums( albumList );
+}
+
+void GalleryTalker::parseResponseListPhotos(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+ bool success = false;
+
+ typedef QValueList<GPhoto> GPhotoList;
+ GPhotoList photoList;
+ GPhotoList::iterator iter = photoList.begin();
+
+ QString albumURL;
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+
+ if (!foundResponse)
+ {
+ foundResponse = line.startsWith("#__GR2PROTO__");
+ }
+ else
+ {
+ // Boris the Gallery default URL contains "=" char. So we will split the string only from the first "=" char
+ QStringList strlist = QStringList();
+ strlist << line.left(line.find('=')) << line.mid(line.find('=')+1);
+ if (strlist.count() >= 2)
+ {
+ QString key = strlist[0];
+ QString value = strlist[1];
+
+ if (key == "status")
+ {
+ success = (value == "0");
+ }
+ else if (key.startsWith("image.name"))
+ {
+ GPhoto photo;
+ photo.name = value;
+ photo.ref_num = key.section(".", 2, 2).toInt();
+ iter = photoList.append(photo);
+ }
+ else if (key.startsWith("image.caption"))
+ {
+ if (iter != photoList.end())
+ (*iter).caption = value;
+ }
+ else if (key.startsWith("image.thumbName"))
+ {
+ if (iter != photoList.end())
+ (*iter).thumbName = value;
+ }
+ else if (key.startsWith("baseurl"))
+ {
+ albumURL = value.replace("\\","");
+ }
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalError(i18n("Invalid response received from remote Gallery"));
+ return;
+ }
+
+ if (!success)
+ {
+ emit signalError(i18n("Failed to list photos"));
+ return;
+ }
+
+ for ( iter = photoList.begin(); iter != photoList.end(); ++iter )
+ {
+ (*iter).albumURL = albumURL;
+ }
+
+ emit signalPhotos( photoList );
+}
+
+void GalleryTalker::parseResponseCreateAlbum(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+ bool success = false;
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+
+ if (!foundResponse)
+ {
+ foundResponse = line.startsWith("#__GR2PROTO__");
+ }
+ else
+ {
+ QStringList strlist = QStringList::split("=", line);
+ if (strlist.count() == 2)
+ {
+ QString key = strlist[0];
+ QString value = strlist[1];
+
+ if (key == "status")
+ {
+ success = (value == "0");
+ }
+ else if (key.startsWith("status_text"))
+ {
+ kdDebug() << "STATUS: Create Album: " << value << endl;
+ }
+
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalError(i18n("Invalid response received from remote Gallery"));
+ return;
+ }
+
+ if (!success)
+ {
+ emit signalError(i18n("Failed to create new album"));
+ return;
+ }
+
+ listAlbums();
+}
+
+void GalleryTalker::parseResponseAddPhoto(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+ bool success = false;
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+
+ if (!foundResponse)
+ {
+ // Gallery1 sends resizing debug code sometimes so we
+ // have to detect things slightly differently
+ foundResponse = (line.startsWith("#__GR2PROTO__")
+ || (line.startsWith("<br>- Resizing")
+ && line.endsWith("#__GR2PROTO__")));
+ }
+ else
+ {
+ QStringList strlist = QStringList::split("=", line);
+ if (strlist.count() == 2)
+ {
+ QString key = strlist[0];
+ QString value = strlist[1];
+
+ if (key == "status")
+ {
+ success = (value == "0");
+ }
+ else if (key.startsWith("status_text"))
+ {
+ kdDebug() << "STATUS: Add Photo: " << value << endl;
+ }
+
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalAddPhotoFailed(i18n("Invalid response received from remote Gallery"));
+ return;
+ }
+
+ if (!success)
+ {
+ emit signalAddPhotoFailed(i18n("Failed to upload photo"));
+ }
+ else
+ {
+ emit signalAddPhotoSucceeded();
+ }
+}
+
+}
+
+#include "gallerytalker.moc"
+
diff --git a/kipi-plugins/galleryexport/gallerytalker.h b/kipi-plugins/galleryexport/gallerytalker.h
new file mode 100644
index 0000000..5e5891d
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerytalker.h
@@ -0,0 +1,118 @@
+/* ============================================================
+ * File : gallerytalker.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-30
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GALLERYTALKER_H
+#define GALLERYTALKER_H
+
+#include <qobject.h>
+#include <kurl.h>
+
+namespace KIO
+{
+ class Job;
+}
+
+class KURL;
+template <class T> class QValueList;
+
+namespace KIPIGalleryExportPlugin
+{
+
+class GAlbum;
+class GPhoto;
+
+class GalleryTalker : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ enum State {
+ GE_LOGIN = 0,
+ GE_LISTALBUMS,
+ GE_LISTPHOTOS,
+ GE_CREATEALBUM,
+ GE_ADDPHOTO
+ };
+
+ GalleryTalker(QWidget* parent);
+ ~GalleryTalker();
+
+ static void setGallery2(bool usegallery2) {s_using_gallery2 = usegallery2;};
+ static bool isGallery2() {return s_using_gallery2;};
+
+ static QString getAuthToken() {return s_authToken;};
+
+ bool loggedIn() const;
+
+ void login( const KURL& url, const QString& name,
+ const QString& passwd );
+ void listAlbums();
+ void listPhotos( const QString& albumName );
+ void createAlbum( const QString& parentAlbumName,
+ const QString& albumName,
+ const QString& albumTitle,
+ const QString& albumCaption );
+ bool addPhoto( const QString& albumName,
+ const QString& photoPath,
+ const QString& caption=QString(),
+ bool captionIsTitle=true, bool captionIsDescription=false,
+ bool rescale=false, int maxDim=600);
+
+ void cancel();
+
+private:
+
+ QWidget* m_parent;
+ State m_state;
+ QString m_cookie;
+ KURL m_url;
+ KIO::Job* m_job;
+ bool m_loggedIn;
+ QByteArray m_buffer;
+
+ static bool s_using_gallery2;
+ static QString s_authToken;
+
+private:
+
+ void parseResponseLogin(const QByteArray &data);
+ void parseResponseListAlbums(const QByteArray &data);
+ void parseResponseListPhotos(const QByteArray &data);
+ void parseResponseCreateAlbum(const QByteArray &data);
+ void parseResponseAddPhoto(const QByteArray &data);
+
+signals:
+
+ void signalError( const QString& msg );
+ void signalLoginFailed( const QString& msg );
+ void signalBusy( bool val );
+ void signalAlbums( const QValueList<GAlbum>& albumList );
+ void signalPhotos( const QValueList<GPhoto>& photoList );
+ void signalAddPhotoSucceeded( );
+ void signalAddPhotoFailed( const QString& msg );
+
+private slots:
+
+ void data(KIO::Job *job, const QByteArray &data);
+ void slotResult (KIO::Job *job);
+};
+
+}
+
+#endif /* GALLERYTALKER_H */
diff --git a/kipi-plugins/galleryexport/galleryviewitem.cpp b/kipi-plugins/galleryexport/galleryviewitem.cpp
new file mode 100644
index 0000000..4a847ca
--- /dev/null
+++ b/kipi-plugins/galleryexport/galleryviewitem.cpp
@@ -0,0 +1,93 @@
+/* ============================================================
+ * File : galleryviewitem.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-03
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <qpainter.h>
+#include <qpixmap.h>
+
+#include "galleryviewitem.h"
+#include "gallerytalker.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+void GAlbumViewItem::paintCell(QPainter * p, const QColorGroup & cg,
+ int column, int width, int )
+{
+ if (!p)
+ return;
+
+ QListView *lv = listView();
+ if (!lv)
+ return;
+ QFontMetrics fm(p->fontMetrics());
+
+ if (isSelected())
+ p->fillRect(0, 0, width, height(), cg.highlight());
+ else
+ p->fillRect(0, 0, width, height(), cg.base());
+
+ const QPixmap * icon = pixmap( column );
+
+ int iconWidth = 0;
+ if (icon)
+ {
+ iconWidth = icon->width() + lv->itemMargin();
+ int xo = lv->itemMargin();
+ int yo = (height() - icon->height())/2;
+ p->drawPixmap( xo, yo, *icon );
+ }
+
+ if (isSelected())
+ p->setPen( cg.highlightedText() );
+ else
+ p->setPen( cg.text() );
+
+ int r = lv->itemMargin() + iconWidth;
+ int h = lv->fontMetrics().height() + 2;
+
+ // Gallery2 does not return the "name" of the album, instead it
+ // returns a reference number than means nothing to the user.
+ // We display things slightly differently depending on version.
+ if (GalleryTalker::isGallery2())
+ {
+ p->drawText(r, h/2, width-r, h, Qt::AlignVCenter, album.title);
+ }
+ else
+ {
+ p->drawText(r, 0, width-r, h, Qt::AlignVCenter, album.title);
+
+ QFont fn(lv->font());
+ fn.setPointSize(fn.pointSize()-2);
+ fn.setItalic(true);
+ p->setFont(fn);
+ p->setPen(isSelected() ? cg.highlightedText() : Qt::gray);
+ p->drawText(r, h, width-r, h, Qt::AlignVCenter, album.name);
+ }
+}
+
+void GAlbumViewItem::setup()
+{
+ int h = listView()->fontMetrics().height();
+ int margin = 4;
+ setHeight( QMAX(2*h + margin, 32) );
+}
+
+}
diff --git a/kipi-plugins/galleryexport/galleryviewitem.h b/kipi-plugins/galleryexport/galleryviewitem.h
new file mode 100644
index 0000000..6c5077a
--- /dev/null
+++ b/kipi-plugins/galleryexport/galleryviewitem.h
@@ -0,0 +1,55 @@
+/* ============================================================
+ * File : galleryviewitem.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-01
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GALLERYVIEWITEM_H
+#define GALLERYVIEWITEM_H
+
+#include <qlistview.h>
+
+#include "galleryitem.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+class GAlbumViewItem : public QListViewItem
+{
+public:
+
+ GAlbumViewItem(QListView* parent, const QString& name,
+ const GAlbum& _album)
+ : QListViewItem(parent, name), album(_album) {}
+ GAlbumViewItem(QListViewItem* parent, const QString& name,
+ const GAlbum& _album)
+ : QListViewItem(parent, name), album(_album) {}
+
+ GAlbum album;
+
+ void paintCell(QPainter * p, const QColorGroup & cg,
+ int column, int width, int );
+ void paintFocus (QPainter*, const QColorGroup&,
+ const QRect&) {}
+
+protected:
+
+ void setup();
+
+};
+
+}
+
+#endif /* GALLERYVIEWITEM_H */
diff --git a/kipi-plugins/galleryexport/gallerywidget.cpp b/kipi-plugins/galleryexport/gallerywidget.cpp
new file mode 100644
index 0000000..e3fcc5c
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerywidget.cpp
@@ -0,0 +1,167 @@
+/* ============================================================
+ * File : gallerywidget.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-01
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <klocale.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qframe.h>
+#include <qheader.h>
+#include <qlistview.h>
+#include <qbuttongroup.h>
+#include <qgroupbox.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qsplitter.h>
+#include <qwhatsthis.h>
+
+#include "gallerywidget.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+GalleryWidget::GalleryWidget( QWidget* parent, const char* name, WFlags fl )
+ : QWidget( parent, name, fl )
+{
+ if ( !name )
+ setName( "GalleryWidget" );
+ QVBoxLayout* galleryWidgetLayout
+ = new QVBoxLayout( this, 5, 5, "GalleryWidgetLayout");
+
+ // ------------------------------------------------------------------------
+
+ QLabel* headerLabel;
+ QFrame* headerLine;
+
+ headerLabel = new QLabel( this, "headerLabel" );
+ galleryWidgetLayout->addWidget( headerLabel, 0 );
+ headerLine = new QFrame( this, "headerLine" );
+ headerLine->setFrameShape( QFrame::HLine );
+ headerLine->setFrameShadow( QFrame::Sunken );
+ galleryWidgetLayout->addWidget( headerLine, 0 );
+
+ // ------------------------------------------------------------------------
+
+ QSplitter* splitter = new QSplitter(this);
+ galleryWidgetLayout->addWidget( splitter, 5 );
+
+ m_albumView = new QListView( splitter, "m_albumView" );
+ m_albumView->addColumn( i18n( "Albums" ) );
+ m_albumView->setResizeMode( QListView::AllColumns );
+
+ // ------------------------------------------------------------------------
+
+ m_photoView = new KHTMLPart( splitter, "m_photoView" );
+
+ // ------------------------------------------------------------------------
+
+ QVBoxLayout* rightButtonGroupLayout;
+ QSpacerItem* spacer;
+ QButtonGroup* rightButtonGroup;
+
+ rightButtonGroup = new QButtonGroup( splitter, "rightButtonGroup" );
+ rightButtonGroupLayout = new QVBoxLayout( rightButtonGroup );
+ rightButtonGroupLayout->setSpacing( 5 );
+ rightButtonGroupLayout->setMargin( 5 );
+
+ m_newAlbumBtn = new QPushButton( rightButtonGroup, "m_newAlbumBtn" );
+ m_newAlbumBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ rightButtonGroupLayout->addWidget( m_newAlbumBtn, 0, Qt::AlignHCenter );
+
+ m_addPhotoBtn = new QPushButton( rightButtonGroup, "m_addPhotoBtn" );
+ m_addPhotoBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ rightButtonGroupLayout->addWidget( m_addPhotoBtn, 0, Qt::AlignHCenter );
+
+ // ------------------------------------------------------------------------
+
+ QGroupBox* optionsBox = new QGroupBox(i18n("Override Default Options"),
+ rightButtonGroup);
+ optionsBox->setColumnLayout(0, Qt::Vertical);
+ optionsBox->layout()->setSpacing(5);
+ optionsBox->layout()->setMargin(5);
+ QGridLayout* optionsBoxLayout = new QGridLayout(optionsBox->layout());
+
+ // ------------------------------------------------------------------------
+ m_captTitleCheckBox = new QCheckBox(optionsBox);
+ m_captTitleCheckBox->setText(i18n("Comment sets Title"));
+ optionsBoxLayout->addMultiCellWidget(m_captTitleCheckBox, 0, 0, 0, 1);
+
+ m_captDescrCheckBox = new QCheckBox(optionsBox);
+ m_captDescrCheckBox->setText(i18n("Comment sets Description"));
+ optionsBoxLayout->addMultiCellWidget(m_captDescrCheckBox, 1, 1, 0, 1);
+
+ m_resizeCheckBox = new QCheckBox(optionsBox);
+ m_resizeCheckBox->setText(i18n("Resize photos before uploading"));
+ optionsBoxLayout->addMultiCellWidget(m_resizeCheckBox, 2, 2, 0, 1);
+
+ m_dimensionSpinBox = new QSpinBox(0, 5000, 10, optionsBox);
+ m_dimensionSpinBox->setValue(600);
+ m_dimensionSpinBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ optionsBoxLayout->addWidget(m_dimensionSpinBox, 3, 1);
+
+ QLabel* resizeLabel = new QLabel(i18n("Maximum dimension:"), optionsBox);
+ optionsBoxLayout->addWidget(resizeLabel, 3, 0);
+
+ m_captTitleCheckBox->setChecked(true);
+ m_captDescrCheckBox->setChecked(false);
+
+ m_resizeCheckBox->setChecked(false);
+ m_dimensionSpinBox->setEnabled(false);
+ connect(m_resizeCheckBox, SIGNAL(clicked()), SLOT(slotResizeChecked()));
+
+ // ------------------------------------------------------------------------
+
+ rightButtonGroupLayout->addWidget(optionsBox);
+
+ // ------------------------------------------------------------------------
+
+ spacer = new QSpacerItem( 20, 100, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ rightButtonGroupLayout->addItem( spacer );
+
+ // ------------------------------------------------------------------------
+
+ headerLabel->setText( i18n( "<h2>Gallery Export</h2>" ) );
+ m_albumView->header()->setLabel( 0, i18n( "Albums" ) );
+ m_newAlbumBtn->setText( i18n( "&New Album" ) );
+ m_addPhotoBtn->setText( i18n( "&Add Photos" ) );
+
+ // ------------------------------------------------------------------------
+
+ resize( QSize(600, 400).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+}
+
+GalleryWidget::~GalleryWidget()
+{
+}
+
+void GalleryWidget::slotResizeChecked()
+{
+ m_dimensionSpinBox->setEnabled(m_resizeCheckBox->isChecked());
+}
+
+}
+
+#include "gallerywidget.moc"
diff --git a/kipi-plugins/galleryexport/gallerywidget.h b/kipi-plugins/galleryexport/gallerywidget.h
new file mode 100644
index 0000000..2022856
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerywidget.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ * File : gallerywidget.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-01
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GALLERYWIDGET_H
+#define GALLERYWIDGET_H
+
+#include <qwidget.h>
+
+class QListView;
+class QPushButton;
+class QSpinBox;
+class QCheckBox;
+class KHTMLPart;
+
+namespace KIPIGalleryExportPlugin
+{
+
+class GalleryWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ GalleryWidget( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+ ~GalleryWidget();
+
+private slots:
+
+ void slotResizeChecked();
+
+private:
+
+ QListView* m_albumView;
+ KHTMLPart* m_photoView;
+ QPushButton* m_newAlbumBtn;
+ QPushButton* m_addPhotoBtn;
+ QCheckBox* m_captTitleCheckBox;
+ QCheckBox* m_captDescrCheckBox;
+ QCheckBox* m_resizeCheckBox;
+ QSpinBox* m_dimensionSpinBox;
+
+ friend class GalleryWindow;
+};
+
+}
+
+#endif // GALLERYWIDGET_H
diff --git a/kipi-plugins/galleryexport/gallerywindow.cpp b/kipi-plugins/galleryexport/gallerywindow.cpp
new file mode 100644
index 0000000..2dabde2
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerywindow.cpp
@@ -0,0 +1,654 @@
+/* ============================================================
+ * File : gallerywindow.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-30
+ * Description :
+ *
+ * Copyright 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qlineedit.h>
+#include <qprogressdialog.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+
+// Include files for KDE
+
+#include <kaboutdata.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+#include <krun.h>
+#include <kdebug.h>
+#include <kconfig.h>
+
+// KIPI include files
+
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "galleries.h"
+#include "gallerylist.h"
+#include "gallerytalker.h"
+#include "galleryitem.h"
+#include "galleryviewitem.h"
+#include "gallerywidget.h"
+#include "galleryalbumdialog.h"
+#include "gallerywindow.h"
+#include "gallerywindow.moc"
+
+namespace KIPIGalleryExportPlugin
+{
+
+GalleryWindow::GalleryWindow(KIPI::Interface* interface, QWidget *parent, Galleries* pGalleries)
+ : KDialogBase(parent, 0, true, i18n("Gallery Export"), Help|Close, Close, false),
+ m_interface(interface),
+ mpGalleries(pGalleries)
+{
+ m_uploadCount = 0;
+ m_uploadTotal = 0;
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Gallery Export"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to export image collection to remote Gallery server."),
+ "(c) 2003-2005, Renchi Raju");
+
+ m_about->addAuthor("Renchi Raju", I18N_NOOP("Author"),
+ "renchi at pooh dot tam dot uiuc dot edu");
+
+ m_about->addAuthor("Colin Guthrie", I18N_NOOP("Maintainer"),
+ "kde at colin dot guthr dot ie");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ GalleryWidget* widget = new GalleryWidget(this);
+ setMainWidget(widget);
+ widget->setMinimumSize(600, 400);
+
+ m_albumView = widget->m_albumView;
+ m_photoView = widget->m_photoView;
+ m_newAlbumBtn = widget->m_newAlbumBtn;
+ m_addPhotoBtn = widget->m_addPhotoBtn;
+ m_captTitleCheckBox = widget->m_captTitleCheckBox;
+ m_captDescrCheckBox = widget->m_captDescrCheckBox;
+ m_resizeCheckBox = widget->m_resizeCheckBox;
+ m_dimensionSpinBox = widget->m_dimensionSpinBox;
+
+ m_albumView->setRootIsDecorated( true );
+
+ m_newAlbumBtn->setEnabled( false );
+ m_addPhotoBtn->setEnabled( false );
+
+ m_progressDlg = new QProgressDialog( this, 0, true );
+ m_progressDlg->setAutoReset( true );
+ m_progressDlg->setAutoClose( true );
+
+ connect(m_progressDlg, SIGNAL(canceled()), SLOT(slotAddPhotoCancel()));
+
+ connect(m_albumView, SIGNAL(selectionChanged()), SLOT(slotAlbumSelected()));
+ connect(m_photoView->browserExtension(),
+ SIGNAL(openURLRequest(const KURL&,
+ const KParts::URLArgs&)),
+ SLOT(slotOpenPhoto(const KURL&)));
+
+ connect(m_newAlbumBtn, SIGNAL(clicked()), SLOT(slotNewAlbum()));
+ connect(m_addPhotoBtn, SIGNAL(clicked()), SLOT( slotAddPhotos()));
+
+ // read config
+ KConfig config("kipirc");
+ config.setGroup("GallerySync Settings");
+
+ m_talker = new GalleryTalker( this );
+ connect( m_talker, SIGNAL( signalError( const QString& ) ),
+ SLOT( slotError( const QString& ) ) );
+ connect( m_talker, SIGNAL( signalBusy( bool ) ),
+ SLOT( slotBusy( bool ) ) );
+ connect( m_talker, SIGNAL( signalLoginFailed( const QString& ) ),
+ SLOT( slotLoginFailed( const QString& ) ) );
+ connect( m_talker, SIGNAL( signalAlbums( const QValueList<GAlbum>& ) ),
+ SLOT( slotAlbums( const QValueList<GAlbum>& ) ) );
+ connect( m_talker, SIGNAL( signalPhotos( const QValueList<GPhoto>& ) ),
+ SLOT( slotPhotos( const QValueList<GPhoto>& ) ) );
+ connect( m_talker, SIGNAL( signalAddPhotoSucceeded() ),
+ SLOT( slotAddPhotoSucceeded() ) );
+ connect( m_talker, SIGNAL( signalAddPhotoFailed( const QString& ) ),
+ SLOT( slotAddPhotoFailed( const QString& ) ) );
+
+ if (config.readBoolEntry("Resize", false))
+ {
+ m_resizeCheckBox->setChecked(true);
+ m_dimensionSpinBox->setEnabled(true);
+ }
+ else
+ {
+ m_resizeCheckBox->setChecked(false);
+ m_dimensionSpinBox->setEnabled(false);
+ }
+
+ if (config.readBoolEntry("Set title", true))
+ m_captTitleCheckBox->setChecked(true);
+ else
+ m_captTitleCheckBox->setChecked(false);
+
+ if (config.readBoolEntry("Set description", false))
+ m_captDescrCheckBox->setChecked(true);
+ else
+ m_captDescrCheckBox->setChecked(false);
+
+ m_dimensionSpinBox->setValue(config.readNumEntry("Maximum Width", 1600));
+
+ QTimer::singleShot( 0, this, SLOT( slotDoLogin() ) );
+}
+
+GalleryWindow::~GalleryWindow()
+{
+ // write config
+ KConfig config("kipirc");
+ config.setGroup("GallerySync Settings");
+ config.writeEntry("Resize", m_resizeCheckBox->isChecked());
+ config.writeEntry("Set title", m_captTitleCheckBox->isChecked());
+ config.writeEntry("Set description", m_captDescrCheckBox->isChecked());
+ config.writeEntry("Maximum Width", m_dimensionSpinBox->value());
+
+ delete m_progressDlg;
+ delete m_talker;
+ delete m_about;
+}
+
+void GalleryWindow::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("galleryexport", "kipi-plugins");
+}
+
+void GalleryWindow::slotDoLogin()
+{
+ GalleryList dlg(this, mpGalleries);
+
+ if (QDialog::Accepted != dlg.exec())
+ {
+ close();
+ return;
+ }
+
+ Gallery* p_gallery = dlg.GetGallery();
+ if (!p_gallery)
+ {
+ close();
+ return;
+ }
+
+ GalleryTalker::setGallery2((2 == p_gallery->version()));
+
+ KURL url(p_gallery->url());
+ if (url.protocol().isEmpty())
+ {
+ url.setProtocol("http");
+ url.setHost(p_gallery->url());
+ }
+ if (!url.url().endsWith(".php"))
+ {
+ if (GalleryTalker::isGallery2())
+ url.addPath("main.php");
+ else
+ url.addPath("gallery_remote2.php");
+ }
+ // If we've done something clever, save it back to the gallery.
+ if (p_gallery->url() != url.url())
+ {
+ p_gallery->setUrl(url.url());
+ mpGalleries->Save();
+ }
+
+ m_talker->login(url.url(), p_gallery->username(), p_gallery->password());
+}
+
+void GalleryWindow::slotLoginFailed( const QString& msg )
+{
+ if ( KMessageBox::warningYesNo( this,
+ i18n( "Failed to login into remote gallery. " )
+ + msg
+ + i18n("\nDo you want to try again?" ) )
+ != KMessageBox::Yes )
+ {
+ close();
+ return;
+ }
+
+ slotDoLogin();
+}
+
+void GalleryWindow::slotBusy( bool val )
+{
+ if ( val )
+ {
+ setCursor(QCursor::WaitCursor);
+ m_newAlbumBtn->setEnabled( false );
+ m_addPhotoBtn->setEnabled( false );
+ }
+ else
+ {
+ setCursor(QCursor::ArrowCursor);
+ bool loggedIn = m_talker->loggedIn();
+ m_newAlbumBtn->setEnabled( loggedIn );
+ m_addPhotoBtn->setEnabled( loggedIn && m_albumView->selectedItem() );
+ }
+}
+
+void GalleryWindow::slotError( const QString& msg )
+{
+ KMessageBox::error( this, msg );
+}
+
+void GalleryWindow::slotAlbums( const QValueList<GAlbum>& albumList )
+{
+ m_albumDict.clear();
+ m_albumView->clear();
+ m_photoView->begin();
+ m_photoView->write( "<html></html>" );
+ m_photoView->end();
+
+ KIconLoader* iconLoader = KApplication::kApplication()->iconLoader();
+ QPixmap pix = iconLoader->loadIcon( "folder", KIcon::NoGroup, 32 );
+
+ typedef QValueList<GAlbum> GAlbumList;
+ GAlbumList::const_iterator iter;
+ for ( iter = albumList.begin(); iter != albumList.end(); ++iter )
+ {
+ const GAlbum& album = *iter;
+
+ if ( album.parent_ref_num == 0 )
+ {
+ GAlbumViewItem* item = new GAlbumViewItem( m_albumView, album.title,
+ album );
+ item->setPixmap( 0, pix );
+ m_albumDict.insert( album.ref_num, item );
+ }
+ else
+ {
+ QListViewItem* parent = m_albumDict.find( album.parent_ref_num );
+ if ( parent )
+ {
+ GAlbumViewItem* item = new GAlbumViewItem( parent, album.title,
+ album);
+ item->setPixmap( 0, pix );
+ m_albumDict.insert( album.ref_num, item );
+ }
+ else
+ {
+ kdWarning() << "Failed to find parent for album "
+ << album.name
+ << " with id " << album.ref_num << "\n";
+ }
+ }
+ }
+
+
+ // find and select the last selected album
+ int lastSelectedID = 0;
+ for ( iter = albumList.begin(); iter != albumList.end(); ++iter )
+ {
+ if ((*iter).name == m_lastSelectedAlbum)
+ {
+ lastSelectedID = (*iter).ref_num;
+ break;
+ }
+ }
+
+ if (lastSelectedID > 0)
+ {
+ GAlbumViewItem* lastSelectedItem = m_albumDict.find( lastSelectedID );
+ if (lastSelectedItem)
+ {
+ m_albumView->setSelected( lastSelectedItem, true );
+ m_albumView->ensureItemVisible( lastSelectedItem );
+ }
+ }
+}
+
+void GalleryWindow::slotPhotos( const QValueList<GPhoto>& photoList)
+{
+ int pxSize = fontMetrics().height() - 2;
+ QString styleSheet =
+ QString( "body { margin: 8px; font-size: %1px; "
+ " color: %2; background-color: %3;}" )
+ .arg( pxSize )
+ .arg( colorGroup().text().name() )
+ .arg( colorGroup().base().name() );
+
+ styleSheet += QString( "a { font-size: %1px; color: %2; "
+ "text-decoration: none;}" )
+ .arg( pxSize )
+ .arg( colorGroup().text().name() );
+ styleSheet += QString( "i { font-size: %1px; color: %2; "
+ "text-decoration: none;}" )
+ .arg( pxSize-2 )
+ .arg( QColor("steelblue").name() );
+
+ m_photoView->begin();
+ m_photoView->setUserStyleSheet( styleSheet );
+ m_photoView->write( "<html>" );
+
+
+ m_photoView->write("<table class='box-body' width='100%' "
+ "border='0' cellspacing='1' cellpadding='1'>" );
+
+
+ typedef QValueList<GPhoto> GPhotoList;
+ GPhotoList::const_iterator iter;
+ for ( iter = photoList.begin(); iter != photoList.end(); ++iter )
+ {
+ const GPhoto& photo = *iter;
+ KURL imageurl(photo.albumURL + photo.name);
+ KURL thumburl(photo.albumURL + photo.thumbName);
+
+ m_photoView->write( "<tr><td class='photo'>"
+ + QString("<a href='%1'>")
+ .arg(imageurl.url())
+ + QString("<img border=1 src=\"%1\"><br>")
+ .arg(thumburl.url())
+ + photo.name
+ + ( photo.caption.isEmpty() ? QString() :
+ QString("<br><i>%1</i>")
+ .arg(photo.caption) )
+ + "</a></td></tr>" );
+ }
+
+ m_photoView->write("</table>");
+
+ m_photoView->write( "</html>" );
+ m_photoView->end( );
+}
+
+void GalleryWindow::slotAlbumSelected()
+{
+ QListViewItem* item = m_albumView->selectedItem();
+ if ( !item )
+ {
+ m_addPhotoBtn->setEnabled( false );
+ }
+ else
+ {
+ if ( m_talker->loggedIn() )
+ {
+ m_addPhotoBtn->setEnabled( true );
+
+ m_photoView->begin();
+ m_photoView->write( "<html></html>" );
+ m_photoView->end();
+
+ GAlbumViewItem* viewItem = static_cast<GAlbumViewItem*>(item);
+ m_talker->listPhotos(viewItem->album.name);
+ m_lastSelectedAlbum = viewItem->album.name;
+ }
+ }
+}
+
+void GalleryWindow::slotOpenPhoto( const KURL& url )
+{
+ new KRun(url);
+}
+
+void GalleryWindow::slotNewAlbum()
+{
+ GalleryAlbumDialog dlg;
+ dlg.titleEdit->setFocus( );
+ if ( dlg.exec() != QDialog::Accepted )
+ {
+ return;
+ }
+
+ QString name = dlg.nameEdit->text();
+ QString title = dlg.titleEdit->text();
+ QString caption = dlg.captionEdit->text();
+
+ // check for prohibited chars in the album name
+ // \ / * ? " ' & < > | . + # ( ) or spaces
+ // Todo: Change this to a QRegExp check.
+ QChar ch;
+ bool clean = true;
+ for (uint i=0; i<name.length(); i++)
+ {
+ ch = name[i];
+ if (ch == '\\')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '/')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '*')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '?')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '"')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '\'')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '&')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '<')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '>')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '|')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '.')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '+')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '#')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '(')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == ')')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == ' ')
+ {
+ clean = false;
+ break;
+ }
+ }
+
+ if (!clean)
+ {
+ KMessageBox::error( this, i18n("Sorry, these characters are not allowed in album name: %1")
+ .arg("\\ / * ? \" \' & < > | . + # ( ) or spaces") );
+ return;
+ }
+
+ QString parentAlbumName;
+
+ QListViewItem* item = m_albumView->selectedItem();
+ if (item)
+ {
+ GAlbumViewItem* viewItem = static_cast<GAlbumViewItem*>(item);
+ parentAlbumName = viewItem->album.name;
+ }
+ else
+ {
+ parentAlbumName = "0";
+ }
+
+ m_talker->createAlbum(parentAlbumName, name, title, caption);
+}
+
+void GalleryWindow::slotAddPhotos()
+{
+ QListViewItem* item = m_albumView->selectedItem();
+ if (!item)
+ return;
+
+ KURL::List urls = KIPI::ImageDialog::getImageURLs( this, m_interface );
+ if (urls.isEmpty())
+ return;
+
+ typedef QPair<QString,QString> Pair;
+
+ m_uploadQueue.clear();
+ for (KURL::List::iterator it = urls.begin(); it != urls.end(); ++it)
+ {
+ KIPI::ImageInfo info = m_interface->info( *it );
+ m_uploadQueue.append( Pair( (*it).path(), info.description() ) );
+ }
+
+ m_uploadTotal = m_uploadQueue.count();
+ m_uploadCount = 0;
+ m_progressDlg->reset();
+ slotAddPhotoNext();
+}
+
+void GalleryWindow::slotAddPhotoNext()
+{
+ if ( m_uploadQueue.isEmpty() )
+ {
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+ slotAlbumSelected();
+ return;
+ }
+
+ typedef QPair<QString,QString> Pair;
+ Pair pathComments = m_uploadQueue.first();
+ m_uploadQueue.pop_front();
+
+ bool res = m_talker->addPhoto( m_lastSelectedAlbum, pathComments.first,
+ pathComments.second,
+ m_captTitleCheckBox->isChecked(),
+ m_captDescrCheckBox->isChecked(),
+ m_resizeCheckBox->isChecked(),
+ m_dimensionSpinBox->value() );
+ if (!res)
+ {
+ slotAddPhotoFailed( "" );
+ return;
+ }
+
+ m_progressDlg->setLabelText( i18n("Uploading file %1 ")
+ .arg( KURL(pathComments.first).filename() ) );
+
+ if (m_progressDlg->isHidden())
+ m_progressDlg->show();
+}
+
+void GalleryWindow::slotAddPhotoSucceeded()
+{
+ m_uploadCount++;
+ m_progressDlg->setProgress( m_uploadCount, m_uploadTotal );
+ slotAddPhotoNext();
+}
+
+void GalleryWindow::slotAddPhotoFailed( const QString& msg )
+{
+ if ( KMessageBox::warningContinueCancel( this,
+ i18n( "Failed to upload photo into "
+ "remote gallery. " )
+ + msg
+ + i18n("\nDo you want to continue?" ) )
+ != KMessageBox::Continue )
+ {
+ m_uploadQueue.clear();
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+
+ // refresh the thumbnails
+ slotAlbumSelected();
+ }
+ else
+ {
+ m_uploadTotal--;
+ m_progressDlg->setProgress( m_uploadCount, m_uploadTotal );
+ slotAddPhotoNext();
+ }
+}
+
+void GalleryWindow::slotAddPhotoCancel()
+{
+ m_uploadQueue.clear();
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+
+ m_talker->cancel();
+
+ // refresh the thumbnails
+ slotAlbumSelected();
+}
+
+}
+
diff --git a/kipi-plugins/galleryexport/gallerywindow.h b/kipi-plugins/galleryexport/gallerywindow.h
new file mode 100644
index 0000000..3d160e0
--- /dev/null
+++ b/kipi-plugins/galleryexport/gallerywindow.h
@@ -0,0 +1,108 @@
+/* ============================================================
+ * File : gallerywindow.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-30
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GALLERYWINDOW_H
+#define GALLERYWINDOW_H
+
+#include <kdialogbase.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qintdict.h>
+
+class QListView;
+class QPushButton;
+class QSpinBox;
+class QCheckBox;
+class QProgressDialog;
+class KHTMLPart;
+class KURL;
+
+namespace KIPI
+{
+class Interface;
+}
+namespace KIPIPlugins
+{
+class KPAboutData;
+}
+
+namespace KIPIGalleryExportPlugin
+{
+
+class Galleries;
+class GalleryTalker;
+class GAlbum;
+class GPhoto;
+class GAlbumViewItem;
+
+class GalleryWindow : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ GalleryWindow(KIPI::Interface *interface, QWidget *parent, Galleries* pGalleries);
+ ~GalleryWindow();
+
+private:
+
+ QListView *m_albumView;
+ KHTMLPart *m_photoView;
+ QPushButton *m_newAlbumBtn;
+ QPushButton *m_addPhotoBtn;
+ QPushButton *m_helpButton;
+ QCheckBox *m_captTitleCheckBox;
+ QCheckBox *m_captDescrCheckBox;
+ QCheckBox *m_resizeCheckBox;
+ QSpinBox *m_dimensionSpinBox;
+ GalleryTalker *m_talker;
+ QIntDict<GAlbumViewItem> m_albumDict;
+ QString m_lastSelectedAlbum;
+ KIPI::Interface *m_interface;
+ KIPIPlugins::KPAboutData *m_about;
+
+ QProgressDialog *m_progressDlg;
+ unsigned int m_uploadCount;
+ unsigned int m_uploadTotal;
+ QValueList< QPair<QString,QString> > m_uploadQueue;
+
+ Galleries* mpGalleries;
+ Gallery* mpGallery;
+
+private slots:
+
+ void slotDoLogin();
+ void slotLoginFailed( const QString& msg );
+ void slotBusy( bool val );
+ void slotError( const QString& msg );
+ void slotAlbums( const QValueList<GAlbum>& albumList );
+ void slotPhotos( const QValueList<GPhoto>& photoList );
+ void slotAlbumSelected();
+ void slotOpenPhoto( const KURL& url );
+ void slotNewAlbum();
+ void slotAddPhotos();
+ void slotAddPhotoNext();
+ void slotAddPhotoSucceeded();
+ void slotAddPhotoFailed( const QString& msg );
+ void slotAddPhotoCancel();
+ void slotHelp();
+};
+
+}
+
+#endif /* GALLERYWINDOW_H */
diff --git a/kipi-plugins/galleryexport/kipiplugin_galleryexport.desktop b/kipi-plugins/galleryexport/kipiplugin_galleryexport.desktop
new file mode 100644
index 0000000..e1331c1
--- /dev/null
+++ b/kipi-plugins/galleryexport/kipiplugin_galleryexport.desktop
@@ -0,0 +1,59 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Remote Gallery Export
+Name[br]=Ezporzh ar garidell d'ar pelloù
+Name[ca]=Exportador a galeries remotes
+Name[cs]=Export do vzdálené galerie
+Name[da]=Eksport til fjerngalleri
+Name[de]=Export in entfernte Galerien
+Name[el]=Εξαγωγή απομακρυσμένης συλλογής
+Name[es]=Exportar galería remota
+Name[et]=Võrgugalerii eksport
+Name[fi]=Gallerian etävienti
+Name[ga]=Easpórtáil Cianghailearaí
+Name[gl]=Exportazón a Galeria Remota
+Name[is]=Útflutningur í fjarlæg myndasöfn
+Name[it]=Esportazione remota di gallerie
+Name[nds]=Bildgalerie-Exporteren
+Name[nl]=Export naar externe galerij
+Name[pa]=ਰਿਮੋਟ ਗੈਲਰੀ ਨਿਰਯਾਤ
+Name[pl]=Eksport do zdalnej galerii
+Name[pt]=Exportação para Galeria Remota
+Name[sr]=Извоз у удаљену галерију
+Name[sr@Latn]=Izvoz u udaljenu galeriju
+Name[sv]=Export till fjärrgalleri
+Name[tg]=Воридоти Намоишгари Дурдаст
+Name[tr]=Uzak Galeri Aktarma
+Name[xx]=xxRemote Gallery Exportxx
+Name[zh_CN]=远程图库导出
+Comment=KIPI Remote Gallery Export Plugin
+Comment[ca]=Connector del KIPI per exportar a galeries remotes
+Comment[cs]=KIPI modul exportu do vzdálené galerie
+Comment[da]=KIPI-plugin: Eksport til fjerngalleri
+Comment[de]=Ein KIPI-Modul zum Exportieren einer Galerie zu einem entfernten Rechner
+Comment[el]=Πρόσθετο εξαγωγής απομακρυσμένης συλλογής του KIPI
+Comment[es]=Complemento de KIPI para exportar galería remota
+Comment[et]=KIPI võrgugalerii ekspordiplugin
+Comment[fi]=Kipi-liitännäinen gallerian vientiä etäkohteeseen varten
+Comment[fr]=Module externe KIPI pour exporter des images vers un site Gallery
+Comment[gl]=Plugin de KIPI para Exportar a unha Galeria Remota
+Comment[is]=KIPI íforrit fyrir útflutning í fjarlæg myndasöfn
+Comment[it]=Plugin per l'esportazione remota di gallerie di KIPI
+Comment[ja]=Kipi リモートギャラリーエクスポートプラグイン
+Comment[nds]=KIPI-Moduul för't Exporteren na en feern Galerie
+Comment[nl]=KIPI-plugin voor het exporteren naar externe galerijen
+Comment[pa]=KIPI ਰਿਮੋਟ ਗੈਲਰੀ ਨਿਰਯਾਤ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Eksport do zdalnej galerii
+Comment[pt]='Plugin' do KIPI de Exportação para Galeria Remota
+Comment[pt_BR]=Plugin para Exportação Remota de Galerias do KIPI
+Comment[sr]=KIPI прикључак за извоз у удаљену галерију
+Comment[sr@Latn]=KIPI priključak za izvoz u udaljenu galeriju
+Comment[sv]=KIPI-insticksprogram: Export till fjärrgalleri
+Comment[tg]=Модули воридикунандаи намоишгаири дурдастаи KIPI
+Comment[tr]=KIPI Uzak Galeri Aktarma Eklentisi
+Comment[xx]=xxKIPI Remote Gallery Export Pluginxx
+Comment[zh_CN]=KIPI 远程图库导出插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_galleryexport
+author=Renchi Raju, renchi@pooh.tam.uiuc.edu
diff --git a/kipi-plugins/galleryexport/plugin_galleryexport.cpp b/kipi-plugins/galleryexport/plugin_galleryexport.cpp
new file mode 100644
index 0000000..032fea9
--- /dev/null
+++ b/kipi-plugins/galleryexport/plugin_galleryexport.cpp
@@ -0,0 +1,190 @@
+/* ============================================================
+ * File : plugin_galleryexport.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Modified By : Colin Guthrie
+ * Date : 2004-11-06
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published bythe 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.
+ *
+ * ============================================================ */
+
+// KDE includes.
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+
+// libkipi includes.
+#include <libkipi/interface.h>
+
+// Local includes.
+#include "galleries.h"
+#include "gallerylist.h"
+#include "gallerywindow.h"
+#include "galleryconfig.h"
+#include "plugin_galleryexport.h"
+
+typedef KGenericFactory<Plugin_GalleryExport> Factory;
+
+K_EXPORT_COMPONENT_FACTORY(kipiplugin_galleryexport,
+ Factory("kipiplugin_galleryexport"))
+
+Plugin_GalleryExport::Plugin_GalleryExport(QObject *parent,
+ const char*,
+ const QStringList&)
+ : KIPI::Plugin(Factory::instance(), parent, "GalleryExport"),
+ mpGalleries(0)
+{
+ kdDebug(51001) << "Plugin_GalleryExport plugin loaded"
+ << endl;
+}
+
+void Plugin_GalleryExport::setup(QWidget* widget)
+{
+ mpGalleries = new KIPIGalleryExportPlugin::Galleries();
+
+ KIPI::Plugin::setup(widget);
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ // Add our directory in to the icon loader dirs.
+ KGlobal::iconLoader()->addAppDir("kipiplugin_galleryexport");
+
+ m_action_sync = new KAction(i18n("Remote Gallery Sync..."),
+ 0,
+ this,
+ SLOT(slotSync()),
+ actionCollection(),
+ "galleryexport");
+ m_action_sync->setEnabled(true);
+ addAction(m_action_sync);
+
+ m_action_configure = new KAction(i18n("Remote Galleries..."),
+ 0,
+ this,
+ SLOT(slotConfigure()),
+ actionCollection(),
+ "galleryexport");
+ m_action_configure->setEnabled(true);
+ addAction(m_action_configure);
+/*
+ m_action_collection_settings = new KAction(i18n("Remote Gallery Settings..."),
+ 0,
+ this,
+ SLOT(slotCollectionSettings()),
+ actionCollection(),
+ "galleryexport");
+ m_action_collection_settings->setEnabled(true);
+ addAction(m_action_collection_settings);
+
+ m_action_image_setting = new KAction(i18n("Remote Gallery Settings..."),
+ 0,
+ this,
+ SLOT(slotImageSettings()),
+ actionCollection(),
+ "galleryexport");
+ m_action_image_setting->setEnabled(true);
+ addAction(m_action_image_setting);
+*/
+}
+
+
+Plugin_GalleryExport::~Plugin_GalleryExport()
+{
+ if (mpGalleries)
+ delete mpGalleries;
+}
+
+
+void Plugin_GalleryExport::slotSync()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPIGalleryExportPlugin::GalleryWindow dlg(interface, kapp->activeWindow(), mpGalleries);
+ dlg.exec();
+}
+
+void Plugin_GalleryExport::slotConfigure()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPIGalleryExportPlugin::GalleryList dlg(kapp->activeWindow(), mpGalleries, false);
+ dlg.exec();
+}
+
+void Plugin_GalleryExport::slotCollectionSettings()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KMessageBox::error(kapp->activeWindow(), "Not Implemented Yet!");
+}
+
+void Plugin_GalleryExport::slotImageSettings()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KMessageBox::error(kapp->activeWindow(), "Not Implemented Yet!");
+}
+
+KIPI::Category Plugin_GalleryExport::category( KAction* action ) const
+{
+ if (action == m_action_sync)
+ return KIPI::EXPORTPLUGIN;
+ if (action == m_action_configure)
+ return KIPI::TOOLSPLUGIN;
+ if (action == m_action_collection_settings)
+ return KIPI::COLLECTIONSPLUGIN;
+ if (action == m_action_image_setting)
+ return KIPI::IMAGESPLUGIN;
+
+ kdWarning(51000) << "Unrecognized action for plugin category identification"
+ << endl;
+ return KIPI::EXPORTPLUGIN;
+}
+
+
+#include "plugin_galleryexport.moc"
diff --git a/kipi-plugins/galleryexport/plugin_galleryexport.h b/kipi-plugins/galleryexport/plugin_galleryexport.h
new file mode 100644
index 0000000..b6505dc
--- /dev/null
+++ b/kipi-plugins/galleryexport/plugin_galleryexport.h
@@ -0,0 +1,67 @@
+/* ============================================================
+ * File : plugin_galleryexport.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-06
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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 bythe 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 PLUGIN_GALLERYEXPORT_H
+#define PLUGIN_GALLERYEXPORT_H
+
+// libKIPI includes.
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+namespace KIPIGalleryExportPlugin
+{
+class Galleries;
+}
+
+class Plugin_GalleryExport : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_GalleryExport(QObject *parent,
+ const char* name,
+ const QStringList &args);
+ ~Plugin_GalleryExport();
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* );
+
+public slots:
+
+ void slotSync();
+ void slotConfigure();
+ void slotCollectionSettings();
+ void slotImageSettings();
+
+private:
+
+ KAction *m_action_sync;
+ KAction *m_action_configure;
+ KAction *m_action_collection_settings;
+ KAction *m_action_image_setting;
+
+ KIPIGalleryExportPlugin::Galleries* mpGalleries;
+};
+
+#endif
diff --git a/kipi-plugins/gpssync/Makefile.am b/kipi-plugins/gpssync/Makefile.am
new file mode 100644
index 0000000..c5fcc64
--- /dev/null
+++ b/kipi-plugins/gpssync/Makefile.am
@@ -0,0 +1,35 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKEXIV2_CFLAGS) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_gpssync.la
+
+kipiplugin_gpssync_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP)
+
+# Srcs for the plugin
+kipiplugin_gpssync_la_SOURCES = plugin_gpssync.cpp gpssyncdialog.cpp gpslistviewitem.cpp \
+ gpsbabelbinary.cpp gpsdataparser.cpp gpseditdialog.cpp \
+ gpsmapwidget.cpp kmlexport.cpp kmlexportconfig.cpp \
+ kmlgpsdataparser.cpp
+
+# Libs needed by the plugin
+kipiplugin_gpssync_la_LIBADD = $(LIBKEXIV2_LIBS) -lkipiplugins $(LIBKIPI_LIBS) $(LIB_KHTML) \
+ $(LIB_KPARTS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) \
+ $(LIB_KFILE)
+
+# LD flags for the plugin
+kipiplugin_gpssync_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries)
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_gpssync.desktop
+
+# Icons set for the plugin.
+kipiplugin_gpssyncicondir = $(kde_datadir)/kipiplugin_gpssync/icons
+kipiplugin_gpssyncicon_ICON = AUTO
+
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_gpssync.pot
+
diff --git a/kipi-plugins/gpssync/getlonlat.php b/kipi-plugins/gpssync/getlonlat.php
new file mode 100644
index 0000000..da76386
--- /dev/null
+++ b/kipi-plugins/gpssync/getlonlat.php
@@ -0,0 +1,186 @@
+<?php
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-22
+ * Description : a php script to show GPS locator world map
+ * this script is used by GPSSync kipi-plugin.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Notes : This script use Google Map API version 2:
+ * http://www.google.com/apis/maps/documentation
+ * This script must be copied to host kipi-plugins
+ * web project page.
+ * This script accept these values from url:
+ * - 'altitude' : picture altitude.
+ * - 'longitude' : picture longitude.
+ * - 'width' : width of map.
+ * - 'height' : height of map.
+ * - 'zoom' : map zoom level.
+ * - 'maptype' : type of map (G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP)
+ * - 'filename' : photo file name as string.
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>GPSSync Kipi-plugin Geographical Location Editor</title>
+<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAy_Vv5rc03ctmYvwfsuTH6RSK29CRGKrdb78LNYpP1_riKtR3zRRxy4unyuWAi2vp7m1isLwuHObXDg"
+type="text/javascript">
+</script>
+<style type="text/css">
+ @import url("http://www.google.com/uds/css/gsearch.css");
+ @import url("http://www.google.com/uds/solutions/localsearch/gmlocalsearch.css");
+</style>
+<script src="http://www.google.com/uds/api?file=uds.js&amp;v=1.0" type="text/javascript"></script>
+<script src="http://www.google.com/uds/solutions/localsearch/gmlocalsearch.js" type="text/javascript"></script>
+
+<style type="text/css">
+ /*<![CDATA[*/
+ body {
+ padding: 0px;
+ margin: 0px;
+ }
+ /*]]>*/
+</style>
+
+<script type="text/javascript">
+
+//<![CDATA[
+function loadMap()
+{
+ var map = new GMap2(document.getElementById("map"));
+ var searchoptions = {
+ suppressInitialResultSelection : true
+ };
+
+ var markeroptions = {
+ autoPan : true,
+ draggable : true,
+<?php
+ $filename = $_GET['filename'];
+ if ($filename != "") echo "title : \"$filename\"";
+?>
+ };
+
+ map.addControl(new GLargeMapControl());
+ map.addControl(new GMapTypeControl());
+ map.addControl(new GScaleControl());
+ map.addControl(new google.maps.LocalSearch(searchoptions), new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(10,20)));
+
+<?php
+ $maptype = $_GET['maptype'];
+ if ($maptype == "") $maptype = "G_NORMAL_MAP";
+
+ echo "map.setCenter(new GLatLng(";
+ echo $_GET['latitude'];
+ echo ", ";
+ echo $_GET['longitude'];
+ echo "), ";
+ echo $_GET['zoom'];
+ echo ", ";
+ echo $maptype;
+ echo ");\n";
+
+ echo "var marker = new GMarker(new GLatLng(";
+ echo $_GET['latitude'];
+ echo ", ";
+ echo $_GET['longitude'];
+ echo "), markeroptions";
+ echo ");\n";
+
+ echo "map.addOverlay(marker)";
+?>
+
+ GEvent.addListener(map, "click",
+ function(overlay, point)
+ {
+ if (point)
+ {
+ marker.setPoint(point);
+ msg = "(lat:" + point.lat() + ", lon:" + point.lng() + ")";
+ window.status=msg;
+ }
+ }
+ );
+
+ GEvent.addListener(marker, "drag",
+ function()
+ {
+ var point = marker.getPoint();
+ msg = "(lat:" + point.lat() + ", lon:" + point.lng() + ")";
+ window.status=msg;
+ }
+ );
+
+ GEvent.addListener(marker, "dragend",
+ function()
+ {
+ var point = marker.getPoint();
+ msg = "(lat:" + point.lat() + ", lon:" + point.lng() + ")";
+ window.status=msg;
+ }
+ );
+
+ GEvent.addListener(map, "zoomend",
+ function(oldLevel, newLevel)
+ {
+ msg = "newZoomLevel:" + newLevel;
+ window.status=msg;
+ }
+ );
+
+ GEvent.addListener(map, "maptypechanged",
+ function()
+ {
+ var myMapType = map.getCurrentMapType();
+ if (myMapType == G_SATELLITE_TYPE) {msg = "newMapType:G_SATELLITE_TYPE";}
+ if (myMapType == G_MAP_TYPE) {msg = "newMapType:G_MAP_TYPE";}
+ if (myMapType == G_HYBRID_TYPE) {msg = "newMapType:G_HYBRID_TYPE";}
+ window.status=msg;
+ }
+ );
+}
+{
+ window.addEventListener("load",
+ function()
+ {
+ loadMap(); // Firefox and standard browsers
+ }
+ , false);
+}
+//]]>
+
+</script>
+</head>
+
+<body onLoad="loadMap()">
+
+<?php
+ echo "<div id=\"map\" ";
+ echo "style=\"width: ";
+ echo $_GET['width'];
+ echo "px; height: ";
+ echo $_GET['height'];
+ echo "px;\">";
+?>
+
+</div>
+</body>
+</html>
diff --git a/kipi-plugins/gpssync/getlonlatalt.php b/kipi-plugins/gpssync/getlonlatalt.php
new file mode 100644
index 0000000..91f2bac
--- /dev/null
+++ b/kipi-plugins/gpssync/getlonlatalt.php
@@ -0,0 +1,206 @@
+<?php
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-22
+ * Description : a php script to show GPS locator world map
+ * this script is used by GPSSync kipi-plugin.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2008 by Gerhard Kulzer <gerhard at kulzer dot net>
+ *
+ * Notes : This script use Google Map API version 2:
+ * http://www.google.com/apis/maps/documentation
+ * This script must be copied to host kipi-plugins
+ * web project page.
+ * This script accept these values from url:
+ * - 'altitude' : picture altitude.
+ * - 'longitude' : picture longitude.
+ * - 'width' : width of map.
+ * - 'height' : height of map.
+ * - 'zoom' : map zoom level.
+ * - 'maptype' : type of map (G_NORMAL_MAP, G_SATELLITE_MAP, G_HYBRID_MAP)
+ * - 'filename' : photo file name as string.
+
+ * Notes on the service topocoding :
+ * here is how topoGetAltitude behaves:
+ * 1. You call *topoGetAltitude*( lat, lon, action, context, timeout )
+ * 2. As soon as the server sends back the altitude, the asynchronous call
+ * to action(altitude,context) is performed.
+ * Here you can operate with the altitude information. And the context
+ * variable contains any useful data that you also want to pass in,
+ * it can be for example the reference to an element where you want the altitude to be assigned.
+ * So for example you can pass the marker as a context.
+ * Note that you can ommit the context if you don't need it.
+ * 3. If the server response does not arrive (timeout), the asynchronous
+ * call to action(null,context) is performed.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>GPSSync Kipi-plugin Geographical Location Editor</title>
+<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAy_Vv5rc03ctmYvwfsuTH6RSK29CRGKrdb78LNYpP1_riKtR3zRRxy4unyuWAi2vp7m1isLwuHObXDg"
+type="text/javascript">
+</script>
+<script src="http://www.google.com/uds/api?file=uds.js&amp;v=1.0" type="text/javascript"></script>
+<script src="http://www.google.com/uds/solutions/localsearch/gmlocalsearch.js" type="text/javascript"></script>
+<script type="text/javascript" src="http://topocoding.com/api/getapi_v1.php?key=ILOGFVOBCUOSRHC"></script>
+<style type="text/css">
+ @import url("http://www.google.com/uds/css/gsearch.css");
+ @import url("http://www.google.com/uds/solutions/localsearch/gmlocalsearch.css");
+
+ /*<![CDATA[*/
+ body {
+ padding: 0px;
+ margin: 0px;
+ }
+ /*]]>*/
+</style>
+
+<script type="text/javascript">
+
+//<![CDATA[
+
+function loadMap()
+{
+ var map = new GMap2(document.getElementById("map"));
+ var searchoptions = {
+ suppressInitialResultSelection : true
+ };
+
+ var markeroptions = {
+ autoPan : true,
+ draggable : true,
+<?php
+$topoKey = 'COMBBKMQQYCKMMK';
+include( 'topocoding.inc' );
+
+ // Gets data from URL parameters
+ $filename = $_GET['filename'];
+ if ($filename != "") echo "title : \"$filename\"";
+
+?>
+ };
+
+ map.addControl(new GLargeMapControl());
+ map.addControl(new GMapTypeControl());
+ map.addControl(new GScaleControl());
+ map.addControl(new google.maps.LocalSearch(searchoptions), new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(10,20)));
+
+<?php
+ $maptype = $_GET['maptype'];
+ if ($maptype == "") $maptype = "G_NORMAL_MAP";
+
+ echo "map.setCenter(new GLatLng(";
+ echo $_GET['latitude'];
+ echo ", ";
+ echo $_GET['longitude'];
+ echo "), ";
+ echo $_GET['zoom'];
+ echo ", ";
+ echo $maptype;
+ echo ");\n";
+
+ echo "var marker = new GMarker(new GLatLng(";
+ echo $_GET['latitude'];
+ echo ", ";
+ echo $_GET['longitude'];
+ echo "), markeroptions";
+ echo ");\n";
+ echo "map.addOverlay(marker)";
+?>
+
+ GEvent.addListener(map, "click",
+ function(overlay, point)
+ {
+ if (point)
+ {
+ marker.setPoint(point);
+ topoGetAltitude( point.lat(), point.lng(), function( altitude ) { window.status = "(lat:" + point.lat() + ", lon:" + point.lng() + ", alt:" + altitude + ")" ; } );
+ }
+ }
+ );
+
+ GEvent.addListener(marker, "drag",
+ function()
+ {
+ var point = marker.getPoint();
+ topoGetAltitude( point.lat(), point.lng(), function( altitude ) { window.status = "(lat:" + point.lat() + ", lon:" + point.lng() + ", alt:" + altitude + ")" ; } );
+ }
+ );
+
+ GEvent.addListener(marker, "dragend",
+ function()
+ {
+ var point = marker.getPoint();
+ topoGetAltitude( point.lat(), point.lng(), function( altitude ) { window.status = "(lat:" + point.lat() + ", lon:" + point.lng() + ", alt:" + altitude + ")" ; } );
+ }
+ );
+
+ GEvent.addListener(map, "zoomend",
+ function(oldLevel, newLevel)
+ {
+ msg = "newZoomLevel:" + newLevel;
+ window.status=msg;
+ }
+ );
+
+ GEvent.addListener(map, "maptypechanged",
+ function()
+ {
+ var myMapType = map.getCurrentMapType();
+ if (myMapType == G_SATELLITE_TYPE) {msg = "newMapType:G_SATELLITE_TYPE";}
+ if (myMapType == G_MAP_TYPE) {msg = "newMapType:G_MAP_TYPE";}
+ if (myMapType == G_HYBRID_TYPE) {msg = "newMapType:G_HYBRID_TYPE";}
+ window.status=msg;
+ }
+ );
+}
+{
+ window.addEventListener("load",
+ function()
+ {
+ loadMap(); // Firefox and standard browsers
+ }
+ , false);
+}
+//]]>
+
+</script>
+</head>
+
+<body onLoad="loadMap()">
+<div>
+<?php
+// print_r ( topoGetAltitudes( array( array( 'latitude', 'longitude' ) ) ) );
+?>
+</div>
+<?php
+ echo "<div id=\"map\" ";
+ echo "style=\"width: ";
+ echo $_GET['width'];
+ echo "px; height: ";
+ echo $_GET['height'];
+ echo "px;\">";
+?>
+
+</div>
+</body>
+</html>
diff --git a/kipi-plugins/gpssync/gpsbabelbinary.cpp b/kipi-plugins/gpssync/gpsbabelbinary.cpp
new file mode 100644
index 0000000..5dd6ab2
--- /dev/null
+++ b/kipi-plugins/gpssync/gpsbabelbinary.cpp
@@ -0,0 +1,125 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-19
+ * Description : Autodetect gpsbabel binary program and version
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes
+
+#include <kapplication.h>
+#include <kprocess.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+// Local includes
+
+#include "gpsbabelbinary.h"
+#include "gpsbabelbinary.moc"
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSBabelBinaryPriv
+{
+public:
+
+ GPSBabelBinaryPriv()
+ {
+ available = false;
+ version = QString::null;
+ }
+
+ bool available;
+
+ QString version;
+};
+
+GPSBabelBinary::GPSBabelBinary()
+ : QObject()
+{
+ d = new GPSBabelBinaryPriv;
+ checkSystem();
+}
+
+GPSBabelBinary::~GPSBabelBinary()
+{
+ delete d;
+}
+
+void GPSBabelBinary::checkSystem()
+{
+ KProcess process;
+ process.clearArguments();
+ process << path() << "-V";
+
+ connect(&process, SIGNAL(receivedStdout(KProcess *, char*, int)),
+ this, SLOT(slotReadStdoutFromGPSBabel(KProcess*, char*, int)));
+
+ d->available = process.start(KProcess::Block, KProcess::Stdout);
+}
+
+void GPSBabelBinary::slotReadStdoutFromGPSBabel(KProcess*, char* buffer, int buflen)
+{
+ // The gpsbabel output look like this : GPSBabel Version 1.2.5
+ QString headerStarts("GPSBabel Version ");
+
+ QString stdOut = QString::fromLocal8Bit(buffer, buflen);
+ QString firstLine = stdOut.section('\n', 1, 1);
+
+ if (firstLine.startsWith(headerStarts))
+ {
+ d->version = firstLine.remove(0, headerStarts.length());
+ kdDebug( 51001 ) << "Found gpsbabel version: " << version() << endl;
+ }
+}
+
+const char *GPSBabelBinary::path()
+{
+ return "gpsbabel";
+}
+
+bool GPSBabelBinary::isAvailable() const
+{
+ return d->available;
+}
+
+QString GPSBabelBinary::version() const
+{
+ return d->version;
+}
+
+bool GPSBabelBinary::versionIsRight() const
+{
+ if (d->version.isNull() || !isAvailable())
+ return false;
+
+ if (d->version.toFloat() >= minimalVersion().toFloat())
+ return true;
+
+ return false;
+}
+
+QString GPSBabelBinary::minimalVersion() const
+{
+ return QString("1.2.5");
+}
+
+} // namespace KIPIGPSSyncPlugin
diff --git a/kipi-plugins/gpssync/gpsbabelbinary.h b/kipi-plugins/gpssync/gpsbabelbinary.h
new file mode 100644
index 0000000..3dc95ab
--- /dev/null
+++ b/kipi-plugins/gpssync/gpsbabelbinary.h
@@ -0,0 +1,66 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-19
+ * Description : Autodetect gpsbabel binary program and version
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPSBABELBINARY_H
+#define GPSBABELBINARY_H
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qobject.h>
+
+class KProcess;
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSBabelBinaryPriv;
+
+class GPSBabelBinary : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ GPSBabelBinary();
+ ~GPSBabelBinary();
+
+ static const char *path();
+ bool isAvailable() const;
+ QString version() const;
+ bool versionIsRight() const;
+ QString minimalVersion() const;
+
+ void checkSystem();
+
+private slots:
+
+ void slotReadStdoutFromGPSBabel(KProcess*, char*, int);
+
+private:
+
+ GPSBabelBinaryPriv *d;
+};
+
+} // namespace KIPIGPSSyncPlugin
+
+#endif // GPSBABELBINARY_H
diff --git a/kipi-plugins/gpssync/gpsdatacontainer.h b/kipi-plugins/gpssync/gpsdatacontainer.h
new file mode 100644
index 0000000..2413950
--- /dev/null
+++ b/kipi-plugins/gpssync/gpsdatacontainer.h
@@ -0,0 +1,78 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-19
+ * Description : GPS data container.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPSDATACONTAINER_H
+#define GPSDATACONTAINER_H
+
+// Qt includes.
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSDataContainer
+{
+public:
+
+ GPSDataContainer(): m_interpolated(false), m_altitude(0.0),
+ m_latitude(0.0), m_longitude(0.0)
+ {};
+
+ GPSDataContainer(double altitude, double latitude,
+ double longitude, bool interpolated)
+ : m_interpolated(interpolated), m_altitude(altitude),
+ m_latitude(latitude), m_longitude(longitude)
+ {};
+
+ ~GPSDataContainer()
+ {};
+
+ GPSDataContainer& operator=(const GPSDataContainer& data)
+ {
+ m_interpolated = data.isInterpolated();
+ m_altitude = data.altitude();
+ m_latitude = data.latitude();
+ m_longitude = data.longitude();
+ return *this;
+ };
+
+ void setInterpolated(bool ite) { m_interpolated = ite; };
+ void setAltitude(double alt) { m_altitude = alt; };
+ void setLatitude(double lat) { m_latitude = lat; };
+ void setLongitude(double lng) { m_longitude = lng; };
+
+ bool isInterpolated() const { return m_interpolated; };
+ double altitude() const { return m_altitude; };
+ double latitude() const { return m_latitude; };
+ double longitude() const { return m_longitude; };
+
+private:
+
+ bool m_interpolated;
+
+ double m_altitude;
+ double m_latitude;
+ double m_longitude;
+};
+
+} // NameSpace KIPIGPSSyncPlugin
+
+#endif // GPSDATACONTAINER_H
diff --git a/kipi-plugins/gpssync/gpsdataparser.cpp b/kipi-plugins/gpssync/gpsdataparser.cpp
new file mode 100644
index 0000000..2124f1d
--- /dev/null
+++ b/kipi-plugins/gpssync/gpsdataparser.cpp
@@ -0,0 +1,275 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-19
+ * Description : GPS data file parser.
+ * (GPX format http://www.topografix.com/gpx.asp).
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qfile.h>
+#include <qdom.h>
+#include <qtextstream.h>
+
+// KDE includes.
+
+#include <kdebug.h>
+
+// Local includes.
+
+#include "gpsdataparser.h"
+
+namespace KIPIGPSSyncPlugin
+{
+
+GPSDataParser::GPSDataParser()
+{
+ clear();
+}
+
+void GPSDataParser::clear()
+{
+ m_GPSDataMap.clear();
+}
+
+int GPSDataParser::numPoints()
+{
+ return m_GPSDataMap.count();
+}
+
+bool GPSDataParser::matchDate(const QDateTime& photoDateTime, int maxGapTime, int timeZone,
+ bool interpolate, int interpolationDstTime,
+ GPSDataContainer& gpsData)
+{
+ // GPS device are sync in time by satelite using GMT time.
+ // If the camera time is different than GMT time, we need to convert it to GMT time
+ // Using the time zone.
+ QDateTime cameraGMTDateTime = photoDateTime.addSecs(timeZone*(-1));
+
+ kdDebug() << "cameraGMTDateTime: " << cameraGMTDateTime << endl;
+
+ // We trying to find the right date in the GPS points list.
+ bool findItem = false;
+ int nbSecItem = maxGapTime;
+ int nbSecs;
+
+ for (GPSDataMap::Iterator it = m_GPSDataMap.begin();
+ it != m_GPSDataMap.end(); ++it )
+ {
+ // Here we check a possible accuracy in seconds between the
+ // Camera GMT time and the GPS device GMT time.
+
+ nbSecs = abs(cameraGMTDateTime.secsTo( it.key() ));
+
+ // We tring to find the minimal accuracy.
+ if( nbSecs < maxGapTime && nbSecs < nbSecItem)
+ {
+ gpsData = m_GPSDataMap[it.key()];
+ findItem = true;
+ nbSecItem = nbSecs;
+ }
+ }
+
+ if (findItem) return true;
+
+ // If we can't find it, we will trying to interpolate the GPS point.
+
+ if (interpolate)
+ {
+ // The interpolate GPS point will be separate by at the maximum of 'interpolationDstTime'
+ // seconds before and after the next and previous real GPS point found.
+
+ QDateTime prevDateTime = findPrevDate(cameraGMTDateTime, interpolationDstTime);
+ QDateTime nextDateTime = findNextDate(cameraGMTDateTime, interpolationDstTime);
+
+ if (!nextDateTime.isNull() && !prevDateTime.isNull())
+ {
+ GPSDataContainer prevGPSPoint = m_GPSDataMap[prevDateTime];
+ GPSDataContainer nextGPSPoint = m_GPSDataMap[nextDateTime];
+
+ double alt1 = prevGPSPoint.altitude();
+ double lon1 = prevGPSPoint.longitude();
+ double lat1 = prevGPSPoint.latitude();
+ uint t1 = prevDateTime.toTime_t();
+ double alt2 = nextGPSPoint.altitude();
+ double lon2 = nextGPSPoint.longitude();
+ double lat2 = nextGPSPoint.latitude();
+ uint t2 = nextDateTime.toTime_t();
+ uint tCor = cameraGMTDateTime.toTime_t();
+
+ if (tCor-t1 != 0)
+ {
+ gpsData.setAltitude(alt1 + (alt2-alt1) * (tCor-t1)/(t2-t1));
+ gpsData.setLatitude(lat1 + (lat2-lat1) * (tCor-t1)/(t2-t1));
+ gpsData.setLongitude(lon1 + (lon2-lon1) * (tCor-t1)/(t2-t1));
+ gpsData.setInterpolated(true);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+QDateTime GPSDataParser::findNextDate(const QDateTime& dateTime, int secs)
+{
+ // We will find the item in GPS data list where the time is
+ // at the maximum bigger than 'secs' mn of the value to match.
+ QDateTime itemFound = dateTime.addSecs(secs);
+ bool found = false;
+
+ for (GPSDataMap::Iterator it = m_GPSDataMap.begin();
+ it != m_GPSDataMap.end(); ++it )
+ {
+ if (it.key() > dateTime)
+ {
+ if (it.key() < itemFound)
+ {
+ itemFound = it.key();
+ found = true;
+ }
+ }
+ }
+
+ if (found)
+ return itemFound;
+
+ return QDateTime();
+}
+
+QDateTime GPSDataParser::findPrevDate(const QDateTime& dateTime, int secs)
+{
+ // We will find the item in GPS data list where the time is
+ // at the maximum smaller than 'secs' mn of the value to match.
+ QDateTime itemFound = dateTime.addSecs((-1)*secs);
+ bool found = false;
+
+ for (GPSDataMap::Iterator it = m_GPSDataMap.begin();
+ it != m_GPSDataMap.end(); ++it )
+ {
+ if (it.key() < dateTime)
+ {
+ if (it.key() > itemFound)
+ {
+ itemFound = it.key();
+ found = true;
+ }
+ }
+ }
+
+ if (found)
+ return itemFound;
+
+ return QDateTime();
+}
+
+bool GPSDataParser::loadGPXFile(const KURL& url)
+{
+ QFile gpxfile(url.path());
+
+ if (!gpxfile.open(IO_ReadOnly))
+ return false;
+
+ QDomDocument gpxDoc("gpx");
+ if (!gpxDoc.setContent(&gpxfile))
+ return false;
+
+ QDomElement gpxDocElem = gpxDoc.documentElement();
+ if (gpxDocElem.tagName()!="gpx")
+ return false;
+
+ for (QDomNode nTrk = gpxDocElem.firstChild();
+ !nTrk.isNull(); nTrk = nTrk.nextSibling())
+ {
+ QDomElement trkElem = nTrk.toElement();
+ if (trkElem.isNull()) continue;
+ if (trkElem.tagName() != "trk") continue;
+
+ for (QDomNode nTrkseg = trkElem.firstChild();
+ !nTrkseg.isNull(); nTrkseg = nTrkseg.nextSibling())
+ {
+ QDomElement trksegElem = nTrkseg.toElement();
+ if (trksegElem.isNull()) continue;
+ if (trksegElem.tagName() != "trkseg") continue;
+
+ for (QDomNode nTrkpt = trksegElem.firstChild();
+ !nTrkpt.isNull(); nTrkpt = nTrkpt.nextSibling())
+ {
+ QDomElement trkptElem = nTrkpt.toElement();
+ if (trkptElem.isNull()) continue;
+ if (trkptElem.tagName() != "trkpt") continue;
+
+ QDateTime ptDateTime;
+ double ptAltitude = 0.0;
+ double ptLatitude = 0.0;
+ double ptLongitude = 0.0;
+
+ // Get GPS position. If not available continue to next point.
+ QString lat = trkptElem.attribute("lat");
+ QString lon = trkptElem.attribute("lon");
+ if (lat.isEmpty() || lon.isEmpty()) continue;
+
+ ptLatitude = lat.toDouble();
+ ptLongitude = lon.toDouble();
+
+ // Get metadata of track point (altitude and time stamp)
+ for (QDomNode nTrkptMeta = trkptElem.firstChild();
+ !nTrkptMeta.isNull(); nTrkptMeta = nTrkptMeta.nextSibling())
+ {
+ QDomElement trkptMetaElem = nTrkptMeta.toElement();
+ if (trkptMetaElem.isNull()) continue;
+ if (trkptMetaElem.tagName() == QString("time"))
+ {
+ // Get GPS point time stamp. If not available continue to next point.
+ QString time = trkptMetaElem.text();
+ if (time.isEmpty()) continue;
+ ptDateTime = QDateTime::fromString(time, Qt::ISODate);
+ }
+ if (trkptMetaElem.tagName() == QString("ele"))
+ {
+ // Get GPS point altitude. If not available continue to next point.
+ QString ele = trkptMetaElem.text();
+ if (!ele.isEmpty())
+ ptAltitude = ele.toDouble();
+ }
+ }
+
+ if (ptDateTime.isNull())
+ continue;
+
+ GPSDataContainer gpsData(ptAltitude, ptLatitude, ptLongitude, false);
+ m_GPSDataMap.insert( ptDateTime, gpsData );
+ }
+ }
+ }
+
+ kdDebug( 51001 ) << "GPX File " << url.fileName()
+ << " parsed with " << numPoints()
+ << " points extracted" << endl;
+ return true;
+}
+
+} // NameSpace KIPIGPSSyncPlugin
diff --git a/kipi-plugins/gpssync/gpsdataparser.h b/kipi-plugins/gpssync/gpsdataparser.h
new file mode 100644
index 0000000..121a97e
--- /dev/null
+++ b/kipi-plugins/gpssync/gpsdataparser.h
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-19
+ * Description : GPS data file parser.
+ * (GPX format http://www.topografix.com/gpx.asp).
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPSDATAPARSER_H
+#define GPSDATAPARSER_H
+
+// Qt includes.
+
+#include <qdatetime.h>
+#include <qmap.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "gpsdatacontainer.h"
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSDataParser
+{
+
+public:
+
+ GPSDataParser();
+ ~GPSDataParser(){};
+
+ bool loadGPXFile(const KURL& url);
+
+ void clear();
+ int numPoints();
+ bool matchDate(const QDateTime& photoDateTime, int maxGapTime, int timeZone,
+ bool interpolate, int interpolationDstTime,
+ GPSDataContainer& gpsData);
+
+private:
+
+ // Methods used to perform interpolation.
+ QDateTime findNextDate(const QDateTime& dateTime, int secs);
+ QDateTime findPrevDate(const QDateTime& dateTime, int secs);
+
+protected:
+
+ typedef QMap<QDateTime, GPSDataContainer> GPSDataMap;
+
+ GPSDataMap m_GPSDataMap;
+};
+
+} // NameSpace KIPIGPSSyncPlugin
+
+#endif // GPSDATAPARSER_H
diff --git a/kipi-plugins/gpssync/gpseditdialog.cpp b/kipi-plugins/gpssync/gpseditdialog.cpp
new file mode 100644
index 0000000..032aecd
--- /dev/null
+++ b/kipi-plugins/gpssync/gpseditdialog.cpp
@@ -0,0 +1,339 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-22
+ * Description : a dialog to edit GPS positions
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qtimer.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qvalidator.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <khelpmenu.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <klineedit.h>
+#include <kmessagebox.h>
+#include <khtmlview.h>
+#include <kpopupmenu.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "gpsmapwidget.h"
+#include "gpseditdialog.h"
+#include "gpseditdialog.moc"
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSEditDialogDialogPrivate
+{
+
+public:
+
+ GPSEditDialogDialogPrivate()
+ {
+ altitudeInput = 0;
+ latitudeInput = 0;
+ longitudeInput = 0;
+ worldMap = 0;
+ about = 0;
+ goButton = 0;
+ hasGPSInfo = false;
+ }
+
+ bool hasGPSInfo;
+
+ QPushButton *goButton;
+
+ KLineEdit *altitudeInput;
+ KLineEdit *latitudeInput;
+ KLineEdit *longitudeInput;
+
+ KIPIPlugins::KPAboutData *about;
+
+ GPSDataContainer gpsData;
+
+ GPSMapWidget *worldMap;
+};
+
+GPSEditDialog::GPSEditDialog(QWidget* parent, const GPSDataContainer& gpsData,
+ const QString& fileName, bool hasGPSInfo)
+ : KDialogBase(Plain, i18n("%1 - Edit Geographical Coordinates").arg(fileName),
+ Help|Ok|Cancel, Ok,
+ parent, 0, true, false)
+{
+ d = new GPSEditDialogDialogPrivate;
+ d->hasGPSInfo = hasGPSInfo;
+ d->gpsData = gpsData;
+
+ QGridLayout* grid = new QGridLayout(plainPage(), 8, 3, 0, spacingHint());
+
+ QLabel *message = new QLabel(i18n("<p>Use the map on the right to select the location where "
+ "the picture have been taken. Click with left mouse button or move the marker "
+ "on the map to get the GPS coordinates.<p>"), plainPage());
+
+ QLabel *altitudeLabel = new QLabel(i18n("Altitude:"), plainPage());
+ QLabel *latitudeLabel = new QLabel(i18n("Latitude:"), plainPage());
+ QLabel *longitudeLabel = new QLabel(i18n("Longitude:"), plainPage());
+
+ d->altitudeInput = new KLineEdit(plainPage());
+ d->latitudeInput = new KLineEdit(plainPage());
+ d->longitudeInput = new KLineEdit(plainPage());
+
+ QPushButton *altResetButton = new QPushButton(SmallIcon("clear_left"), QString::null, plainPage());
+ QPushButton *latResetButton = new QPushButton(SmallIcon("clear_left"), QString::null, plainPage());
+ QPushButton *lonResetButton = new QPushButton(SmallIcon("clear_left"), QString::null, plainPage());
+
+ d->altitudeInput->setValidator(new QDoubleValidator(-20000.0, 20000.0, 1, this));
+ d->latitudeInput->setValidator(new QDoubleValidator(-90.0, 90.0, 12, this));
+ d->longitudeInput->setValidator(new QDoubleValidator(-180.0, 180.0, 12, this));
+
+ d->goButton = new QPushButton(i18n("Goto Location"), plainPage());
+ d->goButton->setEnabled(false);
+
+ d->worldMap = new GPSMapWidget(plainPage());
+ d->worldMap->setFileName(fileName);
+ d->worldMap->show();
+
+ grid->addMultiCellWidget(message, 0, 0, 0, 2);
+ grid->addMultiCellWidget(altitudeLabel, 1, 1, 0, 2);
+ grid->addMultiCellWidget(d->altitudeInput, 2, 2, 0, 1);
+ grid->addMultiCellWidget(altResetButton, 2, 2, 2, 2);
+ grid->addMultiCellWidget(latitudeLabel, 3, 3, 0, 2);
+ grid->addMultiCellWidget(d->latitudeInput, 4, 4, 0, 1);
+ grid->addMultiCellWidget(latResetButton, 4, 4, 2, 2);
+ grid->addMultiCellWidget(longitudeLabel, 5, 5, 0, 2);
+ grid->addMultiCellWidget(d->longitudeInput, 6, 6, 0, 1);
+ grid->addMultiCellWidget(lonResetButton, 6, 6, 2, 2);
+ grid->addMultiCellWidget(d->goButton, 7, 7, 0, 1);
+ grid->addMultiCellWidget(d->worldMap->view(), 0, 8, 3, 3);
+ grid->setColStretch(0, 3);
+ grid->setColStretch(3, 10);
+ grid->setRowStretch(8, 10);
+
+ // ---------------------------------------------------------------
+ // About data and help button.
+
+ d->about = new KIPIPlugins::KPAboutData(I18N_NOOP("GPS Sync"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Plugin to synchronize pictures metadata with a GPS device"),
+ "(c) 2006-2008, Gilles Caulier");
+
+ d->about->addAuthor("Gilles Caulier", I18N_NOOP("Author and Maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, d->about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"),
+ this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // ---------------------------------------------------------------
+
+ connect(altResetButton, SIGNAL(released()),
+ d->altitudeInput, SLOT(clear()));
+
+ connect(latResetButton, SIGNAL(released()),
+ d->latitudeInput, SLOT(clear()));
+
+ connect(lonResetButton, SIGNAL(released()),
+ d->longitudeInput, SLOT(clear()));
+
+ connect(d->altitudeInput, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotGPSPositionChanged()));
+
+ connect(d->latitudeInput, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotGPSPositionChanged()));
+
+ connect(d->longitudeInput, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotGPSPositionChanged()));
+
+ connect(d->worldMap, SIGNAL(signalNewGPSLocationFromMap(const QString&, const QString&, const QString&)),
+ this, SLOT(slotNewGPSLocationFromMap(const QString&, const QString&, const QString&)));
+
+ connect(d->goButton, SIGNAL(released()),
+ this, SLOT(slotGotoLocation()));
+
+ // ---------------------------------------------------------------
+
+ readSettings();
+ QTimer::singleShot(0, this, SLOT(slotUpdateWorldMap()));
+}
+
+GPSEditDialog::~GPSEditDialog()
+{
+ delete d->about;
+ delete d;
+}
+
+void GPSEditDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("gpssync", "kipi-plugins");
+}
+
+void GPSEditDialog::closeEvent(QCloseEvent *e)
+{
+ if (!e) return;
+ saveSettings();
+ e->accept();
+}
+
+void GPSEditDialog::slotGPSPositionChanged()
+{
+ d->goButton->setEnabled(true);
+}
+
+void GPSEditDialog::slotGotoLocation()
+{
+ if (!checkGPSLocation()) return;
+ d->worldMap->setGPSPosition(d->latitudeInput->text(), d->longitudeInput->text());
+ slotUpdateWorldMap();
+}
+
+void GPSEditDialog::slotUpdateWorldMap()
+{
+ d->worldMap->resized();
+}
+
+void GPSEditDialog::resizeEvent(QResizeEvent *e)
+{
+ if (!e) return;
+ slotUpdateWorldMap();
+}
+
+void GPSEditDialog::slotCancel()
+{
+ saveSettings();
+ KDialogBase::slotCancel();
+}
+
+void GPSEditDialog::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("GPS Sync Settings");
+ resize(configDialogSize(config, QString("GPS Edit Dialog")));
+
+ d->worldMap->setZoomLevel(config.readNumEntry("Zoom Level", 8));
+ d->worldMap->setMapType(config.readEntry("Map Type", QString("G_MAP_TYPE")));
+
+ d->altitudeInput->blockSignals(true);
+ d->latitudeInput->blockSignals(true);
+ d->longitudeInput->blockSignals(true);
+
+ if (d->hasGPSInfo)
+ {
+ d->altitudeInput->setText(QString::number(d->gpsData.altitude(), 'g', 12));
+ d->latitudeInput->setText(QString::number(d->gpsData.latitude(), 'g', 12));
+ d->longitudeInput->setText(QString::number(d->gpsData.longitude(), 'g', 12));
+ }
+ else
+ {
+ d->altitudeInput->setText(QString::number(config.readDoubleNumEntry("GPS Last Altitude", 0.0), 'g', 12));
+ d->latitudeInput->setText(QString::number(config.readDoubleNumEntry("GPS Last Latitude", 0.0), 'g', 12));
+ d->longitudeInput->setText(QString::number(config.readDoubleNumEntry("GPS Last Longitude", 0.0), 'g', 12));
+ }
+
+ d->altitudeInput->blockSignals(false);
+ d->latitudeInput->blockSignals(false);
+ d->longitudeInput->blockSignals(false);
+
+ d->worldMap->setGPSPosition(d->latitudeInput->text(), d->longitudeInput->text());
+ d->worldMap->resized();
+}
+
+void GPSEditDialog::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("GPS Sync Settings");
+ saveDialogSize(config, QString("GPS Edit Dialog"));
+ config.writeEntry("GPS Last Latitude", d->latitudeInput->text().toDouble());
+ config.writeEntry("GPS Last Longitude", d->longitudeInput->text().toDouble());
+ config.writeEntry("GPS Last Altitude", d->altitudeInput->text().toDouble());
+ config.writeEntry("Zoom Level", d->worldMap->zoomLevel());
+ config.writeEntry("Map Type", d->worldMap->mapType());
+ config.sync();
+}
+
+GPSDataContainer GPSEditDialog::getGPSInfo()
+{
+ return GPSDataContainer(d->altitudeInput->text().toDouble(),
+ d->latitudeInput->text().toDouble(),
+ d->longitudeInput->text().toDouble(),
+ false);
+}
+
+bool GPSEditDialog::checkGPSLocation()
+{
+ bool ok;
+
+ d->altitudeInput->text().toDouble(&ok);
+ if (!ok)
+ {
+ KMessageBox::error(this, i18n("Altitude value is not correct!"),
+ i18n("Edit Geographical Coordinates"));
+ return false;
+ }
+
+ d->latitudeInput->text().toDouble(&ok);
+ if (!ok)
+ {
+ KMessageBox::error(this, i18n("Latitude value is not correct!"),
+ i18n("Edit Geographical Coordinates"));
+ return false;
+ }
+
+ d->longitudeInput->text().toDouble(&ok);
+ if (!ok)
+ {
+ KMessageBox::error(this, i18n("Longitude value is not correct!"),
+ i18n("Edit Geographical Coordinates"));
+ return false;
+ }
+
+ return true;
+}
+
+void GPSEditDialog::slotOk()
+{
+ if (!checkGPSLocation()) return;
+ saveSettings();
+ accept();
+}
+
+void GPSEditDialog::slotNewGPSLocationFromMap(const QString& lat, const QString& lon, const QString& alt)
+{
+ d->latitudeInput->setText(lat);
+ d->longitudeInput->setText(lon);
+ d->altitudeInput->setText(alt);
+ d->goButton->setEnabled(false);
+}
+
+} // namespace KIPIGPSSyncPlugin
diff --git a/kipi-plugins/gpssync/gpseditdialog.h b/kipi-plugins/gpssync/gpseditdialog.h
new file mode 100644
index 0000000..5ce243d
--- /dev/null
+++ b/kipi-plugins/gpssync/gpseditdialog.h
@@ -0,0 +1,79 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-22
+ * Description : a dialog to edit GPS positions
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPSEDITDIALOG_H
+#define GPSEDITDIALOG_H
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Local includes.
+
+#include "gpsdatacontainer.h"
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSEditDialogDialogPrivate;
+
+class GPSEditDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ GPSEditDialog(QWidget* parent, const GPSDataContainer& gpsData,
+ const QString& fileName, bool hasGPSInfo);
+ ~GPSEditDialog();
+
+ GPSDataContainer getGPSInfo();
+
+protected slots:
+
+ void slotOk();
+ void slotCancel();
+ void slotNewGPSLocationFromMap(const QString& lat, const QString& lon, const QString& alt);
+ void slotUpdateWorldMap();
+ void slotGotoLocation();
+ void slotGPSPositionChanged();
+ void slotHelp();
+
+protected:
+
+ void resizeEvent(QResizeEvent *);
+ void closeEvent(QCloseEvent *);
+
+private:
+
+ void readSettings();
+ void saveSettings();
+ bool checkGPSLocation();
+
+private:
+
+ GPSEditDialogDialogPrivate *d;
+};
+
+} // namespace KIPIGPSSyncPlugin
+
+#endif /* GPSEDITDIALOG_H */
diff --git a/kipi-plugins/gpssync/gpslistviewitem.cpp b/kipi-plugins/gpssync/gpslistviewitem.cpp
new file mode 100644
index 0000000..8951c87
--- /dev/null
+++ b/kipi-plugins/gpssync/gpslistviewitem.cpp
@@ -0,0 +1,246 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-19
+ * Description : GPS file list view item.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qpainter.h>
+#include <qfileinfo.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kiconloader.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "gpslistviewitem.h"
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSListViewItemPriv
+{
+public:
+
+ GPSListViewItemPriv()
+ {
+ enabled = false;
+ dirty = false;
+ erase = false;
+ hasGPSInfo = false;
+ }
+
+ bool enabled;
+ bool dirty;
+ bool erase;
+ bool hasGPSInfo;
+
+ QDateTime date;
+
+ KURL url;
+
+ GPSDataContainer gpsData;
+};
+
+GPSListViewItem::GPSListViewItem(KListView *view, QListViewItem *after, const KURL& url)
+ : KListViewItem(view, after)
+{
+ d = new GPSListViewItemPriv;
+ d->url = url;
+
+ setEnabled(false);
+ setPixmap(0, SmallIcon( "file_broken", KIcon::SizeLarge, KIcon::DisabledState ));
+ setText(1, d->url.fileName());
+
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.load(d->url.path());
+ setDateTime(exiv2Iface.getImageDateTime());
+ double alt, lat, lng;
+ d->hasGPSInfo = exiv2Iface.getGPSInfo(alt, lat, lng);
+ if (hasGPSInfo())
+ setGPSInfo(GPSDataContainer(alt, lat, lng, false), false);
+}
+
+GPSListViewItem::~GPSListViewItem()
+{
+ delete d;
+}
+
+void GPSListViewItem::setGPSInfo(const GPSDataContainer& gpsData, bool dirty, bool addedManually)
+{
+ setEnabled(true);
+ d->dirty = dirty;
+ d->gpsData = gpsData;
+ d->erase = false;
+ d->hasGPSInfo = true;
+ setText(3, QString::number(d->gpsData.latitude(), 'g', 12));
+ setText(4, QString::number(d->gpsData.longitude(), 'g', 12));
+ setText(5, QString::number(d->gpsData.altitude(), 'g', 12));
+
+ if (isDirty())
+ {
+ QString status;
+
+ if (d->gpsData.isInterpolated())
+ status = i18n("Interpolated");
+ else
+ {
+ if (addedManually)
+ status = i18n("Added");
+ else
+ status = i18n("Found");
+ }
+
+ setText(6, status);
+ }
+
+ repaint();
+}
+
+GPSDataContainer GPSListViewItem::GPSInfo() const
+{
+ return d->gpsData;
+}
+
+void GPSListViewItem::eraseGPSInfo()
+{
+ d->erase = true;
+ d->dirty = true;
+ setText(6, i18n("Deleted!"));
+ repaint();
+}
+
+void GPSListViewItem::setDateTime(const QDateTime& date)
+{
+ if (date.isValid())
+ {
+ d->date = date;
+ setText(2, date.toString(Qt::LocalDate));
+ }
+ else
+ {
+ setText(2, i18n("Not available"));
+ }
+}
+
+QDateTime GPSListViewItem::dateTime() const
+{
+ return d->date;
+}
+
+KURL GPSListViewItem::url()
+{
+ return d->url;
+}
+
+bool GPSListViewItem::hasGPSInfo()
+{
+ return d->hasGPSInfo;
+}
+
+bool GPSListViewItem::isInterpolated()
+{
+ return d->gpsData.isInterpolated();
+}
+
+void GPSListViewItem::writeGPSInfoToFile()
+{
+ if (isEnabled() && isDirty())
+ {
+ setPixmap(1, SmallIcon("run"));
+ KExiv2Iface::KExiv2 exiv2Iface;
+ bool ret = exiv2Iface.load(d->url.path());
+
+ if (d->erase)
+ ret &= exiv2Iface.removeGPSInfo();
+ else
+ {
+ ret &= exiv2Iface.setGPSInfo(d->gpsData.altitude(),
+ d->gpsData.latitude(),
+ d->gpsData.longitude());
+ }
+
+ ret &= exiv2Iface.save(d->url.path());
+
+ if (ret)
+ setPixmap(1, SmallIcon("ok"));
+ else
+ setPixmap(1, SmallIcon("cancel"));
+
+ d->dirty = false;
+ }
+}
+
+void GPSListViewItem::setEnabled(bool e)
+{
+ d->enabled = e;
+ repaint();
+}
+
+bool GPSListViewItem::isEnabled()
+{
+ return d->enabled;
+}
+
+bool GPSListViewItem::isDirty()
+{
+ return d->dirty;
+}
+
+void GPSListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
+{
+ if (isEnabled())
+ {
+ if ( isDirty() && !d->erase && column >= 3 && column <= 5 )
+ {
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+ _cg.setColor( QColorGroup::Text, Qt::red );
+ KListViewItem::paintCell( p, _cg, column, width, alignment );
+ _cg.setColor( QColorGroup::Text, c );
+ }
+ else if ( isDirty() && d->erase && column == 6)
+ {
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+ _cg.setColor( QColorGroup::Text, Qt::red );
+ KListViewItem::paintCell( p, _cg, column, width, alignment );
+ _cg.setColor( QColorGroup::Text, c );
+ }
+ else
+ KListViewItem::paintCell(p, cg, column, width, alignment);
+ }
+ else
+ {
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+ _cg.setColor( QColorGroup::Text, Qt::gray );
+ KListViewItem::paintCell( p, _cg, column, width, alignment );
+ _cg.setColor( QColorGroup::Text, c );
+ }
+}
+
+} // NameSpace KIPIGPSSyncPlugin
diff --git a/kipi-plugins/gpssync/gpslistviewitem.h b/kipi-plugins/gpssync/gpslistviewitem.h
new file mode 100644
index 0000000..b4483c5
--- /dev/null
+++ b/kipi-plugins/gpssync/gpslistviewitem.h
@@ -0,0 +1,83 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-19
+ * Description : GPS file list view item.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPSLISTVIEWITEM_H
+#define GPSLISTVIEWITEM_H
+
+// Qt includes.
+
+#include <qdatetime.h>
+#include <qstring.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <klistview.h>
+
+// Local includes.
+
+#include "gpsdatacontainer.h"
+
+class QPainter;
+class QColorGroup;
+class QPixmap;
+
+namespace KIPIGPSSyncPlugin
+{
+class GPSListViewItemPriv;
+
+class GPSListViewItem : public KListViewItem
+{
+
+public:
+
+ GPSListViewItem(KListView *view, QListViewItem *after, const KURL& url);
+ ~GPSListViewItem();
+
+ void setGPSInfo(const GPSDataContainer& gpsData, bool dirty=true, bool addedManually=false);
+ GPSDataContainer GPSInfo() const;
+ void eraseGPSInfo();
+
+ void setDateTime(const QDateTime &date);
+ QDateTime dateTime() const;
+
+ void setEnabled(bool e);
+ bool isEnabled();
+ bool isDirty();
+ bool isInterpolated();
+ bool hasGPSInfo();
+
+ KURL url();
+ void writeGPSInfoToFile();
+
+protected:
+
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment);
+
+private:
+
+ GPSListViewItemPriv *d;
+};
+
+} // NameSpace KIPIGPSSyncPlugin
+
+#endif /* GPSLISTVIEWITEM_H */
diff --git a/kipi-plugins/gpssync/gpsmapwidget.cpp b/kipi-plugins/gpssync/gpsmapwidget.cpp
new file mode 100644
index 0000000..92484cd
--- /dev/null
+++ b/kipi-plugins/gpssync/gpsmapwidget.cpp
@@ -0,0 +1,188 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-28
+ * Description : a widget to display a GPS web map locator.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2008 by Gerhard Kulzer <gerhard at kulzer dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <kdebug.h>
+#include <khtmlview.h>
+#include <kurl.h>
+
+// Local includes.
+
+#include "gpsmapwidget.h"
+#include "gpsmapwidget.moc"
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSMapWidgetPrivate
+{
+
+public:
+
+ GPSMapWidgetPrivate()
+ {
+ gpsLocalorUrl = QString("http://digikam3rdparty.free.fr/gpslocator/getlonlatalt.php");
+ }
+
+ QString gpsLocalorUrl;
+ QString latitude;
+ QString longitude;
+ QString altitude;
+ QString zoomLevel;
+ QString mapType;
+ QString fileName;
+};
+
+GPSMapWidget::GPSMapWidget(QWidget* parent)
+ : KHTMLPart(parent)
+{
+ d = new GPSMapWidgetPrivate;
+
+ setJScriptEnabled(true);
+ setDNDEnabled(false);
+ setEditable(false);
+
+ view()->setVScrollBarMode(QScrollView::AlwaysOff);
+ view()->setHScrollBarMode(QScrollView::AlwaysOff);
+ view()->setMinimumSize(480, 360);
+}
+
+GPSMapWidget::~GPSMapWidget()
+{
+ delete d;
+}
+
+void GPSMapWidget::setFileName(const QString& fileName)
+{
+ d->fileName = fileName;
+}
+
+QString GPSMapWidget::fileName()
+{
+ return d->fileName;
+}
+
+void GPSMapWidget::setGPSPosition(const QString& lat, const QString& lon)
+{
+ d->latitude = lat;
+ d->longitude = lon;
+}
+
+void GPSMapWidget::setMapType(const QString& mapType)
+{
+ d->mapType = mapType;
+}
+
+QString GPSMapWidget::mapType()
+{
+ return d->mapType;
+}
+
+void GPSMapWidget::setZoomLevel(int zoomLevel)
+{
+ d->zoomLevel = QString::number(zoomLevel);
+}
+
+int GPSMapWidget::GPSMapWidget::zoomLevel()
+{
+ return d->zoomLevel.toInt();
+}
+
+void GPSMapWidget::extractGPSPositionfromStatusbar(const QString& txt)
+{
+ QString status = txt;
+ status.remove(0, 5);
+ status.truncate(status.length()-1);
+ d->latitude = status.section(",", 0, 0);
+ d->longitude = status.section(",", 1, 1);
+ d->altitude = status.section(",", 2, 2);
+ d->longitude.remove(0, 5);
+ d->altitude.remove(0, 5);
+ emit signalNewGPSLocationFromMap(d->latitude, d->longitude, d->altitude);
+}
+
+void GPSMapWidget::khtmlMouseMoveEvent(khtml::MouseMoveEvent *e)
+{
+ QString status = jsStatusBarText();
+
+ // If a new point to the map have been moved, the Status
+ // string is like : "(lat:25.5894748, lon:47.6897455478, alt:211)"
+ if (status.startsWith(QString("(lat:")))
+ extractGPSPositionfromStatusbar(status);
+
+ KHTMLPart::khtmlMouseMoveEvent(e);
+}
+
+void GPSMapWidget::khtmlMouseReleaseEvent(khtml::MouseReleaseEvent *e)
+{
+ QString status = jsStatusBarText();
+
+ // If a new point to the map have been moved, the Status
+ // string is like : "(lat:25.5894748, lon:47.6897455478, alt:211)"
+ if (status.startsWith(QString("(lat:")))
+ extractGPSPositionfromStatusbar(status);
+
+ // If a new map zoom level have been selected, the Status
+ // string is like : "newZoomLevel:5"
+ if (status.startsWith(QString("newZoomLevel:")))
+ {
+ status.remove(0, 13);
+ d->zoomLevel = status;
+ }
+
+ // If a new map type have been selected, the Status
+ // string is like : "newMapType:G_SATELLITE_TYPE"
+ if (status.startsWith(QString("newMapType:")))
+ {
+ status.remove(0, 11);
+ d->mapType = status;
+ }
+
+ KHTMLPart::khtmlMouseReleaseEvent(e);
+}
+
+void GPSMapWidget::resized()
+{
+ QString url = d->gpsLocalorUrl;
+ url.append("?latitude=");
+ url.append(d->latitude);
+ url.append("&longitude=");
+ url.append(d->longitude);
+ url.append("&altitude=");
+ url.append(d->altitude);
+ url.append("&width=");
+ url.append(QString::number(view()->width()));
+ url.append("&height=");
+ url.append(QString::number(view()->height()));
+ url.append("&zoom=");
+ url.append(d->zoomLevel);
+ url.append("&maptype=");
+ url.append(d->mapType);
+ url.append("&filename=");
+ url.append(d->fileName);
+ openURL(KURL(url));
+ kdDebug( 51001 ) << url << endl;
+}
+
+} // namespace KIPIGPSSyncPlugin
diff --git a/kipi-plugins/gpssync/gpsmapwidget.h b/kipi-plugins/gpssync/gpsmapwidget.h
new file mode 100644
index 0000000..3ca2e52
--- /dev/null
+++ b/kipi-plugins/gpssync/gpsmapwidget.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-28
+ * Description : a widget to display a GPS web map locator.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2008 by Gerhard Kulzer <gerhard at kulzer dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPSMAPWIDGET_H
+#define GPSMAPWIDGET_H
+
+// Qt includes.
+
+#include <qstring.h>
+
+// KDE includes.
+
+#include <khtml_part.h>
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSMapWidgetPrivate;
+
+class GPSMapWidget : public KHTMLPart
+{
+ Q_OBJECT
+
+public:
+
+ GPSMapWidget(QWidget* parent);
+ ~GPSMapWidget();
+
+ void setGPSPosition(const QString& lat, const QString& lon);
+
+ void setZoomLevel(int zoomLevel);
+ int zoomLevel();
+
+ void setMapType(const QString& mapType);
+ QString mapType();
+
+ void setFileName(const QString& fileName);
+ QString fileName();
+
+ void resized();
+
+signals:
+
+ void signalNewGPSLocationFromMap(const QString&, const QString&, const QString&);
+
+protected:
+
+ void khtmlMouseMoveEvent(khtml::MouseMoveEvent*);
+ void khtmlMouseReleaseEvent(khtml::MouseReleaseEvent *);
+
+private:
+
+ void extractGPSPositionfromStatusbar(const QString& txt);
+
+private:
+
+ GPSMapWidgetPrivate *d;
+};
+
+} // namespace KIPIGPSSyncPlugin
+
+#endif /* GPSMAPWIDGET_H */
diff --git a/kipi-plugins/gpssync/gpssyncdialog.cpp b/kipi-plugins/gpssync/gpssyncdialog.cpp
new file mode 100644
index 0000000..eed7154
--- /dev/null
+++ b/kipi-plugins/gpssync/gpssyncdialog.cpp
@@ -0,0 +1,548 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a plugin to synchronize pictures with
+ * a GPS device.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qcombobox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qvgroupbox.h>
+#include <qgrid.h>
+#include <qpushbutton.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+
+// KDE includes.
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <ksqueezedtextlabel.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <klistview.h>
+#include <kfiledialog.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kglobalsettings.h>
+#include <knuminput.h>
+#include <kseparator.h>
+#include <kio/previewjob.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "gpslistviewitem.h"
+#include "gpsdataparser.h"
+#include "gpseditdialog.h"
+#include "gpssyncdialog.h"
+#include "gpssyncdialog.moc"
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSSyncDialogPriv
+{
+public:
+
+ GPSSyncDialogPriv()
+ {
+ listView = 0;
+ interface = 0;
+ maxGapInput = 0;
+ gpxFileName = 0;
+ gpxPointsLabel = 0;
+ timeZoneCB = 0;
+ interpolateBox = 0;
+ maxTimeInput = 0;
+ maxTimeLabel = 0;
+ about = 0;
+ }
+
+ QLabel *gpxPointsLabel;
+ QLabel *maxTimeLabel;
+
+ QComboBox *timeZoneCB;
+
+ QCheckBox *interpolateBox;
+
+ KListView *listView;
+
+ KIntSpinBox *maxGapInput;
+ KIntSpinBox *maxTimeInput;
+
+ KSqueezedTextLabel *gpxFileName;
+
+ KIPI::Interface *interface;
+
+ KIPIPlugins::KPAboutData *about;
+
+ GPSDataParser gpxParser;
+};
+
+GPSSyncDialog::GPSSyncDialog( KIPI::Interface* interface, QWidget* parent)
+ : KDialogBase(Plain, i18n("Geolocation"),
+ Help|User1|User2|User3|Apply|Close, Close,
+ parent, 0, true, false)
+{
+ d = new GPSSyncDialogPriv;
+ d->interface = interface;
+
+ setButtonText(User1, i18n("Correlate"));
+ setButtonText(User2, i18n("Edit..."));
+ setButtonText(User3, i18n("Remove"));
+
+ setButtonTip(User1, i18n("Correlate in time and interpolate distance of data from GPX file with all images on the list."));
+ setButtonTip(User2, i18n("Manually edit GPS coordinates of selected images from the list."));
+ setButtonTip(User3, i18n("Remove GPS coordinates of selected images from the list."));
+
+ enableButton(User1, false);
+ enableButton(User2, true);
+ enableButton(User3, true);
+
+ QGridLayout *mainLayout = new QGridLayout(plainPage(), 3, 1, 0, marginHint());
+
+ // --------------------------------------------------------------
+
+ d->listView = new KListView(plainPage());
+ d->listView->addColumn( i18n("Thumbnail") );
+ d->listView->addColumn( i18n("File Name") );
+ d->listView->addColumn( i18n("Camera time stamp") );
+ d->listView->addColumn( i18n("Latitude") );
+ d->listView->addColumn( i18n("Longitude") );
+ d->listView->addColumn( i18n("Altitude") );
+ d->listView->addColumn( i18n("Status") );
+ d->listView->setResizeMode(QListView::AllColumns);
+ d->listView->setAllColumnsShowFocus(true);
+ d->listView->setSorting(-1);
+ d->listView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ d->listView->setSelectionMode(QListView::Extended);
+ d->listView->setMinimumWidth(450);
+
+ // ---------------------------------------------------------------
+
+ QGroupBox *settingsBox = new QGroupBox(0, Qt::Vertical, i18n("Settings"), plainPage());
+ QGridLayout *settingsBoxLayout = new QGridLayout(settingsBox->layout(), 8, 1,
+ KDialog::spacingHint());
+
+ QPushButton *loadGPXButton = new QPushButton(i18n("Load GPX File..."), settingsBox);
+
+ QLabel *gpxFileLabel = new QLabel(i18n("Current GPX file:"), settingsBox);
+ d->gpxFileName = new KSqueezedTextLabel(i18n("No GPX file"), settingsBox);
+ d->gpxPointsLabel = new QLabel(settingsBox);
+ KSeparator *line = new KSeparator(Horizontal, settingsBox);
+
+ QLabel *maxGapLabel = new QLabel(i18n("Max. time gap (sec.):"), settingsBox);
+ d->maxGapInput = new KIntSpinBox(0, 1000000, 1, 30, 10, settingsBox);
+ QWhatsThis::add(d->maxGapInput, i18n("<p>Sets the maximum difference in "
+ "seconds from a GPS track point to the image time to be matched. "
+ "If the time difference exceeds this setting, no match will be attempted."));
+
+ QLabel *timeZoneLabel = new QLabel(i18n("Time zone:"), settingsBox);
+ d->timeZoneCB = new QComboBox( false, settingsBox );
+
+ // See list of time zomes over the world :
+ // http://en.wikipedia.org/wiki/List_of_time_zones
+ // NOTE: Combo box strings are not i18n.
+ d->timeZoneCB->insertItem("GMT-12:00");
+ d->timeZoneCB->insertItem("GMT-11:00");
+ d->timeZoneCB->insertItem("GMT-10:00");
+ d->timeZoneCB->insertItem("GMT-09:30");
+ d->timeZoneCB->insertItem("GMT-09:00");
+ d->timeZoneCB->insertItem("GMT-08:00");
+ d->timeZoneCB->insertItem("GMT-07:00");
+ d->timeZoneCB->insertItem("GMT-06:00");
+ d->timeZoneCB->insertItem("GMT-05:30");
+ d->timeZoneCB->insertItem("GMT-05:00");
+ d->timeZoneCB->insertItem("GMT-04:30");
+ d->timeZoneCB->insertItem("GMT-04:00");
+ d->timeZoneCB->insertItem("GMT-03:30");
+ d->timeZoneCB->insertItem("GMT-03:00");
+ d->timeZoneCB->insertItem("GMT-02:00");
+ d->timeZoneCB->insertItem("GMT-01:00");
+ d->timeZoneCB->insertItem("GMT+00:00");
+ d->timeZoneCB->insertItem("GMT+01:00");
+ d->timeZoneCB->insertItem("GMT+02:00");
+ d->timeZoneCB->insertItem("GMT+03:00");
+ d->timeZoneCB->insertItem("GMT+03:30");
+ d->timeZoneCB->insertItem("GMT+04:00");
+ d->timeZoneCB->insertItem("GMT+05:00");
+ d->timeZoneCB->insertItem("GMT+05:30"); // See B.K.O # 149491
+ d->timeZoneCB->insertItem("GMT+05:45");
+ d->timeZoneCB->insertItem("GMT+06:00");
+ d->timeZoneCB->insertItem("GMT+06:30");
+ d->timeZoneCB->insertItem("GMT+07:00");
+ d->timeZoneCB->insertItem("GMT+08:00");
+ d->timeZoneCB->insertItem("GMT+08:45");
+ d->timeZoneCB->insertItem("GMT+09:00");
+ d->timeZoneCB->insertItem("GMT+09:30");
+ d->timeZoneCB->insertItem("GMT+10:00");
+ d->timeZoneCB->insertItem("GMT+10:30");
+ d->timeZoneCB->insertItem("GMT+11:00");
+ d->timeZoneCB->insertItem("GMT+11:30");
+ d->timeZoneCB->insertItem("GMT+12:00");
+ d->timeZoneCB->insertItem("GMT+12:45");
+ d->timeZoneCB->insertItem("GMT+13:00");
+ d->timeZoneCB->insertItem("GMT+14:00");
+ QWhatsThis::add(d->timeZoneCB, i18n("<p>Sets the time zone the camera was set to "
+ "during photo shooting, so that the time stamps of the images "
+ "can be converted to GMT to match the GPS time reference.\n"
+ "Note: positive offsets count eastwards from zero longitude (GMT), "
+ "they are 'ahead of time'."));
+
+ d->interpolateBox = new QCheckBox(i18n("Interpolate"), settingsBox);
+ QWhatsThis::add(d->interpolateBox, i18n("<p>Set this option to interpolate GPS track points "
+ "which are not closely matched to the GPX data file."));
+
+ d->maxTimeLabel = new QLabel(i18n("Difference in min.:"), settingsBox);
+ d->maxTimeInput = new KIntSpinBox(0, 240, 1, 15, 10, settingsBox);
+ QWhatsThis::add(d->maxTimeInput, i18n("<p>Sets the maximum time difference in minutes (240 max.)"
+ " to interpolate GPX file points to image time data."));
+
+ settingsBoxLayout->addMultiCellWidget(loadGPXButton, 0, 0, 0, 1);
+ settingsBoxLayout->addMultiCellWidget(gpxFileLabel, 1, 1, 0, 1);
+ settingsBoxLayout->addMultiCellWidget(d->gpxFileName, 2, 2, 0, 1);
+ settingsBoxLayout->addMultiCellWidget(d->gpxPointsLabel, 3, 3, 0, 1);
+ settingsBoxLayout->addMultiCellWidget(line, 4, 4, 0, 1);
+ settingsBoxLayout->addMultiCellWidget(maxGapLabel, 5, 5, 0, 0);
+ settingsBoxLayout->addMultiCellWidget(d->maxGapInput, 5, 5, 1, 1);
+ settingsBoxLayout->addMultiCellWidget(timeZoneLabel, 6, 6, 0, 0);
+ settingsBoxLayout->addMultiCellWidget(d->timeZoneCB, 6, 6, 1, 1);
+ settingsBoxLayout->addMultiCellWidget(d->interpolateBox, 7, 7, 0, 1);
+ settingsBoxLayout->addMultiCellWidget(d->maxTimeLabel, 8, 8, 0, 0);
+ settingsBoxLayout->addMultiCellWidget(d->maxTimeInput, 8, 8, 1, 1);
+
+ // ---------------------------------------------------------------
+
+ mainLayout->addMultiCellWidget(d->listView, 0, 2, 0, 1);
+ mainLayout->addMultiCellWidget(settingsBox, 0, 1, 2, 2);
+ mainLayout->setColStretch(1, 10);
+ mainLayout->setRowStretch(2, 10);
+
+ // ---------------------------------------------------------------
+ // About data and help button.
+
+ d->about = new KIPIPlugins::KPAboutData(I18N_NOOP("GPS Sync"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A plugin to synchronize images' metadata with a GPS device"),
+ "(c) 2006-2008, Gilles Caulier");
+
+ d->about->addAuthor("Gilles Caulier", I18N_NOOP("Author and Maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, d->about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"),
+ this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // ---------------------------------------------------------------
+
+ connect(loadGPXButton, SIGNAL(released()),
+ this, SLOT(slotLoadGPXFile()));
+
+ connect(d->interpolateBox, SIGNAL(toggled(bool)),
+ d->maxTimeLabel, SLOT(setEnabled(bool)));
+
+ connect(d->interpolateBox, SIGNAL(toggled(bool)),
+ d->maxTimeInput, SLOT(setEnabled(bool)));
+
+ readSettings();
+}
+
+GPSSyncDialog::~GPSSyncDialog()
+{
+ delete d->about;
+ delete d;
+}
+
+void GPSSyncDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("gpssync", "kipi-plugins");
+}
+
+void GPSSyncDialog::setImages( const KURL::List& images )
+{
+ for( KURL::List::ConstIterator it = images.begin(); it != images.end(); ++it )
+ new GPSListViewItem(d->listView, d->listView->lastItem(), *it);
+
+ KIO::PreviewJob *thumbnailJob = KIO::filePreview(images, 64);
+
+ connect(thumbnailJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ this, SLOT(slotGotThumbnail(const KFileItem*, const QPixmap&)));
+}
+
+void GPSSyncDialog::slotLoadGPXFile()
+{
+ KURL loadGPXFile = KFileDialog::getOpenURL(KGlobalSettings::documentPath(),
+ i18n("%1|GPS Exchange Format").arg("*.gpx"), this,
+ i18n("Select GPX File to Load") );
+ if( loadGPXFile.isEmpty() )
+ return;
+
+ d->gpxParser.clear();
+ bool ret = d->gpxParser.loadGPXFile(loadGPXFile);
+
+ if (!ret)
+ {
+ KMessageBox::error(this, i18n("Cannot parse %1 GPX file!")
+ .arg(loadGPXFile.fileName()), i18n("GPS Sync"));
+ enableButton(User1, false);
+ return;
+ }
+
+ if (d->gpxParser.numPoints() <= 0)
+ {
+ KMessageBox::sorry(this, i18n("The %1 GPX file do not have a date-time track to use!")
+ .arg(loadGPXFile.fileName()), i18n("GPS Sync"));
+ enableButton(User1, false);
+ return;
+ }
+
+ d->gpxFileName->setText(loadGPXFile.fileName());
+ d->gpxPointsLabel->setText(i18n("Points parsed: %1").arg(d->gpxParser.numPoints()));
+ enableButton(User1, true);
+ slotUser1();
+}
+
+void GPSSyncDialog::closeEvent(QCloseEvent *e)
+{
+ if (!e) return;
+ if (!promptUserClose())
+ {
+ e->ignore();
+ return;
+ }
+
+ saveSettings();
+ e->accept();
+}
+
+void GPSSyncDialog::slotClose()
+{
+ if (!promptUserClose()) return;
+ saveSettings();
+ KDialogBase::slotClose();
+}
+
+bool GPSSyncDialog::promptUserClose()
+{
+ // Check if one item is dirty in the list.
+
+ QListViewItemIterator it( d->listView );
+ int dirty = 0;
+
+ while ( it.current() )
+ {
+ GPSListViewItem *item = (GPSListViewItem*) it.current();
+ if (item->isDirty())
+ dirty++;
+
+ ++it;
+ }
+
+ if (dirty > 0)
+ {
+ QString msg = i18n("1 image from the list is not updated.",
+ "%n images from the list are not updated.", dirty);
+
+ if (KMessageBox::No == KMessageBox::warningYesNo(this,
+ i18n("<p>%1\n"
+ "Do you really want to close this window without applying changes?</p>")
+ .arg(msg)))
+ return false;
+ }
+
+ return true;
+}
+
+void GPSSyncDialog::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("GPS Sync Settings");
+ d->maxGapInput->setValue(config.readNumEntry("Max Gap Time", 30));
+ d->timeZoneCB->setCurrentItem(config.readNumEntry("Time Zone", 16)); // GMT+00:00
+ d->interpolateBox->setChecked(config.readBoolEntry("Interpolate", false));
+ d->maxTimeInput->setValue(config.readNumEntry("Max Inter Dist Time", 15));
+
+ d->maxTimeLabel->setEnabled(d->interpolateBox->isChecked());
+ d->maxTimeInput->setEnabled(d->interpolateBox->isChecked());
+ resize(configDialogSize(config, QString("GPS Sync Dialog")));
+}
+
+void GPSSyncDialog::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("GPS Sync Settings");
+ config.writeEntry("Max Gap Time", d->maxGapInput->value() );
+ config.writeEntry("Time Zone", d->timeZoneCB->currentItem() );
+ config.writeEntry("Interpolate", d->interpolateBox->isChecked() );
+ config.writeEntry("Max Inter Dist Time", d->maxTimeInput->value() );
+ saveDialogSize(config, QString("GPS Sync Dialog"));
+ config.sync();
+}
+
+// Correlate the GPS positions from Pictures using a GPX file data.
+void GPSSyncDialog::slotUser1()
+{
+ int itemsUpdated = 0;
+
+ QListViewItemIterator it( d->listView );
+ while ( it.current() )
+ {
+ GPSListViewItem *item = dynamic_cast<GPSListViewItem*>(it.current());
+ GPSDataContainer gpsData;
+ QString tz = d->timeZoneCB->currentText();
+ int hh = QString(QString(tz[4])+QString(tz[5])).toInt();
+ int mm = QString(QString(tz[7])+QString(tz[8])).toInt();
+ int offset = hh*3600 + mm*60;
+
+ if (tz[3] == QChar('-'))
+ offset = (-1)*offset;
+
+ if (d->gpxParser.matchDate(item->dateTime(),
+ d->maxGapInput->value(),
+ offset,
+ d->interpolateBox->isChecked(),
+ d->maxTimeInput->value()*60,
+ gpsData))
+ {
+ item->setGPSInfo(gpsData);
+ itemsUpdated++;
+ }
+ ++it;
+ }
+
+ if (itemsUpdated == 0)
+ {
+ KMessageBox::sorry(this, i18n("Cannot find pictures to correlate with GPX file data."),
+ i18n("GPS Sync"));
+ return;
+ }
+
+ QString msg = i18n("GPS data of 1 image have been updated on the list using the GPX data file.",
+ "GPS data of %n images have been updated on the list using the GPX data file.",
+ itemsUpdated);
+ msg += '\n';
+ msg += i18n("Press Apply button to update images metadata.");
+
+ KMessageBox::information(this, msg, i18n("GPS Sync"));
+}
+
+// Start the GPS coordinates editor dialog.
+void GPSSyncDialog::slotUser2()
+{
+ if (!d->listView->currentItem())
+ {
+ KMessageBox::information(this, i18n("Please, select at least one image from "
+ "the list to edit GPS coordinates manually."), i18n("GPS Sync"));
+ return;
+ }
+
+ GPSListViewItem *item = dynamic_cast<GPSListViewItem*>(d->listView->currentItem());
+
+ GPSEditDialog dlg(this, item->GPSInfo(),
+ item->url().fileName(),
+ item->hasGPSInfo());
+
+ if (dlg.exec() == KDialogBase::Accepted)
+ {
+ QListViewItemIterator it(d->listView);
+
+ while (it.current())
+ {
+ if (it.current()->isSelected())
+ {
+ GPSListViewItem *selItem = dynamic_cast<GPSListViewItem*>(it.current());
+ selItem->setGPSInfo(dlg.getGPSInfo(), true, true);
+ }
+ ++it;
+ }
+ }
+}
+
+// Remove GPS coordinates from pictures.
+void GPSSyncDialog::slotUser3()
+{
+ if (!d->listView->currentItem())
+ {
+ KMessageBox::information(this, i18n("Please, select at least one image from "
+ "the list to remove GPS coordinates."), i18n("GPS Sync"));
+ return;
+ }
+
+ QListViewItemIterator it(d->listView);
+
+ while (it.current())
+ {
+ if (it.current()->isSelected())
+ {
+ GPSListViewItem *selItem = dynamic_cast<GPSListViewItem*>(it.current());
+ selItem->eraseGPSInfo();
+ }
+ ++it;
+ }
+}
+
+void GPSSyncDialog::slotApply()
+{
+ KURL::List images;
+
+ QListViewItemIterator it( d->listView );
+ while ( it.current() )
+ {
+ GPSListViewItem *selItem = dynamic_cast<GPSListViewItem*>(it.current());
+ d->listView->setSelected(selItem, true);
+ d->listView->ensureItemVisible(selItem);
+ selItem->writeGPSInfoToFile();
+ images.append(selItem->url());
+ ++it;
+ kapp->processEvents();
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-readed.
+
+ d->interface->refreshImages(images);
+}
+
+void GPSSyncDialog::slotGotThumbnail(const KFileItem *item, const QPixmap& pix)
+{
+ QListViewItemIterator it(d->listView);
+
+ while (it.current())
+ {
+ GPSListViewItem *selItem = dynamic_cast<GPSListViewItem*>(it.current());
+ if (selItem->url() == item->url())
+ {
+ selItem->setPixmap(0, pix);
+ }
+ ++it;
+ }
+}
+
+} // NameSpace KIPIGPSSyncPlugin
diff --git a/kipi-plugins/gpssync/gpssyncdialog.h b/kipi-plugins/gpssync/gpssyncdialog.h
new file mode 100644
index 0000000..053e97a
--- /dev/null
+++ b/kipi-plugins/gpssync/gpssyncdialog.h
@@ -0,0 +1,87 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a plugin to synchronize pictures with
+ * a GPS device.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPSSYNCDIALOG_H
+#define GPSSYNCDIALOG_H
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <kurl.h>
+
+// LibKipi includes.
+
+#include <libkipi/interface.h>
+
+class QListViewItem;
+
+class KFileItem;
+
+namespace KIPIGPSSyncPlugin
+{
+
+class GPSSyncDialogPriv;
+
+class GPSSyncDialog :public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ GPSSyncDialog(KIPI::Interface* interface, QWidget* parent);
+ ~GPSSyncDialog();
+
+ void setImages(const KURL::List& images);
+
+protected:
+
+ void closeEvent(QCloseEvent *);
+
+protected slots:
+
+ void slotApply();
+ void slotHelp();
+ void slotClose();
+ void slotUser1();
+ void slotUser2();
+ void slotUser3();
+
+private slots:
+
+ void slotGotThumbnail(const KFileItem*, const QPixmap&);
+ void slotLoadGPXFile();
+
+private:
+
+ bool promptUserClose();
+ void readSettings();
+ void saveSettings();
+
+private:
+
+ GPSSyncDialogPriv *d;
+};
+
+} // NameSpace KIPIGPSSyncPlugin
+
+#endif /* GPSSYNCDIALOG_H */
diff --git a/kipi-plugins/gpssync/hi16-action-gpsimagetag.png b/kipi-plugins/gpssync/hi16-action-gpsimagetag.png
new file mode 100644
index 0000000..2d11450
--- /dev/null
+++ b/kipi-plugins/gpssync/hi16-action-gpsimagetag.png
Binary files differ
diff --git a/kipi-plugins/gpssync/hi32-action-gpsimagetag.png b/kipi-plugins/gpssync/hi32-action-gpsimagetag.png
new file mode 100644
index 0000000..64da47f
--- /dev/null
+++ b/kipi-plugins/gpssync/hi32-action-gpsimagetag.png
Binary files differ
diff --git a/kipi-plugins/gpssync/kipiplugin_gpssync.desktop b/kipi-plugins/gpssync/kipiplugin_gpssync.desktop
new file mode 100644
index 0000000..77cab68
--- /dev/null
+++ b/kipi-plugins/gpssync/kipiplugin_gpssync.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Comment=KIPI plugin to Geolocalize pictures
+Comment[ca]=Connector del KIPI per a geolocalitzar fotografies
+Comment[da]=KIPI-plugin til at lokalisere billeder geografisk
+Comment[de]=Ein KIPI-Modul zur geographischen Zuordnung von Bildern
+Comment[el]=Πρόσθετο του KIPI για γεωτοποθέτηση εικόνων
+Comment[es]=Complemento de KIPI para geolocalizar imágenes
+Comment[et]=KIPI piltide geolokatsiooni plugin
+Comment[fr]=Module externe KIPI pour géolocaliser les images
+Comment[is]=KIPI íforrit til að GPS-staðsetja myndir
+Comment[it]=Plugin di KIPI per geolocalizzare le immagini
+Comment[ja]=Kipi ジオロケーションプラグイン
+Comment[nds]=KIPI-Moduul för Standöörd vun Biller
+Comment[nl]=KIPI-plugin voor het geolokaliseren van afbeeldingen
+Comment[pa]=ਭੂ-ਚਿੱਤਰਾਂ ਲਈ KIPI ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Geolokalizacja zdjęć
+Comment[pt]='Plugin' do KIPI para localizar geograficamente as imagens
+Comment[pt_BR]=Plugin para Geolocalização de Figuras do KIPI
+Comment[sr]=KIPI прикључак за гео-локализацију слика
+Comment[sr@Latn]=KIPI priključak za geo-lokalizaciju slika
+Comment[sv]=KIPI-insticksprogram för att lokalisera bilder geografiskt
+Comment[xx]=xxKIPI plugin to Geolocalize picturesxx
+Comment[zh_CN]=KIPI 地理化图片插件
+Encoding=UTF-8
+Icon=
+Name=GPSSync
+Name[ca]=Sincronització GPS
+Name[da]=GPS-synkronisering
+Name[de]=GPS-Abgleich
+Name[el]=Συγχρονισμός GPS
+Name[fi]=GPS-synkronointi
+Name[pt]=Sincronização GPS
+Name[sv]=GPS-synkronisering
+Name[xx]=xxGPSSyncxx
+Name[zh_CN]=GPS 同步
+ServiceTypes=KIPI/Plugin
+Type=Service
+X-KDE-Library=kipiplugin_gpssync
+X-KIPI-ReqFeatures=ImagesHasTime
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/kipi-plugins/gpssync/kmlexport.cpp b/kipi-plugins/gpssync/kmlexport.cpp
new file mode 100644
index 0000000..5262140
--- /dev/null
+++ b/kipi-plugins/gpssync/kmlexport.cpp
@@ -0,0 +1,523 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a tool to export GPS data to KML file.
+ *
+ * Copyright (C) 2006-2007 by Stephane Pontier <shadow dot walker at free dot fr>
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// Qt includes.
+
+#include <qpainter.h>
+#include <qregexp.h>
+
+// KDE includes.
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kio/job.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+
+// Libkexiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// LibKipi includes
+
+#include <libkipi/plugin.h>
+#include <libkipi/batchprogressdialog.h>
+#include <libkipi/imageinfo.h>
+
+// Local includes.
+
+#include "kmlexport.h"
+
+namespace KIPIGPSSyncPlugin
+{
+
+kmlExport::kmlExport(KIPI::Interface* interface)
+{
+ m_interface = interface;
+ QWidget* parent = KApplication::kApplication()->mainWidget();
+ m_progressDialog = new KIPI::BatchProgressDialog(parent, i18n("Generating KML file..."));
+}
+
+kmlExport::~kmlExport()
+{
+ delete m_progressDialog;
+}
+
+/*!
+ \fn kmlExport::createDir(QDir dir)
+ */
+bool kmlExport::createDir(QDir dir)
+{
+ if (dir.exists()) return true;
+
+ QDir parent = dir;
+ parent.cdUp();
+ bool ok = createDir(parent);
+ if (!ok)
+ {
+ logError(i18n("Could not create '%1").arg(parent.path()));
+ return false;
+ }
+ return parent.mkdir(dir.dirName());
+}
+
+/*!
+\fn kmlExport::webifyFileName(const QString &fileName)
+ */
+QString kmlExport::webifyFileName(const QString &fileName)
+{
+ QString webFileName=fileName.lower();
+
+ // Remove potentially troublesome chars
+ webFileName=webFileName.replace(QRegExp("[^-0-9a-z]+"), "_");
+
+ return webFileName;
+}
+
+/*!
+ \fn kmlExport::generateSquareThumbnail(const QImage& fullImage, int size)
+ */
+QImage kmlExport::generateSquareThumbnail(const QImage& fullImage, int size)
+{
+ QImage image = fullImage.smoothScale(size, size, QImage::ScaleMax);
+
+ if (image.width() == size && image.height() == size)
+ {
+ return image;
+ }
+ QPixmap croppedPix(size, size);
+ QPainter painter(&croppedPix);
+
+ int sx=0, sy=0;
+ if (image.width()>size)
+ {
+ sx=(image.width() - size)/2;
+ }
+ else
+ {
+ sy=(image.height() - size)/2;
+ }
+ painter.drawImage(0, 0, image, sx, sy, size, size);
+ painter.end();
+
+ return croppedPix.convertToImage();
+}
+
+/*!
+ \fn kmlExport::generateBorderedThumbnail(const QImage& fullImage, int size)
+ */
+QImage kmlExport::generateBorderedThumbnail(const QImage& fullImage, int size)
+{
+ int image_border = 3;
+
+ // getting an image minus the border
+ QImage image = fullImage.smoothScale(size -(2*image_border), size - (2*image_border), QImage::ScaleMax);
+
+ QPixmap croppedPix(image.width() + (2*image_border), image.height() + (2*image_border));
+ QPainter painter(&croppedPix);
+
+ QColor BrushColor(255,255,255);
+ painter.fillRect(0,0,image.width() + (2*image_border),image.height() + (2*image_border),BrushColor);
+ /*! @todo add a corner to the thumbnail and a hotspot to the kml element */
+
+ painter.drawImage(image_border, image_border, image );
+ painter.end();
+
+ return croppedPix.convertToImage();
+}
+
+/*!
+\fn kmlExport::generateImagesthumb(KIPI::Interface* interface, const KURL& imageURL, QDomElement &kmlAlbum )
+ */
+void kmlExport::generateImagesthumb(KIPI::Interface* interface, const KURL& imageURL, QDomElement &kmlAlbum )
+{
+ KIPI::Interface* mInterface = interface;
+ KIPI::ImageInfo info = mInterface->info(imageURL);
+
+ // Load image
+ QString path = imageURL.path();
+ QFile imageFile(path);
+ if (!imageFile.open(IO_ReadOnly))
+ {
+ logWarning(i18n("Could not read image '%1'").arg(path));
+ return;
+ }
+
+ QString imageFormat = QImageIO::imageFormat(&imageFile);
+ if (imageFormat.isEmpty())
+ {
+ logWarning(i18n("Format of image '%1' is unknown").arg(path));
+ return;
+ }
+ imageFile.close();
+ imageFile.open(IO_ReadOnly);
+
+ QByteArray imageData = imageFile.readAll();
+ QImage image;
+ if (!image.loadFromData(imageData) )
+ {
+ logWarning(i18n("Error loading image '%1'").arg(path));
+ return;
+ }
+
+ // Process images
+ /** FIXME depending the soft used, angle could return a good value (digikam) or a value of 0 (gwenview)
+ * and, in some case the picture is not rotated as it should be.
+ */
+ if ( info.angle() != 0 )
+ {
+ QWMatrix matrix;
+ matrix.rotate( info.angle() );
+ image = image.xForm( matrix );
+ }
+ image = image.smoothScale(m_size, m_size, QImage::ScaleMax);
+
+ QImage icon;
+ if (m_optimize_googlemap)
+ {
+ icon = generateSquareThumbnail(image,m_googlemapSize);
+ }
+ else
+ {
+ // icon = image.smoothScale(m_iconSize, m_iconSize, QImage::ScaleMax);
+ icon = generateBorderedThumbnail(image, m_iconSize);
+ }
+
+ // Save images
+ /** @todo remove the extension of the file
+ * it's appear with digikam but not with gwenview
+ * which already seems to strip the extension
+ */
+ QString baseFileName = webifyFileName(info.title());
+ // baseFileName = mUniqueNameHelper.makeNameUnique(baseFileName);
+ QString fullFileName;
+ fullFileName = baseFileName + '.' + imageFormat.lower();
+ QString destPath = m_tempDestDir + m_imageDir + fullFileName;
+ if (!image.save(destPath, imageFormat.ascii(), 85))
+ {
+ // if not able to save the image, it's pointless to create a placemark
+ logWarning(i18n("Could not save image '%1' to '%2'").arg(path).arg(destPath));
+ }
+ else
+ {
+ //logInfo(i18n("Creation of picture '%1'").arg(fullFileName));
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.load(imageURL.path());
+ double alt, lat, lng;
+ exiv2Iface.getGPSInfo(alt, lat, lng);
+ QDomElement kmlPlacemark = addKmlElement(kmlAlbum, "Placemark");
+ addKmlTextElement(kmlPlacemark,"name",fullFileName);
+ // location and altitude
+ QDomElement kmlGeometry = addKmlElement(kmlPlacemark, "Point");
+
+ if (alt)
+ {
+ addKmlTextElement(kmlGeometry, "coordinates", QString("%1,%2,%3").arg(lng).arg(lat).arg(alt));
+ }
+ else
+ {
+ addKmlTextElement(kmlGeometry, "coordinates", QString("%1,%2").arg(lng).arg(lat));
+ }
+
+ if (m_altitudeMode == 2 )
+ {
+ addKmlTextElement(kmlGeometry, "altitudeMode", "absolute");
+ }
+ else if (m_altitudeMode == 1 )
+ {
+ addKmlTextElement(kmlGeometry, "altitudeMode", "relativeToGround");
+ }
+ else
+ {
+ addKmlTextElement(kmlGeometry, "altitudeMode", "clampToGround");
+ }
+ addKmlTextElement(kmlGeometry, "extrude", "1");
+
+ // we try to load exif value if any otherwise, try the application db
+ /** we need to take the DateTimeOriginal
+ * if we refer to http://www.exif.org/Exif2-2.PDF
+ * (standard)DateTime: is The date and time of image creation. In this standard it is the date and time the file was changed
+ * DateTimeOriginal: The date and time when the original image data was generated.
+ * For a DSC the date and time the picture was taken are recorded.
+ * DateTimeDigitized: The date and time when the image was stored as digital data.
+ * So for:
+ * - a DSC: the right time is the DateTimeDigitized which is also DateTimeOriginal
+ * if the picture has been modified the (standard)DateTime should change.
+ * - a scanned picture, the right time is the DateTimeOriginal which should also be the the DateTime
+ * the (standard)DateTime should be the same except if the picture is modified
+ * - a panorama created from several pictures, the right time is the DateTimeOriginal (average of DateTimeOriginal actually)
+ * The (standard)DateTime is the creation date of the panorama.
+ * it's seems the time to take into acccount is the DateTimeOriginal.
+ * but the exiv2Iface.getImageDateTime() return the (standard)DateTime first
+ * libkexiv2 seems to take Original dateTime first so it shoul be alright now.
+ */
+ QDateTime datetime = exiv2Iface.getImageDateTime();
+ if (datetime.isValid())
+ {
+ QDomElement kmlTimeStamp = addKmlElement(kmlPlacemark, "TimeStamp");
+ addKmlTextElement(kmlTimeStamp, "when", datetime.toString("yyyy-MM-ddThh:mm:ssZ"));
+ }
+ else if ( mInterface->hasFeature(KIPI::ImagesHasTime))
+ {
+ QDomElement kmlTimeStamp = addKmlElement(kmlGeometry, "TimeStamp");
+ addKmlTextElement(kmlTimeStamp, "when", (info.time()).toString("yyyy-MM-ddThh:mm:ssZ"));
+ }
+ QString my_description;
+ if (m_optimize_googlemap)
+ {
+ my_description = "<img src=\"" + m_UrlDestDir + m_imageDir + fullFileName + "\">";
+ }
+ else
+ {
+ my_description = "<img src=\"" + m_imageDir + fullFileName + "\">";
+ }
+ if ( m_interface->hasFeature( KIPI::ImagesHasComments ) )
+ {
+ my_description += "<br/>" + info.description() ;
+ }
+ addKmlTextElement(kmlPlacemark, "description", my_description);
+ logInfo(i18n("Creation of placemark '%1'").arg(fullFileName));
+
+ // Save icon
+ QString iconFileName = "thumb_" + baseFileName + '.' + imageFormat.lower();
+ QString destPath = m_tempDestDir + m_imageDir + iconFileName;
+ if (!icon.save(destPath, imageFormat.ascii(), 85))
+ {
+ logWarning(i18n("Could not save icon for image '%1' to '%2'").arg(path).arg(destPath));
+ }
+ else
+ {
+ //logInfo(i18n("Creation of icon '%1'").arg(iconFileName));
+ // style et icon
+ QDomElement kmlStyle = addKmlElement(kmlPlacemark, "Style");
+ QDomElement kmlIconStyle = addKmlElement(kmlStyle, "IconStyle");
+ QDomElement kmlIcon = addKmlElement(kmlIconStyle, "Icon");
+ if (m_optimize_googlemap)
+ {
+ addKmlTextElement(kmlIcon, "href", m_UrlDestDir + m_imageDir + iconFileName);
+ }
+ else
+ {
+ addKmlTextElement(kmlIcon, "href", m_imageDir + iconFileName);
+ }
+ QDomElement kmlBallonStyle = addKmlElement(kmlStyle, "BalloonStyle");
+ addKmlTextElement(kmlBallonStyle, "text", "$[description]");
+ }
+ }
+}
+
+/*!
+\fn kmlExport::addTrack(QDomElement &kmlAlbum)
+ */
+void kmlExport::addTrack(QDomElement &kmlAlbum)
+{
+ if( m_GPXFile.isEmpty() )
+ {
+ logWarning(i18n("No GPX file Chosen!"));
+ return;
+ }
+
+ m_gpxParser.clear();
+ bool ret = m_gpxParser.loadGPXFile(m_GPXFile);
+
+ if (!ret)
+ {
+ logError(i18n("Cannot parse %1 GPX file!").arg(m_GPXFile));
+ return;
+ }
+
+ if (m_gpxParser.numPoints() <= 0)
+ {
+ logError(i18n("The %1 GPX file do not have a date-time track to use!")
+ .arg(m_GPXFile));
+ return;
+ }
+
+ // create a folder that will contain tracks and points
+ QDomElement kmlFolder = addKmlElement(kmlAlbum, "Folder");
+ addKmlTextElement(kmlFolder, "name", i18n("Tracks"));
+
+ if (!m_optimize_googlemap)
+ {
+ // style of points and track
+ QDomElement kmlTrackStyle = addKmlElement(kmlAlbum, "Style");
+ kmlTrackStyle.setAttribute("id","track");
+ QDomElement kmlIconStyle = addKmlElement(kmlTrackStyle, "IconStyle");
+ QDomElement kmlIcon = addKmlElement(kmlIconStyle, "Icon");
+ //! FIXME is there a way to be sure of the location of the icon?
+ addKmlTextElement(kmlIcon, "href", "http://maps.google.com/mapfiles/kml/pal4/icon60.png");
+
+ m_gpxParser.CreateTrackPoints(kmlFolder, *kmlDocument, m_TimeZone - 12, m_GPXAltitudeMode);
+ }
+
+ // linetrack style
+ QDomElement kmlLineTrackStyle = addKmlElement(kmlAlbum, "Style");
+ kmlLineTrackStyle.setAttribute("id","linetrack");
+ QDomElement kmlLineStyle = addKmlElement(kmlLineTrackStyle, "LineStyle");
+ // the KML color is not #RRGGBB but AABBGGRR
+ QString KMLColorValue = QString("%1%2%3%4")
+ .arg((int)m_GPXOpacity*256/100, 2, 16)
+ .arg((&m_GPXColor)->blue(), 2, 16)
+ .arg((&m_GPXColor)->green(), 2, 16)
+ .arg((&m_GPXColor)->red(), 2, 16);
+ addKmlTextElement(kmlLineStyle, "color", KMLColorValue);
+ addKmlTextElement(kmlLineStyle, "width", QString("%1").arg(m_LineWidth) );
+
+ m_gpxParser.CreateTrackLine(kmlAlbum, *kmlDocument, m_GPXAltitudeMode);
+}
+
+/*!
+ \fn kmlExport::generate()
+ */
+void kmlExport::generate()
+{
+ //! @todo perform a test here before to continue.
+ createDir(m_tempDestDir + m_imageDir);
+
+ m_progressDialog->show();
+ KIPI::ImageCollection selection = m_interface->currentSelection();
+ KIPI::ImageCollection album = m_interface->currentAlbum();
+ // create the document, and it's root
+ kmlDocument = new QDomDocument("");
+ QDomImplementation impl;
+ QDomProcessingInstruction instr = kmlDocument->createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
+ kmlDocument->appendChild(instr);
+ QDomElement kmlRoot = kmlDocument->createElementNS( "http://earth.google.com/kml/2.1","kml");
+ kmlDocument->appendChild( kmlRoot );
+
+ QDomElement kmlAlbum = addKmlElement( kmlRoot, "Document");
+ QDomElement kmlName= addKmlTextElement( kmlAlbum, "name", album.name());
+ QDomElement kmlDescription = addKmlHtmlElement( kmlAlbum, "description", "Created with kmlexport <a href=\"http://www.kipi-plugins.org/\">kipi-plugin</a>");
+
+ if (m_GPXtracks)
+ {
+ addTrack(kmlAlbum);
+ }
+
+ KURL::List images = selection.images();
+ int defectImage = 0;
+ int pos = 1;
+ int count = images.count();
+ KURL::List::ConstIterator imagesEnd (images.constEnd());
+ for( KURL::List::ConstIterator selIt = images.constBegin(); selIt != imagesEnd; ++selIt, ++pos)
+ {
+ KExiv2Iface::KExiv2 exiv2Iface;
+ KIPI::ImageInfo info = m_interface->info( *selIt );
+ // exiv2 load from url not image
+ KURL url = *selIt;
+ exiv2Iface.load(url.path());
+ double alt, lat, lng;
+ bool hasGPSInfo = exiv2Iface.getGPSInfo(alt, lat, lng);
+ if ( hasGPSInfo )
+ {
+ // generation de l'image et de l'icone
+ generateImagesthumb(m_interface,url,kmlAlbum);
+ }
+ else
+ {
+ logWarning(i18n("No position data for '%1'").arg(info.title()));
+ defectImage++;
+ }
+ m_progressDialog->setProgress(pos, count);
+ qApp->processEvents();
+ }
+
+ if (defectImage)
+ {
+ /** @todo if defectImage==count there are no pictures exported, does it worst to continue? */
+ QWidget* parent = KApplication::kApplication()->mainWidget();
+ KMessageBox::information(parent, i18n("No position data for 1 picture",
+ "No position data for %n pictures", defectImage));
+ }
+
+ /** @todo change to kml or kmz if compressed */
+ QFile file( m_tempDestDir + m_KMLFileName + ".kml");
+ /** @todo handle file opening problems */
+ file.open( IO_WriteOnly );
+ QTextStream stream( &file ); // we will serialize the data into the file
+ stream << kmlDocument->toString();
+ file.close();
+
+ delete kmlDocument;
+
+ KIO::moveAs(m_tempDestDir,m_baseDestDir,false);
+ logInfo(i18n("Move to final directory"));
+ m_progressDialog->close();
+}
+
+/*!
+ \fn kmlExport::getConfig()
+ */
+int kmlExport::getConfig()
+{
+ KConfig config("kipirc");
+ config.setGroup("KMLExport Settings");
+
+ m_localTarget = config.readBoolEntry("localTarget");
+ m_optimize_googlemap = config.readBoolEntry("optimize_googlemap");
+ m_iconSize = config.readNumEntry("iconSize");
+ // googlemapSize = config.readNumEntry("googlemapSize");
+ m_size = config.readNumEntry("size");
+
+ // UrlDestDir have to have the trailing
+ m_baseDestDir = config.readEntry("baseDestDir");
+ m_UrlDestDir = config.readEntry("UrlDestDir");
+ m_altitudeMode = config.readNumEntry("Altitude Mode", 0);
+ m_KMLFileName = config.readEntry("KMLFileName");
+ m_GPXtracks = config.readBoolEntry("UseGPXTracks");
+ m_GPXFile = config.readEntry("GPXFile");
+ m_TimeZone = config.readNumEntry("Time Zone", 12);
+ m_LineWidth = config.readNumEntry("Line Width", 4);
+ m_GPXColor = config.readEntry("Track Color", "#17eeee" );
+ m_GPXOpacity = config.readNumEntry("Track Opacity", 64 );
+ m_GPXAltitudeMode = config.readNumEntry("GPX Altitude Mode", 0);
+
+ KStandardDirs dir;
+ m_tempDestDir = dir.saveLocation("tmp", "kipi-kmlrexportplugin-" + QString::number(getpid()) + '/');
+ m_imageDir = "images/";
+ m_googlemapSize = 32;
+ return 1;
+}
+
+void kmlExport::logInfo(const QString& msg)
+{
+ m_progressDialog->addedAction(msg, KIPI::ProgressMessage);
+}
+
+void kmlExport::logError(const QString& msg)
+{
+ m_progressDialog->addedAction(msg, KIPI::ErrorMessage);
+}
+
+void kmlExport::logWarning(const QString& msg)
+{
+ m_progressDialog->addedAction(msg, KIPI::WarningMessage);
+ // mWarnings=true;
+}
+
+} //namespace KIPIGPSSyncPlugin
diff --git a/kipi-plugins/gpssync/kmlexport.h b/kipi-plugins/gpssync/kmlexport.h
new file mode 100644
index 0000000..0dc32f2
--- /dev/null
+++ b/kipi-plugins/gpssync/kmlexport.h
@@ -0,0 +1,195 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a tool to export GPS data to KML file.
+ *
+ * Copyright (C) 2006-2007 by Stephane Pontier <shadow dot walker at free dot fr>
+ *
+ * This program is free software; you can redistribute 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 KIPIKMLEXPORTKMLEXPORT_H
+#define KIPIKMLEXPORTKMLEXPORT_H
+
+// Qt includes.
+
+#include <qcolor.h>
+#include <qdir.h>
+#include <qdom.h>
+
+// Local includes.
+
+#include "kmlgpsdataparser.h"
+
+class QImage;
+
+namespace KIPI
+{
+ class BatchProgressDialog;
+ class Interface;
+}
+
+namespace KIPIGPSSyncPlugin
+{
+
+/**
+Exporter to KML
+
+ @author KIPI dev. team
+*/
+class kmlExport
+{
+
+public:
+
+ kmlExport(KIPI::Interface* interface);
+ ~kmlExport();
+
+ bool createDir(QDir dir);
+
+ /*! generate the kml element for pictures with tumbnails
+ * @param interface the kipi interface
+ * @param KURL the URL of the picture
+ * @param kmlAlbum the album used
+ */
+ void generateImagesthumb(KIPI::Interface* interface, const KURL&, QDomElement &kmlAlbum);
+
+ /*! Produce a web-friendly file name
+ * otherwise, while google earth works fine, maps.google.com may not find pictures and thumbnail
+ * thank htmlexport
+ * @param the filename
+ * @return the webifyed filename
+ */
+ QString webifyFileName(const QString &fileName);
+
+ /*! Generate a square thumbnail from @fullImage of @size x @size pixels
+ * @param fullImage the original image
+ * @param size the size of the thumbnail
+ * @return the thumbnail
+ */
+ QImage generateSquareThumbnail(const QImage& fullImage, int size);
+
+ /*! Generate a square thumbnail from @fullImage of @size x @size pixels
+ * with a white border
+ * @param fullImage the original image
+ * @param size the size of the thumbnail
+ * @return the thumbnail
+ */
+ QImage generateBorderedThumbnail(const QImage& fullImage, int size);
+ void addTrack(QDomElement &kmlAlbum);
+ void generate();
+ int getConfig();
+
+public:
+
+ bool m_localTarget;
+ bool m_optimize_googlemap;
+ bool m_GPXtracks;
+
+ int m_iconSize;
+ int m_googlemapSize;
+ int m_size;
+ int m_altitudeMode;
+ int m_TimeZone;
+ int m_LineWidth;
+ int m_GPXOpacity;
+ int m_GPXAltitudeMode;
+
+ /** directory used in kmldocument structure */
+ QString m_imageDir;
+ QString m_GPXFile;
+ QString m_UrlDestDir;
+
+ /** temporary directory where everything will be created */
+ QString m_tempDestDir;
+
+ /** directory selected by user*/
+ QString m_baseDestDir;
+
+ QString m_imgdir;
+ QString m_KMLFileName;
+
+ QColor m_GPXColor;
+
+ KIPI::Interface *m_interface;
+
+private:
+
+ /*! the root document, used to create all QDomElements */
+ QDomDocument *kmlDocument;
+
+ /*! the GPS parsed data */
+ KMLGPSDataParser m_gpxParser;
+
+ KIPI::BatchProgressDialog *m_progressDialog;
+
+private:
+
+ void logInfo(const QString& msg);
+ void logError(const QString& msg);
+ void logWarning(const QString& msg);
+
+ /*!
+ * \fn KIPIKMLExport::kmlExport::addKmlElement(QDomElement target, QString tag)
+ * Add a new element
+ * @param target the parent element to which add the element
+ * @param tag the new element name
+ * @return the New element
+ */
+ QDomElement addKmlElement(QDomElement &target, QString tag)
+ {
+ QDomElement kmlElement = kmlDocument->createElement( tag );
+ target.appendChild( kmlElement );
+ return kmlElement;
+ }
+
+ /*!
+ * \fn KIPIKMLExport::kmlExport::addKmlTextElement(QDomElement target, QString tag, QString text)
+ * Add a new element with a text
+ * @param target the parent element to which add the element
+ * @param tag the new element name
+ * @param text the text content of the new element
+ * @return the New element
+ */
+ QDomElement addKmlTextElement(QDomElement &target, QString tag, QString text)
+ {
+ QDomElement kmlElement = kmlDocument->createElement( tag );
+ target.appendChild( kmlElement );
+ QDomText kmlTextElement = kmlDocument->createTextNode( text );
+ kmlElement.appendChild( kmlTextElement );
+ return kmlElement;
+ }
+
+ /*!
+ * \fn KIPIKMLExport::kmlExport::addKmlHtmlElement(QDomElement target, QString tag, QString text)
+ * Add a new element with html content (html entities are escaped and text is wrapped in a CDATA section)
+ * @param target the parent element to which add the element
+ * @param tag the new element name
+ * @param text the HTML content of the new element
+ * @return the New element
+ */
+ QDomElement addKmlHtmlElement(QDomElement &target, QString tag, QString text)
+ {
+ QDomElement kmlElement = kmlDocument->createElement( tag );
+ target.appendChild( kmlElement );
+ QDomText kmlTextElement = kmlDocument->createCDATASection( text );
+ kmlElement.appendChild( kmlTextElement );
+ return kmlElement;
+ }
+};
+
+} // namespace KIPIGPSSyncPlugin
+
+#endif // KIPIKMLEXPORTKMLEXPORT_H
diff --git a/kipi-plugins/gpssync/kmlexportconfig.cpp b/kipi-plugins/gpssync/kmlexportconfig.cpp
new file mode 100644
index 0000000..7e991ef
--- /dev/null
+++ b/kipi-plugins/gpssync/kmlexportconfig.cpp
@@ -0,0 +1,479 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a tool to export GPS data to KML file.
+ *
+ * Copyright (C) 2006-2007 by Stephane Pontier <shadow dot walker at free dot fr>
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+// KDE includes.
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kcolorbutton.h>
+#include <kdialog.h>
+#include <khelpmenu.h>
+#include <klocale.h>
+#include <klineedit.h>
+#include <knuminput.h>
+#include "kpaboutdata.h"
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kurlrequester.h>
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "kmlexportconfig.h"
+#include "kmlexportconfig.moc"
+
+namespace KIPIGPSSyncPlugin
+{
+
+/*
+ * Constructs a KIPIKMLExport::KMLExportConfig which is a child of 'parent', with the
+ * name 'name'.'
+ */
+KMLExportConfig::KMLExportConfig( QWidget* parent, const char* name)
+ : KDialogBase(Plain, i18n("KML Export"),
+ Help|Ok|Cancel, Ok,
+ parent, 0, true, false)
+{
+ if ( !name ) setName( "KMLExportConfig" );
+ setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0,
+ (QSizePolicy::SizeType)0, 0, 0, sizePolicy().hasHeightForWidth() ) );
+ KMLExportConfigLayout = new QGridLayout ( plainPage(), 1, 3, 0, spacingHint());
+
+ // --------------------------------------------------------------
+ // Target preferences
+ TargetPreferenceGroupBox = new QGroupBox(0, Qt::Vertical, i18n( "Target Preferences" ), plainPage());
+ TargetPreferenceGroupBoxLayout = new QGridLayout( TargetPreferenceGroupBox->layout(), 6, 5, KDialog::spacingHint());
+ TargetPreferenceGroupBoxLayout->setAlignment( Qt::AlignTop );
+
+ // target type
+ buttonGroupTargetType = new QButtonGroup(0, Qt::Vertical, i18n( "Target Type" ), TargetPreferenceGroupBox, "buttonGroupTargetType" );
+ buttonGroupTargetTypeLayout = new QGridLayout( buttonGroupTargetType->layout(), 2, 1, KDialog::spacingHint() );
+ buttonGroupTargetTypeLayout->setAlignment( Qt::AlignTop );
+
+ LocalTargetRadioButton_ = new QRadioButton( i18n( "&Local or web target used by GoogleEarth" ),
+ buttonGroupTargetType, "LocalTargetRadioButton_" );
+ LocalTargetRadioButton_->setChecked( true );
+ buttonGroupTargetTypeLayout->addWidget( LocalTargetRadioButton_, 0, 0 );
+
+ GoogleMapTargetRadioButton_ = new QRadioButton( i18n( "Web target used by GoogleMap" ),
+ buttonGroupTargetType, "GoogleMapTargetRadioButton_" );
+ buttonGroupTargetTypeLayout->addWidget( GoogleMapTargetRadioButton_, 1, 0 );
+ QToolTip::add( GoogleMapTargetRadioButton_, i18n(
+ "When using GoogleMap, all image must have complete URL, icons are squared and when drawing a track, only linetrack is exported" ) );
+
+ // --------------------------------------------------------------
+ // target preference, suite
+ TargetPreferenceGroupBoxLayout->addMultiCellWidget( buttonGroupTargetType, 0, 1, 0, 4 );
+
+ QLabel *AltitudeLabel_ = new QLabel(i18n("Picture altitude" ),
+ TargetPreferenceGroupBox, "AltitudeLabel_");
+ TargetPreferenceGroupBoxLayout->addMultiCellWidget( AltitudeLabel_, 2, 2, 0, 4 );
+ AltitudeCB_ = new QComboBox( false, TargetPreferenceGroupBox );
+ AltitudeCB_->insertItem(i18n("clamp to ground"));
+ AltitudeCB_->insertItem(i18n("relative to ground"));
+ AltitudeCB_->insertItem(i18n("absolute"));
+ QWhatsThis::add(AltitudeCB_, i18n("<p>Specifies how pictures are displayed"
+ "<dl><dt>clamp to ground (default)</dt>"
+ "<dd>Indicates to ignore an altitude specification</dd>"
+ "<dt>relative to ground</dt>"
+ "<dd>Sets the altitude of the element relative to the actual ground "
+ "elevation of a particular location.</dd>"
+ "<dt>absolute</dt>"
+ "<dd>Sets the altitude of the coordinate relative to sea level, regardless "
+ "of the actual elevation of the terrain beneath the element.</dd></dl>"));
+ TargetPreferenceGroupBoxLayout->addMultiCellWidget( AltitudeCB_, 2, 2, 2, 4 );
+
+ destinationDirectoryLabel_ = new QLabel( i18n( "Destination directory" ),
+ TargetPreferenceGroupBox, "destinationDirectoryLabel_" );
+ TargetPreferenceGroupBoxLayout->addMultiCellWidget( destinationDirectoryLabel_, 3, 3, 0, 2 );
+
+ // DestinationDirectory_ = new QLineEdit( TargetPreferenceGroupBox, "DestinationDirectory_" );
+ DestinationDirectory_= new KURLRequester( TargetPreferenceGroupBox, "DestinationDirectory_");
+ DestinationDirectory_->setCaption(i18n("Select a directory to save the kml file and pictures"));
+ DestinationDirectory_->setMode(KFile::Directory | KFile::LocalOnly );
+ TargetPreferenceGroupBoxLayout->addMultiCellWidget( DestinationDirectory_, 3, 3, 3, 4 );
+
+ DestinationUrlLabel_ = new QLabel( i18n( "Destination URL" ),
+ TargetPreferenceGroupBox, "DestinationUrlLabel_" );
+ TargetPreferenceGroupBoxLayout->addMultiCellWidget( DestinationUrlLabel_, 4, 4, 0, 1 );
+
+ DestinationURL_ = new QLineEdit( TargetPreferenceGroupBox, "DestinationURL_" );
+
+ TargetPreferenceGroupBoxLayout->addMultiCellWidget( DestinationURL_, 4, 4, 2, 4 );
+ FileNameLabel_ = new QLabel( i18n( "File name" ),
+ TargetPreferenceGroupBox, "FileNameLabel_" );
+ TargetPreferenceGroupBoxLayout->addWidget( FileNameLabel_, 5, 0 );
+
+ FileName_ = new QLineEdit( TargetPreferenceGroupBox, "FileName_" );
+ TargetPreferenceGroupBoxLayout->addMultiCellWidget( FileName_, 5, 5, 1, 4 );
+
+ KMLExportConfigLayout->addWidget( TargetPreferenceGroupBox, 0, 0 );
+
+ // --------------------------------------------------------------
+ // Sizes
+ QGroupBox *SizeGroupBox = new QGroupBox(0, Qt::Vertical, i18n( "Sizes" ), plainPage() );
+ SizeGroupBox->setColumnLayout(0, Qt::Vertical );
+ SizeGroupBoxLayout = new QGridLayout( SizeGroupBox->layout(), 2, 3, KDialog::spacingHint() );
+ SizeGroupBoxLayout->setAlignment( Qt::AlignTop );
+
+ IconSizeLabel = new QLabel( i18n( "Icon size" ),
+ SizeGroupBox, "IconSizeLabel" );
+ SizeGroupBoxLayout->addWidget( IconSizeLabel, 0, 0 );
+
+ IconSizeInput_ = new KIntNumInput( SizeGroupBox, "IconSizeInput_" );
+ IconSizeInput_->setValue( 33 );
+ SizeGroupBoxLayout->addWidget( IconSizeInput_, 0, 1 );
+
+ spacer3 = new QSpacerItem( 191, 21, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ SizeGroupBoxLayout->addItem( spacer3, 0, 2 );
+
+ ImageSizeLabel = new QLabel( i18n( "Image size" ),
+ SizeGroupBox, "ImageSizeLabel" );
+ SizeGroupBoxLayout->addWidget( ImageSizeLabel, 1, 0 );
+
+ ImageSizeInput_ = new KIntNumInput( SizeGroupBox, "ImageSizeInput_" );
+ ImageSizeInput_->setValue( 320 );
+ SizeGroupBoxLayout->addWidget( ImageSizeInput_, 1, 1 );
+
+ spacer4 = new QSpacerItem( 191, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ SizeGroupBoxLayout->addItem( spacer4, 1, 2 );
+
+ KMLExportConfigLayout->addWidget( SizeGroupBox, 1, 0 );
+
+ // --------------------------------------------------------------
+ // GPX Tracks
+ QGroupBox *GPXTracksGroupBox = new QGroupBox(0, Qt::Vertical, i18n( "GPX Tracks" ), plainPage());
+ QGridLayout *GPXTracksGroupBoxLayout = new QGridLayout(GPXTracksGroupBox->layout(), 5, 4,
+ KDialog::spacingHint());
+ GPXTracksGroupBoxLayout->setAlignment( Qt::AlignTop );
+
+ // add a gpx track checkbox
+ GPXTracksCheckBox_ = new QCheckBox( i18n( "Draw GPX track" ), GPXTracksGroupBox, "GPXTracksCheckBox");
+ GPXTracksGroupBoxLayout->addMultiCellWidget( GPXTracksCheckBox_, 0, 0, 0, 3);
+
+ // file selector
+ GPXFileLabel_ = new QLabel( i18n( "GPX file" ),
+ GPXTracksGroupBox, "GPXFileLabel_" );
+ GPXTracksGroupBoxLayout->addMultiCellWidget( GPXFileLabel_, 1, 1, 0, 0);
+
+ GPXFileKURLRequester_ = new KURLRequester( GPXTracksGroupBox, "GPXFileKURLRequester" );
+ GPXFileKURLRequester_->setFilter(i18n("%1|GPS Exchange Format").arg("*.gpx"));
+ GPXFileKURLRequester_->setCaption(i18n("Select GPX File to Load"));
+ GPXTracksGroupBoxLayout->addMultiCellWidget( GPXFileKURLRequester_, 1, 1, 1, 3);
+
+ timeZoneLabel_ = new QLabel(i18n("Time zone"), GPXTracksGroupBox);
+ GPXTracksGroupBoxLayout->addMultiCellWidget( timeZoneLabel_, 2, 2, 0, 0);
+ timeZoneCB = new QComboBox( false, GPXTracksGroupBox );
+ timeZoneCB->insertItem(i18n("GMT-12:00"), 0);
+ timeZoneCB->insertItem(i18n("GMT-11:00"), 1);
+ timeZoneCB->insertItem(i18n("GMT-10:00"), 2);
+ timeZoneCB->insertItem(i18n("GMT-09:00"), 3);
+ timeZoneCB->insertItem(i18n("GMT-08:00"), 4);
+ timeZoneCB->insertItem(i18n("GMT-07:00"), 5);
+ timeZoneCB->insertItem(i18n("GMT-06:00"), 6);
+ timeZoneCB->insertItem(i18n("GMT-05:00"), 7);
+ timeZoneCB->insertItem(i18n("GMT-04:00"), 8);
+ timeZoneCB->insertItem(i18n("GMT-03:00"), 9);
+ timeZoneCB->insertItem(i18n("GMT-02:00"), 10);
+ timeZoneCB->insertItem(i18n("GMT-01:00"), 11);
+ timeZoneCB->insertItem(i18n("GMT"), 12);
+ timeZoneCB->insertItem(i18n("GMT+01:00"), 13);
+ timeZoneCB->insertItem(i18n("GMT+02:00"), 14);
+ timeZoneCB->insertItem(i18n("GMT+03:00"), 15);
+ timeZoneCB->insertItem(i18n("GMT+04:00"), 16);
+ timeZoneCB->insertItem(i18n("GMT+05:00"), 17);
+ timeZoneCB->insertItem(i18n("GMT+06:00"), 18);
+ timeZoneCB->insertItem(i18n("GMT+07:00"), 19);
+ timeZoneCB->insertItem(i18n("GMT+08:00"), 20);
+ timeZoneCB->insertItem(i18n("GMT+09:00"), 21);
+ timeZoneCB->insertItem(i18n("GMT+10:00"), 22);
+ timeZoneCB->insertItem(i18n("GMT+11:00"), 23);
+ timeZoneCB->insertItem(i18n("GMT+12:00"), 24);
+ timeZoneCB->insertItem(i18n("GMT+13:00"), 25);
+ timeZoneCB->insertItem(i18n("GMT+14:00"), 26);
+ QWhatsThis::add(timeZoneCB, i18n("<p>Sets the time zone of the camera during "
+ "picture shooting, so that the time stamps of the GPS "
+ "can be converted to match the local time"));
+ GPXTracksGroupBoxLayout->addMultiCellWidget( timeZoneCB, 2, 2, 1, 3);
+
+ GPXLineWidthLabel_ = new QLabel( i18n( "Track width" ),
+ GPXTracksGroupBox, "GPXLineWidthLabel_" );
+ GPXTracksGroupBoxLayout->addMultiCellWidget( GPXLineWidthLabel_, 3, 3, 0, 0);
+ GPXLineWidthInput_ = new KIntNumInput( GPXTracksGroupBox, "GPXLineWidthInput_" );
+ GPXLineWidthInput_->setValue( 4 );
+ GPXTracksGroupBoxLayout->addMultiCellWidget( GPXLineWidthInput_, 3, 3, 1, 3);
+
+ GPXColorLabel_ = new QLabel( i18n( "Track color" ),
+ GPXTracksGroupBox, "GPXColorLabel_" );
+ GPXTracksGroupBoxLayout->addWidget( GPXColorLabel_, 4, 0 );
+ GPXTrackColor_ = new KColorButton(QColor("#ffffff"), GPXTracksGroupBox);
+ GPXTracksGroupBoxLayout->addWidget( GPXTrackColor_, 4, 1 );
+
+ GPXTracksOpacityInput_ = new KIntNumInput( GPXTracksGroupBox , "GPXTracksOpacityInput_" );
+ GPXTracksOpacityInput_->setRange( 0, 100, 1, false );
+ GPXTracksOpacityInput_->setValue( 100 );
+ GPXTracksOpacityInput_->setLabel( i18n( "Opacity:" ), AlignVCenter);
+ GPXTracksOpacityInput_->setSuffix( QString::fromAscii( "%" ) );
+ GPXTracksGroupBoxLayout->addMultiCellWidget( GPXTracksOpacityInput_, 4, 4, 2, 3);
+
+ GPXAltitudeLabel_ = new QLabel( i18n( "Track altitude" ),
+ GPXTracksGroupBox, "GPXAltitudeLabel_" );
+ GPXTracksGroupBoxLayout->addMultiCellWidget( GPXAltitudeLabel_, 5, 5, 0, 0);
+ GPXAltitudeCB_ = new QComboBox( false, GPXTracksGroupBox );
+ GPXAltitudeCB_->insertItem(i18n("clamp to ground"));
+ GPXAltitudeCB_->insertItem(i18n("relative to ground"));
+ GPXAltitudeCB_->insertItem(i18n("absolute"));
+ QWhatsThis::add(GPXAltitudeCB_, i18n("<p>Specifies how the points are displayed"
+ "<dl><dt>clamp to ground (default)</dt>"
+ "<dd>Indicates to ignore an altitude specification</dd>"
+ "<dt>relative to ground</dt>"
+ "<dd>Sets the altitude of the element relative to the actual ground "
+ "elevation of a particular location.</dd>"
+ "<dt>absolute</dt>"
+ "<dd>Sets the altitude of the coordinate relative to sea level, "
+ "regardless of the actual elevation of the terrain beneath "
+ "the element.</dd></dl>"));
+ GPXTracksGroupBoxLayout->addMultiCellWidget( GPXAltitudeCB_, 5, 5, 1, 3);
+
+ KMLExportConfigLayout->addWidget( GPXTracksGroupBox, 2, 0 );
+
+ connect( GoogleMapTargetRadioButton_, SIGNAL( toggled(bool) ),
+ this, SLOT( GoogleMapTargetRadioButton__toggled(bool) ) );
+
+ connect( GPXTracksCheckBox_, SIGNAL( toggled(bool) ),
+ this, SLOT( KMLTracksCheckButton__toggled(bool) ) );
+
+ // --------------------------------------------------------------
+ // About data and help button.
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("KML Export"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for kml exporting"),
+ "(c) 2006-2007, Stéphane Pontier");
+
+ m_about->addAuthor("Stéphane Pontier", I18N_NOOP("Author"),
+ "shadow.walker@free.fr");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // --------------------------------------------------------------
+ // Configuration file management
+
+ config_ = new KConfig("kipirc");
+ config_->setGroup("KMLExport Settings");
+
+ readSettings();
+
+ // --------------------------------------------------------------
+ // Just to initialize the UI
+ GoogleMapTargetRadioButton__toggled(true);
+ KMLTracksCheckButton__toggled(false);
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+KMLExportConfig::~KMLExportConfig()
+{
+ // no need to delete child widgets, Qt does it all for us
+ if(config_)
+ delete config_;
+ delete m_about;
+}
+
+void KMLExportConfig::slotOk()
+ //void KMLExportConfig::slotOkClicked()
+{
+ saveSettings();
+
+ emit okButtonClicked();
+ accept();
+}
+
+void KMLExportConfig::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("KMLExport", "kipi-plugins");
+}
+
+void KMLExportConfig::GoogleMapTargetRadioButton__toggled(bool)
+{
+ if (GoogleMapTargetRadioButton_->isChecked())
+ {
+ DestinationUrlLabel_->setEnabled(true);
+ DestinationURL_->setEnabled(true);
+ IconSizeLabel->setEnabled(false);
+ IconSizeInput_->setEnabled(false);
+ }
+ else
+ {
+ DestinationUrlLabel_->setEnabled(false);
+ DestinationURL_->setEnabled(false);
+ IconSizeLabel->setEnabled(true);
+ IconSizeInput_->setEnabled(true);
+ }
+}
+
+void KMLExportConfig::KMLTracksCheckButton__toggled(bool)
+{
+ if (GPXTracksCheckBox_->isChecked())
+ {
+ GPXFileKURLRequester_->setEnabled(true);
+ GPXFileLabel_->setEnabled(true);
+ timeZoneCB->setEnabled(true);
+ GPXColorLabel_->setEnabled(true);
+ GPXAltitudeLabel_->setEnabled(true);
+ timeZoneLabel_->setEnabled(true);
+ GPXAltitudeCB_->setEnabled(true);
+ GPXTrackColor_->setEnabled(true);
+ GPXLineWidthLabel_->setEnabled(true);
+ GPXLineWidthInput_->setEnabled(true);
+ GPXTracksOpacityInput_->setEnabled(true);
+ }
+ else
+ {
+ GPXFileKURLRequester_->setEnabled(false);
+ GPXFileLabel_->setEnabled(false);
+ timeZoneCB->setEnabled(false);
+ GPXColorLabel_->setEnabled(false);
+ GPXAltitudeLabel_->setEnabled(false);
+ timeZoneLabel_->setEnabled(false);
+ GPXAltitudeCB_->setEnabled(false);
+ GPXTrackColor_->setEnabled(false);
+ GPXLineWidthLabel_->setEnabled(false);
+ GPXLineWidthInput_->setEnabled(false);
+ GPXTracksOpacityInput_->setEnabled(false);
+ }
+}
+
+void KMLExportConfig::saveSettings()
+{
+ if (!config_) return;
+
+ config_->writeEntry("localTarget", LocalTargetRadioButton_->isChecked());
+ config_->writeEntry("optimize_googlemap", GoogleMapTargetRadioButton_->isChecked());
+ config_->writeEntry("iconSize", IconSizeInput_->value());
+ config_->writeEntry("size", ImageSizeInput_->value());
+ QString destination = DestinationDirectory_->url();
+ if (!destination.endsWith("/"))
+ {
+ destination.append("/");
+ }
+ config_->writeEntry("baseDestDir",destination);
+ QString url = DestinationURL_->text();
+ if (!url.endsWith("/"))
+ {
+ url.append("/");
+ }
+ config_->writeEntry("UrlDestDir",url);
+ config_->writeEntry("KMLFileName",FileName_->text());
+ config_->writeEntry("Altitude Mode", AltitudeCB_->currentItem() );
+
+ config_->writeEntry("UseGPXTracks", GPXTracksCheckBox_->isChecked());
+
+ config_->writeEntry("GPXFile", GPXFileKURLRequester_->lineEdit()->originalText());
+ config_->writeEntry("Time Zone", timeZoneCB->currentItem() );
+ config_->writeEntry("Line Width", GPXLineWidthInput_->value());
+ config_->writeEntry("Track Color", GPXTrackColor_->color().name () );
+ config_->writeEntry("Track Opacity", GPXTracksOpacityInput_->value() );
+ config_->writeEntry("GPX Altitude Mode", GPXAltitudeCB_->currentItem() );
+
+ config_->sync();
+}
+
+void KMLExportConfig::readSettings()
+{
+ bool localTarget;
+ bool optimize_googlemap;
+ int iconSize;
+ // int googlemapSize;
+ int size;
+ QString UrlDestDir;
+ QString baseDestDir;
+ QString KMLFileName;
+ int AltitudeMode;
+
+ bool GPXtracks;
+ QString GPXFile;
+ int TimeZone;
+ int LineWidth;
+ QString GPXColor;
+ int GPXOpacity;
+ int GPXAltitudeMode;
+
+ localTarget = config_->readBoolEntry("localTarget", true);
+ optimize_googlemap = config_->readBoolEntry("optimize_googlemap", false);
+ iconSize = config_->readNumEntry("iconSize", 33);
+ // not saving this size as it should not change
+ // googlemapSize = config_->readNumEntry("googlemapSize", 32);
+ size = config_->readNumEntry("size", 320);
+ // UrlDestDir have to have the trailing /
+ baseDestDir = config_->readEntry("baseDestDir", "/tmp/");
+ UrlDestDir = config_->readEntry("UrlDestDir", "http://www.example.com/");
+ KMLFileName = config_->readEntry("KMLFileName", "kmldocument");
+ AltitudeMode = config_->readNumEntry("Altitude Mode", 0);
+
+ GPXtracks = config_->readBoolEntry("UseGPXTracks", false);
+ GPXFile = config_->readEntry("GPXFile", "");
+ TimeZone = config_->readNumEntry("Time Zone", 12);
+ LineWidth = config_->readNumEntry("Line Width", 4);
+ GPXColor = config_->readEntry("Track Color", "#17eeee" );
+ GPXOpacity = config_->readNumEntry("Track Opacity", 64 );
+ GPXAltitudeMode = config_->readNumEntry("GPX Altitude Mode", 0);
+
+ // -- Apply Settings to widgets ------------------------------
+
+ LocalTargetRadioButton_->setChecked(localTarget);
+ GoogleMapTargetRadioButton_->setChecked(optimize_googlemap);
+
+ IconSizeInput_->setValue(iconSize);
+ ImageSizeInput_->setValue(size);
+
+ AltitudeCB_->setCurrentItem(AltitudeMode);
+ DestinationDirectory_->setURL(baseDestDir);
+ DestinationURL_->setText(UrlDestDir);
+ FileName_->setText(KMLFileName);
+
+ timeZoneCB->setCurrentItem(TimeZone);
+ GPXLineWidthInput_->setValue(LineWidth);
+ GPXTrackColor_->setColor(GPXColor);
+ GPXTracksOpacityInput_->setValue(GPXOpacity);
+ GPXAltitudeCB_->setCurrentItem(GPXAltitudeMode);
+}
+
+} //namespace KIPIGPSSyncPlugin
diff --git a/kipi-plugins/gpssync/kmlexportconfig.h b/kipi-plugins/gpssync/kmlexportconfig.h
new file mode 100644
index 0000000..54841b7
--- /dev/null
+++ b/kipi-plugins/gpssync/kmlexportconfig.h
@@ -0,0 +1,138 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a tool to export GPS data to KML file.
+ *
+ * Copyright (C) 2006-2007 by Stephane Pontier <shadow dot walker at free dot fr>
+ *
+ * This program is free software; you can redistribute 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 KMLEXPORTCONFIG_H
+#define KMLEXPORTCONFIG_H
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+class QButtonGroup;
+class QCheckBox;
+class QComboBox;
+class QGridLayout;
+class QGroupBox;
+class QLabel;
+class QLineEdit;
+class QRadioButton;
+class QSpacerItem;
+
+class KColorButton;
+class KIntNumInput;
+class KURLRequester;
+
+namespace KIPIPlugins
+{
+ class KPAboutData;
+}
+
+namespace KIPIGPSSyncPlugin
+{
+
+class KMLExportConfig : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ explicit KMLExportConfig( QWidget* parent = 0, const char* name = 0);
+ ~KMLExportConfig();
+
+public:
+
+ QLabel *ImageSizeLabel;
+ QLabel *IconSizeLabel;
+ QLabel *destinationDirectoryLabel_;
+ QLabel *FileNameLabel_;
+ QLabel *DestinationUrlLabel_;
+ QLabel *GPXFileLabel_;
+ QLabel *timeZoneLabel_;
+ QLabel *GPXLineWidthLabel_;
+ QLabel *GPXColorLabel_;
+ QLabel *GPXTracksOpacityLabel_;
+ QLabel *GPXAltitudeLabel_;
+
+ QGroupBox *TargetPreferenceGroupBox;
+
+ QButtonGroup *buttonGroupTargetType;
+
+ QRadioButton *LocalTargetRadioButton_;
+ QRadioButton *GoogleMapTargetRadioButton_;
+
+ QLineEdit *DestinationURL_;
+ QLineEdit *FileName_;
+
+ QCheckBox *GPXTracksCheckBox_;
+
+ QComboBox *AltitudeCB_;
+ QComboBox *timeZoneCB;
+ QComboBox *GPXAltitudeCB_;
+
+ KColorButton *GPXTrackColor_;
+
+ KURLRequester *DestinationDirectory_;
+ KURLRequester *GPXFileKURLRequester_;
+
+ KIntNumInput *ImageSizeInput_;
+ KIntNumInput *IconSizeInput_;
+ KIntNumInput *GPXTracksOpacityInput_;
+ KIntNumInput *GPXLineWidthInput_;
+
+public slots:
+
+ void GoogleMapTargetRadioButton__toggled(bool);
+ void KMLTracksCheckButton__toggled(bool);
+
+signals:
+
+ void okButtonClicked(); // Signal needed by plugin_kmlexport class
+
+protected:
+
+ QSpacerItem *spacer3;
+ QSpacerItem *spacer4;
+
+ QGridLayout *KMLExportConfigLayout;
+ QGridLayout *SizeGroupBoxLayout;
+ QGridLayout *TargetPreferenceGroupBoxLayout;
+ QGridLayout *buttonGroupTargetTypeLayout;
+
+ KConfig *config_;
+
+ KIPIPlugins::KPAboutData *m_about;
+
+protected:
+
+ void saveSettings();
+ void readSettings();
+
+protected slots:
+
+ void slotOk();
+ // void slotOkClicked();
+ void slotHelp();
+};
+
+} // namespace
+
+#endif // KMLEXPORTCONFIG_H
diff --git a/kipi-plugins/gpssync/kmlgpsdataparser.cpp b/kipi-plugins/gpssync/kmlgpsdataparser.cpp
new file mode 100644
index 0000000..4a796a9
--- /dev/null
+++ b/kipi-plugins/gpssync/kmlgpsdataparser.cpp
@@ -0,0 +1,141 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a tool to export GPS data to KML file.
+ *
+ * Copyright (C) 2006-2007 by Stephane Pontier <shadow dot walker at free dot fr>
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "kmlgpsdataparser.h"
+
+// KDE includes.
+
+#include <kdebug.h>
+#include <klocale.h>
+
+namespace KIPIGPSSyncPlugin
+{
+
+KMLGPSDataParser::KMLGPSDataParser()
+ : GPSDataParser()
+{
+}
+
+KMLGPSDataParser::~KMLGPSDataParser()
+{
+}
+
+QString KMLGPSDataParser::lineString()
+{
+ QString line = "";
+ // cache the end to not recalculate it with large number of points
+ GPSDataMap::ConstIterator end (m_GPSDataMap.constEnd());
+ for (GPSDataMap::ConstIterator it = m_GPSDataMap.constBegin();
+ it != end; ++it )
+ {
+ line += QString("%1,%2,%3 ").arg(it.data().longitude()).arg(it.data().latitude()).arg(it.data().altitude());
+ }
+ return line;
+}
+
+/*!
+\fn void KIPIGPSSyncPlugin::KMLGPSDataParser::CreateTrackLine(QDomElement &parent, QDomDocument &root, int altitudeMode)
+ */
+void KIPIGPSSyncPlugin::KMLGPSDataParser::CreateTrackLine(QDomElement &parent, QDomDocument &root, int altitudeMode)
+{
+ kmlDocument = &root;
+
+ // add the linetrack
+ QDomElement kmlPlacemark = addKmlElement(parent, "Placemark");
+ addKmlTextElement(kmlPlacemark, "name", i18n("Track"));
+ QDomElement kmlLineString = addKmlElement(kmlPlacemark, "LineString");
+ addKmlTextElement(kmlLineString, "coordinates", lineString());
+ addKmlTextElement(kmlPlacemark, "styleUrl", "#linetrack");
+ if (altitudeMode == 2 )
+ {
+ addKmlTextElement(kmlLineString, "altitudeMode", "absolute");
+ }
+ else if (altitudeMode == 1 )
+ {
+ addKmlTextElement(kmlLineString, "altitudeMode", "relativeToGround");
+ }
+ else
+ {
+ addKmlTextElement(kmlLineString, "altitudeMode", "clampToGround");
+ }
+}
+
+/*!
+\fn void KIPIGPSSyncPlugin::KMLGPSDataParser::CreateTrackPoints(QDomElement &parent, QDomDocument &root, int timeZone, int altitudeMode)
+ */
+void KIPIGPSSyncPlugin::KMLGPSDataParser::CreateTrackPoints(QDomElement &parent, QDomDocument &root,
+ int timeZone, int altitudeMode)
+{
+ kmlDocument = &root;
+ kdDebug( 51001 ) << "creation d'un trackpoint" << endl;
+
+ // create the points
+ QDomElement kmlPointsFolder = addKmlElement(parent, "Folder");
+ addKmlTextElement(kmlPointsFolder, "name", i18n("Points"));
+ addKmlTextElement(kmlPointsFolder, "visibility", "0");
+ addKmlTextElement(kmlPointsFolder, "open", "0");
+ int i = 0;
+ // cache the end to not recalculate it with large number of points
+ GPSDataMap::ConstIterator end (m_GPSDataMap.constEnd());
+ for (GPSDataMap::ConstIterator it = m_GPSDataMap.constBegin();
+ it != end; ++it, i++)
+ {
+ QDomElement kmlPointPlacemark = addKmlElement(kmlPointsFolder, "Placemark");
+ addKmlTextElement(kmlPointPlacemark, "name", QString("%1 %2 ").arg(i18n("Point")).arg(i));
+ addKmlTextElement(kmlPointPlacemark, "styleUrl", "#track");
+ QDomElement kmlTimeStamp = addKmlElement(kmlPointPlacemark, "TimeStamp");
+ // GPS device are sync in time by satellite using GMT time.
+ // If the camera time is different than GMT time, we want to
+ // convert the GPS time to localtime of the picture to be display
+ // in the same timeframe
+ QDateTime GPSLocalizedTime = it.key().addSecs(timeZone*3600);
+
+ addKmlTextElement(kmlTimeStamp, "when", GPSLocalizedTime.toString("yyyy-MM-ddThh:mm:ssZ"));
+ QDomElement kmlGeometry = addKmlElement(kmlPointPlacemark, "Point");
+ addKmlTextElement(kmlPointPlacemark, "visibility", "0");
+ if (it.data().latitude())
+ {
+ addKmlTextElement(kmlGeometry, "coordinates",
+ QString("%1,%2,%3").arg(it.data().longitude()).arg(it.data().latitude()).arg(it.data().altitude()));
+ }
+ else
+ {
+ addKmlTextElement(kmlGeometry, "coordinates", QString("%1,%2").arg(it.data().longitude()).arg(it.data().latitude()));
+ }
+ if (altitudeMode == 2 )
+ {
+ addKmlTextElement(kmlGeometry, "altitudeMode", "absolute");
+ }
+ else if (altitudeMode == 1 )
+ {
+ addKmlTextElement(kmlGeometry, "altitudeMode", "relativeToGround");
+ }
+ else
+ {
+ addKmlTextElement(kmlGeometry, "altitudeMode", "clampToGround");
+ }
+ }
+}
+
+} // namespace KIPIGPSSyncPlugin
diff --git a/kipi-plugins/gpssync/kmlgpsdataparser.h b/kipi-plugins/gpssync/kmlgpsdataparser.h
new file mode 100644
index 0000000..e3e271e
--- /dev/null
+++ b/kipi-plugins/gpssync/kmlgpsdataparser.h
@@ -0,0 +1,107 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a tool to export GPS data to KML file.
+ *
+ * Copyright (C) 2006-2007 by Stephane Pontier <shadow dot walker at free dot fr>
+ *
+ * This program is free software; you can redistribute 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 KIPIGPSSYNCPLUGINKMLGPSDATAPARSER_H
+#define KIPIGPSSYNCPLUGINKMLGPSDATAPARSER_H
+
+// Local includes.
+
+#include "gpsdataparser.h"
+
+// Qt includes.
+
+#include <qdom.h>
+
+namespace KIPIGPSSyncPlugin
+{
+
+/*! a classe derivated from GPSDataParser mainly to transform GPS data to KML
+ * @author Stéphane Pontier shadow.walker@free.fr
+ */
+class KMLGPSDataParser : public GPSDataParser
+{
+
+public:
+
+ KMLGPSDataParser();
+ ~KMLGPSDataParser();
+
+ /*! KIPIGPSSyncPlugin::KMLGPSDataParser::lineString()
+ * @return the string containing the time ordered point (lon,lat,alt)
+ */
+ QString lineString();
+ /*! Create a KML Element that will contain the linetrace of the GPS
+ * @param parent the QDomElement to which the track will be added
+ * @param root the QDomDocument used to create all elements
+ * @param altitudeMode altitude mode of the line and points
+ */
+
+ void CreateTrackLine(QDomElement &parent, QDomDocument &root, int altitudeMode);
+ /*! Create a KML Element that will contain the points and of the GPS
+ * @param parent the QDomElement to which the track will be added
+ * @param root the QDomDocument used to create all elements
+ * @param timeZone the Timezone of the pictures
+ * @param altitudeMode altitude mode of the line and points
+ */
+ void CreateTrackPoints(QDomElement &parent, QDomDocument &root, int timeZone, int altitudeMode);
+
+private:
+
+ /*! @todo maybe initialize it in the constructor */
+ /*! the root document, used to create all QDomElements */
+ QDomDocument *kmlDocument;
+
+ /*!
+ \fn QDomElement KIPIGPSSyncPlugin::KMLGPSDataParser::addKmlElement(QDomElement target, QString tag)
+ * Add a new element
+ * @param target the parent element to which add the element
+ * @param tag the new element name
+ * @return the New element
+ */
+ QDomElement addKmlElement(QDomElement &target, QString tag)
+ {
+ QDomElement kmlElement = kmlDocument->createElement( tag );
+ target.appendChild( kmlElement );
+ return kmlElement;
+ }
+
+ /*!
+ \fn QDomElement KIPIGPSSyncPlugin::KMLGPSDataParser::addKmlTextElement(QDomElement target, QString tag, QString text)
+ * Add a new element with a text
+ * @param target the parent element to which add the element
+ * @param tag the new element name
+ * @param text the text content of the new element
+ * @return the New element
+ */
+ QDomElement addKmlTextElement(QDomElement &target, QString tag, QString text)
+ {
+ QDomElement kmlElement = kmlDocument->createElement( tag );
+ target.appendChild( kmlElement );
+ QDomText kmlTextElement = kmlDocument->createTextNode( text );
+ kmlElement.appendChild( kmlTextElement );
+ return kmlElement;
+ }
+};
+
+} // namespace KIPIGPSSyncPlugin
+
+#endif // KIPIGPSSYNCPLUGINKMLGPSDATAPARSER_H
diff --git a/kipi-plugins/gpssync/plugin_gpssync.cpp b/kipi-plugins/gpssync/plugin_gpssync.cpp
new file mode 100644
index 0000000..15c7f51
--- /dev/null
+++ b/kipi-plugins/gpssync/plugin_gpssync.cpp
@@ -0,0 +1,342 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a plugin to synchronize pictures with
+ * a GPS device.
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qfileinfo.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+// LibKIPI includes.
+
+#include <libkipi/imagecollection.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "gpsbabelbinary.h"
+#include "gpsdatacontainer.h"
+#include "gpseditdialog.h"
+#include "gpssyncdialog.h"
+#include "kmlexport.h"
+#include "kmlexportconfig.h"
+#include "plugin_gpssync.h"
+#include "plugin_gpssync.moc"
+
+typedef KGenericFactory<Plugin_GPSSync> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_gpssync, Factory("kipiplugin_gpssync"))
+
+Plugin_GPSSync::Plugin_GPSSync(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "GPSSync")
+{
+ kdDebug( 51001 ) << "Plugin_GPSSync plugin loaded" << endl;
+}
+
+void Plugin_GPSSync::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_action_geolocation = new KActionMenu(i18n("Geolocation"),
+ 0,
+ actionCollection(),
+ "geolocation");
+
+ m_action_geolocation->insert(new KAction (i18n("Correlator..."),
+ "gpsimagetag",
+ 0,
+ this,
+ SLOT(slotGPSSync()),
+ actionCollection(),
+ "gpssync"));
+
+ m_action_geolocation->insert(new KAction (i18n("Edit Coordinates..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotGPSEdit()),
+ actionCollection(),
+ "gpsedit"));
+
+ m_action_geolocation->insert(new KAction (i18n("Remove Coordinates..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotGPSRemove()),
+ actionCollection(),
+ "gpsremove"));
+
+ addAction( m_action_geolocation );
+
+ // this is our action shown in the menubar/toolbar of the mainwindow
+ m_actionKMLExport = new KAction (i18n("KML Export..."),
+ "www", // icon
+ 0, // do never set shortcuts from plugins.
+ this,
+ SLOT(slotKMLExport()),
+ actionCollection(),
+ "kmlexport");
+
+ addAction( m_actionKMLExport );
+
+ m_interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection selection = m_interface->currentSelection();
+ m_action_geolocation->setEnabled( selection.isValid() && !selection.images().isEmpty() );
+
+ connect( m_interface, SIGNAL(selectionChanged(bool)),
+ m_action_geolocation, SLOT(setEnabled(bool)));
+}
+
+bool Plugin_GPSSync::checkBinaries(QString &gpsBabelVersion)
+{
+ KIPIGPSSyncPlugin::GPSBabelBinary gpsBabelBinary;
+ gpsBabelVersion = gpsBabelBinary.version();
+
+ if (!gpsBabelBinary.isAvailable())
+ {
+ KMessageBox::information(
+ kapp->activeWindow(),
+ i18n("<qt><p>Unable to find the gpsbabel executable:<br> "
+ "This program is required by this plugin to support GPS data file decoding. "
+ "Please install gpsbabel as a package from your distributor "
+ "or <a href=\"%1\">download the source</a>.</p>"
+ "<p>Note: at least, gpsbabel version %2 is required by this plugin.</p></qt>")
+ .arg("http://www.gpsbabel.org")
+ .arg(gpsBabelBinary.minimalVersion()),
+ QString::null,
+ QString::null,
+ KMessageBox::Notify | KMessageBox::AllowLink);
+ return false;
+ }
+
+ if (!gpsBabelBinary.versionIsRight())
+ {
+ KMessageBox::information(
+ kapp->activeWindow(),
+ i18n("<qt><p>gpsbabel executable is not up to date:<br> "
+ "The version %1 of gpsbabel have been found on your computer. "
+ "This version is too old to run properly with this plugin. "
+ "Please update gpsbabel as a package from your distributor "
+ "or <a href=\"%2\">download the source</a>.</p>"
+ "<p>Note: at least, gpsbabel version %3 is required by this "
+ "plugin</p></qt>")
+ .arg(gpsBabelVersion)
+ .arg("http://www.gpsbabel.org")
+ .arg(gpsBabelBinary.minimalVersion()),
+ QString::null,
+ QString::null,
+ KMessageBox::Notify | KMessageBox::AllowLink);
+ return false;
+ }
+
+ return true;
+}
+
+void Plugin_GPSSync::slotGPSSync()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ /* NOTE: this plugin do not use yet GPSBabel to convert GPS data file to GPX
+ QString gpsBabelVersion;
+ if (!checkBinaries(gpsBabelVersion))
+ return;
+ */
+
+ KIPIGPSSyncPlugin::GPSSyncDialog *dialog = new KIPIGPSSyncPlugin::GPSSyncDialog(
+ m_interface, kapp->activeWindow());
+
+ dialog->setImages( images.images() );
+ dialog->show();
+}
+
+void Plugin_GPSSync::slotGPSEdit()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ KURL img = images.images().first();
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.load(img.path());
+ double alt, lat, lng;
+ bool hasGPSInfo = exiv2Iface.getGPSInfo(alt, lat, lng);
+ KIPIGPSSyncPlugin::GPSDataContainer gpsData(alt, lat, lng, false);
+
+ KIPIGPSSyncPlugin::GPSEditDialog dlg(kapp->activeWindow(),
+ gpsData, img.fileName(), hasGPSInfo);
+
+ if (dlg.exec() == KDialogBase::Accepted)
+ {
+ gpsData = dlg.getGPSInfo();
+ KURL::List imageURLs = images.images();
+ KURL::List updatedURLs;
+ QStringList errorFiles;
+
+ for( KURL::List::iterator it = imageURLs.begin() ;
+ it != imageURLs.end(); ++it)
+ {
+ KURL url = *it;
+
+ bool ret = true;
+ ret &= exiv2Iface.load(url.path());
+ if (ret)
+ {
+ ret &= exiv2Iface.setGPSInfo(gpsData.altitude(),
+ gpsData.latitude(),
+ gpsData.longitude());
+ ret &= exiv2Iface.save(url.path());
+ }
+
+ if (!ret)
+ errorFiles.append(url.fileName());
+ else
+ updatedURLs.append(url);
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-readed.
+
+ m_interface->refreshImages(updatedURLs);
+
+ if (!errorFiles.isEmpty())
+ {
+ KMessageBox::errorList(
+ kapp->activeWindow(),
+ i18n("Unable to save geographical coordinates into:"),
+ errorFiles,
+ i18n("Edit Geographical Coordinates"));
+ }
+ }
+}
+
+void Plugin_GPSSync::slotGPSRemove()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ if (KMessageBox::warningYesNo(
+ kapp->activeWindow(),
+ i18n("Geographical coordinates will be definitively removed from all selected images.\n"
+ "Do you want to continue ?"),
+ i18n("Remove Geographical Coordinates")) != KMessageBox::Yes)
+ return;
+
+ KURL::List imageURLs = images.images();
+ KURL::List updatedURLs;
+ QStringList errorFiles;
+
+ for( KURL::List::iterator it = imageURLs.begin() ;
+ it != imageURLs.end(); ++it)
+ {
+ KURL url = *it;
+
+ bool ret = true;
+ KExiv2Iface::KExiv2 exiv2Iface;
+ ret &= exiv2Iface.load(url.path());
+ ret &= exiv2Iface.removeGPSInfo();
+ ret &= exiv2Iface.save(url.path());
+
+ if (!ret)
+ errorFiles.append(url.fileName());
+ else
+ updatedURLs.append(url);
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-readed.
+
+ m_interface->refreshImages(updatedURLs);
+
+ if (!errorFiles.isEmpty())
+ {
+ KMessageBox::errorList(
+ kapp->activeWindow(),
+ i18n("Unable to remove geographical coordinates from:"),
+ errorFiles,
+ i18n("Remove Geographical Coordinates"));
+ }
+}
+
+void Plugin_GPSSync::slotKMLExport()
+{
+ KIPI::ImageCollection selection = m_interface->currentSelection();
+
+ if ( !selection.isValid() )
+ {
+ kdDebug( 51000) << "No Selection!" << endl;
+ }
+ else
+ {
+ KIPIGPSSyncPlugin::KMLExportConfig *kmlExportConfigGui = new KIPIGPSSyncPlugin::KMLExportConfig(
+ kapp->activeWindow(), i18n("KMLExport").ascii());
+ connect(kmlExportConfigGui, SIGNAL(okButtonClicked()),
+ this, SLOT(slotKMLGenerate()));
+ kmlExportConfigGui->show();
+ }
+}
+
+void Plugin_GPSSync::slotKMLGenerate()
+{
+ KIPI::ImageCollection selection = m_interface->currentSelection();
+ KIPIGPSSyncPlugin::kmlExport myExport(m_interface);
+ if(!myExport.getConfig())
+ return;
+ myExport.generate();
+}
+
+KIPI::Category Plugin_GPSSync::category( KAction* action ) const
+{
+ if ( action == m_action_geolocation )
+ return KIPI::IMAGESPLUGIN;
+ if ( action == m_actionKMLExport )
+ return KIPI::EXPORTPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMAGESPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/gpssync/plugin_gpssync.h b/kipi-plugins/gpssync/plugin_gpssync.h
new file mode 100644
index 0000000..c12105c
--- /dev/null
+++ b/kipi-plugins/gpssync/plugin_gpssync.h
@@ -0,0 +1,66 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-05-16
+ * Description : a plugin to synchronize pictures with
+ * a GPS device.
+ *
+ * Copyright 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_GPSSYNC_H
+#define PLUGIN_GPSSYNC_H
+
+// LibKIPI includes.
+
+#include <libkipi/plugin.h>
+
+class KActionMenu;
+class KAction;
+
+class Plugin_GPSSync : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_GPSSync(QObject *parent, const char* name, const QStringList &args);
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* );
+
+protected slots:
+
+ void slotGPSSync();
+ void slotGPSEdit();
+ void slotGPSRemove();
+ void slotKMLGenerate();
+ void slotKMLExport();
+
+private:
+
+ bool checkBinaries(QString &gpsBabelVersion);
+
+private:
+
+ KActionMenu *m_action_geolocation;
+ KAction *m_actionKMLExport;
+
+ KIPI::Interface *m_interface;
+};
+
+#endif // PLUGIN_GPSSYNC_H
diff --git a/kipi-plugins/helloworld/Makefile.am b/kipi-plugins/helloworld/Makefile.am
new file mode 100644
index 0000000..25258d4
--- /dev/null
+++ b/kipi-plugins/helloworld/Makefile.am
@@ -0,0 +1,23 @@
+INCLUDES = $(LIBKIPI_CFLAGS) $(all_includes)
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_helloworld.la
+kipiplugin_helloworld_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+# Srcs for the plugin
+kipiplugin_helloworld_la_SOURCES = plugin_helloworld.cpp
+
+# Libs needed by the plugin
+kipiplugin_helloworld_la_LIBADD = $(LIBKIPI_LIBS) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_helloworld_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_helloworld.desktop
+
+# i18n translation messages
+#Nota : no need a translation file for this plugin.
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_helloworld.pot
+
diff --git a/kipi-plugins/helloworld/kipiplugin_helloworld.desktop b/kipi-plugins/helloworld/kipiplugin_helloworld.desktop
new file mode 100644
index 0000000..fcdb1cb
--- /dev/null
+++ b/kipi-plugins/helloworld/kipiplugin_helloworld.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=HelloWorld
+Name[ca]=Hola món!
+Name[cs]=Hello World
+Name[da]=Hello world
+Name[de]=Hallo Welt!
+Name[el]=ΓειάΣουΚόσμε
+Name[es]=Hola mundo
+Name[et]=Tere, maailm
+Name[gl]=Olá Mundo
+Name[it]=CiaoMondo
+Name[nds]=Moin Welt
+Name[nl]=Hallo wereld
+Name[pl]=Witaj świecie
+Name[pt]=Olá Mundo
+Name[sr]=Здраво свете
+Name[sr@Latn]=Zdravo svete
+Name[sv]=Hello world
+Name[tg]=Салом Ҷаҳон
+Name[tr]=MerhabaDünya
+Name[xx]=xxHelloWorldxx
+Name[zh_CN]=世界你好
+Comment=KIPI Hello World Plugin
+Comment[ca]=Connector del KIPI per a fer un Hola món!
+Comment[cs]=KIPI modul Hello World
+Comment[da]=KIPI-plugin: Hello world
+Comment[de]=KIPI Hallo-Welt-Modul
+Comment[el]=Πρόσθετο γεια σου κόσμε του KIPI
+Comment[es]=Complemento de KIPI «Hola mundo»
+Comment[et]=KIPI plugin 'Tere, maailm'
+Comment[fi]=Kipi-liitännäinen 'Hello World'
+Comment[fr]=Module externe KIPI pour afficher Hello World
+Comment[gl]=Plugin «Olá Mundo» de KIPI
+Comment[it]=Plugin ciao mondo di KIPI
+Comment[ja]=Kipi Hello World プラグイン
+Comment[nds]=KIPI-Moduul "Moin Welt!"
+Comment[nl]=KIPI-plugin voor "Hallo wereld"
+Comment[pa]=KIPI ਹੈਲੋ ਵਰਲਡ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Witaj świecie
+Comment[pt]='Plugin' de Olá Mundo do KIPI
+Comment[pt_BR]=Plugin Alô Mundo do KIPI
+Comment[sr]=KIPI прикључак Здраво свете
+Comment[sr@Latn]=KIPI priključak Zdravo svete
+Comment[sv]=KIPI-insticksprogram: Hello world
+Comment[tg]=Модули Салом Ҷаҳони KIPI
+Comment[tr]=KIPI Merhaba Dünya Eklentisi
+Comment[xx]=xxKIPI Hello World Pluginxx
+Comment[zh_CN]=KIPI 世界你好插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_helloworld
+author=John Doe, johndoe@somewhere.com
diff --git a/kipi-plugins/helloworld/plugin_helloworld.cpp b/kipi-plugins/helloworld/plugin_helloworld.cpp
new file mode 100644
index 0000000..ec58253
--- /dev/null
+++ b/kipi-plugins/helloworld/plugin_helloworld.cpp
@@ -0,0 +1,185 @@
+/* ============================================================
+ * File : plugin_helloworld.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-03-10
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * ============================================================ */
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+// LibKIPi includes.
+
+#include <libkipi/imagecollection.h>
+
+// Local includes.
+
+#include "plugin_helloworld.h"
+
+// A macro from KDE KParts to export the symbols for this plugin and
+// create the factory for it. The first argument is the name of the
+// plugin library and the second is the genericfactory templated from
+// the class for your plugin
+
+typedef KGenericFactory<Plugin_HelloWorld> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_helloworld,
+ Factory("kipiplugin_helloworld"));
+
+Plugin_HelloWorld::Plugin_HelloWorld(QObject *parent,
+ const char*,
+ const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "HelloWorld")
+{
+ kdDebug( 51001 ) << "Plugin_HelloWorld plugin loaded" << endl;
+}
+
+void Plugin_HelloWorld::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ // this is our action shown in the menubar/toolbar of the mainwindow
+ m_actionHelloWorld = new KAction (i18n("Hello World..."),
+ "misc",
+ 0, // do never set shortcuts from plugins.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "helloworld");
+
+ addAction( m_actionHelloWorld );
+
+ m_interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+}
+
+void Plugin_HelloWorld::slotActivate()
+{
+ kdDebug( 51000 ) << "Plugin_HelloWorld slot activated" << endl;
+
+ // Print some information about the capabilities of the host application.
+ kdDebug( 51000 ) << "Features supported by the host application:"
+ << endl;
+
+ kdDebug( 51000 ) << " AlbumsHaveComments: "
+ << (m_interface->hasFeature( KIPI::AlbumsHaveComments ) ? "Yes" : "No")
+ << endl;
+
+ kdDebug( 51000 ) << " ImagesHasComments: "
+ << (m_interface->hasFeature( KIPI::ImagesHasComments ) ? "Yes" : "No")
+ << endl;
+
+ kdDebug( 51000 ) << " ImagesHasTime: "
+ << (m_interface->hasFeature( KIPI::ImagesHasTime ) ? "Yes" : "No")
+ << endl;
+
+ kdDebug( 51000 ) << " SupportsDateRanges: "
+ << (m_interface->hasFeature( KIPI::SupportsDateRanges ) ? "Yes" : "No")
+ << endl;
+
+ kdDebug( 51000 ) << " AcceptNewImages: "
+ << (m_interface->hasFeature( KIPI::AcceptNewImages ) ? "Yes" : "No")
+ << endl;
+
+ kdDebug( 51000 ) << " ImageTitlesWritable: "
+ << (m_interface->hasFeature( KIPI::ImageTitlesWritable ) ? "Yes" : "No")
+ << endl;
+
+ kdDebug( 51000 ) << " AlbumsHaveCategory: "
+ << (m_interface->hasFeature( KIPI::AlbumsHaveCategory ) ? "Yes" : "No")
+ << endl;
+
+ kdDebug( 51000 ) << " AlbumsHaveCreationDate: "
+ << (m_interface->hasFeature( KIPI::AlbumsHaveCreationDate ) ? "Yes" : "No")
+ << endl;
+
+ kdDebug( 51000 ) << " AlbumsUseFirstImagePreview: "
+ << (m_interface->hasFeature( KIPI::AlbumsUseFirstImagePreview ) ? "Yes" : "No")
+ << endl;
+
+
+ // ================================================== Selection
+
+ kdDebug( 51000 ) << endl
+ << "==================================================" << endl
+ << " Selection " << endl
+ << "==================================================" << endl;
+
+ KIPI::ImageCollection selection = m_interface->currentSelection();
+
+ if ( !selection.isValid() ) {
+ kdDebug( 51000) << "No Selection!" << endl;
+ }
+ else {
+ KURL::List images = selection.images();
+
+ for( KURL::List::Iterator selIt = images.begin(); selIt != images.end(); ++selIt ) {
+ kdDebug( 51000 ) << *selIt << endl;
+ KIPI::ImageInfo info = m_interface->info( *selIt );
+ kdDebug( 51000 ) << "\ttitle: " << info.title() << endl;
+ if ( m_interface->hasFeature( KIPI::ImagesHasComments ) )
+ kdDebug( 51000 ) << "\tdescription: " << info.description() << endl;
+ }
+ }
+
+ // ================================================== Current Album
+
+ kdDebug( 51000 ) << endl
+ << "==================================================" << endl
+ << " Current Album " << endl
+ << "==================================================" << endl;
+
+ KIPI::ImageCollection album = m_interface->currentAlbum();
+
+ if ( !album.isValid() ) {
+ kdDebug( 51000 ) << "No album!" << endl;
+ }
+ else {
+ KURL::List images = album.images();
+
+ for( KURL::List::Iterator albumIt = images.begin(); albumIt != images.end(); ++albumIt ) {
+ kdDebug( 51000 ) << *albumIt << endl;
+ }
+
+ kdDebug( 51000 ) << "Album name: " << album.name() << endl;
+
+ if ( m_interface->hasFeature( KIPI::AlbumsHaveComments ) ) {
+ kdDebug( 51000 ) << "Album Comment: " << album.comment() << endl;
+ }
+ }
+}
+
+KIPI::Category Plugin_HelloWorld::category( KAction* action ) const
+{
+ if ( action == m_actionHelloWorld )
+ return KIPI::IMAGESPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMAGESPLUGIN; // no warning from compiler, please
+}
+
+#include "plugin_helloworld.moc"
diff --git a/kipi-plugins/helloworld/plugin_helloworld.h b/kipi-plugins/helloworld/plugin_helloworld.h
new file mode 100644
index 0000000..0af3b9e
--- /dev/null
+++ b/kipi-plugins/helloworld/plugin_helloworld.h
@@ -0,0 +1,58 @@
+/* ============================================================
+ * File : plugin_helloworld.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-03-10
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_HELLOWORLD_H
+#define PLUGIN_HELLOWORLD_H
+
+// LibKIPI includes
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+class Plugin_HelloWorld : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ // Notice the constructor
+ // takes three arguments QObject *parent (the parent of this object),
+ // const char* name (the name of this object) and
+ // const QStringList &args (the arguments passed).
+ Plugin_HelloWorld(QObject *parent,
+ const char* name,
+ const QStringList &args);
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+private slots:
+
+ //This is an example slot to which your action is connected.
+ void slotActivate();
+
+private:
+ KAction *m_actionHelloWorld;
+ KIPI::Interface *m_interface;
+};
+
+#endif
diff --git a/kipi-plugins/htmlexport/.vimrc b/kipi-plugins/htmlexport/.vimrc
new file mode 100644
index 0000000..a37475c
--- /dev/null
+++ b/kipi-plugins/htmlexport/.vimrc
@@ -0,0 +1,4 @@
+set tabstop=4
+set shiftwidth=4
+set noexpandtab
+set makeprg=unsermake
diff --git a/kipi-plugins/htmlexport/Makefile.am b/kipi-plugins/htmlexport/Makefile.am
new file mode 100644
index 0000000..e3254e3
--- /dev/null
+++ b/kipi-plugins/htmlexport/Makefile.am
@@ -0,0 +1,39 @@
+SUBDIRS = themes
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(all_includes) $(LIBXSLT_CFLAGS)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_htmlexport.la
+
+kipiplugin_htmlexport_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+kipiplugin_htmlexport_la_SOURCES = \
+ generator.cpp \
+ themepage.ui \
+ themeparameterspage.ui \
+ imagesettingspage.ui \
+ outputpage.ui \
+ plugin.cpp \
+ wizard.cpp \
+ theme.cpp \
+ htmlexportconfig.kcfgc \
+ abstractthemeparameter.cpp \
+ stringthemeparameter.cpp \
+ listthemeparameter.cpp \
+ colorthemeparameter.cpp \
+ intthemeparameter.cpp \
+ galleryinfo.cpp
+
+kde_kcfg_DATA = \
+ htmlexportconfig.kcfg
+
+kipiplugin_htmlexport_la_LIBADD = -lexslt -lxml2 $(LIBXSLT_LIBS) $(LIBKIPI_LIBS) $(LIB_KFILE) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+kipiplugin_htmlexport_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_htmlexport.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_htmlexport.pot
diff --git a/kipi-plugins/htmlexport/THEME_HOWTO b/kipi-plugins/htmlexport/THEME_HOWTO
new file mode 100644
index 0000000..689b9e5
--- /dev/null
+++ b/kipi-plugins/htmlexport/THEME_HOWTO
@@ -0,0 +1,293 @@
+# HTML Export Plugin Theme Howto
+
+The HTML export plugin can easily be themed to produce very different sites.
+This document explains how to create themes.
+
+*This document can be converted to HTML using
+[Markdown](http://www.daringfireball.net/projects/markdown).*
+
+## Getting started
+
+A theme is a folder which contains at least two files: a desktop file describing
+the theme and a template.xsl file to generate the HTML files.
+
+When the plugin is run it does the following:
+
+- Create an output folder
+- For each image collection:
+ - Create a folder
+ - Generate square thumbnails
+ - Generate full images
+ - Optionally copy original images
+- Copy the theme folder to the output folder
+- Generate an XML file describing the image collections: gallery.xml
+- Generate the HTML files by applying template.xsl to gallery.xml
+
+## Presentation of the desktop file
+
+The desktop file describes the theme. The information it contains is used in the
+theme selection page of the plugin.
+
+It's a .ini-style file and looks like this:
+
+ [Desktop Entry]
+ Name=Hello World
+ Comment=A demonstration theme
+
+ [X-HTMLExport Author]
+ Name=The Author
+ Url=http://example.com/themes/helloworld
+
+We use a desktop file format so that entries can be translated. If you look at
+the desktop file for one of the themes shipped with the plugin, you will find
+something like this:
+
+ [Desktop Entry]
+ Name=Simple
+ Name[br]=Eeun
+ Name[cs]=Jednoduchý
+ Name[cy]=Syml
+ Name[da]=Simpel
+ ...
+
+The nice thing is that when your theme get integrated into HTML export default
+themes, KDE translators will translate the desktop file for you.
+
+## Getting started: creating one theme from another
+
+The easiest way to get started is to copy one theme and modify it. Theme folders
+can be found in $KDEDIR/share/apps/kipiplugin_htmlexport/themes/, where $KDEDIR
+is the install folder of KDE on your machine (usually /usr or /opt/kde3).
+Writing in this folder requires root access, so we will not create our theme
+there, instead do the following:
+
+Create a theme folder in your home:
+
+ mkdir -p ~/.kde/share/apps/kipiplugin_htmlexport/themes/
+
+Cd to it:
+
+ cd ~/.kde/share/apps/kipiplugin_htmlexport/themes/
+
+Copy the "snow" theme to this folder, under a new name: "snow2":
+
+ cp -r $KDEDIR/share/apps/kipiplugin_htmlexport/themes/snow snow2
+
+Rename the desktop file accordingly:
+
+ cd snow2
+ mv snow.desktop snow2.desktop
+
+Edit "snow2.desktop": Remove all the `Name[...]` entries and replace `Name=Snow`
+with `Name=Snow 2`.
+
+You are done, you can now open your favorite KIPI enabled application and start the
+HTML Export plugin, the "Snow 2" theme should appear in the theme list.
+
+## Generating HTML files, template.xsl
+
+The template.xsl file is responsible for generating the HTML files from the
+gallery.xml file.
+
+gallery.xml looks like this:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <collections>
+ <collection>
+ <name>Name of first collection</name>
+ <fileName>collection_folder</fileName>
+ <image>
+ <title>Image Title</title>
+ <description>Image Description</description>
+ <full fileName="pict1279.jpeg" height="450" width="600"/>
+ <thumbnail fileName="thumb_pict1279.jpeg" height="80" width="80"/>
+ <!-- If there is an original image, you will get the 'original' tag -->
+ <original fileName="original_pict1279.jpeg" height="3000" width="4000"/>
+
+ </image>
+ <image>
+ <title>Image Title</title>
+ <description>Image Description</description>
+ <full fileName="pict1280.jpeg" height="450" width="600"/>
+ <thumbnail fileName="thumb_pict1280.jpeg" height="80" width="80"/>
+ <original fileName="original_pict1279.jpeg" height="3000" width="4000"/>
+ </image>
+ ...
+ </collection>
+
+ <collection>
+ <name>Name of second collection</name>
+ ...
+ </collection>
+ </collections>
+
+I won't explain XSLT here, you should be able to find the documentation you
+need on the web. I personally learned XSLT with the [XSLT tutorial from
+w3schools.com][1].
+
+It's worth noting nevertheless that you can make use of [EXSLT][2], a set of
+extensions to XSLT. In particular, the [`exslt:document` element][3] is
+extremely useful because it allows you to generate multiple documents from the
+same file.
+
+HTML Export Plugin imposes no constraint on the organisation of HTML files: you
+can generate one file per image, or only one per collection. One could imagine
+a theme which would only contains one HTML file and uses Javascript to show the
+different images, there is already one theme using frames, you can even
+generate CSS files on the fly if you want to.
+
+[1]: http://www.w3schools/xsl
+[2]: http://www.exslt.org
+[3]: http://www.exslt.org/exsl/elements/document
+
+### About translations
+
+You should not "hardcode" any text in the template, instead you should use the
+"i18n parameters". For example instead of using this:
+
+ <a href="previous">Previous</a>
+ | <a href="next">Next</a>
+
+Do this:
+
+ <a href="previous"><xsl:value-of select="$i18nPrevious"/></a>
+ | <a href="next"><xsl:value-of select="$i18nNext"/></a>
+
+It's quite a lot more verbose, but this way your user will get localized HTML
+output.
+
+If you want to use "i18n parameters" in attributes, do it like this:
+
+ <a href="previous" title="{$i18nPrevious}"><img src="previous.png"/></a>
+ | <a href="next" title="{$i18nNext}"><img src="next.png"/></a>
+
+For now, the available "i18n parameters" are:
+
+- i18nPrevious
+- i18nNext
+- i18nCollectionList
+- i18nOriginalImage
+- i18nUp
+
+*generated from 'grep \"i18n generator.cpp'*
+
+If you need other i18n parameters, let us know.
+
+## Images, CSS files and others
+
+You are free to use images, CSS files or other files in your theme: just put
+them in the theme folder and the plugin will copy them in the output folder.
+
+## Original images
+
+As explained before, if the user selects the option "include original images",
+the gallery.xml file will contain `<original />` tags. If this tag is present,
+the image page should contain a link to download the original image.
+
+Here is an example:
+
+ <xsl:if test="original/@fileName != ''">
+ <p>
+ <a href="{original/@fileName}"><xsl:value-of select="$i18nOriginalImage"/></a>
+ </p>
+ </xsl:if>
+
+## Going further, theme parameters
+
+You might want to provide a way for your user to customize your theme, for
+example you could provide a few alternative CSS files, or let the user
+customize the background color. This is easy to do.
+
+### Declaring a parameter
+
+First, you need to declare your parameter. Edit your desktop file and add
+something like this:
+
+ [X-HTMLExport Parameter bgColor]
+ Name=Background Color
+ Type=color
+ Default=#123456
+
+Now start the plugin and select your theme, after pressing next, you should
+see an option page with a color button initialized to the #123456 color.
+
+### Using the value of a parameter
+
+In template.xsl, you can get the value of your parameter like this:
+
+ <xsl:value-of select="$bgColor"/>
+
+To change the background color of the "body" tag, you would write something
+like this:
+
+ <body bgcolor="{$bgColor}">
+ ...
+ </body>
+
+### Parameter reference
+Here is a more complete description of the way to declare parameters:
+
+A parameter is declared by a section named "X-HTMLExport Parameter someName".
+`someName` should be replaced with the name you want to use in template.xsl.
+
+- The `Name` key defines the text which will be shown in the option page. Since
+this is a desktop file, it can be translated like the other keys.
+- The `Type` key defines the type of the parameter. At the time
+of this writing it can be one of:
+ - string
+ - color
+ - list
+ - int
+- The `Default` key defines the default value of the
+parameter.
+
+#### List parameter keys
+
+A list parameter lets the user select an item from a list. To declare the
+available items, you must use two sets of keys: `Value_N` and `Caption_N`,
+where N is the position of the item, starting from 0.
+
+`Value_N` is the internal value of the item. This is the value which will be
+set to the parameter.
+
+`Caption_N` is the displayed value of the item. This is the text which will
+be shown in the list.
+
+Here is an example: the "style" parameter from the "Simple" theme:
+
+ [X-HTMLExport Parameter style]
+ Name=Style
+ Type=list
+ Default=natural.css
+ Value_0=natural.css
+ Caption_0=Natural
+ Value_1=dark.css
+ Caption_1=Dark
+
+As you can see, the user will be able to choose either "Natural" or "Dark".
+Depending on the user choice, `<xsl:value-of select='$style'/>` will expand to
+either "natural.css" or "dark.css".
+
+#### Int parameter keys
+
+An int parameter lets the user select an integer using a spinbox. In addition
+to the default value, you can define the minimum and maximum values, using the
+`Min` and `Max` keys.
+
+Here is an example:
+
+ [X-HTMLExport Parameter size]
+ Name=Size
+ Type=int
+ Default=12
+ Min=4
+ Max=28
+
+## Final words
+
+This is the end of this howto, now is the time for you to get creative and
+design awesome themes!
+
+When you are done, do not hesitate to contact the kde-imaging mailing
+list (<kde-imaging@kde.org>). If you want to get your theme included in the
+official theme list, we need more themes!
diff --git a/kipi-plugins/htmlexport/TODO b/kipi-plugins/htmlexport/TODO
new file mode 100644
index 0000000..3285bcb
--- /dev/null
+++ b/kipi-plugins/htmlexport/TODO
@@ -0,0 +1,8 @@
+# Would be nice
+- Show screenshot alongside theme description
+- Support for remote URLs
+- Keep EXIF information
+- Make EXIF information available to themes
+- Implement an "update" mode which would only generate files for new or
+ modified images
+- Support for videos.
diff --git a/kipi-plugins/htmlexport/abstractthemeparameter.cpp b/kipi-plugins/htmlexport/abstractthemeparameter.cpp
new file mode 100644
index 0000000..7432ce8
--- /dev/null
+++ b/kipi-plugins/htmlexport/abstractthemeparameter.cpp
@@ -0,0 +1,70 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+// Self
+#include "abstractthemeparameter.h"
+
+// KDE
+#include <kconfigbase.h>
+
+static const char* NAME_KEY = "Name";
+static const char* DEFAULT_VALUE_KEY = "Default";
+
+namespace KIPIHTMLExport {
+
+struct AbstractThemeParameter::Private {
+ QCString mInternalName;
+ QString mName;
+ QString mDefaultValue;
+};
+
+AbstractThemeParameter::AbstractThemeParameter() {
+ d = new Private;
+}
+
+
+AbstractThemeParameter::~AbstractThemeParameter() {
+ delete d;
+}
+
+
+void AbstractThemeParameter::init(const QCString& internalName, const KConfigBase* configFile) {
+ d->mInternalName = internalName;
+ d->mName = configFile->readEntry(NAME_KEY);
+ d->mDefaultValue = configFile->readEntry(DEFAULT_VALUE_KEY);
+}
+
+
+QCString AbstractThemeParameter::internalName() const {
+ return d->mInternalName;
+}
+
+
+QString AbstractThemeParameter::name() const {
+ return d->mName;
+}
+
+
+QString AbstractThemeParameter::defaultValue() const {
+ return d->mDefaultValue;
+}
+
+
+} // namespace
diff --git a/kipi-plugins/htmlexport/abstractthemeparameter.h b/kipi-plugins/htmlexport/abstractthemeparameter.h
new file mode 100644
index 0000000..7c6393a
--- /dev/null
+++ b/kipi-plugins/htmlexport/abstractthemeparameter.h
@@ -0,0 +1,72 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef ABSTRACTTHEMEPARAMETER_H
+#define ABSTRACTTHEMEPARAMETER_H
+
+class QCString;
+class QString;
+class QWidget;
+class KConfigBase;
+
+namespace KIPIHTMLExport {
+
+/**
+ * Represents a theme parameter. For each type of parameter, one should inherit
+ * from this class and add the necessary code in the Theme class to load the
+ * new type.
+ */
+class AbstractThemeParameter {
+public:
+ AbstractThemeParameter();
+ virtual ~AbstractThemeParameter();
+
+ /**
+ * Reads theme parameters from configFile. Initializes the internalName,
+ * name and defaultValue fields.
+ */
+ virtual void init(const QCString& internalName, const KConfigBase* configFile);
+
+ QCString internalName() const;
+
+ QString name() const;
+
+ QString defaultValue() const;
+
+ /**
+ * This method should return a QWidget representing the parameter,
+ * initialized with value.
+ */
+ virtual QWidget* createWidget(QWidget* parent, const QString& value) const = 0;
+
+ /**
+ * The opposite of createWidget: given a widget previously created with
+ * createWidget, this method returns the current widget value.
+ */
+ virtual QString valueFromWidget(QWidget*) const = 0;
+
+private:
+ class Private;
+ Private* d;
+};
+
+} // namespace
+
+#endif /* ABSTRACTTHEMEPARAMETER_H */
diff --git a/kipi-plugins/htmlexport/colorthemeparameter.cpp b/kipi-plugins/htmlexport/colorthemeparameter.cpp
new file mode 100644
index 0000000..c7905be
--- /dev/null
+++ b/kipi-plugins/htmlexport/colorthemeparameter.cpp
@@ -0,0 +1,48 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+// Self
+#include "colorthemeparameter.h"
+
+// Qt
+
+// KDE
+#include <kcolorbutton.h>
+
+// Local
+
+namespace KIPIHTMLExport {
+
+
+QWidget* ColorThemeParameter::createWidget(QWidget* parent, const QString& value) const {
+ KColorButton* button = new KColorButton(parent);
+ QColor color(value);
+ button->setColor(color);
+ return button;
+}
+
+
+QString ColorThemeParameter::valueFromWidget(QWidget* widget) const {
+ KColorButton* button = static_cast<KColorButton*>(widget);
+ return button->color().name();
+}
+
+
+} // namespace
diff --git a/kipi-plugins/htmlexport/colorthemeparameter.h b/kipi-plugins/htmlexport/colorthemeparameter.h
new file mode 100644
index 0000000..6ba0577
--- /dev/null
+++ b/kipi-plugins/htmlexport/colorthemeparameter.h
@@ -0,0 +1,46 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef COLORTHEMEPARAMETER_H
+#define COLORTHEMEPARAMETER_H
+
+// Qt
+
+// KDE
+
+// Local
+#include "abstractthemeparameter.h"
+
+namespace KIPIHTMLExport {
+
+
+/**
+ * A theme parameter to select a color.
+ */
+class ColorThemeParameter : public AbstractThemeParameter {
+public:
+ virtual QWidget* createWidget(QWidget* parent, const QString& value) const;
+ virtual QString valueFromWidget(QWidget*) const;
+};
+
+
+} // namespace
+
+#endif /* COLORTHEMEPARAMETER_H */
diff --git a/kipi-plugins/htmlexport/galleryinfo.cpp b/kipi-plugins/htmlexport/galleryinfo.cpp
new file mode 100644
index 0000000..26c26a3
--- /dev/null
+++ b/kipi-plugins/htmlexport/galleryinfo.cpp
@@ -0,0 +1,61 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+// Self
+#include "galleryinfo.h"
+
+// Qt
+
+// KDE
+#include <kconfigbase.h>
+
+// Local
+
+namespace KIPIHTMLExport {
+
+static const char* THEME_GROUP_PREFIX="Theme ";
+
+QString GalleryInfo::getThemeParameterValue(
+ const QString& theme,
+ const QString& parameter,
+ const QString& defaultValue) const
+{
+ QString groupName = THEME_GROUP_PREFIX + theme;
+ KConfigGroupSaver saver(config(), groupName);
+ return config()->readEntry(parameter, defaultValue);
+}
+
+
+void GalleryInfo::setThemeParameterValue(
+ const QString& theme,
+ const QString& parameter,
+ const QString& value)
+{
+ // FIXME: This is hackish, but config() is const :'(
+ KConfig* localConfig = const_cast<KConfig*>(config());
+
+ QString groupName = THEME_GROUP_PREFIX + theme;
+ KConfigGroupSaver saver(localConfig, groupName);
+ return localConfig->writeEntry(parameter, value);
+}
+
+
+
+} // namespace
diff --git a/kipi-plugins/htmlexport/galleryinfo.h b/kipi-plugins/htmlexport/galleryinfo.h
new file mode 100644
index 0000000..f65e7bc
--- /dev/null
+++ b/kipi-plugins/htmlexport/galleryinfo.h
@@ -0,0 +1,97 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef GALLERYINFO_H
+#define GALLERYINFO_H
+
+// Qt
+#include <qvaluelist.h>
+
+// KDE
+#include <kurl.h>
+
+// KIPI
+#include <libkipi/imagecollection.h>
+
+// Local
+#include <theme.h>
+#include <htmlexportconfig.h>
+
+namespace KIPIHTMLExport {
+
+/**
+ * This class stores all the export settings. It is initialized by the
+ * Wizard and read by the Generator.
+ */
+class GalleryInfo : public Config {
+public:
+ /**
+ * Convenience method to get destURL as a KURL rather than a QString
+ */
+ KURL destKURL() const {
+ return KURL(destURL());
+ }
+
+ QString fullFormatString() const {
+ return getEnumString("fullFormat");
+ }
+
+ QString thumbnailFormatString() const {
+ return getEnumString("thumbnailFormat");
+ }
+
+ QValueList<KIPI::ImageCollection> mCollectionList;
+
+ QString getThemeParameterValue(const QString& theme, const QString& parameter, const QString& defaultValue) const;
+
+ void setThemeParameterValue(const QString& theme, const QString& parameter, const QString& value);
+
+private:
+
+ /**
+ * KConfigXT enums are mapped to ints.
+ * This method returns the string associated to the enum value.
+ */
+ QString getEnumString(const QString& itemName) const {
+ // findItem is not marked const :-(
+ GalleryInfo* that=const_cast<GalleryInfo*>(this);
+ KConfigSkeletonItem* tmp=that->findItem(itemName);
+
+ KConfigSkeleton::ItemEnum* item=dynamic_cast<KConfigSkeleton::ItemEnum*>(tmp);
+ Q_ASSERT(item);
+ if (!item) return QString::null;
+
+ int value=item->value();
+ QValueList<KConfigSkeleton::ItemEnum::Choice> lst=item->choices();
+ QValueList<KConfigSkeleton::ItemEnum::Choice>::ConstIterator
+ it=lst.begin(), end=lst.end();
+
+ for (int pos=0; it!=end; ++it, pos++) {
+ if (pos==value) {
+ return (*it).name;
+ }
+ }
+ return QString::null;
+ }
+};
+
+} // namespace
+
+#endif /* GALLERYINFO_H */
diff --git a/kipi-plugins/htmlexport/generator.cpp b/kipi-plugins/htmlexport/generator.cpp
new file mode 100644
index 0000000..4ae73a4
--- /dev/null
+++ b/kipi-plugins/htmlexport/generator.cpp
@@ -0,0 +1,532 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+// Self
+#include "generator.moc"
+
+// Qt
+#include <qdir.h>
+#include <qfile.h>
+#include <qpainter.h>
+#include <qregexp.h>
+
+// KDE
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+
+// KIPI
+#include <libkipi/batchprogressdialog.h>
+#include <libkipi/imageinfo.h>
+#include <libkipi/interface.h>
+
+// libxslt
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xslt.h>
+#include <libexslt/exslt.h>
+
+// Local
+#include "abstractthemeparameter.h"
+#include "galleryinfo.h"
+#include "theme.h"
+#include "xmlutils.h"
+
+namespace KIPIHTMLExport {
+
+
+typedef QMap<QCString,QCString> XsltParameterMap;
+
+
+/**
+ * Produce a web-friendly file name
+ */
+QString webifyFileName(QString fileName) {
+ fileName=fileName.lower();
+
+ // Remove potentially troublesome chars
+ fileName=fileName.replace(QRegExp("[^-0-9a-z]+"), "_");
+
+ return fileName;
+}
+
+
+/**
+ * This helper class is used to make sure we use unique filenames
+ */
+class UniqueNameHelper {
+public:
+ QString makeNameUnique(QString name) {
+ QString nameBase = name;
+ int count=2;
+ while (mList.findIndex(name)!=-1) {
+ name = nameBase + QString::number(count);
+ ++count;
+ };
+
+ mList.append(name);
+ return name;
+ }
+
+private:
+ QStringList mList;
+};
+
+
+/**
+ * Prepare an XSLT param, managing quote mess.
+ * abc => 'abc'
+ * a"bc => 'a"bc'
+ * a'bc => "a'bc"
+ * a"'bc => concat('a"', "'", 'bc')
+ */
+QCString makeXsltParam(const QString& txt) {
+ QString param;
+ static const char apos='\'';
+ static const char quote='"';
+
+ if (txt.find(apos)==-1) {
+ // First or second case: no apos
+ param= apos + txt + apos;
+
+ } else if (txt.find(quote)==-1) {
+ // Third case: only apos, no quote
+ param= quote + txt + quote;
+
+ } else {
+ // Forth case: both apos and quote :-(
+ QStringList lst=QStringList::split(apos, txt, true /*allowEmptyEntries*/);
+
+ QStringList::Iterator it=lst.begin(), end=lst.end();
+ param= "concat(";
+ param+= apos + *it + apos;
+ ++it;
+ for (;it!=end; ++it) {
+ param+= ", \"'\", ";
+ param+= apos + *it + apos;
+ }
+ param+= ")";
+ }
+ //kdDebug() << "param: " << txt << " => " << param << endl;
+ return param.utf8();
+}
+
+
+/**
+ * Genearate a square thumbnail from @fullImage of @size x @size pixels
+ */
+QImage generateSquareThumbnail(const QImage& fullImage, int size) {
+ QImage image = fullImage.smoothScale(size, size, QImage::ScaleMax);
+
+ if (image.width() == size && image.height() == size) {
+ return image;
+ }
+ QPixmap croppedPix(size, size);
+ QPainter painter(&croppedPix);
+
+ int sx=0, sy=0;
+ if (image.width()>size) {
+ sx=(image.width() - size)/2;
+ } else {
+ sy=(image.height() - size)/2;
+ }
+ painter.drawImage(0, 0, image, sx, sy, size, size);
+ painter.end();
+
+ return croppedPix.convertToImage();
+}
+
+
+struct Generator::Private {
+ KIPI::Interface* mInterface;
+ GalleryInfo* mInfo;
+ KIPI::BatchProgressDialog* mProgressDialog;
+ Theme::Ptr mTheme;
+
+ // State info
+ bool mWarnings;
+ QString mXMLFileName;
+ UniqueNameHelper mUniqueNameHelper;
+
+ bool init() {
+ mTheme=Theme::findByInternalName(mInfo->theme());
+ if (!mTheme) {
+ logError( i18n("Could not find theme in '%1'").arg(mInfo->theme()) );
+ return false;
+ }
+ return true;
+ }
+
+ bool copyTheme() {
+ mProgressDialog->addedAction(i18n("Copying theme"), KIPI::ProgressMessage);
+
+ KURL srcURL=KURL(mTheme->directory());
+
+ KURL destURL=mInfo->destKURL();
+ destURL.addPath(srcURL.filename());
+
+ if (QFile::exists(destURL.path())) {
+ KIO::NetAccess::del(destURL, mProgressDialog);
+ }
+ bool ok=KIO::NetAccess::dircopy(srcURL, destURL, mProgressDialog);
+ if (!ok) {
+ logError(i18n("Could not copy theme"));
+ return false;
+ }
+ return true;
+ }
+
+ bool writeDataToFile(const QByteArray& data, const QString& destPath) {
+ QFile destFile(destPath);
+ if (!destFile.open(IO_WriteOnly)) {
+ logWarning(i18n("Could not open file '%1' for writing").arg(destPath));
+ return false;
+ }
+ if (destFile.writeBlock(data) != (Q_LONG)data.size()) {
+ logWarning(i18n("Could not save image to file '%1'").arg(destPath));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Helper class for generateImageAndXMLForURL
+ */
+ void appendImageElementToXML(XMLWriter& xmlWriter, const QString& elementName, const QString& fileName, const QImage& image) {
+ XMLAttributeList attrList;
+ attrList.append("fileName", fileName);
+ attrList.append("width", image.width());
+ attrList.append("height", image.height());
+ XMLElement elem(xmlWriter, elementName, &attrList);
+ }
+
+
+ /**
+ * Generate images (full and thumbnail) for imageURL
+ * Fills xmlWriter with info about this image
+ */
+ void generateImageAndXMLForURL(XMLWriter& xmlWriter, const QString& destDir, const KURL& imageURL) {
+ KIPI::ImageInfo info=mInterface->info(imageURL);
+
+ // Load image
+ QString path=imageURL.path();
+ QFile imageFile(path);
+ if (!imageFile.open(IO_ReadOnly)) {
+ logWarning(i18n("Could not read image '%1'").arg(path));
+ return;
+ }
+
+ QString imageFormat = QImageIO::imageFormat(&imageFile);
+ if (imageFormat.isEmpty()) {
+ logWarning(i18n("Format of image '%1' is unknown").arg(path));
+ return;
+ }
+ imageFile.close();
+ imageFile.open(IO_ReadOnly);
+
+ QByteArray imageData = imageFile.readAll();
+ QImage originalImage;
+ if (!originalImage.loadFromData(imageData) ) {
+ logWarning(i18n("Error loading image '%1'").arg(path));
+ return;
+ }
+
+ // Process images
+ QImage fullImage = originalImage;
+ if (!mInfo->useOriginalImageAsFullImage()) {
+ if (mInfo->fullResize()) {
+ int size = mInfo->fullSize();
+ fullImage = fullImage.smoothScale(size, size, QImage::ScaleMin);
+ }
+ if (info.angle() != 0) {
+ QWMatrix matrix;
+ matrix.rotate(info.angle());
+ fullImage = fullImage.xForm(matrix);
+ }
+ }
+
+ QImage thumbnail = generateSquareThumbnail(fullImage, mInfo->thumbnailSize());
+
+ // Save images
+ QString baseFileName = webifyFileName(info.title());
+ baseFileName = mUniqueNameHelper.makeNameUnique(baseFileName);
+
+ // Save full
+ QString fullFileName;
+ if (mInfo->useOriginalImageAsFullImage()) {
+ fullFileName = baseFileName + "." + imageFormat.lower();
+ if (!writeDataToFile(imageData, destDir + "/" + fullFileName)) {
+ return;
+ }
+
+ } else {
+ fullFileName = baseFileName + "." + mInfo->fullFormatString().lower();
+ QString destPath = destDir + "/" + fullFileName;
+ if (!fullImage.save(destPath, mInfo->fullFormatString().ascii(), mInfo->fullQuality())) {
+ logWarning(i18n("Could not save image '%1' to '%2'").arg(path).arg(destPath));
+ return;
+ }
+ }
+
+ // Save original
+ QString originalFileName;
+ if (mInfo->copyOriginalImage()) {
+ originalFileName = "original_" + fullFileName;
+ if (!writeDataToFile(imageData, destDir + "/" + originalFileName)) {
+ return;
+ }
+ }
+
+ // Save thumbnail
+ QString thumbnailFileName = "thumb_" + baseFileName + "." + mInfo->thumbnailFormatString().lower();
+ QString destPath = destDir + "/" + thumbnailFileName;
+ if (!thumbnail.save(destPath, mInfo->thumbnailFormatString().ascii(), mInfo->thumbnailQuality())) {
+ logWarning(i18n("Could not save thumbnail for image '%1' to '%2'").arg(path).arg(destPath));
+ return;
+ }
+
+ // Write XML
+ XMLElement imageX(xmlWriter, "image");
+ xmlWriter.writeElement("title", info.title());
+ xmlWriter.writeElement("description", info.description());
+
+ appendImageElementToXML(xmlWriter, "full", fullFileName, fullImage);
+ appendImageElementToXML(xmlWriter, "thumbnail", thumbnailFileName, thumbnail);
+ if (mInfo->copyOriginalImage()) {
+ appendImageElementToXML(xmlWriter, "original", originalFileName, originalImage);
+ }
+ }
+
+
+ bool generateImagesAndXML() {
+ QString baseDestDir=mInfo->destKURL().path();
+ if (!createDir(baseDestDir)) return false;
+
+ mXMLFileName=baseDestDir + "/gallery.xml";
+ XMLWriter xmlWriter;
+ if (!xmlWriter.open(mXMLFileName)) {
+ logError(i18n("Could not create gallery.xml"));
+ return false;
+ }
+
+ XMLElement collectionsX(xmlWriter, "collections");
+
+ // Loop on collections
+ QValueList<KIPI::ImageCollection>::Iterator collectionIt=mInfo->mCollectionList.begin();
+ QValueList<KIPI::ImageCollection>::Iterator collectionEnd=mInfo->mCollectionList.end();
+ for (; collectionIt!=collectionEnd; ++collectionIt) {
+ KIPI::ImageCollection collection=*collectionIt;
+ logInfo( i18n("Generating files for \"%1\"").arg(collection.name()) );
+
+ QString collectionFileName = webifyFileName(collection.name());
+ QString destDir = baseDestDir + "/" + collectionFileName;
+ if (!createDir(destDir)) return false;
+
+ XMLElement collectionX(xmlWriter, "collection");
+ xmlWriter.writeElement("name", collection.name());
+ xmlWriter.writeElement("fileName", collectionFileName);
+
+ // Loop on image in collection
+ KURL::List imageList = collection.images();
+ KURL::List::Iterator it = imageList.begin();
+ KURL::List::Iterator end = imageList.end();
+
+ int pos = 1;
+ int count = imageList.count();
+ for (; it!=end; ++it, ++pos) {
+ mProgressDialog->setProgress(pos, count);
+ qApp->processEvents();
+ generateImageAndXMLForURL(xmlWriter, destDir, *it);
+ }
+
+ }
+ return true;
+ }
+
+
+ /**
+ * Add to map all the i18n parameters.
+ */
+ void addI18nParameters(XsltParameterMap& map) {
+ map["i18nPrevious"] = makeXsltParam(i18n("Previous"));
+ map["i18nNext"] = makeXsltParam(i18n("Next"));
+ map["i18nCollectionList"] = makeXsltParam(i18n("Collection List"));
+ map["i18nOriginalImage"] = makeXsltParam(i18n("Original Image"));
+ map["i18nUp"] = makeXsltParam(i18n("Go Up"));
+ }
+
+
+ /**
+ * Add to map all the theme parameters, as specified by the user.
+ */
+ void addThemeParameters(XsltParameterMap& map) {
+ Theme::ParameterList parameterList = mTheme->parameterList();
+ QString themeInternalName = mTheme->internalName();
+ Theme::ParameterList::ConstIterator
+ it = parameterList.begin(),
+ end = parameterList.end();
+ for (; it!=end; ++it) {
+ AbstractThemeParameter* themeParameter = *it;
+ QCString internalName = themeParameter->internalName();
+ QString value = mInfo->getThemeParameterValue(
+ themeInternalName,
+ internalName,
+ themeParameter->defaultValue());
+
+ map[internalName] = makeXsltParam(value);
+ }
+ }
+
+
+ bool generateHTML() {
+ logInfo(i18n("Generating HTML files"));
+
+ QString xsltFileName=mTheme->directory() + "/template.xsl";
+ CWrapper<xsltStylesheetPtr, xsltFreeStylesheet> xslt= xsltParseStylesheetFile( (const xmlChar*) xsltFileName.local8Bit().data() );
+
+ if (!xslt) {
+ logError(i18n("Could not load XSL file '%1'").arg(xsltFileName));
+ return false;
+ }
+
+ CWrapper<xmlDocPtr, xmlFreeDoc> xmlGallery=xmlParseFile( mXMLFileName.local8Bit().data() );
+ if (!xmlGallery) {
+ logError(i18n("Could not load XML file '%1'").arg(mXMLFileName));
+ return false;
+ }
+
+ // Prepare parameters
+ XsltParameterMap map;
+ addI18nParameters(map);
+ addThemeParameters(map);
+
+ const char** params=new const char*[map.size()*2+1];
+
+ XsltParameterMap::Iterator it=map.begin(), end=map.end();
+ const char** ptr=params;
+ for (;it!=end; ++it) {
+ *ptr=it.key().data();
+ ++ptr;
+ *ptr=it.data().data();
+ ++ptr;
+ }
+ *ptr=0;
+
+ // Move to the destination dir, so that external documents get correctly
+ // produced
+ QString oldCD=QDir::currentDirPath();
+ QDir::setCurrent(mInfo->destKURL().path());
+
+ CWrapper<xmlDocPtr, xmlFreeDoc> xmlOutput= xsltApplyStylesheet(xslt, xmlGallery, params);
+
+ QDir::setCurrent(oldCD);
+ //delete []params;
+
+ if (!xmlOutput) {
+ logError(i18n("Error processing XML file"));
+ return false;
+ }
+
+ QString destFileName=mInfo->destKURL().path() + "/index.html";
+ FILE* file=fopen(destFileName.local8Bit().data(), "w");
+ if (!file) {
+ logError(i18n("Could not open '%1' for writing").arg(destFileName));
+ return false;
+ }
+ xsltSaveResultToFile(file, xmlOutput, xslt);
+ fclose(file);
+
+ return true;
+ }
+
+
+ bool createDir(const QString& dirName) {
+ QStringList parts = QStringList::split('/', dirName);
+ QStringList::ConstIterator it = parts.begin(), end = parts.end();
+ QDir dir = QDir::root();
+ for( ;it!=end; ++it) {
+ QString part = *it;
+ if (!dir.exists(part)) {
+ if (!dir.mkdir(part)) {
+ logError(i18n("Could not create folder '%1' in '%2'").arg(part).arg(dir.absPath()));
+ return false;
+ }
+ }
+ dir.cd(part);
+ }
+ return true;
+ }
+
+
+ void logInfo(const QString& msg) {
+ mProgressDialog->addedAction(msg, KIPI::ProgressMessage);
+ }
+
+ void logError(const QString& msg) {
+ mProgressDialog->addedAction(msg, KIPI::ErrorMessage);
+ }
+
+ void logWarning(const QString& msg) {
+ mProgressDialog->addedAction(msg, KIPI::WarningMessage);
+ mWarnings=true;
+ }
+};
+
+Generator::Generator(KIPI::Interface* interface, GalleryInfo* info, KIPI::BatchProgressDialog* progressDialog)
+: QObject() {
+ d=new Private;
+ d->mInterface=interface;
+ d->mInfo=info;
+ d->mProgressDialog=progressDialog;
+ d->mWarnings=false;
+}
+
+
+Generator::~Generator() {
+ delete d;
+}
+
+
+bool Generator::run() {
+ if (!d->init()) return false;
+
+ QString destDir=d->mInfo->destKURL().path();
+ if (!d->createDir(destDir)) return false;
+
+ if (!d->copyTheme()) return false;
+
+ if (!d->generateImagesAndXML()) return false;
+
+ exsltRegisterAll();
+ bool result=d->generateHTML();
+ xsltCleanupGlobals();
+ xmlCleanupParser();
+ return result;
+}
+
+bool Generator::warnings() const {
+ return d->mWarnings;
+}
+
+} // namespace
diff --git a/kipi-plugins/htmlexport/generator.h b/kipi-plugins/htmlexport/generator.h
new file mode 100644
index 0000000..a85f99c
--- /dev/null
+++ b/kipi-plugins/htmlexport/generator.h
@@ -0,0 +1,56 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public 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 GENERATOR_H
+#define GENERATOR_H
+
+#include <qobject.h>
+
+namespace KIPI {
+class BatchProgressDialog;
+class Interface;
+}
+
+namespace KIPIHTMLExport {
+
+class GalleryInfo;
+
+
+/**
+ * This class is responsible for generating the HTML and scaling the images
+ * according to the settings specified by the user.
+ */
+class Generator : public QObject {
+Q_OBJECT
+public:
+ Generator(KIPI::Interface*, GalleryInfo*, KIPI::BatchProgressDialog*);
+ ~Generator();
+ bool run();
+ bool warnings() const;
+
+private:
+ struct Private;
+ Private* d;
+};
+
+
+} // namespace
+
+#endif /* GENERATOR_H */
diff --git a/kipi-plugins/htmlexport/htmlexportconfig.kcfg b/kipi-plugins/htmlexport/htmlexportconfig.kcfg
new file mode 100644
index 0000000..0deb014
--- /dev/null
+++ b/kipi-plugins/htmlexport/htmlexportconfig.kcfg
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.dtd">
+<kcfg>
+ <kcfgfile name="kipihtmlexportrc"/>
+ <group name="general">
+ <entry name="theme" type="String">
+ </entry>
+
+ <entry name="useOriginalImageAsFullImage" type="Bool">
+ <default>false</default>
+ </entry>
+
+ <entry name="fullResize" type="Bool">
+ <default>true</default>
+ </entry>
+
+ <entry name="fullSize" type="Int">
+ <default>1024</default>
+ </entry>
+
+ <entry name="fullFormat" type="Enum">
+ <!-- choices should match .ui file -->
+ <choices>
+ <choice name="JPEG"/>
+ <choice name="PNG"/>
+ </choices>
+ <default>JPEG</default>
+ </entry>
+
+ <entry name="fullQuality" type="Int">
+ <default>80</default>
+ </entry>
+
+ <entry name="copyOriginalImage" type="Bool">
+ <default>false</default>
+ </entry>
+
+ <entry name="thumbnailSize" type="Int">
+ <default>120</default>
+ </entry>
+
+ <entry name="thumbnailFormat" type="Enum">
+ <!-- choices should match .ui file -->
+ <choices>
+ <choice name="JPEG"/>
+ <choice name="PNG"/>
+ </choices>
+ <default>JPEG</default>
+ </entry>
+
+ <entry name="thumbnailQuality" type="Int">
+ <default>80</default>
+ </entry>
+
+ <entry name="destURL" type="String">
+ </entry>
+
+ <entry name="openInBrowser" type="Bool">
+ <default>true</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kipi-plugins/htmlexport/htmlexportconfig.kcfgc b/kipi-plugins/htmlexport/htmlexportconfig.kcfgc
new file mode 100644
index 0000000..b4ced5c
--- /dev/null
+++ b/kipi-plugins/htmlexport/htmlexportconfig.kcfgc
@@ -0,0 +1,5 @@
+File=htmlexportconfig.kcfg
+ClassName=Config
+NameSpace=KIPIHTMLExport
+Singleton=false
+Mutators=true
diff --git a/kipi-plugins/htmlexport/imagesettingspage.ui b/kipi-plugins/htmlexport/imagesettingspage.ui
new file mode 100644
index 0000000..e15009c
--- /dev/null
+++ b/kipi-plugins/htmlexport/imagesettingspage.ui
@@ -0,0 +1,456 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ImageSettingsPage</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ImageSettingsPage</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>381</width>
+ <height>310</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>ImageSettingsPage</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Full Image</string>
+ </property>
+ </widget>
+ <spacer row="1" column="3">
+ <property name="name">
+ <cstring>spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>58</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer2_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="5" column="2">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>104</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="3" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Thumbnail</string>
+ </property>
+ </widget>
+ <spacer row="4" column="0">
+ <property name="name">
+ <cstring>spacer2_2_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer4_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QButtonGroup" row="1" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>kcfg_useOriginalImageAsFullImage</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>radioButton3</cstring>
+ </property>
+ <property name="text">
+ <string>Save image</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QFrame" row="1" column="1">
+ <property name="name">
+ <cstring>frame6</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>kcfg_fullResize</cstring>
+ </property>
+ <property name="text">
+ <string>Max size:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2_2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Format:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_fullFormat</cstring>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="0" column="4">
+ <property name="name">
+ <cstring>kcfg_fullQuality</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>JPEG</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>PNG</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>kcfg_fullFormat</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="3">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Quality:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_fullQuality</cstring>
+ </property>
+ </widget>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_fullSize</cstring>
+ </property>
+ <property name="maxValue">
+ <number>9999</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>800</number>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="5">
+ <property name="name">
+ <cstring>kcfg_copyOriginalImage</cstring>
+ </property>
+ <property name="text">
+ <string>Include full-size original images for download</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer2_2_2_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer4_3_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>19</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QRadioButton" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>radioButton4</cstring>
+ </property>
+ <property name="text">
+ <string>Use original image</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="4" column="3">
+ <property name="name">
+ <cstring>spacer2_2_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget" row="4" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_thumbnailSize</cstring>
+ </property>
+ <property name="maxValue">
+ <number>9999</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>160</number>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="0" column="4">
+ <property name="name">
+ <cstring>kcfg_thumbnailQuality</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="3">
+ <property name="name">
+ <cstring>textLabel4_2</cstring>
+ </property>
+ <property name="text">
+ <string>Quality:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_thumbnailQuality</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Format:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_thumbnailFormat</cstring>
+ </property>
+ </widget>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer4_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>JPEG</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>PNG</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>kcfg_thumbnailFormat</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Size:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_thumbnailSize</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>kcfg_fullResize</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>kcfg_fullSize</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radioButton3</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>frame6</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kipi-plugins/htmlexport/intthemeparameter.cpp b/kipi-plugins/htmlexport/intthemeparameter.cpp
new file mode 100644
index 0000000..710f040
--- /dev/null
+++ b/kipi-plugins/htmlexport/intthemeparameter.cpp
@@ -0,0 +1,77 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+// Self
+#include "intthemeparameter.h"
+
+// Qt
+#include <qspinbox.h>
+
+// KDE
+#include <kconfigbase.h>
+
+// Local
+
+static const char* MIN_VALUE_KEY = "Min";
+static const char* MAX_VALUE_KEY = "Max";
+
+namespace KIPIHTMLExport {
+
+
+struct IntThemeParameter::Private {
+ int mMinValue;
+ int mMaxValue;
+};
+
+
+IntThemeParameter::IntThemeParameter() {
+ d = new Private;
+}
+
+
+IntThemeParameter::~IntThemeParameter() {
+ delete d;
+}
+
+
+void IntThemeParameter::init(const QCString& internalName, const KConfigBase* configFile) {
+ AbstractThemeParameter::init(internalName, configFile);
+
+ d->mMinValue = configFile->readNumEntry(MIN_VALUE_KEY, 0);
+ d->mMaxValue = configFile->readNumEntry(MAX_VALUE_KEY, 99999);
+}
+
+
+QWidget* IntThemeParameter::createWidget(QWidget* parent, const QString& value) const {
+ QSpinBox* spinBox = new QSpinBox(parent);
+ spinBox->setValue(value.toInt());
+ spinBox->setMinValue(d->mMinValue);
+ spinBox->setMaxValue(d->mMaxValue);
+ return spinBox;
+}
+
+
+QString IntThemeParameter::valueFromWidget(QWidget* widget) const {
+ QSpinBox* spinBox = static_cast<QSpinBox*>(widget);
+ return QString::number(spinBox->value());
+}
+
+
+} // namespace
diff --git a/kipi-plugins/htmlexport/intthemeparameter.h b/kipi-plugins/htmlexport/intthemeparameter.h
new file mode 100644
index 0000000..4db06d1
--- /dev/null
+++ b/kipi-plugins/htmlexport/intthemeparameter.h
@@ -0,0 +1,54 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef INTTHEMEPARAMETER_H
+#define INTTHEMEPARAMETER_H
+
+// Qt
+
+// KDE
+
+// Local
+#include "abstractthemeparameter.h"
+
+namespace KIPIHTMLExport {
+
+
+/**
+ * A theme parameter to select an integer value.
+ */
+class IntThemeParameter : public AbstractThemeParameter {
+public:
+ IntThemeParameter();
+ ~IntThemeParameter();
+
+ virtual void init(const QCString& internalName, const KConfigBase* configFile);
+ virtual QWidget* createWidget(QWidget* parent, const QString& value) const;
+ virtual QString valueFromWidget(QWidget*) const;
+
+private:
+ class Private;
+ Private* d;
+};
+
+
+} // namespace
+
+#endif /* INTTHEMEPARAMETER_H */
diff --git a/kipi-plugins/htmlexport/kipiplugin_htmlexport.desktop b/kipi-plugins/htmlexport/kipiplugin_htmlexport.desktop
new file mode 100644
index 0000000..e9963d2
--- /dev/null
+++ b/kipi-plugins/htmlexport/kipiplugin_htmlexport.desktop
@@ -0,0 +1,57 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=HTML Gallery
+Name[br]=Garidell HTML
+Name[ca]=Galeria HTML
+Name[cs]=HTML galerie obrázků
+Name[da]=HTML-galleri
+Name[de]=HTML-Galerie
+Name[el]=Συλλογή HTML
+Name[es]=Galería HTML
+Name[et]=HTML-galerii
+Name[fi]=HTML-galleria
+Name[ga]=Gailearaí HTML
+Name[gl]=Galeria HTML
+Name[it]=Galleria HTML
+Name[ja]=HTML ギャラリー
+Name[nds]=HTML-Galerie
+Name[nl]=Webgalerij
+Name[pa]=HTML ਗੈਲਰੀ
+Name[pl]=Galeria HTML
+Name[pt]=Galeria em HTML
+Name[sr]=HTML галерија
+Name[sr@Latn]=HTML galerija
+Name[sv]=HTML-galleri
+Name[xx]=xxHTML Galleryxx
+Name[zh_CN]=HTML 图库
+Comment=KIPI HTML Gallery Export Plugin
+Comment[ca]=Connector del KIPI exportar una galeria a HTML
+Comment[cs]=KIPI modul pro export galerie obrázků
+Comment[da]=KIPI-plugin: Eksport af HTML-galleri
+Comment[de]=Ein KIPI-Modul zum Exportieren einer Galerie
+Comment[el]=Πρόσθετο του KIPI για εξαγωγή HTML συλλογής
+Comment[es]=Complemento de KIPI para exportar galerías en HTML
+Comment[et]=KIPI HTML-galerii ekspordiplugin
+Comment[fi]=Kipi-liitännäinen webbigallerian luontia varten
+Comment[fr]=Module externe KIPI pour créer une galerie web
+Comment[gl]=Plugin de KIPI para Exportar a unha Galeria HTML
+Comment[is]=KIPI íforrit fyrir HTML-útflutning í á vef
+Comment[it]=Plugin di esportazione HTML di gallerie di KIPI
+Comment[ja]=Kipi HTML ギャラリーエクスポートプラグイン
+Comment[nds]=KIPI-Moduul för't Exporteren vun en HTML-Galerie
+Comment[nl]=KIPI-plugin voor het exporteren naar HTML-afbeeldingsgalerijen
+Comment[pa]=KIPI HTML ਗੈਲਰੀ ਨਿਰਯਾਤ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Eksport do galerii HTML
+Comment[pt]='Plugin' do KIPI de Exportação para Galeria em HTML
+Comment[pt_BR]=Plugin para Exportação de Galeria HTML do KIPI
+Comment[sr]=KIPI прикључак за извоз у HTML галерију
+Comment[sr@Latn]=KIPI priključak za izvoz u HTML galeriju
+Comment[sv]=KIPI-insticksprogram: Export av HTML-galleri
+Comment[tg]=Модули воридкунандаи намоишгари KIPI HTML
+Comment[tr]=KIPI HTML Galeri Aktarma Eklentisi
+Comment[xx]=xxKIPI HTML Gallery Export Pluginxx
+Comment[zh_CN]=KIPI HTML 图库导出插件
+Icon=
+ServiceTypes=KIPI/Plugin
+Type=Service
+X-KDE-Library=kipiplugin_htmlexport
diff --git a/kipi-plugins/htmlexport/listthemeparameter.cpp b/kipi-plugins/htmlexport/listthemeparameter.cpp
new file mode 100644
index 0000000..234f427
--- /dev/null
+++ b/kipi-plugins/htmlexport/listthemeparameter.cpp
@@ -0,0 +1,91 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+// Self
+#include "listthemeparameter.h"
+
+// Qt
+#include <qcombobox.h>
+
+// KDE
+#include <kconfigbase.h>
+
+namespace KIPIHTMLExport {
+
+static const char* ITEM_VALUE_KEY = "Value_";
+static const char* ITEM_CAPTION_KEY = "Caption_";
+
+struct ListThemeParameter::Private {
+ QStringList mOrderedValueList;
+ QMap<QString, QString> mContentMap;
+};
+
+ListThemeParameter::ListThemeParameter() {
+ d = new Private;
+}
+
+ListThemeParameter::~ListThemeParameter() {
+ delete d;
+}
+
+void ListThemeParameter::init(const QCString& internalName, const KConfigBase* configFile) {
+ AbstractThemeParameter::init(internalName, configFile);
+
+ for (int pos=0;; ++pos) {
+ QString valueKey = QString("%1%2").arg(ITEM_VALUE_KEY).arg(pos);
+ QString captionKey = QString("%1%2").arg(ITEM_CAPTION_KEY).arg(pos);
+ if (!configFile->hasKey(valueKey) || !configFile->hasKey(captionKey)) {
+ break;
+ }
+
+ QString value = configFile->readEntry(valueKey);
+ QString caption = configFile->readEntry(captionKey);
+
+ d->mOrderedValueList << value;
+ d->mContentMap[value] = caption;
+ }
+}
+
+QWidget* ListThemeParameter::createWidget(QWidget* parent, const QString& widgetDefaultValue) const {
+ QComboBox* comboBox = new QComboBox(parent);
+
+ QStringList::ConstIterator
+ it = d->mOrderedValueList.begin(),
+ end = d->mOrderedValueList.end();
+ for (;it!=end; ++it) {
+ QString value = *it;
+ QString caption = d->mContentMap[value];
+ comboBox->insertItem(caption);
+ if (value == widgetDefaultValue) {
+ comboBox->setCurrentItem(comboBox->count() - 1);
+ }
+ }
+
+ return comboBox;
+}
+
+QString ListThemeParameter::valueFromWidget(QWidget* widget) const {
+ Q_ASSERT(widget);
+ QComboBox* comboBox = static_cast<QComboBox*>(widget);
+ return d->mOrderedValueList[comboBox->currentItem()];
+}
+
+} // namespace
+
diff --git a/kipi-plugins/htmlexport/listthemeparameter.h b/kipi-plugins/htmlexport/listthemeparameter.h
new file mode 100644
index 0000000..10c5939
--- /dev/null
+++ b/kipi-plugins/htmlexport/listthemeparameter.h
@@ -0,0 +1,48 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef LISTTHEMEPARAMETER_H
+#define LISTTHEMEPARAMETER_H
+
+// Local
+#include "abstractthemeparameter.h"
+
+namespace KIPIHTMLExport {
+
+
+/**
+ * A theme parameter to select a value in a list
+ */
+class ListThemeParameter : public AbstractThemeParameter {
+public:
+ ListThemeParameter();
+ ~ListThemeParameter();
+
+ virtual void init(const QCString& internalName, const KConfigBase* configFile);
+ virtual QWidget* createWidget(QWidget* parent, const QString& value) const;
+ virtual QString valueFromWidget(QWidget*) const;
+
+private:
+ struct Private;
+ Private* d;
+};
+
+} // namespace
+#endif /* LISTTHEMEPARAMETER_H */
diff --git a/kipi-plugins/htmlexport/outputpage.ui b/kipi-plugins/htmlexport/outputpage.ui
new file mode 100644
index 0000000..4c1f6f6
--- /dev/null
+++ b/kipi-plugins/htmlexport/outputpage.ui
@@ -0,0 +1,83 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>OutputPage</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>OutputPage</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>347</width>
+ <height>192</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Destination folder:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_destURL</cstring>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>kcfg_destURL</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_openInBrowser</cstring>
+ </property>
+ <property name="text">
+ <string>Open in browser</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>51</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kipi-plugins/htmlexport/plugin.cpp b/kipi-plugins/htmlexport/plugin.cpp
new file mode 100644
index 0000000..7b95aab
--- /dev/null
+++ b/kipi-plugins/htmlexport/plugin.cpp
@@ -0,0 +1,112 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+// Self
+#include "plugin.moc"
+
+// KDE
+#include <kaction.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <krun.h>
+
+// KIPI
+#include <libkipi/batchprogressdialog.h>
+
+// Local
+#include "galleryinfo.h"
+#include "generator.h"
+#include "wizard.h"
+
+typedef KGenericFactory<KIPIHTMLExport::Plugin> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_htmlexport, Factory("kipiplugin_htmlexport"))
+
+namespace KIPIHTMLExport {
+
+
+struct Plugin::Private {
+ KAction* mAction;
+};
+
+
+Plugin::Plugin(QObject *parent, const char*, const QStringList&)
+: KIPI::Plugin(Factory::instance(), parent, "HTMLExport")
+{
+ d=new Private;
+ d->mAction=0;
+}
+
+
+Plugin::~Plugin() {
+ delete d;
+}
+
+
+void Plugin::setup( QWidget* widget ) {
+ KIPI::Plugin::setup( widget );
+ d->mAction = new KAction(i18n("HTML Gallery..."), "www", 0,
+ this, SLOT(slotActivate()),
+ actionCollection(), "htmlexport");
+ addAction(d->mAction);
+}
+
+
+void Plugin::slotActivate() {
+ KIPI::Interface* interface = dynamic_cast< KIPI::Interface* >( parent() );
+ Q_ASSERT(interface);
+
+ GalleryInfo info;
+ info.readConfig();
+ QWidget* parent=KApplication::kApplication()->mainWidget();
+ Wizard wizard(parent, interface, &info);
+ if (wizard.exec()==QDialog::Rejected) return;
+ info.writeConfig();
+
+ KIPI::BatchProgressDialog* progressDialog=new KIPI::BatchProgressDialog(parent, i18n("Generating gallery..."));
+
+ Generator generator(interface, &info, progressDialog);
+ progressDialog->show();
+ if (!generator.run()) return;
+
+ if (!generator.warnings()) {
+ progressDialog->close();
+ }
+
+ if (info.openInBrowser()) {
+ KURL url=info.destKURL();
+ url.addPath("index.html");
+ KRun::runURL(url, "text/html");
+ }
+}
+
+
+KIPI::Category Plugin::category(KAction* action) const {
+ if (action == d->mAction) {
+ return KIPI::EXPORTPLUGIN;
+ }
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::EXPORTPLUGIN; // no warning from compiler, please
+}
+
+} // namespace
diff --git a/kipi-plugins/htmlexport/plugin.h b/kipi-plugins/htmlexport/plugin.h
new file mode 100644
index 0000000..9327ea0
--- /dev/null
+++ b/kipi-plugins/htmlexport/plugin.h
@@ -0,0 +1,55 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef PLUGIN_H
+#define PLUGIN_H
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+namespace KIPIHTMLExport {
+
+
+/**
+ * Implementation of the KIPI::Plugin abstract class for HTMLExport.
+ */
+class Plugin : public KIPI::Plugin {
+ Q_OBJECT
+
+public:
+ Plugin(QObject *parent, const char* name, const QStringList &args);
+ virtual ~Plugin();
+
+ KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+private slots:
+ void slotActivate();
+
+private:
+ struct Private;
+ Private* d;
+};
+
+} // namespace
+
+
+#endif // PLUGIN_H
diff --git a/kipi-plugins/htmlexport/stringthemeparameter.cpp b/kipi-plugins/htmlexport/stringthemeparameter.cpp
new file mode 100644
index 0000000..fb18fc4
--- /dev/null
+++ b/kipi-plugins/htmlexport/stringthemeparameter.cpp
@@ -0,0 +1,45 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+// Self
+#include "stringthemeparameter.h"
+
+// Qt
+#include <qlineedit.h>
+
+// KDE
+#include <kconfigbase.h>
+
+namespace KIPIHTMLExport {
+
+QWidget* StringThemeParameter::createWidget(QWidget* parent, const QString& value) const {
+ QLineEdit* edit = new QLineEdit(parent);
+ edit->setText(value);
+
+ return edit;
+}
+
+QString StringThemeParameter::valueFromWidget(QWidget* widget) const {
+ Q_ASSERT(widget);
+ QLineEdit* edit = static_cast<QLineEdit*>(widget);
+ return edit->text();
+}
+
+} // namespace
diff --git a/kipi-plugins/htmlexport/stringthemeparameter.h b/kipi-plugins/htmlexport/stringthemeparameter.h
new file mode 100644
index 0000000..89d661a
--- /dev/null
+++ b/kipi-plugins/htmlexport/stringthemeparameter.h
@@ -0,0 +1,40 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef STRINGTHEMEPARAMETER_H
+#define STRINGTHEMEPARAMETER_H
+
+// Local
+#include "abstractthemeparameter.h"
+
+namespace KIPIHTMLExport {
+
+/**
+ * A theme parameter which let the user enter a string.
+ */
+class StringThemeParameter : public AbstractThemeParameter {
+public:
+ virtual QWidget* createWidget(QWidget* parent, const QString& value) const;
+ virtual QString valueFromWidget(QWidget*) const;
+};
+
+} // namespace
+
+#endif /* STRINGTHEMEPARAMETER_H */
diff --git a/kipi-plugins/htmlexport/theme.cpp b/kipi-plugins/htmlexport/theme.cpp
new file mode 100644
index 0000000..ee70a9b
--- /dev/null
+++ b/kipi-plugins/htmlexport/theme.cpp
@@ -0,0 +1,211 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+
+// Self
+#include "theme.h"
+
+// Qt
+#include <qfile.h>
+#include <qtextstream.h>
+
+// KDE
+#include <kdebug.h>
+#include <kdesktopfile.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+
+// Local
+#include "colorthemeparameter.h"
+#include "intthemeparameter.h"
+#include "listthemeparameter.h"
+#include "stringthemeparameter.h"
+
+namespace KIPIHTMLExport {
+
+
+static const char* AUTHOR_GROUP = "X-HTMLExport Author";
+static const char* PARAMETER_GROUP_PREFIX = "X-HTMLExport Parameter ";
+static const char* PARAMETER_TYPE_KEY = "Type";
+
+static const char* STRING_PARAMETER_TYPE = "string";
+static const char* LIST_PARAMETER_TYPE = "list";
+static const char* COLOR_PARAMETER_TYPE = "color";
+static const char* INT_PARAMETER_TYPE = "int";
+
+static Theme::List sList;
+
+
+struct Theme::Private {
+ KDesktopFile* mDesktopFile;
+ KURL mURL;
+ ParameterList mParameterList;
+
+ /**
+ * Return the list of parameters defined in the desktop file. We need to
+ * parse the file ourself to preserve parameter order.
+ */
+ QStringList readParameterNameList(const QString& desktopFileName) {
+ QStringList list;
+ QFile file(desktopFileName);
+ if (!file.open(IO_ReadOnly)) {
+ return QStringList();
+ }
+
+ QTextStream stream(&file);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ QString prefix = QString("[") + PARAMETER_GROUP_PREFIX;
+ while (!stream.atEnd()) {
+ QString line = stream.readLine();
+ line = line.stripWhiteSpace();
+ if (!line.startsWith(prefix)) {
+ continue;
+ }
+ // Remove opening bracket and group prefix
+ line = line.mid(prefix.length());
+
+ // Remove closing bracket
+ line.truncate(line.length() - 1);
+
+ list.append(line);
+ }
+
+ return list;
+ }
+
+ void init(const QString& desktopFileName) {
+ mDesktopFile=new KDesktopFile(desktopFileName, true /*read only*/);
+ mURL.setPath(desktopFileName);
+
+ QStringList parameterNameList = readParameterNameList(desktopFileName);
+ readParameters(parameterNameList);
+ }
+
+ void readParameters(const QStringList& list) {
+ QStringList::ConstIterator it=list.begin(), end=list.end();
+ for (;it!=end; ++it) {
+ QString group = PARAMETER_GROUP_PREFIX + *it;
+ QCString internalName = (*it).utf8();
+
+ KConfigGroupSaver saver(mDesktopFile, group);
+ QString type = mDesktopFile->readEntry(PARAMETER_TYPE_KEY);
+ AbstractThemeParameter* parameter;
+ if (type == STRING_PARAMETER_TYPE) {
+ parameter = new StringThemeParameter();
+ } else if (type == LIST_PARAMETER_TYPE) {
+ parameter = new ListThemeParameter();
+ } else if (type == COLOR_PARAMETER_TYPE) {
+ parameter = new ColorThemeParameter();
+ } else if (type == INT_PARAMETER_TYPE) {
+ parameter = new IntThemeParameter();
+ } else {
+ kdWarning() << "Parameter '" << internalName << "' has unknown type '" << type << "'. Falling back to string type\n";
+ parameter = new StringThemeParameter();
+ }
+ parameter->init(internalName, mDesktopFile);
+ mParameterList << parameter;
+ }
+ }
+};
+
+
+Theme::Theme() {
+ d=new Private;
+}
+
+
+Theme::~Theme() {
+ delete d->mDesktopFile;
+ delete d;
+}
+
+
+const Theme::List& Theme::getList() {
+ if (sList.isEmpty()) {
+ QStringList internalNameList;
+ QStringList list=KGlobal::instance()->dirs()->findAllResources("data", "kipiplugin_htmlexport/themes/*/*.desktop");
+ QStringList::Iterator it=list.begin(), end=list.end();
+ for (;it!=end; ++it) {
+ Theme* theme=new Theme;
+ theme->d->init(*it);
+ QString internalName = theme->internalName();
+ if (!internalNameList.contains(internalName)) {
+ sList << Theme::Ptr(theme);
+ internalNameList << internalName;
+ }
+ }
+ }
+ return sList;
+}
+
+
+Theme::Ptr Theme::findByInternalName(const QString& internalName) {
+ const Theme::List& lst=getList();
+ Theme::List::ConstIterator it=lst.begin(), end=lst.end();
+ for (; it!=end; ++it) {
+ Theme::Ptr theme = *it;
+ if (theme->internalName() == internalName) {
+ return theme;
+ }
+ }
+ return 0;
+}
+
+
+QString Theme::internalName() const {
+ KURL url = d->mURL;
+ url.setFileName("");
+ return url.fileName();
+}
+
+
+QString Theme::name() const {
+ return d->mDesktopFile->readName();
+}
+
+
+QString Theme::comment() const {
+ return d->mDesktopFile->readComment();
+}
+
+
+QString Theme::directory() const {
+ return d->mURL.directory();
+}
+
+
+QString Theme::authorName() const {
+ KConfigGroupSaver saver(d->mDesktopFile, AUTHOR_GROUP);
+ return d->mDesktopFile->readEntry("Name");
+}
+
+
+QString Theme::authorUrl() const {
+ KConfigGroupSaver saver(d->mDesktopFile, AUTHOR_GROUP);
+ return d->mDesktopFile->readEntry("Url");
+}
+
+
+Theme::ParameterList Theme::parameterList() const {
+ return d->mParameterList;
+}
+
+
+} // namespace
diff --git a/kipi-plugins/htmlexport/theme.h b/kipi-plugins/htmlexport/theme.h
new file mode 100644
index 0000000..438bc47
--- /dev/null
+++ b/kipi-plugins/htmlexport/theme.h
@@ -0,0 +1,78 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef THEME_H
+#define THEME_H
+
+// Qt
+#include <qstring.h>
+#include <qvaluelist.h>
+
+// KDE
+#include <ksharedptr.h>
+
+namespace KIPIHTMLExport {
+
+class AbstractThemeParameter;
+
+
+/**
+ * An HTML theme. This class gives access to the various theme properties,
+ * including the theme parameters.
+ */
+class Theme : public KShared {
+public:
+ typedef KSharedPtr<Theme> Ptr;
+ typedef QValueList<Ptr> List;
+ typedef QValueList<AbstractThemeParameter*> ParameterList;
+
+ ~Theme();
+ /**
+ * Internal theme name == name of theme folder
+ */
+ QString internalName() const;
+ QString name() const;
+ QString comment() const;
+
+ QString authorName() const;
+ QString authorUrl() const;
+
+ /**
+ * Theme directory on hard disk
+ */
+ QString directory() const;
+
+ ParameterList parameterList() const;
+
+ /**
+ * Returns the list of available themes
+ */
+ static const List& getList();
+ static Ptr findByInternalName(const QString& internalName);
+
+private:
+ Theme();
+ struct Private;
+ Private* d;
+};
+
+} // namespace
+
+#endif /* THEME_H */
diff --git a/kipi-plugins/htmlexport/themepage.ui b/kipi-plugins/htmlexport/themepage.ui
new file mode 100644
index 0000000..635443c
--- /dev/null
+++ b/kipi-plugins/htmlexport/themepage.ui
@@ -0,0 +1,41 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>ThemePage</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ThemePage</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>412</width>
+ <height>247</height>
+ </rect>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KListBox">
+ <property name="name">
+ <cstring>mThemeList</cstring>
+ </property>
+ </widget>
+ <widget class="KTextBrowser">
+ <property name="name">
+ <cstring>mThemeInfo</cstring>
+ </property>
+ </widget>
+ </hbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistbox.h</includehint>
+ <includehint>ktextbrowser.h</includehint>
+</includehints>
+</UI>
diff --git a/kipi-plugins/htmlexport/themeparameterspage.ui b/kipi-plugins/htmlexport/themeparameterspage.ui
new file mode 100644
index 0000000..0c0fc73
--- /dev/null
+++ b/kipi-plugins/htmlexport/themeparameterspage.ui
@@ -0,0 +1,92 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ThemeParametersPage</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ThemeParametersPage</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>In this page, you can change some theme parameters. Depending on the theme, different parameters are available.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer2_2_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QFrame" row="2" column="1">
+ <property name="name">
+ <cstring>content</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ </widget>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>spacer12</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="0"/>
+</UI>
diff --git a/kipi-plugins/htmlexport/themes/Makefile.am b/kipi-plugins/htmlexport/themes/Makefile.am
new file mode 100644
index 0000000..9f51896
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/Makefile.am
@@ -0,0 +1,8 @@
+SUBDIRS = \
+ matrix \
+ snow \
+ simple \
+ frames \
+ cleanframes \
+ s0 \
+ classic
diff --git a/kipi-plugins/htmlexport/themes/classic/Makefile.am b/kipi-plugins/htmlexport/themes/classic/Makefile.am
new file mode 100644
index 0000000..170ec09
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/classic/Makefile.am
@@ -0,0 +1,6 @@
+themedir=$(kde_datadir)/kipiplugin_htmlexport/themes/classic
+theme_DATA= \
+ classic.desktop \
+ template.xsl \
+ up.png \
+ gohome.png
diff --git a/kipi-plugins/htmlexport/themes/classic/classic.desktop b/kipi-plugins/htmlexport/themes/classic/classic.desktop
new file mode 100644
index 0000000..d463211
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/classic/classic.desktop
@@ -0,0 +1,258 @@
+[Desktop Entry]
+Name=Classic
+Name[ca]=Clàssic
+Name[da]=Klassisk
+Name[de]=Klassisch
+Name[el]=Κλασικό
+Name[es]=Clásico
+Name[et]=Klassikaline
+Name[fi]=Klassikko
+Name[is]=Klassískt
+Name[it]=Classico
+Name[ja]=クラシック
+Name[nds]=Klass'sch
+Name[nl]=Klassiek
+Name[pl]=Klasyczny
+Name[pt]=Clássico
+Name[sr]=Класичан
+Name[sr@Latn]=Klasičan
+Name[sv]=Klassiskt
+Name[xx]=xxClassicxx
+Name[zh_CN]=经典
+Comment=A port of the old HTML Export plugin theme
+Comment[ca]=Un port de l'antic tema del connector d'exportació a HTML
+Comment[da]=En overførsel af det gamle tema for pluginnet HTML-eksport
+Comment[de]=Ein Portierung des Themas des alten HTML-Export-Moduls
+Comment[el]=Το παλιό θέμα προσθέτου εξαγωγής σε HTML
+Comment[es]=Una versión del antiguo tema del complemento de exportación en HTML
+Comment[et]=Vana HTML-ekspordi plugina teema port
+Comment[fr]=Module externe KIPI pour exporter vers HTML (ancien thème)
+Comment[is]=Gamla íforritið til útflutnings á HTML
+Comment[it]=Un trasferimento del vecchio tema di esportazione HTML
+Comment[ja]=以前の HTML エクスポートプラグインから移植したテーマ
+Comment[nds]=En Porteren vun dat ole HTML-Exportmoduul sien Muster
+Comment[nl]=Het klassieke thema van de HTML-exportplugin
+Comment[pl]=Stary motyw wtyczki eksportu do HTML-a
+Comment[pt]=Uma versão do antigo tema de Exportação para HTML
+Comment[pt_BR]=Um port do antigo tema do plugin de Exportação HTML
+Comment[sr]=Прилагођење старе теме прикључка HTML извоза
+Comment[sr@Latn]=Prilagođenje stare teme priključka HTML izvoza
+Comment[sv]=En överföring av det gamla temat för insticksprogrammet HTML-export
+Comment[xx]=xxA port of the old HTML Export plugin themexx
+Comment[zh_CN]=旧的 HTML 导出插件主题
+
+[X-HTMLExport Author]
+Name=Aurélien Gâteau
+Name[sr]=Орелиен Гато
+Name[sr@Latn]=Orelien Gato
+Name[xx]=xxAurélien Gâteauxx
+Url=mailto:aurelien.gateau@free.fr
+
+[X-HTMLExport Parameter thumbnailPerRow]
+Name=Thumbnails per row
+Name[ca]=Miniatures per fila
+Name[da]=Miniaturebilleder per linje
+Name[de]=Vorschaubilder pro Zeile
+Name[el]=Εικόνες επισκόπησης ανά γραμμή
+Name[es]=Miniaturas por filas
+Name[et]=Pisipilte reas
+Name[fr]=Nombre d'aperçus par ligne
+Name[is]=Smámyndir í röð
+Name[it]=Miniature per riga
+Name[ja]=横一列あたりのサムネイル数
+Name[nds]=Vöransichtbiller per Reeg
+Name[nl]=Miniaturen per rij
+Name[pl]=Miniatur na wiersz
+Name[pt]=Miniaturas por linha
+Name[pt_BR]=Miniaturas por fileira
+Name[sr]=Сличица по реду
+Name[sr@Latn]=Sličica po redu
+Name[sv]=Miniatyrbilder per rad
+Name[xx]=xxThumbnails per rowxx
+Name[zh_CN]=每行缩略图
+Type=int
+Default=4
+Min=1
+Max=100
+
+[X-HTMLExport Parameter bgColor]
+Name=Background Color
+Name[ca]=Color de fons
+Name[da]=Baggrundsfarve
+Name[de]=Hintergrundfarbe
+Name[el]=Χρώμα φόντου
+Name[es]=Color del fondo
+Name[et]=Taustavärv
+Name[fi]=Taustaväri
+Name[fr]=Couleur d'arrière plan
+Name[is]=Bakgrunnslitur
+Name[it]=Colore di sfondo
+Name[ja]=背景色
+Name[nds]=Achtergrundklöör
+Name[nl]=Achtergrondkleur
+Name[pl]=Kolor tła
+Name[pt]=Cor de Fundo
+Name[pt_BR]=Cor de Segundo Plano
+Name[sr]=Боја позадине
+Name[sr@Latn]=Boja pozadine
+Name[sv]=Bakgrundsfärg
+Name[xx]=xxBackground Colorxx
+Name[zh_CN]=背景颜色
+Type=color
+Default=#333333
+
+[X-HTMLExport Parameter fgColor]
+Name=Foreground Color
+Name[ca]=Color de primer pla
+Name[da]=Forgrundsfarve
+Name[de]=Vordergrundfarbe
+Name[el]=Χρώμα προσκηνίου
+Name[es]=Color del primer plano
+Name[et]=Esiplaani värv
+Name[fi]=Edustaväri
+Name[fr]=Couleur d'avant plan
+Name[is]=Forgrunnslitur
+Name[it]=Colore di primo piano
+Name[ja]=前景色
+Name[nds]=Vörgrundklöör
+Name[nl]=Voorgrondkleur
+Name[pl]=Kolor czcionki
+Name[pt]=Cor Principal
+Name[pt_BR]=Cor de Primeiro Plano
+Name[sr]=Боја исписа
+Name[sr@Latn]=Boja ispisa
+Name[sv]=Förgrundsfärg
+Name[xx]=xxForeground Colorxx
+Name[zh_CN]=前景颜色
+Type=color
+Default=#d0ffd0
+
+[X-HTMLExport Parameter fontSize]
+Name=Font Size
+Name[ca]=Mida del tipus de lletra
+Name[da]=Tegnstørrelse
+Name[de]=Zeichensatzgröße
+Name[el]=Μέγεθος γραμματοσειράς
+Name[es]=Tamaño del tipo de letra
+Name[et]=Fondi suurus
+Name[fi]=Kirjasinkoko
+Name[fr]=Taille de la fonte
+Name[is]=Leturstærð
+Name[it]=Dimensione dei caratteri
+Name[ja]=フォントサイズ
+Name[nds]=Schriftgrött
+Name[nl]=Tekengrootte
+Name[pl]=Rozmiar czcionki
+Name[pt]=Tamanho da Letra
+Name[pt_BR]=Tamanho da Fonte
+Name[sr]=Величина фонта
+Name[sr@Latn]=Veličina fonta
+Name[sv]=Teckenstorlek
+Name[xx]=xxFont Sizexx
+Name[zh_CN]=字体大小
+Type=int
+Default=14
+Min=1
+Max=100
+
+[X-HTMLExport Parameter imgBorderSize]
+Name=Image Border Size
+Name[ca]=Mida de la vora de la imatge
+Name[da]=Billedkantstørrelse
+Name[de]=Größe des Bildrahmens
+Name[el]=Μέγεθος περιγράμματος εικόνας
+Name[es]=Tamaño del borde de la imagen
+Name[et]=Pildi piirete suurus
+Name[fr]=Taille du bord de l'image
+Name[is]=Stærð myndramma
+Name[it]=Dimensione del bordo delle immagini
+Name[ja]=画像の縁取りの幅
+Name[nds]=Bildrahmengrött
+Name[nl]=Grootte afbeeldingsrand
+Name[pl]=Rozmiar obramowania zdjęcia
+Name[pt]=Tamanho do Contorno da Imagem
+Name[pt_BR]=Tamanho da Borda da Imagem
+Name[sr]=Величина оквира
+Name[sr@Latn]=Veličina okvira
+Name[sv]=Bildkantstorlek
+Name[xx]=xxImage Border Sizexx
+Name[zh_CN]=图像边框大小
+Type=int
+Default=1
+Min=1
+Max=50
+
+[X-HTMLExport Parameter imgBorderColor]
+Name=Image Border Color
+Name[ca]=Color de la vora de la imatge
+Name[da]=Billedkantfarve
+Name[de]=Farbe des Bildrahmens
+Name[el]=Χρώμα περιγράμματος εικόνας
+Name[es]=Color del borde de la imagen
+Name[et]=Pildi piirete värv
+Name[fr]=Couleur du bord de l'image
+Name[is]=Litur myndramma
+Name[it]=Colore del bordo delle immagini
+Name[ja]=画像の縁取りの色
+Name[nds]=Bildrahmenklöör
+Name[nl]=Kleur afbeeldingsrand
+Name[pl]=Kolor obramowania zdjęcia
+Name[pt]=Cor do Contorno da Imagem
+Name[pt_BR]=Cor da Borda da Imagem
+Name[sr]=Боја оквира
+Name[sr@Latn]=Boja okvira
+Name[sv]=Bildkantsfärg
+Name[xx]=xxImage Border Colorxx
+Name[zh_CN]=图像边框颜色
+Type=color
+Default=#d0ffd0
+
+[X-HTMLExport Parameter linkColor]
+Name=Link Color
+Name[ca]=Color de l'enllaç
+Name[da]=Linkfarve
+Name[de]=Verknüpfungsfarbe
+Name[el]=Χρώμα δεσμού
+Name[es]=Color del enlace
+Name[et]=Lingi värv
+Name[fr]=Couleur du lien
+Name[is]=Litur tengils
+Name[it]=Colore dei collegamenti
+Name[ja]=リンクの色
+Name[nds]=Linkklöör
+Name[nl]=Kleur koppeling
+Name[pl]=Kolor łącza
+Name[pt]=Cor da Hiperligação
+Name[pt_BR]=Cor do Link
+Name[sr]=Боја везе
+Name[sr@Latn]=Boja veze
+Name[sv]=Länkfärg
+Name[xx]=xxLink Colorxx
+Name[zh_CN]=链接颜色
+Type=color
+Default=#b3b3b3
+
+[X-HTMLExport Parameter visitedLinkColor]
+Name=Visited Link Color
+Name[ca]=Color de l'enllaç visitat
+Name[da]=Besøgt linkfarve
+Name[de]=Farbe der besuchten Verknüpfungen
+Name[el]=Χρώμα ακολουθημένου δεσμού
+Name[es]=Color del enlace visitado
+Name[et]=Külastatud lingi värv
+Name[fr]=Couleur du lien déjà visité
+Name[is]=Litur skoðaðs tengils
+Name[it]=Colore dei collegamenti visitati
+Name[ja]=訪問済みリンクの色
+Name[nds]=Klöör för besöcht Link
+Name[nl]=Kleur gevolgde koppeling
+Name[pl]=Kolor odwiedzonego łącza
+Name[pt]=Cor da Ligação Visitada
+Name[pt_BR]=Cor do Link Visitado
+Name[sr]=Боја посећене везе
+Name[sr@Latn]=Boja posećene veze
+Name[sv]=Besökt länkfärg
+Name[xx]=xxVisited Link Colorxx
+Name[zh_CN]=已浏览链接颜色
+Type=color
+Default=#b3b3b3
diff --git a/kipi-plugins/htmlexport/themes/classic/gohome.png b/kipi-plugins/htmlexport/themes/classic/gohome.png
new file mode 100644
index 0000000..acf3e4a
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/classic/gohome.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/classic/template.xsl b/kipi-plugins/htmlexport/themes/classic/template.xsl
new file mode 100644
index 0000000..638f54c
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/classic/template.xsl
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE stylesheet [
+<!ENTITY raquo "&#187;">
+]>
+
+<xsl:transform version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl">
+
+<xsl:template name="style">
+ <style type='text/css'>
+ body {
+ color: <xsl:value-of select="$fgColor"/>;
+ background: <xsl:value-of select="$bgColor"/>;
+ font-family: /*param*/Helvetica, sans-serif;
+ font-size: <xsl:value-of select="$fontSize"/>pt;
+ margin: 4%;
+ }
+
+ h1 {
+ color: <xsl:value-of select="$fgColor"/>;
+ }
+
+ table {
+ text-align: center;
+ margin-left: auto;
+ margin-right: auto;
+ }
+
+ td {
+ color: <xsl:value-of select="$fgColor"/>;
+ padding: 1em;
+ }
+
+ img.photo {
+ border: <xsl:value-of select="$imgBorderSize"/>px solid <xsl:value-of select="$imgBorderColor"/>;
+ }
+
+ a:link {
+ color: <xsl:value-of select="$linkColor"/>;
+ }
+
+ a:visited {
+ color: <xsl:value-of select="$visitedLinkColor"/>;
+ }
+ </style>
+</xsl:template>
+
+<xsl:template name="imagePage">
+ <xsl:param name="index" select="1"/>
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="title"/></title>
+ <xsl:call-template name="style"/>
+ </head>
+ <body>
+ <div align="center">
+ <xsl:if test="$index &gt; 1">
+ <xsl:for-each select="../image[$index - 1]">
+ <a href="{full/@fileName}.html">
+ <img class="photo" src="{thumbnail/@fileName}" alt="{$i18nPrevious}" title="{$i18nPrevious}" height="{thumbnail/@width}" width="{thumbnail/@height}"/>
+ </a>
+ </xsl:for-each>
+ |
+ </xsl:if>
+
+ <xsl:choose>
+ <xsl:when test="count(/collections/collection) > 1">
+ <a href="../{../fileName}.html"><img src="../classic/up.png" border="0" title="{../description}" alt="{../description}"/></a>
+ | <a href="../index.html"><img src="../classic/gohome.png" border="0" alt="{$i18nCollectionList}" title="{$i18nCollectionList}"/></a>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="../index.html"><img src="../classic/up.png" border="0" title="{$i18nCollectionList}" alt="{$i18nCollectionList}"/></a>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="$index &lt; count(../image)">
+ |
+ <xsl:for-each select="../image[$index + 1]">
+ <a href="{full/@fileName}.html">
+ <img class="photo" src="{thumbnail/@fileName}" alt="{$i18nNext}" title="{$i18nNext}" height="{thumbnail/@width}" width="{thumbnail/@height}"/>
+ </a>
+ </xsl:for-each>
+ </xsl:if>
+ <br/>
+ <hr/>
+ <br/>
+ <br/>
+ <img class="photo" src="{full/@fileName}" width="{full/@width}" height="{full/@height}" alt="{description}" title="{description}"/>
+ <xsl:if test="original/@fileName != ''">
+ <p>
+ <a href="{original/@fileName}"><xsl:value-of select="$i18nOriginalImage"/></a>
+ (<xsl:value-of select="original/@width"/>x<xsl:value-of select="original/@height"/>)
+ </p>
+ </xsl:if>
+ <!-- FIXME title="description, imageSize, fileSize" -->
+ <br/>
+ <br/>
+ </div>
+ <hr/>
+ <!-- FIXME footer -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="collectionPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="name"/></title>
+ <xsl:call-template name="style"/>
+ </head>
+ <body>
+ <xsl:if test="count(/collections/collection) > 1">
+ <a href="index.html"><img src="classic/gohome.png" border="0" alt="{$i18nCollectionList}" title="{$i18nCollectionList}"/></a>
+ </xsl:if>
+ <h1>&quot;<xsl:value-of select="name"/>&quot;</h1>
+ <!-- FIXME: Album info -->
+
+ <table>
+ <xsl:call-template name="thumbnailTable"/>
+ </table>
+ <hr/>
+
+ <!-- FIXME: Footer -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<!-- Called only once per table, use recursion to generate every row -->
+<xsl:template name="thumbnailTable">
+ <xsl:param name="index" select="1"/>
+
+ <xsl:if test="$index &lt; count(image)+1">
+ <tr>
+ <xsl:call-template name="thumbnailTableCell">
+ <xsl:with-param name="index" select="$index"/>
+ <xsl:with-param name="counter" select="$index + $thumbnailPerRow - 1"/>
+ </xsl:call-template>
+ </tr>
+
+ <xsl:call-template name="thumbnailTable">
+ <xsl:with-param name="index" select="$index + $thumbnailPerRow"/>
+ </xsl:call-template>
+ </xsl:if>
+</xsl:template>
+
+
+<!-- Called for every cell, use recursion to generate every cell -->
+<xsl:template name="thumbnailTableCell">
+ <xsl:param name="index" select="1"/>
+ <xsl:param name="counter" select="1"/>
+
+ <xsl:if test="$index &lt; count(image) + 1">
+ <td align="center">
+ <xsl:variable name="folder" select='fileName'/>
+ <xsl:for-each select="image[$index]">
+ <a href='{$folder}/{full/@fileName}.html'>
+ <img class="photo" src="{$folder}/{thumbnail/@fileName}" width="{thumbnail/@width}" height="{thumbnail/@height}" />
+ <div><xsl:value-of select="title"/></div>
+ <!--FIXME image size and file size -->
+ </a>
+
+ <exsl:document href='{$folder}/{full/@fileName}.html'>
+ <xsl:call-template name="imagePage">
+ <xsl:with-param name="index" select="$index"/>
+ </xsl:call-template>
+ </exsl:document>
+ </xsl:for-each>
+ </td>
+
+ <xsl:if test="$counter > $index">
+ <xsl:call-template name="thumbnailTableCell">
+ <xsl:with-param name="index" select="$index + 1"/>
+ <xsl:with-param name="counter" select="$counter"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+</xsl:template>
+
+
+<xsl:template name="collectionListPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="$i18nCollectionList"/></title>
+ <xsl:call-template name="style"/>
+ </head>
+ <body>
+ <h1><xsl:value-of select="$i18nCollectionList"/></h1>
+ <hr/>
+ <p>
+
+ <xsl:for-each select="collections/collection">
+ <xsl:variable name="title" select='concat(name, " [", count(image), "]")'/>
+ <a href="{fileName}.html">
+ <!-- Use first image as collection image -->
+ <img class="photo"
+ src="{fileName}/{image[1]/thumbnail/@fileName}"
+ width="{image[1]/thumbnail/@width}"
+ height="{image[1]/thumbnail/@height}"
+ alt="{$title}"
+ title="{$title}"/>
+ </a>
+ <a href="{fileName}.html"><xsl:value-of select="$title"/></a>
+ <br />
+ <exsl:document href="{fileName}.html">
+ <xsl:call-template name="collectionPage"/>
+ </exsl:document>
+ </xsl:for-each>
+
+ </p>
+ <hr/>
+ <!-- FIXME: Footer -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template match="/">
+ <xsl:choose>
+ <xsl:when test="count(collections/collection) &gt; 1">
+ <xsl:call-template name="collectionListPage"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="collections/collection">
+ <xsl:call-template name="collectionPage"/>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+</xsl:transform>
diff --git a/kipi-plugins/htmlexport/themes/classic/up.png b/kipi-plugins/htmlexport/themes/classic/up.png
new file mode 100644
index 0000000..89f77e6
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/classic/up.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/Makefile.am b/kipi-plugins/htmlexport/themes/cleanframes/Makefile.am
new file mode 100644
index 0000000..0140622
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/Makefile.am
@@ -0,0 +1,13 @@
+themedir=$(kde_datadir)/kipiplugin_htmlexport/themes/cleanframes
+theme_DATA= \
+ cleanframes.desktop \
+ template.xsl \
+ star.png \
+ black.css \
+ blue.css \
+ brown.css \
+ green.css \
+ lavender.css \
+ pink.css \
+ red.css \
+ yellow.css
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/black.css b/kipi-plugins/htmlexport/themes/cleanframes/black.css
new file mode 100644
index 0000000..f1df190
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/black.css
@@ -0,0 +1,82 @@
+body {
+ background-color: #000000; /*background behind thumbnails, outside boxes*/
+ color: #000055; /*default text color*/
+ font-size: 14pt;
+ text-align: center;
+ font-family: Bitstream Vera Serif, serif;
+ margin: 0in;
+ padding: 0in;
+}
+
+a { /*links (album titles)*/
+ color: #FFFFFF;
+ text-decoration: none;
+}
+
+a:hover { /*links when mouse is over them (album titles)*/
+ color: #5555FF;
+ text-decoration: underline;
+}
+
+h1 { /*album title above thumbnails*/
+ padding-top: 0.1em;
+ color: #FFFFFF;
+ font-size: 14pt;
+}
+
+/* Collection page */
+#collectionPage h1 {
+ margin-top: 12px;
+}
+
+#collectionPage ul { /*affects list of thumbnails*/
+ padding: 0;
+ padding-left: 5%;
+ text-align: center;
+ width: 95%
+}
+
+#collectionPage li { /*affects stuff in boxes with thumbnails*/
+ display: block;
+ float: left;
+ margin-left: 6px;
+ margin-top: 6px;
+ padding: 5px;
+ color: #000000;
+ font-size: 8pt;
+ background-color: #FFFFFF;
+ border: 1px solid #000000;
+}
+
+/* Blank Page */
+#blankPage {
+ background-color: #FFFFFF;
+}
+
+/* Collect Page */
+#collectPage { /*album titles at top*/
+ background-color: #333333;
+ font-size: 12pt;
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ color: #AAAAAA; /*number of pics in collection*/
+}
+
+
+/* Image page */
+#imagePage {
+ padding:.5em;
+ background-color:#FFFFFF; /*background color behind the big image*/
+}
+
+
+#caption { /*caption below photo*/
+ padding-bottom:1em;
+ color: #000000;
+ font-size: 16pt;
+}
+
+#imagePage img {
+ border: 1px solid #CECECE; /*border around picture*/
+}
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/blue.css b/kipi-plugins/htmlexport/themes/cleanframes/blue.css
new file mode 100644
index 0000000..923a4fd
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/blue.css
@@ -0,0 +1,82 @@
+body {
+ background-color: #FFFFFF; /*background behind thumbnails, outside boxes*/
+ color: #000055; /*default text color*/
+ font-size: 14pt;
+ text-align: center;
+ font-family: Bitstream Vera Serif, serif;
+ margin: 0in;
+ padding: 0in;
+}
+
+a { /*links (album titles)*/
+ color: #FFFFFF;
+ text-decoration: none;
+}
+
+a:hover { /*links when mouse is over them (album titles)*/
+ color: #5555FF;
+ text-decoration: underline;
+}
+
+h1 { /*album title above thumbnails*/
+ padding-top: 0.1em;
+ color: #000055;
+ font-size: 14pt;
+}
+
+/* Collection page */
+#collectionPage h1 {
+ margin-top: 12px;
+}
+
+#collectionPage ul { /*affects list of thumbnails*/
+ padding: 0;
+ padding-left: 5%;
+ text-align: center;
+ width: 95%
+}
+
+#collectionPage li { /*affects stuff in boxes with thumbnails*/
+ display: block;
+ float: left;
+ margin-left: 6px;
+ margin-top: 6px;
+ padding: 5px;
+ color: #FFFFFF;
+ font-size: 8pt;
+ background-color: #000055;
+ border: 1px solid #000000;
+}
+
+/* Blank Page */
+#blankPage {
+ background-color: #000055;
+}
+
+/* Collect Page */
+#collectPage { /*album titles at top*/
+ background-color: #000011;
+ font-size: 12pt;
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ color: #AAAAAA; /*number of pics in collection*/
+}
+
+
+/* Image page */
+#imagePage {
+ padding:.5em;
+ background-color:#000055; /*background color behind the big image*/
+}
+
+
+#caption { /*caption below photo*/
+ padding-bottom:1em;
+ color: #FFFFFF;
+ font-size: 16pt;
+}
+
+#imagePage img {
+ border: 1px solid #CECECE; /*border around picture*/
+}
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/brown.css b/kipi-plugins/htmlexport/themes/cleanframes/brown.css
new file mode 100644
index 0000000..1474aeb
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/brown.css
@@ -0,0 +1,82 @@
+body {
+ background-color: #552211; /*background behind thumbnails, outside boxes*/
+ color: #CCAA88; /*default text color*/
+ font-size: 14pt;
+ text-align: center;
+ font-family: Bitstream Vera Serif, serif;
+ margin: 0in;
+ padding: 0in;
+}
+
+a { /*links (album titles)*/
+ color: #FFDDBB;
+ text-decoration: none;
+}
+
+a:hover { /*links when mouse is over them (album titles)*/
+ color: #FFFFFF;
+ text-decoration: underline;
+}
+
+h1 { /*album title above thumbnails*/
+ padding-top: 0.1em;
+ color: #CCAA88;
+ font-size: 14pt;
+}
+
+/* Collection page */
+#collectionPage h1 {
+ margin-top: 12px;
+}
+
+#collectionPage ul { /*affects list of thumbnails*/
+ padding: 0;
+ padding-left: 5%;
+ text-align: center;
+ width: 95%
+}
+
+#collectionPage li { /*affects stuff in boxes with thumbnails*/
+ display: block;
+ float: left;
+ margin-left: 6px;
+ margin-top: 6px;
+ padding: 5px;
+ color: #CCAA88;
+ font-size: 8pt;
+ background-color: #552211;
+ border: 1px solid #CCAA88;
+}
+
+/* Blank Page */
+#blankPage {
+ background-color: #FFFFFF;
+}
+
+/* Collect Page */
+#collectPage { /*album titles at top*/
+ background-color: #885544;
+ font-size: 12pt;
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ color: #BBBBBB; /*number of pics in collection*/
+}
+
+
+/* Image page */
+#imagePage {
+ padding:.5em;
+ background-color:#CCAA88; /*background color behind the big image*/
+}
+
+
+#caption { /*caption below photo*/
+ padding-bottom:1em;
+ color: #552211;
+ font-size: 16pt;
+}
+
+#imagePage img {
+ border: 1px solid #CECECE; /*border around picture*/
+}
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/cleanframes.desktop b/kipi-plugins/htmlexport/themes/cleanframes/cleanframes.desktop
new file mode 100644
index 0000000..12c996a
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/cleanframes.desktop
@@ -0,0 +1,92 @@
+[Desktop Entry]
+Name=Clean Frames
+Name[ca]=Marcs nets
+Name[da]=Rene rammer
+Name[de]=Saubere Rahmen
+Name[es]=Marcos limpios
+Name[et]=Puhtad raamid
+Name[is]=Hreinsa ramma
+Name[it]=Riquadri puliti
+Name[ja]=クリーンフレーム
+Name[nds]=Kloor Rahmens
+Name[nl]=Nette frames
+Name[pl]=Czyste ramki
+Name[pt]=Molduras Simples
+Name[pt_BR]=Bordas Limpas
+Name[sr]=Чисти оквири
+Name[sr@Latn]=Čisti okviri
+Name[sv]=Rena ramar
+Name[xx]=xxClean Framesxx
+Name[zh_CN]=简洁框架
+Comment=A frame theme based on Ruediger Bente's frame theme
+Comment[ca]=Un tema de marcs basat en el tema de marcs del Ruediger Bente
+Comment[da]=Et rammetema baseret på Ruediger Bentes rammetema
+Comment[de]=Ein rahmenbasiertes Design, das auf das Rahmendesign von Ruediger Bente basiert.
+Comment[el]=Ένα θέμα με πλαίσια βασισμένο στο θέμα του Ruediger Bente
+Comment[es]=Un tema de marcos basado en el tema de Ruediger Bente
+Comment[et]=Raamiteema Ruediger Bente raamiteema põhjal
+Comment[fr]=Un thème avec frame basé sur celui de Ruediger Bente
+Comment[is]=Rammagerðarþema byggt á öðru slíku eftir Ruediger Bente
+Comment[it]=Un tema a riquadri basato sul tema a riquadri di Rüdiger Bente
+Comment[ja]=Ruediger Bente のフレームテーマに基づくフレームテーマ
+Comment[nds]=En Rahmenmuster, buut op Rüdiger Bente sien Rahmenmuster
+Comment[nl]=Een framethema gebaseerd op het framethema van Ruediger Bente
+Comment[pl]=Motyw oparty na ramkach wzorowany na motywie, którego autorem jest Ruediger Bente.
+Comment[pt]=Um tema de molduras baseado no tema de Ruediger Bente
+Comment[pt_BR]=Uma tema de bordas baseado no tema de bordas de Ruediger Bente
+Comment[sr]=Тема оквира заснована на теми Рудигера Бентеа
+Comment[sr@Latn]=Tema okvira zasnovana na temi Rudigera Bentea
+Comment[sv]=Ett ramtema baserat på Ruediger Bentes ramtema
+Comment[xx]=xxA frame theme based on Ruediger Bente's frame themexx
+Comment[zh_CN]=基于 Ruediger Bente 的创意的像框主题
+
+[X-HTMLExport Author]
+Name=Elizabeth Marmorstein
+Name[sr]=Елизабет Марморштајн
+Name[sr@Latn]=Elizabet Marmorštajn
+Name[xx]=xxElizabeth Marmorsteinxx
+Url=mailto:purplegamba@cox.net
+
+[X-HTMLExport Parameter style]
+Name=Style
+Name[br]=Giz
+Name[ca]=Estil
+Name[da]=Stil
+Name[de]=Stil
+Name[el]=Στυλ
+Name[es]=Estilo
+Name[et]=Stiil
+Name[fi]=Tyyli
+Name[is]=Stíll
+Name[it]=Stile
+Name[ja]=スタイル
+Name[nds]=Stil
+Name[nl]=Stijl
+Name[pl]=Styl
+Name[pt]=Estilo
+Name[pt_BR]=Estilo
+Name[sr]=Стил
+Name[sr@Latn]=Stil
+Name[sv]=Stil
+Name[xh]=Uhlobo
+Name[xx]=xxStylexx
+Name[zh_CN]=样式
+Name[zu]=Uhlobo
+Type=list
+Default=pink.css
+Value_0=pink.css
+Caption_0=Pink
+Value_1=blue.css
+Caption_1=Blue
+Value_2=lavender.css
+Caption_2=Lavender
+Value_3=green.css
+Caption_3=Green
+Value_4=black.css
+Caption_4=Black
+Value_5=red.css
+Caption_5=Red
+Value_6=yellow.css
+Caption_6=Yellow
+Value_7=brown.css
+Caption_7=Brown
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/green.css b/kipi-plugins/htmlexport/themes/cleanframes/green.css
new file mode 100644
index 0000000..c1b3c7b
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/green.css
@@ -0,0 +1,115 @@
+body {
+ background-color: #FFFFFF; /*background behind thumbnails, outside boxes*/
+ color: #000055; /*default text color*/
+ font-size: 14pt;
+ text-align: center;
+ font-family: Bitstream Vera Serif, serif;
+ margin: 0in;
+ padding: 0in;
+}
+
+a { /*links (album titles)*/
+ color: #FFFFFF;
+ text-decoration: none;
+}
+
+a:hover { /*links when mouse is over them (album titles)*/
+ color: #5555ff;
+ text-decoration: underline;
+}
+
+h1 { /*album title above thumbnails*/
+ padding-top: 0.1em;
+ color: #FFFFFF;
+ background-color: #006633;
+ font-size: 16pt;
+
+ background-size: 100% auto;
+ background-origin: content;
+ background-repeat: no-repeat;
+ background-position: center;
+ display: block;
+ margin: 6px;
+ padding: 5px;
+ margin-top: 1em;
+
+}
+
+/* Collection page */
+#collectionPage {
+ background-image: url(star.png);
+}
+
+#collectionPage h1 {
+ margin-top: 12px;
+}
+
+#collectionPage ul { /*affects list of thumbnails*/
+ padding: 0;
+ padding-left: 5%;
+ text-align: center;
+ width: 95%
+}
+
+#collectionPage li { /*affects stuff in boxes with thumbnails*/
+ display: block;
+ float: left;
+ margin-left: 6px;
+ margin-top: 6px;
+ padding: 5px;
+ color: #FFFFFF;
+ font-size: 8pt;
+ background-color: #006633;
+ border: 1px solid #000000;
+}
+
+/* Blank Page */
+#blank page {
+ background-color: #000055;
+}
+
+/* Collect Page */
+#collectPage { /*album titles at top*/
+ background-color: #006633;
+ font-size: 14pt;
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ color: #AAAAAA; /*number of pics in collection*/
+}
+
+#collectPage a { /*links (album titles)*/
+ color: #FFFFFF;
+ text-decoration: none;
+}
+
+#collectPage a:hover { /*links when mouse is over them (album titles)*/
+ color: #5555ff;
+ text-decoration: underline;
+}
+
+
+/* Image page */
+#imagePage {
+ padding: 0;
+ margin: 0;
+ background-color:#006633; /*background color behind the big image*/
+ text-align: center;
+}
+
+
+#caption { /*caption below photo*/
+ width: 90%;
+ margin-left: 3%;
+ padding:.5em;
+ color: #FFFFFF;
+ background-image: none;
+ background-color: #006633;
+ font-size: 16pt;
+ background-color:#006633;
+}
+
+#imagePage img {
+ margin: 0.5em;
+ border: 1px solid #CECECE; /*border around picture*/
+}
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/lavender.css b/kipi-plugins/htmlexport/themes/cleanframes/lavender.css
new file mode 100644
index 0000000..b4e2b92
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/lavender.css
@@ -0,0 +1,86 @@
+body {
+ background-color: #9977DD; /*background behind thumbnails, outside boxes*/
+ color: #000066; /*default text color*/
+ font-size: 14pt;
+ text-align: center;
+ font-family: Bitstream Vera Serif, serif;
+ margin: 0in;
+ padding: 0in;
+}
+
+a { /*links (album titles)*/
+ color: #9977DD;
+ text-decoration: none;
+}
+
+a:hover { /*links when mouse is over them (album titles)*/
+ color: #000033;
+ text-decoration: underline;
+}
+
+h1 { /*album title above thumbnails*/
+ padding-top: 0.1em;
+ color: #FFFFFF;
+ font-size: 16pt;
+}
+
+/* Collection page */
+#collectionPage h1 {
+ margin-top: 12px;
+}
+
+#collectionPage ul { /*affects list of thumbnails*/
+ padding: 0;
+ padding-left: 5%;
+ text-align: center;
+ width: 95%
+}
+
+#collectionPage li { /*affects stuff in boxes with thumbnails*/
+ display: block;
+ float: left;
+ margin-left: 6px;
+ margin-top: 6px;
+ padding: 5px;
+ color: #660099;
+ font-size: 8pt;
+ background-color: #ffffff;
+ border: 1px solid #000000;
+}
+
+/* Collect Page */
+#collectPage { /*album titles at top*/
+ background-color: #FFFFFF;
+ font-size: 12pt;
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ color: #9977DD; /*number of pics in collection*/
+}
+#collectPage a { /*links (album titles)*/
+ color: #5533AA;
+ text-decoration: none;
+}
+
+#collectPage a:hover { /*links when mouse is over them (album titles)*/
+ color: #000033;
+ text-decoration: underline;
+}
+
+
+/* Image page */
+#imagePage {
+ padding:.5em;
+ background-color:#9977DD; /*background color behind the big image*/
+}
+
+
+#caption { /*caption below photo*/
+ padding-bottom:1em;
+ color: #FFFFFF;
+ font-size: 16pt;
+}
+
+#imagePage img {
+ border: 1px solid #CECECE; /*border around picture*/
+}
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/pink.css b/kipi-plugins/htmlexport/themes/cleanframes/pink.css
new file mode 100644
index 0000000..326e9b1
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/pink.css
@@ -0,0 +1,77 @@
+body {
+ background-color: #FF99FF; /*background behind thumbnails, outside boxes*/
+ color: #660099; /*default text color*/
+ font-size: 14pt;
+ text-align: center;
+ font-family: Bitstream Vera Serif, serif;
+ margin: 0in;
+ padding: 0in;
+}
+
+a { /*links (album titles)*/
+ color: #FFFFFF;
+ text-decoration: none;
+}
+
+a:hover { /*links when mouse is over them (album titles)*/
+ color: #000033;
+ text-decoration: underline;
+}
+
+h1 { /*album title above thumbnails*/
+ padding-top: 0.1em;
+ color: #660099;
+ font-size: 16pt;
+}
+
+/* Collection page */
+#collectionPage h1 {
+ margin-top: 12px;
+}
+
+#collectionPage ul { /*affects list of thumbnails*/
+ padding: 0;
+ padding-left: 5%;
+ text-align: center;
+ width: 95%
+}
+
+#collectionPage li { /*affects stuff in boxes with thumbnails*/
+ display: block;
+ float: left;
+ margin-left: 6px;
+ margin-top: 6px;
+ padding: 5px;
+ color: #660099;
+ font-size: 8pt;
+ background-color: #ffffff;
+ border: 1px solid #000000;
+}
+
+/* Collect Page */
+#collectPage { /*album titles at top*/
+ background-color: #CC0066;
+ font-size: 12pt;
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ color: #000033; /*number of pics in collection*/
+}
+
+
+/* Image page */
+#imagePage {
+ padding:.5em;
+ background-color:#FF99FF; /*background color behind the big image*/
+}
+
+
+#caption { /*caption below photo*/
+ padding-bottom:1em;
+ color: #660099;
+ font-size: 16pt;
+}
+
+#imagePage img {
+ border: 1px solid #CECECE; /*border around picture*/
+}
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/red.css b/kipi-plugins/htmlexport/themes/cleanframes/red.css
new file mode 100644
index 0000000..995771c
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/red.css
@@ -0,0 +1,82 @@
+body {
+ background-color: #990000; /*background behind thumbnails, outside boxes*/
+ color: #000055; /*default text color*/
+ font-size: 14pt;
+ text-align: center;
+ font-family: Bitstream Vera Serif, serif;
+ margin: 0in;
+ padding: 0in;
+}
+
+a { /*links (album titles)*/
+ color: #FFFFFF;
+ text-decoration: none;
+}
+
+a:hover { /*links when mouse is over them (album titles)*/
+ color: #5555FF;
+ text-decoration: underline;
+}
+
+h1 { /*album title above thumbnails*/
+ padding-top: 0.1em;
+ color: #FFFFFF;
+ font-size: 14pt;
+}
+
+/* Collection page */
+#collectionPage h1 {
+ margin-top: 12px;
+}
+
+#collectionPage ul { /*affects list of thumbnails*/
+ padding: 0;
+ padding-left: 5%;
+ text-align: center;
+ width: 95%
+}
+
+#collectionPage li { /*affects stuff in boxes with thumbnails*/
+ display: block;
+ float: left;
+ margin-left: 6px;
+ margin-top: 6px;
+ padding: 5px;
+ color: 990000;
+ font-size: 8pt;
+ background-color: #FFFFFF;
+ border: 1px solid #990000;
+}
+
+/* Blank Page */
+#blankPage {
+ background-color: #FFFFFF;
+}
+
+/* Collect Page */
+#collectPage { /*album titles at top*/
+ background-color: #000000;
+ font-size: 12pt;
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ color: #AAAAAA; /*number of pics in collection*/
+}
+
+
+/* Image page */
+#imagePage {
+ padding:.5em;
+ background-color:#FFFFFF; /*background color behind the big image*/
+}
+
+
+#caption { /*caption below photo*/
+ padding-bottom:1em;
+ color: #990000;
+ font-size: 16pt;
+}
+
+#imagePage img {
+ border: 1px solid #CECECE; /*border around picture*/
+}
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/star.png b/kipi-plugins/htmlexport/themes/cleanframes/star.png
new file mode 100644
index 0000000..0558264
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/star.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/template.xsl b/kipi-plugins/htmlexport/themes/cleanframes/template.xsl
new file mode 100644
index 0000000..dfe8c78
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/template.xsl
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE stylesheet [
+<!ENTITY raquo "&#187;" >
+<!ENTITY blank "&#160;" >
+]>
+
+<xsl:transform version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl">
+
+<!-- ********************************************************************* -->
+<!-- ** Create single image page for each imag ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createImagePage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="title"/></title>
+ <link rel="stylesheet" type="text/css">
+ <xsl:attribute name="href">../cleanframes/<xsl:value-of select="$style"/></xsl:attribute>
+ </link>
+ </head>
+ <body id="imagePage">
+ <table border="0" width="100%">
+ <tr>
+ <td align="center">
+ <img src="{full/@fileName}" width="{full/@width}" height="{full/@height}" />
+ <xsl:if test="original/@fileName != ''">
+ <p>
+ <a href="{original/@fileName}"><xsl:value-of select="$i18nOriginalImage"/></a>
+ (<xsl:value-of select="original/@width"/>x<xsl:value-of select="original/@height"/>)
+ </p>
+ </xsl:if>
+´ </td>
+ </tr>
+ </table>
+ <div id="caption">
+ <xsl:value-of select="description"/>
+
+ </div>
+ </body>
+ </html>
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create thumbnail page for each collection ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createThumbnailPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="name"/></title>
+ <link rel="stylesheet" type="text/css">
+ <xsl:attribute name="href">cleanframes/<xsl:value-of select="$style"/></xsl:attribute>
+ </link>
+ </head>
+ <h1>
+ <span>
+ <xsl:value-of select="name"/>
+ </span>
+ </h1>
+
+ <body id="collectionPage">
+ <ul>
+ <xsl:variable name="folder" select='fileName'/>
+ <xsl:for-each select="image">
+ <li>
+ <a href="{$folder}/{full/@fileName}.html" target="image">
+ <img src="{$folder}/{thumbnail/@fileName}" width="{thumbnail/@width}" height="{thumbnail/@height}"/>
+ </a><br/>
+ (<xsl:value-of select="position()"/>/<xsl:value-of select="last()"/>)
+ </li>
+ <exsl:document href='{$folder}/{full/@fileName}.html'>
+ <xsl:call-template name="createImagePage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </ul>
+ </body>
+ </html>
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create frameset page if only one collection ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createFrameSetPage">
+<!-- ** create variable tsize for the width of the thumbnails frame ** -->
+<!-- ** add 10 pixel to tsize for the border around the thumbnail ** -->
+ <xsl:variable name="tsize" select="3*(image[1]/thumbnail/@width + 18) + 65"/>
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+ <title>
+ <xsl:value-of select="name"/>
+ </title>
+ <link rel="stylesheet" type="text/css">
+ <xsl:attribute name="href">cleanframes/<xsl:value-of select="$style"/></xsl:attribute>
+ </link>
+ </head>
+ <frameset cols="{$tsize},*" noresize="1" border="0">
+ <frame src="thmbs.html" name="mythmbs"/>
+ <frame src="blank.html" name="image"/>
+ </frameset>
+ <exsl:document href="thmbs.html">
+ <xsl:call-template name="createThumbnailPage"/>
+ </exsl:document>
+ </html>
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create the collection index page when more than one collection ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createCollectionIndexPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="$i18nCollectionList"/></title>
+ <link rel="stylesheet" type="text/css">
+ <xsl:attribute name="href">cleanframes/<xsl:value-of select="$style"/></xsl:attribute>
+ </link>
+ </head>
+ <body id="collectPage">
+ <xsl:for-each select="collections/collection">
+ &blank;
+ <a href="Thmbs{fileName}.html" target="mythmbs">
+ <xsl:value-of select="name"/>
+
+ </a>
+ <xsl:for-each select="image">
+ <xsl:choose>
+ <xsl:when test="position()=last()">
+ (<xsl:value-of select="last()"/>)
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ <exsl:document href="Thmbs{fileName}.html">
+ <xsl:call-template name="createThumbnailPage"/>
+ </exsl:document>
+
+ </xsl:for-each>
+ </body>
+ </html>
+
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create the frameset page when more than one collection ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createCollectionFrameSetPage">
+<!-- ** create variable tsize for the width of the thumbnails frame ** -->
+<!-- ** add 10 pixel to tsize for the border around the thumbnail ** -->
+ <xsl:variable name="tsize" select="3*(collections/collection[1]/image[1]/thumbnail/@width + 18) + 65"/>
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+ <title>
+ <xsl:value-of select="name"/>
+ </title>
+ <link rel="stylesheet" type="text/css">
+ <xsl:attribute name="href">cleanframes/<xsl:value-of select="$style"/></xsl:attribute>
+ </link>
+ </head>
+ <frameset rows="40,*" noresize="1" border="0">
+ <frame src="collect.html" name="collection"/>
+ <frameset cols="{$tsize},*" noresize="1" border="0">
+ <frame src="blank.html" name="mythmbs"/>
+ <frame src="blank.html" name="image"/>
+ </frameset>
+ </frameset>
+ </html>
+ <exsl:document href="collect.html">
+ <xsl:call-template name="createCollectionIndexPage"/>
+ </exsl:document>
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create a blank page ** -->
+<!-- ** as a starting page when more than one collection is used ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createBlankPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+ <title>
+ <xsl:value-of select="name"/>
+ </title>
+ <link rel="stylesheet" type="text/css">
+ <xsl:attribute name="href">cleanframes/<xsl:value-of select="$style"/></xsl:attribute>
+ </link>
+ </head>
+ <body id="collectionPage">
+ <xsl:value-of select="title"/>
+ </body>
+
+ </html>
+</xsl:template>
+
+
+<!-- ********************************************************************* -->
+<!-- ** the beginning of all ** -->
+<!-- ********************************************************************* -->
+<xsl:template match="/">
+ <xsl:choose>
+ <xsl:when test="count(collections/collection) &gt; 1">
+ <xsl:call-template name="createCollectionFrameSetPage"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="collections/collection">
+ <xsl:call-template name="createFrameSetPage"/>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ <exsl:document href="blank.html">
+ <xsl:call-template name="createBlankPage"/>
+ </exsl:document>
+</xsl:template>
+
+</xsl:transform>
diff --git a/kipi-plugins/htmlexport/themes/cleanframes/yellow.css b/kipi-plugins/htmlexport/themes/cleanframes/yellow.css
new file mode 100644
index 0000000..5f99f24
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/cleanframes/yellow.css
@@ -0,0 +1,82 @@
+body {
+ background-color: #FFFF33; /*background behind thumbnails, outside boxes*/
+ color: #000055; /*default text color*/
+ font-size: 14pt;
+ text-align: center;
+ font-family: Bitstream Vera Serif, serif;
+ margin: 0in;
+ padding: 0in;
+}
+
+a { /*links (album titles)*/
+ color: #FFFF33;
+ text-decoration: none;
+}
+
+a:hover { /*links when mouse is over them (album titles)*/
+ color: #FFFFFF;
+ text-decoration: underline;
+}
+
+h1 { /*album title above thumbnails*/
+ padding-top: 0.1em;
+ color: #FF4400;
+ font-size: 14pt;
+}
+
+/* Collection page */
+#collectionPage h1 {
+ margin-top: 12px;
+}
+
+#collectionPage ul { /*affects list of thumbnails*/
+ padding: 0;
+ padding-left: 5%;
+ text-align: center;
+ width: 95%
+}
+
+#collectionPage li { /*affects stuff in boxes with thumbnails*/
+ display: block;
+ float: left;
+ margin-left: 6px;
+ margin-top: 6px;
+ padding: 5px;
+ color: #FFFF33;
+ font-size: 8pt;
+ background-color: #FF4400;
+ border: 1px solid #FFFF33;
+}
+
+/* Blank Page */
+#blankPage {
+ background-color: #FFFFFF;
+}
+
+/* Collect Page */
+#collectPage { /*album titles at top*/
+ background-color: #FF3300;
+ font-size: 12pt;
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ color: #FFFF44; /*number of pics in collection*/
+}
+
+
+/* Image page */
+#imagePage {
+ padding:.5em;
+ background-color:#FFFF33; /*background color behind the big image*/
+}
+
+
+#caption { /*caption below photo*/
+ padding-bottom:1em;
+ color: #CC2200;
+ font-size: 16pt;
+}
+
+#imagePage img {
+ border: 1px solid #CECECE; /*border around picture*/
+}
diff --git a/kipi-plugins/htmlexport/themes/frames/Makefile.am b/kipi-plugins/htmlexport/themes/frames/Makefile.am
new file mode 100644
index 0000000..b776406
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/frames/Makefile.am
@@ -0,0 +1,5 @@
+themedir=$(kde_datadir)/kipiplugin_htmlexport/themes/frames
+theme_DATA= \
+ frames.desktop \
+ style.css \
+ template.xsl
diff --git a/kipi-plugins/htmlexport/themes/frames/frames.desktop b/kipi-plugins/htmlexport/themes/frames/frames.desktop
new file mode 100644
index 0000000..fba9f70
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/frames/frames.desktop
@@ -0,0 +1,49 @@
+[Desktop Entry]
+Name=Frames
+Name[ca]=Marcs
+Name[da]=Rammer
+Name[de]=Rahmen
+Name[el]=Καρέ
+Name[es]=Marcos
+Name[et]=Raamid
+Name[is]=Rammar
+Name[it]=Riquadri
+Name[ja]=フレーム
+Name[nds]=Rahmens
+Name[pl]=Ramki
+Name[pt]=Molduras
+Name[pt_BR]=Bordas
+Name[sr]=Оквири
+Name[sr@Latn]=Okviri
+Name[sv]=Ramar
+Name[xx]=xxFramesxx
+Name[zh_CN]=像框
+Comment=A frame theme
+Comment[ca]=Un tema de marcs
+Comment[da]=Et tema med rammer
+Comment[de]=Ein Rahmen-Stil
+Comment[el]=Ένα θέμα καρέ
+Comment[es]=Un tema con marcos
+Comment[et]=Raamiteema
+Comment[fr]=Un thème avec frame
+Comment[is]=Þema með römmum
+Comment[it]=Un tema a riquadri
+Comment[ja]=フレームテーマ
+Comment[nds]=En Rahmen-Muster
+Comment[nl]=Een frame-thema
+Comment[pl]=Motyw oparty na ramkach
+Comment[pt]=Um tema de molduras
+Comment[pt_BR]=Um tema de bordas
+Comment[sr]=Тема оквира
+Comment[sr@Latn]=Tema okvira
+Comment[sv]=Ett tema med ramar
+Comment[xx]=xxA frame themexx
+Comment[zh_CN]=像框主题
+
+[X-HTMLExport Author]
+Name=Ruediger Bente
+Name[nds]=Rüdiger Bente
+Name[sr]=Рудигер Бенте
+Name[sr@Latn]=Rudiger Bente
+Name[xx]=xxRuediger Bentexx
+Url=mailto:ruediger.bente@gmx.de
diff --git a/kipi-plugins/htmlexport/themes/frames/style.css b/kipi-plugins/htmlexport/themes/frames/style.css
new file mode 100644
index 0000000..68c3ae9
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/frames/style.css
@@ -0,0 +1,121 @@
+body {
+ background-color: #123456;
+ color: black;
+ margin: 0;
+ padding: 0;
+}
+
+a {
+ color: #2f5d2c;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #456ff3;
+ text-decoration: underline;
+}
+
+h1 {
+ padding: 0;
+ margin: 0;
+ padding-top: 0.1em;
+ padding-bottom: 0.5em;
+ color: #EEEE20;
+ font-size: 150%;
+ font-family: Bitstream Vera Serif, serif;
+ background-color: #123456;
+ border-bottom: 1px dashed #cccbb9;
+ border-top: 1px dashed #cccbb9;
+ text-align: center;
+}
+
+#content {
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ text-align: center;
+}
+
+/* Collection page */
+#collectionPage ul {
+ padding: 0;
+ text-align: center;
+}
+
+#collectionPage li {
+ display: block;
+ float: left;
+ text-align: center;
+ margin: 6px;
+ padding: 5px;
+ background-color: #ffffbb;
+ border: 1px solid #000000;
+}
+
+
+#collectionPage img {
+ border: 0;
+}
+
+#collectionPage .image {
+ float: center;
+ text-align: center;
+ margin: 6px;
+}
+
+/* Collect Page */
+
+#collectPage {
+ background-color: #012345;
+}
+
+#collectPage a:hover {
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ text-align: center;
+ color: #ff5d2c;
+
+ text-decoration: underline;
+}
+#collectPage a {
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ text-align: center;
+ color: #c5cf13;
+ text-decoration: none;
+}
+#CollectPageContent {
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ text-align: center;
+ color: #ffffff;
+}
+
+
+/* Image page */
+#imagePage {
+ background-color:#123456;
+}
+
+#caption {
+ background-color:#123456;
+}
+
+#imagePage h1 {
+ text-align:center;
+ border: 1px solid #123456;
+ background-color: #123456;
+}
+}
+#nav {
+ background-color:#123456;
+ float: right;
+}
+
+#imagePage img {
+ text-align: right;
+ border: 1px solid #CECECE;
+}
diff --git a/kipi-plugins/htmlexport/themes/frames/template.xsl b/kipi-plugins/htmlexport/themes/frames/template.xsl
new file mode 100644
index 0000000..5626b6a
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/frames/template.xsl
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE stylesheet [
+<!ENTITY raquo "&#187;" >
+<!ENTITY blank "&#160;" >
+]>
+
+<xsl:transform version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl">
+
+<!-- ********************************************************************* -->
+<!-- ** Create single image page for each imag ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createImagePage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="title"/></title>
+ <link rel="stylesheet" type="text/css" href="../frames/style.css"/>
+ </head>
+ <body id="imagePage">
+ <h1>
+ <span>
+ <xsl:value-of select="../name"/>
+ </span>
+ </h1>
+ <div id="imagePage">
+ <table border="0" width="100%">
+ <tr>
+ <td align="center">
+ <img src="{full/@fileName}" width="{full/@width}" height="{full/@height}" />
+ <xsl:if test="original/@fileName != ''">
+ <p>
+ <a href="{original/@fileName}"><xsl:value-of select="$i18nOriginalImage"/></a>
+ (<xsl:value-of select="original/@width"/>x<xsl:value-of select="original/@height"/>)
+ </p>
+ </xsl:if>
+´ </td>
+ </tr>
+ </table>
+ <p>
+ <xsl:value-of select="description"/>
+ </p>
+
+ </div>
+ <h1>
+ <span>
+ &raquo; <xsl:value-of select="title"/>
+ (<xsl:value-of select="position()"/>/<xsl:value-of select="last()"/>)
+ &raquo;
+ </span>
+ </h1>
+ </body>
+ </html>
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create thumbnail page for each collection ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createThumbnailPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="name"/></title>
+ <link rel="stylesheet" type="text/css" href="frames/style.css"/>
+ </head>
+ <body id="collectionPage">
+ <div id="content">
+ <ul>
+ <xsl:variable name="folder" select='fileName'/>
+ <xsl:for-each select="image">
+ <li>
+ <a href="{$folder}/{full/@fileName}.html" target="image">
+ <img src="{$folder}/{thumbnail/@fileName}" width="{thumbnail/@width}" height="{thumbnail/@height}"/>
+ </a>
+ <xsl:value-of select="title"/>
+ (<xsl:value-of select="position()"/>/<xsl:value-of select="last()"/>)
+ </li>
+ <exsl:document href='{$folder}/{full/@fileName}.html'>
+ <xsl:call-template name="createImagePage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </ul>
+ </div>
+ </body>
+ </html>
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create frameset page if only one collection ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createFrameSetPage">
+<!-- ** create variable tsize for the width of the thumbnails frame ** -->
+<!-- ** add 50 pixel to tsize for the border around the thumbnail ** -->
+ <xsl:variable name="tsize" select="image[1]/thumbnail/@width + 50"/>
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+ <title>
+ <xsl:value-of select="name"/>
+ </title>
+ <link rel="stylesheet" type="text/css" href="frames/style.css"/>
+ </head>
+ <frameset cols="{$tsize},*" noresize="1" border="0">
+ <frame src="thmbs.html" name="mythmbs"/>
+ <frame src="blank.html" name="image"/>
+ </frameset>
+ <exsl:document href="thmbs.html">
+ <xsl:call-template name="createThumbnailPage"/>
+ </exsl:document>
+ </html>
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create the collection index page when more than one collection ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createCollectionIndexPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="$i18nCollectionList"/></title>
+ <link rel="stylesheet" type="text/css" href="frames/style.css"/>
+ </head>
+ <body id="collectPage">
+ <div id="CollectPageContent">
+ <xsl:for-each select="collections/collection">
+ &blank;
+ <a href="Thmbs{fileName}.html" target="mythmbs">
+ <xsl:value-of select="name"/>
+
+ </a>
+ <xsl:for-each select="image">
+ <xsl:choose>
+ <xsl:when test="position()=last()">
+ (<xsl:value-of select="last()"/>)
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ <exsl:document href="Thmbs{fileName}.html">
+ <xsl:call-template name="createThumbnailPage"/>
+ </exsl:document>
+
+ </xsl:for-each>
+ </div> <!-- /content -->
+ </body>
+ </html>
+
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create the frameset page when more than one collection ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createCollectionFrameSetPage">
+<!-- ** create variable tsize for the width of the thumbnails frame ** -->
+<!-- ** add 50 pixel to tsize for the border around the thumbnail ** -->
+ <xsl:variable name="tsize" select="collections/collection[1]/image[1]/thumbnail/@width + 50"/>
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+ <title>
+ <xsl:value-of select="name"/>
+ </title>
+ <link rel="stylesheet" type="text/css" href="frames/style.css"/>
+ </head>
+ <frameset rows="5%,*" noresize="1" border="0">
+ <frame src="collect.html" name="collection"/>
+ <frameset cols="{$tsize},*" noresize="1" border="0">
+ <frame src="blank.html" name="mythmbs"/>
+ <frame src="blank.html" name="image"/>
+ </frameset>
+ </frameset>
+ </html>
+ <exsl:document href="collect.html">
+ <xsl:call-template name="createCollectionIndexPage"/>
+ </exsl:document>
+</xsl:template>
+
+<!-- ********************************************************************* -->
+<!-- ** Create a blank page ** -->
+<!-- ** as a starting page when more than one collection is used ** -->
+<!-- ********************************************************************* -->
+<xsl:template name="createBlankPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+ <title>
+ <xsl:value-of select="name"/>
+ </title>
+ <link rel="stylesheet" type="text/css" href="frames/style.css"/>
+ </head>
+ <body id="collectionPage">
+ <xsl:value-of select="title"/>
+ </body>
+
+ </html>
+</xsl:template>
+
+
+<!-- ********************************************************************* -->
+<!-- ** the beginning of all ** -->
+<!-- ********************************************************************* -->
+<xsl:template match="/">
+ <xsl:choose>
+ <xsl:when test="count(collections/collection) &gt; 1">
+ <xsl:call-template name="createCollectionFrameSetPage"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="collections/collection">
+ <xsl:call-template name="createFrameSetPage"/>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ <exsl:document href="blank.html">
+ <xsl:call-template name="createBlankPage"/>
+ </exsl:document>
+</xsl:template>
+
+</xsl:transform>
diff --git a/kipi-plugins/htmlexport/themes/matrix/Makefile.am b/kipi-plugins/htmlexport/themes/matrix/Makefile.am
new file mode 100644
index 0000000..4646fa0
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/matrix/Makefile.am
@@ -0,0 +1,6 @@
+themedir=$(kde_datadir)/kipiplugin_htmlexport/themes/matrix
+theme_DATA= \
+ matrix.desktop \
+ style.css \
+ template.xsl \
+ bg.png
diff --git a/kipi-plugins/htmlexport/themes/matrix/bg.png b/kipi-plugins/htmlexport/themes/matrix/bg.png
new file mode 100644
index 0000000..092589c
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/matrix/bg.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/matrix/matrix.desktop b/kipi-plugins/htmlexport/themes/matrix/matrix.desktop
new file mode 100644
index 0000000..cdca28a
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/matrix/matrix.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Name=Matrix
+Name[cy]=Matrics
+Name[pa]=ਮੈਟਰਿਕਸ
+Name[sr]=Матрикс
+Name[sr@Latn]=Matriks
+Name[xx]=xxMatrixxx
+Name[zh_CN]=黑客帝国
+Comment=Show your photos with Matrix style
+Comment[ca]=Visualitza les fotos amb l'estil Matrix
+Comment[cs]=Zobrazení obrázků ve stylu Matrix
+Comment[da]=Vis foto med Matrix-stil
+Comment[de]=Zeigt Ihre Fotos in einem Matrix-Stil
+Comment[el]=Εμφάνιση των φωτογραφιών σας με στυλ Matrix
+Comment[es]=Muestra sus fotografías con el estilo Matrix
+Comment[et]=Fotode näitamine Matrixi stiiliga
+Comment[fi]=Valokuvat Matrix-tyyliin esitettyinä
+Comment[fr]=Voir vos photos avec le style Matrix
+Comment[gl]=Mostra as fotos con estilo Matrix
+Comment[is]=Sýndu myndirnar þínar eins og í Matrix
+Comment[it]=Mostra le tue foto in stile Matrix
+Comment[ja]=写真を Matrix スタイルで表示
+Comment[nds]=Dien Biller in Matrix-Stil wiesen
+Comment[nl]=Afbeeldingsgalerij in de stijl van The Matrix
+Comment[pa]=ਆਪਣੀਆਂ ਫੋਟੋ ਮਟੈਰਕਿਸ ਸ਼ੈਲੀ 'ਚ ਵੇਖਾਓ
+Comment[pl]=Pokaż swoje zdjęcia w stylu Matrixa
+Comment[pt]=A suas fotos no estilo Matrix
+Comment[pt_BR]=Mostrar suas fotos com estilo Matrix
+Comment[sr]=Прикажите ваше слике у Матрикс стилу
+Comment[sr@Latn]=Prikažite vaše slike u Matriks stilu
+Comment[sv]=Visa foton med Matrix-stil
+Comment[xx]=xxShow your photos with Matrix stylexx
+Comment[zh_CN]=以黑客帝国风格显示您的照片
+
+[X-HTMLExport Author]
+Name=Aurélien Gâteau
+Name[sr]=Орелиен Гато
+Name[sr@Latn]=Orelien Gato
+Name[xx]=xxAurélien Gâteauxx
+Url=mailto:aurelien.gateau@free.fr
diff --git a/kipi-plugins/htmlexport/themes/matrix/style.css b/kipi-plugins/htmlexport/themes/matrix/style.css
new file mode 100644
index 0000000..fe5ec5d
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/matrix/style.css
@@ -0,0 +1,82 @@
+body {
+ background-color: black;
+ color: green;
+ margin: 0;
+}
+
+a {
+ color: #0c0;
+}
+
+a:hover {
+ color: #0f0;
+}
+
+h1 {
+ padding-bottom: 6px;
+ margin-bottom: 0px;
+ color: #0f0;
+ font-size: 16px;
+}
+
+img {
+ border: 0;
+}
+
+#content {
+ background-image: url("bg.png");
+ background-color: #020;
+ padding: 6px;
+ border-top: 2px solid #080;
+ border-bottom: 2px solid #080;
+}
+
+a.imageLink {
+ background-color: #040;
+ border: 1px solid #0c0;
+ padding: 6px;
+ display: block;
+ text-align: center;
+ text-decoration: none;
+}
+
+a.imageLink:hover {
+ border: 1px solid #0f0;
+ background-color: #050;
+}
+
+/* collectionPage */
+#collectionPage ul {
+ list-style-type: none;
+}
+
+#collectionPage li {
+ float: left;
+ margin: 6px;
+}
+
+
+/* imagePage */
+#imagePage #content {
+ text-align: center;
+ color: #0f0;
+}
+
+#full {
+ margin: auto;
+}
+
+#previous {
+ float: left;
+}
+
+#next {
+ float: right;
+}
+
+.endOfCollection {
+ padding: 6px;
+ background-color: #040;
+ border: 1px dotted #080;
+ color: #080;
+}
diff --git a/kipi-plugins/htmlexport/themes/matrix/template.xsl b/kipi-plugins/htmlexport/themes/matrix/template.xsl
new file mode 100644
index 0000000..c56d3cf
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/matrix/template.xsl
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE stylesheet [
+<!ENTITY raquo "&#187;">
+]>
+
+<xsl:transform version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl">
+
+<xsl:template name="thumbnailLink">
+ <xsl:param name="text"/>
+ <xsl:param name="folder" select="'.'"/>
+ <a class="imageLink" href="{$folder}/{full/@fileName}.html">
+ <img src="{$folder}/{thumbnail/@fileName}" width="{thumbnail/@width}" height="{thumbnail/@height}" />
+ <br/>
+ <xsl:value-of select="$text"/>
+ </a>
+</xsl:template>
+
+<xsl:template name="imagePage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="title"/></title>
+ <link rel="stylesheet" type="text/css" href="../matrix/style.css"/>
+ </head>
+ <body id="imagePage">
+ <h1>
+ <div id="caption">
+ <xsl:choose>
+ <xsl:when test="count(/collections/collection) &gt; 1">
+ <a href="../index.html"><xsl:value-of select="$i18nCollectionList"/></a>
+ &raquo;
+ <a href="../{../fileName}.html"><xsl:value-of select="../name"/></a>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="../index.html"><xsl:value-of select="../name"/></a>
+ </xsl:otherwise>
+ </xsl:choose>
+ &raquo; <xsl:value-of select="title"/>
+ (<xsl:value-of select="position()"/>/<xsl:value-of select="last()"/>)
+ </div>
+ </h1>
+
+ <div id="content">
+ <div>
+ <div id="previous">
+ <xsl:choose>
+ <xsl:when test="position() &gt; 1">
+ <xsl:for-each select="preceding-sibling::image[position()=1]">
+ <xsl:call-template name="thumbnailLink">
+ <xsl:with-param name="text">Previous</xsl:with-param>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <div class="endOfCollection">
+ Previous
+ </div>
+ </xsl:otherwise>
+ </xsl:choose>
+ </div>
+
+ <div id="next">
+ <xsl:choose>
+ <xsl:when test="position() &lt; last()">
+ <xsl:for-each select="following-sibling::image[position()=1]">
+ <xsl:call-template name="thumbnailLink">
+ <xsl:with-param name="text">Next</xsl:with-param>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <div class="endOfCollection">
+ Next
+ </div>
+ </xsl:otherwise>
+ </xsl:choose>
+ </div>
+
+ <div id="full">
+ <img src="{full/@fileName}" width="{full/@width}" height="{full/@height}" />
+ <p>
+ <xsl:value-of select="description"/>
+ </p>
+ <xsl:if test="original/@fileName != ''">
+ <p>
+ <a href="{original/@fileName}"><xsl:value-of select="$i18nOriginalImage"/></a>
+ (<xsl:value-of select="original/@width"/>x<xsl:value-of select="original/@height"/>)
+ </p>
+ </xsl:if>
+ </div>
+ <br style="clear:both"/>
+ </div>
+
+ </div>
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="collectionPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="name"/></title>
+ <link rel="stylesheet" type="text/css" href="matrix/style.css"/>
+ </head>
+ <body id="collectionPage">
+ <h1>
+ <xsl:if test="count(/collections/collection) &gt; 1">
+ <a href="index.html"><xsl:value-of select="$i18nCollectionList"/></a>
+ &raquo;
+ </xsl:if>
+ <xsl:value-of select="name"/>
+ </h1>
+ <div id="content">
+ <ul>
+ <xsl:variable name="folder" select='fileName'/>
+ <xsl:for-each select="image">
+ <li>
+ <xsl:call-template name="thumbnailLink">
+ <xsl:with-param name="text"><xsl:value-of select="title"/></xsl:with-param>
+ <xsl:with-param name="folder"><xsl:value-of select="$folder"/></xsl:with-param>
+ </xsl:call-template>
+ </li>
+ <exsl:document href='{$folder}/{full/@fileName}.html'>
+ <xsl:call-template name="imagePage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </ul>
+ <br style="clear:both"/>
+ </div> <!-- /content -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="collectionListPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="$i18nCollectionList"/></title>
+ <link rel="stylesheet" type="text/css" href="matrix/style.css"/>
+ </head>
+ <body>
+ <h1><xsl:value-of select="$i18nCollectionList"/></h1>
+ <div id="content">
+ <ul>
+ <xsl:for-each select="collections/collection">
+ <li>
+ <a href="{fileName}.html">
+ <!-- Use first image as collection image -->
+ <img src="{fileName}/{image[1]/thumbnail/@fileName}"
+ width="{image[1]/thumbnail/@width}"
+ height="{image[1]/thumbnail/@height}" />
+ <br />
+ <xsl:value-of select="name"/>
+ </a>
+ </li>
+ <exsl:document href="{fileName}.html">
+ <xsl:call-template name="collectionPage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </ul>
+ </div> <!-- /content -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template match="/">
+ <xsl:choose>
+ <xsl:when test="count(collections/collection) &gt; 1">
+ <xsl:call-template name="collectionListPage"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="collections/collection">
+ <xsl:call-template name="collectionPage"/>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+</xsl:transform>
diff --git a/kipi-plugins/htmlexport/themes/s0/Makefile.am b/kipi-plugins/htmlexport/themes/s0/Makefile.am
new file mode 100644
index 0000000..56819c6
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/Makefile.am
@@ -0,0 +1,10 @@
+themedir=$(kde_datadir)/kipiplugin_htmlexport/themes/s0
+theme_DATA= \
+ s0.desktop \
+ style.css \
+ template.xsl \
+ next_disabled.png \
+ next.png \
+ previous_disabled.png \
+ previous.png \
+ up.png
diff --git a/kipi-plugins/htmlexport/themes/s0/arrows_source.svg b/kipi-plugins/htmlexport/themes/s0/arrows_source.svg
new file mode 100644
index 0000000..94dc9d8
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/arrows_source.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ inkscape:label="Pozadí"
+ sodipodi:version="0.32"
+ inkscape:version="0.44"
+ sodipodi:docbase="/home/pvanek/.kde/share/apps/kipiplugin_htmlexport/themes/s0"
+ sodipodi:docname="arrows_source.svg">
+ <defs
+ id="defs3" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="375"
+ inkscape:cy="640"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1008"
+ inkscape:window-height="568"
+ inkscape:window-x="597"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata6">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Vrstva 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ id="g1897"
+ transform="matrix(0.304031,0,0,0.304031,67.82486,264.6121)"
+ inkscape:export-filename="/home/pvanek/.kde/share/apps/kipiplugin_htmlexport/themes/s0/previous.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ d="M 63.356906,268.3638 C 68.150409,268.96549 72.961517,269.80549 77.770346,270.52824 C 85.279268,272.33972 92.962476,273.32217 100.58489,274.42474 C 107.74376,276.7477 114.89455,276.13083 122.20574,275.97499 C 129.15364,274.96016 136.15306,274.7825 143.15035,274.49274 C 151.05339,273.98159 158.88992,272.77624 166.81168,272.17182 C 175.77936,271.54894 184.70055,270.23791 193.64913,269.27076 C 197.21733,268.90294 200.80674,268.87692 204.38436,268.68006 L 170.49858,293.51424 C 167.0148,293.73329 163.51862,293.79055 160.04503,294.17152 C 151.12843,295.19761 142.21996,296.3815 133.25971,296.95539 C 125.29993,297.81239 117.36757,299.10166 109.35054,299.23145 C 102.39265,299.69091 95.43747,300.14892 88.494721,300.81964 C 81.006837,300.53779 73.543958,300.63371 66.241419,298.44319 C 58.632507,297.32996 51.034547,296.18319 43.472718,294.78103 C 38.591326,294.10881 33.704773,293.07986 28.755193,293.50342 L 63.356906,268.3638 z "
+ id="path1875"
+ style="fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 96.944534,257.45706 C 139.44398,231.80712 114.57957,246.84839 65.104202,275.08853 C 133.96893,236.2401 50.031929,283.54396 25.129756,295.43671 C -23.969475,322.27503 46.123664,278.28226 26.354652,295.38329 C 21.685568,304.00696 25.873082,308.32943 29.873473,316.03635 C 36.642466,324.11763 45.985884,328.64394 55.142845,333.39717 C 59.948383,335.47305 64.86154,337.27004 69.731528,339.17816 L 35.198639,362.37346 C 30.283858,360.33775 25.331494,358.38952 20.497071,356.16324 C 10.831338,350.99889 1.1079084,345.86441 -5.9976513,337.23382 C -11.376742,328.87023 -15.654417,321.85833 -12.065204,311.72237 C 6.1559472,291.95874 32.857631,282.24502 56.698605,270.30232 C 107.62259,246.56091 -17.139711,313.09307 97.076719,249.2384 C 144.2574,222.38705 7.4666151,300.65302 130.25984,230.80797 L 96.944534,257.45706 z "
+ id="path1877"
+ style="fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <g
+ id="g1905"
+ transform="matrix(0.199566,0,0,0.199566,105.9595,235.9365)"
+ inkscape:export-filename="/home/pvanek/.kde/share/apps/kipiplugin_htmlexport/themes/s0/up.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ d="M 324.69091,498.00412 C 322.88411,511.7913 320.15948,525.48918 317.84603,539.21352 C 313.08982,565.92245 308.88602,592.73945 303.70746,619.37077 C 300.22117,636.79873 296.66996,654.17167 294.16594,671.76495 C 293.98863,673.62773 293.81131,675.49052 293.634,677.3533 L 256.54766,695.75184 C 256.77835,693.82184 257.00903,691.89184 257.23972,689.96184 C 260.05882,672.03001 264.11467,654.41824 268.01517,636.69137 C 273.29979,610.18028 278.36921,583.60904 282.04642,556.81973 C 283.57634,543.67664 285.90909,530.51572 286.73766,517.34226 L 324.69091,498.00412 z "
+ id="path1887"
+ style="fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 254.48404,538.69587 C 255.82349,538.25296 256.8928,537.32325 258.09718,536.63695 C 199.23703,574.97769 223.02332,557.70685 235.20025,546.66092 C 241.9451,539.70877 249.23658,533.32173 256.3914,526.80118 C 272.42754,512.3043 291.71445,501.82229 312.50877,496.46461 C 320.39532,494.2497 328.08272,495.74452 335.9219,496.76655 C 347.47734,504.07102 357.36853,513.76945 367.44264,522.96097 C 376.59961,530.97282 384.20817,540.4807 392.16163,549.63377 C 400.39322,559.84215 409.39171,569.3809 417.89851,579.35329 C 418.90718,580.55402 419.91585,581.75475 420.92452,582.95548 L 385.19139,604.3717 C 384.21261,603.14931 383.23384,601.92692 382.25507,600.70453 C 374.06893,590.5095 365.46342,580.67673 356.81818,570.86646 C 348.96697,561.84215 341.07307,552.83371 332.37615,544.59323 C 322.92118,535.70134 313.68674,525.76285 301.48735,520.79351 C 293.97157,520.23081 286.65386,519.40788 279.28802,521.91064 C 245.01712,533.9765 317.41774,490.08881 294.98556,511.00559 C 287.83109,517.5408 280.42934,523.83435 273.6547,530.76291 C 258.7134,545.76926 240.64171,556.42674 221.16873,565.34497 L 254.48404,538.69587 z "
+ id="path1895"
+ style="fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <g
+ id="g1923"
+ transform="matrix(0.92827,0,0,0.92827,15.49829,31.2752)"
+ inkscape:export-filename="/home/pvanek/.kde/share/apps/kipiplugin_htmlexport/themes/s0/next.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ d="M 228.17492,353.96275 C 230.77699,354.23536 233.32909,353.82734 235.90496,353.49579 C 243.67834,352.08929 251.42686,350.57548 259.25099,349.47358 C 264.50999,348.74717 269.79812,348.32115 275.09724,348.05727 C 277.6397,347.98238 280.1839,348.01846 282.727,348.02886 C 285.44797,347.87423 288.11518,348.16824 290.80905,348.41165 C 291.64547,348.54396 292.48903,348.61797 293.32902,348.72113 L 281.34439,357.2077 C 280.51082,357.09831 279.67692,356.99137 278.84367,356.87954 C 276.17988,356.73088 273.51728,356.53916 270.84128,356.65579 C 268.33339,356.64555 265.82527,356.6245 263.31762,356.67515 C 258.22739,356.84018 253.13971,357.1262 248.08955,357.82502 C 240.13764,358.95539 232.28776,360.59514 224.39917,362.08963 C 221.62285,362.43418 218.86964,362.81315 216.06432,362.76162 L 228.17492,353.96275 z "
+ id="path1909"
+ style="fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 270.17492,326.96275 C 272.3408,327.22355 274.18293,328.83604 276.05396,329.93845 C 279.35852,331.8196 282.47525,333.97769 285.54925,336.20728 C 288.76648,338.81735 292.05249,341.30353 295.11313,344.09652 C 297.84125,346.12965 298.10789,348.36317 298.66435,351.31528 C 295.55472,358.34571 286.71683,360.71608 279.84051,363.60962 C 276.65524,365.07555 273.63487,366.85979 270.54231,368.50532 C 286.27346,359.47499 285.38903,359.97033 267.92491,370.05366 L 279.30085,360.85231 C 263.44757,370.03247 264.31015,369.53038 281.89611,359.35904 C 284.9911,357.70659 288.04208,355.95974 291.2682,354.56897 C 302.0255,349.50167 276.26143,364.90467 285.4166,357.74642 C 284.93996,355.41755 285.35921,353.48797 282.69803,351.73058 C 279.73787,348.9329 276.58718,346.37565 273.26662,344.00725 C 270.24056,341.80199 267.17909,339.6542 263.8881,337.85268 C 262.01122,336.84334 260.28024,335.52769 258.06432,335.76162 L 270.17492,326.96275 z "
+ id="path1921"
+ style="fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <g
+ id="g1927"
+ transform="matrix(0.304031,0,0,0.304031,61.578,328.1894)"
+ style="fill:#9ea59e;fill-opacity:1"
+ inkscape:export-filename="/home/pvanek/.kde/share/apps/kipiplugin_htmlexport/themes/s0/previous_disabled.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ d="M 63.356906,268.3638 C 68.150409,268.96549 72.961517,269.80549 77.770346,270.52824 C 85.279268,272.33972 92.962476,273.32217 100.58489,274.42474 C 107.74376,276.7477 114.89455,276.13083 122.20574,275.97499 C 129.15364,274.96016 136.15306,274.7825 143.15035,274.49274 C 151.05339,273.98159 158.88992,272.77624 166.81168,272.17182 C 175.77936,271.54894 184.70055,270.23791 193.64913,269.27076 C 197.21733,268.90294 200.80674,268.87692 204.38436,268.68006 L 170.49858,293.51424 C 167.0148,293.73329 163.51862,293.79055 160.04503,294.17152 C 151.12843,295.19761 142.21996,296.3815 133.25971,296.95539 C 125.29993,297.81239 117.36757,299.10166 109.35054,299.23145 C 102.39265,299.69091 95.43747,300.14892 88.494721,300.81964 C 81.006837,300.53779 73.543958,300.63371 66.241419,298.44319 C 58.632507,297.32996 51.034547,296.18319 43.472718,294.78103 C 38.591326,294.10881 33.704773,293.07986 28.755193,293.50342 L 63.356906,268.3638 z "
+ id="path1929"
+ style="fill:#9ea59e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 96.944534,257.45706 C 139.44398,231.80712 114.57957,246.84839 65.104202,275.08853 C 133.96893,236.2401 50.031929,283.54396 25.129756,295.43671 C -23.969475,322.27503 46.123664,278.28226 26.354652,295.38329 C 21.685568,304.00696 25.873082,308.32943 29.873473,316.03635 C 36.642466,324.11763 45.985884,328.64394 55.142845,333.39717 C 59.948383,335.47305 64.86154,337.27004 69.731528,339.17816 L 35.198639,362.37346 C 30.283858,360.33775 25.331494,358.38952 20.497071,356.16324 C 10.831338,350.99889 1.1079084,345.86441 -5.9976513,337.23382 C -11.376742,328.87023 -15.654417,321.85833 -12.065204,311.72237 C 6.1559472,291.95874 32.857631,282.24502 56.698605,270.30232 C 107.62259,246.56091 -17.139711,313.09307 97.076719,249.2384 C 144.2574,222.38705 7.4666151,300.65302 130.25984,230.80797 L 96.944534,257.45706 z "
+ id="path1931"
+ style="fill:#9ea59e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <g
+ id="g1939"
+ transform="matrix(0.92827,0,0,0.92827,9.2514,94.8525)"
+ style="fill:#9ea59e;fill-opacity:1"
+ inkscape:export-filename="/home/pvanek/.kde/share/apps/kipiplugin_htmlexport/themes/s0/next_disabled.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ d="M 228.17492,353.96275 C 230.77699,354.23536 233.32909,353.82734 235.90496,353.49579 C 243.67834,352.08929 251.42686,350.57548 259.25099,349.47358 C 264.50999,348.74717 269.79812,348.32115 275.09724,348.05727 C 277.6397,347.98238 280.1839,348.01846 282.727,348.02886 C 285.44797,347.87423 288.11518,348.16824 290.80905,348.41165 C 291.64547,348.54396 292.48903,348.61797 293.32902,348.72113 L 281.34439,357.2077 C 280.51082,357.09831 279.67692,356.99137 278.84367,356.87954 C 276.17988,356.73088 273.51728,356.53916 270.84128,356.65579 C 268.33339,356.64555 265.82527,356.6245 263.31762,356.67515 C 258.22739,356.84018 253.13971,357.1262 248.08955,357.82502 C 240.13764,358.95539 232.28776,360.59514 224.39917,362.08963 C 221.62285,362.43418 218.86964,362.81315 216.06432,362.76162 L 228.17492,353.96275 z "
+ id="path1941"
+ style="fill:#9ea59e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 270.17492,326.96275 C 272.3408,327.22355 274.18293,328.83604 276.05396,329.93845 C 279.35852,331.8196 282.47525,333.97769 285.54925,336.20728 C 288.76648,338.81735 292.05249,341.30353 295.11313,344.09652 C 297.84125,346.12965 298.10789,348.36317 298.66435,351.31528 C 295.55472,358.34571 286.71683,360.71608 279.84051,363.60962 C 276.65524,365.07555 273.63487,366.85979 270.54231,368.50532 C 286.27346,359.47499 285.38903,359.97033 267.92491,370.05366 L 279.30085,360.85231 C 263.44757,370.03247 264.31015,369.53038 281.89611,359.35904 C 284.9911,357.70659 288.04208,355.95974 291.2682,354.56897 C 302.0255,349.50167 276.26143,364.90467 285.4166,357.74642 C 284.93996,355.41755 285.35921,353.48797 282.69803,351.73058 C 279.73787,348.9329 276.58718,346.37565 273.26662,344.00725 C 270.24056,341.80199 267.17909,339.6542 263.8881,337.85268 C 262.01122,336.84334 260.28024,335.52769 258.06432,335.76162 L 270.17492,326.96275 z "
+ id="path1943"
+ style="fill:#9ea59e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ </g>
+</svg>
diff --git a/kipi-plugins/htmlexport/themes/s0/next.png b/kipi-plugins/htmlexport/themes/s0/next.png
new file mode 100644
index 0000000..3b0cde1
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/next.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/s0/next_disabled.png b/kipi-plugins/htmlexport/themes/s0/next_disabled.png
new file mode 100644
index 0000000..b19ed38
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/next_disabled.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/s0/previous.png b/kipi-plugins/htmlexport/themes/s0/previous.png
new file mode 100644
index 0000000..bc3e403
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/previous.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/s0/previous_disabled.png b/kipi-plugins/htmlexport/themes/s0/previous_disabled.png
new file mode 100644
index 0000000..9185e92
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/previous_disabled.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/s0/s0.desktop b/kipi-plugins/htmlexport/themes/s0/s0.desktop
new file mode 100644
index 0000000..78e3844
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/s0.desktop
@@ -0,0 +1,36 @@
+[Desktop Entry]
+Comment=Yet another nice theme. Very simple and clean look with "calligraphics" icons.
+Comment[ca]=Un altre tema agradable. D'aparença molt simple i neta, amb icones "cal·ligràfiques".
+Comment[da]=Yderligere et pænt tema. Meget enkelt og rent udseende med "kalligrafiske" ikoner.
+Comment[de]=Ein weiteres nettes Design. Sehr einfach und sauber aufgebaut. Es benutzt kalligraphische Symbole.
+Comment[el]=Ένα ακόμα ωραίο θέμα. Πολλή απλή εμφάνιση με "καλλιτεχνικά" εικονίδια.
+Comment[es]=Otro bonito tema. Aspecto muy sencillo y limpio con iconos «calligraphics».
+Comment[et]=Veel üks kena teema. Väga lihtne ja selge välimus ning "kalligraafilised" ikoonid.
+Comment[fr]=Encore un autre joli thème. Très simple et propre avec des icônes "calligraphiques".
+Comment[is]=Enn eitt sætt þema. Mjög einfalt og hreinlegt með "skrautskriftarlegum" táknmyndum.
+Comment[it]=Un altro bel tema. Aspetto semplice e pulito con icone «calligrafiche».
+Comment[ja]=もう一つの素晴しいテーマ。書道のアイコンを使った非常にシンプルですっきりしたテーマ。
+Comment[nds]=Noch en anner smuck Muster. Bannig eenfach un oprüümt, bruukt "kalligraafsche" Lüttbiller.
+Comment[nl]=Alweer een mooi thema. Erg eenvoudig en schoon uiterlijk met kaligrafische pictogrammen.
+Comment[pa]=ਹੋਰ ਵੀ ਸੋਹਣਾ ਸਰੂਪ ਹੈ। ਬਹੁਤ ਹੀ ਸਧਾਰਨ ਅਤੇ ਸਾਫ਼ ਦਿੱਖ ਵਾਲਾ "calligraphics" ਆਈਕਾਨਾਂ ਨਾਲ।
+Comment[pl]=Jeszcze jeden niezły motyw. Bardzo prosty i schludny, korzysta z ikon "calligraphics".
+Comment[pt]=Mais outro tema bonito. Aparência muito simples e limpa, com ícones "caligrafados".
+Comment[pt_BR]=Mais um bom tema. Muito simples e com aparência limpa com ícones "caligráficos".
+Comment[sr]=Још једна лепа тема. Веома једноставан и прегледан изглед са „калиграфским“ иконама.
+Comment[sr@Latn]=Još jedna lepa tema. Veoma jednostavan i pregledan izgled sa „kaligrafskim“ ikonama.
+Comment[sv]=Ytterligare ett snyggt tema. Mycket enkelt och rent utseende med "kalligrafiska" ikoner.
+Comment[xx]=xxYet another nice theme. Very simple and clean look with "calligraphics" icons.xx
+Comment[zh_CN]=另一个漂亮的主题,非常干净简练,使用书法风格的图标。
+Icon=
+Name=S0
+Name[sr]=СО
+Name[sr@Latn]=SO
+Name[xx]=xxS0xx
+
+[X-HTMLExport Author]
+Name=Petr Vaněk
+Name[sr]=Петр Ванек
+Name[sr@Latn]=Petr Vanek
+Name[xx]=xxPetr Vaněkxx
+Name[zh_CN]=Petr Vanek
+Url=mailto:petr@scribus.info
diff --git a/kipi-plugins/htmlexport/themes/s0/style.css b/kipi-plugins/htmlexport/themes/s0/style.css
new file mode 100644
index 0000000..2097e28
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/style.css
@@ -0,0 +1,112 @@
+body {
+ background-color: #ffffef;
+ color: black;
+ margin: 0;
+ font-family: sans-serif;
+ font-size: 12pt;
+}
+
+a {
+ color: #009d0b;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #008c00;
+ text-decoration: underline;
+}
+
+img {
+ border: 0px solid black;
+}
+
+h1 {
+ margin-top: 0.6em;
+ margin-bottom: 0.4em;
+ padding-left: 2em;
+ padding-top: 0.6em;
+ padding-bottom: 0.4em;
+ font-size: 100%;
+ background-color: #009d0b;
+ border: 2px solid #006a00;
+ border-left: 0px;
+ border-right: 0px;
+}
+h1 a {
+ color: #ffffef;
+}
+h1 a:hover {
+ color: #fffdaf;
+}
+
+.thumbnail {
+ display: inline;
+ float: left;
+ width: 160px;
+ height: 180px;
+ margin: 1em;
+ text-align: center;
+}
+.thumbnail img {
+ display: block;
+ border: 2px solid #006a00;
+}
+
+#footer {
+ clear: both;
+ margin: 1em;
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-bottom: 0px;
+ padding: 2em;
+ border: 2px solid #707070;
+ border-left: 0px;
+ border-right: 0px;
+ border-bottom: 0px;
+ color: #707070;
+ background-color: #a0a0a0;
+ font-size: 90%;
+}
+
+#navigation {
+ width: 100%;
+ text-align: center;
+}
+
+#content {
+ clear: both;
+ overflow: auto;
+ margin-top: 1em;
+ margin-left: 4em;
+ margin-right: 4em;
+}
+#content img {
+ border: 2px solid #006a00;
+}
+
+#collectionPage img {
+ display: block;
+}
+
+#previous {
+ float: left;
+ width: 33%;
+ text-align: right;
+}
+
+#next {
+ float: left;
+ width: 33%;
+ text-align: left;
+}
+
+#up {
+ float: left;
+ width: 33%;
+ text-align: center;
+}
+
+#imagePage #content {
+ text-align:center;
+ margin-top: 4em;
+}
diff --git a/kipi-plugins/htmlexport/themes/s0/template.xsl b/kipi-plugins/htmlexport/themes/s0/template.xsl
new file mode 100644
index 0000000..6f487f9
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/template.xsl
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE stylesheet [<!ENTITY raquo "&#187;">]>
+
+<xsl:transform version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl">
+
+<xsl:template name="imagePage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="title"/></title>
+ <link rel="stylesheet" type="text/css" href="../s0/style.css"/>
+ </head>
+ <body id="imagePage">
+
+ <h1>
+ <xsl:choose>
+ <xsl:when test="count(/collections/collection) &gt; 1">
+ <a href="../index.html"><xsl:value-of select="$i18nCollectionList"/></a>
+ &raquo;
+ <a href="../{../fileName}.html"><xsl:value-of select="../name"/></a>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="../index.html"><xsl:value-of select="../name"/></a>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ &raquo; <xsl:value-of select="title"/>
+ (<xsl:value-of select="position()"/>/<xsl:value-of select="last()"/>)
+ </h1>
+ <div id="navigation">
+ <div id="previous">
+ <xsl:choose>
+ <xsl:when test="position() &gt; 1">
+ <a href="{preceding-sibling::image[position()=1]/full/@fileName}.html">
+ <img src="../s0/previous.png" alt="{$i18nPrevious}" title="{$i18nPrevious}" />
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <img src="../s0/previous_disabled.png" alt="{$i18nPrevious}" title="{$i18nPrevious}" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </div>
+ <div id="up">
+ <a href="../index.html">
+ <img src="../s0/up.png" alt="{$i18nUp}" title="{$i18nUp}" />
+ </a>
+ </div>
+ <div id="next">
+ <xsl:choose>
+ <xsl:when test="position() &lt; last()">
+ <a href="{following-sibling::image[position()=1]/full/@fileName}.html">
+ <img src="../s0/next.png" alt="{$i18nNext}" title="{$i18nNext}" />
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <img src="../s0/next_disabled.png" alt="{$i18nNext}" title="{$i18nNext}" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </div>
+ </div>
+
+ <div id="content">
+ <img src="{full/@fileName}" width="{full/@width}" height="{full/@height}" />
+ <p>
+ <xsl:value-of select="description"/>
+ </p>
+ <xsl:if test="original/@fileName != ''">
+ <p>
+ <a href="{original/@fileName}"><xsl:value-of select="$i18nOriginalImage"/></a>
+ (<xsl:value-of select="original/@width"/>x<xsl:value-of select="original/@height"/>)
+ </p>
+ </xsl:if>
+ </div>
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="collectionPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="name"/></title>
+ <link rel="stylesheet" type="text/css" href="s0/style.css"/>
+ </head>
+ <body id="collectionPage">
+ <h1>
+ <xsl:if test="count(/collections/collection) &gt; 1">
+ <a href="index.html"><xsl:value-of select="$i18nCollectionList"/></a>
+ &raquo;
+ </xsl:if>
+ <xsl:value-of select="name"/>
+ </h1>
+ <div id="content">
+ <xsl:variable name="folder" select='fileName'/>
+ <xsl:for-each select="image">
+ <span class="thumbnail">
+ <a href='{$folder}/{full/@fileName}.html'>
+ <img src="{$folder}/{thumbnail/@fileName}" width="{thumbnail/@width}" height="{thumbnail/@height}" />
+ </a>
+ <a href='{$folder}/{full/@fileName}.html'>
+ <xsl:value-of select="title"/>
+ </a>
+ </span>
+ <exsl:document href='{$folder}/{full/@fileName}.html'>
+ <xsl:call-template name="imagePage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </div> <!-- /content -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="collectionListPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="$i18nCollectionList"/></title>
+ <link rel="stylesheet" type="text/css" href="s0/style.css"/>
+ </head>
+ <body>
+ <h1><xsl:value-of select="$i18nCollectionList"/></h1>
+ <div id="content">
+ <xsl:for-each select="collections/collection">
+ <span class="thumbnail">
+ <a href="{fileName}.html">
+ <!-- Use first image as collection image -->
+ <img src="{fileName}/{image[1]/thumbnail/@fileName}"
+ width="{image[1]/thumbnail/@width}"
+ height="{image[1]/thumbnail/@height}" />
+ <xsl:value-of select="name"/>
+ </a>
+ </span>
+ <exsl:document href="{fileName}.html">
+ <xsl:call-template name="collectionPage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </div> <!-- /content -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template match="/">
+ <xsl:choose>
+ <xsl:when test="count(collections/collection) &gt; 1">
+ <xsl:call-template name="collectionListPage"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="collections/collection">
+ <xsl:call-template name="collectionPage"/>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+</xsl:transform>
diff --git a/kipi-plugins/htmlexport/themes/s0/up.png b/kipi-plugins/htmlexport/themes/s0/up.png
new file mode 100644
index 0000000..958fdf4
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/s0/up.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/simple/Makefile.am b/kipi-plugins/htmlexport/themes/simple/Makefile.am
new file mode 100644
index 0000000..1915914
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/simple/Makefile.am
@@ -0,0 +1,6 @@
+themedir=$(kde_datadir)/kipiplugin_htmlexport/themes/simple
+theme_DATA= \
+ simple.desktop \
+ natural.css \
+ dark.css \
+ template.xsl
diff --git a/kipi-plugins/htmlexport/themes/simple/dark.css b/kipi-plugins/htmlexport/themes/simple/dark.css
new file mode 100644
index 0000000..4f417fd
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/simple/dark.css
@@ -0,0 +1,76 @@
+body {
+ background-color: black;
+ color: #888;
+ margin: 0;
+ padding: 0;
+}
+
+a {
+ color: #ff650c;
+ text-decoration: none;
+ border-bottom: 1px dotted #ff650c;
+}
+
+a:hover {
+ color: #ff9900;
+ border-bottom: 1px solid #ff9900;
+}
+
+h1 {
+ padding: 0;
+ margin: 0;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+
+ font-size: 120%;
+ font-family: Bitstream Vera Sans, sans-serif;
+ background-color: #222;
+ border-bottom: 1px solid #434343;
+ text-align: center;
+}
+
+#content {
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ text-align: center;
+}
+
+ul {
+ list-style-type: none;
+}
+
+li {
+ float: left;
+}
+
+img {
+ border: 1px solid #434343;
+}
+
+li a {
+ display: block;
+ margin: 6px;
+ padding: 5px;
+ background-color: #222;
+ border: 1px solid #434343;
+ text-align: center;
+}
+
+li a:hover {
+ border: 1px solid #ff9900;
+}
+
+/* Image page */
+#imagePage h1 {
+ text-align:left;
+}
+#nav {
+ float: right;
+}
+
+#imagePage img {
+ padding: 5px;
+ background-color: #222;
+ border: 1px solid #434343;
+}
diff --git a/kipi-plugins/htmlexport/themes/simple/natural.css b/kipi-plugins/htmlexport/themes/simple/natural.css
new file mode 100644
index 0000000..994b42a
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/simple/natural.css
@@ -0,0 +1,72 @@
+body {
+ background-color: #dddcca;
+ color: black;
+ margin: 0;
+ padding: 0;
+}
+
+a {
+ color: #2f5d9c;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #456ff3;
+ text-decoration: underline;
+}
+
+h1 {
+ padding: 0;
+ margin: 0;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+
+ color: #460;
+ font-size: 120%;
+ font-family: Bitstream Vera Serif, serif;
+ background-color: #fbfaf4;
+ border-bottom: 1px dashed #cccbb9;
+ text-align: center;
+}
+
+#content {
+ padding-top: 0.5em;
+ margin: 0 auto;
+ width: 95%;
+ text-align: center;
+}
+
+ul {
+ list-style-type: none;
+}
+
+li {
+ float: left;
+}
+
+li a {
+ display: block;
+ margin: 6px;
+ padding: 5px;
+ background-color: #eee;
+ border: 1px solid #cccbb9;
+ text-align: center;
+}
+
+li a:hover {
+ border: 1px solid #456ff3;
+}
+
+/* Image page */
+#imagePage h1 {
+ text-align:left;
+}
+#nav {
+ float: right;
+}
+
+#imagePage img {
+ padding: 5px;
+ background-color: #eee;
+ border: 1px solid #cccbb9;
+}
diff --git a/kipi-plugins/htmlexport/themes/simple/simple.desktop b/kipi-plugins/htmlexport/themes/simple/simple.desktop
new file mode 100644
index 0000000..1420447
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/simple/simple.desktop
@@ -0,0 +1,88 @@
+[Desktop Entry]
+Name=Simple
+Name[br]=Eeun
+Name[cs]=Jednoduchý
+Name[cy]=Syml
+Name[da]=Simpel
+Name[el]=Απλό
+Name[es]=Sencillo
+Name[et]=Lihtne
+Name[fi]=Yksinkertainen
+Name[ga]=Simplí
+Name[gl]=Simples
+Name[it]=Semplice
+Name[ja]=シンプル
+Name[nds]=Eenfach
+Name[nl]=Eenvoudig
+Name[pa]=ਸਧਾਰਨ
+Name[pl]=Prosty
+Name[pt]=Simples
+Name[sr]=Једноставно
+Name[sr@Latn]=Jednostavno
+Name[sv]=Enkelt
+Name[xx]=xxSimplexx
+Name[zh_CN]=简单
+Comment=A simple and light theme
+Comment[ca]=Un tema senzill i lluminós
+Comment[cs]=Jednoduché a malé téma
+Comment[da]=Et enkelt og lyst tema
+Comment[de]=Ein einfacher und leichter Stil
+Comment[el]=Ένα απλό και ελαφρύ θέμα
+Comment[es]=Un tema sencillo y ligero
+Comment[et]=Lihtne ja tagasihoidlik teema
+Comment[fi]=Yksinkertainen ja kevyt teema
+Comment[fr]=Un thème simple et lumineux
+Comment[ga]=Téama simplí éadrom
+Comment[gl]=Un tema sinxelo e lixeiro
+Comment[it]=Un tema semplice e leggero
+Comment[ja]=シンプルで軽いテーマ
+Comment[nds]=En eenfach un licht Muster
+Comment[nl]=Een eenvoudig en licht thema
+Comment[pa]=ਇੱਕ ਸਧਾਰਨ ਅਤੇ ਹਲਕਾ ਸਰੂਪ
+Comment[pl]=Prosty i lekki motyw
+Comment[pt]=Ajuste de Data e Hora do KIPI
+Comment[pt_BR]=Um tema simples e leve
+Comment[sr]=Једноставна и лагана тема
+Comment[sr@Latn]=Jednostavna i lagana tema
+Comment[sv]=Ett enkelt och lättviktigt tema
+Comment[xx]=xxA simple and light themexx
+Comment[zh_CN]=简洁明快的主题
+
+[X-HTMLExport Author]
+Name=Aurélien Gâteau
+Name[sr]=Орелиен Гато
+Name[sr@Latn]=Orelien Gato
+Name[xx]=xxAurélien Gâteauxx
+Url=mailto:aurelien.gateau@free.fr
+
+[X-HTMLExport Parameter style]
+Name=Style
+Name[br]=Giz
+Name[ca]=Estil
+Name[da]=Stil
+Name[de]=Stil
+Name[el]=Στυλ
+Name[es]=Estilo
+Name[et]=Stiil
+Name[fi]=Tyyli
+Name[is]=Stíll
+Name[it]=Stile
+Name[ja]=スタイル
+Name[nds]=Stil
+Name[nl]=Stijl
+Name[pl]=Styl
+Name[pt]=Estilo
+Name[pt_BR]=Estilo
+Name[sr]=Стил
+Name[sr@Latn]=Stil
+Name[sv]=Stil
+Name[xh]=Uhlobo
+Name[xx]=xxStylexx
+Name[zh_CN]=样式
+Name[zu]=Uhlobo
+Type=list
+Default=natural.css
+Value_0=natural.css
+Caption_0=Natural
+Value_1=dark.css
+Caption_1=Dark
diff --git a/kipi-plugins/htmlexport/themes/simple/template.xsl b/kipi-plugins/htmlexport/themes/simple/template.xsl
new file mode 100644
index 0000000..14f32b1
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/simple/template.xsl
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE stylesheet [
+<!ENTITY raquo "&#187;">
+]>
+
+<xsl:transform version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl">
+
+<xsl:template name="imagePage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="title"/></title>
+ <link rel="stylesheet" type="text/css">
+ <xsl:attribute name="href">../simple/<xsl:value-of select="$style"/></xsl:attribute>
+ </link>
+ </head>
+ <body id="imagePage">
+ <h1>
+ <span id="nav">
+ <xsl:choose>
+ <xsl:when test="position() &gt; 1">
+ <a href="{preceding-sibling::image[position()=1]/full/@fileName}.html">
+ « <xsl:value-of select="$i18nPrevious"/>
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ « <xsl:value-of select="$i18nPrevious"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ |
+ <xsl:choose>
+ <xsl:when test="position() &lt; last()">
+ <a href="{following-sibling::image[position()=1]/full/@fileName}.html">
+ <xsl:value-of select="$i18nNext"/> »
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$i18nNext"/> »
+ </xsl:otherwise>
+ </xsl:choose>
+ </span>
+ <span id="caption">
+ <xsl:choose>
+ <xsl:when test="count(/collections/collection) &gt; 1">
+ <a href="../index.html"><xsl:value-of select="$i18nCollectionList"/></a>
+ &raquo;
+ <a href="../{../fileName}.html"><xsl:value-of select="../name"/></a>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="../index.html"><xsl:value-of select="../name"/></a>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ &raquo; <xsl:value-of select="title"/>
+ (<xsl:value-of select="position()"/>/<xsl:value-of select="last()"/>)
+ </span>
+ </h1>
+
+ <div id="content">
+ <div id="image">
+ <img src="{full/@fileName}" width="{full/@width}" height="{full/@height}" />
+ <p>
+ <xsl:value-of select="description"/>
+ </p>
+ <xsl:if test="original/@fileName != ''">
+ <p>
+ <a href="{original/@fileName}"><xsl:value-of select="$i18nOriginalImage"/></a>
+ (<xsl:value-of select="original/@width"/>x<xsl:value-of select="original/@height"/>)
+ </p>
+ </xsl:if>
+ </div>
+ </div>
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="collectionPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="name"/></title>
+ <link rel="stylesheet" type="text/css">
+ <xsl:attribute name="href">simple/<xsl:value-of select="$style"/></xsl:attribute>
+ </link>
+ </head>
+ <body id="collectionPage">
+ <h1>
+ <xsl:if test="count(/collections/collection) &gt; 1">
+ <a href="index.html"><xsl:value-of select="$i18nCollectionList"/></a>
+ &raquo;
+ </xsl:if>
+ <xsl:value-of select="name"/>
+ </h1>
+ <div id="content">
+ <ul>
+ <xsl:variable name="folder" select='fileName'/>
+ <xsl:for-each select="image">
+ <li>
+ <a href='{$folder}/{full/@fileName}.html'>
+ <img src="{$folder}/{thumbnail/@fileName}" width="{thumbnail/@width}" height="{thumbnail/@height}" />
+ <br/>
+ <xsl:value-of select="title"/>
+ </a>
+ </li>
+ <exsl:document href='{$folder}/{full/@fileName}.html'>
+ <xsl:call-template name="imagePage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </ul>
+ </div> <!-- /content -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="collectionListPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="$i18nCollectionList"/></title>
+ <link rel="stylesheet" type="text/css">
+ <xsl:attribute name="href">simple/<xsl:value-of select="$style"/></xsl:attribute>
+ </link>
+ </head>
+ <body id="collectionListPage">
+ <h1><xsl:value-of select="$i18nCollectionList"/></h1>
+ <div id="content">
+ <ul>
+ <xsl:for-each select="collections/collection">
+ <li>
+ <a href="{fileName}.html">
+ <!-- Use first image as collection image -->
+ <img src="{fileName}/{image[1]/thumbnail/@fileName}"
+ width="{image[1]/thumbnail/@width}"
+ height="{image[1]/thumbnail/@height}" />
+ <br />
+ <xsl:value-of select="name"/>
+ </a>
+ </li>
+ <exsl:document href="{fileName}.html">
+ <xsl:call-template name="collectionPage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </ul>
+ </div> <!-- /content -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template match="/">
+ <xsl:choose>
+ <xsl:when test="count(collections/collection) &gt; 1">
+ <xsl:call-template name="collectionListPage"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="collections/collection">
+ <xsl:call-template name="collectionPage"/>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+</xsl:transform>
diff --git a/kipi-plugins/htmlexport/themes/snow/Makefile.am b/kipi-plugins/htmlexport/themes/snow/Makefile.am
new file mode 100644
index 0000000..d6423de
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/snow/Makefile.am
@@ -0,0 +1,6 @@
+themedir=$(kde_datadir)/kipiplugin_htmlexport/themes/snow
+theme_DATA= \
+ snow.desktop \
+ style.css \
+ template.xsl \
+ previous.png next.png previous_disabled.png next_disabled.png
diff --git a/kipi-plugins/htmlexport/themes/snow/next.png b/kipi-plugins/htmlexport/themes/snow/next.png
new file mode 100644
index 0000000..bde4bc9
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/snow/next.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/snow/next.svg b/kipi-plugins/htmlexport/themes/snow/next.svg
new file mode 100644
index 0000000..9db0d2c
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/snow/next.svg
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48.000000px"
+ height="48.000000px"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.42"
+ sodipodi:docbase="/home/bk/kde/trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow"
+ sodipodi:docname="next.svg"
+ inkscape:export-filename="/home/bk/kde/trunk/extragear/libs/kipi-plugins/htmlexport/themes/snow/next.png"
+ inkscape:export-xdpi="89.947815"
+ inkscape:export-ydpi="89.947815">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient2104">
+ <stop
+ id="stop2106"
+ offset="0.0000000"
+ style="stop-color:none" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.19681723"
+ id="stop2108" />
+ <stop
+ id="stop2110"
+ offset="0.58646619"
+ style="stop-color:#6d8da7;stop-opacity:1.0000000;" />
+ <stop
+ id="stop2112"
+ offset="1.0000000"
+ style="stop-color:#646a70;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2070">
+ <stop
+ style="stop-color:#000000;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop2072" />
+ <stop
+ id="stop2078"
+ offset="0.30075186"
+ style="stop-color:#000000;stop-opacity:0.49803922;" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop2074" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2056">
+ <stop
+ style="stop-color:#cbe1f3;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop2058" />
+ <stop
+ id="stop2064"
+ offset="0.19681723"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+ <stop
+ style="stop-color:#6d8da7;stop-opacity:1.0000000;"
+ offset="0.58646619"
+ id="stop2066" />
+ <stop
+ style="stop-color:#646a70;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop2060" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2038">
+ <stop
+ style="stop-color:#643618;stop-opacity:1;"
+ offset="0"
+ id="stop2040" />
+ <stop
+ style="stop-color:#d4814b;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop2042" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2038"
+ id="linearGradient2044"
+ x1="23.860802"
+ y1="24.091139"
+ x2="23.167048"
+ y2="8.5974693"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2038"
+ id="linearGradient2052"
+ x1="29.069065"
+ y1="27.341772"
+ x2="19.173973"
+ y2="27.159492"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2056"
+ id="linearGradient2062"
+ x1="21.584764"
+ y1="4.7860761"
+ x2="21.962801"
+ y2="17.237530"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2070"
+ id="linearGradient2076"
+ x1="21.508860"
+ y1="24.455696"
+ x2="21.508858"
+ y2="26.521519"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,1.616452,-8.592690e-2,-15.13636)" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="11.637799"
+ inkscape:cx="24.000000"
+ inkscape:cy="22.802907"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1280"
+ inkscape:window-height="956"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:url(#linearGradient2052);fill-opacity:1.0;fill-rule:evenodd;stroke:#472610;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none"
+ d="M 16.465823,7.5949367 L 19.625316,45.751899 L 30.622785,45.751899 L 23.210127,7.2303797 L 16.465823,7.5949367 z "
+ id="path1306"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2076);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 18.404020,25.315860 L 26.122264,24.972152 L 26.891288,29.060310 L 18.768577,29.146237 L 18.404020,25.315860 z "
+ id="path2068"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2044);fill-opacity:1.0;fill-rule:evenodd;stroke:#472610;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none"
+ d="M 1.5797468,9.6005333 L 38.643038,7.3196557 L 47.574684,15.758412 L 37.853165,25.065154 L 2.2481012,25.127844 L 1.5797468,9.6005333 z "
+ id="path1308"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:url(#linearGradient2062);fill-opacity:1.0;fill-rule:evenodd;stroke:#8b9198;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none"
+ d="M 1.7620253,7.9594937 L 0.54683544,10.572152 L 1.9443038,20.415190 L 3.4025316,14.156962 L 4.6784810,17.073418 L 7.3518987,11.544304 L 10.804765,16.969171 L 15.446913,11.016529 L 20.118547,16.122857 L 23.584367,12.558895 L 26.939093,20.593892 L 29.252272,10.585106 L 31.640953,14.008487 L 33.706776,10.545196 L 35.809979,16.770361 L 37.368877,10.467905 L 39.539687,13.361722 L 40.960535,10.605955 L 44.962025,14.096203 L 46.632017,14.303649 L 39.736709,5.2860759 L 25.275949,6.9873418 L 1.7620253,7.9594937 z "
+ id="path2054"
+ sodipodi:nodetypes="ccccccccccccccccccccccc"
+ inkscape:export-xdpi="89.000000"
+ inkscape:export-ydpi="89.000000" />
+ </g>
+</svg>
diff --git a/kipi-plugins/htmlexport/themes/snow/next_disabled.png b/kipi-plugins/htmlexport/themes/snow/next_disabled.png
new file mode 100644
index 0000000..4adb7ad
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/snow/next_disabled.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/snow/previous.png b/kipi-plugins/htmlexport/themes/snow/previous.png
new file mode 100644
index 0000000..576c752
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/snow/previous.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/snow/previous_disabled.png b/kipi-plugins/htmlexport/themes/snow/previous_disabled.png
new file mode 100644
index 0000000..e790138
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/snow/previous_disabled.png
Binary files differ
diff --git a/kipi-plugins/htmlexport/themes/snow/snow.desktop b/kipi-plugins/htmlexport/themes/snow/snow.desktop
new file mode 100644
index 0000000..bea5966
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/snow/snow.desktop
@@ -0,0 +1,59 @@
+[Desktop Entry]
+Name=Snow
+Name[br]=Erc'h
+Name[ca]=Neu
+Name[cs]=Sníh
+Name[cy]=Eira
+Name[da]=Sne
+Name[de]=Schnee
+Name[el]=Χιόνι
+Name[es]=Nieve
+Name[et]=Lumi
+Name[fi]=Lumi
+Name[fr]=Neige
+Name[ga]=Sneachta
+Name[gl]=Neve
+Name[it]=Neve
+Name[ja]=雪 (Snow)
+Name[nds]=Snee
+Name[nl]=Sneeuw
+Name[pa]=ਬਰਫ਼
+Name[pl]=Śnieg
+Name[pt]=Neve
+Name[sr]=Снег
+Name[sr@Latn]=Sneg
+Name[sv]=Snö
+Name[xx]=xxSnowxx
+Name[zh_CN]=雪月
+Comment=A perfect match for your mountain holidays
+Comment[ca]=Un complement perfecte per les vacances de muntanya
+Comment[cs]=Skvělé pro dovolenou na horách
+Comment[da]=Passer perfekt til din ferie i bjergene
+Comment[de]=Passt perfekt zu Ihren Ferien in den Bergen
+Comment[el]=Μια υπέροχη επιλογή για διακοπές σε βουνό
+Comment[es]=Una coincidencia perfecta para sus vacaciones de montaña
+Comment[et]=Sobib hiilgavalt kokku mägipuhkuse pilti8dega
+Comment[fi]=Luo valokuviisi lumiefekti
+Comment[fr]=Un complément parfait pour vos photos de montagne
+Comment[gl]=O que precisa para as suas vacazóns na montaña
+Comment[is]=Frábært eftir fríið að fjallabaki
+Comment[it]=Perfetto per le settimane bianche
+Comment[ja]=冬山での休日にぴったりのテーマ
+Comment[nds]=Heel passlich för Dien Oorlööf in de Bargen
+Comment[nl]=Een perfect thema voor uw bergvakanties
+Comment[pa]=ਤੁਹਾਡੀ ਪਹਾੜੀ ਉੱਤੇ ਮਨਾਈਆਂ ਛੁੱਟੀਆਂ ਲਈ ਠੀਕ
+Comment[pl]=Idealnie pasuje do prezentacji zdjęć z Twoich górskich wakacji
+Comment[pt]=A combinação perfeita com as suas férias na montanha
+Comment[pt_BR]=Um companheiro perfeito para suas férias nas montanhas
+Comment[sr]=Савршено за ваш одмор на планини
+Comment[sr@Latn]=Savršeno za vaš odmor na planini
+Comment[sv]=Passar perfekt med din alpinsemester
+Comment[xx]=xxA perfect match for your mountain holidaysxx
+Comment[zh_CN]=野营的绝配
+
+[X-HTMLExport Author]
+Name=Aurélien Gâteau
+Name[sr]=Орелиен Гато
+Name[sr@Latn]=Orelien Gato
+Name[xx]=xxAurélien Gâteauxx
+Url=mailto:aurelien.gateau@free.fr
diff --git a/kipi-plugins/htmlexport/themes/snow/style.css b/kipi-plugins/htmlexport/themes/snow/style.css
new file mode 100644
index 0000000..636cc0d
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/snow/style.css
@@ -0,0 +1,67 @@
+body {
+ background-color: white;
+ color: black;
+ margin: 0;
+}
+
+a {
+ color: #2f5d9c;
+}
+
+a:hover {
+ color: #456ff3;
+}
+
+img {
+ border: 0;
+}
+
+h1 {
+ background-color: #eef;
+ border-bottom: 1px solid #ddf;
+ height: 48px;
+ margin: 0;
+ padding: 0;
+ padding-top: 3px;
+ padding-bottom: 3px;
+ position: fixed;
+ left: 0;
+ top: 0;
+ width: 100%;
+ z-index: 1000;
+
+ text-align: center;
+ line-height: 48px;
+ height: 48px;
+ font-size: 14px;
+}
+
+#content {
+ overflow: auto;
+ margin-top: 57px;
+}
+
+/* Collection page */
+#collectionPage li {
+ display: block;
+ float: left;
+ text-align: center;
+ margin: 6px;
+}
+
+#collectionPage img {
+ display: block;
+}
+
+/* Image page */
+#previous {
+ float: left;
+}
+
+#next {
+ float: right;
+}
+
+#imagePage #content {
+ text-align:center;
+}
diff --git a/kipi-plugins/htmlexport/themes/snow/template.xsl b/kipi-plugins/htmlexport/themes/snow/template.xsl
new file mode 100644
index 0000000..1487fd0
--- /dev/null
+++ b/kipi-plugins/htmlexport/themes/snow/template.xsl
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE stylesheet [
+<!ENTITY raquo "&#187;">
+]>
+
+<xsl:transform version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="exsl">
+
+<xsl:template name="imagePage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="title"/></title>
+ <link rel="stylesheet" type="text/css" href="../snow/style.css"/>
+ </head>
+ <body id="imagePage">
+ <h1>
+ <div id="previous">
+ <xsl:choose>
+ <xsl:when test="position() &gt; 1">
+ <a href="{preceding-sibling::image[position()=1]/full/@fileName}.html">
+ <img src="../snow/previous.png" alt="&lt;" title="{$i18nPrevious}" />
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <img src="../snow/previous_disabled.png" alt="&lt;" title="{$i18nPrevious}" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </div>
+ <div id="next">
+ <xsl:choose>
+ <xsl:when test="position() &lt; last()">
+ <a href="{following-sibling::image[position()=1]/full/@fileName}.html">
+ <img src="../snow/next.png" alt="&gt;" title="{$i18nNext}" />
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <img src="../snow/next_disabled.png" alt="&gt;" title="{$i18nNext}" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </div>
+ <div id="caption">
+ <xsl:choose>
+ <xsl:when test="count(/collections/collection) &gt; 1">
+ <a href="../index.html"><xsl:value-of select="$i18nCollectionList"/></a>
+ &raquo;
+ <a href="../{../fileName}.html"><xsl:value-of select="../name"/></a>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="../index.html"><xsl:value-of select="../name"/></a>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ &raquo; <xsl:value-of select="title"/>
+ (<xsl:value-of select="position()"/>/<xsl:value-of select="last()"/>)
+ </div>
+ </h1>
+
+ <div id="content">
+ <img src="{full/@fileName}" width="{full/@width}" height="{full/@height}" />
+ <p>
+ <xsl:value-of select="description"/>
+ </p>
+ <xsl:if test="original/@fileName != ''">
+ <p>
+ <a href="{original/@fileName}"><xsl:value-of select="$i18nOriginalImage"/></a>
+ (<xsl:value-of select="original/@width"/>x<xsl:value-of select="original/@height"/>)
+ </p>
+ </xsl:if>
+ </div>
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="collectionPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="name"/></title>
+ <link rel="stylesheet" type="text/css" href="snow/style.css"/>
+ </head>
+ <body id="collectionPage">
+ <h1>
+ <xsl:if test="count(/collections/collection) &gt; 1">
+ <a href="index.html"><xsl:value-of select="$i18nCollectionList"/></a>
+ &raquo;
+ </xsl:if>
+ <xsl:value-of select="name"/>
+ </h1>
+ <div id="content">
+ <ul>
+ <xsl:variable name="folder" select='fileName'/>
+ <xsl:for-each select="image">
+ <li>
+ <a href='{$folder}/{full/@fileName}.html'>
+ <img src="{$folder}/{thumbnail/@fileName}" width="{thumbnail/@width}" height="{thumbnail/@height}" />
+ </a>
+ <br/>
+ <a href='{$folder}/{full/@fileName}.html'>
+ <xsl:value-of select="title"/>
+ </a>
+ </li>
+ <exsl:document href='{$folder}/{full/@fileName}.html'>
+ <xsl:call-template name="imagePage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </ul>
+ </div> <!-- /content -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="collectionListPage">
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title><xsl:value-of select="$i18nCollectionList"/></title>
+ <link rel="stylesheet" type="text/css" href="snow/style.css"/>
+ </head>
+ <body>
+ <h1><xsl:value-of select="$i18nCollectionList"/></h1>
+ <div id="content">
+ <ul>
+ <xsl:for-each select="collections/collection">
+ <li>
+ <a href="{fileName}.html">
+ <!-- Use first image as collection image -->
+ <img src="{fileName}/{image[1]/thumbnail/@fileName}"
+ width="{image[1]/thumbnail/@width}"
+ height="{image[1]/thumbnail/@height}" />
+ <br />
+ <xsl:value-of select="name"/>
+ </a>
+ </li>
+ <exsl:document href="{fileName}.html">
+ <xsl:call-template name="collectionPage"/>
+ </exsl:document>
+ </xsl:for-each>
+ </ul>
+ </div> <!-- /content -->
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template match="/">
+ <xsl:choose>
+ <xsl:when test="count(collections/collection) &gt; 1">
+ <xsl:call-template name="collectionListPage"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="collections/collection">
+ <xsl:call-template name="collectionPage"/>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+</xsl:transform>
diff --git a/kipi-plugins/htmlexport/wizard.cpp b/kipi-plugins/htmlexport/wizard.cpp
new file mode 100644
index 0000000..3f8660b
--- /dev/null
+++ b/kipi-plugins/htmlexport/wizard.cpp
@@ -0,0 +1,298 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+// Self
+#include "wizard.moc"
+
+// Qt
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qobjectlist.h>
+#include <qpainter.h>
+#include <qspinbox.h>
+
+// KDE
+#include <kconfigdialogmanager.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klistbox.h>
+#include <klocale.h>
+#include <ktextbrowser.h>
+#include <kurlrequester.h>
+#include <kwizard.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+
+// KIPI
+#include <libkipi/imagecollectionselector.h>
+
+// Local
+#include "abstractthemeparameter.h"
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "galleryinfo.h"
+#include "imagesettingspage.h"
+#include "theme.h"
+#include "themepage.h"
+#include "themeparameterspage.h"
+#include "outputpage.h"
+#include "kpaboutdata.h"
+
+namespace KIPIHTMLExport {
+
+
+class ThemeListBoxItem : public QListBoxText {
+public:
+ ThemeListBoxItem(QListBox* list, Theme::Ptr theme)
+ : QListBoxText(list, theme->name())
+ , mTheme(theme)
+ {}
+
+ Theme::Ptr mTheme;
+};
+
+
+struct Wizard::Private {
+ GalleryInfo* mInfo;
+ KConfigDialogManager* mConfigManager;
+
+ KIPI::ImageCollectionSelector* mCollectionSelector;
+ ThemePage* mThemePage;
+ ThemeParametersPage* mThemeParametersPage;
+ ImageSettingsPage* mImageSettingsPage;
+ OutputPage* mOutputPage;
+ KIPIPlugins::KPAboutData* mAbout;
+ QMap<QCString, QWidget*> mThemeParameterWidgetFromName;
+
+ void initThemePage() {
+ KListBox* listBox=mThemePage->mThemeList;
+ Theme::List list=Theme::getList();
+ Theme::List::Iterator it=list.begin(), end=list.end();
+ for (; it!=end; ++it) {
+ Theme::Ptr theme = *it;
+ ThemeListBoxItem* item=new ThemeListBoxItem(listBox, theme);
+ if ( theme->internalName()==mInfo->theme() ) {
+ listBox->setCurrentItem(item);
+ }
+ }
+ }
+
+ void fillThemeParametersPage(Theme::Ptr theme) {
+ // Delete any previous widgets
+ QFrame* content = mThemeParametersPage->content;
+ if (content->layout()) {
+ // Setting recursiveSearch to false is very important, if we don't
+ // we will end up deleting subwidgets of our child widgets
+ QObjectList* list = content->queryList("QWidget", 0 /*objName*/,
+ false /*regexpMatch*/, false /*recursiveSearch*/);
+ QObjectListIterator it(*list);
+ for( ; it.current(); ++it) {
+ delete it.current();
+ }
+
+ delete content->layout();
+ }
+ mThemeParameterWidgetFromName.clear();
+
+ // Create layout. We need to recreate it everytime, to get rid of
+ // spacers
+ QGridLayout* layout = new QGridLayout(content, 0, 3);
+ layout->setSpacing(KDialog::spacingHint());
+
+ // Create widgets
+ Theme::ParameterList parameterList = theme->parameterList();
+ QString themeInternalName = theme->internalName();
+ Theme::ParameterList::ConstIterator
+ it = parameterList.begin(),
+ end = parameterList.end();
+ for (; it!=end; ++it) {
+ AbstractThemeParameter* themeParameter = *it;
+ QCString internalName = themeParameter->internalName();
+ QString value = mInfo->getThemeParameterValue(
+ themeInternalName,
+ internalName,
+ themeParameter->defaultValue());
+
+ QString name = themeParameter->name();
+ name = i18n("'%1' is a label for a theme parameter", "%1:").arg(name);
+
+ QLabel* label = new QLabel(name, content);
+ QWidget* widget = themeParameter->createWidget(content, value);
+ label->setBuddy(widget);
+
+ int row = layout->numRows();
+ layout->addWidget(label, row, 0);
+
+ if (widget->sizePolicy().expanding() & QSizePolicy::Horizontally) {
+ // Widget wants full width
+ layout->addMultiCellWidget(widget, row, row, 1, 2);
+ } else {
+ // Widget doesn't like to be stretched, add a spacer next to it
+ layout->addWidget(widget, row, 1);
+ QSpacerItem* spacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ layout->addItem(spacer, row, 2);
+ }
+
+ mThemeParameterWidgetFromName[internalName] = widget;
+ }
+
+ // Add spacer at the end, so that widgets aren't spread on the whole
+ // parent height
+ QSpacerItem* spacer = new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding);
+ layout->addItem(spacer, layout->numRows(), 0);
+ }
+};
+
+Wizard::Wizard(QWidget* parent, KIPI::Interface* interface, GalleryInfo* info)
+: KWizard(parent)
+{
+ d=new Private;
+ d->mInfo=info;
+
+ // About data
+ d->mAbout = new KIPIPlugins::KPAboutData(I18N_NOOP("HTML Export"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A KIPI plugin to export image collections to HTML pages"),
+ "(c) 2006, Aurelien Gateau");
+
+ d->mAbout->addAuthor("Aurelien Gateau", I18N_NOOP("Author and Maintainer"),
+ "aurelien.gateau@free.fr");
+
+ // Help button
+ KHelpMenu* helpMenu = new KHelpMenu(this, d->mAbout, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(showHelp()), 0, -1, 0);
+ helpButton()->setPopup( helpMenu->menu() );
+
+ d->mCollectionSelector=new KIPI::ImageCollectionSelector(this, interface);
+ addPage(d->mCollectionSelector, i18n("Collection Selection"));
+
+ d->mThemePage=new ThemePage(this);
+ d->initThemePage();
+ addPage(d->mThemePage, i18n("Theme"));
+ connect(d->mThemePage->mThemeList, SIGNAL(selectionChanged()),
+ this, SLOT(slotThemeSelectionChanged()) );
+
+ d->mThemeParametersPage = new ThemeParametersPage(this);
+ addPage(d->mThemeParametersPage, i18n("Theme Parameters"));
+
+ d->mImageSettingsPage=new ImageSettingsPage(this);
+ addPage(d->mImageSettingsPage, i18n("Image Settings"));
+
+ d->mOutputPage=new OutputPage(this);
+ d->mOutputPage->kcfg_destURL->setMode(KFile::Directory);
+ addPage(d->mOutputPage, i18n("Output"));
+
+ connect(d->mOutputPage->kcfg_destURL, SIGNAL(textChanged(const QString&)),
+ this, SLOT(updateFinishButton()) );
+
+ d->mConfigManager=new KConfigDialogManager(this, d->mInfo);
+ d->mConfigManager->updateWidgets();
+
+ // Set page states
+ // Pages can only be disabled after they have *all* been added!
+ slotThemeSelectionChanged();
+ updateFinishButton();
+}
+
+
+Wizard::~Wizard() {
+ delete d->mAbout;
+ delete d;
+}
+
+void Wizard::showHelp() {
+ KApplication::kApplication()->invokeHelp("htmlexport", "kipi-plugins");
+}
+
+void Wizard::updateFinishButton() {
+ setFinishEnabled(d->mOutputPage, !d->mOutputPage->kcfg_destURL->url().isEmpty());
+}
+
+
+void Wizard::slotThemeSelectionChanged() {
+ KListBox* listBox=d->mThemePage->mThemeList;
+ KTextBrowser* browser=d->mThemePage->mThemeInfo;
+ if (listBox->selectedItem()) {
+ Theme::Ptr theme=static_cast<ThemeListBoxItem*>(listBox->selectedItem())->mTheme;
+
+ QString url=theme->authorUrl();
+ QString author=theme->authorName();
+ if (!url.isEmpty()) {
+ author=QString("<a href='%1'>%2</a>").arg(url).arg(author);
+ }
+
+ QString txt=
+ QString("<b>%1</b><br><br>%2<br><br>").arg(theme->name(), theme->comment())
+ + i18n("Author: %1").arg(author);
+ browser->setText(txt);
+ setNextEnabled(d->mThemePage, true);
+
+ // Enable theme parameter page if there is any parameter
+ Theme::ParameterList parameterList = theme->parameterList();
+ setAppropriate(d->mThemeParametersPage, parameterList.size() > 0);
+
+ d->fillThemeParametersPage(theme);
+ } else {
+ browser->clear();
+ setNextEnabled(d->mThemePage, false);
+ }
+}
+
+
+/**
+ * Update mInfo
+ */
+void Wizard::accept() {
+ d->mInfo->mCollectionList=d->mCollectionSelector->selectedImageCollections();
+
+ Theme::Ptr theme=static_cast<ThemeListBoxItem*>(d->mThemePage->mThemeList->selectedItem())->mTheme;
+ QString themeInternalName = theme->internalName();
+ d->mInfo->setTheme(themeInternalName);
+
+ Theme::ParameterList parameterList = theme->parameterList();
+ Theme::ParameterList::ConstIterator
+ it = parameterList.begin(),
+ end = parameterList.end();
+ for (; it!=end; ++it) {
+ AbstractThemeParameter* themeParameter = *it;
+ QCString parameterInternalName = themeParameter->internalName();
+ QWidget* widget = d->mThemeParameterWidgetFromName[parameterInternalName];
+ QString value = themeParameter->valueFromWidget(widget);
+
+ d->mInfo->setThemeParameterValue(
+ themeInternalName,
+ parameterInternalName,
+ value);
+ }
+
+ d->mConfigManager->updateSettings();
+
+ KWizard::accept();
+}
+
+
+} // namespace
diff --git a/kipi-plugins/htmlexport/wizard.h b/kipi-plugins/htmlexport/wizard.h
new file mode 100644
index 0000000..23749ad
--- /dev/null
+++ b/kipi-plugins/htmlexport/wizard.h
@@ -0,0 +1,60 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef WIZARD_H
+#define WIZARD_H
+
+// KDE
+#include <kwizard.h>
+
+namespace KIPI {
+class Interface;
+}
+
+namespace KIPIHTMLExport {
+
+class GalleryInfo;
+
+/**
+ * The wizard used by the user to select the various settings.
+ */
+class Wizard : public KWizard {
+Q_OBJECT
+public:
+ Wizard(QWidget* parent, KIPI::Interface* interface, GalleryInfo* info);
+ ~Wizard();
+
+protected slots:
+ virtual void accept();
+
+private slots:
+ void showHelp();
+ void updateFinishButton();
+ void slotThemeSelectionChanged();
+
+private:
+ struct Private;
+ Private* d;
+};
+
+
+} // namespace
+
+#endif /* WIZARD_H */
diff --git a/kipi-plugins/htmlexport/xmlutils.h b/kipi-plugins/htmlexport/xmlutils.h
new file mode 100644
index 0000000..baca26a
--- /dev/null
+++ b/kipi-plugins/htmlexport/xmlutils.h
@@ -0,0 +1,156 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab:
+/*
+A KIPI plugin to generate HTML image galleries
+Copyright 2006 by Aurelien Gateau <aurelien dot gateau at free.fr>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+*/
+#ifndef XMLUTILS_H
+#define XMLUTILS_H
+
+#include <kdebug.h>
+
+#include <libxml/xmlwriter.h>
+
+namespace KIPIHTMLExport {
+
+
+/**
+ * A simple wrapper for a C structure pointed to by @Ptr, which must be freed
+ * with @freeFcn
+ */
+template <class Ptr, void(*freeFcn)(Ptr)>
+class CWrapper {
+public:
+ CWrapper() : mPtr(0) {}
+ CWrapper(Ptr ptr)
+ : mPtr(ptr) {}
+
+ ~CWrapper() {
+ freeFcn(mPtr);
+ }
+
+ operator Ptr() const {
+ return mPtr;
+ }
+
+ bool operator!() const {
+ return !mPtr;
+ }
+
+ void assign(Ptr ptr) {
+ if (mPtr) freeFcn(mPtr);
+ mPtr=ptr;
+ }
+
+private:
+ Ptr mPtr;
+};
+
+
+/**
+ * Simple wrapper around xmlTextWriter
+ */
+class XMLWriter {
+public:
+ bool open(const QString& name) {
+ xmlTextWriterPtr ptr=xmlNewTextWriterFilename(name.local8Bit(), 0);
+ if (!ptr) return false;
+ mWriter.assign(ptr);
+
+ int rc=xmlTextWriterStartDocument(ptr, NULL, "UTF-8", NULL);
+ if (rc<0) {
+ mWriter.assign(0);
+ return false;
+ }
+
+ xmlTextWriterSetIndent(ptr, 1);
+
+ return true;
+ }
+
+ operator xmlTextWriterPtr() const {
+ return mWriter;
+ }
+
+ void writeElement(const char* element, const QString& value) {
+ xmlTextWriterWriteElement(mWriter, BAD_CAST element, BAD_CAST value.utf8().data());
+ }
+
+ void writeElement(const char* element, int value) {
+ writeElement(element, QString::number(value));
+ }
+
+private:
+ CWrapper<xmlTextWriterPtr,xmlFreeTextWriter> mWriter;
+};
+
+
+/**
+ * A list of attributes for an XML element. To be used with @ref XMLElement
+ */
+class XMLAttributeList {
+ typedef QMap<QString, QString> Map;
+public:
+ void write(XMLWriter& writer) const {
+ Map::const_iterator it=mMap.begin();
+ Map::const_iterator end=mMap.end();
+ for (; it!=end; ++it) {
+ xmlTextWriterWriteAttribute(writer,
+ BAD_CAST it.key().ascii(),
+ BAD_CAST it.data().utf8().data());
+ }
+ }
+
+ void append(const QString& key, const QString& value) {
+ mMap[key]=value;
+ }
+
+ void append(const QString& key, int value) {
+ mMap[key]=QString::number(value);
+ }
+
+private:
+ Map mMap;
+};
+
+
+/**
+ * A class to generate an XML element
+ */
+class XMLElement {
+public:
+ XMLElement(XMLWriter& writer, const QString& element, const XMLAttributeList* attributeList=0)
+ : mWriter(writer)
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST element.ascii());
+ if (attributeList) {
+ attributeList->write(writer);
+ }
+ }
+
+ ~XMLElement() {
+ xmlTextWriterEndElement(mWriter);
+ }
+
+private:
+ XMLWriter& mWriter;
+};
+
+
+} // namespace
+
+#endif /* XMLUTILS_H */
diff --git a/kipi-plugins/imageviewer/Makefile.am b/kipi-plugins/imageviewer/Makefile.am
new file mode 100644
index 0000000..628c44f
--- /dev/null
+++ b/kipi-plugins/imageviewer/Makefile.am
@@ -0,0 +1,25 @@
+# set the include path for X, qt and KDE
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(LIBKDCRAW_CFLAGS) $(all_includes)
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_viewer.la
+
+kipiplugin_viewer_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+kipiplugin_viewer_la_SOURCES = viewerwidget.cpp texture.cpp timer.cpp plugin_viewer.cpp help.ui
+kipiplugin_viewer_la_LIBADD = $(LIBKIPI_LIBS) $(LIBKDCRAW_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) -lGL
+kipiplugin_viewer_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries)
+
+kde_services_DATA = kipiplugin_viewer.desktop
+
+
+kipiviewericondir = $(kde_datadir)/kipiplugin_viewer/icons
+kipiviewericon_ICON = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_viewer.pot
+
+
+#icon is still missing \ No newline at end of file
diff --git a/kipi-plugins/imageviewer/README b/kipi-plugins/imageviewer/README
new file mode 100644
index 0000000..6adf663
--- /dev/null
+++ b/kipi-plugins/imageviewer/README
@@ -0,0 +1,69 @@
+-------------------------------
+KIPI image viewer plugin
+-------------------------------
+
+This image viewer was designed with speed and ease of usage in mind as well as for mouseless setups (notebooks). A image is converted to a non-power-of two OpenGL texture. This means your video driver has to support the GL_ARB_texture_rectangle OpenGL extension. Please verify with the command glxinfo. Please keep in mind that you need alot of video memory: a 5MP image requires 20MB texture memory. If you run out texture ram, the downloading time of the texture can be increased up to several seconds. Next generation window managers like Beryl will require a massive amount of video memory to run this plugin.
+
+-------------------
+Handbook
+-------------------
+
+1) Start
+--------
+
+- select the images you'd like to view. Ctrl-A for all images
+ if no image is selected, all images of the album are loaded and the first image will be displayed
+ if one image is selected, all images are loaded and the selected image image will be displayed
+ if several images are selected, only the selected images are loaded
+- in Digikam, select Tool->Image viewer
+ in Gwenview, select Plugins->Tools->Image viewer
+- for convenience, create a shortcut in the host application. In Digikam, select Settings->Configure Shortcut, search for "image viewer"
+
+
+2) Usage
+--------
+
+next image : scrollwheel down or n or down arrow or right arrow or Space
+previous image : scrollwheel up or p or up arrow or left arrow
+toggle fullscreen/normal : f
+quit : Esc
+toggle scrollwheel action : c (scrollwheel either zooms or changes the image), default is changing images
+rotation : r
+reset view : double click
+original size : o
+
+
+zooming:
+
+- move mouse in y-direction while pressing the right mouse button
+- alternatively, press c and use the scrollwheel
+- plus/minus
+- ctrl + scrollwheel
+
+
+panning:
+
+- move mouse while pressing the left button
+
+
+3) Performace & technical details
+---------------------------------
+
+On a PentiumM 1Ghz, slow 2.5 inch harddrive, I measured the following times for changing an image (5 megapixel, 2MB)
+- loading image from cache: 0ms
+- download texture to video memory: 15ms
+- draw image: 16ms
+ the new image is on the screen after 31ms of the user interaction
+- preload next image to cache 690ms
+ only after preloading is done, the next image can be displayed.
+
+The most expensive part is instanciating a QImage(myimage) object with 690ms, which includes reading the file from the harddrive. Downscaling to screensize and converting to GL format takes around 70ms. At least on my setup, downscaling by CPU is still faster than copying a 20Mb texture to video mem and downscaling by GPU.
+
+Other programs/libraries: time of loading and displaying an image
+SDL : 750ms
+Kuickshow: (imlib) 690ms (without smooth rendering)
+Kuickshow: (imlib) 1770ms (with smooth rendering)
+feh: (imlib2) 670ms
+this Image Viewer plugin: 720ms (implicit smooth rendering due to OGL)
+
+
diff --git a/kipi-plugins/imageviewer/TODO b/kipi-plugins/imageviewer/TODO
new file mode 100644
index 0000000..da964cb
--- /dev/null
+++ b/kipi-plugins/imageviewer/TODO
@@ -0,0 +1,2 @@
+- slideshow (in progress)
+- make plugin configurable \ No newline at end of file
diff --git a/kipi-plugins/imageviewer/cursors/Makefile.am b/kipi-plugins/imageviewer/cursors/Makefile.am
new file mode 100644
index 0000000..b970bcd
--- /dev/null
+++ b/kipi-plugins/imageviewer/cursors/Makefile.am
@@ -0,0 +1,3 @@
+METASOURCES = AUTO
+mycursorsdir = $(kde_datadir)/kipiplugin_imageviewer/pics
+mycursors_DATA = hand.png zoom.png nullImage.png
diff --git a/kipi-plugins/imageviewer/cursors/hand.png b/kipi-plugins/imageviewer/cursors/hand.png
new file mode 100644
index 0000000..0d9790c
--- /dev/null
+++ b/kipi-plugins/imageviewer/cursors/hand.png
Binary files differ
diff --git a/kipi-plugins/imageviewer/cursors/nullImage.png b/kipi-plugins/imageviewer/cursors/nullImage.png
new file mode 100644
index 0000000..9757c84
--- /dev/null
+++ b/kipi-plugins/imageviewer/cursors/nullImage.png
Binary files differ
diff --git a/kipi-plugins/imageviewer/cursors/zoom.png b/kipi-plugins/imageviewer/cursors/zoom.png
new file mode 100644
index 0000000..2250544
--- /dev/null
+++ b/kipi-plugins/imageviewer/cursors/zoom.png
Binary files differ
diff --git a/kipi-plugins/imageviewer/help.ui b/kipi-plugins/imageviewer/help.ui
new file mode 100644
index 0000000..c35a135
--- /dev/null
+++ b/kipi-plugins/imageviewer/help.ui
@@ -0,0 +1,122 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KIPIviewer::HelpDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>HelpDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>712</width>
+ <height>539</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Usage Image Viewer</string>
+ </property>
+ <property name="modal">
+ <bool>false</bool>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>pushButton1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>260</x>
+ <y>500</y>
+ <width>230</width>
+ <height>26</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>O&amp;K</string>
+ </property>
+ <property name="accel">
+ <string>Alt+K</string>
+ </property>
+ </widget>
+ <widget class="QTextBrowser">
+ <property name="name">
+ <cstring>textBrowser2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>690</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;&lt;font color="#5500ff"&gt;&lt;font size="+2"&gt;Image Access&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;br&gt;
+&lt;TABLE&gt;
+ &lt;TR&gt;
+ &lt;TD&gt;next image&lt;/TD&gt;
+ &lt;TD&gt;scrollwheel down/down arrow/right arrow/PgDown/Space/n&lt;/TD&gt;
+ &lt;/TR&gt;
+ &lt;TR&gt;
+ &lt;TD&gt;previous image &lt;/TD&gt;
+ &lt;TD&gt;scrollwheel up/up arrow/left arrow/PgUp/p &lt;/TD&gt;
+ &lt;/TR&gt;
+&lt;TR&gt;
+ &lt;TD&gt;quit&lt;/TD&gt;
+ &lt;TD&gt;Esc&lt;/TD&gt;
+ &lt;/TR&gt;
+ &lt;/TABLE&gt;
+&lt;br&gt;
+ &lt;TH&gt;&lt;b&gt;&lt;font color="#5500ff"&gt;&lt;font size="+2"&gt;Display&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/TH&gt; &lt;/br&gt;
+&lt;TABLE&gt;
+ &lt;TR&gt;
+ &lt;TD&gt;toggle fullscreen/normal &lt;/TD&gt;
+ &lt;TD&gt;f&lt;/TD&gt;
+ &lt;/TR&gt;
+ &lt;TR&gt;
+ &lt;TD&gt;toggle scrollwheel action&lt;/TD&gt;
+ &lt;TD&gt;c (either zoom or change image)&lt;/TD&gt;
+ &lt;/TR&gt;
+ &lt;TR&gt;
+ &lt;TD&gt;rotation &lt;/TD&gt;
+ &lt;TD&gt;r&lt;/TD&gt;
+ &lt;/TR&gt;
+ &lt;TR&gt;
+ &lt;TD&gt;reset view &lt;/TD&gt;
+ &lt;TD&gt;double click&lt;/TD&gt;
+ &lt;/TR&gt;
+ &lt;TR&gt;
+ &lt;TD&gt;original size&lt;/TD&gt;
+ &lt;TD&gt;o&lt;/TD&gt;
+ &lt;/TR&gt;
+ &lt;/TABLE&gt;
+&lt;br&gt;
+
+
+&lt;b&gt;&lt;font color="#5500ff" size="+2"&gt;Zooming&lt;/font&gt;&lt;/b&gt;&lt;br&gt;
+&lt;UL&gt;
+&lt;LI&gt;move mouse in up/down-direction while pressing the right mouse button
+&lt;LI&gt;alternatively, press c and use the scrollwheel&lt;br&gt;
+&lt;LI&gt;plus/minus
+&lt;LI&gt;ctrl + scrollwheel
+&lt;/UL&gt;
+
+&lt;b&gt;&lt;font color="#5500ff" size="+2"&gt;Panning&lt;/font&gt;&lt;/b&gt;&lt;br&gt;
+&lt;UL&gt;
+&lt;LI&gt;move mouse while pressing the left button
+&lt;/UL&gt;</string>
+ </property>
+ </widget>
+</widget>
+<connections>
+ <connection>
+ <sender>pushButton1</sender>
+ <signal>clicked()</signal>
+ <receiver>HelpDialog</receiver>
+ <slot>close()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>pushButton1_clicked()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kipi-plugins/imageviewer/hi16-action-ogl.png b/kipi-plugins/imageviewer/hi16-action-ogl.png
new file mode 100644
index 0000000..4ed606c
--- /dev/null
+++ b/kipi-plugins/imageviewer/hi16-action-ogl.png
Binary files differ
diff --git a/kipi-plugins/imageviewer/hi32-action-ogl.png b/kipi-plugins/imageviewer/hi32-action-ogl.png
new file mode 100644
index 0000000..45ae1a1
--- /dev/null
+++ b/kipi-plugins/imageviewer/hi32-action-ogl.png
Binary files differ
diff --git a/kipi-plugins/imageviewer/kipiplugin_viewer.desktop b/kipi-plugins/imageviewer/kipiplugin_viewer.desktop
new file mode 100644
index 0000000..6514b21
--- /dev/null
+++ b/kipi-plugins/imageviewer/kipiplugin_viewer.desktop
@@ -0,0 +1,49 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Viewer
+Name[br]=Gweler
+Name[ca]=Visualitzador
+Name[da]=Visning
+Name[de]=Betrachter
+Name[el]=Προβολέας
+Name[es]=Visor
+Name[et]=Pildinäitaja
+Name[fi]=Katselin
+Name[fr]=Afficheur
+Name[it]=Visore
+Name[ja]=ビューア
+Name[nds]=Kieker
+Name[pa]=ਦਰਸ਼ਕ
+Name[pl]=Przeglądarka
+Name[pt]=Visualizador
+Name[sr]=Прегледач
+Name[sr@Latn]=Pregledač
+Name[sv]=Visning
+Name[xx]=xxViewerxx
+Name[zh_CN]=查看器
+Comment=KIPI OpenGL Image Viewer
+Comment[ca]=Visualitzador d'imatges OpenGL del KIPI
+Comment[da]=KIPI-OpenGL billedvisning
+Comment[de]=Ein KIPI-Modul zum Betrachten von Bildern mittels OpenGL
+Comment[el]=Προβολέας εικόνων OpenGL των KIPI
+Comment[es]=Visor KIPI de imágenes OpenGL
+Comment[et]=KIPI OpenGL pildinäitaja
+Comment[fi]=KIPI-OpenGL -kuvankatselin
+Comment[fr]=Afficheur d'image OpenGL KIPI
+Comment[it]=Visore di immagini OpenGL di KIPI
+Comment[ja]=Kipi OpenGL 画像ビューア
+Comment[nds]=KIPI-Bildkieker för OpenGL
+Comment[nl]=KIPI OpenGL Afbeeldingsviewer
+Comment[pa]=KIPI OpenGL ਚਿੱਤਰ ਦਰਸ਼ਕ
+Comment[pl]=Wtyczka KIPI - Przeglądarka OpenGL zdjęć
+Comment[pt]=Visualizador de Imagens em OpenGL do KIPI
+Comment[pt_BR]=Visualizador de Imagens OpenGL do KIPI
+Comment[sr]=KIPI-јев OpenGL прегледач слика
+Comment[sr@Latn]=KIPI-jev OpenGL pregledač slika
+Comment[sv]=KIPI-OpenGL bildvisning
+Comment[xx]=xxKIPI OpenGL Image Viewerxx
+Comment[zh_CN]=KIPI OpenGL 图像查看器
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_viewer
+author=Markus Leuthold
diff --git a/kipi-plugins/imageviewer/plugin_viewer.cpp b/kipi-plugins/imageviewer/plugin_viewer.cpp
new file mode 100644
index 0000000..9c9ebe1
--- /dev/null
+++ b/kipi-plugins/imageviewer/plugin_viewer.cpp
@@ -0,0 +1,116 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Markus Leuthold *
+ * <kusi (+at) forum.titlis.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, Cambridge, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+// KDE includes
+#include <kgenericfactory.h>
+#include <kmessagebox.h>
+#include <kurl.h>
+
+// QT includes
+#include <qmessagebox.h>
+
+// kipi includes
+#include <libkipi/imageinfo.h>
+
+// local includes
+#include "plugin_viewer.h"
+#include "viewerwidget.h"
+
+typedef KGenericFactory<Plugin_viewer> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_viewer,
+ Factory("kipiplugin_viewer"))
+
+Plugin_viewer::Plugin_viewer( QObject *parent, const char* name, const QStringList& )
+ :KIPI::Plugin::Plugin( Factory::instance(), parent, name )
+{
+ kdDebug(51001) << "image viewer plugin loaded" << endl;
+}
+
+void Plugin_viewer::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ actionViewer = new KAction (i18n("Image Viewer"),
+ "ViewerWidget",
+ 0, // do never set shortcuts from plugins.
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "viewer");
+ addAction(actionViewer);
+ widget=0;
+}
+
+KIPI::Category Plugin_viewer::category( KAction* action ) const
+{
+ if ( action == actionViewer ) {
+ return KIPI::TOOLSPLUGIN;
+ }
+ else {
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::TOOLSPLUGIN; // no warning from compiler, please
+ }
+}
+
+
+
+
+
+/*!
+ \fn Plugin_viewer::slotActivate()
+ */
+void Plugin_viewer::slotActivate()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ widget = new KIPIviewer::ViewerWidget(interface);
+
+ switch(widget->getOGLstate()) {
+ case KIPIviewer::oglOK:
+ widget->show();
+ break;
+
+ case KIPIviewer::oglNoRectangularTexture:
+ kdError( 51000 ) << "GL_ARB_texture_rectangle not supported" << endl;
+ delete widget;
+ QMessageBox::critical(new QWidget(),"OpenGL error","GL_ARB_texture_rectangle not supported");
+ break;
+
+ case KIPIviewer::oglNoContext:
+ kdError( 51000 ) << "no OpenGL context found" << endl;
+ delete widget;
+ QMessageBox::critical(new QWidget(),"OpenGL error","no OpenGL context found");
+ }
+}
diff --git a/kipi-plugins/imageviewer/plugin_viewer.h b/kipi-plugins/imageviewer/plugin_viewer.h
new file mode 100644
index 0000000..5ae5547
--- /dev/null
+++ b/kipi-plugins/imageviewer/plugin_viewer.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Markus Leuthold *
+ * <kusi (+at) forum.titlis.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, Cambridge, MA 02110-1301, USA. *
+ ***************************************************************************/
+#ifndef PLUGIN_VIEWER_H
+#define PLUGIN_VIEWER_H
+
+// kipi includes
+#include <libkipi/plugin.h>
+
+// local includes
+#include "viewerwidget.h"
+
+
+class KAction;
+
+/**
+ * @short integration with KIPI
+ * @author Markus Leuthold <kusi (+at) forum.titlis.org>
+ * @version 0.2
+ */
+
+class Plugin_viewer :public KIPI::Plugin
+{
+ Q_OBJECT
+public:
+ Plugin_viewer( QObject *parent, const char* name, const QStringList& );
+ virtual void setup( QWidget* widget );
+ virtual KIPI::Category category( KAction* action ) const;
+
+protected:
+ KIPIviewer::ViewerWidget * widget;
+ KAction * actionViewer;
+
+public slots:
+ void slotActivate();
+};
+
+#endif /* PLUGIN_VIEWER_H */
+
diff --git a/kipi-plugins/imageviewer/texture.cpp b/kipi-plugins/imageviewer/texture.cpp
new file mode 100644
index 0000000..3581be2
--- /dev/null
+++ b/kipi-plugins/imageviewer/texture.cpp
@@ -0,0 +1,440 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Markus Leuthold *
+ * <kusi (+at) forum.titlis.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, Cambridge, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#undef PERFORMANCE_ANALYSIS
+
+// Qt includes
+#include <qwmatrix.h>
+#include <qfileinfo.h>
+
+//KDE includes
+#include <kdebug.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+// libkipi includes
+
+#include <libkipi/interface.h>
+#include <libkipi/imagecollection.h>
+
+// Local includes
+#ifdef PERFORMANCE_ANALYSIS
+ #include "timer.h"
+#endif
+#include "texture.h"
+
+using namespace KIPIviewer;
+
+Texture::Texture(KIPI::Interface *i)
+{
+ kipiInterface = i;
+ rotate_list[0]=90;
+ rotate_list[1]=180;
+ rotate_list[2]=270;
+ rotate_list[3]=180;
+ rotate_idx=0;
+ reset();
+}
+
+
+Texture::~Texture()
+{
+}
+
+
+/*!
+ \fn Texture::height()
+ */
+int Texture::height()
+{
+ return glimage.height();
+}
+
+
+/*!
+ \fn Texture::width()
+ */
+int Texture::width()
+{
+ return glimage.width();
+}
+
+
+/*!
+ \fn Texture::load(QString fn, QSize size, GLuint tn)
+ \brief load file from disc and save it in texture
+ \param fn filename to load
+ \param size size of image which is downloaded to texture mem
+ \param tn texture id generated by glGenTexture
+ if "size" is set to image size, scaling is only performed by the GPU but not
+ by the CPU, however the AGP usage to texture memory is increased (20MB for a 5mp image)
+ */
+bool Texture::load(QString fn, QSize size, GLuint tn)
+{
+ filename=fn;
+ initial_size=size;
+ _texnr=tn;
+
+ // check if its a RAW file.
+#if KDCRAW_VERSION < 0x000106
+ QString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles());
+#else
+ QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
+#endif
+ QFileInfo fileInfo(fn);
+ if (rawFilesExt.upper().contains( fileInfo.extension(false).upper() )) {
+ // it's a RAW file, use the libkdcraw loader
+ KDcrawIface::KDcraw::loadDcrawPreview(qimage, fn);
+ } else {
+ // use the standard loader
+ qimage=QImage(fn);
+ }
+
+ //handle rotation
+ KIPI::ImageInfo info = kipiInterface->info(filename);
+ if (info.angle() != 0) {
+ QWMatrix r;
+ r.rotate(info.angle());
+ qimage=qimage.xForm(r);
+ kdDebug(51000) << "image rotated by " << info.angle() << " degree" << endl;
+ }
+
+ if (qimage.isNull()) {
+ return false;
+ }
+
+ _load();
+ reset();
+ rotate_idx=0;
+ return true;
+}
+
+/*!
+ \fn Texture::load(QImage im, QSize size, GLuint tn)
+ \brief copy file from QImage to texture
+ \param im Qimage to be copied from
+ \param size size of image which is downloaded to texture mem
+ \param tn texture id generated by glGenTexture
+ if "size" is set to image size, scaling is only performed by the GPU but not
+ by the CPU, however the AGP usage to texture memory is increased (20MB for a 5mp image)
+ */
+bool Texture::load(QImage im, QSize size, GLuint tn)
+{
+ qimage=im;
+ initial_size=size;
+ _texnr=tn;
+ _load();
+ reset();
+ rotate_idx=0;
+ return true;
+}
+
+/*!
+ \fn Texture::load()
+ internal load function
+ rt[xy] <= 1
+ */
+bool Texture::_load()
+{
+ int w=initial_size.width();
+ int h=initial_size.height();
+
+ if (w==0 || w>qimage.width() || h>qimage.height()) {
+ glimage=QGLWidget::convertToGLFormat(qimage);
+ } else {
+ glimage=QGLWidget::convertToGLFormat(qimage.scale(w,h,QImage::ScaleMin));
+ }
+
+ w=glimage.width();
+ h=glimage.height();
+ if (h < w) {
+ rtx = 1;
+ rty = float(h)/float(w);
+ }
+ else {
+ rtx = float(w)/float(h);
+ rty = 1;
+ }
+ return true;
+}
+
+/*!
+ \fn Texture::data()
+ */
+GLvoid * Texture::data()
+{
+ return glimage.bits();
+}
+
+
+/*!
+ \fn Texture::texnr()
+ */
+GLuint Texture::texnr()
+{
+ return _texnr;
+}
+
+
+
+/*!
+ \fn Texture::zoom(float delta, QPoint mousepos)
+ \brief calculate new tex coords on zooming
+ \param delta delta between previous zoom and current zoom
+ \param mousepos mouse position returned by QT
+ \TODO rename mousepos to something more generic
+ */
+void Texture::zoom(float delta, QPoint mousepos)
+//u: start in texture, u=[0..1], u=0 is begin, u=1 is end of texture
+//z=[0..1], z=1 -> no zoom
+//l: length of tex in glFrustum coordinate system
+//rt: ratio of tex, rt<=1, see _load() for definition
+//rd: ratio of display, rd>=1
+//m: mouse pos normalized, cd=[0..rd]
+//c: mouse pos normalized to zoom*l, c=[0..1]
+{
+ z*=delta;
+ delta=z*(1.0/delta-1.0); //convert to real delta=z_old-z_new
+
+ float mx=mousepos.x()/(float)display_x*rdx;
+ float cx=(mx-rdx/2.0+rtx/2.0)/rtx;
+ float vx=ux+cx*z;
+ ux=ux+(vx-ux)*delta/z;
+
+ float my=mousepos.y()/(float)display_y*rdy;
+ float cy=(my-rdy/2.0+rty/2.0)/rty;
+ cy=1-cy;
+ float vy=uy+cy*z;
+ uy=uy+(vy-uy)*delta/z;
+
+ calcVertex();
+}
+
+/*!
+ \fn Texture::calcVertex()
+ Calculate vertices according internal state variables
+ z, ux, uy are calculated in Texture::zoom()
+ */
+void Texture::calcVertex()
+// rt: ratio of tex, rt<=1, see _load() for definition
+// u: start in texture, u=[0..1], u=0 is begin, u=1 is end of texture
+// l: length of tex in glFrustum coordinate system
+// halftexel: the color of a texel is determined by a corner of the texel and not its center point
+// this seems to introduce a visible jump on changing the tex-size.
+//
+// the glFrustum coord-sys is visible in [-rdx..rdx] ([-1..1] for square screen) for z=1 (no zoom)
+// the tex coord-sys goes from [-rtx..rtx] ([-1..1] for square texture)
+{
+ // x part
+ float lx=2*rtx/z; //length of tex
+ float tsx=lx/(float)glimage.width(); //texelsize in glFrustum coordinates
+ float halftexel_x = tsx/2.0;
+ float wx=lx*(1-ux-z);
+ vleft = -rtx-ux*lx - halftexel_x; //left
+ vright = rtx+wx - halftexel_x; //right
+
+ // y part
+ float ly=2*rty/z;
+ float tsy=ly/(float)glimage.height(); //texelsize in glFrustum coordinates
+ float halftexel_y = tsy/2.0;
+ float wy=ly*(1-uy-z);
+ vbottom = -rty - uy*ly + halftexel_y; //bottom
+ vtop = rty + wy + halftexel_y; //top
+
+}
+
+/*!
+ \fn Texture::vertex_bottom()
+ */
+GLfloat Texture::vertex_bottom()
+{
+ return (GLfloat) vbottom;
+}
+
+/*!
+ \fn Texture::vertex_top()
+ */
+GLfloat Texture::vertex_top()
+{
+ return (GLfloat) vtop;
+}
+
+
+/*!
+ \fn Texture::vertex_left()
+ */
+GLfloat Texture::vertex_left()
+{
+ return (GLfloat) vleft;
+}
+
+
+/*!
+ \fn Texture::vertex_right()
+ */
+GLfloat Texture::vertex_right()
+{
+ return (GLfloat) vright;
+}
+
+
+/*!
+ \fn Texture::setViewport(int w, int h)
+ \param w width of window
+ \param h height of window
+ Set widget's viewport. Ensures that rdx & rdy are always > 1
+ */
+void Texture::setViewport(int w, int h)
+{
+ if (h>w) {
+ rdx=1.0;
+ rdy=h/float(w);
+ }
+ else {
+ rdx=w/float(h);
+ rdy=1.0;
+ }
+ display_x=w;
+ display_y=h;
+}
+
+
+/*!
+ \fn Texture::move(QPoint diff)
+ new tex coordinates have to be calculated if the view is panned
+ */
+void Texture::move(QPoint diff)
+{
+ ux=ux-diff.x()/float(display_x)*z*rdx/rtx;
+ uy=uy+diff.y()/float(display_y)*z*rdy/rty;
+ calcVertex();
+}
+
+
+/*!
+ \fn Texture::reset()
+ */
+void Texture::reset()
+{
+ ux=0;
+ uy=0;
+ z=1.0;
+ float zoomdelta=0;
+
+ if ((rtx<rty) && (rdx<rdy) && (rtx/rty < rdx/rdy)) {
+ zoomdelta=z-rdx/rdy;
+ }
+ if ((rtx<rty) && (rtx/rty > rdx/rdy)) {
+ zoomdelta=z-rtx;
+ }
+
+ if ((rtx>=rty) && (rdy<rdx) && (rty/rtx < rdy/rdx)) {
+ zoomdelta=z-rdy/rdx;
+ }
+ if ((rtx>=rty) && (rty/rtx > rdy/rdx)) {
+ zoomdelta=z-rty;
+ }
+ QPoint p = QPoint(display_x/2,display_y/2);
+ zoom(1.0-zoomdelta,p);
+
+ calcVertex();
+}
+
+/*!
+ \fn Texture::setSize(QSize size)
+ \param size desired texture size. QSize(0,0) will take the full image
+ \return true if size has changed, false otherwise
+ set new texture size in order to reduce AGP bandwidth
+ */
+bool Texture::setSize(QSize size)
+{
+ //don't allow larger textures than the original image. the image will be upsampled by
+ //OpenGL if necessary and not by QImage::scale
+ size=size.boundedTo(qimage.size());
+
+ if (glimage.width()==size.width()) {
+ return false;
+ }
+
+ int w=size.width();
+ int h=size.height();
+
+ if (w==0) {
+ glimage=QGLWidget::convertToGLFormat(qimage);
+ } else {
+ glimage=QGLWidget::convertToGLFormat(qimage.scale(w,h,QImage::ScaleMin));
+ }
+
+ //recalculate half-texel offset
+ calcVertex();
+
+ return true;
+}
+
+
+/*!
+ \fn Texture::rotate()
+ \brief smart image rotation
+ since the two most frequent usecases are a CW or CCW rotation of 90,
+ perform these rotation with one (+90) or two (-90) calls of rotation()
+ */
+void Texture::rotate()
+{
+ QWMatrix r;
+ r.rotate(rotate_list[rotate_idx%4]);
+ qimage=qimage.xForm(r);
+ _load();
+
+ //save new rotation in exif header
+ KIPI::ImageInfo info = kipiInterface->info(filename);
+ info.setAngle(rotate_list[rotate_idx%4]);
+
+ reset();
+ rotate_idx++;
+}
+
+
+/*!
+ \fn Texture::setToOriginalSize()
+ zoom image such that each pixel of the screen corresponds to a pixel in the jpg
+ remember that OpenGL is not a pixel exact specification, and the image will still be filtered by OpenGL
+ */
+void Texture::zoomToOriginal()
+{
+ float zoomfactorToOriginal;
+ reset();
+
+ if (qimage.width()/qimage.height() > float(display_x)/float(display_y)) {
+ //image touches right and left edge of window
+ zoomfactorToOriginal=float(display_x)/qimage.width();
+ } else {
+ //image touches upper and lower edge of window
+ zoomfactorToOriginal=float(display_y)/qimage.height();
+ }
+
+ zoom(zoomfactorToOriginal,QPoint(display_x/2,display_y/2));
+}
diff --git a/kipi-plugins/imageviewer/texture.h b/kipi-plugins/imageviewer/texture.h
new file mode 100644
index 0000000..47fbfdd
--- /dev/null
+++ b/kipi-plugins/imageviewer/texture.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Markus Leuthold *
+ * <kusi (+at) forum.titlis.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, Cambridge, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef TEXTURE_H
+#define TEXTURE_H
+
+//QT includes
+#include <qgl.h>
+#include <qstring.h>
+#include <qdatetime.h>
+#include <qimage.h>
+
+// libkipi includes
+
+#include <libkipi/interface.h>
+#include <libkipi/imagecollection.h>
+
+/**
+ * @short Texture class
+ * @author Markus Leuthold <kusi (+at) forum.titlis.org>
+ * @version 0.2
+ */
+
+namespace KIPIviewer {
+class Texture{
+public:
+ Texture(KIPI::Interface *);
+ ~Texture();
+ int height();
+ int width();
+ bool load(QString fn, QSize size, GLuint tn);
+ bool load(QImage im, QSize size, GLuint tn);
+ GLvoid * data();
+ GLuint texnr();
+ GLfloat vertex_bottom();
+ GLfloat vertex_top();
+ GLfloat vertex_left();
+ GLfloat vertex_right();
+ void setViewport(int w, int h);
+ void zoom(float delta, QPoint mousepos);
+ void reset();
+ void move(QPoint diff);
+ bool setSize(QSize size);
+ void rotate();
+ void zoomToOriginal();
+
+protected:
+ bool _load();
+ void calcVertex();
+
+ int display_x, display_y;
+ GLuint _texnr;
+ QSize initial_size;
+ QString filename;
+ QImage qimage, glimage;
+ float rdx,rdy,z,ux,uy,rtx,rty;
+ float vtop, vbottom, vleft, vright;
+ int rotate_list[4], rotate_idx;
+ KIPI::Interface * kipiInterface;
+};
+}; //namespace KIPIviewer
+
+#endif
diff --git a/kipi-plugins/imageviewer/timer.cpp b/kipi-plugins/imageviewer/timer.cpp
new file mode 100644
index 0000000..5c8d818
--- /dev/null
+++ b/kipi-plugins/imageviewer/timer.cpp
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Markus Leuthold *
+ * <kusi (+at) forum.titlis.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, Cambridge, MA 02110-1301, USA. *
+ ***************************************************************************/
+#include <kdebug.h>
+#include "timer.h"
+
+using namespace KIPIviewer;
+
+Timer::Timer()
+{
+}
+
+void Timer::start()
+{
+ timer.start();
+ meantime=0;
+}
+
+void Timer::at(QString s)
+{
+ meantime=timer.elapsed()-meantime;
+ kdDebug(51000) << "stopwatch:"<< s << ": " << meantime << " ms overall: " << timer.elapsed() << " ms" << endl;
+}
+
+Timer::~Timer()
+{
+}
+
+
diff --git a/kipi-plugins/imageviewer/timer.h b/kipi-plugins/imageviewer/timer.h
new file mode 100644
index 0000000..f05e222
--- /dev/null
+++ b/kipi-plugins/imageviewer/timer.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Markus Leuthold *
+ * <kusi at forum.titlis.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, Cambridge, MA 02110-1301, USA. *
+ ***************************************************************************/
+#ifndef TIMER_H
+#define TIMER_H
+#include <qstring.h>
+#include <qdatetime.h>
+
+/**
+ * @short convenience class for profiling
+ * @author Markus Leuthold <kusi (+at) forum.titlis.org>
+ * @version 0.2
+ */
+
+namespace KIPIviewer {
+class Timer{
+public:
+ Timer();
+ ~Timer();
+ void start();
+ void at(QString s);
+protected:
+ QTime timer;
+ int meantime;
+};
+}; //namespace KIPIviewer
+#endif
diff --git a/kipi-plugins/imageviewer/viewerwidget.cpp b/kipi-plugins/imageviewer/viewerwidget.cpp
new file mode 100644
index 0000000..082d27f
--- /dev/null
+++ b/kipi-plugins/imageviewer/viewerwidget.cpp
@@ -0,0 +1,690 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Markus Leuthold *
+ * <kusi (+at) forum.titlis.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, Cambridge, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#undef PERFORMANCE_ANALYSIS
+
+// global includes
+#include <qgl.h>
+#include <iostream>
+#include <qlabel.h>
+#include <klocale.h>
+#include <qdragobject.h>
+#include <qbitmap.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+
+// local includes.
+#include "viewerwidget.h"
+#include "texture.h"
+#include "help.h"
+#ifdef PERFORMANCE_ANALYSIS
+ #include "timer.h"
+#endif
+#include "viewerwidget.moc"
+
+// using namespace std;
+using namespace KIPIviewer;
+
+ViewerWidget::ViewerWidget(KIPI::Interface* i) {
+
+ kipiInterface = i;
+
+ KIPI::ImageCollection selection = kipiInterface->currentSelection();
+ KIPI::ImageCollection album = kipiInterface->currentAlbum();
+
+
+ KURL::List myfiles; //pics which are displayed in imageviewer
+ QString selectedImage; //selected pic in hostapp
+
+ int foundNumber=0;
+ file_idx=0; //index of picture to be displayed
+
+ if ( selection.images().count()==0 ) {
+ kdDebug(51000) << "no image selected, load entire album" << endl;
+ myfiles = album.images();
+ }
+ else if ( selection.images().count()==1 ) {
+ kdDebug(51000) << "one image selected, load entire album and start with selected image" << endl;
+ selectedImage = selection.images().first().path();
+ myfiles = album.images();
+ }
+ else if ( selection.images().count()>1 ) {
+ kdDebug(51000) << "load " << selection.images().count() << " selected images" << endl;
+ myfiles = selection.images();
+ }
+
+ // populate QStringList::files
+ for(KURL::List::Iterator it = myfiles.begin(); it != myfiles.end();it++) {
+
+ // find selected image in album in order to determine the first displayed image
+ // in case one image was selected and the entire album was loaded
+ QString s = (*it).path();
+ if ( s==selectedImage ) {
+ kdDebug(51000) << "selected img " << selectedImage << " has idx=" << foundNumber << endl;
+ file_idx=foundNumber;
+ }
+
+ // only add images to files
+ KMimeType::Ptr type = KMimeType::findByURL(s);
+ bool isImage=type->name().find("image")>=0;
+
+ if ( isImage ) {
+ files.append(s);
+ foundNumber++; //counter for searching the start image in case one image is selected
+ kdDebug(51000) << s << " type=" << type->name() << endl;
+ }
+ }
+
+ firstImage=true;
+ kdDebug(51000) << files.count() << "images loaded" << endl;
+
+ // initialize cache
+ for(int i=0;i<CACHESIZE;i++) {
+ cache[i].file_index=EMPTY;
+ cache[i].texture=new Texture(kipiInterface);
+ }
+
+ // define zoomfactors for one zoom step
+ zoomfactor_scrollwheel = 1.1;
+ zoomfactor_mousemove = 1.03;
+ zoomfactor_keyboard = 1.05;
+
+ // load cursors for zooming and panning
+ QString file;
+ file = locate( "data", "kipiplugin_imageviewer/pics/zoom.png" );
+ zoomCursor=QCursor(file);
+ file = locate( "data", "kipiplugin_imageviewer/pics/hand.png" );
+ moveCursor=QCursor(file);
+
+ // get path of nullImage in case QImage can't load the image
+ nullImage = locate( "data", "kipiplugin_imageviewer/pics/nullImage.png" );
+
+ showFullScreen();
+
+ // let the cursor dissapear after 2sec of inactivity
+ connect( &timerMouseMove, SIGNAL(timeout()),this, SLOT( timeoutMouseMove()) );
+ timerMouseMove.start(2000);
+ setMouseTracking(true);
+
+ // while zooming is performed, the image is downsampled to zoomsize. This seems to
+ // be the optimal way for a PentiumM 1.4G, Nvidia FX5200. For a faster setup, this might
+ // not be necessary anymore
+ zoomsize=QSize(1024,768);
+
+ // other initialisations
+ wheelAction = changeImage;
+}
+
+
+/*!
+ \fn ViewerWidget::initializeGL()
+ \todo blending
+ */
+void ViewerWidget::initializeGL() {
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ // Clear The Background Color
+ glClearColor(0.0, 0.0, 0.0, 1.0f);
+ // Turn Blending On
+ glEnable(GL_BLEND);
+ // Blending Function For Translucency Based On Source Alpha Value
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ // Enable perspective vision
+ glClearDepth(1.0f);
+ // Generate texture
+ glGenTextures(1, tex);
+}
+
+
+/*!
+ \fn ViewerWidget::paintGL()
+ */
+void ViewerWidget::paintGL() {
+ //prepare 1st image
+ //this test has to be performed here since QWidget::width() is only updated now
+ if (firstImage) {
+ texture=loadImage(file_idx);
+ texture->reset();
+ downloadTex(texture);
+ }
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+ glTranslatef(0.0f,0.0f,-5.0f);
+ drawImage(texture);
+
+ //preload the 2nd image
+ if (firstImage) {
+ if (file_idx<(files.count()-1)) {
+ loadImage(file_idx+1);
+ }
+ firstImage=false;
+ }
+}
+
+
+
+
+/*!
+ \fn ViewerWidget::resizeGL(int w, int h)
+ */
+void ViewerWidget::resizeGL(int w, int h)
+{
+ glViewport(0, 0, (GLint)w, (GLint)h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ if (h>w) {
+ ratio_view_x=1.0;
+ ratio_view_y=h/float(w);
+ }
+ else {
+ ratio_view_x=w/float(h);
+ ratio_view_y=1.0;
+ }
+
+ glFrustum( -ratio_view_x, ratio_view_x, -ratio_view_y, ratio_view_y,5, 5000.0 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ if (!firstImage) {
+ texture->setViewport(w,h);
+ }
+}
+
+
+
+
+
+/*!
+ \fn ViewerWidget::drawImage(Texture * texture)
+ \brief render the image
+ */
+void ViewerWidget::drawImage(Texture * texture)
+{
+// cout << "enter drawImage: target=" << texture->texnr() << " dim=" << texture->height() << " " << texture->width() << endl;
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, texture->texnr());
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0);
+ glVertex3f(texture->vertex_left(), texture->vertex_bottom(), 0);
+
+ glTexCoord2f(texture->width(), 0);
+ glVertex3f(texture->vertex_right(), texture->vertex_bottom(), 0);
+
+ glTexCoord2f(texture->width(), texture->height());
+ glVertex3f(texture->vertex_right(), texture->vertex_top(), 0);
+
+ glTexCoord2f(0, texture->height());
+ glVertex3f(texture->vertex_left(), texture->vertex_top(), 0);
+ glEnd();
+}
+
+
+/*!
+ \fn ViewerWidget::keyPressEvent(QKeyEvent *k)
+ Handle all keyboard events. All events which are not handled trigger
+ a help window.
+ */
+void ViewerWidget::keyPressEvent(QKeyEvent *k)
+{
+ QPoint middlepoint;
+
+ switch (k->key()) {
+ // next image
+ case Key_N:
+ case Key_Right:
+ case Key_Down:
+ case Key_PageDown:
+ case Key_Space:
+ nextImage();
+ break;
+
+ // previous image
+ case Key_P:
+ case Key_Left:
+ case Key_Up:
+ case Key_PageUp:
+ prevImage();
+ break;
+
+ // rotate image
+ case Key_R:
+ texture->rotate();
+ downloadTex(texture);
+ updateGL();
+ break;
+
+ // terminate image viewer
+ case Key_Escape:
+ // clean up: where does this have to be done?
+ close(true);
+ break;
+
+ // full screen
+ case Key_F:
+ // according to QT documentation, showFullScreen() has some
+ // serious issues on window managers that do not follow modern
+ // post-ICCCM specifications
+ if (isFullScreen()) {
+ texture->reset();
+ showNormal();
+ } else {
+ texture->reset();
+ showFullScreen();
+ }
+ break;
+
+ // reset size and redraw
+ case Key_Z:
+ texture->reset();
+ updateGL();
+ break;
+
+ // toggle permanent between "show next image" and "zoom" on mousewheel change
+ case Key_C:
+ if (wheelAction==zoomImage)
+ wheelAction=changeImage;
+ else
+ wheelAction=zoomImage;
+ break;
+
+ // zoom in
+ case Key_Plus:
+ middlepoint = QPoint(width()/2,height()/2);
+ if (texture->setSize( zoomsize )) {
+ downloadTex(texture); //load full resolution image
+ };
+ zoom(-1, middlepoint, zoomfactor_keyboard);
+ break;
+
+ // zoom out
+ case Key_Minus:
+ middlepoint = QPoint(width()/2,height()/2);
+ if (texture->setSize( zoomsize ))
+ downloadTex(texture); //load full resolution image
+ zoom(1, middlepoint, zoomfactor_keyboard);
+ break;
+
+ // zoom to original size
+ case Key_O:
+ texture->zoomToOriginal();
+ updateGL();
+ break;
+
+ // toggle temorarily between "show next image" and "zoom" on mousewheel change
+ case Key_Control:
+ if (wheelAction==zoomImage)
+ //scrollwheel changes to the next image
+ wheelAction=changeImage;
+ else {
+ //scrollwheel does zoom
+ wheelAction=zoomImage;
+ setCursor (zoomCursor);
+ timerMouseMove.stop();
+ }
+ break;
+
+
+ //do noting, don't trigger the help dialog
+ case Key_Shift:
+ break;
+
+ //key is not bound to any action, therefore show help dialog to enlighten the user
+ default:
+ QDialog * h = new HelpDialog(0,0,Qt::WStyle_StaysOnTop);
+ h->show();
+ }
+}
+
+/*!
+ \fn ViewerWidget::keyReleaseEvent ( QKeyEvent * e )
+ */
+void ViewerWidget::keyReleaseEvent ( QKeyEvent * e )
+{
+ switch (e->key()) {
+ case Key_Plus:
+ case Key_Minus:
+ if (!e->isAutoRepeat()) {
+ unsetCursor();
+ if (texture->setSize(QSize(0,0))) {
+ downloadTex(texture); //load full resolution image
+ }
+ updateGL();
+ } else
+ e->ignore();
+ break;
+
+ case Key_Control:
+ if (wheelAction==zoomImage)
+ wheelAction=changeImage;
+ else
+ wheelAction=zoomImage;
+ unsetCursor();
+ timerMouseMove.start(2000);
+ break;
+
+ default:
+ e->ignore();
+ break;
+ }
+
+}
+
+
+/*!
+ \fn ViewerWidget::downloadTex(Texture * tex)
+ download texture to video memory
+ */
+void ViewerWidget::downloadTex(Texture * tex)
+{
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, tex->texnr());
+ // glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_ARB);
+ // glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_ARB);
+
+// uncomment the following line to enable flat shading of texels -> debugging
+// glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+
+ glTexImage2D( GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, tex->width(), tex->height(), 0,GL_RGBA, GL_UNSIGNED_BYTE, tex->data());
+}
+
+
+
+/*!
+ \fn ViewerWidget::loadImage(int file_index)
+ \param file_index index to QStringList files
+ load files[file_index] into a texture object if it is not already cached
+ */
+Texture * ViewerWidget::loadImage(int file_index)
+{
+ int imod=file_index%CACHESIZE; //index for cache
+
+ if (cache[imod].file_index==file_index){
+ //image is already cached
+ kdDebug(51000) << "image " << file_index << " is already in cache@" << imod << endl;
+ return cache[imod].texture;
+
+ } else {
+ // image is net yet loaded
+ QString f = files[file_index];
+ kdDebug(51000) << "loading image " << f << "(idx=" << file_index << ") to cache@" << imod << endl;
+ cache[imod].file_index=file_index;
+
+ // handle non-loadable images
+ if (!cache[imod].texture->load(f,QSize(width(),height()),tex[0])) {
+ cache[imod].texture->load(nullImage,QSize(width(),height()),tex[0]);
+ }
+
+ cache[imod].texture->setViewport(width(),height());
+ return cache[imod].texture;
+ }
+}
+
+
+/*!
+ \fn ViewerWidget::wheelEvent ( QWheelEvent * e )
+ */
+void ViewerWidget::wheelEvent ( QWheelEvent * e )
+{
+ switch(wheelAction) {
+ // mousewheel triggers zoom
+ case zoomImage:
+ setCursor(zoomCursor);
+ zoom(e->delta(), e->pos(), zoomfactor_scrollwheel);
+ break;
+
+ // mousewheel triggers image change
+ case changeImage:
+ if (e->delta() < 0)
+ nextImage();
+ else
+ prevImage();
+ break;
+ }
+}
+
+
+/*!
+ \fn ViewerWidget::mousePressEvent ( QMouseEvent * e )
+ */
+void ViewerWidget::mousePressEvent ( QMouseEvent * e )
+{
+ // begin zoom
+ // scale down texture for fast zooming
+ // texture will be set to original size on mouse up
+ if (texture->setSize( zoomsize )) { //load downsampled image
+ downloadTex(texture);
+ }
+
+ timerMouseMove.stop(); //user is something up to, therefore keep the cursor
+ if ( e->button() == LeftButton ) {
+ setCursor (moveCursor); //defined in constructor
+ }
+
+ if ( e->button() == RightButton ) {
+ setCursor (zoomCursor);
+ }
+
+ startdrag=e->pos();
+ previous_pos=e->pos();
+}
+
+
+/*!
+ \fn ViewerWidget::mouseMoveEvent ( QMouseEvent * e )
+ */
+void ViewerWidget::mouseMoveEvent ( QMouseEvent * e )
+{
+ if ( e->state() == LeftButton ) {
+ //panning
+ QPoint diff=e->pos()-startdrag;
+ texture->move(diff);
+ updateGL();
+ startdrag=e->pos();
+ } else if ( e->state() == RightButton ) {
+ //zooming
+ zoom(previous_pos.y()-e->y(), startdrag, zoomfactor_mousemove );
+ previous_pos=e->pos();
+ } else {
+ //no key is pressed while moving mouse
+ //don't do anything if ctrl is pressed
+ if (timerMouseMove.isActive()) {
+ //ctrl is not pressed, no zooming, therefore restore and hide cursor in 2 sec
+ unsetCursor();
+ timerMouseMove.start(2000);
+ }
+ }
+ return;
+}
+
+
+
+
+/*!
+ \fn ViewerWidget::prevImage()
+ */
+void ViewerWidget::prevImage()
+{
+ #ifdef PERFORMANCE_ANALYSIS
+ Timer timer;
+ #endif
+
+ if (file_idx>0)
+ file_idx--;
+ else
+ return;
+#ifdef PERFORMANCE_ANALYSIS
+ timer.start();
+#endif
+ texture = loadImage(file_idx);
+ texture->reset();
+
+#ifdef PERFORMANCE_ANALYSIS
+ timer.at("loadImage");
+#endif
+
+ downloadTex(texture);
+
+#ifdef PERFORMANCE_ANALYSIS
+ timer.at("downloadTex");
+#endif
+
+ updateGL();
+
+#ifdef PERFORMANCE_ANALYSIS
+ timer.at("updateGL");
+#endif
+
+ //image preloading
+ if (file_idx>0)
+ loadImage(file_idx-1);
+}
+
+
+/*!
+ \fn ViewerWidget::nextImage()
+ */
+void ViewerWidget::nextImage()
+{
+#ifdef PERFORMANCE_ANALYSIS
+ Timer timer;
+#endif
+ if (file_idx<(files.count()-1))
+ file_idx++;
+ else
+ return;
+#ifdef PERFORMANCE_ANALYSIS
+ timer.start();
+#endif
+ texture = loadImage(file_idx);
+ texture->reset();
+#ifdef PERFORMANCE_ANALYSIS
+ timer.at("loadImage");
+#endif
+ downloadTex(texture);
+#ifdef PERFORMANCE_ANALYSIS
+ timer.at("downloadTex");
+#endif
+ updateGL();
+#ifdef PERFORMANCE_ANALYSIS
+ timer.at("updateGL");
+#endif
+
+ //image preloading
+ if (file_idx<(files.count()-1)) {
+ loadImage(file_idx+1);
+#ifdef PERFORMANCE_ANALYSIS
+ timer.at("preloading");
+#endif
+ }
+}
+
+
+/*!
+ \fn ViewerWidget::zoom(int mdelta, QPos pos)
+ \param mdelta delta of mouse movement:
+ mdelta>0: zoom in
+ mdelta<0: zoom out
+ mdelta=0: do nothing
+ \param pos position of mouse
+ \param factor zoom factor:scrollwheel needs a higher factor that right click mouse move. factor=1 -> no zoom
+ */
+void ViewerWidget::zoom(int mdelta, QPoint pos, float factor)
+{
+ if (mdelta==0) {
+ //do nothing
+ return;
+ }
+
+ if (mdelta > 0) {
+ //multiplicator for zooming in
+ delta=factor;
+ }
+
+ if (mdelta < 0) {
+ //multiplicator for zooming out
+ delta=2.0-factor;
+ }
+
+ texture->zoom(delta,pos);
+ updateGL();
+}
+
+
+/*!
+ \fn ViewerWidget::mouseDoubleClickEvent(QMouseEvent * e )
+ a double click resets the view (zoom and move)
+ */
+void ViewerWidget::mouseDoubleClickEvent(QMouseEvent * )
+{
+ texture->reset();
+ updateGL();
+}
+
+
+/*!
+ \fn ViewerWidget::mouseReleaseEvent(QMouseEvent * e)
+ */
+void ViewerWidget::mouseReleaseEvent(QMouseEvent * )
+{
+ timerMouseMove.start(2000);
+ unsetCursor();
+ if (texture->setSize(QSize(0,0))) { //load full resolution image
+ downloadTex(texture);
+ }
+ updateGL();
+}
+
+
+/*!
+ \fn ViewerWidget::timeoutMouseMove()
+ being called if user didn't move the mouse for longer than 2 sec
+ */
+void ViewerWidget::timeoutMouseMove()
+{
+ setCursor (QCursor (blankCursor));
+}
+
+
+
+/*!
+ \fn ViewerWidget::getOGLstate()
+ check if OpenGL engine is ready. This function is called from outside the widget.
+ If OpenGL doen't work correctly, the widget can be destroyed
+ \return OGLstate::oglNoContext No OpenGl context could be retrieved
+ \return OGLstate::oglNoRectangularTexture GLGL_ARB_texture_rectangle is not supported
+ \return OGLstate::oglOK all is fine
+ */
+OGLstate ViewerWidget::getOGLstate()
+{
+ //no OpenGL context is found. Are the drivers ok?
+ if ( !isValid() ) {
+ return oglNoContext;
+ }
+
+ //GL_ARB_texture_rectangle is not supported
+ QString s = QString ( ( char* ) glGetString ( GL_EXTENSIONS ) );
+ if ( !s.contains ( "GL_ARB_texture_rectangle",false ) ) {
+ return oglNoRectangularTexture;
+ }
+
+ //everything is ok!
+ return oglOK;
+}
diff --git a/kipi-plugins/imageviewer/viewerwidget.h b/kipi-plugins/imageviewer/viewerwidget.h
new file mode 100644
index 0000000..6ea093c
--- /dev/null
+++ b/kipi-plugins/imageviewer/viewerwidget.h
@@ -0,0 +1,129 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Markus Leuthold *
+ * <kusi (+at) forum.titlis.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, Cambridge, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef _VIEWERWIDGET_H_
+#define _VIEWERWIDGET_H_
+
+//QT includes
+#include <qgl.h>
+#include <qdir.h>
+#include <qimage.h>
+#include <qdatetime.h>
+#include <iostream>
+#include <kurl.h>
+#include <kmimetype.h>
+#include <qregexp.h>
+#include <qcursor.h>
+#include <qtimer.h>
+
+//kipi includes
+#include <libkipi/imageinfo.h>
+#include <libkipi/interface.h>
+#include <libkipi/imagecollection.h>
+
+//local includes
+#include "texture.h"
+
+/**
+ * @short OpenGL widget for image viewer
+ * @author Markus Leuthold <kusi (+at) forum.titlis.org>
+ * @version 0.2
+ */
+
+
+//keep in mind that one cache entry takes 20MB for a 5mpix pic
+#define CACHESIZE 4
+#define EMPTY 99999
+
+namespace KIPIviewer {
+using namespace std;
+
+enum OGLstate {
+ oglOK, oglNoRectangularTexture, oglNoContext
+};
+
+class ViewerWidget : public QGLWidget
+{
+ Q_OBJECT
+
+public:
+ ViewerWidget(KIPI::Interface*);
+ ~ViewerWidget() {
+ glDeleteTextures(1,tex);
+ for(int i=0;i<CACHESIZE;i++) {
+ cache[i].file_index=EMPTY;
+ delete cache[i].texture;
+ }
+ }
+
+ virtual void initializeGL();
+ virtual void resizeGL(int w, int h);
+ virtual void paintGL();
+ void drawImage(Texture * tex);
+ void downloadTex(Texture * tex);
+ Texture * loadImage(int file_index);
+ void prevImage();
+ void nextImage();
+ void zoom(int mdelta, QPoint pos, float factor);
+ virtual void mouseReleaseEvent(QMouseEvent * e);
+ virtual void keyReleaseEvent ( QKeyEvent * e );
+ OGLstate getOGLstate();
+
+protected:
+ struct Cache {
+ int file_index;
+ Texture * texture;
+
+ };
+
+ enum WheelAction {
+ zoomImage, changeImage
+ };
+ Texture * texture;
+ unsigned int old_file_idx,file_idx,idx, oldidx;
+ float ratio_view_y,ratio_view_x,delta;
+ QTime timer;
+ QDir directory;
+ QStringList files;
+ unsigned char * imageJPEGLIB;
+ Cache cache[CACHESIZE];
+ GLuint tex[3];
+ float vertex_height,vertex_width,vertex_left,vertex_top,vertex_right,vertex_bottom;
+ QPoint startdrag, previous_pos;
+ WheelAction wheelAction;
+ bool firstImage;
+ QSize zoomsize;
+ QTimer timerMouseMove;
+ QCursor moveCursor, zoomCursor;
+ float zoomfactor_scrollwheel, zoomfactor_mousemove, zoomfactor_keyboard;
+ QString nullImage;
+ KIPI::Interface * kipiInterface;
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *k);
+ virtual void wheelEvent ( QWheelEvent * e );
+ virtual void mouseMoveEvent ( QMouseEvent * e );
+ virtual void mousePressEvent ( QMouseEvent * e );
+ virtual void mouseDoubleClickEvent(QMouseEvent * e );
+private slots:
+ void timeoutMouseMove();
+};
+}; //namespace KIPIviewer
+#endif // _VIEWERWIDGET_H_
diff --git a/kipi-plugins/ipodexport/Makefile.am b/kipi-plugins/ipodexport/Makefile.am
new file mode 100644
index 0000000..8d14a4f
--- /dev/null
+++ b/kipi-plugins/ipodexport/Makefile.am
@@ -0,0 +1,27 @@
+
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) \
+ $(LIBKIPI_CFLAGS) \
+ $(LIBGPOD_CFLAGS) \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = kipiplugin_ipodexport.la
+kipiplugin_ipodexport_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+
+kipiplugin_ipodexport_la_SOURCES = plugin_ipodexport.cpp \
+ ipodexportdialog.cpp \
+ ipodheader.cpp \
+ ipodlistitem.cpp \
+ imagelist.cpp
+
+kipiplugin_ipodexport_la_LIBADD = $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_ipodexport_la_LDFLAGS = -module $(KDE_PLUGIN) $(LIBGPOD_LIBS) $(all_libraries)
+
+kde_services_DATA = kipiplugin_ipodexport.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_ipodexport.pot
+
diff --git a/kipi-plugins/ipodexport/imagelist.cpp b/kipi-plugins/ipodexport/imagelist.cpp
new file mode 100644
index 0000000..443fa96
--- /dev/null
+++ b/kipi-plugins/ipodexport/imagelist.cpp
@@ -0,0 +1,145 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.net> *
+ * Originally based off Kipi plugins code, by Gilles Caulier *
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the 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 <qapplication.h>
+#include <qevent.h>
+#include <qdragobject.h>
+#include <qfileinfo.h>
+#include <qpainter.h>
+#include <qsimplerichtext.h>
+
+#include <klocale.h>
+
+#include "imagelist.h"
+
+using namespace IpodExport;
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+ImageList::ImageList( ListType type, QWidget *parent, const char *name )
+ : KListView( parent, name )
+ , m_type( type )
+{
+ if( type == ImageList::UploadType )
+ {
+ setAcceptDrops( true );
+ setDropVisualizer( false );
+ addColumn( i18n("Source Album") );
+ addColumn( i18n("Image") );
+ }
+ else if( type == ImageList::IpodType )
+ {
+ addColumn( i18n("Albums") );
+ setRootIsDecorated( true ); // show expand icons
+ setSorting( -1 );
+ setSelectionMode( QListView::Single );
+ }
+
+ setItemMargin( 3 );
+ setResizeMode( QListView::LastColumn );
+ setAllColumnsShowFocus( true );
+}
+
+void
+ImageList::viewportPaintEvent( QPaintEvent *e )
+{
+ if( e ) KListView::viewportPaintEvent( e );
+
+ if( !childCount() && e )
+ {
+ QPainter p( viewport() );
+ QString minimumText;
+
+ if( m_type == UploadType )
+ {
+ minimumText = (i18n(
+ "<div align=center>"
+ "<h3>Upload Queue</h3>"
+ "To create a queue, "
+ "<b>drag</b> images and "
+ "<b>drop</b> them here.<br><br>"
+ "</div>" ) );
+ }
+ else if( m_type == IpodType )
+ {
+ minimumText = (i18n(
+ "<div align=center>"
+ "<h3>iPod Albums</h3>"
+ "An album needs to be created before images "
+ "can be transferred to the iPod."
+ "</div>" ) );
+ }
+ QSimpleRichText t( minimumText, QApplication::font() );
+
+ if ( t.width()+30 >= viewport()->width() || t.height()+30 >= viewport()->height() )
+ //too big, giving up
+ return;
+
+ const uint w = t.width();
+ const uint h = t.height();
+ const uint x = (viewport()->width() - w - 30) / 2 ;
+ const uint y = (viewport()->height() - h - 30) / 2 ;
+
+ p.setBrush( colorGroup().background() );
+ p.drawRoundRect( x, y, w+30, h+30, (8*200)/w, (8*200)/h );
+ t.draw( &p, x+15, y+15, QRect(), colorGroup() );
+ }
+}
+
+void ImageList::dragEnterEvent( QDragEnterEvent *e )
+{
+ e->accept( QUriDrag::canDecode(e) );
+}
+
+
+bool ImageList::acceptDrag( QDropEvent* e ) const
+{
+ return QUriDrag::canDecode( e );
+}
+
+void ImageList::contentsDropEvent( QDropEvent *e )
+{
+ droppedImagesItems( e );
+}
+
+void ImageList::dropEvent( QDropEvent *e )
+{
+ droppedImagesItems( e );
+}
+
+void ImageList::droppedImagesItems( QDropEvent *e )
+{
+ QStrList strList;
+ QStringList filesPath;
+
+ if ( !QUriDrag::decode(e, strList) ) return;
+
+ QStrList stringList;
+ QStrListIterator it(strList);
+ char *str;
+
+ while ( (str = it.current()) != 0 )
+ {
+ QString filePath = QUriDrag::uriToLocalFile(str);
+ QFileInfo fileInfo(filePath);
+
+ if( fileInfo.isFile() && fileInfo.exists() )
+ filesPath.append( fileInfo.filePath() );
+
+ ++it;
+ }
+
+ if( !filesPath.isEmpty() )
+ emit addedDropItems( filesPath );
+}
diff --git a/kipi-plugins/ipodexport/imagelist.h b/kipi-plugins/ipodexport/imagelist.h
new file mode 100644
index 0000000..351ed5a
--- /dev/null
+++ b/kipi-plugins/ipodexport/imagelist.h
@@ -0,0 +1,60 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// ImageList.H
+//
+// Copyright (C) 2004 Gilles CAULIER <caulier dot gilles at gmail dot com>
+// (C) 2006 Seb Ruiz <me@sebruiz.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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef IMAGELIST_H
+#define IMAGELIST_H
+
+#include <klistview.h>
+
+namespace IpodExport
+{
+
+class ImageList : public KListView
+{
+ Q_OBJECT
+
+ public:
+ enum ListType { UploadType, IpodType };
+
+ ImageList( ListType=UploadType, QWidget *parent=0, const char *name=0 );
+
+ ListType getType() const { return m_type; }
+
+ signals:
+ void addedDropItems( QStringList filesPath );
+
+ protected:
+ bool acceptDrag( QDropEvent *e ) const;
+ void contentsDropEvent( QDropEvent *e );
+ void dragEnterEvent( QDragEnterEvent *e );
+ void dropEvent( QDropEvent *e );
+ void droppedImagesItems( QDropEvent *e );
+ void viewportPaintEvent( QPaintEvent *e );
+
+ private:
+ ListType m_type;
+};
+
+}
+
+#endif
diff --git a/kipi-plugins/ipodexport/imagelistitem.h b/kipi-plugins/ipodexport/imagelistitem.h
new file mode 100644
index 0000000..3751025
--- /dev/null
+++ b/kipi-plugins/ipodexport/imagelistitem.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.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. *
+ * *
+ ***************************************************************************/
+
+#ifndef IMAGELISTITEM_H
+#define IMAGELISTITEM_H
+
+extern "C" {
+#include <gpod/itdb.h>
+}
+
+#include <qstring.h>
+#include <klistview.h>
+#include <klocale.h>
+
+namespace IpodExport
+{
+
+ class ImageListItem : public KListViewItem
+ {
+ public:
+
+ ImageListItem( QListView *parent, QString const & pathSrc, QString const & name )
+ : KListViewItem( parent, QString::null/*set below*/, name )
+ , m_pathSrc( pathSrc )
+ {
+ setText( 0, pathSrc.section('/', -2, -2) );
+ }
+
+ QString pathSrc() const { return m_pathSrc; }
+
+ private:
+ QString m_pathSrc;
+ };
+
+}
+
+#endif // IMAGELISTITEM_H
diff --git a/kipi-plugins/ipodexport/ipodexportdialog.cpp b/kipi-plugins/ipodexport/ipodexportdialog.cpp
new file mode 100644
index 0000000..9cd2b78
--- /dev/null
+++ b/kipi-plugins/ipodexport/ipodexportdialog.cpp
@@ -0,0 +1,798 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.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. *
+ * *
+ ***************************************************************************/
+
+#include "ipodheader.h"
+#include "imagelist.h"
+#include "imagelistitem.h"
+#include "ipodexportdialog.h"
+#include "ipodlistitem.h"
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qframe.h>
+#include <qhgroupbox.h>
+#include <qimage.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qvgroupbox.h>
+#include <qwhatsthis.h>
+#include <qwmatrix.h>
+
+#include <kdebug.h>
+#include <kfileitem.h>
+#include <kfiledialog.h> // add images
+#include <kiconloader.h>
+#include <kinputdialog.h> //new album
+#include <kio/previewjob.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kmountpoint.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+
+#if KIPI_PLUGIN
+#include <libkipi/imagedialog.h>
+#endif
+
+#define debug() kdDebug()
+
+using namespace IpodExport;
+
+UploadDialog *UploadDialog::s_instance = 0;
+
+UploadDialog::UploadDialog(
+ #if KIPI_PLUGIN
+ KIPI::Interface* interface,
+ #endif
+ QString caption, QWidget *parent )
+ : KDialogBase( KDialogBase::Plain, caption, /*Help|*/Close,
+ Cancel, parent, "TripodDialog", false, false )
+#if KIPI_PLUGIN
+ , m_interface( interface )
+#endif
+ , m_itdb( 0 )
+ , m_ipodInfo( 0 )
+ , m_ipodHeader( 0 )
+ , m_transferring( false )
+ , m_destinationAlbum( 0 )
+ , m_ipodAlbumList( 0 )
+ , m_mountPoint( QString::null )
+ , m_deviceNode( QString::null )
+{
+ s_instance = this;
+
+ QWidget *box = plainPage();
+ QVBoxLayout *dvlay = new QVBoxLayout( box, 6 );
+
+ dvlay->setMargin( 2 );
+
+ m_ipodHeader = new IpodHeader( box );
+ dvlay->addWidget( m_ipodHeader );
+
+ m_destinationBox = new QHGroupBox( i18n("iPod"), box );
+
+ m_ipodAlbumList = new ImageList( ImageList::IpodType, m_destinationBox );
+ m_ipodAlbumList->setMinimumHeight( 80 );
+
+ QWidget *buttons = new QWidget( m_destinationBox );
+ QVBoxLayout *buttonLayout = new QVBoxLayout( buttons, 0, spacingHint() );
+
+ m_createAlbumButton = new QPushButton( i18n("&New..."), buttons, "addAlbumButton");
+ QWhatsThis::add( m_createAlbumButton, i18n("Create a new photo album on the iPod."));
+
+ m_removeAlbumButton = new QPushButton( i18n("&Remove"), buttons, "remAlbumButton");
+ m_renameAlbumButton = new QPushButton( i18n("R&ename..."), buttons, "renameAlbumsButton");
+
+ m_removeAlbumButton->setEnabled( false );
+ m_renameAlbumButton->setEnabled( false );
+
+ QWhatsThis::add( m_removeAlbumButton, i18n("Remove the selected photos or albums from the iPod."));
+ QWhatsThis::add( m_renameAlbumButton, i18n("Rename the selected photo album on the iPod."));
+
+ QLabel *ipod_icon = new QLabel( buttons );
+ ipod_icon->setPixmap( KGlobal::iconLoader()->loadIcon( "ipod", KIcon::Desktop, KIcon::SizeHuge ) );
+
+ m_ipodPreview = new QLabel( buttons );
+ m_ipodPreview->setFixedHeight( 80 );
+ m_ipodPreview->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ m_ipodPreview->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
+
+ buttonLayout->addWidget( m_createAlbumButton );
+ buttonLayout->addWidget( m_removeAlbumButton );
+ buttonLayout->addWidget( m_renameAlbumButton );
+ buttonLayout->addWidget( m_ipodPreview );
+ buttonLayout->addStretch( 1 );
+ buttonLayout->addWidget( ipod_icon );
+
+ dvlay->addWidget( m_destinationBox );
+
+ m_urlListBox = new QHGroupBox( i18n("Hard Disk"), box );
+ QWidget* urlBox = new QWidget( m_urlListBox );
+ QHBoxLayout* urlLayout = new QHBoxLayout( urlBox, 0, spacingHint() );
+ m_uploadList = new ImageList( ImageList::UploadType, urlBox );
+ m_uploadList->setMinimumHeight( 80 );
+ urlLayout->addWidget( m_uploadList );
+
+ m_uploadList->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::MinimumExpanding );
+
+ QVBoxLayout* uploadPaneLayout = new QVBoxLayout( urlLayout );
+ m_addImagesButton = new QPushButton ( i18n( "&Add..." ), urlBox );
+ uploadPaneLayout->addWidget( m_addImagesButton );
+ QWhatsThis::add( m_addImagesButton, i18n("Add images to be queued for the iPod.") );
+
+ m_remImagesButton = new QPushButton ( i18n( "&Remove" ), urlBox );
+ uploadPaneLayout->addWidget( m_remImagesButton );
+ QWhatsThis::add( m_remImagesButton, i18n("Remove selected image from the list.") );
+
+ m_transferImagesButton = new QPushButton( i18n( "&Transfer" ), urlBox );
+ uploadPaneLayout->addWidget( m_transferImagesButton );
+ QWhatsThis::add( m_transferImagesButton, i18n("Transfer images to the selected iPod album.") );
+
+ m_imagePreview = new QLabel( urlBox );
+ m_imagePreview->setFixedHeight( 80 );
+ m_imagePreview->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ m_imagePreview->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
+ QWhatsThis::add( m_imagePreview, i18n( "The preview of the selected image in the list." ) );
+
+ QLabel *hdd_icon = new QLabel( urlBox );
+ hdd_icon->setPixmap( KGlobal::iconLoader()->loadIcon( "system", KIcon::Desktop, KIcon::SizeHuge ) );
+
+ uploadPaneLayout->addWidget( m_imagePreview );
+ uploadPaneLayout->addStretch( 1 );
+ uploadPaneLayout->addWidget( hdd_icon );
+
+ dvlay->addWidget( m_urlListBox );
+
+ /// populate the ipod view with a list of albums etc
+ refreshDevices();
+
+#if KIPI_PLUGIN
+ /// add selected items to the ImageList
+ KIPI::ImageCollection images = interface->currentSelection();
+
+ if ( images.isValid() )
+ {
+ KURL::List selected = images.images();
+ for( KURL::List::Iterator it = selected.begin(); it != selected.end(); ++it )
+ {
+ addUrlToList( (*it).path() );
+ }
+ }
+#endif
+
+ enableButtons();
+
+ /// connect the signals & slots
+
+ connect( m_createAlbumButton, SIGNAL( clicked() ), SLOT( createIpodAlbum() ) );
+ connect( m_removeAlbumButton, SIGNAL( clicked() ), SLOT( deleteIpodAlbum() ) );
+ connect( m_renameAlbumButton, SIGNAL( clicked() ), SLOT( renameIpodAlbum() ) );
+
+ connect( m_uploadList, SIGNAL( addedDropItems(QStringList) ), SLOT( addDropItems(QStringList) ) );
+ connect( m_uploadList, SIGNAL( currentChanged(QListViewItem*) ), SLOT( imageSelected(QListViewItem*) ) );
+ connect( m_ipodAlbumList, SIGNAL( currentChanged(QListViewItem*) ), SLOT( ipodItemSelected(QListViewItem*) ) );
+
+ connect( m_addImagesButton, SIGNAL( clicked() ), SLOT( imagesFilesButtonAdd() ) );
+ connect( m_remImagesButton, SIGNAL( clicked() ), SLOT( imagesFilesButtonRem() ) );
+ connect( m_transferImagesButton, SIGNAL( clicked() ), SLOT( startTransfer() ) );
+}
+
+void
+UploadDialog::getIpodAlbums()
+{
+ if( !m_itdb ) return;
+
+ debug() << "populating ipod view" << endl;
+
+ // clear cache
+ while( m_ipodAlbumList->firstChild() )
+ delete m_ipodAlbumList->firstChild();
+
+ IpodAlbumItem *last = 0;
+ for( GList *it = m_itdb->photoalbums; it; it = it->next )
+ {
+ Itdb_PhotoAlbum *ipodAlbum = (Itdb_PhotoAlbum *)it->data;
+ debug() << " found album: " << ipodAlbum->name << endl;
+ last = new IpodAlbumItem( m_ipodAlbumList, last, ipodAlbum );
+ last->setPixmap( 0, KGlobal::iconLoader()->loadIcon( "folder", KIcon::Toolbar, KIcon::SizeSmall ) );
+ getIpodAlbumPhotos( last, ipodAlbum );
+ }
+}
+
+void
+UploadDialog::getIpodAlbumPhotos( IpodAlbumItem *item, Itdb_PhotoAlbum *album )
+{
+ if( !item || !album || !m_itdb )
+ return;
+
+ IpodPhotoItem *last = 0;
+ for( GList *it = album->members; it; it = it->next )
+ {
+ Itdb_Artwork *photo = (Itdb_Artwork*)it->data;
+ gint photo_id = photo->id;
+ last = new IpodPhotoItem( item, last, photo );
+ last->setText( 0, QString::number( photo_id ) );
+ last->setPixmap( 0, KGlobal::iconLoader()->loadIcon( "image", KIcon::Toolbar, KIcon::SizeSmall ) );
+ }
+}
+
+void
+UploadDialog::reloadIpodAlbum( IpodAlbumItem *item, Itdb_PhotoAlbum *album )
+{
+ if( !item ) return;
+
+ while( item->firstChild() )
+ delete item->firstChild(); // clear the items, so we can reload them again
+
+ Itdb_PhotoAlbum *ipodAlbum = 0;
+ for( GList *it = m_itdb->photoalbums; it; it = it->next )
+ {
+ ipodAlbum = (Itdb_PhotoAlbum *)it->data;
+ if( strcmp( ipodAlbum->name, album->name ) == 0 )
+ break; // we found the album
+ }
+
+ dynamic_cast<IpodAlbumItem*>(item)->setPhotoAlbum( ipodAlbum );
+
+ getIpodAlbumPhotos( item, ipodAlbum );
+}
+
+void
+UploadDialog::enableButtons()
+{
+ // enable the start button only if there are albums to transfer to, items to transfer
+ // and a database to add to!
+ const bool transfer = m_uploadList->childCount() > 0 && // we have items to transfer
+ m_ipodAlbumList->childCount() > 0 && // the ipod has albums
+ !m_transferring && // we aren't transferring
+ m_ipodAlbumList->selectedItem() && // selected a destination album
+ m_itdb;
+
+ m_transferImagesButton->setEnabled( transfer );
+
+ enableButton( KDialogBase::Close, !m_transferring );
+
+ const QListViewItem *ipodSelection = m_ipodAlbumList->selectedItem();
+ const bool isMasterLibrary = ( ipodSelection == m_ipodAlbumList->firstChild() );
+
+ m_removeAlbumButton->setEnabled( ipodSelection && !isMasterLibrary );
+ m_renameAlbumButton->setEnabled( ipodSelection && !isMasterLibrary && ipodSelection->depth() == 0 );
+}
+
+void
+UploadDialog::startTransfer()
+{
+ if( !m_itdb || !m_uploadList->childCount() )
+ return;
+
+ QListViewItem *selected = m_ipodAlbumList->selectedItem();
+ if( !selected || selected->depth() != 0 /*not album*/)
+ return;
+
+ m_transferring = true;
+
+#define selected static_cast<IpodAlbumItem*>( selected )
+
+ Itdb_PhotoAlbum *album = selected->photoAlbum();
+
+ enableButton( KDialogBase::User1, false );
+ enableButton( KDialogBase::Close, false );
+
+ GError *err = 0;
+
+ while( QListViewItem *item = m_uploadList->firstChild() )
+ {
+#define item static_cast<ImageListItem*>(item)
+ debug() << "Uploading " << item->pathSrc()
+ << " to ipod album " << album->name << endl;
+ Itdb_Artwork *art = itdb_photodb_add_photo( m_itdb, QFile::encodeName( item->pathSrc() ), 0, 0, &err );
+ if( !art )
+ {
+ if( err )
+ {
+ debug() << "Error adding photo " << item->pathSrc() << " to database:"
+ << err->message << endl;
+ err = 0;
+ }
+ }
+ else
+ itdb_photodb_photoalbum_add_photo( m_itdb, album, art, 0 );
+
+ delete item;
+#undef item
+ }
+
+ itdb_photodb_write( m_itdb, &err );
+ if( err ) debug() << "Failed with error: " << err->message << endl;
+
+ reloadIpodAlbum( selected, album );
+
+ IpodAlbumItem *library = static_cast<IpodAlbumItem*>( m_ipodAlbumList->firstChild() );
+ reloadIpodAlbum( library, library->photoAlbum() );
+
+ m_transferring = false;
+
+ enableButtons();
+#undef selected
+}
+
+void
+UploadDialog::ipodItemSelected( QListViewItem *item )
+{
+ m_ipodPreview->clear();
+
+ if( m_ipodAlbumList->currentItem() )
+ m_ipodAlbumList->currentItem()->setSelected( true );
+
+ enableButtons();
+
+#define item dynamic_cast<IpodPhotoItem*>(item)
+ if( !item )
+ return;
+
+ Itdb_Artwork *artwork = item->artwork();
+ Itdb_Thumb *thumb = itdb_artwork_get_thumb_by_type( artwork, ITDB_THUMB_PHOTO_SMALL );
+
+ if( !thumb )
+ {
+ debug() << "no thumb was found" << endl;
+ return;
+ }
+#undef item
+
+// GdkPixbuf *buf = itdb_thumb_get_gdk_pixbuf( m_itdb->device, thumb );
+// int size = 0;
+// QImage *image = buf->convertToImage();
+// debug() << "image size: " << image->size() << endl;
+//
+// QPixmap pix;
+// pix.convertFromImage( image );
+// m_ipodPreview->setPixmap( pix );
+}
+
+void
+UploadDialog::imageSelected( QListViewItem *item )
+{
+ if( !item || m_uploadList->childCount() == 0 || m_transferring )
+ {
+ m_imagePreview->clear();
+ return;
+ }
+
+ ImageListItem *pitem = static_cast<ImageListItem*>( item );
+ if ( !pitem ) return;
+
+ m_imagePreview->clear();
+
+ QString IdemIndexed = "file:" + pitem->pathSrc();
+
+ KURL url( IdemIndexed );
+
+ KIO::PreviewJob* m_thumbJob = KIO::filePreview( url, m_imagePreview->height() );
+
+ connect( m_thumbJob, SIGNAL( gotPreview(const KFileItem*, const QPixmap&) ),
+ this, SLOT( gotImagePreview(const KFileItem*, const QPixmap&) ) );
+}
+
+void
+UploadDialog::gotImagePreview( const KFileItem* url, const QPixmap &pixmap )
+{
+#if KIPI_PLUGIN
+ QPixmap pix( pixmap );
+
+ // Rotate the thumbnail compared to the angle the host application dictate
+ KIPI::ImageInfo info = m_interface->info( url->url() );
+ if ( info.angle() != 0 )
+ {
+ QImage img = pix.convertToImage();
+ QWMatrix matrix;
+
+ matrix.rotate( info.angle() );
+ img = img.xForm( matrix );
+ pix.convertFromImage( img );
+ }
+
+ m_imagePreview->setPixmap(pix);
+#else
+ Q_UNUSED( url );
+ m_imagePreview->setPixmap( pixmap );
+#endif
+}
+
+void
+UploadDialog::imagesFilesButtonAdd()
+{
+ QStringList fileList;
+ KURL::List urls;
+#if KIPI_PLUGIN
+ urls = KIPI::ImageDialog::getImageURLs( this, m_interface );
+#else
+ const QString filter = QString( "*.jpg *.jpeg *.jpe *.tiff *.gif *.png *.bmp|" + i18n("Image files") );
+ KFileDialog dlg( QString::null, filter, this, "addImagesDlg", true );
+ dlg.setCaption( i18n("Add Images") );
+ dlg.setMode( KFile::Files | KFile::Directory );
+ dlg.exec();
+ urls = dlg.selectedURLs();
+#endif
+ for( KURL::List::Iterator it = urls.begin() ; it != urls.end() ; ++it )
+ fileList << (*it).path();
+
+ if ( urls.isEmpty() ) return;
+
+ addDropItems( fileList );
+}
+
+void
+UploadDialog::imagesFilesButtonRem()
+{
+ QPtrList<QListViewItem> selected = m_uploadList->selectedItems();
+
+ for( QListViewItem *it = selected.first(); it; it = selected.next() )
+ delete it;
+
+ enableButton( KDialogBase::User1, m_uploadList->childCount() > 0 );
+}
+
+void
+UploadDialog::createIpodAlbum()
+{
+ QString helper;
+ #if KIPI_PLUGIN
+ KIPI::ImageCollection album = m_interface->currentAlbum();
+ if( album.isValid() )
+ helper = album.name();
+ #endif
+
+ bool ok = false;
+ QString newAlbum = KInputDialog::getText( i18n("New iPod Photo Album"),
+ i18n("Create a new album:"),
+ helper, &ok, this );
+ if( ok )
+ {
+ debug() << "creating album " << newAlbum << endl;
+
+ IpodAlbumItem *last = static_cast<IpodAlbumItem*>(m_ipodAlbumList->lastItem()); // FIXME?? O(n)
+
+ Itdb_PhotoAlbum *photoAlbum = itdb_photodb_photoalbum_create( m_itdb, QFile::encodeName( newAlbum ), -1/*end*/ );
+ // add the new album to the list view
+ IpodAlbumItem *i = new IpodAlbumItem( m_ipodAlbumList, last, photoAlbum );
+ i->setPixmap( 0, KGlobal::iconLoader()->loadIcon( "folder", KIcon::Toolbar, KIcon::SizeSmall ) );
+ m_ipodAlbumList->clearSelection();
+ m_ipodAlbumList->setSelected( i, true );
+
+ // commit the changes to the iPod
+ GError *err = 0;
+ itdb_photodb_write( m_itdb, &err );
+ }
+}
+
+void
+UploadDialog::renameIpodAlbum()
+{
+ IpodAlbumItem *selected = dynamic_cast<IpodAlbumItem*>(m_ipodAlbumList->selectedItem());
+
+ // only allow renaming of album items
+ if( !selected || selected->depth() != 0 ) return;
+
+ bool ok = false;
+ QString newName = KInputDialog::getText( i18n("Rename iPod Photo Album"),
+ i18n("New album title:"),
+ selected->text(0), &ok, this );
+ if( ok )
+ {
+ // change the name on the ipod, and rename the listviewitem
+ selected->setName( newName );
+ // commit changes to the iPod
+ GError *err = 0;
+ itdb_photodb_write( m_itdb, &err );
+ }
+}
+
+bool UploadDialog::deleteIpodPhoto( IpodPhotoItem *photo )
+{
+ if( !photo )
+ return false;
+
+ IpodAlbumItem *album = static_cast<IpodAlbumItem *>( photo->parent() );
+
+ if( !album )
+ return false;
+
+ Itdb_Artwork *artwork = photo->artwork();
+
+ if( !artwork )
+ {
+ debug() << "Could not find photo artwork with id: " << photo->text(0) << endl;
+ return false;
+ }
+
+ Itdb_PhotoAlbum *photo_album = album->photoAlbum();
+ itdb_photodb_remove_photo( m_itdb, photo_album, artwork );
+
+ // if we remove from the library, remove from all sub albums too
+ if( photo_album->album_type == 0x01 ) // master album
+ {
+ for( QListViewItem *albumIt = m_ipodAlbumList->firstChild()->nextSibling(); //skip library
+ albumIt; albumIt = albumIt->nextSibling() )
+ {
+ for( QListViewItem *photoIt = albumIt->firstChild();
+ photoIt; photoIt = photoIt->nextSibling() )
+ {
+ if( photoIt->text(0) == photo->text(0) )
+ {
+ debug() << "removing reference to photo from album " << albumIt->text(0) << endl;
+ delete photoIt;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool UploadDialog::deleteIpodAlbum( IpodAlbumItem *album )
+{
+ debug() << "deleting album: " << album->name() << ", and removing all photos" << endl;
+ itdb_photodb_photoalbum_remove( m_itdb, album->photoAlbum(), true/*remove photos*/);
+
+ return true;
+}
+
+void
+UploadDialog::deleteIpodAlbum()
+{
+ QListViewItem *selected = m_ipodAlbumList->selectedItem();
+ if( !selected ) return;
+
+ bool result = false;
+ switch( selected->depth() )
+ {
+ case 0: //album
+ result = deleteIpodAlbum( dynamic_cast<IpodAlbumItem*>( selected ) );
+ break;
+
+ case 1: //image
+ result = deleteIpodPhoto( dynamic_cast<IpodPhotoItem*>( selected ) );
+ break;
+ }
+
+ if( result ) //selected item may have been deleted by deleteIpodPhoto
+ delete selected;
+
+ GError *err = 0;
+ itdb_photodb_write( m_itdb, &err );
+}
+
+void
+UploadDialog::addDropItems( QStringList filesPath )
+{
+ if( filesPath.isEmpty() ) return;
+
+ for( QStringList::Iterator it = filesPath.begin() ; it != filesPath.end() ; ++it )
+ {
+ QString currentDropFile = *it;
+
+ // Check if the new item already exist in the list.
+
+ bool itemExists = false;
+
+ QListViewItemIterator it2( m_uploadList );
+
+ while( it2.current() )
+ {
+ ImageListItem *item = static_cast<ImageListItem*>(it2.current());
+
+ if( item->pathSrc() == currentDropFile.section('/', 0, -1) )
+ {
+ itemExists = true;
+ break;
+ }
+ ++it2;
+ }
+
+ if( !itemExists )
+ addUrlToList( currentDropFile );
+ }
+
+ enableButton( KDialogBase::User1, m_uploadList->childCount() > 0 );
+}
+
+void
+UploadDialog::addUrlToList( QString file )
+{
+ QFileInfo *fi = new QFileInfo( file );
+
+ new ImageListItem( m_uploadList, file.section('/', 0, -1), fi->fileName() );
+
+ delete fi;
+}
+
+
+bool
+UploadDialog::openDevice()
+{
+ if( m_itdb )
+ {
+ debug() << "ipod at " << m_mountPoint << " already opened" << endl;
+ return false;
+ }
+
+ // try to find a mounted ipod
+ bool ipodFound = false;
+
+ KMountPoint::List currentmountpoints = KMountPoint::currentMountPoints();
+ for( KMountPoint::List::Iterator mountiter = currentmountpoints.begin();
+ mountiter != currentmountpoints.end();
+ ++mountiter )
+ {
+ QString devicenode = (*mountiter)->mountedFrom();
+ QString mountpoint = (*mountiter)->mountPoint();
+
+ if( !m_mountPoint.isEmpty() &&
+ mountpoint != m_mountPoint )
+ continue;
+
+ if( mountpoint.startsWith( "/proc" ) ||
+ mountpoint.startsWith( "/sys" ) ||
+ mountpoint.startsWith( "/dev" ) ||
+ mountpoint.startsWith( "/boot" ) )
+ continue;
+
+ if( !m_deviceNode.isEmpty() &&
+ devicenode != m_deviceNode )
+ continue;
+
+ /// Detecting whether an iPod exists.
+ QString path = QString( itdb_get_control_dir( QFile::encodeName( mountpoint ) ) );
+ QDir d( path );
+
+ if( path.isEmpty() || !d.exists() )
+ continue;
+
+ if( m_mountPoint.isEmpty() )
+ m_mountPoint = mountpoint;
+
+ /// Here, we have found an ipod, but we are not sure if the photo db exists.
+ /// Try and parse it to determine whether we have initialised the iPod.
+ ipodFound = true;
+ GError *err = 0;
+ m_itdb = itdb_photodb_parse( QFile::encodeName( mountpoint ), &err );
+ if( err )
+ {
+ g_error_free( err );
+ if( m_itdb )
+ {
+ itdb_photodb_free( m_itdb );
+ m_itdb = 0;
+ }
+ }
+ break;
+ }
+
+ if( !ipodFound )
+ {
+ debug() << "no mounted ipod found" << endl;
+ if( m_itdb )
+ {
+ itdb_photodb_free( m_itdb );
+ m_itdb = 0;
+ }
+ return false;
+ }
+
+ debug() << "ipod found mounted at " << m_mountPoint << endl;
+
+ /// No photodb was able to be parsed, so offer to initialise the ipod for the user.
+ if( !m_itdb )
+ {
+ debug() << "could not find iTunesDB on device mounted at " << m_mountPoint << endl;
+
+ QString msg = i18n( "An iPod photo database could not be found on device mounted at %1. "
+ "Should I try to initialize your iPod photo database?" ).arg( m_mountPoint );
+
+ if( KMessageBox::warningContinueCancel( this, msg, i18n( "Initialize iPod Photo Database?" ),
+ KGuiItem(i18n("&Initialize"), "new") ) == KMessageBox::Continue )
+ {
+
+ m_itdb = itdb_photodb_create( QFile::encodeName( m_mountPoint ) );
+ itdb_device_set_mountpoint( m_itdb->device, QFile::encodeName( m_mountPoint ) );
+
+ if( !m_itdb )
+ {
+ debug() << "Could not initialise photodb..." << endl;
+ return false;
+ }
+
+ GError *err = 0;
+ itdb_photodb_write( m_itdb, &err );
+ }
+ else
+ return false;
+ }
+
+ return true;
+}
+
+Itdb_Artwork *
+UploadDialog::photoFromId( const uint id )
+{
+ if( !m_itdb )
+ return 0;
+
+ for( GList *it = m_itdb->photos; it; it=it->next )
+ {
+ Itdb_Artwork *photo = (Itdb_Artwork*)it->data;
+ if( !photo )
+ return 0;
+
+ if( photo->id == id )
+ return photo;
+ }
+ return 0;
+}
+
+QString UploadDialog::ipodModel() const
+{
+ if( m_ipodInfo )
+ return QString( itdb_info_get_ipod_model_name_string( m_ipodInfo->ipod_model ) );
+
+ return QString::null;
+}
+
+
+void UploadDialog::refreshDevices()
+{
+ debug() << "refreshing ipod devices" << endl;
+
+ if( !m_ipodHeader )
+ return;
+
+ m_ipodHeader->disconnect();
+
+ if( !openDevice() )
+ {
+ m_ipodHeader->setViewType( IpodHeader::NoIpod );
+ connect( m_ipodHeader, SIGNAL( refreshDevices() ), SLOT( refreshDevices() ) );
+ }
+ else //device opened! hooray!
+ {
+ m_ipodInfo = const_cast<Itdb_IpodInfo*>( itdb_device_get_ipod_info( m_itdb->device ) );
+ const QString model = ipodModel();
+
+ if( !m_ipodInfo || model.isEmpty() || model == "Invalid" )
+ {
+ debug() << "the ipod model must be set before photos can be added" << endl;
+ m_ipodHeader->setViewType( IpodHeader::IncompatibleIpod );
+ connect( m_ipodHeader, SIGNAL( updateSysInfo() ), SLOT( updateSysInfo() ) );
+ return;
+ }
+ else
+ {
+ m_ipodHeader->setViewType( IpodHeader::ValidIpod );
+ }
+ }
+
+ if( m_ipodAlbumList )
+ getIpodAlbums();
+
+ m_destinationBox->setEnabled( m_itdb );
+ m_urlListBox->setEnabled( m_itdb );
+}
+
+void UploadDialog::updateSysInfo()
+{
+ debug() << "updateSysInfo()" << endl;
+}
+
diff --git a/kipi-plugins/ipodexport/ipodexportdialog.h b/kipi-plugins/ipodexport/ipodexportdialog.h
new file mode 100644
index 0000000..6cdd861
--- /dev/null
+++ b/kipi-plugins/ipodexport/ipodexportdialog.h
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.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. *
+ * *
+ ***************************************************************************/
+
+#ifndef IPOD_EXPORTDIALOG_H
+#define IPOD_EXPORTDIALOG_H
+
+extern "C" {
+#include <gpod/itdb.h>
+}
+
+#define KIPI_PLUGIN 1
+
+#include <kdialogbase.h>
+
+#if KIPI_PLUGIN
+#include <libkipi/interface.h>
+#endif
+
+class QCheckBox;
+class QHGroupBox;
+class QLabel;
+class QPushButton;
+class KComboBox;
+class KFileItem;
+class KLineEdit;
+class KListView;
+class KListViewItem;
+class KURL;
+
+namespace IpodExport
+{
+
+class ImageList;
+class IpodAlbumItem;
+class IpodPhotoItem;
+class IpodHeader;
+
+class UploadDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ UploadDialog(
+ #if KIPI_PLUGIN
+ KIPI::Interface* interface,
+ #endif
+ QString caption, QWidget *parent=0 );
+
+ ~UploadDialog()
+ {
+ if( m_itdb )
+ itdb_photodb_free( m_itdb );
+ }
+
+ static UploadDialog *instance() { return s_instance; }
+
+ QString ipodModel() const;
+ QString mountPoint() { return m_mountPoint; }
+ QString deviceNode() { return m_deviceNode; }
+
+ private slots:
+ void startTransfer();
+
+ void addDropItems( QStringList filesPath );
+
+ void imageSelected( QListViewItem *item );
+ void gotImagePreview( const KFileItem* , const QPixmap &pixmap );
+
+ void ipodItemSelected( QListViewItem *item );
+ void ipodShowContextMenu( QListViewItem * ) { }
+
+ void imagesFilesButtonAdd();
+ void imagesFilesButtonRem();
+
+ void createIpodAlbum();
+ void deleteIpodAlbum();
+ void renameIpodAlbum();
+
+ void refreshDevices();
+ void updateSysInfo();
+
+ private:
+ void addUrlToList( QString file );
+ bool deleteIpodAlbum( IpodAlbumItem *album );
+ bool deleteIpodPhoto( IpodPhotoItem *photo );
+ void enableButtons();
+ void getIpodAlbums();
+ void getIpodAlbumPhotos( IpodAlbumItem *item, Itdb_PhotoAlbum *album );
+ Itdb_Artwork *photoFromId( const uint id );
+ void reloadIpodAlbum( IpodAlbumItem *item, Itdb_PhotoAlbum *album );
+
+ bool openDevice(); // connect to the ipod
+
+#if KIPI_PLUGIN
+ KIPI::Interface *m_interface;
+#endif
+ Itdb_PhotoDB *m_itdb;
+ Itdb_IpodInfo *m_ipodInfo;
+ IpodHeader *m_ipodHeader;
+ bool m_transferring;
+
+ QListViewItem *m_destinationAlbum;
+
+ QPushButton *m_createAlbumButton;
+ QPushButton *m_removeAlbumButton;
+ QPushButton *m_renameAlbumButton;
+ QPushButton *m_addImagesButton;
+ QPushButton *m_remImagesButton;
+ QPushButton *m_transferImagesButton;
+ ImageList *m_uploadList;
+ KListView *m_ipodAlbumList;
+ QLabel *m_imagePreview;
+ QLabel *m_ipodPreview;
+
+ QHGroupBox *m_destinationBox;
+ QHGroupBox *m_urlListBox;
+
+ QString m_mountPoint;
+ QString m_deviceNode;
+
+ static UploadDialog *s_instance;
+};
+
+}
+
+#endif // IPOD_EXPORTDIALOG_H
diff --git a/kipi-plugins/ipodexport/ipodheader.cpp b/kipi-plugins/ipodexport/ipodheader.cpp
new file mode 100644
index 0000000..24b2d94
--- /dev/null
+++ b/kipi-plugins/ipodexport/ipodheader.cpp
@@ -0,0 +1,125 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.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. *
+ * *
+ ***************************************************************************/
+
+#include "ipodheader.h"
+#include "ipodexportdialog.h"
+
+#include "klocale.h"
+#include "kpushbutton.h"
+
+#include "qlabel.h"
+#include "qlayout.h"
+
+using namespace IpodExport;
+
+IpodHeader::IpodHeader( QWidget *parent, const char *name, WFlags f )
+ : QFrame( parent, name, f )
+{
+ QVBoxLayout *layout = new QVBoxLayout( this, 10/*margin*/, 5/*spacing*/ );
+
+ setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
+
+ m_messageLabel = new QLabel( QString::null, this );
+ m_messageLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
+
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
+ m_button = new KPushButton( this );
+ m_button->hide();
+
+ buttonLayout->addStretch( 1 );
+ buttonLayout->addWidget( m_button );
+ buttonLayout->addStretch( 1 );
+
+ layout->addWidget( m_messageLabel );
+ layout->addLayout( buttonLayout );
+}
+
+void IpodHeader::setViewType( ViewType view )
+{
+ m_viewType = view;
+
+ switch( view )
+ {
+ case NoIpod:
+ setNoIpod();
+ break;
+
+ case IncompatibleIpod:
+ setIncompatibleIpod();
+ break;
+
+ case ValidIpod:
+ setValidIpod();
+ break;
+
+ default:
+ break;
+ }
+}
+
+void IpodHeader::setNoIpod()
+{
+ m_messageLabel->setText( i18n("<p align=\"center\"><b>No iPod was detected</b></p>" ) );
+
+ setPaletteBackgroundColor( QColor(147,18,18) );
+ m_messageLabel->setPaletteBackgroundColor( QColor(147,18,18) );
+ m_messageLabel->setPaletteForegroundColor( Qt::white );
+
+ m_button->setText( i18n( "Refresh" ) );
+ m_button->show();
+
+ m_button->disconnect();
+ connect( m_button, SIGNAL( clicked() ), SIGNAL( refreshDevices() ) );
+}
+
+void IpodHeader::setIncompatibleIpod()
+{
+ const QString modelType = UploadDialog::instance()->ipodModel();
+
+ m_messageLabel->setText( i18n("<p align=\"center\"><b>Your iPod (%1) does not seem to support artwork.</b></p>" ).arg( modelType ) );
+
+ setPaletteBackgroundColor( QColor(225,150,0) );
+ m_messageLabel->setPaletteBackgroundColor( QColor(225,150,0) );
+ m_messageLabel->setPaletteForegroundColor( Qt::white );
+
+ m_button->setText( i18n( "Set iPod Model" ) );
+// m_button->show();
+ m_button->hide(); // FIXME its not implemented!
+
+ m_button->disconnect();
+ connect( m_button, SIGNAL( clicked() ), SIGNAL( updateSysInfo() ) );
+}
+
+
+void IpodHeader::setValidIpod()
+{
+ const QString modelType = UploadDialog::instance()->ipodModel();
+ const QString mountPoint = UploadDialog::instance()->mountPoint();
+
+ if( !mountPoint.isEmpty() )
+ {
+ m_messageLabel->setText( i18n("<p align=\"center\"><b>iPod %1 detected at: %2</b></p>" )
+ .arg( modelType, mountPoint ) );
+ }
+ else
+ {
+ m_messageLabel->setText( i18n("<p align=\"center\"><b>iPod %1 detected</b></p>" )
+ .arg( modelType ) );
+ }
+ setPaletteBackgroundColor( QColor(0,98,0) );
+ m_messageLabel->setPaletteBackgroundColor( QColor(0,98,0) );
+ m_messageLabel->setPaletteForegroundColor( Qt::white );
+
+ m_button->hide();
+}
+
diff --git a/kipi-plugins/ipodexport/ipodheader.h b/kipi-plugins/ipodexport/ipodheader.h
new file mode 100644
index 0000000..7678682
--- /dev/null
+++ b/kipi-plugins/ipodexport/ipodheader.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.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. *
+ * *
+ ***************************************************************************/
+
+#ifndef IPOD_HEADER_H
+#define IPOD_HEADER_H
+
+#include <qframe.h> //baseclass
+
+class QLabel;
+class KPushButton;
+
+namespace IpodExport
+{
+
+class IpodHeader : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ IpodHeader( QWidget *parent=0, const char *name=0, WFlags f=0 );
+ ~IpodHeader() { }
+
+ enum ViewType { NoIpod, IncompatibleIpod, ValidIpod };
+
+ void setViewType( ViewType view );
+ ViewType viewType() const { return m_viewType; }
+
+ signals:
+ void refreshDevices();
+ void updateSysInfo();
+
+ private:
+ void setNoIpod();
+ void setIncompatibleIpod();
+ void setValidIpod();
+
+ ViewType m_viewType;
+
+ KPushButton *m_button;
+ QLabel *m_messageLabel;
+
+};
+
+}
+
+#endif /* IPOD_HEADER_H */
diff --git a/kipi-plugins/ipodexport/ipodlistitem.cpp b/kipi-plugins/ipodexport/ipodlistitem.cpp
new file mode 100644
index 0000000..6c6d950
--- /dev/null
+++ b/kipi-plugins/ipodexport/ipodlistitem.cpp
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.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. *
+ * *
+ ***************************************************************************/
+
+
+#include "ipodlistitem.h"
+
+#include <klocale.h>
+
+using namespace IpodExport;
+
+////////////////////////////////////////////
+/// Class IpodAlbumItem
+////////////////////////////////////////////
+
+IpodAlbumItem::IpodAlbumItem( QListView *parent, QListViewItem *after, Itdb_PhotoAlbum *pa )
+ : KListViewItem( parent, after )
+ , m_photoAlbum( pa )
+{
+ // don't use setName, as it writes to the ipod
+ m_name = pa->name;
+ if( m_name.isEmpty() )
+ m_name = i18n( "Unnamed" );
+ setText( 0, m_name );
+}
+
+void IpodAlbumItem::setPhotoAlbum( Itdb_PhotoAlbum *pa )
+{
+ m_photoAlbum = pa;
+}
+
+void IpodAlbumItem::setName( const QString & name )
+{
+ if( name == m_name )
+ return;
+
+ if( m_photoAlbum )
+ strcpy( m_photoAlbum->name, name.utf8() );
+
+ m_name = name;
+ setText( 0, m_name );
+}
+
+
+////////////////////////////////////////////
+/// Class IpodPhotoItem
+////////////////////////////////////////////
+
+IpodPhotoItem::IpodPhotoItem( IpodAlbumItem *parent, IpodPhotoItem *after,
+ Itdb_Artwork *art )
+ : KListViewItem( parent, after )
+ , m_artwork( art )
+{
+}
+
+void IpodPhotoItem::setArtwork( Itdb_Artwork *art )
+{
+ m_artwork = art;
+}
+
+
diff --git a/kipi-plugins/ipodexport/ipodlistitem.h b/kipi-plugins/ipodexport/ipodlistitem.h
new file mode 100644
index 0000000..9684a63
--- /dev/null
+++ b/kipi-plugins/ipodexport/ipodlistitem.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.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. *
+ * *
+ ***************************************************************************/
+
+#ifndef IPODLISTITEM_H
+#define IPODLISTITEM_H
+
+extern "C" {
+#include <gpod/itdb.h>
+}
+
+#include <klistview.h>
+
+namespace IpodExport
+{
+
+ class IpodAlbumItem : public KListViewItem
+ {
+ public:
+ IpodAlbumItem( QListView *parent, QListViewItem *after, Itdb_PhotoAlbum *pa );
+
+ QString name() const { return m_name; }
+ Itdb_PhotoAlbum *photoAlbum() const { return m_photoAlbum; }
+
+ void setPhotoAlbum( Itdb_PhotoAlbum *pa );
+ void setName( const QString & name );
+
+ private:
+ QString m_name;
+ Itdb_PhotoAlbum *m_photoAlbum;
+ };
+
+ class IpodPhotoItem : public KListViewItem
+ {
+ public:
+ IpodPhotoItem( IpodAlbumItem *parent, IpodPhotoItem *after, Itdb_Artwork *art );
+
+ Itdb_Artwork *artwork() const { return m_artwork; }
+ void setArtwork( Itdb_Artwork *art );
+
+ private:
+ Itdb_Artwork *m_artwork;
+ };
+
+}
+
+#endif // IPODLISTITEM_H
diff --git a/kipi-plugins/ipodexport/kipiplugin_ipodexport.desktop b/kipi-plugins/ipodexport/kipiplugin_ipodexport.desktop
new file mode 100644
index 0000000..7c45bc1
--- /dev/null
+++ b/kipi-plugins/ipodexport/kipiplugin_ipodexport.desktop
@@ -0,0 +1,45 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=iPodExport
+Name[ca]=Exportador a iPod
+Name[da]=Eksport til iPod
+Name[el]=Εξαγωγή iPod
+Name[et]=iPodi eksport
+Name[fi]=iPod-vienti
+Name[it]=Esportazione a iPod
+Name[nds]=iPod-Exporteren
+Name[pa]=iPod ਨਿਰਯਾਤ
+Name[pl]=Eksport do iPoda
+Name[pt]=Exportação para o iPod
+Name[sr]=iPod извоз
+Name[sr@Latn]=iPod izvoz
+Name[sv]=Export till iPod
+Name[xx]=xxiPodExportxx
+Name[zh_CN]=iPod 导出
+Comment=KIPI iPod Export Plugin
+Comment[br]=Lugent ezporzh iPod evit KIPI
+Comment[ca]=Connector del KIPI d'exportació a l'iPod
+Comment[da]=KIPI-plugin for eksport til iPod
+Comment[de]=KIPI iPod-Exportmodul
+Comment[el]=Πρόσθετο εξαγωγής iPod του KIPI
+Comment[es]=Complemento de KIPI para exportación a iPod
+Comment[et]=KIPI iPodi ekspordiplugin
+Comment[fi]=Kipi-liitännäinen iPod-vientiä varten
+Comment[fr]=Un module externe KIPI pour exporter les images avec un Ipod
+Comment[it]=Plugin per l'esportazione remota a iPod di KIPI
+Comment[ja]=Kipi iPod エクスポートプラグイン
+Comment[nds]=KIPI-Moduul för't Exporteren na Dien iPod
+Comment[nl]=KIPI-plugin voor exporteren naar iPod
+Comment[pa]=KIPI iPod ਨਿਰਯਾਤ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Eksport do iPoda
+Comment[pt]='Plugin' do KIPI de Exportação para o iPod
+Comment[pt_BR]=Plugin de Exportação para iPod do KIPI
+Comment[sr]=KIPI прикључак за извоз у iPod
+Comment[sr@Latn]=KIPI priključak za izvoz u iPod
+Comment[sv]=KIPI-insticksprogram för export till iPod
+Comment[xx]=xxKIPI iPod Export Pluginxx
+Comment[zh_CN]=KIPI iPod 导出插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_ipodexport
+author=Seb Ruiz, me@sebruiz.net
diff --git a/kipi-plugins/ipodexport/plugin_ipodexport.cpp b/kipi-plugins/ipodexport/plugin_ipodexport.cpp
new file mode 100644
index 0000000..4f1f2e9
--- /dev/null
+++ b/kipi-plugins/ipodexport/plugin_ipodexport.cpp
@@ -0,0 +1,75 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.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. *
+ * *
+ ***************************************************************************/
+
+extern "C" {
+#include <glib-object.h> //g_type_init
+}
+
+#include "ipodexportdialog.h"
+#include "plugin_ipodexport.h"
+
+#include <libkipi/imagecollection.h>
+
+
+#include <kaction.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+
+
+#define debug() kdDebug( 51000 )
+
+typedef KGenericFactory<Plugin_iPodExport> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_ipodexport, Factory("kipiplugin_ipodexport"));
+
+Plugin_iPodExport::Plugin_iPodExport( QObject *parent, const char*, const QStringList& )
+ : KIPI::Plugin( Factory::instance(), parent, "iPodExport")
+{
+ kdDebug( 51001 ) << "Plugin_iPodExport plugin loaded" << endl;
+
+ g_type_init();
+}
+
+void Plugin_iPodExport::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ // this is our action shown in the menubar/toolbar of the mainwindow
+ m_actionImageUpload = new KAction( i18n( "Export to iPod..." ), "ipod_unmount", 0, this,
+ SLOT( slotImageUpload() ), actionCollection(), "connectipod");
+
+ addAction( m_actionImageUpload );
+
+ m_interface = dynamic_cast< KIPI::Interface* >( parent() );
+}
+
+KIPI::Category Plugin_iPodExport::category( KAction* action ) const
+{
+ if ( action == m_actionImageUpload )
+ return KIPI::EXPORTPLUGIN;
+
+ return KIPI::IMAGESPLUGIN; // no warning from compiler, please
+}
+
+
+void Plugin_iPodExport::slotImageUpload()
+{
+ IpodExport::UploadDialog *dlg = new IpodExport::UploadDialog( m_interface, i18n("iPod Export"),
+ kapp->activeWindow() );
+ dlg->setMinimumWidth( 460 );
+ dlg->show();
+}
diff --git a/kipi-plugins/ipodexport/plugin_ipodexport.h b/kipi-plugins/ipodexport/plugin_ipodexport.h
new file mode 100644
index 0000000..f72b108
--- /dev/null
+++ b/kipi-plugins/ipodexport/plugin_ipodexport.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * copyright : (C) 2006 Seb Ruiz <me@sebruiz.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. *
+ * *
+ ***************************************************************************/
+
+#ifndef PLUGIN_IPODEXPORT_H
+#define PLUGIN_IPODEXPORT_H
+
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+class Plugin_iPodExport : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+ Plugin_iPodExport( QObject *parent, const char* name, const QStringList &args);
+ ~Plugin_iPodExport() { }
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+private slots:
+ void slotImageUpload();
+
+private:
+ KAction *m_actionImageUpload;
+ KIPI::Interface *m_interface;
+};
+
+#endif //PLUGIN_IPODEXPORT_H
diff --git a/kipi-plugins/jpeglossless/Makefile.am b/kipi-plugins/jpeglossless/Makefile.am
new file mode 100644
index 0000000..a6ac81a
--- /dev/null
+++ b/kipi-plugins/jpeglossless/Makefile.am
@@ -0,0 +1,29 @@
+SUBDIRS = pics
+METASOURCES = AUTO
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKEXIV2_CFLAGS) $(LIBKDCRAW_CFLAGS) $(LIBKIPI_CFLAGS) $(all_includes)
+
+# --enable-final triggers: http://bugs.kde.org/show_bug.cgi?id=126326
+# digikam: camera download: auto-rotated images loose EXIF info ...
+# So make sure nofinal is always used here!
+KDE_OPTIONS = nofinal
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_jpeglossless.la
+
+kipiplugin_jpeglossless_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+
+kipiplugin_jpeglossless_la_SOURCES = plugin_jpeglossless.cpp jpegtransform.cpp \
+ actionthread.cpp utils.cpp transupp.cpp \
+ imagerotate.cpp convert2grayscale.cpp imageflip.cpp
+
+kipiplugin_jpeglossless_la_LIBADD = -ljpeg $(LIBKIPI_LIBS) $(LIBKEXIV2_LIBS) $(LIB_KDEUI) \
+ $(LIBKDCRAW_LIBS) $(LIB_KDECORE) $(LIB_QT)
+
+
+kipiplugin_jpeglossless_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+kde_services_DATA = kipiplugin_jpeglossless.desktop
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_jpeglossless.pot
+
diff --git a/kipi-plugins/jpeglossless/actions.h b/kipi-plugins/jpeglossless/actions.h
new file mode 100644
index 0000000..bc4fc77
--- /dev/null
+++ b/kipi-plugins/jpeglossless/actions.h
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-12-05
+ * Description : JPEGLossLess plugin action descriptions
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 ACTIONS_H
+#define ACTIONS_H
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+enum Action
+{
+ Rotate = 0,
+ Flip,
+ GrayScale
+};
+
+enum RotateAction
+{
+ Rot90 = 0,
+ Rot180,
+ Rot270,
+ Rot0
+};
+
+enum FlipAction
+{
+ FlipHorizontal = 0,
+ FlipVertical = 1
+};
+
+class EventData
+{
+
+public:
+
+ EventData()
+ {
+ starting = false;
+ success = false;
+ }
+
+ bool starting;
+ bool success;
+
+ QString fileName;
+ QString errString;
+
+ Action action;
+};
+
+} // NameSpace KIPIJPEGLossLessPlugin
+
+#endif /* ACTIONS_H */
diff --git a/kipi-plugins/jpeglossless/actionthread.cpp b/kipi-plugins/jpeglossless/actionthread.cpp
new file mode 100644
index 0000000..7e85426
--- /dev/null
+++ b/kipi-plugins/jpeglossless/actionthread.cpp
@@ -0,0 +1,237 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-12-03
+ * Description : a class to manage JPEGLossLess plugin
+ * actions using threads
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * NOTE: Do not use kdDebug() in this implementation because
+ * it will be multithreaded. Use qDebug() instead.
+ * See B.K.O #133026 for details.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qapplication.h>
+#include <qdir.h>
+#include <qdeepcopy.h>
+
+// KDE includes.
+
+#include <kdebug.h>
+
+// Local includes.
+
+#include "utils.h"
+#include "imagerotate.h"
+#include "imageflip.h"
+#include "convert2grayscale.h"
+#include "actionthread.h"
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+ActionThread::ActionThread( KIPI::Interface* interface, QObject *parent)
+ : QThread(), m_parent(parent), m_interface( interface )
+{
+}
+
+ActionThread::~ActionThread()
+{
+ // cancel the thread
+ cancel();
+ // wait for the thread to finish
+ wait();
+}
+
+void ActionThread::rotate(const KURL::List& urlList, RotateAction val)
+{
+ for (KURL::List::const_iterator it = urlList.begin();
+ it != urlList.end(); ++it )
+ {
+ KIPI::ImageInfo info = m_interface->info( *it );
+
+ /*
+ Removing this code:
+ - for JPEGs, jpegtransform is using the Exiv2Iface and matrix multiplication
+ to compute the mathematically correct rotation (taking flip operations into account,
+ the code below only angles). Metadata tag is reset.
+ - For ImageMagick, no metadata is taken into account, and no metadata is changed!
+ Angle from host application still applies.
+ // Don't use the host angle in case of auto-rotation (Rot0)
+ if (val != Rot0)
+ {
+ // If the image is being displayed rotaed in the host application, then rotate that
+ // angle too.
+ int angle = (info.angle() + 360) % 360;
+
+ // When the image has been rotated on the disk we can assume that it
+ // does not need to be rotated before being displayed.
+ info.setAngle( 0 );
+
+ if ( val == Rot90 )
+ angle += 90;
+ else if ( val == Rot180 )
+ angle += 180;
+ else if ( val == Rot270 )
+ angle += 270;
+
+ angle = (angle+360) % 360;
+ if ( (90-45) <= angle && angle < (90+45) )
+ val = Rot90;
+ else if ( (180-45) <= angle && angle < (180+45) )
+ val = Rot180;
+ else if ( (270-45) <= angle && angle < (270+45) )
+ val = Rot270;
+ else
+ val = Rot0;
+ }
+ */
+
+ Task *t = new Task;
+ t->filePath = QDeepCopy<QString>((*it).path()); //deep copy
+ t->action = Rotate;
+ t->rotAction = val;
+ m_taskQueue.enqueue(t);
+ }
+}
+
+void ActionThread::flip(const KURL::List& urlList, FlipAction val)
+{
+ for (KURL::List::const_iterator it = urlList.begin();
+ it != urlList.end(); ++it )
+ {
+ KIPI::ImageInfo info = m_interface->info( *it );
+ int angle = (info.angle() + 360) % 360;
+
+ if ( ((90-45) <= angle && angle < (90+45)) || ((270-45) < angle && angle < (270+45)) )
+ {
+ // The image is rotated 90 or 270 degrees, which means that the flip operations
+ // must be switched to gain the effect the user expects.
+ // Note: this will only work if the angles is one of 90,180,270.
+ val = (FlipAction) !val;
+ }
+
+ Task *t = new Task;
+ t->filePath = QDeepCopy<QString>((*it).path()); //deep copy
+ t->action = Flip;
+ t->flipAction = val;
+ m_taskQueue.enqueue(t);
+ }
+}
+
+void ActionThread::convert2grayscale(const KURL::List& urlList)
+{
+ for (KURL::List::const_iterator it = urlList.begin();
+ it != urlList.end(); ++it )
+ {
+ Task *t = new Task;
+ t->filePath = QDeepCopy<QString>((*it).path()); //deep copy
+ t->action = GrayScale;
+ m_taskQueue.enqueue(t);
+ }
+}
+
+void ActionThread::cancel()
+{
+ m_taskQueue.flush();
+}
+
+void ActionThread::run()
+{
+ while (!m_taskQueue.isEmpty())
+ {
+ Task *t = m_taskQueue.dequeue();
+ if (!t) continue;
+
+ QString errString;
+
+ EventData *d = new EventData;
+
+ switch (t->action)
+ {
+ case Rotate :
+ {
+ d->action = Rotate;
+ d->fileName = t->filePath;
+ d->starting = true;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ bool result = true;
+ ImageRotate imageRotate;
+ result = imageRotate.rotate(t->filePath, t->rotAction, errString);
+
+ EventData *r = new EventData;
+ r->action = Rotate;
+ r->fileName = t->filePath;
+ r->success = result;
+ r->errString = errString;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, r));
+ break;
+ }
+ case Flip:
+ {
+ d->action = Flip;
+ d->fileName = t->filePath;
+ d->starting = true;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ ImageFlip imageFlip;
+ bool result = imageFlip.flip(t->filePath, t->flipAction, errString);
+
+ EventData *r = new EventData;
+ r->action = Flip;
+ r->fileName = t->filePath;
+ r->success = result;
+ r->errString = errString;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, r));
+ break;
+ }
+ case GrayScale:
+ {
+ d->action = GrayScale;
+ d->fileName = t->filePath;
+ d->starting = true;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ ImageGrayScale imageGrayScale;
+ bool result = imageGrayScale.image2GrayScale(t->filePath, errString);
+
+ EventData *r = new EventData;
+ r->action = GrayScale;
+ r->fileName = t->filePath;
+ r->success = result;
+ r->errString = errString;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, r));
+ break;
+ }
+ default:
+ {
+ qDebug("KIPIJPEGLossLessPlugin:ActionThread: "
+ "Unknown action specified");
+ delete d;
+ }
+ }
+
+ delete t;
+ }
+}
+
+} // NameSpace KIPIJPEGLossLessPlugin
diff --git a/kipi-plugins/jpeglossless/actionthread.h b/kipi-plugins/jpeglossless/actionthread.h
new file mode 100644
index 0000000..5f41751
--- /dev/null
+++ b/kipi-plugins/jpeglossless/actionthread.h
@@ -0,0 +1,94 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-12-03
+ * Description : a class to manage JPEGLossLess plugin
+ * actions using threads
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * NOTE: Do not use kdDebug() in this implementation because
+ * it will be multithreaded. Use qDebug() instead.
+ * See B.K.O #133026 for details.
+ *
+ * This program is free software; you can redistribute 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 ACTIONTHREAD_H
+#define ACTIONTHREAD_H
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qthread.h>
+#include <qstringlist.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// LibKipi includes.
+
+#include <libkipi/interface.h>
+
+// Local includes.
+
+#include "actions.h"
+#include "mtqueue.h"
+
+class QObject;
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+class ActionThread : public QThread
+{
+public:
+
+ ActionThread( KIPI::Interface* interface, QObject *parent);
+ ~ActionThread();
+
+ void rotate(const KURL::List& urlList, RotateAction val);
+ void flip(const KURL::List& urlList, FlipAction val);
+ void convert2grayscale(const KURL::List& urlList);
+ void cancel();
+
+protected:
+
+ void run();
+
+private:
+
+ struct Task_
+ {
+ QString filePath;
+ Action action;
+ RotateAction rotAction;
+ FlipAction flipAction;
+ };
+
+ typedef struct Task_ Task;
+
+ QObject *m_parent;
+
+ MTQueue<Task> m_taskQueue;
+
+ KIPI::Interface *m_interface;
+};
+
+} // NameSpace KIPIJPEGLossLessPlugin
+
+#endif /* ACTIONTHREAD_H */
diff --git a/kipi-plugins/jpeglossless/convert2grayscale.cpp b/kipi-plugins/jpeglossless/convert2grayscale.cpp
new file mode 100644
index 0000000..66cbbfa
--- /dev/null
+++ b/kipi-plugins/jpeglossless/convert2grayscale.cpp
@@ -0,0 +1,270 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-14
+ * Description : batch images grayscale conversion
+ *
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * NOTE: Do not use kdDebug() in this implementation because
+ * it will be multithreaded. Use qDebug() instead.
+ * See B.K.O #133026 for details.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+#define XMD_H
+
+// C++ includes.
+
+#include <cstdio>
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <unistd.h>
+#include <jpeglib.h>
+}
+
+// Qt includes.
+
+#include <qimage.h>
+#include <qstring.h>
+#include <qwmatrix.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+
+// KDE includes.
+
+#include <kprocess.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <ktempfile.h>
+
+// Local includes.
+
+#include "utils.h"
+#include "transupp.h"
+#include "convert2grayscale.h"
+#include "convert2grayscale.moc"
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+ImageGrayScale::ImageGrayScale()
+ : QObject()
+{
+ m_tmpFile = new KTempFile(QString(), QString("kipiplugin-grayscale"));
+ m_tmpFile->setAutoDelete(true);
+}
+
+ImageGrayScale::~ImageGrayScale()
+{
+ delete m_tmpFile;
+}
+
+bool ImageGrayScale::image2GrayScale(const QString& src, QString& err)
+{
+ QFileInfo fi(src);
+
+ if (!fi.exists() || !fi.isReadable() || !fi.isWritable())
+ {
+ err = i18n("Error in opening input file");
+ return false;
+ }
+
+ if ( !m_tmpFile->file() )
+ {
+ err = i18n("Error in opening temporary file");
+ return false;
+ }
+
+ QString tmp = m_tmpFile->name();
+
+ if (Utils::isRAW(src))
+ {
+ err = i18n("Cannot convert to gray scale RAW file");
+ return false;
+ }
+ else if (Utils::isJPEG(src))
+ {
+ if (!image2GrayScaleJPEG(src, tmp, err))
+ return false;
+ }
+ else
+ {
+ // B.K.O #123499 : using Image Magick API here instead QT API
+ // else RAW/TIFF/PNG 16 bits image are broken!
+ if (!image2GrayScaleImageMagick(src, tmp, err))
+ return false;
+
+ // We update metadata on new image.
+ Utils tools(this);
+ if (!tools.updateMetadataImageMagick(tmp, err))
+ return false;
+ }
+
+ // Move back to original file
+ if (!Utils::MoveFile(tmp, src))
+ {
+ err = i18n("Cannot update source image");
+ return false;
+ }
+
+ return true;
+}
+
+bool ImageGrayScale::image2GrayScaleJPEG(const QString& src, const QString& dest, QString& err)
+{
+ JCOPY_OPTION copyoption = JCOPYOPT_ALL;
+ jpeg_transform_info transformoption;
+
+ transformoption.transform = JXFORM_NONE;
+ transformoption.force_grayscale = true;
+ transformoption.trim = false;
+
+ struct jpeg_decompress_struct srcinfo;
+ struct jpeg_compress_struct dstinfo;
+ struct jpeg_error_mgr jsrcerr;
+ struct jpeg_error_mgr jdsterr;
+ jvirt_barray_ptr * src_coef_arrays;
+ jvirt_barray_ptr * dst_coef_arrays;
+
+ // Initialize the JPEG decompression object with default error handling
+ srcinfo.err = jpeg_std_error(&jsrcerr);
+ jpeg_create_decompress(&srcinfo);
+
+ // Initialize the JPEG compression object with default error handling
+ dstinfo.err = jpeg_std_error(&jdsterr);
+ jpeg_create_compress(&dstinfo);
+
+ FILE *input_file;
+ FILE *output_file;
+
+ input_file = fopen(QFile::encodeName(src), "rb");
+ if (!input_file)
+ {
+ qDebug("Image2GrayScale: Error in opening input file");
+ err = i18n("Error in opening input file");
+ return false;
+ }
+
+ output_file = fopen(QFile::encodeName(dest), "wb");
+ if (!output_file)
+ {
+ fclose(input_file);
+ qDebug("Image2GrayScale: Error in opening output file");
+ err = i18n("Error in opening output file");
+ return false;
+ }
+
+ // Open jpeglib stream
+ jpeg_stdio_src(&srcinfo, input_file);
+
+ // Setup decompression object to save desired markers in memory
+ jcopy_markers_setup(&srcinfo, copyoption);
+
+ // Decompression startup: read start of JPEG datastream to see what's there
+ (void) jpeg_read_header(&srcinfo, true);
+
+ // Request any required workspace
+ jtransform_request_workspace(&srcinfo, &transformoption);
+
+ // Read source file as DCT coefficients
+ src_coef_arrays = jpeg_read_coefficients(&srcinfo);
+
+ // Initialize destination compression parameters from source values
+ jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
+
+ // Adjust output image parameters
+ dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, src_coef_arrays, &transformoption);
+
+ // Specify data destination for compression
+ jpeg_stdio_dest(&dstinfo, output_file);
+
+ // Do not write a JFIF header if previously the image did not contain it
+ dstinfo.write_JFIF_header = false;
+
+ // Start compressor (note no image data is actually written here)
+ jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
+
+ // Copy to the output file any extra markers that we want to preserve (merging from src file with Qt tmp file)
+ jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
+
+ // Execute the actual jpeg transformations
+ jtransform_execute_transformation(&srcinfo, &dstinfo, src_coef_arrays, &transformoption);
+
+ // Finish compression and release memory
+ jpeg_finish_compress(&dstinfo);
+ jpeg_destroy_compress(&dstinfo);
+ (void) jpeg_finish_decompress(&srcinfo);
+ jpeg_destroy_decompress(&srcinfo);
+
+ fclose(input_file);
+ fclose(output_file);
+
+ return true;
+}
+
+bool ImageGrayScale::image2GrayScaleImageMagick(const QString& src, const QString& dest, QString& err)
+{
+ KProcess process;
+ process.clearArguments();
+ process << "convert";
+ process << "-verbose";
+ process << "-type" << "Grayscale";
+ process << src + QString("[0]") << dest;
+
+ qDebug("ImageMagick Command line args:");
+ QValueList<QCString> args = process.args();
+ for (QValueList<QCString>::iterator it = args.begin(); it != args.end(); ++it)
+ qDebug("%s", (const char*)(*it));
+
+ connect(&process, SIGNAL(receivedStderr(KProcess *, char*, int)),
+ this, SLOT(slotReadStderr(KProcess*, char*, int)));
+
+ if (!process.start(KProcess::Block, KProcess::Stderr))
+ return false;
+
+ if (!process.normalExit())
+ return false;
+
+ switch (process.exitStatus())
+ {
+ case 0: // Process finished successfully !
+ {
+ return true;
+ break;
+ }
+ case 15: // process aborted !
+ {
+ return false;
+ break;
+ }
+ }
+
+ // Processing error !
+ err = i18n("Cannot convert to gray scale: %1").arg(m_stdErr.replace('\n', ' '));
+ return false;
+}
+
+void ImageGrayScale::slotReadStderr(KProcess*, char* buffer, int buflen)
+{
+ m_stdErr.append(QString::fromLocal8Bit(buffer, buflen));
+}
+
+} // NameSpace KIPIJPEGLossLessPlugin
diff --git a/kipi-plugins/jpeglossless/convert2grayscale.h b/kipi-plugins/jpeglossless/convert2grayscale.h
new file mode 100644
index 0000000..6d264f8
--- /dev/null
+++ b/kipi-plugins/jpeglossless/convert2grayscale.h
@@ -0,0 +1,67 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-14
+ * Description : batch images grayscale conversion
+ *
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 convert2grayscale_H
+#define convert2grayscale_H
+
+// Qt includes.
+
+#include <qobject.h>
+#include <qstring.h>
+
+class KTempFile;
+class KProcess;
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+class ImageGrayScale : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ ImageGrayScale();
+ ~ImageGrayScale();
+
+ bool image2GrayScale(const QString& src, QString& err);
+
+private slots:
+
+ void slotReadStderr(KProcess*, char*, int);
+
+private:
+
+ bool image2GrayScaleJPEG(const QString& src, const QString& dest, QString& err);
+ bool image2GrayScaleImageMagick(const QString& src, const QString& dest, QString& err);
+
+private:
+
+ QString m_stdErr;
+
+ KTempFile *m_tmpFile;
+};
+
+} // NameSpace KIPIJPEGLossLessPlugin
+
+#endif /* convert2grayscale_H */
diff --git a/kipi-plugins/jpeglossless/imageflip.cpp b/kipi-plugins/jpeglossless/imageflip.cpp
new file mode 100644
index 0000000..4d08a67
--- /dev/null
+++ b/kipi-plugins/jpeglossless/imageflip.cpp
@@ -0,0 +1,226 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-14
+ * Description : batch image flip
+ *
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * NOTE: Do not use kdDebug() in this implementation because
+ * it will be multithreaded. Use qDebug() instead.
+ * See B.K.O #133026 for details.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+#define XMD_H
+
+// C++ includes.
+
+#include <cstdio>
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <unistd.h>
+#include <jpeglib.h>
+}
+
+// Qt includes.
+
+#include <qimage.h>
+#include <qstring.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+
+// KDE includes.
+
+#include <kprocess.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <ktempfile.h>
+
+// Local includes
+
+#include "transupp.h"
+#include "jpegtransform.h"
+#include "utils.h"
+#include "imageflip.h"
+#include "imageflip.moc"
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+ImageFlip::ImageFlip()
+ : QObject()
+{
+ m_tmpFile = new KTempFile(QString(), QString("kipiplugin-flip"));
+ m_tmpFile->setAutoDelete(true);
+}
+
+ImageFlip::~ImageFlip()
+{
+ delete m_tmpFile;
+}
+
+bool ImageFlip::flip(const QString& src, FlipAction action, QString& err)
+{
+ QFileInfo fi(src);
+
+ if (!fi.exists() || !fi.isReadable() || !fi.isWritable())
+ {
+ err = i18n("Error in opening input file");
+ return false;
+ }
+
+ if ( !m_tmpFile->file() )
+ {
+ err = i18n("Error in opening temporary file");
+ return false;
+ }
+
+ QString tmp = m_tmpFile->name();
+
+ if (Utils::isRAW(src))
+ {
+ err = i18n("Cannot rotate RAW file");
+ return false;
+ }
+ else if (Utils::isJPEG(src))
+ {
+ if (!flipJPEG(src, tmp, action, err))
+ return false;
+ }
+ else
+ {
+ // B.K.O #123499 : we using Image Magick API here instead QT API
+ // else TIFF/PNG 16 bits image are broken!
+ if (!flipImageMagick(src, tmp, action, err))
+ return false;
+
+ // We update metadata on new image.
+ Utils tools(this);
+ if (!tools.updateMetadataImageMagick(tmp, err))
+ return false;
+ }
+
+ // Move back to original file
+ if (!Utils::MoveFile(tmp, src))
+ {
+ err = i18n("Cannot update source image");
+ return false;
+ }
+
+ return true;
+}
+
+bool ImageFlip::flipJPEG(const QString& src, const QString& dest, FlipAction action, QString& err)
+{
+ Matrix transform=Matrix::none;
+
+ switch(action)
+ {
+ case (FlipHorizontal):
+ {
+ transform=Matrix::flipHorizontal;
+ break;
+ }
+ case (FlipVertical):
+ {
+ transform=Matrix::flipVertical;
+ break;
+ }
+ default:
+ {
+ qDebug("ImageFlip: Nonstandard flip action");
+ err = i18n("Nonstandard flip action");
+ return false;
+ }
+ }
+
+ return transformJPEG(src, dest, transform, err);
+}
+
+bool ImageFlip::flipImageMagick(const QString& src, const QString& dest, FlipAction action, QString& err)
+{
+ KProcess process;
+ process.clearArguments();
+ process << "convert";
+ process << "-verbose";
+
+ switch(action)
+ {
+ case FlipHorizontal:
+ {
+ process << "-flop";
+ break;
+ }
+ case FlipVertical:
+ {
+ process << "-flip";
+ break;
+ }
+ default:
+ {
+ qDebug("ImageFlip: Nonstandard flip action");
+ err = i18n("Nonstandard flip action");
+ return false;
+ }
+ }
+
+ process << src + QString("[0]") << dest;
+
+ qDebug("ImageMagick Command line args:");
+ QValueList<QCString> args = process.args();
+ for (QValueList<QCString>::iterator it = args.begin(); it != args.end(); ++it)
+ qDebug("%s", (const char*)(*it));
+
+ connect(&process, SIGNAL(receivedStderr(KProcess *, char*, int)),
+ this, SLOT(slotReadStderr(KProcess*, char*, int)));
+
+ if (!process.start(KProcess::Block, KProcess::Stderr))
+ return false;
+
+ if (!process.normalExit())
+ return false;
+
+ switch (process.exitStatus())
+ {
+ case 0: // Process finished successfully !
+ {
+ return true;
+ break;
+ }
+ case 15: // process aborted !
+ {
+ return false;
+ break;
+ }
+ }
+
+ // Processing error !
+ err = i18n("Cannot flip: %1").arg(m_stdErr.replace('\n', ' '));
+ return false;
+}
+
+void ImageFlip::slotReadStderr(KProcess*, char* buffer, int buflen)
+{
+ m_stdErr.append(QString::fromLocal8Bit(buffer, buflen));
+}
+
+} // NameSpace KIPIJPEGLossLessPlugin
+
diff --git a/kipi-plugins/jpeglossless/imageflip.h b/kipi-plugins/jpeglossless/imageflip.h
new file mode 100644
index 0000000..ff787fd
--- /dev/null
+++ b/kipi-plugins/jpeglossless/imageflip.h
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-14
+ * Description : batch image flip
+ *
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IMAGEFLIP_H
+#define IMAGEFLIP_H
+
+// Local includes.
+
+#include "actions.h"
+
+// Qt includes.
+
+#include <qobject.h>
+#include <qstring.h>
+
+class KTempFile;
+class KProcess;
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+class ImageFlip : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ ImageFlip();
+ ~ImageFlip();
+
+ bool flip(const QString& src, FlipAction action, QString& err);
+
+private slots:
+
+ void slotReadStderr(KProcess*, char*, int);
+
+private:
+
+ bool flipJPEG(const QString& src, const QString& dest, FlipAction action, QString& err);
+ bool flipImageMagick(const QString& src, const QString& dest, FlipAction action, QString& err);
+
+private:
+
+ QString m_stdErr;
+
+ KTempFile *m_tmpFile;
+};
+
+} // NameSpace KIPIJPEGLossLessPlugin
+
+#endif /* IMAGEFLIP_H */
diff --git a/kipi-plugins/jpeglossless/imagerotate.cpp b/kipi-plugins/jpeglossless/imagerotate.cpp
new file mode 100644
index 0000000..cff301e
--- /dev/null
+++ b/kipi-plugins/jpeglossless/imagerotate.cpp
@@ -0,0 +1,249 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-14
+ * Description : batch image rotation
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * NOTE: Do not use kdDebug() in this implementation because
+ * it will be multithreaded. Use qDebug() instead.
+ * See B.K.O #133026 for details.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+#define XMD_H
+
+// C++ includes.
+
+#include <cstdio>
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <unistd.h>
+#include <jpeglib.h>
+}
+
+// Qt includes.
+
+#include <qimage.h>
+#include <qwmatrix.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+
+// KDE includes.
+
+#include <kprocess.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <ktempfile.h>
+
+// Local includes.
+
+#include "utils.h"
+#include "transupp.h"
+#include "jpegtransform.h"
+#include "imagerotate.h"
+#include "imagerotate.moc"
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+ImageRotate::ImageRotate()
+ : QObject()
+{
+ m_tmpFile = new KTempFile(QString(), QString("kipiplugin-rotate"));
+ m_tmpFile->setAutoDelete(true);
+}
+
+ImageRotate::~ImageRotate()
+{
+ delete m_tmpFile;
+}
+
+bool ImageRotate::rotate(const QString& src, RotateAction angle, QString& err)
+{
+ QFileInfo fi(src);
+
+ if (!fi.exists() || !fi.isReadable() || !fi.isWritable())
+ {
+ err = i18n("Error in opening input file");
+ return false;
+ }
+
+ if ( !m_tmpFile->file() )
+ {
+ err = i18n("Error in opening temporary file");
+ return false;
+ }
+
+ QString tmp = m_tmpFile->name();
+
+ if (Utils::isRAW(src))
+ {
+ err = i18n("Cannot rotate RAW file");
+ return false;
+ }
+ else if (Utils::isJPEG(src))
+ {
+ if (!rotateJPEG(src, tmp, angle, err)) {
+ if (err == "nothing to do") { err=QString::null; return true; }
+ return false;
+ }
+ }
+ else
+ {
+ // B.K.O #123499 : we using Image Magick API here instead QT API
+ // else TIFF/PNG 16 bits image are broken!
+ if (!rotateImageMagick(src, tmp, angle, err))
+ return false;
+
+ // We update metadata on new image.
+ Utils tools(this);
+ if (!tools.updateMetadataImageMagick(tmp, err))
+ return false;
+ }
+
+ // Move back to original file
+ if (!Utils::MoveFile(tmp, src))
+ {
+ err = i18n("Cannot update source image");
+ return false;
+ }
+
+ return true;
+}
+
+bool ImageRotate::rotateJPEG(const QString& src, const QString& dest, RotateAction angle, QString& err)
+{
+ Matrix transform=Matrix::none;
+
+ switch(angle)
+ {
+ case (Rot90):
+ {
+ transform = Matrix::rotate90;
+ break;
+ }
+ case (Rot180):
+ {
+ transform = Matrix::rotate180;
+ break;
+ }
+ case (Rot270):
+ {
+ transform = Matrix::rotate270;
+ break;
+ }
+ case (Rot0):
+ {
+ transform = Matrix::none;
+ break;
+ }
+ default:
+ {
+ qDebug("ImageRotate: Nonstandard rotation angle");
+ err = i18n("Nonstandard rotation angle");
+ return false;
+ }
+ }
+
+ return transformJPEG(src, dest, transform, err);
+}
+
+bool ImageRotate::rotateImageMagick(const QString& src, const QString& dest,
+ RotateAction angle, QString& err)
+{
+ KProcess process;
+ process.clearArguments();
+ process << "convert";
+ process << "-verbose";
+ process << "-rotate";
+
+ switch(angle)
+ {
+ case (Rot90):
+ {
+ process << "90";
+ break;
+ }
+ case (Rot180):
+ {
+ process << "180";
+ break;
+ }
+ case (Rot270):
+ {
+ process << "270";
+ break;
+ }
+ case (Rot0):
+ {
+ break;
+ }
+ default:
+ {
+ qDebug("ImageRotate: Nonstandard rotation angle");
+ err = i18n("Nonstandard rotation angle");
+ return false;
+ }
+ }
+
+ process << src + QString("[0]") << dest;
+
+ qDebug("ImageMagick Command line args:");
+ QValueList<QCString> args = process.args();
+ for (QValueList<QCString>::iterator it = args.begin(); it != args.end(); ++it)
+ qDebug("%s", (const char*)(*it));
+
+ connect(&process, SIGNAL(receivedStderr(KProcess *, char*, int)),
+ this, SLOT(slotReadStderr(KProcess*, char*, int)));
+
+ if (!process.start(KProcess::Block, KProcess::Stderr))
+ return false;
+
+ if (!process.normalExit())
+ return false;
+
+ switch (process.exitStatus())
+ {
+ case 0: // Process finished successfully !
+ {
+ return true;
+ break;
+ }
+ case 15: // process aborted !
+ {
+ return false;
+ break;
+ }
+ }
+
+ // Processing error !
+ err = i18n("Cannot rotate: %1").arg(m_stdErr.replace('\n', ' '));
+ return false;
+}
+
+void ImageRotate::slotReadStderr(KProcess*, char* buffer, int buflen)
+{
+ m_stdErr.append(QString::fromLocal8Bit(buffer, buflen));
+}
+
+} // NameSpace KIPIJPEGLossLessPlugin
diff --git a/kipi-plugins/jpeglossless/imagerotate.h b/kipi-plugins/jpeglossless/imagerotate.h
new file mode 100644
index 0000000..aaa27c0
--- /dev/null
+++ b/kipi-plugins/jpeglossless/imagerotate.h
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-14
+ * Description : batch image rotation
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IMAGEROTATE_H
+#define IMAGEROTATE_H
+
+// Local includes.
+
+#include "actions.h"
+
+// Qt includes.
+
+#include <qobject.h>
+#include <qstring.h>
+
+class KTempFile;
+class KProcess;
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+class ImageRotate : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ ImageRotate();
+ ~ImageRotate();
+
+ bool rotate(const QString& src, RotateAction angle, QString& err);
+
+private slots:
+
+ void slotReadStderr(KProcess*, char*, int);
+
+private:
+
+ bool rotateJPEG(const QString& src, const QString& dest, RotateAction angle, QString& err);
+ bool rotateImageMagick(const QString& src, const QString& dest, RotateAction angle, QString& err);
+
+private:
+
+ QString m_stdErr;
+
+ KTempFile *m_tmpFile;
+};
+
+} // NameSpace KIPIJPEGLossLessPlugin
+
+#endif /* IMAGEROTATE_H */
diff --git a/kipi-plugins/jpeglossless/jinclude.h b/kipi-plugins/jpeglossless/jinclude.h
new file mode 100644
index 0000000..e36ceec
--- /dev/null
+++ b/kipi-plugins/jpeglossless/jinclude.h
@@ -0,0 +1,96 @@
+/*
+ * jinclude.h
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file exists to provide a single place to fix any problems with
+ * including the wrong system include files. (Common problems are taken
+ * care of by the standard jconfig symbols, but on really weird systems
+ * you may have to edit this file.)
+ *
+ * NOTE: this file is NOT intended to be included by applications using the
+ * JPEG library. Most applications need only include jpeglib.h.
+ */
+
+#ifndef JINCLUDE_H
+#define JINCLUDE_H
+
+/* Include auto-config file to find out which system include files we need. */
+
+#include "jconfig.h" /* auto configuration options */
+#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
+
+/*
+ * We need the NULL macro and size_t typedef.
+ * On an ANSI-conforming system it is sufficient to include <stddef.h>.
+ * Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
+ * pull in <sys/types.h> as well.
+ * Note that the core JPEG library does not require <stdio.h>;
+ * only the default error handler and data source/destination modules do.
+ * But we must pull it in because of the references to FILE in jpeglib.h.
+ * You can remove those references if you want to compile without <stdio.h>.
+ */
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+
+/*
+ * We need memory copying and zeroing functions, plus strncpy().
+ * ANSI and System V implementations declare these in <string.h>.
+ * BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
+ * Some systems may declare memset and memcpy in <memory.h>.
+ *
+ * NOTE: we assume the size parameters to these functions are of type size_t.
+ * Change the casts in these macros if not!
+ */
+
+#ifdef NEED_BSD_STRINGS
+
+#include <strings.h>
+#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
+#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
+
+#else /* not BSD, assume ANSI/SysV string lib */
+
+#include <string.h>
+#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
+#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
+
+#endif
+
+/*
+ * In ANSI C, and indeed any rational implementation, size_t is also the
+ * type returned by sizeof(). However, it seems there are some irrational
+ * implementations out there, in which sizeof() returns an int even though
+ * size_t is defined as long or unsigned long. To ensure consistent results
+ * we always use this SIZEOF() macro in place of using sizeof() directly.
+ */
+
+#define SIZEOF(object) ((size_t) sizeof(object))
+
+/*
+ * The modules that use fread() and fwrite() always invoke them through
+ * these macros. On some systems you may need to twiddle the argument casts.
+ * CAUTION: argument order is different from underlying functions!
+ */
+
+#define JFREAD(file,buf,sizeofbuf) \
+ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+#define JFWRITE(file,buf,sizeofbuf) \
+ ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+
+#endif /*JINCLUDE_H*/
+
diff --git a/kipi-plugins/jpeglossless/jpegint.h b/kipi-plugins/jpeglossless/jpegint.h
new file mode 100644
index 0000000..95b00d4
--- /dev/null
+++ b/kipi-plugins/jpeglossless/jpegint.h
@@ -0,0 +1,392 @@
+/*
+ * jpegint.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides common declarations for the various JPEG modules.
+ * These declarations are considered internal to the JPEG library; most
+ * applications using the library shouldn't need to include this file.
+ */
+
+
+/* Declarations for both compression & decompression */
+
+typedef enum { /* Operating modes for buffer controllers */
+ JBUF_PASS_THRU, /* Plain stripwise operation */
+ /* Remaining modes require a full-image buffer to have been created */
+ JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
+ JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
+ JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
+} J_BUF_MODE;
+
+/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
+#define CSTATE_START 100 /* after create_compress */
+#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
+#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
+#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
+#define DSTATE_START 200 /* after create_decompress */
+#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
+#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
+#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
+#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
+#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
+#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
+#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
+#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
+#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
+#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
+
+
+/* Declarations for compression modules */
+
+/* Master control module */
+struct jpeg_comp_master {
+ JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
+ JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean call_pass_startup; /* True if pass_startup must be called */
+ boolean is_last_pass; /* True during last pass */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_c_main_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, process_data, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail));
+};
+
+/* Compression preprocessing (downsampling input buffer control) */
+struct jpeg_c_prep_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf,
+ JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail));
+};
+
+/* Coefficient buffer control */
+struct jpeg_c_coef_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf));
+};
+
+/* Colorspace conversion */
+struct jpeg_color_converter {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, color_convert, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows));
+};
+
+/* Downsampling */
+struct jpeg_downsampler {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, downsample, (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_index,
+ JSAMPIMAGE output_buf,
+ JDIMENSION out_row_group_index));
+
+ boolean need_context_rows; /* TRUE if need rows above & below */
+};
+
+/* Forward DCT (also controls coefficient quantization) */
+struct jpeg_forward_dct {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ /* perhaps this should be an array??? */
+ JMETHOD(void, forward_DCT, (j_compress_ptr cinfo,
+ jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks));
+};
+
+/* Entropy encoding */
+struct jpeg_entropy_encoder {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
+ JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
+ JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
+};
+
+/* Marker writing */
+struct jpeg_marker_writer {
+ JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
+ JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
+ /* These routines are exported to allow insertion of extra markers */
+ /* Probably only COM and APPn markers should be written this way */
+ JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker,
+ unsigned int datalen));
+ JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val));
+};
+
+
+/* Declarations for decompression modules */
+
+/* Master control module */
+struct jpeg_decomp_master {
+ JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
+};
+
+/* Input control module */
+struct jpeg_input_controller {
+ JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
+ JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
+ JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean has_multiple_scans; /* True if file has multiple scans */
+ boolean eoi_reached; /* True when EOI has been consumed */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_d_main_controller {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, process_data, (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+};
+
+/* Coefficient buffer control */
+struct jpeg_d_coef_controller {
+ JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+ JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
+ JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
+ JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
+ JSAMPIMAGE output_buf));
+ /* Pointer to array of coefficient virtual arrays, or NULL if none */
+ jvirt_barray_ptr *coef_arrays;
+};
+
+/* Decompression postprocessing (color quantization buffer control) */
+struct jpeg_d_post_controller {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+};
+
+/* Marker reading & parsing */
+struct jpeg_marker_reader {
+ JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
+ /* Read markers until SOS or EOI.
+ * Returns same codes as are defined for jpeg_consume_input:
+ * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ */
+ JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
+ /* Read a restart marker --- exported for use by entropy decoder only */
+ jpeg_marker_parser_method read_restart_marker;
+
+ /* State of marker reader --- nominally internal, but applications
+ * supplying COM or APPn handlers might like to know the state.
+ */
+ boolean saw_SOI; /* found SOI? */
+ boolean saw_SOF; /* found SOF? */
+ int next_restart_num; /* next restart number expected (0-7) */
+ unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
+};
+
+/* Entropy decoding */
+struct jpeg_entropy_decoder {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+
+ /* This is here to share code between baseline and progressive decoders; */
+ /* other modules probably should not use it */
+ boolean insufficient_data; /* set TRUE after emitting warning */
+};
+
+/* Inverse DCT (also performs dequantization) */
+typedef JMETHOD(void, inverse_DCT_method_ptr,
+ (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col));
+
+struct jpeg_inverse_dct {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ /* It is useful to allow each component to have a separate IDCT method. */
+ inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
+};
+
+/* Upsampling (note that upsampler must also call color converter) */
+struct jpeg_upsampler {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, upsample, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+
+ boolean need_context_rows; /* TRUE if need rows above & below */
+};
+
+/* Colorspace conversion */
+struct jpeg_color_deconverter {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows));
+};
+
+/* Color quantization or color precision reduction */
+struct jpeg_color_quantizer {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
+ JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf,
+ int num_rows));
+ JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
+};
+
+
+/* Miscellaneous useful macros */
+
+#undef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#undef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+
+/* We assume that right shift corresponds to signed division by 2 with
+ * rounding towards minus infinity. This is correct for typical "arithmetic
+ * shift" instructions that shift in copies of the sign bit. But some
+ * C compilers implement >> with an unsigned shift. For these machines you
+ * must define RIGHT_SHIFT_IS_UNSIGNED.
+ * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
+ * It is only applied with constant shift counts. SHIFT_TEMPS must be
+ * included in the variables of any routine using RIGHT_SHIFT.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define SHIFT_TEMPS INT32 shift_temp;
+#define RIGHT_SHIFT(x,shft) \
+ ((shift_temp = (x)) < 0 ? \
+ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
+ (shift_temp >> (shft)))
+#else
+#define SHIFT_TEMPS
+#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jinit_compress_master jICompress
+#define jinit_c_master_control jICMaster
+#define jinit_c_main_controller jICMainC
+#define jinit_c_prep_controller jICPrepC
+#define jinit_c_coef_controller jICCoefC
+#define jinit_color_converter jICColor
+#define jinit_downsampler jIDownsampler
+#define jinit_forward_dct jIFDCT
+#define jinit_huff_encoder jIHEncoder
+#define jinit_phuff_encoder jIPHEncoder
+#define jinit_marker_writer jIMWriter
+#define jinit_master_decompress jIDMaster
+#define jinit_d_main_controller jIDMainC
+#define jinit_d_coef_controller jIDCoefC
+#define jinit_d_post_controller jIDPostC
+#define jinit_input_controller jIInCtlr
+#define jinit_marker_reader jIMReader
+#define jinit_huff_decoder jIHDecoder
+#define jinit_phuff_decoder jIPHDecoder
+#define jinit_inverse_dct jIIDCT
+#define jinit_upsampler jIUpsampler
+#define jinit_color_deconverter jIDColor
+#define jinit_1pass_quantizer jI1Quant
+#define jinit_2pass_quantizer jI2Quant
+#define jinit_merged_upsampler jIMUpsampler
+#define jinit_memory_mgr jIMemMgr
+#define jdiv_round_up jDivRound
+#define jround_up jRound
+#define jcopy_sample_rows jCopySamples
+#define jcopy_block_row jCopyBlocks
+#define jzero_far jZeroFar
+#define jpeg_zigzag_order jZIGTable
+#define jpeg_natural_order jZAGTable
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Compression module initialization routines */
+EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
+ boolean transcode_only));
+EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
+/* Decompression module initialization routines */
+EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
+/* Memory manager initialization */
+EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
+
+/* Utility routines in jutils.c */
+EXTERN(long) jdiv_round_up JPP((long a, long b));
+EXTERN(long) jround_up JPP((long a, long b));
+EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row,
+ int num_rows, JDIMENSION num_cols));
+EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks));
+EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero));
+/* Constant tables in jutils.c */
+#if 0 /* This table is not actually needed in v6a */
+extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
+#endif
+extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
+
+/* Suppress undefined-structure complaints if necessary. */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+#endif
+#endif /* INCOMPLETE_TYPES_BROKEN */
diff --git a/kipi-plugins/jpeglossless/jpegtransform.cpp b/kipi-plugins/jpeglossless/jpegtransform.cpp
new file mode 100644
index 0000000..7009e47
--- /dev/null
+++ b/kipi-plugins/jpeglossless/jpegtransform.cpp
@@ -0,0 +1,441 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-06-08
+ * Description : Loss less JPEG files transformations.
+ *
+ * Copyright (C) 2004 by Ralf Hoelzer <kde at ralfhoelzer.com>
+ * Copyright (C) 2004-2005 by Marcel Wiesweg <marcel.wiesweg@gmx.de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * NOTE: Do not use kdDebug() in this implementation because
+ * it will be multithreaded. Use qDebug() instead.
+ * See B.K.O #133026 for details.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+#include <cstdlib>
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <jpeglib.h>
+}
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qwmatrix.h>
+#include <qfile.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <ktempfile.h>
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "transupp.h"
+#include "jpegtransform.h"
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+const Matrix Matrix::none ( 1, 0, 0, 1);
+const Matrix Matrix::rotate90 ( 0, -1, 1, 0);
+const Matrix Matrix::rotate180 (-1, 0, 0, -1);
+const Matrix Matrix::rotate270 ( 0, 1, -1, 0);
+const Matrix Matrix::flipHorizontal (-1, 0, 0, 1);
+const Matrix Matrix::flipVertical ( 1, 0, 0, -1);
+const Matrix Matrix::rotate90flipHorizontal ( 0, 1, 1, 0);
+const Matrix Matrix::rotate90flipVertical ( 0, -1, -1, 0);
+
+
+// To manage Errors/Warnings handling provide by libjpeg
+
+//#define ENABLE_DEBUG_MESSAGES
+
+struct jpegtransform_jpeg_error_mgr : public jpeg_error_mgr
+{
+ jmp_buf setjmp_buffer;
+};
+
+static void jpegtransform_jpeg_error_exit(j_common_ptr cinfo);
+static void jpegtransform_jpeg_emit_message(j_common_ptr cinfo, int msg_level);
+static void jpegtransform_jpeg_output_message(j_common_ptr cinfo);
+
+static void jpegtransform_jpeg_error_exit(j_common_ptr cinfo)
+{
+ jpegtransform_jpeg_error_mgr* myerr = (jpegtransform_jpeg_error_mgr*) cinfo->err;
+
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message)(cinfo, buffer);
+
+#ifdef ENABLE_DEBUG_MESSAGES
+ qDebug("%s", buffer)
+#endif
+
+ longjmp(myerr->setjmp_buffer, 1);
+}
+
+static void jpegtransform_jpeg_emit_message(j_common_ptr cinfo, int msg_level)
+{
+ Q_UNUSED(msg_level)
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message)(cinfo, buffer);
+
+#ifdef ENABLE_DEBUG_MESSAGES
+ qDebug("%s (%i)", buffer, msg_level);
+#endif
+}
+
+static void jpegtransform_jpeg_output_message(j_common_ptr cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message)(cinfo, buffer);
+
+#ifdef ENABLE_DEBUG_MESSAGES
+ qDebug("%s", buffer)
+#endif
+}
+
+bool transformJPEG(const QString& src, const QString& destGiven,
+ Matrix &userAction, QString& err)
+{
+ //may be modified
+ QString dest(destGiven);
+
+ JCOPY_OPTION copyoption = JCOPYOPT_ALL;
+ jpeg_transform_info transformoption;
+
+ transformoption.force_grayscale = false;
+ transformoption.trim = false;
+
+ struct jpeg_decompress_struct srcinfo;
+ struct jpeg_compress_struct dstinfo;
+ struct jpegtransform_jpeg_error_mgr jsrcerr, jdsterr;
+ jvirt_barray_ptr * src_coef_arrays;
+ jvirt_barray_ptr * dst_coef_arrays;
+
+ Matrix exifAction, action;
+ JXFORM_CODE flip, rotate;
+
+ // Initialize the JPEG decompression object with default error handling
+ srcinfo.err = jpeg_std_error(&jsrcerr);
+ srcinfo.err->error_exit = jpegtransform_jpeg_error_exit;
+ srcinfo.err->emit_message = jpegtransform_jpeg_emit_message;
+ srcinfo.err->output_message = jpegtransform_jpeg_output_message;
+
+ // Initialize the JPEG compression object with default error handling
+ dstinfo.err = jpeg_std_error(&jdsterr);
+ dstinfo.err->error_exit = jpegtransform_jpeg_error_exit;
+ dstinfo.err->emit_message = jpegtransform_jpeg_emit_message;
+ dstinfo.err->output_message = jpegtransform_jpeg_output_message;
+
+ FILE *input_file;
+ FILE *output_file;
+
+ input_file = fopen(QFile::encodeName(src), "rb");
+ if (!input_file)
+ {
+ qDebug("ImageRotate/ImageFlip: Error in opening input file");
+ err = i18n("Error in opening input file");
+ return false;
+ }
+
+ output_file = fopen(QFile::encodeName(dest), "wb");
+ if (!output_file)
+ {
+ fclose(input_file);
+ qDebug("ImageRotate/ImageFlip: Error in opening output file");
+ err = i18n("Error in opening output file");
+ return false;
+ }
+
+ if (setjmp(jsrcerr.setjmp_buffer) || setjmp(jdsterr.setjmp_buffer))
+ {
+ jpeg_destroy_decompress(&srcinfo);
+ jpeg_destroy_compress(&dstinfo);
+ fclose(input_file);
+ fclose(output_file);
+ return false;
+ }
+
+ jpeg_create_decompress(&srcinfo);
+ jpeg_create_compress(&dstinfo);
+
+ jpeg_stdio_src(&srcinfo, input_file);
+ jcopy_markers_setup(&srcinfo, copyoption);
+
+ (void) jpeg_read_header(&srcinfo, true);
+
+ // Get Exif orientation action to do.
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.load(src);
+ getExifAction(exifAction, exiv2Iface.getImageOrientation());
+
+ // Compose actions: first exif, then user
+ action*=exifAction;
+ action*=userAction;
+
+ // Convert action into flip+rotate action
+ convertTransform(action, flip, rotate);
+ qDebug("Transforming with option %i %i", flip, rotate);
+ if (flip == JXFORM_NONE && rotate == JXFORM_NONE)
+ {
+ err = "nothing to do"; // magic string
+ fclose(output_file);
+ fclose(input_file);
+ return false;
+ }
+
+ bool twoPass = (flip != JXFORM_NONE);
+
+ // If twoPass is true, we need another file (src -> tempFile -> destGiven)
+ if (twoPass)
+ {
+ KTempFile tempFile;
+ tempFile.setAutoDelete(false);
+ dest=tempFile.name();
+ }
+
+ output_file = fopen(QFile::encodeName(dest), "wb");
+ if (!output_file)
+ {
+ fclose(input_file);
+ qDebug("ImageRotate/ImageFlip: Error in opening output file");
+ err = i18n("Error in opening output file");
+ return false;
+ }
+
+ // First rotate - execute even if rotate is JXFORM_NONE to apply new EXIF settings
+ transformoption.transform=rotate;
+
+ jtransform_request_workspace(&srcinfo, &transformoption);
+
+ // Read source file as DCT coefficients
+ src_coef_arrays = jpeg_read_coefficients(&srcinfo);
+
+ // Initialize destination compression parameters from source values
+ jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
+
+ dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
+ src_coef_arrays, &transformoption);
+
+ // Specify data destination for compression
+ jpeg_stdio_dest(&dstinfo, output_file);
+
+ // Do not write a JFIF header if previously the image did not contain it
+ dstinfo.write_JFIF_header = false;
+
+ // Start compressor (note no image data is actually written here)
+ jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
+
+ // Copy to the output file any extra markers that we want to preserve
+ jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
+
+ jtransform_execute_transformation(&srcinfo, &dstinfo,
+ src_coef_arrays, &transformoption);
+
+ // Finish compression and release memory
+ jpeg_finish_compress(&dstinfo);
+ jpeg_destroy_compress(&dstinfo);
+ (void) jpeg_finish_decompress(&srcinfo);
+ jpeg_destroy_decompress(&srcinfo);
+
+ fclose(input_file);
+ fclose(output_file);
+
+ // Flip if needed
+ if (twoPass)
+ {
+ // Initialize the JPEG decompression object with default error handling
+ srcinfo.err = jpeg_std_error(&jsrcerr);
+ jpeg_create_decompress(&srcinfo);
+
+ // Initialize the JPEG compression object with default error handling
+ dstinfo.err = jpeg_std_error(&jdsterr);
+ jpeg_create_compress(&dstinfo);
+
+ input_file = fopen(QFile::encodeName(dest), "rb");
+ if (!input_file)
+ {
+ qDebug("ImageRotate/ImageFlip: Error in opening input file");
+ err = i18n("Error in opening input file");
+ return false;
+ }
+
+ output_file = fopen(QFile::encodeName(destGiven), "wb");
+ if (!output_file)
+ {
+ fclose(input_file);
+ qDebug("ImageRotate/ImageFlip: Error in opening output file");
+ err = i18n("Error in opening output file");
+ return false;
+ }
+
+ jpeg_stdio_src(&srcinfo, input_file);
+ jcopy_markers_setup(&srcinfo, copyoption);
+
+ (void) jpeg_read_header(&srcinfo, true);
+
+ transformoption.transform=flip;
+ jtransform_request_workspace(&srcinfo, &transformoption);
+
+ // Read source file as DCT coefficients
+ src_coef_arrays = jpeg_read_coefficients(&srcinfo);
+
+ // Initialize destination compression parameters from source values
+ jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
+
+ dst_coef_arrays = jtransform_adjust_parameters(&srcinfo,
+ &dstinfo,
+ src_coef_arrays,
+ &transformoption);
+
+ // Specify data destination for compression
+ jpeg_stdio_dest(&dstinfo, output_file);
+
+ // Do not write a JFIF header if previously the image did not contain it
+ dstinfo.write_JFIF_header = false;
+
+ // Start compressor (note no image data is actually written here)
+ jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
+
+ // Copy to the output file any extra markers that we want to preserve
+ jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
+
+ jtransform_execute_transformation(&srcinfo, &dstinfo,
+ src_coef_arrays, &transformoption);
+
+ // Finish compression and release memory
+ jpeg_finish_compress(&dstinfo);
+ jpeg_destroy_compress(&dstinfo);
+ (void) jpeg_finish_decompress(&srcinfo);
+ jpeg_destroy_decompress(&srcinfo);
+
+ fclose(input_file);
+ fclose(output_file);
+
+ // Unlink temp file
+ unlink(QFile::encodeName(dest));
+ }
+
+ // And set finaly update the metadata to target file.
+
+ QImage img(destGiven);
+ QImage exifThumbnail = img.scale(160, 120, QImage::ScaleMin);
+ exiv2Iface.load(destGiven);
+ exiv2Iface.setImageOrientation(KExiv2Iface::KExiv2::ORIENTATION_NORMAL);
+ exiv2Iface.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+ exiv2Iface.setImageDimensions(img.size());
+ exiv2Iface.setExifThumbnail(exifThumbnail);
+ exiv2Iface.save(destGiven);
+
+ return true;
+}
+
+/** Converts the mathematically correct description
+ into the primitive operations that can be carried out losslessly.
+*/
+void convertTransform(Matrix &action, JXFORM_CODE &flip, JXFORM_CODE &rotate)
+{
+ flip = JXFORM_NONE;
+ rotate = JXFORM_NONE;
+
+ if (action == Matrix::rotate90)
+ {
+ rotate = JXFORM_ROT_90;
+ }
+ else if (action == Matrix::rotate180)
+ {
+ rotate = JXFORM_ROT_180;
+ }
+ else if (action == Matrix::rotate270)
+ {
+ rotate = JXFORM_ROT_270;
+ }
+ else if (action == Matrix::flipHorizontal)
+ {
+ flip = JXFORM_FLIP_H;
+ }
+ else if (action == Matrix::flipVertical)
+ {
+ flip = JXFORM_FLIP_V;
+ }
+ else if (action == Matrix::rotate90flipHorizontal)
+ {
+ //first rotate, then flip!
+ rotate = JXFORM_ROT_90;
+ flip = JXFORM_FLIP_H;
+ }
+ else if (action == Matrix::rotate90flipVertical)
+ {
+ //first rotate, then flip!
+ rotate = JXFORM_ROT_90;
+ flip = JXFORM_FLIP_V;
+ }
+}
+
+void getExifAction(Matrix &action, KExiv2Iface::KExiv2::ImageOrientation exifOrientation)
+{
+ switch (exifOrientation)
+ {
+ case KExiv2Iface::KExiv2::ORIENTATION_NORMAL:
+ break;
+
+ case KExiv2Iface::KExiv2::ORIENTATION_HFLIP:
+ action*=Matrix::flipHorizontal;
+ break;
+
+ case KExiv2Iface::KExiv2::ORIENTATION_ROT_180:
+ action*=Matrix::rotate180;
+ break;
+
+ case KExiv2Iface::KExiv2::ORIENTATION_VFLIP:
+ action*=Matrix::flipVertical;
+ break;
+
+ case KExiv2Iface::KExiv2::ORIENTATION_ROT_90_HFLIP:
+ action*=Matrix::rotate90flipHorizontal;
+ break;
+
+ case KExiv2Iface::KExiv2::ORIENTATION_ROT_90:
+ action*=Matrix::rotate90;
+ break;
+
+ case KExiv2Iface::KExiv2::ORIENTATION_ROT_90_VFLIP:
+ action*=Matrix::rotate90flipVertical;
+ break;
+
+ case KExiv2Iface::KExiv2::ORIENTATION_ROT_270:
+ action*=Matrix::rotate270;
+ break;
+
+ case KExiv2Iface::KExiv2::ORIENTATION_UNSPECIFIED:
+ action*=Matrix::none;
+ break;
+ }
+}
+
+} // NameSpace KIPIJPEGLossLessPlugin
diff --git a/kipi-plugins/jpeglossless/jpegtransform.h b/kipi-plugins/jpeglossless/jpegtransform.h
new file mode 100644
index 0000000..1cf76f2
--- /dev/null
+++ b/kipi-plugins/jpeglossless/jpegtransform.h
@@ -0,0 +1,132 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-06-08
+ * Description : Loss less JPEG files transformations.
+ *
+ * Copyright (C) 2004 by Ralf Hoelzer <kde at ralfhoelzer.com>
+ * Copyright (C) 2004-2005 by Marcel Wiesweg <marcel.wiesweg@gmx.de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 JPEGTRANSFORM_H
+#define JPEGTRANSFORM_H
+
+// Qt includes.
+
+#include <qstring.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+/*
+ If the picture is displayed according to the exif orientation tag,
+ the user will request rotating operations relative to what he sees,
+ and that is the picture rotated according to the EXIF tag.
+ So the operation requested and the given EXIF angle must be combined.
+ E.g. if orientation is "6" (rotate 90 clockwiseto show correctly)
+ and the user selects 180 clockwise, the operation is 270.
+ If the user selected 270, the operation would be None (and clearing the exif tag).
+
+ This requires to describe the transformations in a model which
+ cares for both composing (180+90=270) and eliminating (180+180=no action),
+ as well as the non-commutative nature of the operations (vflip+90 is not 90+vflip)
+
+ All 2D transformations can be described by a 2x3 matrix, see QWMatrix.
+ All transformations needed here - rotate 90, 180, 270, flipV, flipH -
+ can be described in a 2x2 matrix with the values 0,1,-1
+ (because flipping is expressed by changing the sign only,
+ and sine and cosine of 90, 180 and 270 are either 0,1 or -1).
+
+ x' = m11 x + m12 y
+ y' = m21 x + m22 y
+
+ Moreover, all combinations of these rotate/flip operations result in one of the eight
+ matrices defined below.
+ (I did not proof that mathematically, but empirically)
+*/
+
+class Matrix
+{
+
+public:
+
+ Matrix()
+ {
+ set( 1, 0, 0, 1 );
+ }
+
+ Matrix &operator*=(const Matrix &ma)
+ {
+ set( ma.m[0][0]*m[0][0] + ma.m[0][1]*m[1][0], ma.m[0][0]*m[0][1] + ma.m[0][1]*m[1][1],
+ ma.m[1][0]*m[0][0] + ma.m[1][1]*m[1][0], ma.m[1][0]*m[0][1] + ma.m[1][1]*m[1][1] );
+ return *this;
+ }
+
+ bool operator==(const Matrix &ma) const
+ {
+ return m[0][0]==ma.m[0][0] &&
+ m[0][1]==ma.m[0][1] &&
+ m[1][0]==ma.m[1][0] &&
+ m[1][1]==ma.m[1][1];
+ }
+
+ bool operator!=(const Matrix &ma) const
+ {
+ return !(*this==ma);
+ }
+
+ static const Matrix none; //( 1, 0, 0, 1)
+ static const Matrix rotate90; //( 0, -1, 1, 0)
+ static const Matrix rotate180; //(-1, 0, 0, -1)
+ static const Matrix rotate270; //( 0, 1, -1, 0)
+ static const Matrix flipHorizontal; //(-1, 0, 0, 1)
+ static const Matrix flipVertical; //( 1, 0, 0, -1)
+ static const Matrix rotate90flipHorizontal; //( 0, 1, 1, 0), first rotate, then flip
+ static const Matrix rotate90flipVertical; //( 0, -1, -1, 0), first rotate, then flip
+
+protected:
+
+ Matrix(int m11, int m12, int m21, int m22)
+ {
+ set(m11, m12, m21, m22);
+ }
+
+ void set(int m11, int m12, int m21, int m22)
+ {
+ m[0][0]=m11;
+ m[0][1]=m12;
+ m[1][0]=m21;
+ m[1][1]=m22;
+ }
+
+ int m[2][2];
+};
+
+
+bool transformJPEG(const QString& src, const QString& dest, Matrix &action, QString& err);
+
+void convertTransform(Matrix &action, JXFORM_CODE &flip, JXFORM_CODE &rotate);
+
+void getExifAction(Matrix &action, KExiv2Iface::KExiv2::ImageOrientation exifOrientation);
+
+} // NameSpace KIPIJPEGLossLessPlugin
+
+#endif // JPEGTRANSFORM_H
diff --git a/kipi-plugins/jpeglossless/kipiplugin_jpeglossless.desktop b/kipi-plugins/jpeglossless/kipiplugin_jpeglossless.desktop
new file mode 100644
index 0000000..2b9c298
--- /dev/null
+++ b/kipi-plugins/jpeglossless/kipiplugin_jpeglossless.desktop
@@ -0,0 +1,55 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=JPEGLossless
+Name[ca]=JPEG sense pèrdua
+Name[cs]=Bezztrátový JPEG
+Name[da]=Tabsfri JPEG
+Name[de]=Verlustloses JPEG
+Name[el]=JPEGΜηΑπωλεστικό
+Name[es]=JPEG sin pérdida de calidad
+Name[fi]=Häviötön JPEG
+Name[gl]=JPEG sen Perdas
+Name[it]=JPEGSenzaPerdita
+Name[nds]=JPEG ahn Verlust
+Name[nl]=JPEG-lossless
+Name[pl]=Bezstratne operacje JPEG
+Name[pt]=JPEG sem Perdas
+Name[sr]=JPEG без губитака
+Name[sr@Latn]=JPEG bez gubitaka
+Name[sv]=Förlustfri JPEG
+Name[tg]=JPEGБебохтан
+Name[tr]=KayıpsızJPEG
+Name[xx]=xxJPEGLosslessxx
+Name[zh_CN]=JPEG 无损
+Comment=KIPI JPEG Lossless Plugin
+Comment[ca]=Connector del KIPI pel JPEG sense pèrdua
+Comment[cs]=KIPI modul bezztrátového JPEGu
+Comment[da]=KIPI-plugin: Tabsfri JPEG
+Comment[de]=Ein KIPI-Modul zur verlustlosen Bearbeitung von JPEG-Bildern
+Comment[el]=Πρόσθετο του KIPI για μη απωλεστικές JPEG
+Comment[es]=Complemento de KIPI para JPEG sin pérdida de calidad
+Comment[et]=KIPI JPEG Lossless plugin
+Comment[fi]=Kipi-liitännäinen jpeg-kuvien häviötöntä käsittelyä varten
+Comment[fr]=Module externe KIPI pour effectuer des opérations JPEG sans pertes
+Comment[gl]=Plugin de JPEG sen Perdas de KIPI
+Comment[is]=KIPI taplaust JPEG íforrit
+Comment[it]=Plugin JPEG senza perdita di KIPI
+Comment[ja]=Kipi JPEG 可逆圧縮プラグイン
+Comment[nds]=KIPI-Moduul för JPEG ahn Verlusten
+Comment[nl]=KIPI-plugin voor verliesloos JPEG
+Comment[pa]=KIPI JPEG ਲੂਜਲੈੱਸ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Bezstratne operacje na plikach JPEG
+Comment[pt]='Plugin' de JPEG sem Perdas do KIPI
+Comment[pt_BR]=Plugin de JPEG Sem Perdas do KIPI
+Comment[sr]=KIPI прикључак за JPEG компресију без губитака
+Comment[sr@Latn]=KIPI priključak za JPEG kompresiju bez gubitaka
+Comment[sv]=KIPI-insticksprogram: Förlustfri JPEG
+Comment[tg]=Модули Бебохтани KIPI JPEG
+Comment[tr]=KIPI Kayıpsız JPEG Eklentisi
+Comment[xx]=xxKIPI JPEG Lossless Pluginxx
+Comment[zh_CN]=KIPI JPEG 无损插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_jpeglossless
+author=Gilles Caulier, caulier dot gilles at gmail dot com
+X-KIPI-MergeMenu=true
diff --git a/kipi-plugins/jpeglossless/libjpeg62.README b/kipi-plugins/jpeglossless/libjpeg62.README
new file mode 100644
index 0000000..86cc206
--- /dev/null
+++ b/kipi-plugins/jpeglossless/libjpeg62.README
@@ -0,0 +1,385 @@
+The Independent JPEG Group's JPEG software
+==========================================
+
+README for release 6b of 27-Mar-1998
+====================================
+
+This distribution contains the sixth public release of the Independent JPEG
+Group's free JPEG software. You are welcome to redistribute this software and
+to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
+
+Serious users of this software (particularly those incorporating it into
+larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
+our electronic mailing list. Mailing list members are notified of updates
+and have a chance to participate in technical discussions, etc.
+
+This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
+Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
+Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG
+Group.
+
+IJG is not affiliated with the official ISO JPEG standards committee.
+
+
+DOCUMENTATION ROADMAP
+=====================
+
+This file contains the following sections:
+
+OVERVIEW General description of JPEG and the IJG software.
+LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
+REFERENCES Where to learn more about JPEG.
+ARCHIVE LOCATIONS Where to find newer versions of this software.
+RELATED SOFTWARE Other stuff you should get.
+FILE FORMAT WARS Software *not* to get.
+TO DO Plans for future IJG releases.
+
+Other documentation files in the distribution are:
+
+User documentation:
+ install.doc How to configure and install the IJG software.
+ usage.doc Usage instructions for cjpeg, djpeg, jpegtran,
+ rdjpgcom, and wrjpgcom.
+ *.1 Unix-style man pages for programs (same info as usage.doc).
+ wizard.doc Advanced usage instructions for JPEG wizards only.
+ change.log Version-to-version change highlights.
+Programmer and internal documentation:
+ libjpeg.doc How to use the JPEG library in your own programs.
+ example.c Sample code for calling the JPEG library.
+ structure.doc Overview of the JPEG library's internal structure.
+ filelist.doc Road map of IJG files.
+ coderules.doc Coding style rules --- please read if you contribute code.
+
+Please read at least the files install.doc and usage.doc. Useful information
+can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
+ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
+
+If you want to understand how the JPEG code works, we suggest reading one or
+more of the REFERENCES, then looking at the documentation files (in roughly
+the order listed) before diving into the code.
+
+
+OVERVIEW
+========
+
+This package contains C software to implement JPEG image compression and
+decompression. JPEG (pronounced "jay-peg") is a standardized compression
+method for full-color and gray-scale images. JPEG is intended for compressing
+"real-world" scenes; line drawings, cartoons and other non-realistic images
+are not its strong suit. JPEG is lossy, meaning that the output image is not
+exactly identical to the input image. Hence you must not use JPEG if you
+have to have identical output bits. However, on typical photographic images,
+very good compression levels can be obtained with no visible change, and
+remarkably high compression levels are possible if you can tolerate a
+low-quality image. For more details, see the references, or just experiment
+with various compression settings.
+
+This software implements JPEG baseline, extended-sequential, and progressive
+compression processes. Provision is made for supporting all variants of these
+processes, although some uncommon parameter settings aren't implemented yet.
+For legal reasons, we are not distributing code for the arithmetic-coding
+variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting
+the hierarchical or lossless processes defined in the standard.
+
+We provide a set of library routines for reading and writing JPEG image files,
+plus two sample applications "cjpeg" and "djpeg", which use the library to
+perform conversion between JPEG and some other popular image file formats.
+The library is intended to be reused in other applications.
+
+In order to support file conversion and viewing software, we have included
+considerable functionality beyond the bare JPEG coding/decoding capability;
+for example, the color quantization modules are not strictly part of JPEG
+decoding, but they are essential for output to colormapped file formats or
+colormapped displays. These extra functions can be compiled out of the
+library if not required for a particular application. We have also included
+"jpegtran", a utility for lossless transcoding between different JPEG
+processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
+inserting and extracting textual comments in JFIF files.
+
+The emphasis in designing this software has been on achieving portability and
+flexibility, while also making it fast enough to be useful. In particular,
+the software is not intended to be read as a tutorial on JPEG. (See the
+REFERENCES section for introductory material.) Rather, it is intended to
+be reliable, portable, industrial-strength code. We do not claim to have
+achieved that goal in every aspect of the software, but we strive for it.
+
+We welcome the use of this software as a component of commercial products.
+No royalty is required, but we do ask for an acknowledgement in product
+documentation, as described under LEGAL ISSUES.
+
+
+LEGAL ISSUES
+============
+
+In plain English:
+
+1. We don't promise that this software works. (But if you find any bugs,
+ please let us know!)
+2. You can use this software for whatever you want. You don't have to pay us.
+3. You may not pretend that you wrote this software. If you use it in a
+ program, you must acknowledge somewhere in your documentation that
+ you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose. This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-1998, Thomas G. Lane.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library. If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it. This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it. (See the file
+ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
+of any program generated from the IJG code, this does not limit you more than
+the foregoing paragraphs do.
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltconfig, ltmain.sh). Another support script, install-sh, is copyright
+by M.I.T. but is also freely distributable.
+
+It appears that the arithmetic coding option of the JPEG spec is covered by
+patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
+legally be used without obtaining one or more licenses. For this reason,
+support for arithmetic coding has been removed from the free JPEG software.
+(Since arithmetic coding provides only a marginal gain over the unpatented
+Huffman mode, it is unlikely that very many implementations will support it.)
+So far as we are aware, there are no patent restrictions on the remaining
+code.
+
+The IJG distribution formerly included code to read and write GIF files.
+To avoid entanglement with the Unisys LZW patent, GIF reading support has
+been removed altogether, and the GIF writer has been simplified to produce
+"uncompressed GIFs". This technique does not use the LZW algorithm; the
+resulting GIF files are larger than usual, but are readable by all standard
+GIF decoders.
+
+We are required to state that
+ "The Graphics Interchange Format(c) is the Copyright property of
+ CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ CompuServe Incorporated."
+
+
+REFERENCES
+==========
+
+We highly recommend reading one or more of these references before trying to
+understand the innards of the JPEG software.
+
+The best short technical introduction to the JPEG compression algorithm is
+ Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
+ Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
+(Adjacent articles in that issue discuss MPEG motion picture compression,
+applications of JPEG, and related topics.) If you don't have the CACM issue
+handy, a PostScript file containing a revised version of Wallace's article is
+available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually
+a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
+omits the sample images that appeared in CACM, but it includes corrections
+and some added material. Note: the Wallace article is copyright ACM and IEEE,
+and it may not be used for commercial purposes.
+
+A somewhat less technical, more leisurely introduction to JPEG can be found in
+"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
+M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides
+good explanations and example C code for a multitude of compression methods
+including JPEG. It is an excellent source if you are comfortable reading C
+code but don't know much about data compression in general. The book's JPEG
+sample code is far from industrial-strength, but when you are ready to look
+at a full implementation, you've got one here...
+
+The best full description of JPEG is the textbook "JPEG Still Image Data
+Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
+by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp.
+The book includes the complete text of the ISO JPEG standards (DIS 10918-1
+and draft DIS 10918-2). This is by far the most complete exposition of JPEG
+in existence, and we highly recommend it.
+
+The JPEG standard itself is not available electronically; you must order a
+paper copy through ISO or ITU. (Unless you feel a need to own a certified
+official copy, we recommend buying the Pennebaker and Mitchell book instead;
+it's much cheaper and includes a great deal of useful explanatory material.)
+In the USA, copies of the standard may be ordered from ANSI Sales at (212)
+642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI
+doesn't take credit card orders, but Global does.) It's not cheap: as of
+1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
+shipping/handling. The standard is divided into two parts, Part 1 being the
+actual specification, while Part 2 covers compliance testing methods. Part 1
+is titled "Digital Compression and Coding of Continuous-tone Still Images,
+Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
+10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
+Continuous-tone Still Images, Part 2: Compliance testing" and has document
+numbers ISO/IEC IS 10918-2, ITU-T T.83.
+
+Some extensions to the original JPEG standard are defined in JPEG Part 3,
+a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG
+currently does not support any Part 3 extensions.
+
+The JPEG standard does not specify all details of an interchangeable file
+format. For the omitted details we follow the "JFIF" conventions, revision
+1.02. A copy of the JFIF spec is available from:
+ Literature Department
+ C-Cube Microsystems, Inc.
+ 1778 McCarthy Blvd.
+ Milpitas, CA 95035
+ phone (408) 944-6300, fax (408) 944-6314
+A PostScript version of this document is available by FTP at
+ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text
+version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
+the figures.
+
+The TIFF 6.0 file format specification can be obtained by FTP from
+ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
+found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
+IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
+Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
+(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or
+from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision
+of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
+Although IJG's own code does not support TIFF/JPEG, the free libtiff library
+uses our library to implement TIFF/JPEG per the Note. libtiff is available
+from ftp://ftp.sgi.com/graphics/tiff/.
+
+
+ARCHIVE LOCATIONS
+=================
+
+The "official" archive site for this software is ftp.uu.net (Internet
+address 192.48.96.9). The most recent released version can always be found
+there in directory graphics/jpeg. This particular version will be archived
+as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have
+direct Internet access, UUNET's archives are also available via UUCP; contact
+help@uunet.uu.net for information on retrieving files that way.
+
+Numerous Internet sites maintain copies of the UUNET files. However, only
+ftp.uu.net is guaranteed to have the latest official version.
+
+You can also obtain this software in DOS-compatible "zip" archive format from
+the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
+on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
+"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net
+release.
+
+The JPEG FAQ (Frequently Asked Questions) article is a useful source of
+general information about JPEG. It is updated constantly and therefore is
+not included in this distribution. The FAQ is posted every two weeks to
+Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
+It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
+and other news.answers archive sites, including the official news.answers
+archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
+If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
+with body
+ send usenet/news.answers/jpeg-faq/part1
+ send usenet/news.answers/jpeg-faq/part2
+
+
+RELATED SOFTWARE
+================
+
+Numerous viewing and image manipulation programs now support JPEG. (Quite a
+few of them use this library to do so.) The JPEG FAQ described above lists
+some of the more popular free and shareware viewers, and tells where to
+obtain them on Internet.
+
+If you are on a Unix machine, we highly recommend Jef Poskanzer's free
+PBMPLUS software, which provides many useful operations on PPM-format image
+files. In particular, it can convert PPM images to and from a wide range of
+other formats, thus making cjpeg/djpeg considerably more useful. The latest
+version is distributed by the NetPBM group, and is available from numerous
+sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
+Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
+you are likely to have difficulty making it work on any non-Unix machine.
+
+A different free JPEG implementation, written by the PVRG group at Stanford,
+is available from ftp://havefun.stanford.edu/pub/jpeg/. This program
+is designed for research and experimentation rather than production use;
+it is slower, harder to use, and less portable than the IJG code, but it
+is easier to read and modify. Also, the PVRG code supports lossless JPEG,
+which we do not. (On the other hand, it doesn't do progressive JPEG.)
+
+
+FILE FORMAT WARS
+================
+
+Some JPEG programs produce files that are not compatible with our library.
+The root of the problem is that the ISO JPEG committee failed to specify a
+concrete file format. Some vendors "filled in the blanks" on their own,
+creating proprietary formats that no one else could read. (For example, none
+of the early commercial JPEG implementations for the Macintosh were able to
+exchange compressed files.)
+
+The file format we have adopted is called JFIF (see REFERENCES). This format
+has been agreed to by a number of major commercial JPEG vendors, and it has
+become the de facto standard. JFIF is a minimal or "low end" representation.
+We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
+Technical Note #2) for "high end" applications that need to record a lot of
+additional data about an image. TIFF/JPEG is fairly new and not yet widely
+supported, unfortunately.
+
+The upcoming JPEG Part 3 standard defines a file format called SPIFF.
+SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
+be able to read the most common variant of SPIFF. SPIFF has some technical
+advantages over JFIF, but its major claim to fame is simply that it is an
+official standard rather than an informal one. At this point it is unclear
+whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
+standard. IJG intends to support SPIFF once the standard is frozen, but we
+have not decided whether it should become our default output format or not.
+(In any case, our decoder will remain capable of reading JFIF indefinitely.)
+
+Various proprietary file formats incorporating JPEG compression also exist.
+We have little or no sympathy for the existence of these formats. Indeed,
+one of the original reasons for developing this free software was to help
+force convergence on common, open format standards for JPEG files. Don't
+use a proprietary file format!
+
+
+TO DO
+=====
+
+The major thrust for v7 will probably be improvement of visual quality.
+The current method for scaling the quantization tables is known not to be
+very good at low Q values. We also intend to investigate block boundary
+smoothing, "poor man's variable quantization", and other means of improving
+quality-vs-file-size performance without sacrificing compatibility.
+
+In future versions, we are considering supporting some of the upcoming JPEG
+Part 3 extensions --- principally, variable quantization and the SPIFF file
+format.
+
+As always, speeding things up is of great interest.
+
+Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
diff --git a/kipi-plugins/jpeglossless/mtqueue.h b/kipi-plugins/jpeglossless/mtqueue.h
new file mode 100644
index 0000000..209ade5
--- /dev/null
+++ b/kipi-plugins/jpeglossless/mtqueue.h
@@ -0,0 +1,89 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-11-09
+ * Description : Multithread queue description class
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 MTQUEUE_H
+#define MTQUEUE_H
+
+// Qt includes.
+
+#include <qptrqueue.h>
+#include <qmutex.h>
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+template<class Type> class MTQueue
+{
+
+public:
+
+ MTQueue()
+ {
+ m_queue.setAutoDelete(true);
+ }
+
+ ~MTQueue()
+ {
+ flush();
+ }
+
+ bool isEmpty()
+ {
+ m_mutex.lock();
+ bool empty = m_queue.isEmpty();
+ m_mutex.unlock();
+ return empty;
+ }
+
+ void flush()
+ {
+ m_mutex.lock();
+ m_queue.clear();
+ m_mutex.unlock();
+ }
+
+ void enqueue(Type * t)
+ {
+ m_mutex.lock();
+ m_queue.enqueue(t);
+ m_mutex.unlock();
+ }
+
+ Type * dequeue()
+ {
+ m_mutex.lock();
+ Type * i = m_queue.dequeue();
+ m_mutex.unlock();
+ return i;
+ }
+
+private:
+
+ QPtrQueue<Type> m_queue;
+ QMutex m_mutex;
+};
+
+} // NameSpace KIPIJPEGLossLessPlugin
+
+#endif // MTQUEUE_H
diff --git a/kipi-plugins/jpeglossless/pics/Makefile.am b/kipi-plugins/jpeglossless/pics/Makefile.am
new file mode 100644
index 0000000..e4d300f
--- /dev/null
+++ b/kipi-plugins/jpeglossless/pics/Makefile.am
@@ -0,0 +1,2 @@
+kipijpeglosslessicondir = $(kde_datadir)/kipiplugin_jpeglossless/icons
+kipijpeglosslessicon_ICON = AUTO
diff --git a/kipi-plugins/jpeglossless/pics/hi32-action-flip.png b/kipi-plugins/jpeglossless/pics/hi32-action-flip.png
new file mode 100644
index 0000000..c52a523
--- /dev/null
+++ b/kipi-plugins/jpeglossless/pics/hi32-action-flip.png
Binary files differ
diff --git a/kipi-plugins/jpeglossless/pics/hi32-action-grayscaleconvert.png b/kipi-plugins/jpeglossless/pics/hi32-action-grayscaleconvert.png
new file mode 100644
index 0000000..e586be8
--- /dev/null
+++ b/kipi-plugins/jpeglossless/pics/hi32-action-grayscaleconvert.png
Binary files differ
diff --git a/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp b/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp
new file mode 100644
index 0000000..71fd86e
--- /dev/null
+++ b/kipi-plugins/jpeglossless/plugin_jpeglossless.cpp
@@ -0,0 +1,503 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-09-26
+ * Description : loss less images transformations plugin.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <iostream>
+
+// Qt includes.
+
+#include <qdir.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+
+// LibKipi includes.
+
+#include <libkipi/batchprogressdialog.h>
+#include <libkipi/interface.h>
+
+// Local includes.
+
+#include "actions.h"
+#include "actionthread.h"
+#include "plugin_jpeglossless.h"
+#include "plugin_jpeglossless.moc"
+
+typedef KGenericFactory<Plugin_JPEGLossless> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_jpeglossless,
+ Factory("kipiplugin_jpeglossless"))
+
+Plugin_JPEGLossless::Plugin_JPEGLossless(QObject *parent, const char*, const QStringList &)
+ : KIPI::Plugin( Factory::instance(), parent, "JPEGLossless")
+{
+ m_total = 0;
+ m_current = 0;
+ m_action_Convert2GrayScale = 0;
+ m_action_AutoExif = 0;
+ m_action_RotateImage = 0;
+ m_action_FlipImage = 0;
+ m_progressDlg = 0;
+ m_thread = 0;
+ m_failed = false;
+
+ kdDebug( 51001 ) << "Plugin_JPEGLossless plugin loaded" << endl;
+}
+
+void Plugin_JPEGLossless::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_action_AutoExif = new KAction(i18n("Auto Rotate/Flip Using Exif Information"),
+ 0, 0,
+ this,
+ SLOT(slotRotate()),
+ actionCollection(),
+ "rotate_exif");
+
+ m_action_RotateImage = new KActionMenu(i18n("Rotate"),
+ "rotate_cw",
+ actionCollection(),
+ "jpeglossless_rotate");
+
+ m_action_RotateImage->insert( new KAction(i18n("Left"),
+ "rotate_ccw",
+ SHIFT+CTRL+Key_Left,
+ this,
+ SLOT(slotRotate()),
+ actionCollection(),
+ "rotate_ccw") );
+ m_action_RotateImage->insert( new KAction(i18n("Right"),
+ "rotate_cw",
+ SHIFT+CTRL+Key_Right,
+ this,
+ SLOT(slotRotate()),
+ actionCollection(),
+ "rotate_cw") );
+
+ m_action_FlipImage = new KActionMenu(i18n("Flip"),
+ "flip",
+ actionCollection(),
+ "jpeglossless_flip");
+
+ m_action_FlipImage->insert( new KAction(i18n("Horizontally"),
+ 0,
+ CTRL+Key_Asterisk,
+ this,
+ SLOT(slotFlip()),
+ actionCollection(),
+ "flip_horizontal") );
+
+ m_action_FlipImage->insert( new KAction(i18n("Vertically"),
+ 0,
+ CTRL+Key_Slash,
+ this,
+ SLOT(slotFlip()),
+ actionCollection(),
+ "flip_vertical") );
+
+ m_action_Convert2GrayScale = new KAction(i18n("Convert to Black && White"),
+ "grayscaleconvert",
+ 0,
+ this,
+ SLOT(slotConvert2GrayScale()),
+ actionCollection(),
+ "jpeglossless_convert2grayscale");
+
+ addAction( m_action_AutoExif );
+ addAction( m_action_RotateImage );
+ addAction( m_action_FlipImage );
+ addAction( m_action_Convert2GrayScale );
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ m_action_AutoExif->setEnabled( false );
+ m_action_RotateImage->setEnabled( false );
+ m_action_FlipImage->setEnabled( false );
+ m_action_Convert2GrayScale->setEnabled( false );
+
+ m_thread = new KIPIJPEGLossLessPlugin::ActionThread(interface, this);
+
+ connect( interface, SIGNAL( selectionChanged( bool ) ),
+ m_action_AutoExif, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( selectionChanged( bool ) ),
+ m_action_RotateImage, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( selectionChanged( bool ) ),
+ m_action_FlipImage, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( selectionChanged( bool ) ),
+ m_action_Convert2GrayScale, SLOT( setEnabled( bool ) ) );
+}
+
+Plugin_JPEGLossless::~Plugin_JPEGLossless()
+{
+ delete m_thread;
+ delete m_progressDlg;
+}
+
+void Plugin_JPEGLossless::slotFlip()
+{
+ KURL::List items = images();
+ if (items.count() <= 0) return;
+
+ QString from(sender()->name());
+ QString title;
+ bool proceed = false;
+
+ if (from == "flip_horizontal")
+ {
+ m_thread->flip(items, KIPIJPEGLossLessPlugin::FlipHorizontal);
+ title = i18n("horizontaly");
+ proceed = true;
+ }
+ else if (from == "flip_vertical")
+ {
+ m_thread->flip(items, KIPIJPEGLossLessPlugin::FlipVertical);
+ title = i18n("vertically");
+ proceed = true;
+ }
+ else
+ {
+ kdWarning( 51000 ) << "The impossible happened... unknown flip specified" << endl;
+ return;
+ }
+
+ if (!proceed) return;
+ m_total = items.count();
+ m_current = 0;
+ m_failed = false;
+
+ if (m_progressDlg)
+ {
+ delete m_progressDlg;
+ m_progressDlg = 0;
+ }
+
+ m_progressDlg = new KIPI::BatchProgressDialog(kapp->activeWindow(),
+ i18n("Flip images %1").arg(title));
+
+ connect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+
+ m_progressDlg->show();
+
+ if (!m_thread->running())
+ m_thread->start();
+}
+
+void Plugin_JPEGLossless::slotRotate()
+{
+ KURL::List items = images();
+ if (items.count() <= 0) return;
+
+ QString from(sender()->name());
+ QString title;
+ bool proceed = false;
+
+ if (from == "rotate_cw")
+ {
+ m_thread->rotate(items, KIPIJPEGLossLessPlugin::Rot90);
+ title = i18n("right (clockwise)");
+ proceed = true;
+ }
+ else if (from == "rotate_ccw")
+ {
+ m_thread->rotate(items, KIPIJPEGLossLessPlugin::Rot270);
+ title = i18n("left (counterclockwise)");
+ proceed = true;
+ }
+ else if (from == "rotate_exif")
+ {
+ m_thread->rotate(items, KIPIJPEGLossLessPlugin::Rot0);
+ title = i18n("using Exif orientation tag");
+ proceed = true;
+ }
+ else
+ {
+ kdWarning( 51000 ) << "The impossible happened... unknown rotation angle specified" << endl;
+ return;
+ }
+
+ if (!proceed) return;
+ m_total = items.count();
+ m_current = 0;
+ m_failed = false;
+
+ if (m_progressDlg)
+ {
+ delete m_progressDlg;
+ m_progressDlg = 0;
+ }
+
+ m_progressDlg = new KIPI::BatchProgressDialog(kapp->activeWindow(),
+ i18n("Rotate images %1").arg(title));
+
+ connect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+
+ m_progressDlg->show();
+
+ if (!m_thread->running())
+ m_thread->start();
+}
+
+void Plugin_JPEGLossless::slotConvert2GrayScale()
+{
+ KURL::List items = images();
+ if (items.count() <= 0 ||
+ KMessageBox::No==KMessageBox::warningYesNo(kapp->activeWindow(),
+ i18n("<p>Are you sure you wish to convert the selected image(s) to "
+ "black and white? This operation <b>cannot</b> be undone.</p>")))
+ return;
+
+ QString from(sender()->name());
+
+ m_total = items.count();
+ m_current = 0;
+ m_failed = false;
+
+ if (m_progressDlg)
+ {
+ delete m_progressDlg;
+ m_progressDlg = 0;
+ }
+
+ m_progressDlg = new KIPI::BatchProgressDialog(kapp->activeWindow(),
+ i18n("Convert images to black & white"));
+
+ connect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+
+ m_progressDlg->show();
+
+ m_thread->convert2grayscale(items);
+ if (!m_thread->running())
+ m_thread->start();
+}
+
+void Plugin_JPEGLossless::slotCancel()
+{
+ m_thread->cancel();
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ interface->refreshImages( m_images );
+}
+
+void Plugin_JPEGLossless::customEvent(QCustomEvent *event)
+{
+ if (!event) return;
+
+ KIPIJPEGLossLessPlugin::EventData *d = (KIPIJPEGLossLessPlugin::EventData*) event->data();
+ if (!d) return;
+
+ QString text;
+
+ if (d->starting)
+ {
+ switch (d->action)
+ {
+ case(KIPIJPEGLossLessPlugin::Rotate):
+ {
+ text = i18n("Rotating Image \"%1\"").arg(d->fileName.section('/', -1));
+ break;
+ }
+ case(KIPIJPEGLossLessPlugin::Flip):
+ {
+ text = i18n("Flipping Image \"%1\"").arg(d->fileName.section('/', -1));
+ break;
+ }
+ case(KIPIJPEGLossLessPlugin::GrayScale):
+ {
+ text = i18n("Converting to Black & White \"%1\"").arg(d->fileName.section('/', -1));
+ break;
+ }
+ default:
+ {
+ kdWarning( 51000 ) << "KIPIJPEGLossLessPlugin: Unknown event" << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::StartingMessage);
+ }
+ else
+ {
+ if (!d->success)
+ {
+ m_failed = true;
+
+ switch (d->action)
+ {
+ case(KIPIJPEGLossLessPlugin::Rotate):
+ {
+ text = i18n("Failed to Rotate image");
+ break;
+ }
+ case(KIPIJPEGLossLessPlugin::Flip):
+ {
+ text = i18n("Failed to Flip image");
+ break;
+ }
+ case(KIPIJPEGLossLessPlugin::GrayScale):
+ {
+ text = i18n("Failed to convert image to Black & White");
+ break;
+ }
+ default:
+ {
+ kdWarning( 51000 ) << "KIPIJPEGLossLessPlugin: Unknown event" << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::WarningMessage);
+
+ if (!d->errString.isEmpty())
+ m_progressDlg->addedAction(d->errString, KIPI::WarningMessage);
+ }
+ else
+ {
+ switch (d->action)
+ {
+ case(KIPIJPEGLossLessPlugin::Rotate):
+ {
+ text = i18n("Rotate image complete");
+ break;
+ }
+ case(KIPIJPEGLossLessPlugin::Flip):
+ {
+ text = i18n("Flip image complete");
+ break;
+ }
+ case(KIPIJPEGLossLessPlugin::GrayScale):
+ {
+ text = i18n("Convert to Black & White complete");
+ break;
+ }
+ default:
+ {
+ kdWarning( 51000 ) << "KIPIJPEGLossLessPlugin: Unknown event" << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::SuccessMessage);
+ }
+
+ m_current++;
+ m_progressDlg->setProgress(m_current, m_total);
+ }
+
+ delete d;
+
+ if (m_current >= m_total)
+ {
+ m_current = 0;
+
+ if (m_failed)
+ {
+#if KDE_VERSION >= 0x30200
+ m_progressDlg->setButtonCancel( KStdGuiItem::close() );
+#else
+ m_progressDlg->setButtonCancelText( i18n("&Close") );
+#endif
+
+ disconnect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+ }
+ else
+ {
+ slotCancel();
+ m_progressDlg->close();
+ m_progressDlg = 0;
+ }
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ interface->refreshImages( m_images );
+ }
+}
+
+KIPI::Category Plugin_JPEGLossless::category( KAction* action ) const
+{
+ if (action == m_action_AutoExif)
+ return KIPI::IMAGESPLUGIN;
+ else if ( action == m_action_RotateImage )
+ return KIPI::IMAGESPLUGIN;
+ else if ( action == m_action_FlipImage )
+ return KIPI::IMAGESPLUGIN;
+ else if ( action == m_action_Convert2GrayScale )
+ return KIPI::IMAGESPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMAGESPLUGIN; // no warning from compiler, please
+}
+
+KURL::List Plugin_JPEGLossless::images()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return KURL::List();
+ }
+
+ KIPI::ImageCollection images = interface->currentSelection();
+ if ( !images.isValid() )
+ return KURL::List();
+
+ // We don't want the set of images to change before we are done
+ // and tells the host app to refresh the images.
+ m_images = images.images();
+ return images.images();
+}
diff --git a/kipi-plugins/jpeglossless/plugin_jpeglossless.h b/kipi-plugins/jpeglossless/plugin_jpeglossless.h
new file mode 100644
index 0000000..71dd22c
--- /dev/null
+++ b/kipi-plugins/jpeglossless/plugin_jpeglossless.h
@@ -0,0 +1,87 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-09-26
+ * Description : loss less images transformations plugin.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_JPEGLOSSLESS_H
+#define PLUGIN_JPEGLOSSLESS_H
+
+// LibKipi includes.
+
+#include <libkipi/plugin.h>
+#include <libkipi/imagecollection.h>
+
+class QCustomEvent;
+class KActionMenu;
+class KAction;
+
+namespace KIPIJPEGLossLessPlugin
+{
+class ActionThread;
+class ProgressDlg;
+}
+
+class Plugin_JPEGLossless : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_JPEGLossless(QObject *parent, const char* name, const QStringList &args);
+ ~Plugin_JPEGLossless();
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+protected:
+
+ void customEvent(QCustomEvent *event);
+ KURL::List images();
+
+private slots:
+
+ void slotRotate();
+ void slotFlip();
+ void slotConvert2GrayScale();
+ void slotCancel();
+
+private:
+
+ bool m_failed;
+
+ int m_total;
+ int m_current;
+
+ KAction *m_action_Convert2GrayScale;
+ KAction *m_action_AutoExif;
+
+ KActionMenu *m_action_RotateImage;
+ KActionMenu *m_action_FlipImage;
+
+ KURL::List m_images;
+
+ KIPI::BatchProgressDialog *m_progressDlg;
+
+ KIPIJPEGLossLessPlugin::ActionThread *m_thread;
+};
+
+#endif /* PLUGIN_JPEGLOSSLESS_H */
diff --git a/kipi-plugins/jpeglossless/transupp.cpp b/kipi-plugins/jpeglossless/transupp.cpp
new file mode 100644
index 0000000..6552364
--- /dev/null
+++ b/kipi-plugins/jpeglossless/transupp.cpp
@@ -0,0 +1,940 @@
+/*
+ * transupp.c
+ *
+ * Copyright (C) 1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains image transformation routines and other utility code
+ * used by the jpegtran sample application. These are NOT part of the core
+ * JPEG library. But we keep these routines separate from jpegtran.c to
+ * ease the task of maintaining jpegtran-like programs that have other user
+ * interfaces.
+ */
+
+/* Although this file really shouldn't have access to the library internals,
+ * it's helpful to let it call jround_up() and jcopy_block_row().
+ */
+#define JPEG_INTERNALS
+
+// LibJPEG includes.
+
+extern "C"
+{
+#include "jinclude.h"
+#include "jpeglib.h"
+}
+
+// Local includes.
+
+#include "transupp.h" /* My own external interface */
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+#if TRANSFORMS_SUPPORTED
+
+/*
+ * Lossless image transformation routines. These routines work on DCT
+ * coefficient arrays and thus do not require any lossy decompression
+ * or recompression of the image.
+ * Thanks to Guido Vollbeding for the initial design and code of this feature.
+ *
+ * Horizontal flipping is done in-place, using a single top-to-bottom
+ * pass through the virtual source array. It will thus be much the
+ * fastest option for images larger than main memory.
+ *
+ * The other routines require a set of destination virtual arrays, so they
+ * need twice as much memory as jpegtran normally does. The destination
+ * arrays are always written in normal scan order (top to bottom) because
+ * the virtual array manager expects this. The source arrays will be scanned
+ * in the corresponding order, which means multiple passes through the source
+ * arrays for most of the transforms. That could result in much thrashing
+ * if the image is larger than main memory.
+ *
+ * Some notes about the operating environment of the individual transform
+ * routines:
+ * 1. Both the source and destination virtual arrays are allocated from the
+ * source JPEG object, and therefore should be manipulated by calling the
+ * source's memory manager.
+ * 2. The destination's component count should be used. It may be smaller
+ * than the source's when forcing to grayscale.
+ * 3. Likewise the destination's sampling factors should be used. When
+ * forcing to grayscale the destination's sampling factors will be all 1,
+ * and we may as well take that as the effective iMCU size.
+ * 4. When "trim" is in effect, the destination's dimensions will be the
+ * trimmed values but the source's will be untrimmed.
+ * 5. All the routines assume that the source and destination buffers are
+ * padded out to a full iMCU boundary. This is true, although for the
+ * source buffer it is an undocumented property of jdcoefct.c.
+ * Notes 2,3,4 boil down to this: generally we should use the destination's
+ * dimensions and ignore the source's.
+ */
+
+
+LOCAL(void)
+do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays)
+/* Horizontal flip; done in-place, so no separate dest array is required */
+{
+ JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
+ int ci, k, offset_y;
+ JBLOCKARRAY buffer;
+ JCOEFPTR ptr1, ptr2;
+ JCOEF temp1, temp2;
+ jpeg_component_info *compptr;
+
+ /* Horizontal mirroring of DCT blocks is accomplished by swapping
+ * pairs of blocks in-place. Within a DCT block, we perform horizontal
+ * mirroring by changing the signs of odd-numbered columns.
+ * Partial iMCUs at the right edge are left untouched.
+ */
+ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ for (blk_y = 0; blk_y < compptr->height_in_blocks;
+ blk_y += compptr->v_samp_factor) {
+ buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
+ ptr1 = buffer[offset_y][blk_x];
+ ptr2 = buffer[offset_y][comp_width - blk_x - 1];
+ /* this unrolled loop doesn't need to know which row it's on... */
+ for (k = 0; k < DCTSIZE2; k += 2) {
+ temp1 = *ptr1; /* swap even column */
+ temp2 = *ptr2;
+ *ptr1++ = temp2;
+ *ptr2++ = temp1;
+ temp1 = *ptr1; /* swap odd column with sign change */
+ temp2 = *ptr2;
+ *ptr1++ = -temp2;
+ *ptr2++ = -temp1;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Vertical flip */
+{
+ JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JBLOCKROW src_row_ptr, dst_row_ptr;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* We output into a separate array because we can't touch different
+ * rows of the source virtual array simultaneously. Otherwise, this
+ * is a pretty straightforward analog of horizontal flip.
+ * Within a DCT block, vertical mirroring is done by changing the signs
+ * of odd-numbered rows.
+ * Partial iMCUs at the bottom edge are copied verbatim.
+ */
+ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ if (dst_blk_y < comp_height) {
+ /* Row is within the mirrorable area. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ } else {
+ /* Bottom-edge blocks will be copied verbatim. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ if (dst_blk_y < comp_height) {
+ /* Row is within the mirrorable area. */
+ dst_row_ptr = dst_buffer[offset_y];
+ src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[dst_blk_x];
+ for (i = 0; i < DCTSIZE; i += 2) {
+ /* copy even row */
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = *src_ptr++;
+ /* copy odd row with sign change */
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = - *src_ptr++;
+ }
+ }
+ } else {
+ /* Just copy row verbatim. */
+ jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
+ compptr->width_in_blocks);
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Transpose source into destination */
+{
+ JDIMENSION dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Transposing pixels within a block just requires transposing the
+ * DCT coefficients.
+ * Partial iMCUs at the edges require no special treatment; we simply
+ * process all the available DCT blocks for every component.
+ */
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* 90 degree rotation is equivalent to
+ * 1. Transposing the image;
+ * 2. Horizontal mirroring.
+ * These two steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Because of the horizontal mirror step, we can't process partial iMCUs
+ * at the (output) right edge properly. They just get transposed and
+ * not mirrored.
+ */
+ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+ if (dst_blk_x < comp_width) {
+ /* Block is within the mirrorable area. */
+ dst_ptr = dst_buffer[offset_y]
+ [comp_width - dst_blk_x - offset_x - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ i++;
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ } else {
+ /* Edge blocks are transposed but not mirrored. */
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* 270 degree rotation is equivalent to
+ * 1. Horizontal mirroring;
+ * 2. Transposing the image.
+ * These two steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Because of the horizontal mirror step, we can't process partial iMCUs
+ * at the (output) bottom edge properly. They just get transposed and
+ * not mirrored.
+ */
+ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ if (dst_blk_y < comp_height) {
+ /* Block is within the mirrorable area. */
+ src_ptr = src_buffer[offset_x]
+ [comp_height - dst_blk_y - offset_y - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ }
+ } else {
+ /* Edge blocks are transposed but not mirrored. */
+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* 180 degree rotation is equivalent to
+ * 1. Vertical mirroring;
+ * 2. Horizontal mirroring.
+ * These two steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JBLOCKROW src_row_ptr, dst_row_ptr;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ if (dst_blk_y < comp_height) {
+ /* Row is within the vertically mirrorable area. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ } else {
+ /* Bottom-edge rows are only mirrored horizontally. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ if (dst_blk_y < comp_height) {
+ /* Row is within the mirrorable area. */
+ dst_row_ptr = dst_buffer[offset_y];
+ src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
+ /* Process the blocks that can be mirrored both ways. */
+ for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
+ for (i = 0; i < DCTSIZE; i += 2) {
+ /* For even row, negate every odd column. */
+ for (j = 0; j < DCTSIZE; j += 2) {
+ *dst_ptr++ = *src_ptr++;
+ *dst_ptr++ = - *src_ptr++;
+ }
+ /* For odd row, negate every even column. */
+ for (j = 0; j < DCTSIZE; j += 2) {
+ *dst_ptr++ = - *src_ptr++;
+ *dst_ptr++ = *src_ptr++;
+ }
+ }
+ }
+ /* Any remaining right-edge blocks are only mirrored vertically. */
+ for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[dst_blk_x];
+ for (i = 0; i < DCTSIZE; i += 2) {
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = *src_ptr++;
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = - *src_ptr++;
+ }
+ }
+ } else {
+ /* Remaining rows are just mirrored horizontally. */
+ dst_row_ptr = dst_buffer[offset_y];
+ src_row_ptr = src_buffer[offset_y];
+ /* Process the blocks that can be mirrored. */
+ for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
+ for (i = 0; i < DCTSIZE2; i += 2) {
+ *dst_ptr++ = *src_ptr++;
+ *dst_ptr++ = - *src_ptr++;
+ }
+ }
+ /* Any remaining right-edge blocks are only copied. */
+ for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[dst_blk_x];
+ for (i = 0; i < DCTSIZE2; i++)
+ *dst_ptr++ = *src_ptr++;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Transverse transpose is equivalent to
+ * 1. 180 degree rotation;
+ * 2. Transposition;
+ * or
+ * 1. Horizontal mirroring;
+ * 2. Transposition;
+ * 3. Horizontal mirroring.
+ * These steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ if (dst_blk_y < comp_height) {
+ src_ptr = src_buffer[offset_x]
+ [comp_height - dst_blk_y - offset_y - 1];
+ if (dst_blk_x < comp_width) {
+ /* Block is within the mirrorable area. */
+ dst_ptr = dst_buffer[offset_y]
+ [comp_width - dst_blk_x - offset_x - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ i++;
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ } else {
+ /* Right-edge blocks are mirrored in y only */
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ } else {
+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+ if (dst_blk_x < comp_width) {
+ /* Bottom-edge blocks are mirrored in x only */
+ dst_ptr = dst_buffer[offset_y]
+ [comp_width - dst_blk_x - offset_x - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ i++;
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ } else {
+ /* At lower right corner, just transpose, no mirroring */
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/* Request any required workspace.
+ *
+ * We allocate the workspace virtual arrays from the source decompression
+ * object, so that all the arrays (both the original data and the workspace)
+ * will be taken into account while making memory management decisions.
+ * Hence, this routine must be called after jpeg_read_header (which reads
+ * the image dimensions) and before jpeg_read_coefficients (which realizes
+ * the source's virtual arrays).
+ */
+
+GLOBAL(void)
+jtransform_request_workspace (j_decompress_ptr srcinfo,
+ jpeg_transform_info *info)
+{
+ jvirt_barray_ptr *coef_arrays = NULL;
+ jpeg_component_info *compptr;
+ int ci;
+
+ if (info->force_grayscale &&
+ srcinfo->jpeg_color_space == JCS_YCbCr &&
+ srcinfo->num_components == 3) {
+ /* We'll only process the first component */
+ info->num_components = 1;
+ } else {
+ /* Process all the components */
+ info->num_components = srcinfo->num_components;
+ }
+
+ switch (info->transform) {
+ case JXFORM_NONE:
+ case JXFORM_FLIP_H:
+ /* Don't need a workspace array */
+ break;
+ case JXFORM_FLIP_V:
+ case JXFORM_ROT_180:
+ /* Need workspace arrays having same dimensions as source image.
+ * Note that we allocate arrays padded out to the next iMCU boundary,
+ * so that transform routines need not worry about missing edge blocks.
+ */
+ coef_arrays = (jvirt_barray_ptr *)
+ (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
+ SIZEOF(jvirt_barray_ptr) * info->num_components);
+ for (ci = 0; ci < info->num_components; ci++) {
+ compptr = srcinfo->comp_info + ci;
+ coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
+ ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) jround_up((long) compptr->width_in_blocks,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) compptr->v_samp_factor);
+ }
+ break;
+ case JXFORM_TRANSPOSE:
+ case JXFORM_TRANSVERSE:
+ case JXFORM_ROT_90:
+ case JXFORM_ROT_270:
+ /* Need workspace arrays having transposed dimensions.
+ * Note that we allocate arrays padded out to the next iMCU boundary,
+ * so that transform routines need not worry about missing edge blocks.
+ */
+ coef_arrays = (jvirt_barray_ptr *)
+ (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
+ SIZEOF(jvirt_barray_ptr) * info->num_components);
+ for (ci = 0; ci < info->num_components; ci++) {
+ compptr = srcinfo->comp_info + ci;
+ coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
+ ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->width_in_blocks,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) compptr->h_samp_factor);
+ }
+ break;
+ }
+ info->workspace_coef_arrays = coef_arrays;
+}
+
+
+/* Transpose destination image parameters */
+
+LOCAL(void)
+transpose_critical_parameters (j_compress_ptr dstinfo)
+{
+ int tblno, i, j, ci, itemp;
+ jpeg_component_info *compptr;
+ JQUANT_TBL *qtblptr;
+ JDIMENSION dtemp;
+ UINT16 qtemp;
+
+ /* Transpose basic image dimensions */
+ dtemp = dstinfo->image_width;
+ dstinfo->image_width = dstinfo->image_height;
+ dstinfo->image_height = dtemp;
+
+ /* Transpose sampling factors */
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ itemp = compptr->h_samp_factor;
+ compptr->h_samp_factor = compptr->v_samp_factor;
+ compptr->v_samp_factor = itemp;
+ }
+
+ /* Transpose quantization tables */
+ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
+ qtblptr = dstinfo->quant_tbl_ptrs[tblno];
+ if (qtblptr != NULL) {
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < i; j++) {
+ qtemp = qtblptr->quantval[i*DCTSIZE+j];
+ qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
+ qtblptr->quantval[j*DCTSIZE+i] = qtemp;
+ }
+ }
+ }
+ }
+}
+
+
+/* Trim off any partial iMCUs on the indicated destination edge */
+
+LOCAL(void)
+trim_right_edge (j_compress_ptr dstinfo)
+{
+ int ci, max_h_samp_factor;
+ JDIMENSION MCU_cols;
+
+ /* We have to compute max_h_samp_factor ourselves,
+ * because it hasn't been set yet in the destination
+ * (and we don't want to use the source's value).
+ */
+ max_h_samp_factor = 1;
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
+ max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
+ }
+ MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
+ if (MCU_cols > 0) /* can't trim to 0 pixels */
+ dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
+}
+
+LOCAL(void)
+trim_bottom_edge (j_compress_ptr dstinfo)
+{
+ int ci, max_v_samp_factor;
+ JDIMENSION MCU_rows;
+
+ /* We have to compute max_v_samp_factor ourselves,
+ * because it hasn't been set yet in the destination
+ * (and we don't want to use the source's value).
+ */
+ max_v_samp_factor = 1;
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
+ max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
+ }
+ MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
+ if (MCU_rows > 0) /* can't trim to 0 pixels */
+ dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
+}
+
+
+/* Adjust output image parameters as needed.
+ *
+ * This must be called after jpeg_copy_critical_parameters()
+ * and before jpeg_write_coefficients().
+ *
+ * The return value is the set of virtual coefficient arrays to be written
+ * (either the ones allocated by jtransform_request_workspace, or the
+ * original source data arrays). The caller will need to pass this value
+ * to jpeg_write_coefficients().
+ */
+
+GLOBAL(jvirt_barray_ptr *)
+jtransform_adjust_parameters (j_decompress_ptr /*srcinfo*/,
+ j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info)
+{
+ /* If force-to-grayscale is requested, adjust destination parameters */
+ if (info->force_grayscale) {
+ /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
+ * properly. Among other things, the target h_samp_factor & v_samp_factor
+ * will get set to 1, which typically won't match the source.
+ * In fact we do this even if the source is already grayscale; that
+ * provides an easy way of coercing a grayscale JPEG with funny sampling
+ * factors to the customary 1,1. (Some decoders fail on other factors.)
+ */
+ if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
+ dstinfo->num_components == 3) ||
+ (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
+ dstinfo->num_components == 1)) {
+ /* We have to preserve the source's quantization table number. */
+ int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
+ jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
+ dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
+ } else {
+ /* Sorry, can't do it */
+ ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
+ }
+ }
+
+ /* Correct the destination's image dimensions etc if necessary */
+ switch (info->transform) {
+ case JXFORM_NONE:
+ /* Nothing to do */
+ break;
+ case JXFORM_FLIP_H:
+ if (info->trim)
+ trim_right_edge(dstinfo);
+ break;
+ case JXFORM_FLIP_V:
+ if (info->trim)
+ trim_bottom_edge(dstinfo);
+ break;
+ case JXFORM_TRANSPOSE:
+ transpose_critical_parameters(dstinfo);
+ /* transpose does NOT have to trim anything */
+ break;
+ case JXFORM_TRANSVERSE:
+ transpose_critical_parameters(dstinfo);
+ if (info->trim) {
+ trim_right_edge(dstinfo);
+ trim_bottom_edge(dstinfo);
+ }
+ break;
+ case JXFORM_ROT_90:
+ transpose_critical_parameters(dstinfo);
+ if (info->trim)
+ trim_right_edge(dstinfo);
+ break;
+ case JXFORM_ROT_180:
+ if (info->trim) {
+ trim_right_edge(dstinfo);
+ trim_bottom_edge(dstinfo);
+ }
+ break;
+ case JXFORM_ROT_270:
+ transpose_critical_parameters(dstinfo);
+ if (info->trim)
+ trim_bottom_edge(dstinfo);
+ break;
+ }
+
+ /* Return the appropriate output data set */
+ if (info->workspace_coef_arrays != NULL)
+ return info->workspace_coef_arrays;
+ return src_coef_arrays;
+}
+
+
+/* Execute the actual transformation, if any.
+ *
+ * This must be called *after* jpeg_write_coefficients, because it depends
+ * on jpeg_write_coefficients to have computed subsidiary values such as
+ * the per-component width and height fields in the destination object.
+ *
+ * Note that some transformations will modify the source data arrays!
+ */
+
+GLOBAL(void)
+jtransform_execute_transformation (j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info)
+{
+ jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
+
+ switch (info->transform) {
+ case JXFORM_NONE:
+ break;
+ case JXFORM_FLIP_H:
+ do_flip_h(srcinfo, dstinfo, src_coef_arrays);
+ break;
+ case JXFORM_FLIP_V:
+ do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_TRANSPOSE:
+ do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_TRANSVERSE:
+ do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_ROT_90:
+ do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_ROT_180:
+ do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_ROT_270:
+ do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ }
+}
+
+#endif /* TRANSFORMS_SUPPORTED */
+
+
+/* Setup decompression object to save desired markers in memory.
+ * This must be called before jpeg_read_header() to have the desired effect.
+ */
+
+GLOBAL(void)
+jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
+{
+#ifdef SAVE_MARKERS_SUPPORTED
+ int m;
+
+ /* Save comments except under NONE option */
+ if (option != JCOPYOPT_NONE) {
+ jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
+ }
+ /* Save all types of APPn markers iff ALL option */
+ if (option == JCOPYOPT_ALL) {
+ for (m = 0; m < 16; m++)
+ jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
+ }
+#endif /* SAVE_MARKERS_SUPPORTED */
+}
+
+/* Copy markers saved in the given source object to the destination object.
+ * This should be called just after jpeg_start_compress() or
+ * jpeg_write_coefficients().
+ * Note that those routines will have written the SOI, and also the
+ * JFIF APP0 or Adobe APP14 markers if selected.
+ */
+
+GLOBAL(void)
+jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JCOPY_OPTION /*option*/)
+{
+ jpeg_saved_marker_ptr marker;
+
+ /* In the current implementation, we don't actually need to examine the
+ * option flag here; we just copy everything that got saved.
+ * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
+ * if the encoder library already wrote one.
+ */
+ for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
+ if (dstinfo->write_JFIF_header &&
+ marker->marker == JPEG_APP0 &&
+ marker->data_length >= 5 &&
+ GETJOCTET(marker->data[0]) == 0x4A &&
+ GETJOCTET(marker->data[1]) == 0x46 &&
+ GETJOCTET(marker->data[2]) == 0x49 &&
+ GETJOCTET(marker->data[3]) == 0x46 &&
+ GETJOCTET(marker->data[4]) == 0)
+ continue; /* reject duplicate JFIF */
+ if (dstinfo->write_Adobe_marker &&
+ marker->marker == JPEG_APP0+14 &&
+ marker->data_length >= 5 &&
+ GETJOCTET(marker->data[0]) == 0x41 &&
+ GETJOCTET(marker->data[1]) == 0x64 &&
+ GETJOCTET(marker->data[2]) == 0x6F &&
+ GETJOCTET(marker->data[3]) == 0x62 &&
+ GETJOCTET(marker->data[4]) == 0x65)
+ continue; /* reject duplicate Adobe */
+#ifdef NEED_FAR_POINTERS
+ /* We could use jpeg_write_marker if the data weren't FAR... */
+ {
+ unsigned int i;
+ jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
+ for (i = 0; i < marker->data_length; i++)
+ jpeg_write_m_byte(dstinfo, marker->data[i]);
+ }
+#else
+ jpeg_write_marker(dstinfo, marker->marker,
+ marker->data, marker->data_length);
+#endif
+ }
+}
+
+} // namespace KIPIJPEGLossLessPlugin
diff --git a/kipi-plugins/jpeglossless/transupp.h b/kipi-plugins/jpeglossless/transupp.h
new file mode 100644
index 0000000..6f6b7fa
--- /dev/null
+++ b/kipi-plugins/jpeglossless/transupp.h
@@ -0,0 +1,145 @@
+/*
+ * transupp.h
+ *
+ * Copyright (C) 1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for image transformation routines and
+ * other utility code used by the jpegtran sample application. These are
+ * NOT part of the core JPEG library. But we keep these routines separate
+ * from jpegtran.c to ease the task of maintaining jpegtran-like programs
+ * that have other user interfaces.
+ *
+ * NOTE: all the routines declared here have very specific requirements
+ * about when they are to be executed during the reading and writing of the
+ * source and destination files. See the comments in transupp.c, or see
+ * jpegtran.c for an example of correct usage.
+ */
+
+#ifndef TRANSUPP_H
+#define TRANSUPP_H
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+/* If you happen not to want the image transform support, disable it here */
+#ifndef TRANSFORMS_SUPPORTED
+#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
+#endif
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jtransform_request_workspace jTrRequest
+#define jtransform_adjust_parameters jTrAdjust
+#define jtransform_execute_transformation jTrExec
+#define jcopy_markers_setup jCMrkSetup
+#define jcopy_markers_execute jCMrkExec
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/*
+ * Codes for supported types of image transformations.
+ */
+
+typedef enum {
+ JXFORM_NONE, /* no transformation */
+ JXFORM_FLIP_H, /* horizontal flip */
+ JXFORM_FLIP_V, /* vertical flip */
+ JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
+ JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
+ JXFORM_ROT_90, /* 90-degree clockwise rotation */
+ JXFORM_ROT_180, /* 180-degree rotation */
+ JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
+} JXFORM_CODE;
+
+/*
+ * Although rotating and flipping data expressed as DCT coefficients is not
+ * hard, there is an asymmetry in the JPEG format specification for images
+ * whose dimensions aren't multiples of the iMCU size. The right and bottom
+ * image edges are padded out to the next iMCU boundary with junk data; but
+ * no padding is possible at the top and left edges. If we were to flip
+ * the whole image including the pad data, then pad garbage would become
+ * visible at the top and/or left, and real pixels would disappear into the
+ * pad margins --- perhaps permanently, since encoders & decoders may not
+ * bother to preserve DCT blocks that appear to be completely outside the
+ * nominal image area. So, we have to exclude any partial iMCUs from the
+ * basic transformation.
+ *
+ * Transpose is the only transformation that can handle partial iMCUs at the
+ * right and bottom edges completely cleanly. flip_h can flip partial iMCUs
+ * at the bottom, but leaves any partial iMCUs at the right edge untouched.
+ * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
+ * The other transforms are defined as combinations of these basic transforms
+ * and process edge blocks in a way that preserves the equivalence.
+ *
+ * The "trim" option causes untransformable partial iMCUs to be dropped;
+ * this is not strictly lossless, but it usually gives the best-looking
+ * result for odd-size images. Note that when this option is active,
+ * the expected mathematical equivalences between the transforms may not hold.
+ * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
+ * followed by -rot 180 -trim trims both edges.)
+ *
+ * We also offer a "force to grayscale" option, which simply discards the
+ * chrominance channels of a YCbCr image. This is lossless in the sense that
+ * the luminance channel is preserved exactly. It's not the same kind of
+ * thing as the rotate/flip transformations, but it's convenient to handle it
+ * as part of this package, mainly because the transformation routines have to
+ * be aware of the option to know how many components to work on.
+ */
+
+typedef struct {
+ /* Options: set by caller */
+ JXFORM_CODE transform; /* image transform operator */
+ boolean trim; /* if TRUE, trim partial MCUs as needed */
+ boolean force_grayscale; /* if TRUE, convert color image to grayscale */
+
+ /* Internal workspace: caller should not touch these */
+ int num_components; /* # of components in workspace */
+ jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
+} jpeg_transform_info;
+
+
+#if TRANSFORMS_SUPPORTED
+
+/* Request any required workspace */
+EXTERN(void) jtransform_request_workspace
+ JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
+/* Adjust output image parameters */
+EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters
+ JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info));
+/* Execute the actual transformation, if any */
+EXTERN(void) jtransform_execute_transformation
+ JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info));
+
+#endif /* TRANSFORMS_SUPPORTED */
+
+
+/*
+ * Support for copying optional markers from source to destination file.
+ */
+
+typedef enum {
+ JCOPYOPT_NONE, /* copy no optional markers */
+ JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */
+ JCOPYOPT_ALL /* copy all optional markers */
+} JCOPY_OPTION;
+
+#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */
+
+/* Setup decompression object to save desired markers in memory */
+EXTERN(void) jcopy_markers_setup
+ JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option));
+/* Copy markers saved in the given source object to the destination object */
+EXTERN(void) jcopy_markers_execute
+ JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JCOPY_OPTION option));
+
+} // namespace KIPIJPEGLossLessPlugin
+
+#endif // TRANSUPP_H
diff --git a/kipi-plugins/jpeglossless/utils.cpp b/kipi-plugins/jpeglossless/utils.cpp
new file mode 100644
index 0000000..b050bde
--- /dev/null
+++ b/kipi-plugins/jpeglossless/utils.cpp
@@ -0,0 +1,302 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-12-03
+ * Description : misc utils to used in batch process
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * NOTE: Do not use kdDebug() in this implementation because
+ * it will be multithreaded. Use qDebug() instead.
+ * See B.K.O #133026 for details.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utime.h>
+#include <unistd.h>
+}
+
+// Qt includes.
+
+#include <qfileinfo.h>
+#include <qimage.h>
+#include <qstring.h>
+#include <qfile.h>
+#include <qdir.h>
+
+// KDE includes.
+
+#include <ktempfile.h>
+#include <kprocess.h>
+#include <klocale.h>
+#include <kurl.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "utils.h"
+#include "utils.moc"
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+Utils::Utils(QObject *parent)
+ : QObject(parent)
+{
+}
+
+Utils::~Utils()
+{
+}
+
+bool Utils::updateMetadataImageMagick(const QString& src, QString& err)
+{
+ QFileInfo finfo(src);
+ if (src.isEmpty() || !finfo.isReadable())
+ {
+ err = i18n("unable to open source file");
+ return false;
+ }
+
+ QImage img(src);
+ QImage iptcPreview = img.scale(1280, 1024, QImage::ScaleMin);
+ QImage exifThumbnail = iptcPreview.scale(160, 120, QImage::ScaleMin);
+
+ KExiv2Iface::KExiv2 meta;
+ meta.load(src);
+ meta.setImageOrientation(KExiv2Iface::KExiv2::ORIENTATION_NORMAL);
+ meta.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+ meta.setImageDimensions(img.size());
+ meta.setExifThumbnail(exifThumbnail);
+ meta.setImagePreview(iptcPreview);
+ QByteArray ba = meta.getExif();
+ const uchar exifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+ QByteArray exifData = QByteArray(ba.size() + sizeof(exifHeader));
+ memcpy(exifData.data(), exifHeader, sizeof(exifHeader));
+ memcpy(exifData.data()+sizeof(exifHeader), ba.data(), ba.size());
+ QByteArray iptcData = meta.getIptc(true);
+
+ KTempFile exifTemp(QString(), "kipipluginsiptc.app1");
+ exifTemp.setAutoDelete(true);
+ QFile *exifFile = exifTemp.file();
+ if ( !exifFile )
+ {
+ err = i18n("unable to open temp file");
+ return false;
+ }
+ QDataStream streamExif( exifFile );
+ streamExif.writeRawBytes(exifData.data(), exifData.size());
+ exifFile->close();
+
+ KTempFile iptcTemp(QString(), "kipipluginsiptc.8bim");
+ iptcTemp.setAutoDelete(true);
+ QFile *iptcFile = iptcTemp.file();
+ if ( !iptcFile )
+ {
+ err = i18n("Cannot rotate: unable to open temp file");
+ return false;
+ }
+ QDataStream streamIptc( iptcFile );
+ streamIptc.writeRawBytes(iptcData.data(), iptcData.size());
+ iptcFile->close();
+
+ KProcess process;
+ process.clearArguments();
+ process << "mogrify";
+ process << "-verbose";
+
+ process << "-profile";
+ process << exifTemp.name();
+
+ process << "-profile";
+ process << iptcTemp.name();
+
+ process << src + QString("[0]");
+
+ qDebug("ImageMagick Command line args:");
+ QValueList<QCString> args = process.args();
+ for (QValueList<QCString>::iterator it = args.begin(); it != args.end(); ++it)
+ qDebug("%s", (const char*)(*it));
+
+ connect(&process, SIGNAL(receivedStderr(KProcess *, char*, int)),
+ this, SLOT(slotReadStderr(KProcess*, char*, int)));
+
+ if (!process.start(KProcess::Block, KProcess::Stderr))
+ return false;
+
+ if (!process.normalExit())
+ return false;
+
+ switch (process.exitStatus())
+ {
+ case 0: // Process finished successfully !
+ {
+ return true;
+ break;
+ }
+ case 15: // process aborted !
+ {
+ return false;
+ break;
+ }
+ }
+
+ // Processing error !
+ err = i18n("Cannot update metadata: %1").arg(m_stdErr.replace('\n', ' '));
+ return false;
+}
+
+void Utils::slotReadStderr(KProcess*, char* buffer, int buflen)
+{
+ m_stdErr.append(QString::fromLocal8Bit(buffer, buflen));
+}
+
+bool Utils::isJPEG(const QString& file)
+{
+ QString format = QString(QImageIO::imageFormat(file)).upper();
+ return format=="JPEG";
+}
+
+bool Utils::isRAW(const QString& file)
+{
+#if KDCRAW_VERSION < 0x000106
+ QString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles());
+#else
+ QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
+#endif
+
+ QFileInfo fileInfo(file);
+ if (rawFilesExt.upper().contains( fileInfo.extension(false).upper() ))
+ return true;
+
+ return false;
+}
+
+bool Utils::CopyFile(const QString& src, const QString& dst)
+{
+ QFile sFile(src);
+ QFile dFile(dst);
+
+ if ( !sFile.open(IO_ReadOnly) )
+ return false;
+
+ if ( !dFile.open(IO_WriteOnly) )
+ {
+ sFile.close();
+ return false;
+ }
+
+ const int MAX_IPC_SIZE = (1024*32);
+ char buffer[MAX_IPC_SIZE];
+
+ Q_LONG len;
+ while ((len = sFile.readBlock(buffer, MAX_IPC_SIZE)) != 0)
+ {
+ if (len == -1 || dFile.writeBlock(buffer, (Q_ULONG)len) == -1)
+ {
+ sFile.close();
+ dFile.close();
+ return false;
+ }
+ }
+
+ sFile.close();
+ dFile.close();
+
+ return true;
+}
+
+bool Utils::MoveFile(const QString& src, const QString& dst)
+{
+ struct stat stbuf;
+ if (::stat(QFile::encodeName(dst), &stbuf) != 0)
+ {
+ qDebug("KIPIJPEGLossLessPlugin:MoveFile: failed to stat src");
+ return false;
+ }
+
+ if (!CopyFile(src, dst))
+ return false;
+
+ struct utimbuf timbuf;
+ timbuf.actime = stbuf.st_atime;
+ timbuf.modtime = stbuf.st_mtime;
+ if (::utime(QFile::encodeName(dst), &timbuf) != 0)
+ {
+ qDebug("KIPIJPEGLossLessPlugin:MoveFile: failed to update dst time");
+ }
+
+ if (::unlink(QFile::encodeName(src).data()) != 0)
+ {
+ qDebug("KIPIJPEGLossLessPlugin:MoveFile: failed to unlink src");
+ }
+ return true;
+}
+
+bool Utils::deleteDir(const QString& dirPath)
+{
+ QDir dir(dirPath);
+ if (!dir.exists())
+ return false;
+
+ dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoSymLinks);
+
+ const QFileInfoList* infoList = dir.entryInfoList();
+ if (!infoList)
+ return false;
+
+ QFileInfoListIterator it(*infoList);
+ QFileInfo* fi;
+
+ while( (fi = it.current()) )
+ {
+ ++it;
+ if(fi->fileName() == "." || fi->fileName() == ".." )
+ continue;
+
+ if( fi->isDir() )
+ {
+ deleteDir(fi->absFilePath());
+ }
+ else if( fi->isFile() )
+ dir.remove(fi->absFilePath());
+ }
+
+ dir.rmdir(dir.absPath());
+ return true;
+}
+
+} // NameSpace KIPIJPEGLossLessPlugin
diff --git a/kipi-plugins/jpeglossless/utils.h b/kipi-plugins/jpeglossless/utils.h
new file mode 100644
index 0000000..b9040d6
--- /dev/null
+++ b/kipi-plugins/jpeglossless/utils.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-12-03
+ * Description : misc utils to used in batch process
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 UTILS_H
+#define UTILS_H
+
+// Qt includes.
+
+#include <qobject.h>
+#include <qstring.h>
+
+class KProcess;
+
+namespace KIPIJPEGLossLessPlugin
+{
+
+class Utils : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ Utils(QObject *parent);
+ ~Utils();
+
+ bool updateMetadataImageMagick(const QString& src, QString& err);
+
+public: // Static methods.
+
+ /** Test if a file is a JPEG file.
+ */
+ static bool isJPEG(const QString& file);
+
+ /** Test if a file is a RAW file supported by dcraw.
+ */
+ static bool isRAW(const QString& file);
+
+ /** POSIX Compliant File Copy and Move -
+ Can't use KIO based operations as we need to use these in a thread
+ */
+
+ static bool CopyFile(const QString& src, const QString& dst);
+ static bool MoveFile(const QString& src, const QString& dst);
+
+ /** Thread-safe recursive dir deletion.
+ */
+
+ static bool deleteDir(const QString& dirPath);
+
+private slots:
+
+ void slotReadStderr(KProcess*, char*, int);
+
+private:
+
+ QString m_stdErr;
+};
+
+} // NameSpace KIPIJPEGLossLessPlugin
+
+#endif /* UTILS_H */
diff --git a/kipi-plugins/kameraklient/Makefile.am b/kipi-plugins/kameraklient/Makefile.am
new file mode 100644
index 0000000..6696144
--- /dev/null
+++ b/kipi-plugins/kameraklient/Makefile.am
@@ -0,0 +1,29 @@
+## Makefile.am for kameraklient
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(GPHOTO_CFLAGS) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = kipiplugin_kameraklient.la
+kipiplugin_kameraklient_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+
+kipiplugin_kameraklient_la_LIBADD = $(LIB_GPHOTO) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_kameraklient_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+kde_services_DATA = kipiplugin_kameraklient.desktop
+
+# Gilles Caulier 12/13/06): order of file to compile is important to support --enable-final compilation option.
+kipiplugin_kameraklient_la_SOURCES = gpiface.cpp gpcamera.cpp gpcontroller.cpp gpeventfilter.cpp \
+ gpfileitemcontainer.cpp gpfileiteminfo.cpp \
+ gpfileiteminfodlg.cpp gpmessages.cpp gpstatus.cpp \
+ kameraklient.cpp camerafolderitem.cpp camerafolderview.cpp \
+ cameraiconitem.cpp cameraiconview.cpp cameralist.cpp \
+ cameraselection.cpp cameratype.cpp cameraui.cpp \
+ dmessagebox.cpp savefiledialog.cpp setupcamera.cpp \
+ thumbitem.cpp thumbview.cpp
+
+kipiplugin_kameraklientdir = $(kde_datadir)/kipiplugin_kameraklient
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_kameraklient.pot
diff --git a/kipi-plugins/kameraklient/camerafolderitem.cpp b/kipi-plugins/kameraklient/camerafolderitem.cpp
new file mode 100644
index 0000000..67fb9a4
--- /dev/null
+++ b/kipi-plugins/kameraklient/camerafolderitem.cpp
@@ -0,0 +1,76 @@
+/* ============================================================
+ * File : camerafolderitem.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-23
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE
+#include <kiconloader.h>
+// Local
+#include "camerafolderitem.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+CameraFolderItem::CameraFolderItem(KListView* parent, const QString& name) : KListViewItem(parent, name) {
+ setPixmap(0, SmallIcon("folder"));
+ virtualFolder_ = true;
+ count_ = 0;
+ name_ = name;
+}
+
+CameraFolderItem::CameraFolderItem(KListViewItem* parent, const QString& folderName, const QString& folderPath) : KListViewItem(parent, folderName) {
+ setPixmap(0, SmallIcon("folder"));
+ folderName_ = folderName;
+ folderPath_ = folderPath;
+ virtualFolder_ = false;
+ count_ = 0;
+ name_ = folderName;
+}
+
+CameraFolderItem::~CameraFolderItem() {
+}
+
+bool CameraFolderItem::isVirtualFolder() {
+ return virtualFolder_;
+}
+
+QString CameraFolderItem::folderName() {
+ return folderName_;
+}
+
+QString CameraFolderItem::folderPath() {
+ return folderPath_;
+}
+
+void CameraFolderItem::changeCount(int val) {
+ count_ += val;
+ setText(0, name_ + " (" + QString::number(count_) + ")");
+}
+
+void CameraFolderItem::setCount(int val) {
+ count_ = val;
+ setText(0, name_ + " (" + QString::number(count_) + ")");
+}
+
+int CameraFolderItem::count() {
+ return count_;
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
diff --git a/kipi-plugins/kameraklient/camerafolderitem.h b/kipi-plugins/kameraklient/camerafolderitem.h
new file mode 100644
index 0000000..7294c87
--- /dev/null
+++ b/kipi-plugins/kameraklient/camerafolderitem.h
@@ -0,0 +1,54 @@
+/* ============================================================
+ * File : camerafolderitem.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-23
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CAMERAFOLDERITEM_H
+#define CAMERAFOLDERITEM_H
+
+#include <klistview.h>
+#include <qstring.h>
+
+namespace KIPIKameraKlientPlugin
+{
+
+class CameraFolderItem : public KListViewItem {
+public:
+ CameraFolderItem(KListView* parent, const QString& name);
+ CameraFolderItem(KListViewItem* parent, const QString& folderName, const QString& folderPath);
+ ~CameraFolderItem();
+ QString folderName();
+ QString folderPath();
+ bool isVirtualFolder();
+ void changeCount(int val);
+ void setCount(int val);
+ int count();
+
+private:
+ QString folderName_;
+ QString folderPath_;
+ QString name_;
+ bool virtualFolder_;
+ int count_;
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/camerafolderview.cpp b/kipi-plugins/kameraklient/camerafolderview.cpp
new file mode 100644
index 0000000..ae30fae
--- /dev/null
+++ b/kipi-plugins/kameraklient/camerafolderview.cpp
@@ -0,0 +1,115 @@
+/* ============================================================
+ * File : camerafolderview.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-23
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE
+#include <klocale.h>
+#include <kiconloader.h>
+// Local
+#include "camerafolderitem.h"
+#include "camerafolderview.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+CameraFolderView::CameraFolderView(QWidget* parent) : KListView(parent) {
+ addColumn(i18n("Camera Folders"));
+ setFullWidth(true);
+ setDragEnabled(false);
+ setDropVisualizer(false);
+ setDropHighlighter(false);
+ setAcceptDrops(true);
+ cameraName_ = "Camera";
+ virtualFolder_ = 0;
+ rootFolder_ = 0;
+ setupConnections();
+}
+
+CameraFolderView::~CameraFolderView() {
+
+}
+
+void CameraFolderView::setupConnections() {
+ connect(this, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotSelectionChanged(QListViewItem*)));
+}
+
+void CameraFolderView::addVirtualFolder(const QString& name) {
+ cameraName_ = name;
+ virtualFolder_ = new CameraFolderItem(this, cameraName_);
+ virtualFolder_->setOpen(true);
+}
+
+void CameraFolderView::addRootFolder(const QString& folder) {
+ rootFolder_ = new CameraFolderItem(virtualFolder_, folder, folder);
+ rootFolder_->setOpen(true);
+}
+
+CameraFolderItem* CameraFolderView::addFolder(const QString& folder, const QString& subFolder) {
+ CameraFolderItem *parentItem = findFolder(folder);
+ if (parentItem) {
+ QString path(folder);
+ if (!folder.endsWith("/")) {
+ path += "/";
+ }
+ path += subFolder;
+ CameraFolderItem* item = new CameraFolderItem(parentItem, subFolder, path);
+ item->setOpen(true);
+ return item;
+ } else {
+ return 0;
+ }
+}
+
+CameraFolderItem* CameraFolderView::findFolder(const QString& folderPath) {
+ QListViewItemIterator it(this);
+ for( ; it.current(); ++it) {
+ CameraFolderItem* item = static_cast<CameraFolderItem*>(it.current());
+ if (item->folderPath() == folderPath) {
+ return item;
+ }
+ }
+ return 0;
+}
+
+void CameraFolderView::slotSelectionChanged(QListViewItem* item) {
+ if (!item) {
+ return;
+ }
+ emit signalFolderChanged(static_cast<CameraFolderItem *>(item));
+}
+
+CameraFolderItem* CameraFolderView::virtualFolder() {
+ return virtualFolder_;
+}
+
+CameraFolderItem* CameraFolderView::rootFolder() {
+ return rootFolder_;
+}
+
+void CameraFolderView::clear() {
+ KListView::clear();
+ virtualFolder_ = 0;
+ rootFolder_ = 0;
+ emit signalCleared();
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "camerafolderview.moc"
diff --git a/kipi-plugins/kameraklient/camerafolderview.h b/kipi-plugins/kameraklient/camerafolderview.h
new file mode 100644
index 0000000..e2208bb
--- /dev/null
+++ b/kipi-plugins/kameraklient/camerafolderview.h
@@ -0,0 +1,68 @@
+/* ============================================================
+ * File : camerafolderview.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-23
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CAMERAFOLDERVIEW_H
+#define CAMERAFOLDERVIEW_H
+
+// Qt
+#include <qstring.h>
+// KDE
+#include <klistview.h>
+
+namespace KIPIKameraKlientPlugin
+{
+
+class CameraFolderItem;
+
+class CameraFolderView : public KListView {
+ Q_OBJECT
+
+public:
+ CameraFolderView(QWidget* parent);
+ ~CameraFolderView();
+ void addVirtualFolder(const QString& name);
+ void addRootFolder(const QString& folder);
+ CameraFolderItem* addFolder(const QString& folder, const QString& subFolder);
+ CameraFolderItem* findFolder(const QString& folderPath);
+ CameraFolderItem* virtualFolder();
+ CameraFolderItem* rootFolder();
+ virtual void clear();
+
+private:
+ QString cameraName_;
+ CameraFolderItem *virtualFolder_;
+ CameraFolderItem *rootFolder_;
+
+private:
+ void setupConnections();
+
+private slots:
+ void slotSelectionChanged(QListViewItem* item);
+
+signals:
+ void signalFolderChanged(CameraFolderItem*);
+ void signalCleared();
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/cameraiconitem.cpp b/kipi-plugins/kameraklient/cameraiconitem.cpp
new file mode 100644
index 0000000..77c4e1b
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameraiconitem.cpp
@@ -0,0 +1,100 @@
+/* ============================================================
+ * File : cameraiconitem.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-23
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <qpalette.h>
+// Local
+#include "gpfileiteminfo.h"
+#include "cameraiconview.h"
+#include "cameraiconitem.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+const char* CameraIconItem::new_xpm[] = {
+"13 13 8 1",
+" c None",
+". c #232300",
+"+ c #F6F611",
+"@ c #000000",
+"# c #DBDA4D",
+"$ c #FFFF00",
+"% c #AAA538",
+"& c #E8E540",
+" . ",
+" . .+. . ",
+" @#@ .$. .#. ",
+" @$@#$#@$. ",
+" @$%&%$@ ",
+" ..#%&&&%#.. ",
+".+$$&&&&&$$+@",
+" ..#%&&&%#@@ ",
+" @$%&%$@ ",
+" .$@#$#@$. ",
+" @#. @$@ @#. ",
+" . @+@ . ",
+" @ "};
+
+
+QPixmap* CameraIconItem::newEmblem = 0;
+
+CameraIconItem::CameraIconItem(ThumbView* parent, const GPFileItemInfo* fileInfo, const QPixmap& pixmap)
+ : ThumbItem(parent, fileInfo->name, pixmap), fileInfo_(fileInfo) {
+ pixWidth_ = pixmap.width();
+ pixHeight_ = pixmap.height();
+ loadNewEmblem();
+}
+
+CameraIconItem::~CameraIconItem() {
+ if(newEmblem) {
+ delete newEmblem;
+ newEmblem = 0;
+ }
+}
+
+const GPFileItemInfo* CameraIconItem::fileInfo() {
+ return fileInfo_;
+}
+
+void CameraIconItem::loadNewEmblem() {
+ if (!newEmblem) {
+ newEmblem = new QPixmap(new_xpm);
+ }
+}
+
+void CameraIconItem::setPixmap(const QImage& thumb) {
+ int size = pixmap()->width();
+ pixWidth_ = thumb.width();
+ pixHeight_ = thumb.height();
+ QPainter painter;
+ painter.begin(pixmap());
+ painter.fillRect(0, 0, size, size, QBrush(iconView()->colorGroup().base()));
+ painter.drawImage((size-thumb.width())/2, (size-thumb.height())/2, thumb);
+ painter.end();
+ repaint();
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
diff --git a/kipi-plugins/kameraklient/cameraiconitem.h b/kipi-plugins/kameraklient/cameraiconitem.h
new file mode 100644
index 0000000..0d67140
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameraiconitem.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ * File : cameraiconitem.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-23
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CAMERAICONITEM_H
+#define CAMERAICONITEM_H
+
+#include "thumbitem.h"
+
+class QString;
+class QPixmap;
+class QImage;
+class QPainter;
+class QColorGroup;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPFileItemInfo;
+class ThumbView;
+
+class CameraIconItem : public ThumbItem {
+ friend class CameraIconView;
+
+public:
+ CameraIconItem(ThumbView* parent, const GPFileItemInfo* fileInfo, const QPixmap& pixmap);
+ ~CameraIconItem();
+ const GPFileItemInfo* fileInfo();
+ void setPixmap(const QImage& thumb);
+
+private:
+ void loadNewEmblem();
+ const GPFileItemInfo* fileInfo_;
+ int pixWidth_, pixHeight_;
+ static QPixmap* newEmblem;
+ static const char* new_xpm[];
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/cameraiconview.cpp b/kipi-plugins/kameraklient/cameraiconview.cpp
new file mode 100644
index 0000000..7d5d542
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameraiconview.cpp
@@ -0,0 +1,144 @@
+/* ============================================================
+ * File : cameraiconview.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-23
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt
+#include <qimage.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qrect.h>
+#include <qpalette.h>
+#include <qpoint.h>
+#include <qpopupmenu.h>
+#include <qvaluevector.h>
+// KDE
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <ktrader.h>
+#include <kservice.h>
+// Local
+#include "gpfileiteminfo.h"
+#include "gpfileiteminfodlg.h"
+#include "cameraiconitem.h"
+#include "cameraiconview.h"
+#include "cameraui.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+const int MAXICONITEMS = 307;
+const int THUMBSIZE = 120;
+
+class CameraIconViewPrivate {
+
+public:
+ QPixmap imagePix;
+ QPixmap audioPix;
+ QPixmap videoPix;
+ QPixmap unknownPix;
+};
+
+CameraIconView::CameraIconView(QWidget *parent) : ThumbView(parent) {
+ d = new CameraIconViewPrivate;
+ setThumbnailSize();
+}
+
+CameraIconView::~CameraIconView() {
+ delete d;
+}
+
+void CameraIconView::setThumbnailSize() {
+ int w = THUMBSIZE;
+ int h = THUMBSIZE;
+ QString iconfile = locate("data", "documents");
+ QImage image(iconfile);
+ double scale = double(w-10) / double(image.width());
+ image = image.smoothScale(w-10, h-10, QImage::ScaleMin);
+ QPixmap pix(w, h);
+ pix.fill(colorGroup().base());
+ QPainter p(&pix);
+ p.fillRect(0, 0, w, h, QBrush(colorGroup().base()));
+ if(!image.isNull()) {
+ p.drawImage((w-image.width())/2, (h-image.height())/2, image);
+ }
+ p.end();
+ d->imagePix = pix;
+ createPixmap(d->imagePix, "image", scale);
+ d->audioPix = pix;
+ createPixmap(d->audioPix, "sound", scale);
+ d->videoPix = pix;
+ createPixmap(d->videoPix, "video", scale);
+ d->unknownPix = pix;
+ createPixmap(d->unknownPix, "document", scale);
+}
+
+void CameraIconView::createPixmap(QPixmap& pix, const QString& icon, double scale) {
+ QString iconfile = locate("data", icon);
+ QImage mimeImg(iconfile);
+ mimeImg = mimeImg.smoothScale((int) (mimeImg.width()*scale), (int) (mimeImg.height()*scale), QImage::ScaleMin);
+ int w = THUMBSIZE;
+ int h = THUMBSIZE;
+ QPainter p(&pix);
+ if (!mimeImg.isNull()) {
+ p.drawImage((w-mimeImg.width())/2, (h-mimeImg.height())/2, mimeImg);
+ }
+ p.end();
+}
+
+CameraIconItem* CameraIconView::addItem(const GPFileItemInfo* fileInfo) {
+ QPixmap& pix = d->unknownPix;
+ if(fileInfo->mime.contains("image")) {
+ pix = d->imagePix;
+ } else if(fileInfo->mime.contains("audio")) {
+ pix = d->audioPix;
+ } else if(fileInfo->mime.contains("video")) {
+ pix = d->videoPix;
+ } else {
+ pix = d->unknownPix;
+ }
+ CameraIconItem *iconItem = new CameraIconItem(this, fileInfo, pix);
+ return iconItem;
+}
+
+void CameraIconView::clear() {
+ ThumbView::clear();
+ emit signalCleared();
+}
+
+void CameraIconView::setThumbnail(CameraIconItem* iconItem, const QImage& thumbnail) {
+ if (!iconItem) {
+ return;
+ }
+ iconItem->setPixmap(thumbnail);
+}
+
+void CameraIconView::markDownloaded(CameraIconItem* iconItem) {
+ if (!iconItem) {
+ return;
+ }
+ GPFileItemInfo *fileInfo = const_cast<GPFileItemInfo*>(iconItem->fileInfo());
+ fileInfo->downloaded = 1;
+ iconItem->repaint();
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "cameraiconview.moc"
diff --git a/kipi-plugins/kameraklient/cameraiconview.h b/kipi-plugins/kameraklient/cameraiconview.h
new file mode 100644
index 0000000..d64814b
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameraiconview.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ * File : cameraiconview.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-23
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CAMERAICONVIEW_H
+#define CAMERAICONVIEW_H
+
+#include "thumbview.h"
+
+class QString;
+class QPainter;
+class QImage;
+class QPixmap;
+class QPoint;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPFileItemInfo;
+class ThumbItem;
+class CameraIconItem;
+class CameraIconViewPrivate;
+
+class CameraIconView : public ThumbView {
+ Q_OBJECT
+
+public:
+ CameraIconView(QWidget *parent);
+ ~CameraIconView();
+ void setThumbnailSize();
+ CameraIconItem* addItem(const GPFileItemInfo* fileInfo);
+ void setThumbnail(CameraIconItem* iconItem, const QImage& thumbnail);
+ void markDownloaded(CameraIconItem* iconItem);
+ virtual void clear();
+
+private:
+ void createPixmap(QPixmap& pix, const QString& icon, double scale);
+
+private:
+ CameraIconViewPrivate *d;
+
+signals:
+ void signalCleared();
+
+signals:
+ void signalDownloadSelectedItems();
+ void signalDeleteSelectedItems();
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
diff --git a/kipi-plugins/kameraklient/cameralist.cpp b/kipi-plugins/kameraklient/cameralist.cpp
new file mode 100644
index 0000000..2477a3f
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameralist.cpp
@@ -0,0 +1,172 @@
+/* ============================================================
+ * File : cameralist.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt
+#include <qdom.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qtextstream.h>
+// Local
+#include "cameralist.h"
+#include "cameratype.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+CameraList* CameraList::instance_ = 0;
+
+CameraList* CameraList::instance() {
+ return instance_;
+}
+
+class CameraListPrivate {
+ public:
+ QPtrList<CameraType> clist;
+ QString file;
+ bool modified;
+};
+
+CameraList::CameraList(QObject *parent, const QString& file) : QObject(parent) {
+ d = new CameraListPrivate;
+ d->clist.setAutoDelete(true);
+ d->file = file;
+ d->modified = false;
+ instance_ = this;
+}
+
+CameraList::~CameraList() {
+ close();
+ d->clist.clear();
+ delete d;
+ instance_ = 0;
+}
+
+bool CameraList::load() {
+ d->modified = false;
+ QFile cfile(d->file);
+ if(!cfile.open(IO_ReadOnly)) {
+ return false;
+ }
+ QDomDocument doc("cameralist");
+ if(!doc.setContent(&cfile)) {
+ return false;
+ }
+ QDomElement docElem = doc.documentElement();
+ if(docElem.tagName()!="cameralist") {
+ return false;
+ }
+ for(QDomNode n = docElem.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ QDomElement e = n.toElement();
+ if (e.isNull()) {
+ continue;
+ }
+ if (e.tagName() != "item") {
+ continue;
+ }
+ QString model = e.attribute("model");
+ QString port = e.attribute("port");
+ CameraType *ctype = new CameraType(model, port);
+ insertPrivate(ctype);
+ }
+ return true;
+}
+
+bool CameraList::close() {
+ // If not modified don't save the file
+ if (!d->modified) {
+ return true;
+ }
+ QDomDocument doc("cameralist");
+ doc.setContent(QString("<!DOCTYPE XMLCameraList><cameralist version=\"1.0\" client=\"kipiplugin_kameraklietnt\"/>"));
+ QDomElement docElem=doc.documentElement();
+ for (CameraType *ctype = d->clist.first(); ctype; ctype = d->clist.next()) {
+ QDomElement elem = doc.createElement("item");
+ elem.setAttribute("model", ctype->model());
+ elem.setAttribute("port", ctype->port());
+ docElem.appendChild(elem);
+ }
+ QFile cfile(d->file);
+ if (!cfile.open(IO_WriteOnly)) {
+ return false;
+ }
+ QTextStream stream(&cfile);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ stream << doc.toString();
+ cfile.close();
+ return true;
+}
+
+void CameraList::insert(CameraType* ctype) {
+ if(!ctype) {
+ return;
+ }
+ d->modified = true;
+ insertPrivate(ctype);
+}
+
+void CameraList::remove(CameraType* ctype) {
+ if (!ctype) {
+ return;
+ }
+ d->modified = true;
+ removePrivate(ctype);
+}
+
+void CameraList::insertPrivate(CameraType* ctype) {
+ if (!ctype) {
+ return;
+ }
+ d->clist.append(ctype);
+ emit signalCameraListChanged();
+}
+
+void CameraList::removePrivate(CameraType* ctype) {
+ if (!ctype) {
+ return;
+ }
+ d->clist.remove(ctype);
+ emit signalCameraListChanged();
+}
+
+QPtrList<CameraType>* CameraList::cameraList() {
+ return &d->clist;
+}
+
+CameraType* CameraList::find(const QString& model) {
+ for (CameraType *ctype = d->clist.first(); ctype; ctype = d->clist.next()) {
+ if (ctype->model() == model) {
+ return ctype;
+ }
+ }
+ return 0;
+}
+
+void CameraList::clear() {
+ CameraType *ctype = d->clist.first();
+ while (ctype) {
+ remove(ctype);
+ ctype = d->clist.first();
+ }
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "cameralist.moc"
diff --git a/kipi-plugins/kameraklient/cameralist.h b/kipi-plugins/kameraklient/cameralist.h
new file mode 100644
index 0000000..e6dda49
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameralist.h
@@ -0,0 +1,64 @@
+/* ============================================================
+ * File : cameralist.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-03
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CAMERALIST_H
+#define CAMERALIST_H
+
+#include <qptrlist.h>
+#include <qobject.h>
+
+class QString;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class CameraType;
+class CameraListPrivate;
+
+class CameraList : public QObject {
+ Q_OBJECT
+
+ public:
+ CameraList(QObject *parent, const QString& file);
+ ~CameraList();
+ bool load();
+ bool close();
+ void insert(CameraType* ctype);
+ void remove(CameraType* ctype);
+ CameraType* find(const QString& title);
+ void clear();
+ QPtrList<CameraType>* cameraList();
+ static CameraList* instance();
+
+ private:
+ static CameraList* instance_;
+ CameraListPrivate *d;
+ void insertPrivate(CameraType* ctype);
+ void removePrivate(CameraType* ctype);
+
+signals:
+ void signalCameraListChanged();
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/cameraselection.cpp b/kipi-plugins/kameraklient/cameraselection.cpp
new file mode 100644
index 0000000..0579d9e
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameraselection.cpp
@@ -0,0 +1,266 @@
+/* ============================================================
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+// Qt includes.
+
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlistview.h>
+#include <qradiobutton.h>
+#include <qvbuttongroup.h>
+#include <qlayout.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qframe.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+
+// Include files for KIPI
+
+#include <libkipi/version.h>
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "kpaboutdata.h"
+#include "cameraselection.h"
+#include "gpiface.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+CameraSelection::CameraSelection(QWidget* parent)
+ : KDialogBase(parent, 0, true, i18n("Camera Selection"),
+ Help|Ok|Cancel, Ok, true)
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("KameraKlient"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Digital camera interface Kipi plugin"),
+ "(c) 2003-2004, Renchi Raju\n"
+ "(c) 2004, Tudor Calin");
+
+ m_about->addAuthor("Renchi Raju", I18N_NOOP("Original author from Digikam project"),
+ "renchi@pooh.tam.uiuc.edu");
+
+ m_about->addAuthor("Tudor Calin", I18N_NOOP("Porting the Digikam GPhoto2 interface to Kipi. Maintainer"),
+ "tudor@1xtech.com");
+
+ helpButton_ = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ helpButton_->setPopup( helpMenu->menu() );
+
+ QWidget *page = new QWidget(this);
+ setMainWidget(page);
+
+ QVBoxLayout *topLayout = new QVBoxLayout(page, 5, 5);
+
+ //---------------------------------------------
+
+ QGroupBox* mainBox = new QGroupBox(page);
+ mainBox->setTitle(i18n("Camera Configuration"));
+ mainBox->setColumnLayout(0, Qt::Vertical );
+ mainBox->layout()->setSpacing( 5 );
+ mainBox->layout()->setMargin( 5 );
+ QGridLayout* mainBoxLayout = new QGridLayout(mainBox->layout());
+ mainBoxLayout->setAlignment(Qt::AlignTop);
+
+ listView_ = new QListView( mainBox );
+ listView_->addColumn( i18n("Cameras") );
+ listView_->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
+ mainBoxLayout->addMultiCellWidget(listView_, 0, 4, 0, 0);
+
+ portButtonGroup_ = new QVButtonGroup(mainBox);
+ portButtonGroup_->setTitle(i18n("Camera Port Type"));
+ portButtonGroup_->setRadioButtonExclusive(true);
+ portButtonGroup_->layout()->setSpacing(5);
+ portButtonGroup_->layout()->setMargin(5);
+
+ usbButton_ = new QRadioButton(portButtonGroup_);
+ usbButton_->setText( i18n("USB"));
+
+ serialButton_ = new QRadioButton( portButtonGroup_ );
+ serialButton_->setText( i18n("Serial"));
+
+ mainBoxLayout->addWidget(portButtonGroup_, 1, 1);
+
+ QGroupBox* portPathBox = new QGroupBox(mainBox);
+ portPathBox->setTitle( i18n("Camera Port Path"));
+ portPathBox->setColumnLayout(0, Qt::Vertical );
+ portPathBox->layout()->setSpacing( 5 );
+ portPathBox->layout()->setMargin( 5 );
+ QVBoxLayout* portPathBoxLayout = new QVBoxLayout( portPathBox->layout() );
+ portPathBoxLayout->setAlignment( Qt::AlignTop );
+
+ QLabel* portPathLabel_ = new QLabel( portPathBox);
+ portPathLabel_->setText( i18n("only for serial port\n" "cameras"));
+ portPathBoxLayout->addWidget( portPathLabel_ );
+
+ portPathComboBox_ = new QComboBox( false, portPathBox );
+ portPathComboBox_->setDuplicatesEnabled( FALSE );
+ portPathBoxLayout->addWidget(portPathComboBox_);
+
+ mainBoxLayout->addWidget(portPathBox, 2, 1);
+
+ QSpacerItem* spacer = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
+ mainBoxLayout->addItem(spacer, 4, 1);
+
+ topLayout->addWidget( mainBox );
+
+ // Connections --------------------------------------------------
+
+ connect(listView_, SIGNAL(selectionChanged(QListViewItem *)),
+ this, SLOT(slotSelectionChanged(QListViewItem *)));
+
+ connect(portButtonGroup_, SIGNAL(clicked(int)), this, SLOT(slotPortChanged()));
+
+ connect(this, SIGNAL(okClicked()), this, SLOT(slotOkClicked()));
+
+ // Initialize --------------------------------------------------
+
+ getCameraList();
+ getSerialPortList();
+}
+
+CameraSelection::~CameraSelection() {
+ delete m_about;
+}
+
+void CameraSelection::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("kameraklient",
+ "kipi-plugins");
+}
+
+void CameraSelection::setCamera(const QString& model, const QString& port) {
+ QString camModel(model);
+ QListViewItem* item = listView_->findItem(camModel, 0);
+ if (!item) {
+ return;
+ }
+ listView_->setSelected(item, true);
+ listView_->ensureItemVisible(item);
+
+ if (port.contains("usb")) {
+ usbButton_->setChecked(true);
+ } else if (port.contains("serial")) {
+ serialButton_->setChecked(true);
+ for (int i=0; i<portPathComboBox_->count(); i++) {
+ if (port == portPathComboBox_->text(i)) {
+ portPathComboBox_->setCurrentItem(i);
+ break;
+ }
+ }
+ }
+}
+
+void CameraSelection::getCameraList() {
+ int count = 0;
+ QStringList clist;
+ GPIface::getSupportedCameras(count, clist);
+ QString cname;
+ for (int i=0; i<count; i++) {
+ cname = clist[i];
+ new QListViewItem(listView_, cname);
+ }
+}
+
+void CameraSelection::getSerialPortList() {
+ QStringList plist;
+ GPIface::getSupportedPorts(plist);
+ serialPortList_.clear();
+ for (unsigned int i=0; i<plist.count(); i++) {
+ if ((plist[i]).startsWith("serial:")) {
+ serialPortList_.append(plist[i]);
+ }
+ }
+}
+
+void CameraSelection::slotSelectionChanged(QListViewItem *item) {
+ if (!item) {
+ return;
+ }
+ QString model(item->text(0));
+ QStringList plist;
+ GPIface::getCameraSupportedPorts(model, plist);
+ if (plist.contains("serial")) {
+ serialButton_->setEnabled(true);
+ serialButton_->setChecked(true);
+ } else {
+ serialButton_->setEnabled(true);
+ serialButton_->setChecked(false);
+ serialButton_->setEnabled(false);
+ }
+ if (plist.contains("usb")) {
+ usbButton_->setEnabled(true);
+ usbButton_->setChecked(true);
+ } else {
+ usbButton_->setEnabled(true);
+ usbButton_->setChecked(false);
+ usbButton_->setEnabled(false);
+ }
+ slotPortChanged();
+}
+
+void CameraSelection::slotPortChanged() {
+ if (usbButton_->isChecked()) {
+ portPathComboBox_->setEnabled(true);
+ portPathComboBox_->clear();
+ portPathComboBox_->insertItem( QString("usb:"), 0 );
+ portPathComboBox_->setEnabled(false);
+ return;
+ }
+ if (serialButton_->isChecked()) {
+ portPathComboBox_->setEnabled(true);
+ portPathComboBox_->clear();
+ portPathComboBox_->insertStringList(serialPortList_);
+ }
+}
+
+QString CameraSelection::currentModel() {
+ QListViewItem* item = listView_->currentItem();
+ if(!item) {
+ return QString::null;
+ }
+ QString model(item->text(0));
+ return model;
+
+}
+
+QString CameraSelection::currentPortPath() {
+ return portPathComboBox_->currentText();
+}
+
+void CameraSelection::slotOkClicked() {
+ emit signalOkClicked(currentModel(), currentPortPath());
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "cameraselection.moc"
diff --git a/kipi-plugins/kameraklient/cameraselection.h b/kipi-plugins/kameraklient/cameraselection.h
new file mode 100644
index 0000000..81d427d
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameraselection.h
@@ -0,0 +1,93 @@
+/* ============================================================
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CAMERASELECTION_H
+#define CAMERASELECTION_H
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qstringlist.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QComboBox;
+class QListView;
+class QListViewItem;
+class QRadioButton;
+class QVButtonGroup;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class CameraSelection : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ CameraSelection( QWidget* parent = 0 );
+ ~CameraSelection();
+
+ void setCamera(const QString& model, const QString& port);
+ QString currentModel();
+ QString currentPortPath();
+
+private:
+
+ void getCameraList();
+ void getSerialPortList();
+
+ QListView* listView_;
+
+ QVButtonGroup* portButtonGroup_;
+
+ QRadioButton* usbButton_;
+ QRadioButton* serialButton_;
+
+ QLabel* portPathLabel_;
+
+ QComboBox* portPathComboBox_;
+
+ QStringList serialPortList_;
+
+ QPushButton* helpButton_;
+
+ KIPIPlugins::KPAboutData* m_about;
+
+private slots:
+
+ void slotSelectionChanged(QListViewItem *item);
+ void slotPortChanged();
+ void slotOkClicked();
+ void slotHelp();
+
+signals:
+
+ void signalOkClicked(const QString& model, const QString& port);
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
diff --git a/kipi-plugins/kameraklient/cameratype.cpp b/kipi-plugins/kameraklient/cameratype.cpp
new file mode 100644
index 0000000..6cc7ebc
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameratype.cpp
@@ -0,0 +1,80 @@
+/* ============================================================
+ * File : cameratype.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-29
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Local
+#include "cameratype.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+CameraType::CameraType() {
+ valid_ = false;
+}
+
+CameraType::CameraType(const QString& model, const QString& port) {
+ model_ = model;
+ port_ = port;
+ valid_ = true;
+}
+
+CameraType::~CameraType() {
+}
+
+CameraType::CameraType(const CameraType& ctype) {
+ model_ = ctype.model_;
+ port_ = ctype.port_;
+ valid_ = ctype.valid_;
+}
+
+CameraType& CameraType::operator=(const CameraType& ctype) {
+ if (this != &ctype) {
+ model_ = ctype.model_;
+ port_ = ctype.port_;
+ valid_ = ctype.valid_;
+ }
+ return *this;
+}
+
+void CameraType::setModel(const QString& model) {
+ model_ = model;
+}
+
+void CameraType::setPort(const QString& port) {
+ port_ = port;
+}
+
+QString CameraType::model() const {
+ return model_;
+}
+
+QString CameraType::port() const {
+ return port_;
+}
+
+bool CameraType::valid() {
+ return valid_;
+}
+
+void CameraType::setValid(bool valid) {
+ valid_ = valid;
+}
+
+} // NameSpace KIPIKameraKlientPlugin
diff --git a/kipi-plugins/kameraklient/cameratype.h b/kipi-plugins/kameraklient/cameratype.h
new file mode 100644
index 0000000..68fef23
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameratype.h
@@ -0,0 +1,53 @@
+/* ============================================================
+ * File : cameratype.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-29
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CAMERATYPE_H
+#define CAMERATYPE_H
+
+#include <qstring.h>
+
+namespace KIPIKameraKlientPlugin
+{
+
+class CameraType {
+ public:
+ CameraType();
+ CameraType(const QString& model, const QString& port);
+ ~CameraType();
+ CameraType(const CameraType& ctype);
+ CameraType& operator=(const CameraType& type);
+ void setModel(const QString& model);
+ void setPort(const QString& port);
+ void setValid(bool valid);
+ QString model() const;
+ QString port() const;
+ bool valid();
+
+ private:
+ QString model_;
+ QString port_;
+ bool valid_;
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/cameraui.cpp b/kipi-plugins/kameraklient/cameraui.cpp
new file mode 100644
index 0000000..cbe55bb
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameraui.cpp
@@ -0,0 +1,667 @@
+/* ============================================================
+ * File : cameraui.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.com>
+ *
+ * Update : 08/28/2003 - Gilles Caulier <caulier.gilles@free.fr>
+ * Add standard shortcuts and toolbars KDE menu entry.
+ * Add new toolbar icons.
+ * Improve i18n messages.
+ * 17/09/2003 - Gilles Caulier <caulier.gilles@free.fr>
+ * Add FullScreen mode.
+ * 19/09/2003 - Gilles Caulier <caulier.gilles@free.fr>
+ * Add new default shortcuts.
+ *
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qcombobox.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qimage.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qsplitter.h>
+#include <qstringlist.h>
+#include <qtooltip.h>
+#include <qvaluelist.h>
+#include <qvbox.h>
+#include <qpushbutton.h>
+#include <qframe.h>
+
+// KDE includes
+
+#include <kaccel.h>
+#include <kcombobox.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdirlister.h>
+#include <kfiledialog.h>
+#include <kfileitem.h>
+#include <klocale.h>
+#include <kedittoolbar.h>
+#include <kio/job.h>
+#include <kkeydialog.h>
+#include <klineeditdlg.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kprogress.h>
+#include <krun.h>
+#include <kservice.h>
+#include <kstandarddirs.h>
+#include <kstatusbar.h>
+#include <kstdaccel.h>
+#include <kurl.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kguiitem.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "camerafolderitem.h"
+#include "cameraiconview.h"
+#include "camerafolderview.h"
+#include "cameraiconitem.h"
+#include "cameralist.h"
+#include "cameratype.h"
+#include "dmessagebox.h"
+#include "gpcontroller.h"
+#include "gpeventfilter.h"
+#include "gpfileitemcontainer.h"
+#include "gpfileiteminfo.h"
+#include "savefiledialog.h"
+#include "setupcamera.h"
+#include "cameraui.h"
+#include "cameraui.moc"
+
+namespace KIPIKameraKlientPlugin
+{
+
+CameraUI::CameraUI() : QWidget()
+{
+ setWFlags(Qt::WDestructiveClose);
+ resize(700, 440);
+ setMinimumSize(600, 400);
+
+ mCameraList = new CameraList(this, locateLocal("data", "kipi/cameras.xml"));
+ mCameraType = new CameraType();
+
+ //---------------------------------------------
+
+ QVBoxLayout *dvlay = new QVBoxLayout( this, 6 );
+ QHBoxLayout* mMainBoxLayout = new QHBoxLayout(dvlay);
+ mMainBoxLayout->setResizeMode(QLayout::FreeResize);
+ QVBoxLayout* mLeftBoxLayout = new QVBoxLayout(mMainBoxLayout, 0);
+ QVBoxLayout* mBtnBoxLayout = new QVBoxLayout(mMainBoxLayout, 4);
+ mBtnBoxLayout->setMargin(2);
+
+ // create Button Box ----------------------------------------------------------------------
+
+ mCameraSetupBtn = new QPushButton(i18n("Setup"), this);
+ mCameraSetupBtn->setMinimumSize(QSize(100, 0));
+ mBtnBoxLayout->addWidget(mCameraSetupBtn);
+ mCameraStopBtn = new QPushButton(i18n("Stop"), this);
+ mCameraStopBtn->setMinimumSize(QSize(100, 0));
+ mBtnBoxLayout->addWidget(mCameraStopBtn);
+ mCameraDownloadBtn = new QPushButton(i18n("Download"), this);
+ mCameraDownloadBtn->setMinimumSize(QSize(100, 0));
+ mBtnBoxLayout->addWidget(mCameraDownloadBtn);
+ mCameraUploadBtn = new QPushButton(i18n("Upload"), this);
+ mCameraUploadBtn->setMinimumSize(QSize(100, 0));
+ mBtnBoxLayout->addWidget(mCameraUploadBtn);
+ mCameraDeleteBtn = new QPushButton(i18n("Delete"), this);
+ mCameraDeleteBtn->setMinimumSize(QSize(100, 0));
+ mBtnBoxLayout->addWidget(mCameraDeleteBtn);
+ QSpacerItem* mBtnSpacer = new QSpacerItem(0, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
+ mBtnBoxLayout->addItem(mBtnSpacer);
+ mDialogCloseBtn = new QPushButton(i18n("Close"), this);
+ mDialogCloseBtn->setMinimumSize(QSize(100, 0));
+ mBtnBoxLayout->addWidget(mDialogCloseBtn);
+
+ // About data and help button ---------------------------------------------------
+
+ mhelpButton = new QPushButton(i18n("&Help"), this);
+ mhelpButton->setMinimumSize(QSize(100, 0));
+ mBtnBoxLayout->addWidget(mhelpButton);
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("KameraKlient"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Digital camera interface Kipi plugin"),
+ "(c) 2003-2004, Renchi Raju\n"
+ "(c) 2004, Tudor Calin");
+
+ m_about->addAuthor("Renchi Raju", I18N_NOOP("Original author from Digikam project"),
+ "renchi@pooh.tam.uiuc.edu");
+
+ m_about->addAuthor("Tudor Calin", I18N_NOOP("Porting the Digikam GPhoto2 interface to Kipi. Maintainer"),
+ "tudor@1xtech.com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ mhelpButton->setPopup( helpMenu->menu() );
+
+ // create Camera Box-----------------------------------------------------------------------
+
+ QHBoxLayout* mCameraBoxLayout = new QHBoxLayout(mLeftBoxLayout, 4);
+ mCameraBoxLayout->setMargin(4);
+ mCameraConnectBtn = new QPushButton(i18n("Connect"), this);
+ mCameraBoxLayout->addWidget(mCameraConnectBtn);
+ mCameraComboBox = new QComboBox(this, "camera");
+ mCameraComboBox->setInsertionPolicy(QComboBox::AtBottom);
+ mCameraComboBox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ mCameraBoxLayout->addWidget(mCameraComboBox);
+
+ // create Download Directory Camera Box ---------------------------------------------------
+
+ QHBoxLayout *mDownloadDirectoryBoxLayout = new QHBoxLayout(mLeftBoxLayout, 4);
+ mDownloadDirectoryBoxLayout->setMargin(4);
+ QLabel* mDownloadDirectoryLabel = new QLabel(i18n("Download to: "), this);
+ mDownloadDirectoryBoxLayout->addWidget(mDownloadDirectoryLabel);
+ mDownloadDirectoryEdit = new QLineEdit(this);
+ mDownloadDirectoryEdit->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ mDownloadDirectoryEdit->setReadOnly(true);
+ mDownloadDirectoryBoxLayout->addWidget(mDownloadDirectoryEdit);
+ mChangeDownloadDirectoryBtn = new QPushButton(i18n("&Change"), this);
+ mDownloadDirectoryBoxLayout->addWidget(mChangeDownloadDirectoryBtn); // -------------------------
+ mSplitter = new QSplitter(this);
+ mLeftBoxLayout->addWidget(mSplitter);
+ mSplitter->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
+ mFolderView = new CameraFolderView(mSplitter);
+ mIconView = new CameraIconView(mSplitter);
+ mSplitter->setOpaqueResize(true);
+ mSplitter->setResizeMode(mFolderView, QSplitter::Stretch);
+ mSplitter->setResizeMode(mIconView, QSplitter::Stretch);
+ container_ = new GPFileItemContainer(this, mFolderView, mIconView);
+ efilter_ = new GPEventFilter(this);
+ controller_ = new GPController(this, *mCameraType);
+ controller_->start();
+ cameraConnected_ = false;
+
+ // create Status Bar -----------------------------------------------------------------------------
+
+ mStatusBar = new KStatusBar(this);
+ mLeftBoxLayout->addWidget(mStatusBar);
+ mStatusLabel = new QLabel(mStatusBar);
+ mStatusLabel->setText(i18n("Ready"));
+ mStatusBar->addWidget(mStatusLabel, 7, true);
+ mProgressBar = new KProgress(mStatusBar);
+ mProgressBar->setTotalSteps(100);
+ mStatusBar->addWidget(mProgressBar, 5, true);
+
+ // -------------------------------------------------
+
+ setupAccel();
+ setupConnections();
+ mCameraList->load();
+ readSettings();
+}
+
+CameraUI::~CameraUI() {
+ writeSettings();
+ delete controller_;
+ delete container_;
+ mFolderView->clear();
+ mIconView->clear();
+
+ delete m_about;
+}
+
+
+void CameraUI::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("kameraklient",
+ "kipi-plugins");
+}
+
+const CameraType* CameraUI::cameraType() {
+ return mCameraType;
+}
+
+void CameraUI::setupAccel() {
+ mCameraUIAccel = new KAccel(this);
+ mCameraUIAccel->insert("Select All", i18n("Select All"),
+ i18n("Select all the images from the camera."),
+ CTRL+Key_A, this, SLOT(slotSelectAll()));
+ mCameraUIAccel->insert("Select None", i18n("Select None"),
+ i18n("Deselect all the images from the camera."),
+ CTRL+Key_U, this, SLOT(slotSelectNone()));
+ mCameraUIAccel->insert("Invert Selection", i18n("Invert Selection"),
+ i18n("Invert the selection."),
+ CTRL+Key_Asterisk, this, SLOT(slotSelectInvert()));
+ mCameraUIAccel->insert("Select New", i18n("Select New Items"),
+ i18n("Select all the that were not previously downloaded."),
+ CTRL+Key_Slash, this, SLOT(slotSelectNew()));
+ setCameraConnected(false);
+}
+
+void CameraUI::setupConnections() {
+ connect(this, SIGNAL(signalStatusMsg(const QString&)), this, SLOT(slotSetStatusMsg(const QString&)));
+ connect(this, SIGNAL(signalProgressVal(int)), this, SLOT(slotSetProgressVal(int)));
+ connect(this, SIGNAL(signalBusy(bool)), this, SLOT(slotBusy(bool)));
+ connect(efilter_, SIGNAL(signalStatusMsg(const QString&)), this, SIGNAL(signalStatusMsg(const QString&)));
+ connect(efilter_, SIGNAL(signalProgressVal(int)), this, SIGNAL(signalProgressVal(int)));
+ connect(efilter_, SIGNAL(signalBusy(bool)), this, SIGNAL(signalBusy(bool)));
+ connect(mFolderView, SIGNAL(signalFolderChanged(CameraFolderItem*)), this, SLOT(slotFolderSelected(CameraFolderItem*)));
+ connect(mIconView, SIGNAL(signalDownloadSelectedItems()), this, SLOT(slotCameraDownloadSelected()));
+ connect(mIconView, SIGNAL(signalDeleteSelectedItems()), this, SLOT(slotCameraDeleteSelected()));
+ connect(mChangeDownloadDirectoryBtn, SIGNAL(pressed()), this, SLOT(slotChangeDownloadDirectory()));
+ connect(mCameraList, SIGNAL(signalCameraListChanged()), this, SLOT(slotSyncCameraComboBox()));
+ connect(mCameraConnectBtn, SIGNAL(pressed()), this, SLOT(slotCameraConnectToggle()));
+ connect(mCameraSetupBtn, SIGNAL(pressed()), this, SLOT(slotSetupCamera()));
+ connect(mCameraStopBtn, SIGNAL(pressed()), this, SLOT(slotCameraCancel()));
+ connect(mCameraDownloadBtn, SIGNAL(pressed()), this, SLOT(slotCameraDownloadSelected()));
+ connect(mCameraUploadBtn, SIGNAL(pressed()), this, SLOT(slotCameraUpload()));
+ connect(mCameraDeleteBtn, SIGNAL(pressed()), this, SLOT(slotCameraDeleteSelected()));
+ connect(mDialogCloseBtn, SIGNAL(pressed()), this, SLOT(close()));
+}
+
+void CameraUI::setCameraConnected(bool val) {
+ mCameraDownloadBtn->setEnabled(val);
+ mCameraUploadBtn->setEnabled(val);
+ mCameraDeleteBtn->setEnabled(val);
+ if(val) {
+ mStatusLabel->setText(i18n("Connected"));
+ mCameraConnectBtn->setText(i18n("Disconnect"));
+ } else {
+ mStatusLabel->setText(i18n("Disconnected"));
+ mCameraConnectBtn->setText(i18n("Connect"));
+ }
+}
+
+void CameraUI::slotSetStatusMsg(const QString& msg) {
+ mStatusLabel->setText(msg);
+}
+
+void CameraUI::slotSetProgressVal(int val) {
+ if(val >= 0 && val <= 100) {
+ mProgressBar->setProgress(val);
+ }
+}
+
+void CameraUI::slotResetStatusBar() {
+ mProgressBar->setTotalSteps(100);
+ mProgressBar->setProgress(0);
+}
+
+void CameraUI::slotBusy(bool val) {
+ if(!val) {
+ slotResetStatusBar();
+ }
+ mCameraStopBtn->setEnabled(val);
+}
+
+void CameraUI::slotSetupCamera() {
+ SetupCamera *mSetupDialog = new SetupCamera(this, "camerasetup");
+ mSetupDialog->exec();
+}
+
+void CameraUI::slotSyncCameraComboBox() {
+ mCameraComboBox->clear();
+ QPtrList<CameraType>* mCameraTypeList = mCameraList->cameraList();
+ for(mCameraTypeList->first(); mCameraTypeList->current(); mCameraTypeList->next()) {
+ mCameraComboBox->insertItem(mCameraTypeList->current()->model());
+ }
+}
+
+void CameraUI::setCameraType(const CameraType& ctype) {
+ *mCameraType = ctype;
+ delete controller_;
+ controller_ = new GPController(this, *mCameraType);
+ controller_->start();
+}
+
+void CameraUI::cameraInitialized(bool val) {
+ if(val) {
+ cameraConnected_ = true;
+ setCameraConnected(true);
+ container_->addVirtualFolder(mCameraType->model());
+ container_->addRootFolder("/");
+ controller_->requestGetSubFolders("/");
+ controller_->requestGetAllItemsInfo("/");
+ mFolderView->virtualFolder()->setSelected(true);
+ }
+}
+
+void CameraUI::cameraSubFolder(const QString& folder, const QString& subFolder) {
+ container_->addFolder(folder, subFolder);
+}
+
+void CameraUI::cameraNewItems(const QString& folder, const GPFileItemInfoList& infoList) {
+ QListViewItem *item = mFolderView->currentItem();
+ if (!item) {
+ return;
+ }
+ CameraFolderItem *folderItem = static_cast<CameraFolderItem *>(item);
+ if (folderItem->folderPath() != folder && !folderItem->isVirtualFolder()) {
+ return;
+ }
+ container_->addFiles(folder, infoList);
+ GPFileItemInfoList::const_iterator it;
+ for (it = infoList.begin(); it != infoList.end(); ++it) {
+ if ((*it).mime.contains("image")) {
+ controller_->requestGetThumbnail(folder, (*it).name);
+ }
+ }
+}
+
+void CameraUI::cameraNewItems(const GPFileItemInfoList& infoList) {
+ QListViewItem *item = mFolderView->currentItem();
+ if (!item) {
+ return;
+ }
+ CameraFolderItem *folderItem = static_cast<CameraFolderItem *>(item);
+ if (!folderItem->isVirtualFolder()){
+ return;
+ }
+ container_->addFiles(infoList);
+ GPFileItemInfoList::const_iterator it;
+ for (it = infoList.begin(); it != infoList.end(); ++it) {
+ if ((*it).mime.contains("image")) {
+ controller_->requestGetThumbnail((*it).folder, (*it).name);
+ }
+ }
+}
+
+void CameraUI::cameraNewThumbnail(const QString& folder, const QString& itemName, const QImage& thumbnail) {
+ CameraIconItem *iconItem = container_->findItem(folder, itemName);
+ if (!iconItem) {
+ return;
+ }
+ mIconView->setThumbnail(iconItem, thumbnail);
+}
+
+void CameraUI::cameraDownloadedItem(const QString& folder, const QString& itemName) {
+ CameraIconItem *iconItem = container_->findItem(folder, itemName);
+ if(!iconItem) {
+ return;
+ }
+ mIconView->markDownloaded(iconItem);
+}
+
+void CameraUI::cameraDeletedItem(const QString& folder, const QString& itemName) {
+ container_->delFile(folder, itemName);
+}
+
+void CameraUI::cameraErrorMsg(const QString& msg) {
+ DMessageBox::showMsg(msg);
+}
+
+void CameraUI::slotCameraConnectToggle() {
+ if (mCameraComboBox->count() == 0) {
+ KMessageBox::error(this, i18n("There is no configured camera!"));
+ return;
+ }
+ mCameraType = mCameraList->find(mCameraComboBox->currentText());
+ setCameraType(*mCameraType);
+ setCameraConnected(false);
+ if(!cameraConnected_) {
+ controller_->requestInitialize();
+ } else {
+ delete controller_;
+ controller_ = new GPController(this, *mCameraType);
+ controller_->start();
+ cameraConnected_ = false;
+ mIconView->clear();
+ mFolderView->clear();
+ }
+}
+
+void CameraUI::slotCameraDownloadSelected() {
+ if(!cameraConnected_) {
+ return;
+ }
+ QString dir = mDownloadDirectoryEdit->text();
+ QDir qdir(dir);
+ if(!qdir.exists()) {
+ KMessageBox::error(this, i18n("'%1' directory does not exist.").arg(dir));
+ return;
+ }
+ int count = 0;
+ for(ThumbItem *i = mIconView->firstItem(); i; i=i->nextItem() ) {
+ if (i->isSelected()) {
+ ++count;
+ }
+ }
+ if(count == 0) {
+ return;
+ }
+ bool proceed = true;
+ bool overwriteAll = false;
+ for(ThumbItem *i = mIconView->firstItem(); i; i=i->nextItem()) {
+ if(i->isSelected()) {
+ CameraIconItem *item = static_cast<CameraIconItem*>(i);
+ if(!item) {
+ continue;
+ }
+ downloadOneItem(item->fileInfo()->name, item->fileInfo()->folder, dir, proceed, overwriteAll);
+ if(!proceed) {
+ return;
+ }
+ }
+ }
+}
+
+void CameraUI::slotCameraDeleteSelected() {
+ if(!cameraConnected_) {
+ return;
+ }
+ QStringList deleteList;
+ for (ThumbItem *i = mIconView->firstItem(); i;
+ i=i->nextItem()) {
+ if(i->isSelected()) {
+ CameraIconItem *item = static_cast<CameraIconItem*>(i);
+ deleteList.append(item->fileInfo()->name);
+ }
+ }
+ if (deleteList.isEmpty()) {
+ return;
+ }
+ QString warnMsg(i18n("About to delete these Image(s)\n" "Are you sure?"));
+ if(KMessageBox::warningContinueCancelList(this, warnMsg, deleteList, i18n("Warning"), KGuiItem(i18n("Delete"),"editdelete")) == KMessageBox::Continue) {
+ CameraIconItem *item = static_cast<CameraIconItem*>(mIconView->firstItem());
+ while(item) {
+ CameraIconItem *nextItem = static_cast<CameraIconItem *>(item->nextItem());
+ if (item->isSelected()) {
+ controller_->requestDeleteItem(item->fileInfo()->folder, item->fileInfo()->name);
+ }
+ item = nextItem;
+ }
+ }
+}
+
+void CameraUI::slotCameraUpload() {
+ QString reason;
+ if (! cameraReadyForUpload(reason) ) {
+ KMessageBox::error(0, reason);
+ return;
+ }
+ CameraFolderItem *folderItem = static_cast<CameraFolderItem *>(mFolderView->selectedItem());
+ QStringList list = KFileDialog::getOpenFileNames(QString::null);
+ bool ok;
+ for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
+ QFileInfo info(*it);
+ if(!info.exists()) {
+ continue;
+ }
+ if(info.isDir()) {
+ continue;
+ }
+ QString uploadName = info.fileName();
+ while (container_->findItem(folderItem->folderPath(), uploadName)) {
+ QString msg(i18n("Camera Folder '%1' contains item '%2'\n Please, enter New Name").arg(folderItem->folderName()).arg(uploadName));
+ uploadName = KLineEditDlg::getText(msg,uploadName,&ok,this);
+ if(!ok){
+ return;
+ }
+ }
+ controller_->requestUploadItem(folderItem->folderPath(), info.absFilePath(), uploadName);
+ }
+}
+
+void CameraUI::slotCameraCancel() {
+ controller_->cancel();
+}
+
+void CameraUI::slotSelectAll() {
+ mIconView->selectAll();
+}
+
+void CameraUI::slotSelectNone() {
+ mIconView->clearSelection();
+}
+
+void CameraUI::slotSelectInvert() {
+ mIconView->invertSelection();
+}
+
+void CameraUI::slotSelectNew() {
+ mIconView->clearSelection();
+ for (ThumbItem *it = mIconView->firstItem(); it; it = it->nextItem()) {
+ CameraIconItem *item = static_cast<CameraIconItem *>(it);
+ if (item->fileInfo()->downloaded == 0) {
+ item->setSelected(true, false);
+ }
+ }
+}
+
+void CameraUI::slotFolderSelected(CameraFolderItem *folderItem) {
+ if (!folderItem) {
+ return;
+ }
+ controller_->cancel();
+ mIconView->clear();
+ if (folderItem->isVirtualFolder()) {
+ controller_->requestGetAllItemsInfo("/");
+ } else {
+ controller_->requestGetItemsInfo(folderItem->folderPath());
+ }
+}
+
+void CameraUI::downloadOneItem(const QString& item, const QString& folder, const QString& downloadDir, bool& proceedFurther, bool& overwriteAll) {
+ proceedFurther = true;
+ QString saveFile(downloadDir);
+ if (!downloadDir.endsWith("/")) {
+ saveFile += "/";
+ }
+ saveFile += item;
+ while (QFile::exists(saveFile) && !(overwriteAll)) {
+ bool overwrite=false;
+ SavefileDialog *dlg = new SavefileDialog(saveFile);
+ if (dlg->exec()== QDialog::Rejected) {
+ delete dlg;
+ proceedFurther = false;
+ return;
+ }
+ switch(dlg->saveFileOperation()) {
+ case (SavefileDialog::Skip): {
+ delete dlg;
+ return;
+ }
+ case (SavefileDialog::SkipAll): {
+ delete dlg;
+ proceedFurther = false;
+ return;
+ }
+ case (SavefileDialog::Overwrite): {
+ overwrite = true;
+ delete dlg;
+ break;
+ }
+ case (SavefileDialog::OverwriteAll): {
+ overwriteAll = true;
+ delete dlg;
+ break;
+ }
+ case (SavefileDialog::Rename): {
+ saveFile = downloadDir+"/"+dlg->renameFile();
+ delete dlg;
+ break;
+ }
+ default: {
+ delete dlg;
+ proceedFurther = false;
+ return;
+ }
+ }
+ if (overwrite) {
+ break;
+ }
+ }
+ controller_->requestDownloadItem(folder, item, saveFile);
+}
+
+bool CameraUI::cameraReadyForUpload(QString& reason) {
+ bool result = false;
+ if (!cameraConnected_) {
+ reason = i18n("Camera Not Initialized");
+ return result;
+ } /*
+ if (!controller_->cameraSupportsUpload()) {
+ reason = i18n("Camera does not support Uploads");
+ return result;
+ } */
+ if (!mFolderView->selectedItem() || mFolderView->selectedItem() == mFolderView->firstChild()) {
+ reason = i18n("Please Select a Folder on Camera to Upload");
+ return result;
+ }
+ result = true;
+ return result;
+}
+
+void CameraUI::slotChangeDownloadDirectory() {
+ QString result = KFileDialog::getExistingDirectory(mDownloadDirectoryEdit->text(), this);
+ if(!((new QFileInfo(result))->isWritable())) {
+ KMessageBox::sorry(this, i18n("Sorry! The directory is not writable!"));
+ return;
+ }
+ if(!result.isEmpty()) {
+ mDownloadDirectoryEdit->setText(result);
+ }
+}
+
+void CameraUI::writeSettings() {
+ mConfig = new KConfig("kipirc");
+ mConfig->setGroup("KameraKlient Settings");
+ mConfig->writePathEntry("DownloadDirectory", mDownloadDirectoryEdit->text());
+ mConfig->writeEntry("DialogSize", frameSize());
+ mConfig->writeEntry("DialogXPos", x());
+ mConfig->writeEntry("DialogYPos", y());
+ mConfig->writeEntry("SplitterSizes", mSplitter->sizes());
+ mConfig->sync();
+ delete mConfig;
+}
+
+void CameraUI::readSettings() {
+ mConfig = new KConfig("kipirc");
+ mConfig->setGroup("KameraKlient Settings");
+ mDownloadDirectoryEdit->setText(mConfig->readPathEntry("DownloadDirectory", "$HOME"));
+ resize(mConfig->readSizeEntry("DialogSize"));
+ move(mConfig->readNumEntry("DialogXPos"), mConfig->readNumEntry("DialogYPos"));
+ mSplitter->setSizes(mConfig->readIntListEntry("SplitterSizes"));
+ delete mConfig;
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
diff --git a/kipi-plugins/kameraklient/cameraui.h b/kipi-plugins/kameraklient/cameraui.h
new file mode 100644
index 0000000..2fc6b52
--- /dev/null
+++ b/kipi-plugins/kameraklient/cameraui.h
@@ -0,0 +1,188 @@
+/* ============================================================
+ * File : cameraui.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CAMERAUI_H
+#define CAMERAUI_H
+
+// Qt includes.
+
+#include <qdict.h>
+#include <qstring.h>
+#include <qwidget.h>
+
+// KDE includes.
+
+#include <kfileitem.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "gpfileiteminfo.h"
+#include "cameratype.h"
+
+class QComboBox;
+class QImage;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QSplitter;
+
+class KAccel;
+class KComboBox;
+class KDirLister;
+class KProgress;
+class KStatusBar;
+class KToggleAction;
+
+
+
+namespace KIO {
+class Job;
+}
+
+namespace KIPIKameraKlientPlugin
+{
+
+class CameraList;
+class CameraType;
+class GPEventFilter;
+class GPController;
+class GPFileItemContainer;
+class CameraIconItem;
+class CameraIconView;
+class CameraFolderItem;
+class CameraFolderView;
+
+class CameraUI : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ CameraUI();
+ ~CameraUI();
+ void setCameraConnected(bool val);
+ const CameraType* cameraType();
+ void setCameraType(const CameraType& ctype);
+ void cameraInitialized(bool val);
+ void cameraSubFolder(const QString& folder, const QString& subFolder);
+ void cameraNewItems(const QString& folder, const GPFileItemInfoList& infoList);
+ void cameraNewItems(const GPFileItemInfoList& infoList);
+ void cameraNewThumbnail(const QString& folder, const QString& itemName, const QImage& thumbnail);
+ void cameraDownloadedItem(const QString& folder, const QString& itemName);
+ void cameraDeletedItem(const QString& folder, const QString& itemName);
+ void cameraErrorMsg(const QString& msg);
+
+private:
+
+ void setupAccel();
+ void setupConnections();
+ bool cameraReadyForUpload(QString& reason);
+ void downloadOneItem(const QString& item, const QString& folder,
+ const QString& downloadDir, bool& proceedFurther, bool& overwriteAll);
+
+signals:
+
+ void signalStatusMsg(const QString&);
+ void signalProgressVal(int);
+ void signalBusy(bool);
+
+public slots:
+
+ void slotCameraConnectToggle();
+ void slotCameraDownloadSelected();
+ void slotCameraDeleteSelected();
+ void slotCameraUpload();
+ void slotCameraCancel();
+ void slotSelectAll();
+ void slotSelectNone();
+ void slotSelectInvert();
+ void slotSelectNew();
+
+private slots:
+
+ void slotSetStatusMsg(const QString& msg);
+ void slotSetProgressVal(int val);
+ void slotResetStatusBar();
+ void slotBusy(bool val);
+ void slotSetupCamera();
+ void slotSyncCameraComboBox();
+ void slotFolderSelected(CameraFolderItem *item);
+ void slotChangeDownloadDirectory();
+ void writeSettings();
+ void readSettings();
+ void slotHelp();
+
+private:
+
+ QLabel *mStatusLabel;
+
+ KProgress *mProgressBar;
+
+ QComboBox *mCameraComboBox;
+
+ QPushButton *mCameraConnectBtn;
+ QPushButton *mCameraSetupBtn;
+ QPushButton *mCameraStopBtn;
+ QPushButton *mCameraDownloadBtn;
+ QPushButton *mCameraUploadBtn;
+ QPushButton *mCameraDeleteBtn;
+ QPushButton *mDialogCloseBtn;
+ QPushButton *mChangeDownloadDirectoryBtn;
+ QPushButton *mhelpButton;
+
+ KAccel *mCameraUIAccel;
+
+ KToggleAction *mCameraConnectAction;
+
+ CameraType *mCameraType;
+
+ CameraList *mCameraList;
+
+ KStatusBar *mStatusBar;
+
+ KConfig *mConfig;
+
+ GPEventFilter *efilter_;
+
+ GPController *controller_;
+
+ GPFileItemContainer *container_;
+
+ QSplitter *mSplitter;
+
+ CameraFolderView *mFolderView;
+
+ CameraIconView *mIconView;
+
+ QString cameraPath_;
+
+ bool cameraConnected_;
+
+ QLineEdit *mDownloadDirectoryEdit;
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
diff --git a/kipi-plugins/kameraklient/dmessagebox.cpp b/kipi-plugins/kameraklient/dmessagebox.cpp
new file mode 100644
index 0000000..a25d396
--- /dev/null
+++ b/kipi-plugins/kameraklient/dmessagebox.cpp
@@ -0,0 +1,119 @@
+/* ============================================================
+ * File : dmessagebox.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-22
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+
+ * Update : 09/23/2003 - Gilles Caulier <caulier.gilles@free.fr>
+ * Center the dialog box on the desktop.
+ * Improve i18n messages.
+
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Qt
+#include <qapplication.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qtextedit.h>
+// KDE
+#include <klocale.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+// Local
+#include "dmessagebox.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+DMessageBox* DMessageBox::s_instance = 0;
+
+DMessageBox::DMessageBox() : QWidget(0, 0, WShowModal | WStyle_DialogBorder| WDestructiveClose) {
+ setCaption(i18n("Error"));
+ s_instance = this;
+ count_ = 0;
+ QGridLayout *grid = new QGridLayout(this, 1, 1, 6, 11);
+ // ----------------------------------------------------
+ QHBox *hbox = new QHBox(this);
+ hbox->setSpacing(5);
+ QPixmap pix = KApplication::kApplication()->iconLoader()->loadIcon("error",
+ KIcon::NoGroup,
+ KIcon::SizeMedium,
+ KIcon::DefaultState,
+ 0, true);
+ QLabel *pixLabel = new QLabel(hbox);
+ pixLabel->setPixmap(pix);
+ pixLabel->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
+ msgBox_ = new QLabel(hbox);
+ msgBox_->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
+ grid->addMultiCellWidget(hbox, 0, 0, 0, 2);
+ // ---------------------------------------------------
+ extraMsgBox_ = new QTextEdit(this);
+ extraMsgBox_->setReadOnly(true);
+ grid->addMultiCellWidget(extraMsgBox_, 1, 1, 0, 2);
+ extraMsgBox_->hide();
+ // ---------------------------------------------------
+ QPushButton *okButton = new QPushButton(i18n("&OK"), this);
+ grid->addWidget(okButton, 2, 1);
+ // ---------------------------------------------------
+ grid->addItem(new QSpacerItem(5, 10, QSizePolicy::Expanding, QSizePolicy::Minimum), 2, 0);
+ grid->addItem(new QSpacerItem(5, 10, QSizePolicy::Expanding, QSizePolicy::Minimum), 2, 2);
+ // ---------------------------------------------------
+ connect(okButton, SIGNAL(clicked()), this, SLOT(slotOkClicked()));
+ int W=500;
+ int H=400;
+ move(QApplication::desktop()->width ()/2-(W/2), QApplication::desktop()->height()/2-(H/2));
+}
+
+DMessageBox::~DMessageBox() {
+ s_instance = 0;
+}
+
+void DMessageBox::appendMsg(const QString& msg) {
+ if (count_ == 0) {
+ mainMsg_ = msg;
+ msgBox_->setText(msg);
+ } else {
+ QString text(i18n("More errors occurred and are shown below:"));
+ msgBox_->setText(text);
+ extraMsgBox_->append(msg);
+ if (extraMsgBox_->isHidden()) {
+ extraMsgBox_->show();
+ }
+ }
+ count_++;
+}
+
+void DMessageBox::slotOkClicked() {
+ close();
+}
+
+void DMessageBox::showMsg(const QString& msg) {
+ DMessageBox* msgBox = DMessageBox::s_instance;
+ if (!msgBox) {
+ msgBox = new DMessageBox;
+ }
+ msgBox->appendMsg(msg);
+ if (msgBox->isHidden()) {
+ msgBox->show();
+ }
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "dmessagebox.moc"
diff --git a/kipi-plugins/kameraklient/dmessagebox.h b/kipi-plugins/kameraklient/dmessagebox.h
new file mode 100644
index 0000000..bf36d81
--- /dev/null
+++ b/kipi-plugins/kameraklient/dmessagebox.h
@@ -0,0 +1,61 @@
+/* ============================================================
+ * File : dmessagebox.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-22
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 DMESSAGEBOX_H
+#define DMESSAGEBOX_H
+
+// Digikam Message Box
+// If One Message Box is already open, and more messages are posted they will be appended to the open messagebox
+
+#include <qwidget.h>
+#include <qstring.h>
+
+class QLabel;
+class QTextEdit;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class DMessageBox : public QWidget {
+ Q_OBJECT
+
+public:
+ DMessageBox();
+ ~DMessageBox();
+
+ void appendMsg(const QString& msg);
+ static void showMsg(const QString& msg);
+
+private:
+ static DMessageBox* s_instance;
+
+ int count_;
+ QLabel *msgBox_;
+ QTextEdit *extraMsgBox_;
+ QString mainMsg_;
+
+private slots:
+ void slotOkClicked();
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif /* DMESSAGEBOX_H */
diff --git a/kipi-plugins/kameraklient/gpcamera.cpp b/kipi-plugins/kameraklient/gpcamera.cpp
new file mode 100644
index 0000000..40dcb24
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpcamera.cpp
@@ -0,0 +1,601 @@
+/* ============================================================
+ * File : gpcamera.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qimage.h>
+#include <qfile.h>
+// KDE
+#include <kdebug.h>
+// Standard
+#include <iostream>
+extern "C" {
+#include <stdio.h>
+#include <gphoto2.h>
+}
+// Local
+#include "gpstatus.h"
+#include "gpcamera.h"
+#include "cameralist.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPCameraPrivate {
+public:
+ Camera *camera;
+ CameraAbilities cameraAbilities;
+ QString model;
+ QString port;
+ bool cameraSetup;
+ bool cameraInitialized;
+ bool thumbnailSupport;
+ bool deleteSupport;
+ bool uploadSupport;
+ bool mkDirSupport;
+ bool delDirSupport;
+};
+
+GPCamera::GPCamera(const QString& model, const QString& port) {
+ status = 0;
+ d = new GPCameraPrivate;
+ d->camera = 0;
+ d->model = model;
+ d->port = port;
+ d->cameraSetup = false;
+ d->cameraInitialized = false;
+ d->thumbnailSupport = false;
+ d->deleteSupport = false;
+ d->uploadSupport = false;
+ d->mkDirSupport = false;
+ d->delDirSupport = false;
+ setup();
+}
+
+GPCamera::~GPCamera() {
+ if (d->camera) {
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ }
+ delete d;
+}
+
+int GPCamera::setup() {
+ if (d->camera) {
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ }
+ CameraAbilitiesList *abilList;
+ GPPortInfoList *infoList;
+ GPPortInfo info;
+
+ gp_camera_new(&d->camera);
+
+ if (status) {
+ delete status;
+ status = 0;
+ }
+
+ status = new GPStatus();
+
+ gp_abilities_list_new(&abilList);
+ gp_abilities_list_load(abilList, status->context);
+ gp_port_info_list_new(&infoList);
+ gp_port_info_list_load(infoList);
+
+ delete status;
+ status = 0;
+
+ int modelNum = -1, portNum = -1;
+ modelNum = gp_abilities_list_lookup_model(abilList, d->model.latin1());
+ portNum = gp_port_info_list_lookup_path (infoList, d->port.latin1());
+
+ gp_abilities_list_get_abilities(abilList, modelNum, &d->cameraAbilities);
+
+ if (gp_camera_set_abilities(d->camera, d->cameraAbilities) != GP_OK) {
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ gp_abilities_list_free(abilList);
+ gp_port_info_list_free(infoList);
+ return GPSetup;
+ }
+ if (d->model != "Directory Browse") {
+ gp_port_info_list_get_info(infoList, portNum, &info);
+ if (gp_camera_set_port_info(d->camera, info) != GP_OK) {
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ gp_abilities_list_free (abilList);
+ gp_port_info_list_free (infoList);
+ return GPSetup;
+ }
+ }
+ gp_abilities_list_free (abilList);
+ gp_port_info_list_free (infoList);
+ if (d->cameraAbilities.file_operations & GP_FILE_OPERATION_PREVIEW) {
+ d->thumbnailSupport = true;
+ }
+ if (d->cameraAbilities.file_operations & GP_FILE_OPERATION_DELETE) {
+ d->deleteSupport = true;
+ }
+ if (d->cameraAbilities.folder_operations & GP_FOLDER_OPERATION_PUT_FILE) {
+ d->uploadSupport = true;
+ }
+ if (d->cameraAbilities.folder_operations & GP_FOLDER_OPERATION_MAKE_DIR) {
+ d->mkDirSupport = true;
+ }
+ if (d->cameraAbilities.folder_operations & GP_FOLDER_OPERATION_REMOVE_DIR) {
+ d->delDirSupport = true;
+ }
+ d->cameraSetup = true;
+ return GPSuccess;
+}
+
+int GPCamera::initialize() {
+ if (!d->cameraSetup || !d->camera) {
+ int result = setup();
+ if (result != GPSuccess) {
+ return result;
+ }
+ }
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus();
+ // Try and initialize the camera to see if its connected
+ if (gp_camera_init(d->camera, status->context) != GP_OK) {
+ gp_camera_unref(d->camera);
+ d->camera = 0;
+ delete status;
+ status = 0;
+ return GPInit;
+ }
+ delete status;
+ status = 0;
+ d->cameraInitialized = true;
+ return GPSuccess;
+}
+
+void GPCamera::cancel() {
+ if (!status) {
+ return;
+ }
+ status->cancelOperation();
+}
+
+bool GPCamera::thumbnailSupport() {
+ return d->thumbnailSupport;
+}
+
+bool GPCamera::deleteSupport() {
+ return d->deleteSupport;
+}
+
+bool GPCamera::uploadSupport() {
+ return d->uploadSupport;
+}
+
+bool GPCamera::mkDirSupport() {
+ return d->mkDirSupport;
+}
+
+bool GPCamera::delDirSupport() {
+ return d->delDirSupport;
+}
+
+int GPCamera::getSubFolders(const QString& folder, QValueList<QString>& subFolderList) {
+ ::CameraList *clist;
+ gp_list_new(&clist);
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus();
+ if (gp_camera_folder_list_folders(d->camera, folder.latin1(), clist, status->context) != GP_OK) {
+ gp_list_unref(clist);
+ delete status;
+ status = 0;
+ return GPError;
+ }
+ delete status;
+ status = 0;
+ int count = gp_list_count(clist);
+ for (int i=0; i<count; i++) {
+ const char* subFolder;
+ if (gp_list_get_name(clist, i, &subFolder) != GP_OK) {
+ gp_list_unref(clist);
+ return GPError;
+ }
+ subFolderList.append(QString(subFolder));
+ }
+ gp_list_unref(clist);
+ return GPSuccess;
+}
+
+void GPCamera::getAllItemsInfo(const QString& folder, GPFileItemInfoList& infoList) {
+ QValueList<QString> folderList;
+ folderList.clear();
+ // Get all items in this folder first
+ getItemsInfo(folder, infoList);
+ // Get all subfolders in this folder
+ getSubFolders(folder, folderList);
+ if (folderList.count() > 0) {
+ for (unsigned int i=0; i<folderList.count(); i++) {
+ QString subFolder(folder);
+ if (!subFolder.endsWith("/")) {
+ subFolder += "/";
+ }
+ subFolder += folderList[i];
+ getAllItemsInfo(subFolder, infoList);
+ }
+ }
+}
+
+int GPCamera::getItemsInfo(const QString& folder, GPFileItemInfoList& infoList) {
+ ::CameraList *clist;
+ const char *cname;
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus;
+ gp_list_new(&clist);
+ if (gp_camera_folder_list_files(d->camera, folder.latin1(), clist, status->context) != GP_OK) {
+ gp_list_unref(clist);
+ delete status;
+ status = 0;
+ return GPError;
+ }
+ int count = gp_list_count(clist);
+ for (int i=0; i<count; i++) {
+ if (gp_list_get_name(clist, i, &cname) != GP_OK) {
+ gp_list_unref(clist);
+ delete status;
+ status = 0;
+ return GPError;
+ }
+ GPFileItemInfo camFileInfo;
+ camFileInfo.name = QString(cname);
+ camFileInfo.folder = folder;
+ CameraFileInfo info;
+ if (gp_camera_file_get_info(d->camera, folder.latin1(), cname, &info, status->context) == GP_OK) {
+ if (info.file.fields != GP_FILE_INFO_NONE) {
+ camFileInfo.fileInfoAvailable = true;
+
+ if (info.file.fields & GP_FILE_INFO_TYPE) {
+ camFileInfo.mime = QString(info.file.type);
+ }
+ if (info.file.fields & GP_FILE_INFO_SIZE) {
+ camFileInfo.size = info.file.size;
+ }
+ if (info.file.fields & GP_FILE_INFO_WIDTH) {
+ camFileInfo.width = info.file.width;
+ }
+ if (info.file.fields & GP_FILE_INFO_HEIGHT) {
+ camFileInfo.height = info.file.height;
+ }
+ if (info.file.fields & GP_FILE_INFO_STATUS) {
+ if (info.file.status == GP_FILE_STATUS_DOWNLOADED) {
+ camFileInfo.downloaded = 1;
+ } else {
+ camFileInfo.downloaded = 0;
+ }
+ }
+ if (info.file.fields & GP_FILE_INFO_PERMISSIONS) {
+ if (info.file.permissions & GP_FILE_PERM_READ) {
+ camFileInfo.readPermissions = 1;
+ } else {
+ camFileInfo.readPermissions = 0;
+ }
+ if (info.file.permissions & GP_FILE_PERM_DELETE) {
+ camFileInfo.writePermissions = 1;
+ } else {
+ camFileInfo.writePermissions = 0;
+ }
+ }
+ if (info.file.fields & GP_FILE_INFO_MTIME) {
+ QString time = QString(asctime(localtime(&info.file.mtime)));
+ time.truncate(time.length()-1);
+ camFileInfo.time = time;
+ }
+
+ }
+ }
+ infoList.append(camFileInfo);
+ }
+ gp_list_unref(clist);
+ delete status;
+ status = 0;
+ return GPSuccess;
+}
+
+int GPCamera::getThumbnail(const QString& folder, const QString& imageName, QImage& thumbnail) {
+ CameraFile *cfile;
+ const char* data;
+ unsigned long int size;
+ gp_file_new(&cfile);
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus;
+ if (gp_camera_file_get(d->camera, folder.latin1(), imageName.latin1(), GP_FILE_TYPE_PREVIEW, cfile, status->context) != GP_OK) {
+ gp_file_unref(cfile);
+ delete status;
+ status = 0;
+ return GPError;
+ }
+ delete status;
+ status = 0;
+ gp_file_get_data_and_size(cfile, &data, &size);
+ thumbnail.loadFromData((const uchar*) data, (uint) size);
+ gp_file_unref (cfile);
+ return GPSuccess;
+}
+
+int GPCamera::downloadItem(const QString& folder, const QString& itemName, const QString& saveFile) {
+ CameraFile *cfile;
+ gp_file_new(&cfile);
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus;
+ if (gp_camera_file_get(d->camera, folder.latin1(), itemName.latin1(), GP_FILE_TYPE_NORMAL, cfile, status->context) != GP_OK) {
+ gp_file_unref(cfile);
+ delete status;
+ status = 0;
+ return GPError;
+ }
+ delete status;
+ status = 0;
+ if (gp_file_save(cfile, saveFile.latin1()) != GP_OK) {
+ gp_file_unref(cfile);
+ return GPError;
+ }
+ gp_file_unref(cfile);
+ return GPSuccess;
+}
+
+int GPCamera::deleteItem(const QString& folder, const QString& itemName) {
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus;
+ if(gp_camera_file_delete(d->camera, folder.latin1(), itemName.latin1(), status->context) != GP_OK) {
+ delete status;
+ status = 0;
+ return GPError;
+ }
+ delete status;
+ status = 0;
+ return GPSuccess;
+}
+
+// recursively delete all items
+int GPCamera::deleteAllItems(const QString& folder) {
+ QValueList<QString> folderList;
+ folderList.clear();
+ // Get all subfolders in this folder
+ getSubFolders(folder, folderList);
+ if (folderList.count() > 0) {
+ for (unsigned int i=0; i<folderList.count(); i++) {
+ QString subFolder(folder);
+ if (!subFolder.endsWith("/"))
+ subFolder += "/";
+ subFolder += folderList[i];
+
+ deleteAllItems(subFolder);
+ }
+ }
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus;
+ if (gp_camera_folder_delete_all(d->camera, folder.latin1(), status->context) != GP_OK) {
+ delete status;
+ status = 0;
+ return GPError;
+ }
+ delete status;
+ status = 0;
+ return GPSuccess;
+}
+
+int GPCamera::uploadItem(const QString& folder, const QString& itemName, const QString& localFile) {
+ CameraFile *cfile;
+ gp_file_new(&cfile);
+ if (gp_file_open(cfile, QFile::encodeName( localFile )) != GP_OK) {
+ gp_file_unref(cfile);
+ return GPError;
+ }
+ gp_file_set_name(cfile, QFile::encodeName( itemName ));
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus;
+ if (gp_camera_folder_put_file(d->camera, folder.latin1(), cfile, status->context) != GP_OK) {
+ gp_file_unref(cfile);
+ delete status;
+ status = 0;
+ return GPError;
+ }
+ gp_file_unref(cfile);
+ delete status;
+ status = 0;
+ return GPSuccess;
+}
+
+void GPCamera::cameraSummary(QString& summary) {
+ CameraText sum;
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus;
+ gp_camera_get_summary(d->camera, &sum, status->context);
+ summary = QString(sum.text);
+ delete status;
+ status = 0;
+}
+
+void GPCamera::cameraManual(QString& manual) {
+ CameraText man;
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus;
+ gp_camera_get_manual(d->camera, &man, status->context);
+ manual = QString(man.text);
+ delete status;
+ status = 0;
+}
+
+void GPCamera::cameraAbout(QString& about) {
+ CameraText abt;
+ if (status) {
+ delete status;
+ status = 0;
+ }
+ status = new GPStatus;
+ gp_camera_get_about(d->camera, &abt, status->context);
+ about = QString(abt.text);
+ delete status;
+ status = 0;
+}
+
+// Static functions
+void GPCamera::getSupportedCameras(int& count, QStringList& clist) {
+ clist.clear();
+ count = 0;
+
+ CameraAbilitiesList *abilList;
+ CameraAbilities abil;
+ GPContext *context;
+
+ context = gp_context_new ();
+
+ gp_abilities_list_new( &abilList );
+ gp_abilities_list_load( abilList, context );
+
+ count = gp_abilities_list_count( abilList );
+ if ( count < 0) {
+ gp_context_unref( context );
+ qWarning("failed to get list of cameras");
+ return;
+ } else {
+ for (int i=0; i<count; i++) {
+ const char *cname;
+ gp_abilities_list_get_abilities( abilList, i, &abil );
+ cname = abil.model;
+ clist.append( QString( cname ) );
+ }
+ }
+ gp_abilities_list_free( abilList );
+ gp_context_unref( context );
+}
+
+void GPCamera::getSupportedPorts(QStringList& plist) {
+ GPPortInfoList *list;
+ GPPortInfo info;
+
+ plist.clear();
+
+ gp_port_info_list_new( &list );
+ gp_port_info_list_load( list );
+
+ int numPorts = gp_port_info_list_count( list );
+ for (int i = 0; i < numPorts; i++) {
+ gp_port_info_list_get_info( list, i, &info );
+ plist.append(info.path);
+ }
+ gp_port_info_list_free( list );
+}
+
+void GPCamera::getCameraSupportedPorts(const QString& model, QStringList& plist) {
+ int i = 0;
+ plist.clear();
+
+ CameraAbilities abilities;
+ CameraAbilitiesList *abilList;
+ GPContext *context;
+
+ context = gp_context_new ();
+
+ gp_abilities_list_new (&abilList);
+ gp_abilities_list_load (abilList, context);
+ i = gp_abilities_list_lookup_model (abilList, model.local8Bit().data());
+ gp_abilities_list_get_abilities (abilList, i, &abilities);
+ gp_abilities_list_free (abilList);
+
+ if (abilities.port & GP_PORT_SERIAL) {
+ plist.append("serial");
+ }
+ if (abilities.port & GP_PORT_USB) {
+ plist.append("usb");
+ }
+ gp_context_unref( context );
+
+}
+
+int GPCamera::autoDetect(QString& model, QString& port) {
+ ::CameraList *pCamList;
+ CameraAbilitiesList *abilList;
+ GPPortInfoList *infoList;
+ const char *camModel_, *camPort_;
+ GPContext *context;
+
+ context = gp_context_new ();
+ gp_list_new(&pCamList);
+
+ gp_abilities_list_new (&abilList);
+ gp_abilities_list_load (abilList, context);
+ gp_port_info_list_new (&infoList);
+ gp_port_info_list_load (infoList);
+ gp_abilities_list_detect (abilList, infoList, pCamList, context);
+ gp_abilities_list_free (abilList);
+ gp_port_info_list_free (infoList);
+
+ gp_context_unref( context );
+
+ int count = gp_list_count (pCamList);
+
+ if (count<=0) {
+ gp_list_free(pCamList);
+ return -1;
+ }
+ for (int i = 0; i < count; i++) {
+ gp_list_get_name (pCamList, i, &camModel_);
+ gp_list_get_value (pCamList, i, &camPort_);
+ }
+ model = camModel_;
+ port = camPort_;
+ gp_list_free(pCamList);
+
+ return 0;
+}
+
+} // NameSpace KIPIKameraKlientPlugin
diff --git a/kipi-plugins/kameraklient/gpcamera.h b/kipi-plugins/kameraklient/gpcamera.h
new file mode 100644
index 0000000..ca4ea48
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpcamera.h
@@ -0,0 +1,93 @@
+/* ============================================================
+ * File : gpcamera.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPCAMERA_H
+#define GPCAMERA_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+
+#include "gpfileiteminfo.h"
+
+class QImage;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPCameraPrivate;
+class GPStatus;
+
+class GPCamera {
+
+public:
+ enum {
+ GPError=0,
+ GPInit,
+ GPSetup,
+ GPSuccess
+ } Errors;
+
+
+ GPCamera(const QString& model, const QString& port);
+ ~GPCamera();
+
+ bool thumbnailSupport();
+ bool deleteSupport();
+ bool uploadSupport();
+ bool mkDirSupport();
+ bool delDirSupport();
+
+ int initialize();
+
+ void cancel();
+
+ int getSubFolders(const QString& folder, QValueList<QString>& subFolderList);
+
+ void getAllItemsInfo(const QString& folder, GPFileItemInfoList& infoList);
+ int getItemsInfo(const QString& folder, GPFileItemInfoList& infoList);
+ int getThumbnail(const QString& folder, const QString& imageName, QImage& thumbnail);
+ int downloadItem(const QString& folder, const QString& itemName, const QString& saveFile);
+ int deleteItem(const QString& folder, const QString& itemName);
+
+ // recursively delete all items
+ int deleteAllItems(const QString& folder);
+ int uploadItem(const QString& folder, const QString& itemName, const QString& localFile);
+ void cameraSummary(QString& summary);
+ void cameraManual(QString& manual);
+ void cameraAbout(QString& about);
+
+ // Static Functions
+ static void getSupportedCameras(int& count, QStringList& clist);
+ static void getSupportedPorts(QStringList& plist);
+ static void getCameraSupportedPorts(const QString& model, QStringList& plist);
+ static int autoDetect(QString& model, QString& port);
+
+private:
+ int setup();
+ GPCameraPrivate *d;
+ GPStatus *status;
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/gpcommand.h b/kipi-plugins/kameraklient/gpcommand.h
new file mode 100644
index 0000000..08a6bd9
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpcommand.h
@@ -0,0 +1,259 @@
+/* ============================================================
+ * File : gpcommand.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-22
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPCOMMAND_H
+#define GPCOMMAND_H
+
+#include <qstring.h>
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPCommand {
+public:
+ enum Type {
+ Init=0,
+ GetSubFolders,
+ MakeFolder,
+ DeleteFolder,
+ GetItemsInfo,
+ GetAllItemsInfo,
+ GetThumbnail,
+ DownloadItem,
+ DeleteItem,
+ DeleteAllItems,
+ OpenItem,
+ OpenItemWithService,
+ UploadItem,
+ ExifInfo
+ };
+ GPCommand(Type type) : type_(type) {
+ }
+ Type type() const {
+ return type_;
+ }
+
+private:
+ Type type_;
+};
+
+class GPCommandGetSubFolders : public GPCommand {
+public:
+ GPCommandGetSubFolders(const QString& folder) : GPCommand(GetSubFolders), folder_(folder) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+private:
+ QString folder_;
+};
+
+class GPCommandMakeFolder : public GPCommand {
+public:
+ GPCommandMakeFolder(const QString& folder, const QString& newFolder)
+ : GPCommand(MakeFolder), folder_(folder), newFolder_(newFolder) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+ QString newFolder() const {
+ return newFolder_;
+ }
+private:
+ QString folder_;
+ QString newFolder_;
+};
+
+class GPCommandDeleteFolder : public GPCommand {
+public:
+ GPCommandDeleteFolder(const QString& folder) : GPCommand(DeleteFolder), folder_(folder) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+private:
+ QString folder_;
+};
+
+class GPCommandGetItemsInfo : public GPCommand {
+public:
+ GPCommandGetItemsInfo(const QString& folder) : GPCommand(GetItemsInfo), folder_(folder) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+private:
+ QString folder_;
+};
+
+class GPCommandGetAllItemsInfo : public GPCommand {
+public:
+ GPCommandGetAllItemsInfo(const QString& folder) : GPCommand(GetAllItemsInfo), folder_(folder) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+private:
+ QString folder_;
+};
+
+class GPCommandGetThumbnail : public GPCommand {
+public:
+ GPCommandGetThumbnail(const QString& folder, const QString& imageName)
+ : GPCommand(GetThumbnail), folder_(folder), imageName_(imageName) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+ QString imageName() const {
+ return imageName_;
+ }
+
+private:
+ QString folder_;
+ QString imageName_;
+};
+
+class GPCommandDownloadItem : public GPCommand {
+public:
+ GPCommandDownloadItem(const QString& folder, const QString& itemName, const QString& saveFile) : GPCommand(DownloadItem), folder_(folder), itemName_(itemName), saveFile_(saveFile) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+ QString itemName() const {
+ return itemName_;
+ }
+ QString saveFile() const {
+ return saveFile_;
+ }
+private:
+ QString folder_;
+ QString itemName_;
+ QString saveFile_;
+};
+
+class GPCommandDeleteItem : public GPCommand {
+public:
+ GPCommandDeleteItem(const QString& folder, const QString& itemName) : GPCommand(DeleteItem), folder_(folder), itemName_(itemName) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+ QString itemName() const {
+ return itemName_;
+ }
+private:
+ QString folder_;
+ QString itemName_;
+};
+
+class GPCommandDeleteAllItems : public GPCommand {
+public:
+ GPCommandDeleteAllItems(const QString& rootFolder) : GPCommand(DeleteAllItems), folder_(rootFolder) {
+ }
+ QString rootFolder() const {
+ return folder_;
+ }
+private:
+ QString folder_;
+};
+
+class GPCommandUploadItem : public GPCommand {
+public:
+ GPCommandUploadItem(const QString& folder, const QString& localFile, const QString& uploadName) : GPCommand(UploadItem), folder_(folder), localFile_(localFile), uploadName_(uploadName) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+ QString localFile() const {
+ return localFile_;
+ }
+ QString uploadName() const {
+ return uploadName_;
+ }
+private:
+ QString folder_;
+ QString localFile_;
+ QString uploadName_;
+};
+
+class GPCommandOpenItem : public GPCommand {
+public:
+ GPCommandOpenItem(const QString& folder, const QString& itemName, const QString& saveFile) : GPCommand(OpenItem), folder_(folder), itemName_(itemName), saveFile_(saveFile) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+ QString itemName() const {
+ return itemName_;
+ }
+ QString saveFile() const {
+ return saveFile_;
+ }
+private:
+ QString folder_;
+ QString itemName_;
+ QString saveFile_;
+};
+
+class GPCommandOpenItemWithService : public GPCommand {
+public:
+ GPCommandOpenItemWithService(const QString& folder, const QString& itemName, const QString& saveFile, const QString& serviceName) : GPCommand(OpenItemWithService), folder_(folder), itemName_(itemName), saveFile_(saveFile), serviceName_(serviceName) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+ QString itemName() const {
+ return itemName_;
+ }
+ QString saveFile() const {
+ return saveFile_;
+ }
+ QString serviceName() const {
+ return serviceName_;
+ }
+private:
+ QString folder_;
+ QString itemName_;
+ QString saveFile_;
+ QString serviceName_;
+};
+
+class GPCommandExifInfo : public GPCommand {
+public:
+ GPCommandExifInfo(const QString& folder, const QString& itemName) : GPCommand(ExifInfo), folder_(folder), itemName_(itemName) {
+ }
+ QString folder() const {
+ return folder_;
+ }
+ QString itemName() const {
+ return itemName_;
+ }
+private:
+ QString folder_;
+ QString itemName_;
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif /* GPCOMMAND_H */
+
diff --git a/kipi-plugins/kameraklient/gpcontroller.cpp b/kipi-plugins/kameraklient/gpcontroller.cpp
new file mode 100644
index 0000000..3565253
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpcontroller.cpp
@@ -0,0 +1,457 @@
+/* ============================================================
+ * File : gpcontroller.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-22
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+
+ * Update : 09/23/2003 - Gilles Caulier <caulier.gilles@free.fr>
+ * Improve i18n messages.
+
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Standard
+#include <iostream>
+// Qt
+#include <qapplication.h>
+#include <qstring.h>
+#include <qimage.h>
+#include <qcolor.h>
+// KDE
+#include <kdebug.h>
+#include <klocale.h>
+// Local
+#include "gpfileiteminfo.h"
+#include "mtlist.h"
+#include "gpcamera.h"
+#include "gpevents.h"
+#include "gpmessages.h"
+#include "gpcontroller.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+GPController::GPController(QObject *parent, const CameraType& ctype) : QObject(parent) {
+ parent_ = parent;
+ camera_ = new GPCamera(QString(ctype.model().latin1()), QString(ctype.port().latin1()));
+ close_ = false;
+ connect(GPMessages::gpMessagesWrapper(), SIGNAL(statusChanged(const QString&)),
+ this, SLOT(slotStatusMsg(const QString&)) );
+ connect(GPMessages::gpMessagesWrapper(), SIGNAL(progressChanged(int)),
+ this, SLOT(slotProgressVal(int)) );
+ connect(GPMessages::gpMessagesWrapper(), SIGNAL(errorMessage(const QString&)),
+ this, SLOT(slotErrorMsg(const QString&)));
+}
+
+GPController::~GPController() {
+ close_ = true;
+ wait();
+ cmdQueue_.flush();
+ GPMessages::deleteMessagesWrapper();
+ delete camera_;
+
+}
+
+void GPController::requestInitialize() {
+ cmdQueue_.enqueue(new GPCommand(GPCommand::Init));
+}
+
+void GPController::requestGetSubFolders(const QString& folder) {
+ cmdQueue_.enqueue(new GPCommandGetSubFolders(folder));
+}
+
+void GPController::requestMakeFolder(const QString& folder, const QString& newFolder) {
+ cmdQueue_.enqueue(new GPCommandMakeFolder(folder, newFolder));
+}
+
+void GPController::requestDeleteFolder(const QString& folder) {
+ cmdQueue_.enqueue(new GPCommandDeleteFolder(folder));
+}
+
+void GPController::requestGetItemsInfo(const QString& folder) {
+ cmdQueue_.enqueue(new GPCommandGetItemsInfo(folder));
+}
+
+void GPController::requestGetAllItemsInfo(const QString& folder) {
+ cmdQueue_.enqueue(new GPCommandGetAllItemsInfo(folder));
+}
+
+void GPController::requestGetThumbnail(const QString& folder, const QString& imageName) {
+ cmdQueue_.enqueue(new GPCommandGetThumbnail(folder, imageName));
+}
+
+void GPController::requestDownloadItem(const QString& folder, const QString& itemName, const QString& saveFile) {
+ cmdQueue_.enqueue(new GPCommandDownloadItem(folder, itemName, saveFile));
+}
+
+void GPController::requestDeleteItem(const QString& folder, const QString& itemName) {
+ cmdQueue_.enqueue(new GPCommandDeleteItem(folder, itemName));
+}
+
+void GPController::requestUploadItem(const QString& folder, const QString& localFile, const QString& uploadName) {
+ cmdQueue_.enqueue(new GPCommandUploadItem(folder, localFile, uploadName));
+}
+
+void GPController::requestOpenItem(const QString& folder, const QString& itemName, const QString& saveFile) {
+ cmdQueue_.enqueue(new GPCommandOpenItem(folder, itemName, saveFile));
+}
+
+void GPController::requestOpenItemWithService(const QString& folder, const QString& itemName, const QString& saveFile, const QString& serviceName) {
+ cmdQueue_.enqueue(new GPCommandOpenItemWithService(folder, itemName, saveFile, serviceName));
+}
+
+void GPController::cancel() {
+ cmdQueue_.flush();
+ mutex_.lock();
+ camera_->cancel();
+ mutex_.unlock();
+}
+
+void GPController::run() {
+ while(true) {
+ if(cmdQueue_.isEmpty())
+ showBusy(false);
+
+ if(close_) return;
+
+ while(cmdQueue_.isEmpty()) {
+ if (close_) return;
+ msleep(200);
+ }
+
+ GPCommand *cmd = cmdQueue_.dequeue();
+ if(!cmd) {
+ continue;
+ }
+ showBusy(true);
+ switch(cmd->type()) {
+ case(GPCommand::Init): {
+ initialize();
+ break;
+ }
+ case(GPCommand::GetSubFolders): {
+ GPCommandGetSubFolders *command = static_cast<GPCommandGetSubFolders *>(cmd);
+ getSubFolders(command->folder());
+ delete command;
+ cmd = 0;
+ break;
+ }
+ case(GPCommand::GetItemsInfo): {
+ GPCommandGetItemsInfo *command = static_cast<GPCommandGetItemsInfo *>(cmd);
+ getItemsInfo(command->folder());
+ delete command;
+ cmd = 0;
+ break;
+ }
+ case(GPCommand::GetAllItemsInfo): {
+ GPCommandGetAllItemsInfo *command = static_cast<GPCommandGetAllItemsInfo *>(cmd);
+ getAllItemsInfo(command->folder());
+ delete command;
+ cmd = 0;
+ break;
+ }
+ case(GPCommand::GetThumbnail): {
+ GPCommandGetThumbnail *command = static_cast<GPCommandGetThumbnail *>(cmd);
+ getThumbnail(command->folder(), command->imageName());
+ delete command;
+ cmd = 0;
+ break;
+ }
+ case(GPCommand::DownloadItem): {
+ GPCommandDownloadItem *command = static_cast<GPCommandDownloadItem *>(cmd);
+ downloadItem(command->folder(), command->itemName(), command->saveFile());
+ delete command;
+ cmd = 0;
+ break;
+ }
+ case(GPCommand::DeleteItem): {
+ GPCommandDeleteItem *command = static_cast<GPCommandDeleteItem *>(cmd);
+ deleteItem(command->folder(), command->itemName());
+ delete command;
+ cmd = 0;
+ break;
+ }
+ case(GPCommand::UploadItem): {
+ GPCommandUploadItem *command = static_cast<GPCommandUploadItem *>(cmd);
+ uploadItem(command->folder(), command->uploadName(), command->localFile());
+ delete command;
+ cmd = 0;
+ break;
+ }
+ case(GPCommand::OpenItem): {
+ GPCommandOpenItem *command = static_cast<GPCommandOpenItem *>(cmd);
+ openItem(command->folder(), command->itemName(),
+ command->saveFile());
+ delete command;
+ cmd = 0;
+ break;
+ }
+ case(GPCommand::OpenItemWithService): {
+ GPCommandOpenItemWithService *command = static_cast<GPCommandOpenItemWithService *>(cmd);
+ openItemWithService(command->folder(),
+ command->itemName(),
+ command->saveFile(),
+ command->serviceName());
+ delete command;
+ cmd = 0;
+ break;
+ }
+ default:
+ qWarning("GPController: Unknown Command");
+ break;
+ }
+ if (cmd) {
+ delete cmd;
+ }
+ }
+}
+
+void GPController::initialize() {
+ mutex_.lock();
+ int result = camera_->initialize();
+ mutex_.unlock();
+ if (result == GPCamera::GPSuccess) {
+ QApplication::postEvent(parent_, new GPEvent(GPEvent::Init));
+ }
+ else if (result == GPCamera::GPSetup) {
+ QString msg(i18n("Camera Model or Port not specified correctly.\n" "Please run Setup"));
+ error(msg);
+ } else {
+ QString msg(i18n("Failed to initialize camera.\n" "Please ensure camera is connected properly and turned on"));
+ error(msg);
+ }
+}
+
+void GPController::getSubFolders(const QString& folder) {
+ QValueList<QString> subFolderList;
+ subFolderList.clear();
+ mutex_.lock();
+ int result = camera_->getSubFolders(folder, subFolderList);
+ mutex_.unlock();
+ if (result == GPCamera::GPSuccess) {
+ QApplication::postEvent(parent_, new GPEventGetSubFolders(folder, subFolderList));
+ if (subFolderList.count() > 0) {
+ for (unsigned int i=0; i<subFolderList.count(); i++) {
+ QString subFolder(folder);
+ if (subFolder.endsWith("/"))
+ subFolder += subFolderList[i];
+ else
+ subFolder += "/" + subFolderList[i];
+ getSubFolders(subFolder);
+ }
+ }
+ return;
+ } else {
+ QString msg(i18n("Failed to get subfolder names from '%1'\n").arg(folder));
+ error(msg);
+ return;
+ }
+}
+
+void GPController::makeFolder(const QString&, const QString&) {
+}
+
+void GPController::deleteFolder(const QString&) {
+}
+
+void GPController::getItemsInfo(const QString& folder) {
+ GPFileItemInfoList infoList;
+ infoList.clear();
+ mutex_.lock();
+ int result = camera_->getItemsInfo(folder, infoList);
+ mutex_.unlock();
+ if (result == GPCamera::GPSuccess) {
+ QApplication::postEvent(parent_, new GPEventGetItemsInfo(folder, infoList));
+ } else {
+ QString msg(i18n("Failed to get images information from '%1'\n").arg(folder));
+ error(msg);
+ }
+}
+
+void GPController::getAllItemsInfo(const QString& folder) {
+ GPFileItemInfoList infoList;
+ infoList.clear();
+ mutex_.lock();
+ camera_->getAllItemsInfo(folder, infoList);
+ mutex_.unlock();
+ QApplication::postEvent(parent_, new GPEventGetAllItemsInfo(infoList));
+}
+
+void GPController::getThumbnail(const QString& folder, const QString& imageName) {
+ QImage thumbnail;
+ mutex_.lock();
+ int result = camera_->getThumbnail(folder, imageName, thumbnail);
+ mutex_.unlock();
+ if (result == GPCamera::GPSuccess) {
+ scaleHighlightThumbnail(thumbnail);
+ QApplication::postEvent(parent_, new GPEventGetThumbnail(folder, imageName, thumbnail));
+ } else {
+ kdWarning() << i18n("Failed to get preview for '%1/%2'").arg(folder).arg(imageName) << endl;
+ }
+}
+
+void GPController::downloadItem(const QString& folder, const QString& itemName, const QString& saveFile) {
+ mutex_.lock();
+ int result = camera_->downloadItem(folder, itemName, saveFile);
+ mutex_.unlock();
+ if (result != GPCamera::GPSuccess) {
+ QString msg(i18n("Failed to download '%1' from '%2'").arg(itemName).arg(folder));
+ error(msg);
+ } else {
+ QApplication::postEvent(parent_, new GPEventDownloadItem(folder, itemName));
+ }
+}
+
+void GPController::openItem(const QString& folder, const QString& itemName, const QString& saveFile) {
+ mutex_.lock();
+ int result = camera_->downloadItem(folder, itemName, saveFile);
+ mutex_.unlock();
+ if (result != GPCamera::GPSuccess) {
+ QString msg(i18n("Failed to open '%1'").arg(itemName));
+ error(msg);
+ } else {
+ QApplication::postEvent(parent_, new GPEventOpenItem(saveFile));
+ }
+}
+
+void GPController::openItemWithService(const QString& folder, const QString& itemName, const QString& saveFile, const QString& serviceName) {
+ mutex_.lock();
+ int result = camera_->downloadItem(folder, itemName, saveFile);
+ mutex_.unlock();
+ if (result != GPCamera::GPSuccess) {
+ QString msg(i18n("Failed to open '%1'").arg(itemName));
+ error(msg);
+ } else {
+ QApplication::postEvent(parent_, new GPEventOpenItemWithService(saveFile, serviceName));
+ }
+}
+
+void GPController::deleteItem(const QString& folder, const QString& itemName) {
+ mutex_.lock();
+ int result = camera_->deleteItem(folder, itemName);
+ mutex_.unlock();
+ if (result != GPCamera::GPSuccess) {
+ QString msg(i18n("Failed to delete '%1'").arg(itemName));
+ error(msg);
+ } else {
+ QApplication::postEvent(parent_, new GPEventDeleteItem(folder, itemName));
+ }
+}
+
+void GPController::uploadItem(const QString& folder, const QString& uploadName, const QString& localFile) {
+ mutex_.lock();
+ int result = camera_->uploadItem(folder, uploadName, localFile);
+ mutex_.unlock();
+ if (result != GPCamera::GPSuccess) {
+ QString msg(i18n("Failed to upload '%1'").arg(localFile));
+ error(msg);
+ } else {
+ GPFileItemInfoList infoList;
+ GPFileItemInfoList infoList2;
+ infoList.clear();
+ infoList2.clear();
+ mutex_.lock();
+ int result = camera_->getItemsInfo(folder, infoList);
+ mutex_.unlock();
+ if (result == GPCamera::GPSuccess) {
+ while ( !(infoList.isEmpty()) ) {
+ GPFileItemInfo info( infoList.first() );
+ infoList.pop_front();
+ if (info.name == uploadName) {
+ infoList2.push_back(info);
+ break;
+ }
+ }
+ if (!infoList2.isEmpty()) {
+ QApplication::postEvent(parent_, new GPEventGetItemsInfo(folder, infoList2));
+ }
+ }
+ }
+}
+
+void GPController::error(const QString& errorMsg) {
+ kdWarning() << errorMsg;
+ QApplication::postEvent(parent_, new GPEventError(errorMsg));
+}
+
+void GPController::scaleHighlightThumbnail(QImage& thumbnail) {
+ thumbnail = thumbnail.smoothScale(100, 100, QImage::ScaleMin);
+ QColor darkColor(48, 48, 48);
+ QColor lightColor(215, 215, 215);
+ int w = thumbnail.width();
+ int h = thumbnail.height();
+ // Right
+ for (int y=0; y<h; y++) {
+ if (y > 1 && y < h-2) {
+ thumbnail.setPixel(w-3, y, lightColor.rgb());
+ }
+ thumbnail.setPixel(w-1, y, darkColor.rgb());
+ thumbnail.setPixel(w-2, y, darkColor.rgb());
+ }
+ // Bottom
+ for (int x=0; x<w; x++) {
+ if (x > 1 && x < w-2) {
+ thumbnail.setPixel(x, h-3, lightColor.rgb());
+ }
+ thumbnail.setPixel(x, h-1, darkColor.rgb());
+ thumbnail.setPixel(x, h-2, darkColor.rgb());
+ }
+ // Top
+ for (int x=0; x<w; x++) {
+ if (x > 1 && x < w-2) {
+ thumbnail.setPixel(x, 2, lightColor.rgb());
+ }
+ thumbnail.setPixel(x, 0, darkColor.rgb());
+ thumbnail.setPixel(x, 1, darkColor.rgb());
+ }
+ // Left
+ for (int y=0; y<h; y++) {
+ if (y > 1 && y < h-2) {
+ thumbnail.setPixel(2, y, lightColor.rgb());
+ }
+ thumbnail.setPixel(0, y, darkColor.rgb());
+ thumbnail.setPixel(1, y, darkColor.rgb());
+ }
+}
+
+void GPController::slotStatusMsg(const QString& msg) {
+ if (!msg.isEmpty()) {
+ QApplication::postEvent(parent_, new GPEventStatusMsg(msg));
+ }
+}
+
+void GPController::slotProgressVal(int val) {
+ QApplication::postEvent(parent_, new GPEventProgress(val));
+}
+
+void GPController::slotErrorMsg(const QString& msg) {
+ error(msg);
+}
+
+void GPController::showBusy(bool val) {
+ QApplication::postEvent(parent_, new GPEventBusy(val));
+}
+
+void GPController::getInformation(QString& summary, QString& manual, QString& about) {
+ mutex_.lock();
+ camera_->cameraSummary(summary);
+ camera_->cameraManual(manual);
+ camera_->cameraAbout(about);
+ mutex_.unlock();
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "gpcontroller.moc"
diff --git a/kipi-plugins/kameraklient/gpcontroller.h b/kipi-plugins/kameraklient/gpcontroller.h
new file mode 100644
index 0000000..ab9f320
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpcontroller.h
@@ -0,0 +1,99 @@
+/* ============================================================
+ * File : gpcontroller.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-22
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPCONTROLLER_H
+#define GPCONTROLLER_H
+
+#include <qobject.h>
+#include <qthread.h>
+#include <qmutex.h>
+
+#include "mtqueue.h"
+#include "gpcommand.h"
+#include "cameratype.h"
+
+class QString;
+class QImage;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPCamera;
+
+class GPController : public QObject, public QThread {
+ Q_OBJECT
+
+public:
+ GPController(QObject *parent, const CameraType& ctype);
+ ~GPController();
+
+ void requestInitialize();
+ void requestGetSubFolders(const QString& folder);
+ void requestMakeFolder(const QString& folder, const QString& newFolder);
+ void requestDeleteFolder(const QString& folder);
+ void requestGetItemsInfo(const QString& folder);
+ void requestGetAllItemsInfo(const QString& folder);
+ void requestGetThumbnail(const QString& folder, const QString& imageName);
+ void requestDownloadItem(const QString& folder, const QString& itemName, const QString& saveFile);
+ void requestDeleteItem(const QString& folder, const QString& itemName);
+ void requestUploadItem(const QString& folder, const QString& localFile, const QString& uploadName);
+ void requestOpenItem(const QString& folder, const QString& itemName, const QString& saveFile);
+ void requestOpenItemWithService(const QString& folder, const QString& itemName, const QString& saveFile, const QString& serviceName);
+ void cancel();
+ void getInformation(QString& summary, QString& manual, QString& about);
+
+protected:
+ void run();
+
+private:
+ void initialize();
+ void getSubFolders(const QString& folder);
+ void makeFolder(const QString& folder, const QString& newFolder);
+ void deleteFolder(const QString& folder);
+ void getItemsInfo(const QString& folder);
+ void getAllItemsInfo(const QString& folder);
+ void getThumbnail(const QString& folder, const QString& imageName);
+ void downloadItem(const QString& folder, const QString& itemName, const QString& saveFile);
+ void deleteItem(const QString& folder, const QString& itemName);
+ void uploadItem(const QString& folder, const QString& uploadName, const QString& localFile);
+ void openItem(const QString& folder, const QString& itemName, const QString& saveFile);
+ void openItemWithService(const QString& folder, const QString& itemName, const QString& saveFile, const QString& serviceName);
+ void exifInfo(const QString& folder, const QString& itemName);
+ void error(const QString& errorMsg);
+
+ void scaleHighlightThumbnail(QImage& thumbnail);
+ void showBusy(bool val);
+
+ QObject *parent_;
+ GPCamera *camera_;
+ QMutex mutex_;
+ MTQueue<GPCommand> cmdQueue_;
+ bool close_;
+
+private slots:
+ void slotStatusMsg(const QString& msg);
+ void slotProgressVal(int val);
+ void slotErrorMsg(const QString& msg);
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif /* GPCONTROLLER_H */
diff --git a/kipi-plugins/kameraklient/gpeventfilter.cpp b/kipi-plugins/kameraklient/gpeventfilter.cpp
new file mode 100644
index 0000000..7eebc3e
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpeventfilter.cpp
@@ -0,0 +1,128 @@
+/* ============================================================
+ * File : gpeventfilter.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt
+#include <qevent.h>
+// Local
+#include "cameraui.h"
+#include "gpeventfilter.h"
+#include "gpevents.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+GPEventFilter::GPEventFilter(QObject* parent)
+ : QObject(parent) {
+ parent->installEventFilter(this);
+ view_ = static_cast<CameraUI *>(parent);
+}
+
+GPEventFilter::~GPEventFilter() {
+
+}
+
+bool GPEventFilter::eventFilter(QObject *, QEvent *e) {
+ if (e->type() < QCustomEvent::User) {
+ return false;
+ }
+ switch (e->type()) {
+ case(GPEvent::Init): {
+ view_->cameraInitialized(true);
+ break;
+ }
+ case (GPEvent::Error): {
+ GPEventError *event(static_cast<GPEventError *>(e));
+ view_->cameraErrorMsg(event->errorMsg());
+ break;
+ }
+ case (GPEvent::GetSubFolders): {
+ GPEventGetSubFolders *event(static_cast<GPEventGetSubFolders *>(e));
+ QString folder(event->folder());
+ MTList<QString> subFolderList(event->subFolderList());
+ for (int i=0; i<subFolderList.count(); i++) {
+ view_->cameraSubFolder(folder, subFolderList[i]);
+ }
+ break;
+ }
+ case (GPEvent::GetItemsInfo): {
+ GPEventGetItemsInfo *event(static_cast<GPEventGetItemsInfo *>(e));
+ QString folder(event->folder());
+ MTList<GPFileItemInfo> mtList(event->infoList());
+ GPFileItemInfoList infoList;
+ GPFileItemInfoList::const_iterator it;
+ for (it = mtList.begin(); it != mtList.end(); ++it)
+ infoList.append(*it);
+ view_->cameraNewItems(folder, infoList);
+ break;
+ }
+ case (GPEvent::GetAllItemsInfo): {
+ GPEventGetAllItemsInfo *event(static_cast<GPEventGetAllItemsInfo *>(e));
+ MTList<GPFileItemInfo> mtList(event->infoList());
+ GPFileItemInfoList infoList;
+ GPFileItemInfoList::const_iterator it;
+ for (it = mtList.begin(); it != mtList.end(); ++it) {
+ infoList.append(*it);
+ }
+ view_->cameraNewItems(infoList);
+ break;
+ }
+ case(GPEvent::GetThumbnail): {
+ GPEventGetThumbnail *event(static_cast<GPEventGetThumbnail *>(e));
+ view_->cameraNewThumbnail(event->folder(), event->imageName(), event->thumbnail());
+ break;
+ }
+ case(GPEvent::DownloadItem): {
+ GPEventDownloadItem *event(static_cast<GPEventDownloadItem *>(e));
+ view_->cameraDownloadedItem(event->folder(), event->itemName());
+ break;
+ }
+ case(GPEvent::DeleteItem): {
+ GPEventDeleteItem *event(static_cast<GPEventDeleteItem *>(e));
+ view_->cameraDeletedItem(event->folder(), event->itemName());
+ break;
+ }
+ case(GPEvent::StatusMsg): {
+ GPEventStatusMsg *event(static_cast<GPEventStatusMsg *>(e));
+ emit signalStatusMsg(event->msg());
+ break;
+ }
+ case(GPEvent::Progress): {
+ GPEventProgress *event(static_cast<GPEventProgress *>(e));
+ emit signalProgressVal(event->val());
+ break;
+ }
+ case(GPEvent::Busy): {
+ GPEventBusy *event(static_cast<GPEventBusy *>(e));
+ emit signalBusy(event->busy());
+ break;
+ }
+ default: {
+ qWarning("Event Filter: Unknown Event");
+ break;
+ }
+ }
+ // eat this event
+ return true;
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "gpeventfilter.moc"
diff --git a/kipi-plugins/kameraklient/gpeventfilter.h b/kipi-plugins/kameraklient/gpeventfilter.h
new file mode 100644
index 0000000..850a2f2
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpeventfilter.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ * File : gpeventfilter.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPEVENTFILTER_H
+#define GPEVENTFILTER_H
+
+#include <qobject.h>
+
+#include "gpfileiteminfo.h"
+
+class QEvent;
+class QImage;
+class QString;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class CameraUI;
+
+class GPEventFilter : public QObject {
+ Q_OBJECT
+
+public:
+ GPEventFilter(QObject *parent);
+ ~GPEventFilter();
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *e);
+
+private:
+ CameraUI *view_;
+
+signals:
+ void signalCameraError(const QString&);
+ void signalStatusMsg(const QString&);
+ void signalProgressVal(int);
+ void signalBusy(bool);
+
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/gpevents.h b/kipi-plugins/kameraklient/gpevents.h
new file mode 100644
index 0000000..7be51ac
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpevents.h
@@ -0,0 +1,243 @@
+/* ============================================================
+ * File : gpevents.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-22
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPEVENTS_H
+#define GPEVENTS_H
+
+#include <qevent.h>
+#include <qstring.h>
+#include <qimage.h>
+#include <qvaluelist.h>
+
+#include "mtlist.h"
+#include "gpfileiteminfo.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPEvent : public QCustomEvent {
+
+public:
+ enum Type {
+ Init = QCustomEvent::User,
+ GetSubFolders,
+ MakeFolder,
+ DeleteFolder,
+ GetItemsInfo,
+ GetAllItemsInfo,
+ GetThumbnail,
+ DownloadItem,
+ DeleteItem,
+ DeleteAllItems,
+ OpenItem,
+ OpenItemWithService,
+ UploadItem,
+ ExifInfo,
+ Information,
+ StatusMsg,
+ Progress,
+ Error,
+ Busy
+ };
+ GPEvent(Type type) : QCustomEvent(type) {}
+};
+
+class GPEventError : public GPEvent {
+public:
+ GPEventError(const QString errorMsg) : GPEvent(Error), errorMsg_(errorMsg) {}
+ QString errorMsg() const { return errorMsg_; }
+
+private:
+ QString errorMsg_;
+
+};
+
+class GPEventGetSubFolders : public GPEvent {
+public:
+ GPEventGetSubFolders(const QString& folder, const QValueList<QString>& subFolderList)
+ : GPEvent(GetSubFolders),
+ folder_(folder),
+ subFolderList_(subFolderList)
+ {}
+ QString folder() const { return folder_; }
+ const MTList<QString>& subFolderList() const { return subFolderList_; }
+
+private:
+ QString folder_;
+ MTList<QString> subFolderList_;
+};
+
+class GPEventGetItemsInfo : public GPEvent {
+public:
+ GPEventGetItemsInfo(const QString& folder, const GPFileItemInfoList& infoList)
+ : GPEvent(GetItemsInfo),
+ folder_(folder),
+ infoList_(infoList)
+ {}
+ QString folder() const { return folder_; }
+ const MTList<GPFileItemInfo>& infoList() const { return infoList_; }
+
+private:
+ QString folder_;
+ MTList<GPFileItemInfo> infoList_;
+};
+
+class GPEventGetAllItemsInfo : public GPEvent {
+public:
+ GPEventGetAllItemsInfo(const GPFileItemInfoList& infoList)
+ : GPEvent(GetAllItemsInfo),
+ infoList_(infoList)
+ {}
+ const MTList<GPFileItemInfo>& infoList() const { return infoList_; }
+
+private:
+ MTList<GPFileItemInfo> infoList_;
+};
+
+class GPEventGetThumbnail : public GPEvent {
+public:
+
+ GPEventGetThumbnail(const QString& folder, const QString& imageName, const QImage& thumbnail)
+ : GPEvent(GetThumbnail),
+ folder_(folder),
+ imageName_(imageName),
+ thumbnail_(thumbnail)
+ {}
+ QString folder() const { return folder_; }
+ QString imageName() const { return imageName_; }
+ QImage thumbnail() const { return thumbnail_; }
+
+private:
+ QString folder_;
+ QString imageName_;
+ QImage thumbnail_;
+};
+
+class GPEventDownloadItem : public GPEvent {
+public:
+ GPEventDownloadItem(const QString& folder, const QString& itemName)
+ : GPEvent(DownloadItem),
+ folder_(folder),
+ itemName_(itemName)
+ {}
+ QString folder() const { return folder_; }
+ QString itemName() const { return itemName_; }
+
+private:
+ QString folder_;
+ QString itemName_;
+};
+
+class GPEventDeleteItem : public GPEvent {
+public:
+ GPEventDeleteItem(const QString& folder, const QString& itemName)
+ : GPEvent(DeleteItem),
+ folder_(folder),
+ itemName_(itemName)
+ {}
+ QString folder() const { return folder_; }
+ QString itemName() const { return itemName_; }
+
+private:
+ QString folder_;
+ QString itemName_;
+};
+
+class GPEventOpenItem : public GPEvent {
+public:
+ GPEventOpenItem(const QString& openFile) : GPEvent(OpenItem), openFile_(openFile)
+ {}
+ QString openFile() const { return openFile_; }
+
+private:
+ QString openFile_;
+};
+
+class GPEventOpenItemWithService : public GPEvent {
+public:
+ GPEventOpenItemWithService(const QString& openFile, const QString& serviceName)
+ : GPEvent(OpenItemWithService),
+ openFile_(openFile),
+ serviceName_(serviceName)
+ { }
+ QString openFile() const { return openFile_; }
+ QString serviceName() const { return serviceName_; }
+
+private:
+ QString openFile_;
+ QString serviceName_;
+};
+
+class GPEventExifInfo : public GPEvent {
+public:
+ GPEventExifInfo(const QString& folder, const QString& itemName, char *data, int size)
+ : GPEvent(ExifInfo),
+ folder_(folder),
+ itemName_(itemName),
+ data_(data),
+ size_(size)
+ {}
+
+ QString folder() const { return folder_; }
+ QString itemName() const { return itemName_; }
+ char* data() { return data_; }
+ int size() const { return size_; }
+
+private:
+ QString folder_;
+ QString itemName_;
+ char *data_;
+ int size_;
+};
+
+class GPEventStatusMsg : public GPEvent {
+public:
+ GPEventStatusMsg(const QString& msg) : GPEvent(StatusMsg), msg_(msg)
+ {}
+ QString msg() const { return msg_; }
+
+private:
+ QString msg_;
+};
+
+class GPEventProgress : public GPEvent {
+public:
+ GPEventProgress(int val) : GPEvent(Progress), val_(val)
+ {}
+ int val() { return val_; }
+
+private:
+ int val_;
+};
+
+class GPEventBusy : public GPEvent {
+public:
+ GPEventBusy(bool busy) : GPEvent(Busy), busy_(busy)
+ {}
+ bool busy() { return busy_; }
+
+private:
+ bool busy_;
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif /* GPEVENTS_H */
diff --git a/kipi-plugins/kameraklient/gpfileitemcontainer.cpp b/kipi-plugins/kameraklient/gpfileitemcontainer.cpp
new file mode 100644
index 0000000..689b511
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpfileitemcontainer.cpp
@@ -0,0 +1,243 @@
+/* ============================================================
+ * File : gpfileitemcontainer.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt
+#include <qstring.h>
+// KDE
+#include <kdebug.h>
+// Local
+#include "camerafolderview.h"
+#include "camerafolderitem.h"
+#include "cameraiconview.h"
+#include "cameraiconitem.h"
+#include "gpfileitemcontainer.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+GPFileItemContainer::GPFileItemContainer(QObject *parent, CameraFolderView *folderView, CameraIconView *iconView) : QObject(parent) {
+ folderView_ = folderView;
+ iconView_ = iconView;
+ folderDict_.setAutoDelete(true);
+ connect(folderView_, SIGNAL(signalCleared()), this, SLOT(slotFolderViewCleared()));
+ connect(iconView_, SIGNAL(signalCleared()), this, SLOT(slotIconViewCleared()));
+}
+
+GPFileItemContainer::~GPFileItemContainer() {
+
+}
+
+void GPFileItemContainer::addVirtualFolder(const QString& title) {
+ folderView_->addVirtualFolder(title);
+}
+
+void GPFileItemContainer::addRootFolder(const QString& folder) {
+ folderView_->addRootFolder(folder);
+ GPFolder *item = new GPFolder;
+ item->viewItem = folderView_->rootFolder();
+ item->viewItem->setCount(0);
+ folderDict_.insert(folder, item);
+}
+
+void GPFileItemContainer::addFolder(const QString& folder, const QString& subfolder) {
+ QString path(folder);
+ if (!path.endsWith("/")) {
+ path += "/";
+ }
+ path += subfolder;
+ kdDebug() << "GPFileItemContainer: Adding folder " << path << endl;
+ if (!folderDict_.find(path)) {
+ GPFolder *item = new GPFolder;
+ folderDict_.insert(path, item);
+ item->viewItem = folderView_->addFolder(folder, subfolder);
+ if (item->viewItem) {
+ item->viewItem->setCount(0);
+ }
+ }
+}
+
+void GPFileItemContainer::addFiles(const QString& folder, const GPFileItemInfoList& infoList) {
+ GPFolder *folderItem = folderDict_.find(folder);
+ if (!folderItem) {
+ kdWarning() << "GPFileItemContainer: " << "Couldn't find Folder in Dict: " << folder << endl;
+ return;
+ }
+ GPFileDict* fileDict = folderItem->fileDict;
+ GPFileItemInfoList::const_iterator it;
+ for (it = infoList.begin(); it != infoList.end(); ++it) {
+ GPFileItemInfo *fileInfo = fileDict->find((*it).name);
+ if (!fileInfo) {
+ // Hmm... Totally New file
+ fileInfo = new GPFileItemInfo((*it));
+ fileDict->insert((*it).name, fileInfo);
+ // Update the count for the correspong folderviewitem
+ if (folderItem->viewItem)
+ folderItem->viewItem->changeCount(1);
+ // Also update the count of the virtual folder
+ if (folderView_->virtualFolder())
+ folderView_->virtualFolder()->changeCount(1);
+ }
+ // Have to check here: as when changing thumbnailsize, we cannot cancel the controller and so might end up having two items of the same type in the iconview
+ if (!fileInfo->viewItem) {
+ CameraIconItem *iconItem = iconView_->addItem(fileInfo);
+ fileInfo->viewItem = iconItem;
+ }
+ }
+}
+
+// Files to be added to the virtual folder
+void GPFileItemContainer::addFiles(const GPFileItemInfoList& infoList) {
+ if (!folderView_->virtualFolder()) {
+ kdWarning() << "GPFileItemContainer: " << "Virtual Folder not created yet" << endl;
+ return;
+ }
+ GPFileItemInfoList::const_iterator it;
+ for (it = infoList.begin(); it != infoList.end(); ++it) {
+ GPFileItemInfo info(*it);
+
+ GPFolder *folderItem = folderDict_.find(info.folder);
+ if (!folderItem) {
+ kdWarning() << "GPFileItemContainer: " << "Couldn't find Folder in Dict: " << info.folder << endl;
+ continue;
+ }
+ GPFileDict* fileDict = folderItem->fileDict;
+ GPFileItemInfo *fileInfo = fileDict->find((*it).name);
+ if (!fileInfo) {
+ // Hmm... Totally New file
+ fileInfo = new GPFileItemInfo(info);
+ fileDict->insert((*it).name, fileInfo);
+ // Update the count for the correspong folderviewitem
+ if (folderItem->viewItem)
+ folderItem->viewItem->changeCount(1);
+ // Also update the count of the virtual folder
+ if (folderView_->virtualFolder())
+ folderView_->virtualFolder()->changeCount(1);
+ }
+ if (!fileInfo->viewItem) {
+ CameraIconItem *iconItem = iconView_->addItem(fileInfo);
+ fileInfo->viewItem = iconItem;
+ }
+ }
+}
+
+void GPFileItemContainer::addFile(const QString& folder, const GPFileItemInfo& info) {
+ GPFolder *folderItem = folderDict_.find(folder);
+ if (!folderItem) {
+ kdWarning() << "GPFileItemContainer: " << "Couldn't find Folder in Dict: " << folder << endl;
+ return;
+ }
+ GPFileDict* fileDict = folderItem->fileDict;
+ GPFileItemInfo *fileInfo = fileDict->find(info.name);
+ if (!fileInfo) {
+ // Hmm... Totally New file
+ fileInfo = new GPFileItemInfo(info);
+ fileDict->insert(info.name, fileInfo);
+ // Update the count for the correspong folderviewitem
+ if (folderItem->viewItem) {
+ folderItem->viewItem->changeCount(1);
+ }
+ // Also update the count of the virtual folder
+ if (folderView_->virtualFolder()) {
+ folderView_->virtualFolder()->changeCount(1);
+ }
+ }
+ if (!fileInfo->viewItem) {
+ CameraIconItem *iconItem = iconView_->addItem(fileInfo);
+ fileInfo->viewItem = iconItem;
+ }
+}
+
+void GPFileItemContainer::delFile(const QString& folder, const QString& name) {
+ GPFolder *folderItem = folderDict_.find(folder);
+ if (!folderItem) {
+ kdWarning() << "GPFileItemContainer: " << "Couldn't find Folder in Dict: " << folder << endl;
+ return;
+ }
+ GPFileDict* fileDict = folderItem->fileDict;
+ GPFileItemInfo* fileInfo = fileDict->find(name);
+ if (!fileInfo) {
+ kdWarning() << "GPFileItemContainer: " << "Couldn't File Item to Delete in Dict: " << name << endl;
+ return;
+ }
+ if (fileInfo->viewItem) {
+ CameraIconItem *iconItem = (CameraIconItem*) fileInfo->viewItem;
+ delete iconItem;
+ }
+ fileDict->remove(name);
+ // Update the count for the correspong folderviewitem
+ if (folderItem->viewItem) {
+ folderItem->viewItem->changeCount(-1);
+ }
+ // Also update the count of the virtual folder
+ if (folderView_->virtualFolder()) {
+ folderView_->virtualFolder()->changeCount(-1);
+ }
+}
+
+CameraIconItem* GPFileItemContainer::findItem(const QString& folder, const QString& name) {
+ GPFolder *folderItem = folderDict_.find(folder);
+ if (!folderItem) {
+ kdWarning() << "GPFileItemContainer: " << "Couldn't find Folder in Dict: " << folder << endl;
+ return 0;
+ }
+ GPFileDict* fileDict = folderItem->fileDict;
+ GPFileItemInfo* fileInfo = fileDict->find(name);
+ if (!fileInfo) {
+ kdWarning() << "GPFileItemContainer: " << "Couldn't File Item to Delete in Dict: " << name << endl;
+ return 0;
+ }
+ return (CameraIconItem*) fileInfo->viewItem;
+}
+
+QPtrList<GPFileItemInfo> GPFileItemContainer::allFiles() {
+ QPtrList<GPFileItemInfo> ptrList;
+ GPFolderDictIterator it(folderDict_);
+ for (; it.current(); ++it) {
+ GPFolder* folderItem = it.current();
+ GPFileDictIterator iter(*(folderItem->fileDict));
+ for (; iter.current(); ++iter) {
+ ptrList.append(iter.current());
+ }
+ }
+ return ptrList;
+}
+
+void GPFileItemContainer::slotFolderViewCleared() {
+ folderDict_.clear();
+}
+
+void GPFileItemContainer::slotIconViewCleared() {
+ // Uh Oh... expensive process
+ // Zero out all the view items
+ GPFolderDictIterator it(folderDict_);
+ for (; it.current(); ++it) {
+ GPFolder* folderItem = it.current();
+ GPFileDictIterator iter(*(folderItem->fileDict));
+ for (; iter.current(); ++iter) {
+ GPFileItemInfo *fileInfo = iter.current();
+ fileInfo->viewItem = 0;
+ }
+ }
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "gpfileitemcontainer.moc"
diff --git a/kipi-plugins/kameraklient/gpfileitemcontainer.h b/kipi-plugins/kameraklient/gpfileitemcontainer.h
new file mode 100644
index 0000000..da64199
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpfileitemcontainer.h
@@ -0,0 +1,98 @@
+/* ============================================================
+ * File : gpfileitemcontainer.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPFILEITEMCONTAINER_H
+#define GPFILEITEMCONTAINER_H
+
+#include <qobject.h>
+#include <qdict.h>
+#include <qptrlist.h>
+
+#include "gpfileiteminfo.h"
+
+
+class QString;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class CameraFolderItem;
+class CameraFolderView;
+class CameraIconView;
+class CameraIconItem;
+
+class GPFileItemContainer : public QObject {
+ Q_OBJECT
+
+public:
+ GPFileItemContainer(QObject *parent, CameraFolderView *folderView, CameraIconView *iconView);
+ ~GPFileItemContainer();
+
+ void addVirtualFolder(const QString& title);
+ void addRootFolder(const QString& folder);
+ void addFolder(const QString& folder, const QString& subfolder);
+
+ void addFiles(const QString& folder, const GPFileItemInfoList& infoList);
+ void addFiles(const GPFileItemInfoList& infoList);
+ void addFile(const QString& folder, const GPFileItemInfo& info);
+
+ void delFile(const QString& folder, const QString& name);
+
+ CameraIconItem* findItem(const QString& folder, const QString& name);
+
+ QPtrList<GPFileItemInfo> allFiles();
+
+private:
+ typedef QDict<GPFileItemInfo> GPFileDict;
+ typedef QDictIterator<GPFileItemInfo> GPFileDictIterator;
+
+ class GPFolder {
+ public:
+ GPFolder() {
+ viewItem = 0;
+ fileDict = new GPFileDict(307);
+ fileDict->setAutoDelete(true);
+ }
+
+ ~GPFolder() {
+ if (fileDict)
+ delete fileDict;
+ }
+
+ GPFileDict *fileDict;
+ CameraFolderItem *viewItem;
+ };
+
+ typedef QDict<GPFolder> GPFolderDict;
+ typedef QDictIterator<GPFolder> GPFolderDictIterator;
+
+ GPFolderDict folderDict_;
+ CameraFolderView *folderView_;
+ CameraIconView *iconView_;
+
+private slots:
+ void slotFolderViewCleared();
+ void slotIconViewCleared();
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif /* GPFILEITEMCONTAINER_H */
diff --git a/kipi-plugins/kameraklient/gpfileiteminfo.cpp b/kipi-plugins/kameraklient/gpfileiteminfo.cpp
new file mode 100644
index 0000000..c0d6617
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpfileiteminfo.cpp
@@ -0,0 +1,121 @@
+/* ============================================================
+ * File : gpfileiteminfo.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-22
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Local
+#include "gpfileiteminfo.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+GPFileItemInfo::GPFileItemInfo() {
+ name = "";
+ folder = "";
+ // ----------------------------------------------------------
+ fileInfoAvailable = false;
+ mime = "";
+ time = "";
+ size = -1;
+ width = -1;
+ height = -1;
+ readPermissions = -1;
+ writePermissions = -1;
+ downloaded = -1;
+ // ----------------------------------------------------------
+ previewInfoAvailable = false;
+ previewMime = "";
+ previewSize = -1;
+ previewWidth = -1;
+ previewHeight = -1;
+ previewDownloaded = -1;
+ // ----------------------------------------------------------
+ audioInfoAvailable = false;
+ audioMime = "";
+ audioSize = -1;
+ audioDownloaded = -1;
+ // ----------------------------------------------------------
+ viewItem = 0;
+}
+
+GPFileItemInfo::~GPFileItemInfo() {
+}
+
+GPFileItemInfo::GPFileItemInfo(const GPFileItemInfo& info) {
+ name = info.name;
+ folder = info.folder;
+ // ----------------------------------------------------------
+ fileInfoAvailable = info.fileInfoAvailable;
+ mime = info.mime;
+ time = info.time;
+ size = info.size;
+ width = info.width;
+ height = info.height;
+ readPermissions = info.readPermissions;
+ writePermissions = info.writePermissions;
+ downloaded = info.downloaded;
+ // ----------------------------------------------------------
+ previewInfoAvailable = info.previewInfoAvailable;
+ previewMime = info.previewMime;
+ previewSize = info.previewSize;
+ previewWidth = info.previewWidth;
+ previewHeight = info.previewHeight;
+ previewDownloaded = info.previewDownloaded;
+ // ----------------------------------------------------------
+ audioInfoAvailable = info.audioInfoAvailable;
+ audioMime = info.audioMime;
+ audioSize = info.audioSize;
+ audioDownloaded = info.audioDownloaded;
+ // ----------------------------------------------------------
+ viewItem = 0;
+}
+
+GPFileItemInfo& GPFileItemInfo::operator=(const GPFileItemInfo& info) {
+ if (this != &info) {
+ name = info.name;
+ folder = info.folder;
+ // ----------------------------------------------------------
+ fileInfoAvailable = info.fileInfoAvailable;
+ mime = info.mime;
+ time = info.time;
+ size = info.size;
+ width = info.width;
+ height = info.height;
+ readPermissions = info.readPermissions;
+ writePermissions = info.writePermissions;
+ downloaded = info.downloaded;
+ // ----------------------------------------------------------
+ previewInfoAvailable = info.previewInfoAvailable;
+ previewMime = info.previewMime;
+ previewSize = info.previewSize;
+ previewWidth = info.previewWidth;
+ previewHeight = info.previewHeight;
+ previewDownloaded = info.previewDownloaded;
+ // ----------------------------------------------------------
+ audioInfoAvailable = info.audioInfoAvailable;
+ audioMime = info.audioMime;
+ audioSize = info.audioSize;
+ audioDownloaded = info.audioDownloaded;
+ // ----------------------------------------------------------
+ viewItem = 0;
+ }
+ return *this;
+}
+
+} // NameSpace KIPIKameraKlientPlugin
diff --git a/kipi-plugins/kameraklient/gpfileiteminfo.h b/kipi-plugins/kameraklient/gpfileiteminfo.h
new file mode 100644
index 0000000..d9ce95f
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpfileiteminfo.h
@@ -0,0 +1,77 @@
+/* ============================================================
+ * File : gpfileiteminfo.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-22
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPFILEITEMINFO_H
+#define GPFILEITEMINFO_H
+
+#include <qstring.h>
+#include <qvaluelist.h>
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPFileItemInfo {
+
+public:
+ GPFileItemInfo();
+ ~GPFileItemInfo();
+
+ GPFileItemInfo(const GPFileItemInfo& info);
+ GPFileItemInfo& operator=(const GPFileItemInfo& info);
+ // ---------------------------------------------------------
+ QString name;
+ QString folder;
+ // ---------------------------------------------------------
+ bool fileInfoAvailable;
+
+ QString mime;
+ QString time;
+ int size;
+ int width;
+ int height;
+ int readPermissions;
+ int writePermissions;
+ int downloaded;
+ // ---------------------------------------------------------
+ bool previewInfoAvailable;
+
+ QString previewMime;
+ int previewSize;
+ int previewWidth;
+ int previewHeight;
+ int previewDownloaded;
+ // ---------------------------------------------------------
+ bool audioInfoAvailable;
+
+ QString audioMime;
+ int audioSize;
+ int audioDownloaded;
+ // ---------------------------------------------------------
+ void *viewItem;
+};
+
+// Container for GPFileItemInfo
+typedef QValueList<GPFileItemInfo> GPFileItemInfoList;
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/gpfileiteminfodlg.cpp b/kipi-plugins/kameraklient/gpfileiteminfodlg.cpp
new file mode 100644
index 0000000..63976ca
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpfileiteminfodlg.cpp
@@ -0,0 +1,163 @@
+/* ============================================================
+ * File : gpfileiteminfodlg.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-19
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+
+ * Update : 09/23/2003 - Gilles Caulier <caulier.gilles@free.fr>
+ * Improve i18n messages.
+
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+#include <qpixmap.h>
+#include <qstring.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kseparator.h>
+
+#include "gpfileiteminfo.h"
+#include "gpfileiteminfodlg.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+GPFileItemInfoDlg::GPFileItemInfoDlg(const GPFileItemInfo& info,
+ QPixmap *pixmap )
+ : KDialogBase(0L, "GPFileItemInfoDlg", true,
+ info.name,
+ Ok, Ok, true)
+{
+ QWidget *page = new QWidget( this );
+ setMainWidget( page );
+
+ QGridLayout *grid = new QGridLayout( page, 1, 1, 5, 5);
+
+ // -----------------------------------------------------
+
+ QLabel *thumbLabel = new QLabel( page );
+ thumbLabel->setFrameShape(QFrame::Box);
+ thumbLabel->setMargin(2);
+ thumbLabel->setPaletteBackgroundColor(colorGroup().base());
+ if (!pixmap) {
+ if (info.mime.contains("image"))
+ thumbLabel->setPixmap(DesktopIcon("image"));
+ else if (info.mime.contains("audio"))
+ thumbLabel->setPixmap(DesktopIcon("audio"));
+ else if (info.mime.contains("video"))
+ thumbLabel->setPixmap(DesktopIcon("video"));
+ else
+ thumbLabel->setPixmap(DesktopIcon("document"));
+ }
+ else
+ thumbLabel->setPixmap(*pixmap);
+
+ grid->addWidget( thumbLabel, 0, 0);
+
+ // ----------------------------------------------------
+
+ QLabel *nameLabel = new QLabel( page );
+ nameLabel->setText(info.name);
+
+ grid->addWidget( nameLabel, 0, 2);
+
+ // ----------------------------------------------------
+
+ KSeparator *sep = new KSeparator( KSeparator::HLine, page );
+ grid->addMultiCellWidget( sep, 1, 1, 0, 2);
+
+ // ----------------------------------------------------
+
+ QLabel *l = 0;
+ int currRow = 2;
+ QString value;
+
+ l = new QLabel(i18n("MimeType:"), page);
+ grid->addWidget(l, currRow, 0);
+ value = info.mime.isNull() ? i18n("Unknown") : info.mime;
+ l = new QLabel(value, page);
+ grid->addWidget(l, currRow++, 2);
+
+ l = new QLabel(i18n("Date:"), page);
+ grid->addWidget(l, currRow, 0);
+ value = info.time.isNull() ? i18n("Unknown") : info.time;
+ l = new QLabel(value, page);
+ grid->addWidget(l, currRow++, 2);
+
+ l = new QLabel(i18n("Size:"), page);
+ grid->addWidget(l, currRow, 0);
+ value = info.size <= 0 ? i18n("Unknown") : QString::number(info.size);
+ value += i18n( " bytes" );
+ l = new QLabel(value, page);
+ grid->addWidget(l, currRow++, 2);
+
+ l = new QLabel(i18n("Width:"), page);
+ grid->addWidget(l, currRow, 0);
+ value = info.width <= 0 ? i18n("Unknown") : QString::number(info.width);
+ l = new QLabel(value, page);
+ grid->addWidget(l, currRow++, 2);
+
+
+ l = new QLabel(i18n("Height:"), page);
+ grid->addWidget(l, currRow, 0);
+ value = info.height <= 0 ? i18n("Unknown") : QString::number(info.height);
+ l = new QLabel(value, page);
+ grid->addWidget(l, currRow++, 2);
+
+ l = new QLabel(i18n("Read permissions:"), page);
+ grid->addWidget(l, currRow, 0);
+ if (info.readPermissions == 0)
+ value = i18n("No");
+ else if (info.readPermissions == 1)
+ value = i18n("Yes");
+ else
+ value = i18n("Unknown");
+ l = new QLabel(value, page);
+ grid->addWidget(l, currRow++, 2);
+
+ l = new QLabel(i18n("Write permissions:"), page);
+ grid->addWidget(l, currRow, 0);
+ if (info.writePermissions == 0)
+ value = i18n("No");
+ else if (info.writePermissions == 1)
+ value = i18n("Yes");
+ else
+ value = i18n("Unknown");
+ l = new QLabel(value, page);
+ grid->addWidget(l, currRow++, 2);
+
+ l = new QLabel(i18n("Downloaded:"), page);
+ grid->addWidget(l, currRow, 0);
+ if (info.downloaded == 0)
+ value = i18n("No");
+ else if (info.downloaded == 1)
+ value = i18n("Yes");
+ else
+ value = i18n("Unknown");
+ l = new QLabel(value, page);
+ grid->addWidget(l, currRow++, 2);
+
+
+}
+
+GPFileItemInfoDlg::~GPFileItemInfoDlg()
+{
+
+}
+
+} // NameSpace KIPIKameraKlientPlugin
diff --git a/kipi-plugins/kameraklient/gpfileiteminfodlg.h b/kipi-plugins/kameraklient/gpfileiteminfodlg.h
new file mode 100644
index 0000000..00433df
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpfileiteminfodlg.h
@@ -0,0 +1,46 @@
+/* ============================================================
+ * File : gpfileiteminfodlg.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-19
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPFILEITEMINFODLG_H
+#define GPFILEITEMINFODLG_H
+
+#include <kdialogbase.h>
+
+class QPixmap;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPFileItemInfo;
+
+class GPFileItemInfoDlg : public KDialogBase
+{
+public:
+
+ GPFileItemInfoDlg(const GPFileItemInfo& info,
+ QPixmap *pixmap=0);
+ ~GPFileItemInfoDlg();
+
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif /* GPFILEITEMINFODLG_H */
diff --git a/kipi-plugins/kameraklient/gpiface.cpp b/kipi-plugins/kameraklient/gpiface.cpp
new file mode 100644
index 0000000..9c92b64
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpiface.cpp
@@ -0,0 +1,143 @@
+/* ============================================================
+ * File : gpiface.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-19
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// GPhoto2
+
+extern "C"
+{
+#include <gphoto2.h>
+}
+
+// Qt
+#include <qstring.h>
+#include <qstringlist.h>
+
+// Local
+#include "gpiface.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+int GPIface::autoDetect(QString& model, QString& port) {
+ CameraList *pCamList;
+ CameraAbilitiesList *abilList;
+ GPPortInfoList *infoList;
+ const char *camModel_, *camPort_;
+ GPContext *context;
+
+ context = gp_context_new ();
+ gp_list_new(&pCamList);
+
+ gp_abilities_list_new (&abilList);
+ gp_abilities_list_load (abilList, context);
+ gp_port_info_list_new (&infoList);
+ gp_port_info_list_load (infoList);
+ gp_abilities_list_detect (abilList, infoList, pCamList, context);
+ gp_abilities_list_free (abilList);
+ gp_port_info_list_free (infoList);
+
+ gp_context_unref( context );
+
+ int count = gp_list_count (pCamList);
+
+ if (count<=0) {
+ gp_list_free(pCamList);
+ return -1;
+ }
+
+ for (int i = 0; i < count; i++) {
+ gp_list_get_name (pCamList, i, &camModel_);
+ gp_list_get_value (pCamList, i, &camPort_);
+ }
+
+ model = camModel_;
+ port = camPort_;
+ gp_list_free(pCamList);
+
+ return 0;
+}
+
+void GPIface::getSupportedCameras(int& count, QStringList& clist) {
+ clist.clear();
+ count = 0;
+
+ CameraAbilitiesList *abilList;
+ CameraAbilities abil;
+ GPContext *context;
+
+ context = gp_context_new ();
+
+ gp_abilities_list_new( &abilList );
+ gp_abilities_list_load( abilList, context );
+
+ count = gp_abilities_list_count( abilList );
+ if ( count < 0) {
+ gp_context_unref( context );
+ qWarning("failed to get list of cameras");
+ return;
+ } else {
+ for (int i=0; i<count; i++) {
+ const char *cname;
+ gp_abilities_list_get_abilities( abilList, i, &abil );
+ cname = abil.model;
+ clist.append( QString( cname ) );
+ }
+ }
+ gp_abilities_list_free( abilList );
+ gp_context_unref( context );
+}
+
+void GPIface::getSupportedPorts(QStringList& plist) {
+ GPPortInfoList *list;
+ GPPortInfo info;
+ plist.clear();
+ gp_port_info_list_new( &list );
+ gp_port_info_list_load( list );
+ int numPorts = gp_port_info_list_count( list );
+ for (int i = 0; i < numPorts; i++) {
+ gp_port_info_list_get_info( list, i, &info );
+ plist.append( info.path );
+ }
+ gp_port_info_list_free( list );
+}
+
+void GPIface::getCameraSupportedPorts(const QString& model, QStringList& plist) {
+ int i = 0;
+ plist.clear();
+ CameraAbilities abilities;
+ CameraAbilitiesList *abilList;
+ GPContext *context;
+ context = gp_context_new ();
+ gp_abilities_list_new (&abilList);
+ gp_abilities_list_load (abilList, context);
+ i = gp_abilities_list_lookup_model (abilList, model.local8Bit().data());
+ gp_abilities_list_get_abilities (abilList, i, &abilities);
+ gp_abilities_list_free (abilList);
+ if (abilities.port & GP_PORT_SERIAL) {
+ plist.append("serial");
+ }
+ if (abilities.port & GP_PORT_USB) {
+ plist.append("usb");
+ }
+ gp_context_unref( context );
+}
+
+} // NameSpace KIPIKameraKlientPlugin
diff --git a/kipi-plugins/kameraklient/gpiface.h b/kipi-plugins/kameraklient/gpiface.h
new file mode 100644
index 0000000..4b13f24
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpiface.h
@@ -0,0 +1,42 @@
+/* ============================================================
+ * File : gpiface.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-19
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPIFACE_H
+#define GPIFACE_H
+
+class QString;
+class QStringList;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPIface {
+
+public:
+ static int autoDetect(QString& model, QString& port);
+ static void getSupportedCameras(int& count, QStringList& clist);
+ static void getSupportedPorts(QStringList& plist);
+ static void getCameraSupportedPorts(const QString& model, QStringList& plist);
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif /* GPIFACE_H */
diff --git a/kipi-plugins/kameraklient/gpmessages.cpp b/kipi-plugins/kameraklient/gpmessages.cpp
new file mode 100644
index 0000000..39003fb
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpmessages.cpp
@@ -0,0 +1,42 @@
+/***************************************************************************
+ gpmessages.cpp - description
+ -------------------
+ begin : Sun Dec 30 2001
+ copyright : (C) 2001 by Renchi Raju
+ email : renchi@pooh.tam.uiuc.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. *
+ * *
+ ***************************************************************************/
+
+// Local
+#include "gpmessages.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+GPMessages* GPMessages::gpMessages=0;
+
+GPMessages* GPMessages::gpMessagesWrapper() {
+ if (!gpMessages) {
+ gpMessages = new GPMessages;
+ }
+ return gpMessages;
+}
+
+void GPMessages::deleteMessagesWrapper() {
+ if (gpMessages) {
+ delete gpMessages;
+ gpMessages=0;
+ }
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "gpmessages.moc"
diff --git a/kipi-plugins/kameraklient/gpmessages.h b/kipi-plugins/kameraklient/gpmessages.h
new file mode 100644
index 0000000..063c3aa
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpmessages.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ gpmessages.h - description
+ -------------------
+ begin : Sun Dec 30 2001
+ copyright : (C) 2001 by Renchi Raju
+ email : renchi@pooh.tam.uiuc.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. *
+ * *
+ ***************************************************************************/
+
+#ifndef GPMESSAGES_H
+#define GPMESSAGES_H
+
+#include <qobject.h>
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPMessages : public QObject {
+
+ Q_OBJECT
+
+ friend class GPStatus;
+
+public:
+
+ static GPMessages* gpMessagesWrapper();
+ static void deleteMessagesWrapper();
+
+signals:
+
+ void errorMessage(const QString&);
+ void statusChanged(const QString&);
+ void progressChanged(int);
+
+private:
+
+ GPMessages() : QObject() { };
+
+ static GPMessages* gpMessages;
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
diff --git a/kipi-plugins/kameraklient/gpstatus.cpp b/kipi-plugins/kameraklient/gpstatus.cpp
new file mode 100644
index 0000000..b5ea875
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpstatus.cpp
@@ -0,0 +1,103 @@
+/* ============================================================
+ * File : gpstatus.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Local
+#include "gpstatus.h"
+#include "gpmessages.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+float GPStatus::target = 0.0;
+bool GPStatus::cancel = false;
+
+GPStatus::GPStatus() : QObject() {
+ context = gp_context_new();
+ cancel = false;
+ gp_context_set_cancel_func(context, cancel_func, 0);
+ gp_context_set_error_func(context, error_func, 0);
+ gp_context_set_status_func(context, status_func, 0);
+ gp_context_set_progress_funcs(context, progress_start_func, progress_update_func, progress_stop_func, 0);
+}
+
+GPStatus::~GPStatus() {
+ if(context) {
+ gp_context_unref(context);
+ }
+}
+
+void GPStatus::cancelOperation() {
+ cancel = true;
+}
+
+GPContextFeedback GPStatus::cancel_func(GPContext *, void *) {
+ return (cancel ? GP_CONTEXT_FEEDBACK_CANCEL : GP_CONTEXT_FEEDBACK_OK);
+}
+
+void GPStatus::error_func(GPContext *, const char *format, va_list args, void *) {
+ char buf[4096] = "";
+ int nSize = vsnprintf( buf, 4096, format, args );
+ if(nSize > 4094) {
+ nSize = 4094;
+ }
+ buf[nSize] = '\0';
+ QString error;
+ error = error.fromLocal8Bit(buf);
+ GPMessages::gpMessagesWrapper()->emit errorMessage(error);
+}
+
+void GPStatus::status_func (GPContext *, const char *format, va_list args, void *) {
+ char buf[4096] = "";
+ int nSize = vsnprintf( buf, 4096, format, args );
+ if(nSize > 4094) {
+ nSize = 4094;
+ }
+ buf[nSize] = '\0';
+ QString status;
+ status = status.fromLocal8Bit(buf);
+ GPMessages::gpMessagesWrapper()->emit statusChanged(status);
+}
+
+unsigned int GPStatus::progress_start_func(GPContext *, float _target, const char *format, va_list args, void *) {
+ char buf[4096] = "";
+ int nSize = vsnprintf( buf, 4096, format, args );
+ if(nSize > 4094) {
+ nSize = 4094;
+ }
+ buf[nSize] = '\0';
+ QString prog;
+ prog = prog.fromLocal8Bit(buf);
+ target = _target;
+ return GP_OK;
+}
+
+void GPStatus::progress_update_func(GPContext *, unsigned int, float current, void *) {
+ int percentage = int(100.0 * current/target);
+ GPMessages::gpMessagesWrapper()->emit progressChanged(percentage);
+}
+
+void GPStatus::progress_stop_func(GPContext *, unsigned int, void *) {
+ GPMessages::gpMessagesWrapper()->emit progressChanged(0);
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "gpstatus.moc"
diff --git a/kipi-plugins/kameraklient/gpstatus.h b/kipi-plugins/kameraklient/gpstatus.h
new file mode 100644
index 0000000..ca30917
--- /dev/null
+++ b/kipi-plugins/kameraklient/gpstatus.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ * File : gpstatus.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-01-21
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GPSTATUS_H
+#define GPSTATUS_H
+
+#include <qobject.h>
+#include <qstring.h>
+
+extern "C" {
+#include <stdio.h>
+#include <gphoto2.h>
+}
+
+namespace KIPIKameraKlientPlugin
+{
+
+class GPStatus : public QObject {
+ Q_OBJECT
+ friend class GPCamera;
+
+ public:
+ GPStatus();
+ ~GPStatus();
+ void cancelOperation();
+
+ private:
+ GPContext *context;
+ static bool cancel;
+
+ private:
+ static GPContextFeedback cancel_func(GPContext *context, void *data);
+ static void error_func(GPContext *context, const char *format, va_list args, void *data);
+ static void status_func(GPContext *context, const char *format, va_list args, void *data);
+ static unsigned int progress_start_func (GPContext *context, float target, const char *format, va_list args, void *data);
+ static void progress_update_func (GPContext *context, unsigned int id, float current, void *data);
+ static void progress_stop_func(GPContext *context, unsigned int id, void *data);
+ static float target;
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif /* GPSTATUS_H */
+
diff --git a/kipi-plugins/kameraklient/hi16-action-documents.png b/kipi-plugins/kameraklient/hi16-action-documents.png
new file mode 100644
index 0000000..9e8612d
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi16-action-documents.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi16-action-generic.png b/kipi-plugins/kameraklient/hi16-action-generic.png
new file mode 100644
index 0000000..25dbf74
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi16-action-generic.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi16-action-multimedia.png b/kipi-plugins/kameraklient/hi16-action-multimedia.png
new file mode 100644
index 0000000..dfedf13
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi16-action-multimedia.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi16-action-new.png b/kipi-plugins/kameraklient/hi16-action-new.png
new file mode 100644
index 0000000..c292e15
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi16-action-new.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi16-action-pictures.png b/kipi-plugins/kameraklient/hi16-action-pictures.png
new file mode 100644
index 0000000..1de15b2
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi16-action-pictures.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi16-action-sound.png b/kipi-plugins/kameraklient/hi16-action-sound.png
new file mode 100644
index 0000000..eaddd85
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi16-action-sound.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi22-action-documents.png b/kipi-plugins/kameraklient/hi22-action-documents.png
new file mode 100644
index 0000000..b4aaf69
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi22-action-documents.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi22-action-generic.png b/kipi-plugins/kameraklient/hi22-action-generic.png
new file mode 100644
index 0000000..11993f4
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi22-action-generic.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi22-action-multimedia.png b/kipi-plugins/kameraklient/hi22-action-multimedia.png
new file mode 100644
index 0000000..cc252ed
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi22-action-multimedia.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi22-action-new.png b/kipi-plugins/kameraklient/hi22-action-new.png
new file mode 100644
index 0000000..449e141
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi22-action-new.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi22-action-pictures.png b/kipi-plugins/kameraklient/hi22-action-pictures.png
new file mode 100644
index 0000000..4c28fe9
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi22-action-pictures.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi22-action-sound.png b/kipi-plugins/kameraklient/hi22-action-sound.png
new file mode 100644
index 0000000..776ad03
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi22-action-sound.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi32-action-documents.png b/kipi-plugins/kameraklient/hi32-action-documents.png
new file mode 100644
index 0000000..725b7f2
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi32-action-documents.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi32-action-generic.png b/kipi-plugins/kameraklient/hi32-action-generic.png
new file mode 100644
index 0000000..eaa9473
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi32-action-generic.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi32-action-multimedia.png b/kipi-plugins/kameraklient/hi32-action-multimedia.png
new file mode 100644
index 0000000..c5f7d27
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi32-action-multimedia.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi32-action-new.png b/kipi-plugins/kameraklient/hi32-action-new.png
new file mode 100644
index 0000000..cea6a2b
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi32-action-new.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi32-action-pictures.png b/kipi-plugins/kameraklient/hi32-action-pictures.png
new file mode 100644
index 0000000..87adea8
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi32-action-pictures.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi32-action-sound.png b/kipi-plugins/kameraklient/hi32-action-sound.png
new file mode 100644
index 0000000..287eb94
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi32-action-sound.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi48-action-documents.png b/kipi-plugins/kameraklient/hi48-action-documents.png
new file mode 100644
index 0000000..0b383d6
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi48-action-documents.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi48-action-generic.png b/kipi-plugins/kameraklient/hi48-action-generic.png
new file mode 100644
index 0000000..65db143
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi48-action-generic.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi48-action-multimedia.png b/kipi-plugins/kameraklient/hi48-action-multimedia.png
new file mode 100644
index 0000000..b16eeda
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi48-action-multimedia.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi48-action-new.png b/kipi-plugins/kameraklient/hi48-action-new.png
new file mode 100644
index 0000000..1d4dac7
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi48-action-new.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi48-action-pictures.png b/kipi-plugins/kameraklient/hi48-action-pictures.png
new file mode 100644
index 0000000..153ce44
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi48-action-pictures.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/hi48-action-sound.png b/kipi-plugins/kameraklient/hi48-action-sound.png
new file mode 100644
index 0000000..50d8a48
--- /dev/null
+++ b/kipi-plugins/kameraklient/hi48-action-sound.png
Binary files differ
diff --git a/kipi-plugins/kameraklient/kameraklient.cpp b/kipi-plugins/kameraklient/kameraklient.cpp
new file mode 100644
index 0000000..a0ba5e6
--- /dev/null
+++ b/kipi-plugins/kameraklient/kameraklient.cpp
@@ -0,0 +1,77 @@
+/* ============================================================
+ * File : kameraklient.cpp
+ * Author: Tudor Calin <tudor@1xtech.com>
+ * Date : 2004-06-18
+ * Description :
+ *
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt
+#include <qiconset.h>
+#include <qwidget.h>
+// KDE
+#include <kaboutdata.h>
+#include <kaction.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <kinstance.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kshortcut.h>
+#include <kstandarddirs.h>
+// Local
+#include "cameraui.h"
+#include "kameraklient.h"
+
+typedef KGenericFactory<Plugin_KameraKlient> Factory;
+K_EXPORT_COMPONENT_FACTORY(kipiplugin_kameraklient, Factory("kipiplugin_kameraklient"))
+
+Plugin_KameraKlient::Plugin_KameraKlient(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin(Factory::instance(), parent, "KameraKlient") {
+ kdDebug() << "KameraKlient KIPI Plugin loaded" << endl;
+}
+
+Plugin_KameraKlient::~Plugin_KameraKlient() {
+}
+
+void Plugin_KameraKlient::setup(QWidget* widget) {
+ KIPI::Plugin::setup(widget);
+ mKameraKlientAction = new KAction(i18n("Digital Camera"),
+ "camera_unmount",
+ KShortcut(),
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "kipiplugin_kameraklient");
+ addAction(mKameraKlientAction);
+}
+
+void Plugin_KameraKlient::slotActivate() {
+ KIPIKameraKlientPlugin::CameraUI *mCameraUI = new KIPIKameraKlientPlugin::CameraUI();
+ mCameraUI->show();
+}
+
+KIPI::Category Plugin_KameraKlient::category(KAction* action) const {
+ if (action==mKameraKlientAction) {
+ return KIPI::IMPORTPLUGIN;
+ }
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMPORTPLUGIN; // no warning from compiler, please
+}
+
+#include "kameraklient.moc"
+
diff --git a/kipi-plugins/kameraklient/kameraklient.h b/kipi-plugins/kameraklient/kameraklient.h
new file mode 100644
index 0000000..3f726cf
--- /dev/null
+++ b/kipi-plugins/kameraklient/kameraklient.h
@@ -0,0 +1,51 @@
+/* ============================================================
+ * File : kameraklient.h
+ * Author: Tudor Calin <tudor@1xtech.com>
+ * Date : 2004-06-18
+ * Description :
+ *
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_KAMERAKLIENT_H
+#define PLUGIN_KAMERAKLIENT_H
+
+#include <libkipi/plugin.h>
+
+namespace KIPIKameraKlientPlugin
+{
+class CameraUI;
+class CameraType;
+}
+
+class Plugin_KameraKlient : public KIPI::Plugin {
+Q_OBJECT
+
+public:
+ Plugin_KameraKlient(QObject *parent, const char* name, const QStringList& args);
+ ~Plugin_KameraKlient();
+ virtual void setup(QWidget* widget);
+ virtual KIPI::Category category(KAction*) const;
+ QString id() const {
+ return QString::fromLatin1("kameraklient");
+ }
+ KAction* mKameraKlientAction;
+
+protected slots:
+ void slotActivate();
+};
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/kipiplugin_kameraklient.desktop b/kipi-plugins/kameraklient/kipiplugin_kameraklient.desktop
new file mode 100644
index 0000000..3ee81bd
--- /dev/null
+++ b/kipi-plugins/kameraklient/kipiplugin_kameraklient.desktop
@@ -0,0 +1,48 @@
+[Desktop Entry]
+Name=KameraKlient
+Name[cs]=Foto klient
+Name[da]=Kameraklient
+Name[es]=Cliente de cámara
+Name[et]=Kaameraklient
+Name[gl]=Cliente de Kamera
+Name[pt]=Cliente do Kamera
+Name[sr]=Клијент за камеру
+Name[sr@Latn]=Klijent za kameru
+Name[sv]=Kameraklient
+Name[tg]=Барномаи Камера
+Name[tr]=Kameraİstemci
+Name[xx]=xxKameraKlientxx
+Name[zh_CN]=相机客户端
+Comment=KIPI Digital Camera Interface Plugin
+Comment[ca]=Connector del KIPI d'interfície amb càmeres digitals
+Comment[cs]=KIPI modul rozhraní pro připojení fotoaparátu
+Comment[da]=KIPI-plugin: Grænseflade til digitalkamera
+Comment[de]=Ein KIPI-Modul zur Bereitstellung einer Kameraschnittstelle
+Comment[el]=Πρόσθετο του KIPI για σύνδεση ψηφιακής φωτογραφικής
+Comment[es]=Complemento de KIPI para interfaz de cámara digital
+Comment[et]=KIPI digikaamera liidese plugin
+Comment[fi]=Kipi-liitännäinen digitaalikameroita varten
+Comment[fr]=Module externe KIPI pour accéder à un appareil photo numérique
+Comment[gl]=Plugin de KIPI de Interface con Cámaras Dixitais
+Comment[is]=KIPI íforrit fyrir viðmót stafrænna myndavéla
+Comment[it]=Plugin di interfaccia alle fotocamere digitali di KIPI
+Comment[ja]=Kipi デジタルカメラインターフェースプラグイン
+Comment[nds]=KIPI-Koppelsteedmoduul för Digitaalkameras
+Comment[nl]=KIPI-plugin voor de digitale camera-interface
+Comment[pa]=KIPI ਡਿਜ਼ੀਟਲ ਕੈਮਰਾ ਇੰਟਰਫੇਸ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Interfejs aparatu cyfrowego
+Comment[pt]='Plugin' do KIPI de Interface com Máquinas Digitais
+Comment[pt_BR]=Plugin de Interface para Câmeras Digitais do KIPI
+Comment[sr]=KIPI прикључак интерфејса за дигитални фотоапарат
+Comment[sr@Latn]=KIPI priključak interfejsa za digitalni fotoaparat
+Comment[sv]=KIPI-insticksprogram: Gränssnitt till digitalkamera
+Comment[tg]=Модули интерфейси камераи рақамӣ
+Comment[tr]=KIPI Dijital Kamera Arayüz Eklentisi
+Comment[xx]=xxKIPI Digital Camera Interface Pluginxx
+Comment[zh_CN]=KIPI 数码相机接口插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_kameraklient
+X-KIPI-MergeMenu=true
+Encoding=UTF-8
+
diff --git a/kipi-plugins/kameraklient/mtlist.h b/kipi-plugins/kameraklient/mtlist.h
new file mode 100644
index 0000000..ae1dad8
--- /dev/null
+++ b/kipi-plugins/kameraklient/mtlist.h
@@ -0,0 +1,204 @@
+/* ============================================================
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 LISTMT_H
+#define LISTMT_H
+
+
+#include <qvaluelist.h>
+#include <qmutex.h>
+
+namespace KIPIKameraKlientPlugin
+{
+
+template<class Type> class MTList {
+
+public:
+ typedef typename QValueList<Type>::const_iterator const_iterator_type;
+
+ MTList() {
+ }
+
+ ~MTList() {
+
+ flush();
+ }
+
+ MTList(const MTList<Type>& origList) {
+
+ mutex_.lock();
+
+ list_.clear();
+ MTList<Type> &ref = const_cast<MTList<Type>&> (origList); // get rid of const
+
+ const_iterator_type iter;
+ for (iter = ref.begin(); iter != ref.end(); ++iter)
+ list_.push_back(*iter);
+
+ mutex_.unlock();
+
+ }
+
+ MTList(const QValueList<Type>& origList) {
+ mutex_.lock();
+ list_.clear();
+ const_iterator_type iter;
+ for (iter = origList.begin(); iter != origList.end(); ++iter) {
+ list_.push_back(*iter);
+ }
+ mutex_.unlock();
+ }
+
+
+ MTList& operator=(const MTList<Type>& origList) {
+
+ mutex_.lock();
+
+ if (this != &origList) {
+
+ list_.clear();
+ MTList<Type> &ref = const_cast<MTList<Type>&> (origList); // get rid of const
+
+ const_iterator_type iter;
+ for (iter = ref.begin(); iter != ref.end(); ++iter)
+ list_.push_back(*iter);
+
+ }
+
+ mutex_.unlock();
+
+ return *this;
+
+ }
+
+ bool isEmpty() {
+
+ mutex_.lock();
+ bool empty = list_.empty();
+ mutex_.unlock();
+ return empty;
+ }
+
+ int count() {
+
+ mutex_.lock();
+ int num = list_.count();
+ mutex_.unlock();
+ return num;
+ }
+
+
+
+ void flush() {
+
+ mutex_.lock();
+ list_.clear();
+ mutex_.unlock();
+ }
+
+ void push_front(const Type& t) {
+
+ mutex_.lock();
+ list_.push_front(t);
+ mutex_.unlock();
+ }
+
+ void push_back(const Type& t) {
+
+ mutex_.lock();
+ list_.push_back(t);
+ mutex_.unlock();
+ }
+
+ void pop_front() {
+
+ mutex_.lock();
+ list_.pop_front();
+ mutex_.unlock();
+ }
+
+ void pop_back() {
+
+ mutex_.lock();
+ list_.pop_back();
+ mutex_.unlock();
+ }
+
+ void append(const Type& t) {
+
+ mutex_.lock();
+ list_.append(t);
+ mutex_.unlock();
+
+ }
+
+ Type first() {
+
+ mutex_.lock();
+ Type t(list_.first());
+ mutex_.unlock();
+ return t;
+ }
+
+ Type last() {
+
+ mutex_.lock();
+ Type t(list_.last());
+ mutex_.unlock();
+ return t;
+ }
+
+ Type operator[](int i) {
+
+ mutex_.lock();
+ Type t(list_[i]);
+ mutex_.unlock();
+ return t;
+ }
+
+ const_iterator_type begin() {
+
+ mutex_.lock();
+ const_iterator_type iter;
+ iter = list_.begin();
+ mutex_.unlock();
+ return iter;
+
+ }
+
+ const_iterator_type end() {
+
+ mutex_.lock();
+ const_iterator_type iter;
+ iter = list_.end();
+ mutex_.unlock();
+ return iter;
+
+ }
+
+
+private:
+
+ QValueList<Type> list_;
+ QMutex mutex_;
+
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/mtqueue.h b/kipi-plugins/kameraklient/mtqueue.h
new file mode 100644
index 0000000..490f805
--- /dev/null
+++ b/kipi-plugins/kameraklient/mtqueue.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 COMMAND_QUEUE_H
+#define COMMAND_QUEUE_H
+
+#include <qptrqueue.h>
+#include <qmutex.h>
+
+namespace KIPIKameraKlientPlugin
+{
+
+template<class Type> class MTQueue
+{
+
+public:
+
+ MTQueue()
+ {
+ queue_.setAutoDelete(true);
+ }
+
+ ~MTQueue()
+ {
+ flush();
+ }
+
+ bool isEmpty()
+ {
+ mutex_.lock();
+ bool empty = queue_.isEmpty();
+ mutex_.unlock();
+ return empty;
+ }
+
+ void flush()
+ {
+ mutex_.lock();
+ queue_.clear();
+ mutex_.unlock();
+ }
+
+ void enqueue(Type * t)
+ {
+ mutex_.lock();
+ queue_.enqueue(t);
+ mutex_.unlock();
+ }
+
+ Type * dequeue()
+ {
+ mutex_.lock();
+ Type * i = queue_.dequeue();
+ mutex_.unlock();
+ return i;
+ }
+
+private:
+
+ QPtrQueue<Type> queue_;
+ QMutex mutex_;
+
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
diff --git a/kipi-plugins/kameraklient/savefiledialog.cpp b/kipi-plugins/kameraklient/savefiledialog.cpp
new file mode 100644
index 0000000..d31cb27
--- /dev/null
+++ b/kipi-plugins/kameraklient/savefiledialog.cpp
@@ -0,0 +1,75 @@
+/* ============================================================
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+// Qt
+#include <qstring.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qfileinfo.h>
+#include <qlabel.h>
+#include <qlayout.h>
+// KDE
+#include <klocale.h>
+#include <kbuttonbox.h>
+#include <kiconloader.h>
+// Local
+#include "savefiledialog.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+SavefileDialog::SavefileDialog(const QString& file, QWidget *parent, const char* name, bool modal) : QDialog(parent, name, modal) {
+ QFileInfo fileInfo(file);
+ setCaption(i18n("File Already Exists"));
+ QLabel *descLbl = new QLabel(i18n("The file '%1' already exists!").arg(fileInfo.absFilePath()), this);
+ renameEdit = new QLineEdit(this);
+ renameEdit->setText(fileInfo.fileName());
+ connect(renameEdit, SIGNAL(textChanged(const QString &)), this, SLOT(slot_renameEnabled()));
+ KButtonBox *bbox = new KButtonBox(this);
+ renameBtn = bbox->addButton(i18n("Rename"), this, SLOT(slot_rename()), true);
+ renameBtn->setEnabled(false);
+ bbox->addButton(i18n("Skip"), this, SLOT(slot_skip()), false);
+ bbox->addButton(i18n("Skip All"), this, SLOT(slot_skipAll()), true);
+ bbox->addButton(i18n("Overwrite"), this, SLOT(slot_overwrite()), true);
+ bbox->addButton(i18n("Overwrite All"), this, SLOT(slot_overwriteAll()), true);
+ QPushButton *cancelBtn = bbox->addButton(i18n("&Cancel"), this, SLOT(reject()), true);
+ cancelBtn->setDefault(true);
+ bbox->layout();
+ QGridLayout *layout = new QGridLayout(this, 0, 0, 15);
+ layout->addMultiCellWidget(descLbl, 0, 0, 0, 3);
+ layout->addMultiCellWidget(renameEdit, 3, 3, 0, 3);
+ layout->addMultiCellWidget(bbox, 4, 4, 0, 3);
+}
+
+SavefileDialog::~SavefileDialog() {
+}
+
+SavefileDialog::Operation SavefileDialog::saveFileOperation() {
+ return op;
+}
+
+QString SavefileDialog::renameFile() {
+ return renameEdit->text();
+}
+
+void SavefileDialog::slot_renameEnabled() {
+ renameBtn->setEnabled(true);
+ renameBtn->setDefault(true);
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "savefiledialog.moc"
diff --git a/kipi-plugins/kameraklient/savefiledialog.h b/kipi-plugins/kameraklient/savefiledialog.h
new file mode 100644
index 0000000..f3024a5
--- /dev/null
+++ b/kipi-plugins/kameraklient/savefiledialog.h
@@ -0,0 +1,66 @@
+/* ============================================================
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SAVEFILEDIALOG_H
+#define SAVEFILEDIALOG_H
+
+#include <qdialog.h>
+
+class QString;
+class QLineEdit;
+class QPushButton;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class SavefileDialog : public QDialog {
+Q_OBJECT
+
+public:
+ enum Operation { Rename, Skip, SkipAll, Overwrite, OverwriteAll, None };
+ SavefileDialog(const QString& file, QWidget *parent=0, const char* name=0, bool modal=true);
+ ~SavefileDialog();
+ Operation saveFileOperation();
+ QString renameFile();
+
+private slots:
+ void slot_rename() {
+ op=Rename; accept();
+ }
+ void slot_skip() {
+ op=Skip; accept();
+ }
+ void slot_skipAll() {
+ op=SkipAll; accept();
+ }
+ void slot_overwrite() {
+ op=Overwrite; accept();
+ }
+ void slot_overwriteAll() {
+ op=OverwriteAll; accept();
+ }
+ void slot_renameEnabled();
+
+private:
+ QLineEdit *renameEdit;
+ QPushButton *renameBtn;
+ Operation op;
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/setupcamera.cpp b/kipi-plugins/kameraklient/setupcamera.cpp
new file mode 100644
index 0000000..2920dad
--- /dev/null
+++ b/kipi-plugins/kameraklient/setupcamera.cpp
@@ -0,0 +1,245 @@
+/* ============================================================
+ * File : setupcamera.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-10
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qapplication.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qframe.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+
+// Include files for KIPI
+
+#include <libkipi/version.h>
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "kpaboutdata.h"
+#include "setupcamera.h"
+#include "cameraselection.h"
+#include "cameralist.h"
+#include "cameratype.h"
+#include "gpiface.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+SetupCamera::SetupCamera(QWidget* parent, const char* name)
+ : KDialogBase(parent, name, true, i18n("Setup Cameras"),
+ Help|Ok|Cancel, Ok, true)
+{
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("KameraKlient"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("An Digital camera interface Kipi plugin"),
+ "(c) 2003-2004, Renchi Raju\n"
+ "(c) 2004, Tudor Calin");
+
+ m_about->addAuthor("Renchi Raju", I18N_NOOP("Original author from Digikam project"),
+ "renchi@pooh.tam.uiuc.edu");
+
+ m_about->addAuthor("Tudor Calin", I18N_NOOP("Porting the Digikam GPhoto2 interface to Kipi. Maintainer"),
+ "tudor@1xtech.com");
+
+ helpButton_ = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ helpButton_->setPopup( helpMenu->menu() );
+
+ setWFlags(Qt::WDestructiveClose);
+ QWidget *page = new QWidget(this);
+ setMainWidget(page);
+ QVBoxLayout* vbox = new QVBoxLayout(page, 5, 5);
+
+ //---------------------------------------------
+
+ QGroupBox* groupBox = new QGroupBox(page, "groupBox");
+ groupBox->setColumnLayout(0, Qt::Vertical);
+ groupBox->layout()->setSpacing(5);
+ groupBox->layout()->setMargin(5);
+
+ QGridLayout* groupBoxLayout = new QGridLayout(groupBox->layout());
+ groupBoxLayout->setAlignment( Qt::AlignTop );
+ listView_ = new QListView( groupBox );
+ listView_->addColumn(i18n("Model"));
+ listView_->addColumn(i18n("Port"));
+ listView_->setAllColumnsShowFocus(true);
+ groupBoxLayout->addMultiCellWidget(listView_, 0, 4, 0, 0);
+ addButton_ = new QPushButton(groupBox);
+ groupBoxLayout->addWidget(addButton_, 0, 1);
+ removeButton_ = new QPushButton(groupBox);
+ groupBoxLayout->addWidget(removeButton_, 1, 1);
+ editButton_ = new QPushButton( groupBox);
+ groupBoxLayout->addWidget(editButton_, 2, 1);
+ autoDetectButton_ = new QPushButton(groupBox);
+ groupBoxLayout->addWidget(autoDetectButton_, 3, 1);
+ addButton_->setText( i18n("Add..."));
+ removeButton_->setText( i18n( "Remove"));
+ editButton_->setText( i18n("Edit..."));
+ autoDetectButton_->setText(i18n("Auto-Detect"));
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ groupBoxLayout->addItem(spacer, 4, 1);
+ vbox->addWidget(groupBox);
+ removeButton_->setEnabled(false);
+ editButton_->setEnabled(false);
+
+ connect(listView_, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()));
+ connect(addButton_, SIGNAL(clicked()), this, SLOT(slotAddCamera()));
+ connect(removeButton_, SIGNAL(clicked()), this, SLOT(slotRemoveCamera()));
+ connect(editButton_, SIGNAL(clicked()), this, SLOT(slotEditCamera()));
+ connect(autoDetectButton_, SIGNAL(clicked()), this, SLOT(slotAutoDetectCamera()));
+
+ CameraList* clist = CameraList::instance();
+
+ if(clist) {
+ QPtrList<CameraType>* cl = clist->cameraList();
+ for (CameraType *ctype = cl->first(); ctype; ctype = cl->next()) {
+ new QListViewItem(listView_, ctype->model(), ctype->port());
+ }
+ }
+
+ connect(this, SIGNAL(okClicked()), this, SLOT(slotOkClicked()));
+
+ show();
+ int W=SetupCamera::width (), H=SetupCamera::height();
+ move(QApplication::desktop()->width ()/2-(W/2), QApplication::desktop()->height()/2-(H/2));
+}
+
+SetupCamera::~SetupCamera() {
+ delete m_about;
+}
+
+void SetupCamera::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("kameraklient",
+ "kipi-plugins");
+}
+
+void SetupCamera::slotSelectionChanged() {
+ QListViewItem *item = listView_->selectedItem();
+ if (!item) {
+ removeButton_->setEnabled(false);
+ editButton_->setEnabled(false);
+ return;
+ }
+ removeButton_->setEnabled(true);
+ editButton_->setEnabled(true);
+}
+
+void SetupCamera::slotAddCamera() {
+ CameraSelection *select = new CameraSelection;
+ connect(select, SIGNAL(signalOkClicked(const QString&, const QString&)),
+ this, SLOT(slotAddedCamera(const QString&, const QString&)));
+ select->show();
+}
+
+void SetupCamera::slotRemoveCamera() {
+ QListViewItem *item = listView_->currentItem();
+ if (!item) {
+ return;
+ }
+ delete item;
+}
+
+void SetupCamera::slotEditCamera() {
+ QListViewItem *item = listView_->currentItem();
+ if (!item) {
+ return;
+ }
+ CameraSelection *select = new CameraSelection;
+ select->setCamera(item->text(0), item->text(1));
+ connect(select, SIGNAL(signalOkClicked(const QString&, const QString&)),
+ this, SLOT(slotEditedCamera(const QString&, const QString&)));
+ select->show();
+}
+
+void SetupCamera::slotAutoDetectCamera() {
+ QString model, port;
+ if (GPIface::autoDetect(model, port) != 0) {
+ KMessageBox::error(this, i18n("Failed to auto-detect camera!\n" "Please retry or try setting manually."));
+ return;
+ }
+ bool found = false;
+ CameraList* clist = CameraList::instance();
+ if (clist) {
+ if (clist->find(model)) {
+ found = true;
+ }
+ }
+ if (found) {
+ KMessageBox::information(this, i18n("Already added camera: ") + model + " (" + port + ")");
+ } else {
+ KMessageBox::information(this, i18n("Found camera: ") + model + " (" + port + ")");
+ new QListViewItem(listView_, model, port, "/");
+ }
+}
+
+void SetupCamera::slotAddedCamera(const QString& model, const QString& port) {
+ new QListViewItem(listView_, model, port);
+}
+
+void SetupCamera::slotEditedCamera(const QString& model, const QString& port) {
+ QListViewItem *item = listView_->currentItem();
+ if (!item) {
+ return;
+ }
+ item->setText(0, model);
+ item->setText(1, port);
+}
+
+void SetupCamera::applySettings() {
+ CameraList* clist = CameraList::instance();
+ if(clist) {
+ clist->clear();
+ QListViewItemIterator it(listView_);
+ for( ; it.current(); ++it ) {
+ QListViewItem *item = it.current();
+ CameraType *ctype = new CameraType(item->text(0), item->text(1));
+ clist->insert(ctype);
+ }
+ }
+}
+
+void SetupCamera::slotOkClicked() {
+ applySettings();
+ close();
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "setupcamera.moc"
diff --git a/kipi-plugins/kameraklient/setupcamera.h b/kipi-plugins/kameraklient/setupcamera.h
new file mode 100644
index 0000000..ad7e265
--- /dev/null
+++ b/kipi-plugins/kameraklient/setupcamera.h
@@ -0,0 +1,79 @@
+/* ============================================================
+ * File : setupcamera.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2003-02-10
+ * Description :
+ *
+ * Copyright 2003 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SETUPCAMERA_H
+#define SETUPCAMERA_H
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QListView;
+class QListViewItem;
+class QPushButton;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class SetupCamera : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ SetupCamera(QWidget* parent = 0, const char* name = 0);
+ ~SetupCamera();
+
+ void applySettings();
+
+private:
+
+ QListView* listView_;
+
+ QPushButton* addButton_;
+ QPushButton* removeButton_;
+ QPushButton* editButton_;
+ QPushButton* autoDetectButton_;
+ QPushButton* helpButton_;
+
+ KIPIPlugins::KPAboutData* m_about;
+
+private slots:
+
+ void slotHelp();
+ void slotSelectionChanged();
+ void slotAddCamera();
+ void slotRemoveCamera();
+ void slotEditCamera();
+ void slotAutoDetectCamera();
+ void slotAddedCamera(const QString& model, const QString& port);
+ void slotEditedCamera(const QString& model, const QString& port);
+ void slotOkClicked();
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
+
diff --git a/kipi-plugins/kameraklient/thumbitem.cpp b/kipi-plugins/kameraklient/thumbitem.cpp
new file mode 100644
index 0000000..bfa9fec
--- /dev/null
+++ b/kipi-plugins/kameraklient/thumbitem.cpp
@@ -0,0 +1,383 @@
+/* ============================================================
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+// Qt
+#include <qpixmap.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qpalette.h>
+#include <qpainter.h>
+#include <qevent.h>
+#include <qtextedit.h>
+// Local
+#include "thumbview.h"
+#include "thumbitem.h"
+
+namespace KIPIKameraKlientPlugin
+{
+
+class ThumbItemLineEdit : public QTextEdit {
+
+public:
+ ThumbItemLineEdit(const QString& text, QWidget* parent, ThumbItem* item);
+
+private:
+ void keyPressEvent(QKeyEvent *e);
+ void focusOutEvent(QFocusEvent *e);
+ ThumbItem *thumbItem;
+ QString startText;
+};
+
+ThumbItemLineEdit::ThumbItemLineEdit(const QString& text, QWidget* parent, ThumbItem* item)
+ : QTextEdit(parent), thumbItem(item), startText(text) {
+ setFrameStyle(QFrame::Plain | QFrame::Box);
+ setLineWidth(1);
+
+ setHScrollBarMode( AlwaysOff );
+ setVScrollBarMode( AlwaysOff );
+
+ setWordWrap( WidgetWidth );
+ setWrapColumnOrWidth(item->pixmapRect().width());
+ resize(200, 200);
+ setText(text);
+ setAlignment(Qt::AlignCenter);
+ resize(wrapColumnOrWidth() + 2, heightForWidth(wrapColumnOrWidth()) + 2);
+}
+
+void ThumbItemLineEdit::keyPressEvent( QKeyEvent *e ) {
+ if ( e->key() == Key_Escape) {
+ thumbItem->setText(startText);
+ thumbItem->cancelRenameItem();
+ } else if ( e->key() == Key_Enter || e->key() == Key_Return ) {
+ thumbItem->renameItem();
+ } else {
+ QTextEdit::keyPressEvent( e );
+ sync();
+ }
+}
+
+void ThumbItemLineEdit::focusOutEvent( QFocusEvent *e ) {
+ if (e->reason() != QFocusEvent::Popup ) {
+ thumbItem->cancelRenameItem();
+ }
+}
+
+class ThumbItemPrivate {
+
+ public:
+ QString text;
+ QPixmap* pixmap;
+
+ QRect rect;
+ QRect textRect;
+ QRect pixmapRect;
+
+ bool selected;
+ QString key;
+};
+
+ThumbItem::ThumbItem(ThumbView* parent, const QString& text, const QPixmap& pixmap) {
+ view = parent;
+ next = 0;
+ prev = 0;
+ renameBox = 0;
+
+ d = new ThumbItemPrivate;
+ d->text = text;
+ d->pixmap = new QPixmap(pixmap);
+ d->selected = false;
+ d->key = d->text;
+ // make sure to calcrect before inserting; this will calculate the size of the rect; inserting would move it to the required location
+ d->rect = QRect(0, 0, 0, 0);
+ d->textRect = QRect(0, 0, 0, 0);
+ d->pixmapRect = QRect(0, 0, 0, 0);
+ calcRect();
+
+ view->insertItem(this);
+}
+
+ThumbItem::~ThumbItem() {
+ view->takeItem(this);
+ delete d->pixmap;
+ delete d;
+}
+
+void ThumbItem::calcRect() {
+ QRect rect(d->rect);
+ QRect textRect(d->textRect);
+ QRect pixmapRect(d->pixmapRect);
+ // set initial pixrect
+ int pw = d->pixmap->width();
+ int ph = d->pixmap->height();
+
+ pixmapRect.setWidth(pw);
+ pixmapRect.setHeight(ph);
+ // word wrap
+ QFontMetrics fm(view->font());
+ QRect r = QRect(fm.boundingRect(0, 0, pixmapRect.width(),
+ 0xFFFFFFFF, Qt::AlignHCenter |
+ Qt::WordBreak | Qt::BreakAnywhere,
+ d->text));
+ r.setWidth(r.width() + 4);
+
+ textRect.setWidth(r.width());
+ textRect.setHeight(r.height());
+ // Now start updating the rects
+ int w = QMAX(textRect.width(), pixmapRect.width());
+ int h = textRect.height() + pixmapRect.height() + 1;
+
+ rect.setWidth(w);
+ rect.setHeight(h);
+ // Center the pix and text rect
+ pixmapRect = QRect((rect.width() - pixmapRect.width())/2,
+ 0,
+ pixmapRect.width(), pixmapRect.height());
+ textRect = QRect((rect.width() - textRect.width())/2,
+ rect.height() - textRect.height(),
+ textRect.width(), textRect.height());
+ // Finally save the settings
+ setRect(rect);
+ setPixmapRect(pixmapRect);
+ setTextRect(textRect);
+}
+
+void ThumbItem::paintItem(QPainter *, const QColorGroup& cg) {
+ QRect pRect=pixmapRect(true);
+ QRect tRect=textRect(true);
+
+ QPixmap pix(rect().width(), rect().height());
+ pix.fill(cg.base());
+ QPainter painter(&pix);
+ painter.drawPixmap(pRect.x(), pRect.y(), *pixmap() );
+ if (isSelected()) {
+ QPen pen;
+ pen.setColor(cg.highlight());
+ painter.setPen(pen);
+ painter.drawRect(0, 0, pix.width(), pix.height());
+ painter.fillRect(0, tRect.y(), pix.width(),
+ tRect.height(), cg.highlight() );
+ painter.setPen( QPen( cg.highlightedText() ) );
+ } else {
+ painter.setPen( cg.text() );
+ }
+ painter.drawText(tRect, Qt::WordBreak|Qt::BreakAnywhere|Qt::AlignHCenter|Qt::AlignTop,text());
+
+ painter.end();
+
+ QRect r(rect());
+ r = QRect(view->contentsToViewport(QPoint(r.x(), r.y())), QSize(r.width(), r.height()));
+
+ bitBlt(view->viewport(), r.x(), r.y(), &pix, 0, 0, r.width(), r.height());
+}
+
+void ThumbItem::repaint() {
+ QRect r(view->contentsRectToViewport(d->rect));
+ view->viewport()->repaint(r);
+}
+
+QRect ThumbItem::rect() {
+ return d->rect;
+}
+
+QRect ThumbItem::textRect(bool relative) {
+ if (relative) {
+ return d->textRect;
+ } else {
+ QRect r(x() + d->textRect.x(), y() + d->textRect.y(), d->textRect.width(), d->textRect.height());
+ return r;
+ }
+}
+
+QRect ThumbItem::pixmapRect(bool relative) {
+ if (relative) {
+ return d->pixmapRect;
+ } else {
+ QRect r(x() + d->pixmapRect.x(), y() + d->pixmapRect.y(), d->pixmapRect.width(), d->pixmapRect.height());
+ return r;
+ }
+
+}
+
+void ThumbItem::setRect(const QRect& rect) {
+ if (rect.isValid()) {
+ d->rect = rect;
+ }
+}
+
+void ThumbItem::setTextRect(const QRect& rect)
+{
+ if (rect.isValid()) {
+ d->textRect = rect;
+ }
+}
+
+void ThumbItem::setPixmapRect(const QRect& rect) {
+ if (rect.isValid()) {
+ d->pixmapRect = rect;
+ }
+}
+
+QPixmap * ThumbItem::pixmap() const {
+ return d->pixmap;
+}
+
+QString ThumbItem::text() const {
+ return d->text;
+}
+
+int ThumbItem::x() const {
+ return d->rect.x();
+}
+
+int ThumbItem::y() const {
+ return d->rect.y();
+}
+
+int ThumbItem::width() const {
+ return d->rect.width();
+}
+
+int ThumbItem::height() const {
+ return d->rect.height();
+}
+
+bool ThumbItem::move(int x, int y) {
+ if (x == this->x() && y == this->y()) {
+ return false;
+ }
+ d->rect.setRect(x, y, d->rect.width(), d->rect.height());
+ return true;
+}
+
+void ThumbItem::setSelected(bool val, bool cb) {
+ if (cb) {
+ view->blockSignals(true);
+ view->clearSelection();
+ view->blockSignals(false);
+ }
+ d->selected = val;
+ view->selectItem(this, val);
+ QRect r(d->rect);
+ r = QRect(view->contentsToViewport(QPoint(r.x(), r.y())), QSize(r.width(), r.height()));
+ view->viewport()->update(r);
+}
+
+bool ThumbItem::isSelected() {
+ return d->selected;
+}
+
+void ThumbItem::setPixmap(const QPixmap& pixmap) {
+ if (d->pixmap) {
+ delete d->pixmap;
+ d->pixmap = 0;
+ }
+ d->pixmap = new QPixmap(pixmap);
+
+ QRect oR(d->rect);
+ calcRect();
+ oR = oR.unite(d->rect);
+ oR = QRect(view->contentsToViewport(QPoint(oR.x(), oR.y())), QSize(oR.width(), oR.height()));
+
+ view->updateItemContainer(this);
+
+ if(oR.intersects(QRect(view->contentsX(), view->contentsY(), view->visibleWidth(), view->visibleHeight()))) {
+ view->viewport()->repaint(oR);
+ }
+}
+
+void ThumbItem::setText(const QString& text) {
+ d->text = text;
+ d->key = text;
+
+ QRect oR(d->rect);
+ calcRect();
+ oR = oR.unite(d->rect);
+ oR = QRect(view->contentsToViewport(QPoint(oR.x(), oR.y())),
+ QSize(oR.width(), oR.height()));
+
+ view->updateItemContainer(this);
+
+ if(oR.intersects(QRect(view->contentsX(), view->contentsY(), view->visibleWidth(), view->visibleHeight()))) {
+ view->viewport()->repaint(oR);
+ }
+}
+
+ThumbItem * ThumbItem::nextItem() {
+ return next;
+}
+
+ThumbItem * ThumbItem::prevItem() {
+ return prev;
+}
+
+ThumbView* ThumbItem::iconView() {
+ return view;
+}
+
+void ThumbItem::rename() {
+ if (renameBox) {
+ delete renameBox;
+ renameBox = 0;
+ }
+ renameBox = new ThumbItemLineEdit(d->text, view->viewport(), this);
+ QRect tr(textRect(false));
+ view->addChild(renameBox, tr.x() + (tr.width()/2 - renameBox->width()/2 ), tr.y() - 3);
+ renameBox->selectAll();
+ view->viewport()->setFocusProxy(renameBox);
+ renameBox->setFocus();
+ renameBox->show();
+
+ view->renamingItem = this;
+}
+
+void ThumbItem::renameItem() {
+ if (!renameBox) {
+ return;
+ }
+ setText(renameBox->text());
+
+ bool resetFocus = view->viewport()->focusProxy() == renameBox;
+ delete renameBox;
+ renameBox = 0;
+ if (resetFocus) {
+ view->viewport()->setFocusProxy(view);
+ view->setFocus();
+ }
+ view->renamingItem = 0;
+ view->emitRenamed(this);
+}
+
+void ThumbItem::cancelRenameItem() {
+ repaint();
+
+ bool resetFocus = view->viewport()->focusProxy() == renameBox;
+ delete renameBox;
+ renameBox = 0;
+ if (resetFocus) {
+ view->viewport()->setFocusProxy(view);
+ view->setFocus();
+ }
+ view->renamingItem = 0;
+}
+
+int ThumbItem::compare(ThumbItem *item) {
+ return key().localeAwareCompare(item->key());
+}
+
+QString ThumbItem::key() const {
+ return d->key;
+}
+
+} // NameSpace KIPIKameraKlientPlugin
diff --git a/kipi-plugins/kameraklient/thumbitem.h b/kipi-plugins/kameraklient/thumbitem.h
new file mode 100644
index 0000000..557c74e
--- /dev/null
+++ b/kipi-plugins/kameraklient/thumbitem.h
@@ -0,0 +1,101 @@
+/* ============================================================
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 THUMBITEM_H
+#define THUMBITEM_H
+
+#include <qrect.h>
+#include <qstring.h>
+
+class QPixmap;
+class QPainter;
+class QColorGroup;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class ThumbView;
+class ThumbItemLineEdit;
+class ThumbItemPrivate;
+
+class ThumbItem {
+
+ friend class ThumbView;
+ friend class ThumbItemLineEdit;
+
+public:
+
+ ThumbItem(ThumbView* parent,
+ const QString& text,
+ const QPixmap& pixmap);
+ virtual ~ThumbItem();
+
+ QPixmap *pixmap() const;
+ QString text() const;
+
+ ThumbItem *nextItem();
+ ThumbItem *prevItem();
+
+ int x() const;
+ int y() const;
+ int width() const;
+ int height() const;
+
+ QRect rect();
+ QRect textRect(bool relative=true);
+ QRect pixmapRect(bool relative=true);
+
+ bool move(int x, int y);
+
+ void setSelected(bool val, bool cb=true);
+ bool isSelected();
+
+ virtual void setPixmap(const QPixmap& pixmap);
+ virtual void setText(const QString& text);
+ void repaint();
+
+ ThumbView* iconView();
+
+ void rename();
+ virtual int compare(ThumbItem *item);
+
+ virtual QString key() const;
+
+protected:
+
+ virtual void calcRect();
+ void setRect(const QRect& rect);
+ void setTextRect(const QRect& rect);
+ void setPixmapRect(const QRect& rect);
+
+ virtual void paintItem(QPainter *p, const QColorGroup& cg);
+
+ void renameItem();
+ void cancelRenameItem();
+
+private:
+
+ ThumbItemPrivate *d;
+ ThumbView *view;
+ ThumbItem *next;
+ ThumbItem *prev;
+ ThumbItemLineEdit *renameBox;
+
+
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
diff --git a/kipi-plugins/kameraklient/thumbview.cpp b/kipi-plugins/kameraklient/thumbview.cpp
new file mode 100644
index 0000000..1009b39
--- /dev/null
+++ b/kipi-plugins/kameraklient/thumbview.cpp
@@ -0,0 +1,1028 @@
+/* ============================================================
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+// Qt
+#include <qpainter.h>
+#include <qrect.h>
+#include <qpoint.h>
+#include <qsize.h>
+#include <qevent.h>
+#include <qstring.h>
+#include <qstyle.h>
+#include <qpixmap.h>
+#include <qptrlist.h>
+#include <qcursor.h>
+#include <qtimer.h>
+#include <qdragobject.h>
+#include <qstrlist.h>
+#include <qapplication.h>
+// KDE
+#include <kiconloader.h>
+// Standard
+#include <stdlib.h>
+#include <iostream>
+
+// To get INT_MAX
+extern "C" {
+#include <limits.h>
+}
+// Local
+#include "thumbitem.h"
+#include "thumbview.h"
+
+
+#define RECT_EXTENSION 300
+
+namespace KIPIKameraKlientPlugin
+{
+
+class ThumbViewPrivate {
+
+public:
+ ThumbItem *firstItem;
+ ThumbItem *lastItem;
+ int spacing;
+ int count;
+ bool clearing;
+ bool pressedMoved;
+ QRect *rubber;
+ QPoint dragStartPos;
+ QPtrList<ThumbItem> selectedItems;
+ QTimer* updateTimer;
+ struct ItemContainer {
+ ItemContainer(ItemContainer *p, ItemContainer *n, const QRect &r) : prev(p), next(n), rect(r) {
+ items.setAutoDelete(false);
+ if (prev) {
+ prev->next = this;
+ }
+ if (next) {
+ next->prev = this;
+ }
+ }
+ ItemContainer *prev, *next;
+ QRect rect;
+ QPtrList<ThumbItem> items;
+ } *firstContainer, *lastContainer;
+ ThumbItem *startDragItem;
+ struct SortableItem {
+ ThumbItem *item;
+ };
+};
+
+
+static int cmpItems( const void *n1, const void *n2 ) {
+ if (!n1 || !n2) {
+ return 0;
+ }
+ ThumbViewPrivate::SortableItem *i1 = (ThumbViewPrivate::SortableItem *)n1;
+ ThumbViewPrivate::SortableItem *i2 = (ThumbViewPrivate::SortableItem *)n2;
+ return i1->item->compare( i2->item );
+}
+
+
+ThumbView::ThumbView(QWidget* parent, const char* name, WFlags fl) : QScrollView(parent, name, Qt::WStaticContents | fl) {
+ setBackgroundMode(Qt::NoBackground);
+ viewport()->setBackgroundMode(Qt::NoBackground);
+ viewport()->setFocusProxy(this);
+ viewport()->setFocusPolicy(QWidget::TabFocus);
+ renamingItem = 0;
+ d = new ThumbViewPrivate;
+ d->firstItem = 0;
+ d->lastItem = 0;
+ d->spacing = 5;
+ d->count = 0;
+ d->clearing = false;
+ d->pressedMoved = false;
+ d->rubber = 0;
+ d->firstContainer = 0;
+ d->lastContainer = 0;
+ d->selectedItems.setAutoDelete(false);
+ d->updateTimer = new QTimer(this);
+ d->startDragItem = 0;
+ connect(d->updateTimer, SIGNAL(timeout()), this, SLOT(slotUpdate()));
+}
+
+ThumbView::~ThumbView() {
+ clear(false);
+ if (d->rubber) {
+ delete d->rubber;
+ }
+ delete d->updateTimer;
+ delete d;
+}
+
+void ThumbView::clear(bool update) {
+ d->clearing = true;
+ renamingItem = 0;
+ deleteContainers();
+ d->selectedItems.clear();
+ emit signalSelectionChanged();
+ ThumbItem *item = d->firstItem;
+ while (item) {
+ ThumbItem *tmp = item->next;
+ delete item;
+ item = tmp;
+ }
+ d->firstItem = 0;
+ d->lastItem = 0;
+ viewport()->setUpdatesEnabled(false);
+ resizeContents(0, 0);
+ viewport()->setUpdatesEnabled(true);
+ if (update) {
+ updateContents();
+ }
+ d->clearing = false;
+}
+
+int ThumbView::count() {
+ return d->count;
+}
+
+int ThumbView::index(ThumbItem* item) {
+ if (!item) {
+ return -1;
+ }
+ if (item == d->firstItem) {
+ return 0;
+ } else if ( item == d->lastItem ) {
+ return d->count - 1;
+ } else {
+ ThumbItem *i = d->firstItem;
+ int j = 0;
+ while ( i && i != item ) {
+ i = i->next;
+ ++j;
+ }
+ return i ? j : -1;
+ }
+}
+
+ThumbItem* ThumbView::firstItem() {
+ return d->firstItem;
+}
+
+ThumbItem* ThumbView::lastItem() {
+ return d->lastItem;
+}
+
+void ThumbView::insertItem(ThumbItem *item) {
+ if (!item) {
+ return;
+ }
+ if (!d->firstItem) {
+ d->firstItem = item;
+ d->lastItem = item;
+ item->prev = 0;
+ item->next = 0;
+ } else {
+ d->lastItem->next = item;
+ item->prev = d->lastItem;
+ item->next = 0;
+ d->lastItem = item;
+ }
+ d->count++;
+ // this way one can insert items in a loop without too many paintevents
+ d->updateTimer->start(0, true);
+}
+
+void ThumbView::takeItem(ThumbItem *item) {
+ if (!item) {
+ return;
+ }
+ d->count--;
+ // First remove item from any containers holding it
+ ThumbViewPrivate::ItemContainer *tmp = d->firstContainer;
+ while (tmp) {
+ tmp->items.remove(item);
+ tmp = tmp->next;
+ }
+ // Remove from selected item list
+ d->selectedItems.remove(item);
+ if (item == d->firstItem) {
+ d->firstItem = d->firstItem->next;
+ if (d->firstItem) {
+ d->firstItem->prev = 0;
+ } else {
+ d->firstItem = d->lastItem = 0;
+ }
+ } else if (item == d->lastItem) {
+ d->lastItem = d->lastItem->prev;
+ if ( d->lastItem ) {
+ d->lastItem->next = 0;
+ } else {
+ d->firstItem = d->lastItem = 0;
+ }
+ } else {
+ ThumbItem *i = item;
+ if (i) {
+ if (i->prev) {
+ i->prev->next = i->next;
+ }
+ if (i->next) {
+ i->next->prev = i->prev;
+ }
+ }
+ }
+ if (!d->clearing) {
+ QRect r(contentsRectToViewport(item->rect()));
+ viewport()->repaint(r);
+ }
+}
+
+void ThumbView::slotUpdate() {
+ d->updateTimer->stop();
+ sort();
+ rearrangeItems();
+}
+
+void ThumbView::sort() {
+ ThumbViewPrivate::SortableItem *items = new ThumbViewPrivate::SortableItem[ count() ];
+ ThumbItem *item = d->firstItem;
+ int i = 0;
+ for ( ; item; item = item->next) {
+ items[ i++ ].item = item;
+ }
+ qsort( items, count(), sizeof( ThumbViewPrivate::SortableItem ), cmpItems );
+ ThumbItem *prev = 0;
+ item = 0;
+ for (i = 0; i < (int)count(); ++i) {
+ item = items[ i ].item;
+ if ( item ) {
+ item->prev = prev;
+ if (item->prev) {
+ item->prev->next = item;
+ }
+ item->next = 0;
+ }
+ if (i == 0) {
+ d->firstItem = item;
+ }
+ if (i == (int)count() - 1) {
+ d->lastItem = item;
+ }
+ prev = item;
+ }
+ delete [] items;
+}
+
+void ThumbView::viewportPaintEvent(QPaintEvent *pe) {
+ QRect r(pe->rect());
+ QRegion paintRegion(pe->region());
+ QPainter painter(viewport());
+ painter.setClipRegion(paintRegion);
+ ThumbViewPrivate::ItemContainer *c = d->firstContainer;
+ for ( ; c; c = c->next) {
+ QRect cr(contentsRectToViewport(c->rect));
+ if (r.intersects(cr)) {
+ ThumbItem *item = c->items.first();
+ for ( ; item; item = c->items.next()) {
+ QRect ir(contentsRectToViewport(item->rect()));
+ if (r.intersects(ir)) {
+ item->paintItem(&painter, colorGroup());
+ paintRegion -= QRegion(ir);
+ }
+ }
+ }
+ }
+ painter.setClipRegion(paintRegion);
+ painter.fillRect(r, colorGroup().base());
+ painter.end();
+}
+
+void ThumbView::resizeEvent(QResizeEvent* e) {
+ QScrollView::resizeEvent(e);
+ //d->updateTimer->start(0, true);
+ rearrangeItems();
+}
+
+void ThumbView::rearrangeItems(bool update) {
+ if (!d->firstItem || !d->lastItem) {
+ return;
+ }
+ int w = 0, h = 0, y = d->spacing;
+ ThumbItem *item = d->firstItem;
+ bool changedLayout = false;
+ while (item) {
+ bool changed;
+ ThumbItem *next = makeRow(item, y, changed);
+ changedLayout = changed || changedLayout;
+ item = next;
+ w = QMAX(w, item->x() + item->width());
+ h = QMAX(h, item->y() + item->height());
+ h = QMAX(h, y);
+ if (!item || !item->next) {
+ break;
+ }
+ item = item->next;
+ }
+ w = QMAX(w, d->lastItem->x() + d->lastItem->width());
+ h = QMAX(h, d->lastItem->y() + d->lastItem->height());
+ int vw = visibleWidth();
+ viewport()->setUpdatesEnabled(false);
+ resizeContents( w, h );
+ bool doAgain = visibleWidth() != vw;
+ if (doAgain) {
+ rearrangeItems(false);
+ }
+ viewport()->setUpdatesEnabled(true);
+ rebuildContainers();
+ if (changedLayout && update) {
+ viewport()->update();
+ }
+}
+
+ThumbItem* ThumbView::makeRow(ThumbItem *begin, int &y, bool &changed) {
+ ThumbItem *end = 0;
+ changed = false;
+ // first calculate the row height
+ int h = 0;
+ int x = 0;
+ ThumbItem *item = begin;
+ for (;;) {
+ x += d->spacing + item->width();
+ //int maxW = visibleWidth();
+ int maxW = frameRect().width() - 20;
+ if (x > maxW && item != begin) {
+ item = item->prev;
+ break;
+ }
+ h = QMAX(h, item->height());
+ ThumbItem *old = item;
+ item = item->next;
+ if (!item) {
+ item = old;
+ break;
+ }
+ }
+ end = item;
+ // now move the items
+ item = begin;
+ for (;;) {
+ int x;
+ if (item == begin) {
+ x = d->spacing;
+ } else {
+ x = item->prev->x() + item->prev->width() + d->spacing;
+ }
+ changed = item->move(x, y) || changed;
+ if (item == end) {
+ break;
+ }
+ item = item->next;
+ }
+ y += h + d->spacing;
+ return end;
+}
+
+void ThumbView::drawRubber(QPainter *p) {
+ if (!p || !d->rubber) {
+ return;
+ }
+ QRect r(d->rubber->normalize());
+ r = contentsRectToViewport(r);
+ QPoint pnt(r.x(), r.y());
+ style().drawPrimitive(QStyle::PE_FocusRect, p, QRect( pnt.x(), pnt.y(), r.width(), r.height()), colorGroup(), QStyle::Style_Default, QStyleOption(colorGroup().base()));
+}
+
+void ThumbView::contentsMousePressEvent(QMouseEvent *e) {
+ // If renaming any item, cancel it --------------------------
+ if (renamingItem) {
+ renamingItem->cancelRenameItem();
+ }
+ // Delete any existing rubber -------------------------------
+ if ( d->rubber ) {
+ QPainter p;
+ p.begin(viewport());
+ p.setRasterOp(NotROP);
+ p.setPen(QPen(color0, 1));
+ p.setBrush(NoBrush);
+ drawRubber(&p);
+ p.end();
+ delete d->rubber;
+ d->rubber = 0;
+ }
+ d->dragStartPos = e->pos();
+ ThumbItem *item = findItem(e->pos());
+ if (item) {
+ if (e->state() & Qt::ControlButton) {
+ item->setSelected(!item->isSelected(), false);
+ } else if (e->state() & Qt::ShiftButton) {
+ // different selection mode than the Trolls
+ ThumbItem *lastSelectedItem = 0;
+ bool bwdSelection = false;
+ // first go backwards
+ for (ThumbItem *it = item->prev; it; it = it->prev) {
+ if (it->isSelected()) {
+ lastSelectedItem = it;
+ bwdSelection = true;
+ break;
+ }
+ }
+ bool fwdSelection = false;
+ if (!lastSelectedItem) {
+ // Now go forward
+ for (ThumbItem *it = item->next; it; it = it->next) {
+ if (it->isSelected()) {
+ lastSelectedItem = it;
+ fwdSelection = true;
+ break;
+ }
+ }
+ }
+ blockSignals(true);
+ if (bwdSelection) {
+ for (ThumbItem *it = lastSelectedItem;
+ it && it != item->next; it = it->next) {
+ if (!it->isSelected()) {
+ it->setSelected(true, false);
+ }
+ }
+ } else if (fwdSelection) {
+ for (ThumbItem *it = item;
+ it && it != lastSelectedItem->next; it = it->next) {
+ if (!it->isSelected()) {
+ it->setSelected(true, false);
+ }
+ }
+ } else {
+ item->setSelected(!item->isSelected(), false);
+ }
+ blockSignals(false);
+ emit signalSelectionChanged();
+ } else {
+ if (!item->isSelected()) {
+ item->setSelected(true, true);
+ }
+ }
+ d->startDragItem = item;
+ return;
+ }
+ // Press outside any item. unselect all
+ clearSelection();
+ // If not item then initiate rubber
+ if ( d->rubber ) {
+ delete d->rubber;
+ d->rubber = 0;
+ }
+ d->rubber = new QRect( e->x(), e->y(), 0, 0 );
+ QPainter p;
+ p.begin( viewport() );
+ p.setRasterOp( NotROP );
+ p.setPen( QPen( color0, 1 ) );
+ p.setBrush( NoBrush );
+ drawRubber( &p );
+ p.end();
+ d->pressedMoved = false;
+}
+
+void ThumbView::contentsMouseMoveEvent(QMouseEvent *e) {
+ if (!e) {
+ return;
+ }
+ if (e->state() == NoButton) {
+ return;
+ }
+ // Dragging ?
+ if (d->startDragItem) {
+ if ((d->dragStartPos - e->pos() ).manhattanLength() > QApplication::startDragDistance()) {
+ startDrag();
+ }
+ return;
+ }
+ if (!d->rubber) {
+ return;
+ }
+ QRect oldRubber = QRect(*d->rubber);
+ d->rubber->setRight( e->pos().x() );
+ d->rubber->setBottom( e->pos().y() );
+ QRegion paintRegion;
+ viewport()->setUpdatesEnabled(false);
+ QRect nr(d->rubber->normalize());
+ QRect rubberUnion = nr.unite(oldRubber.normalize());
+ bool changed = false;
+ ThumbViewPrivate::ItemContainer *c = d->lastContainer;
+ for (; c; c = c->prev) {
+ if ( rubberUnion.intersects(c->rect) ) {
+ ThumbItem *item = c->items.last();
+ for ( ; item; item = c->items.prev() ) {
+ if (nr.intersects(item->rect())) {
+ if (!item->isSelected()) {
+ item->setSelected(true, false);
+ changed = true;
+ paintRegion += QRect(item->rect());
+ }
+ } else {
+ if (item->isSelected()) {
+ item->setSelected(false, false);
+ changed = true;
+ paintRegion += QRect(item->rect());
+ }
+ }
+ }
+ }
+ }
+ viewport()->setUpdatesEnabled(true);
+ QRect r = *d->rubber;
+ *d->rubber = oldRubber;
+ QPainter p;
+ p.begin( viewport() );
+ p.setRasterOp( NotROP );
+ p.setPen( QPen( color0, 1 ) );
+ p.setBrush( NoBrush );
+ drawRubber( &p );
+ p.end();
+ if (changed) {
+ emit signalSelectionChanged();
+ paintRegion.translate(-contentsX(), -contentsY());
+ viewport()->repaint(paintRegion);
+ }
+ ensureVisible(e->pos().x(), e->pos().y());
+ *d->rubber = r;
+ p.begin(viewport());
+ p.setRasterOp(NotROP);
+ p.setPen(QPen(color0, 1));
+ p.setBrush(NoBrush);
+ drawRubber(&p);
+ p.end();
+ d->pressedMoved = true;
+}
+
+void ThumbView::contentsMouseReleaseEvent(QMouseEvent *e) {
+ if (!e) {
+ return;
+ }
+ d->startDragItem = 0;
+ if (d->rubber) {
+ QPainter p;
+ p.begin( viewport() );
+ p.setRasterOp( NotROP );
+ p.setPen( QPen( color0, 1 ) );
+ p.setBrush( NoBrush );
+ drawRubber( &p );
+ p.end();
+ delete d->rubber;
+ d->rubber = 0;
+ }
+ if (e->button() == Qt::RightButton) {
+ ThumbItem *item = findItem(e->pos());
+ if (item) {
+ emit signalRightButtonClicked(item, e->globalPos());
+ } else {
+ emit signalRightButtonClicked(e->globalPos());
+ }
+ } else if ((e->button() == Qt::LeftButton) && !(e->state() & Qt::ShiftButton) && !(e->state() & Qt::ControlButton)) {
+ if (d->pressedMoved) {
+ d->pressedMoved = false;
+ return;
+ }
+ ThumbItem *item = findItem(e->pos());
+ if (item) {
+ item->setSelected(true, true);
+ }
+ }
+}
+
+void ThumbView::contentsMouseDoubleClickEvent(QMouseEvent *e) {
+ ThumbItem *item = findItem(e->pos());
+ if (item) {
+ blockSignals(true);
+ clearSelection();
+ if (renamingItem) {
+ renamingItem->cancelRenameItem();
+ }
+ blockSignals(false);
+ item->setSelected(true);
+ emit signalDoubleClicked(item);
+ }
+}
+
+void ThumbView::rebuildContainers() {
+ deleteContainers();
+ ThumbItem *item = d->firstItem;
+ appendContainer();
+ ThumbViewPrivate::ItemContainer* c = d->lastContainer;
+ while (item) {
+ if (c->rect.contains(item->rect())) {
+ c->items.append(item);
+ item = item->next;
+ } else if (c->rect.intersects(item->rect())) {
+ c->items.append( item );
+ c = c->next;
+ if (!c) {
+ appendContainer();
+ c = d->lastContainer;
+ }
+ c->items.append(item);
+ item = item->next;
+ c = c->prev;
+ } else {
+ if (item->y() < c->rect.y() && c->prev) {
+ c = c->prev;
+ continue;
+ }
+ c = c->next;
+ if (!c) {
+ appendContainer();
+ c = d->lastContainer;
+ }
+ }
+ }
+}
+
+void ThumbView::appendContainer() {
+ QSize s;
+ s = QSize(INT_MAX - 1, RECT_EXTENSION );
+ if (!d->firstContainer) {
+ d->firstContainer = new ThumbViewPrivate::ItemContainer(0, 0, QRect(QPoint(0, 0), s));
+ d->lastContainer = d->firstContainer;
+ } else {
+ d->lastContainer = new ThumbViewPrivate::ItemContainer(d->lastContainer, 0, QRect(d->lastContainer->rect.bottomLeft(), s));
+ }
+}
+
+void ThumbView::deleteContainers() {
+ ThumbViewPrivate::ItemContainer *c = d->firstContainer, *tmpc;
+ while (c) {
+ tmpc = c->next;
+ delete c;
+ c = tmpc;
+ }
+ d->firstContainer = d->lastContainer = 0;
+}
+
+void ThumbView::updateItemContainer(ThumbItem *item) {
+ if (!item) return;
+ // First remove item from any containers holding it
+ ThumbViewPrivate::ItemContainer *tmp = d->firstContainer;
+ while (tmp) {
+ tmp->items.remove(item);
+ tmp = tmp->next;
+ }
+ ThumbViewPrivate::ItemContainer *c = d->firstContainer;
+ if (!c) {
+ appendContainer();
+ c = d->firstContainer;
+ }
+ const QRect ir = item->rect();
+ bool contains = false;
+ for (;;) {
+ if (c->rect.intersects(ir)) {
+ contains = c->rect.contains(ir);
+ break;
+ }
+ c = c->next;
+ if (!c) {
+ appendContainer();
+ c = d->lastContainer;
+ }
+ }
+ if ( !c ) {
+ return;
+ }
+ c->items.append(item);
+ if (!contains) {
+ c = c->next;
+ if (!c) {
+ appendContainer();
+ c = d->lastContainer;
+ }
+ c->items.append( item );
+ }
+ if (contentsWidth() < ir.right() || contentsHeight() < ir.bottom()) {
+ resizeContents(QMAX(contentsWidth(), ir.right()), QMAX(contentsHeight(), ir.bottom()));
+ }
+}
+
+ThumbItem* ThumbView::findItem(const QPoint& pos) {
+ if (!d->firstItem) {
+ return 0;
+ }
+ ThumbViewPrivate::ItemContainer *c = d->lastContainer;
+ for (; c; c = c->prev) {
+ if ( c->rect.contains(pos) ) {
+ ThumbItem *item = c->items.last();
+ for ( ; item; item = c->items.prev()) {
+ if (item->rect().contains( pos )) {
+ return item;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+ThumbItem* ThumbView::findItem(const QString& text) {
+ if (!d->firstItem) {
+ return 0;
+ }
+ bool found = false;
+ ThumbItem *item = 0;
+ for (item = d->firstItem; item; item = item->next) {
+ if (item->text() == text) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ return item;
+ } else {
+ return 0;
+ }
+}
+
+QRect ThumbView::contentsRectToViewport(const QRect& r) {
+ QRect vr = QRect(contentsToViewport(QPoint(r.x(), r.y())), r.size());
+ return vr;
+}
+
+void ThumbView::clearSelection() {
+ blockSignals(true);
+ for (ThumbItem* item = d->firstItem; item; item = item->next) {
+ if (item->isSelected()) {
+ item->setSelected(false, false);
+ d->selectedItems.remove(item);
+ }
+ }
+ blockSignals(false);
+ emit signalSelectionChanged();
+}
+
+void ThumbView::selectAll() {
+ blockSignals(true);
+ for (ThumbItem* item = d->firstItem; item; item = item->next) {
+ if (!item->isSelected()) {
+ item->setSelected(true, false);
+ d->selectedItems.append(item);
+ }
+ }
+ blockSignals(false);
+ emit signalSelectionChanged();
+}
+
+void ThumbView::invertSelection() {
+ blockSignals(true);
+ for (ThumbItem* item = d->firstItem; item; item = item->next) {
+ if (!item->isSelected()) {
+ item->setSelected(true, false);
+ d->selectedItems.append(item);
+ } else {
+ item->setSelected(false, false);
+ d->selectedItems.remove(item);
+ }
+ }
+ blockSignals(false);
+ emit signalSelectionChanged();
+}
+
+void ThumbView::selectItem(ThumbItem* item, bool select) {
+ if (!item) {
+ return;
+ }
+ if (select) {
+ d->selectedItems.append(item);
+ } else {
+ d->selectedItems.remove(item);
+ }
+ emit signalSelectionChanged();
+}
+
+void ThumbView::emitRenamed(ThumbItem *item) {
+ if (!item) {
+ return;
+ }
+ emit signalItemRenamed(item);
+}
+
+void ThumbView::startDrag() {
+ if (!d->startDragItem) {
+ return;
+ }
+ QStrList uris;
+ for (ThumbItem *it = firstItem(); it; it=it->nextItem()) {
+ if (it->isSelected()) {
+ // PENDING(Aurlien) Check if .ascii() is ok here
+ uris.append(it->text().ascii());
+ }
+ }
+ QUriDrag* drag = new QUriDrag(uris, this);
+ if (!drag) {
+ return;
+ }
+ drag->setPixmap(*d->startDragItem->pixmap());
+ d->startDragItem = 0;
+ drag->dragCopy();
+}
+
+void ThumbView::contentsDropEvent(QDropEvent *e) {
+ if (!e) {
+ return;
+ }
+ if (e->source() == this) {
+ e->accept();
+ return;
+ }
+}
+
+void ThumbView::keyPressEvent(QKeyEvent *e) {
+ bool handled = false;
+ if (!d->firstItem) {
+ return;
+ }
+ ThumbItem *currItem = d->selectedItems.first();
+ if (!currItem) {
+ d->firstItem->setSelected(true, true);
+ return;
+ }
+ switch ( e->key() ) {
+ case Key_Home: {
+ d->firstItem->setSelected(true, true);
+ ensureItemVisible(d->firstItem);
+ handled = true;
+ break;
+ }
+ case Key_End: {
+ d->lastItem->setSelected(true, true);
+ ensureItemVisible(d->lastItem);
+ handled = true;
+ break;
+ }
+ case Key_Enter:
+ case Key_Return: {
+ emit signalReturnPressed(currItem);
+ break;
+ }
+ case Key_Right: {
+ ThumbItem *item = currItem->next;
+ if (item) {
+ item->setSelected(true,true);
+ ensureItemVisible(item);
+ handled = true;
+ }
+ break;
+ }
+ case Key_Left: {
+ ThumbItem *item = currItem->prev;
+ if (item) {
+ item->setSelected(true,true);
+ ensureItemVisible(item);
+ handled = true;
+ }
+ break;
+ }
+ case Key_Up: {
+ int x = currItem->x() + currItem->width()/2;
+ int y = currItem->y() - d->spacing*2;
+ ThumbItem *item = 0;
+ while (!item && y > 0) {
+ item = findItem(QPoint(x,y));
+ y -= d->spacing * 2;
+ }
+ if (item) {
+ item->setSelected(true,true);
+ ensureItemVisible(item);
+ handled = true;
+ }
+ break;
+ }
+ case Key_Down: {
+ int x = currItem->x() + currItem->width()/2;
+ int y = currItem->y() + currItem->height() + d->spacing * 2;
+ ThumbItem *item = 0;
+ while (!item && y < contentsHeight()) {
+ item = findItem(QPoint(x,y));
+ y += d->spacing * 2;
+ }
+ if (item) {
+ item->setSelected(true,true);
+ ensureItemVisible(item);
+ handled = true;
+ }
+ break;
+ }
+ case Key_Next: {
+ QRect r( 0, currItem->y() + visibleHeight(),
+ contentsWidth(), visibleHeight() );
+ ThumbItem *ni = findFirstVisibleItem(r);
+ if (!ni) {
+ r = QRect( 0, currItem->y() + currItem->height(), contentsWidth(), contentsHeight() );
+ ni = findLastVisibleItem( r );
+ }
+ if (ni) {
+ ni->setSelected(true, true);
+ ensureItemVisible(ni);
+ handled = true;
+ }
+ break;
+ }
+ case Key_Prior: {
+ QRect r(0, currItem->y() - visibleHeight(), contentsWidth(), visibleHeight() );
+ ThumbItem *ni = findFirstVisibleItem(r);
+ if ( !ni ) {
+ r = QRect( 0, 0, contentsWidth(), currItem->y() );
+ ni = findFirstVisibleItem( r );
+ }
+ if ( ni ) {
+ ni->setSelected(true, true);
+ ensureItemVisible(ni);
+ handled = true;
+ }
+ break;
+ }
+ default:
+ e->ignore();
+ return;
+ }
+ if (handled) {
+ viewport()->repaint();
+ emit signalSelectionChanged();
+ }
+}
+
+void ThumbView::ensureItemVisible(ThumbItem *item) {
+ if (!item) {
+ return;
+ }
+ int w = item->width();
+ int h = item->height();
+ ensureVisible( item->x() + w / 2, item->y() + h / 2, w / 2 + 1, h / 2 + 1 );
+}
+
+ThumbItem* ThumbView::findFirstVisibleItem(const QRect &r ) const {
+ ThumbViewPrivate::ItemContainer *c = d->firstContainer;
+ ThumbItem *i = 0;
+ bool alreadyIntersected = false;
+ for ( ; c; c = c->next ) {
+ if ( c->rect.intersects( r ) ) {
+ alreadyIntersected = true;
+ ThumbItem *item = c->items.first();
+ for ( ; item; item = c->items.next() ) {
+ if ( r.intersects( item->rect() ) ) {
+ if ( !i ) {
+ i = item;
+ } else {
+ QRect r2 = item->rect();
+ QRect r3 = i->rect();
+ if (r2.y() < r3.y()) {
+ i = item;
+ } else if (r2.y() == r3.y() && r2.x() < r3.x()) {
+ i = item;
+ }
+ }
+ }
+ }
+ } else {
+ if (alreadyIntersected) {
+ break;
+ }
+ }
+ }
+ return i;
+}
+
+ThumbItem* ThumbView::findLastVisibleItem(const QRect &r ) const {
+ ThumbViewPrivate::ItemContainer *c = d->firstContainer;
+ ThumbItem *i = 0;
+ bool alreadyIntersected = false;
+ for ( ; c; c = c->next ) {
+ if ( c->rect.intersects( r ) ) {
+ alreadyIntersected = true;
+ ThumbItem *item = c->items.first();
+ for ( ; item; item = c->items.next() ) {
+ if ( r.intersects( item->rect() ) ) {
+ if ( !i ) {
+ i = item;
+ } else {
+ QRect r2 = item->rect();
+ QRect r3 = i->rect();
+ if (r2.y() > r3.y()) {
+ i = item;
+ } else if (r2.y() == r3.y() && r2.x() > r3.x()) {
+ i = item;
+ }
+ }
+ }
+ }
+ } else {
+ if (alreadyIntersected) {
+ break;
+ }
+ }
+ }
+ return i;
+}
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#include "thumbview.moc"
diff --git a/kipi-plugins/kameraklient/thumbview.h b/kipi-plugins/kameraklient/thumbview.h
new file mode 100644
index 0000000..0a0e188
--- /dev/null
+++ b/kipi-plugins/kameraklient/thumbview.h
@@ -0,0 +1,124 @@
+/* ============================================================
+ * Copyright 2004 by Tudor Calin <tudor@1xtech.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 THUMBVIEW_H
+#define THUMBVIEW_H
+
+#include <qscrollview.h>
+
+class QPainter;
+class QMouseEvent;
+class QPaintEvent;
+class QDropEvent;
+class QPoint;
+
+namespace KIPIKameraKlientPlugin
+{
+
+class ThumbItem;
+class ThumbViewPrivate;
+
+class ThumbView : public QScrollView {
+
+ Q_OBJECT
+
+ friend class ThumbItem;
+
+public:
+
+ ThumbView(QWidget* parent=0, const char* name=0,
+ WFlags fl=0);
+ ~ThumbView();
+
+ ThumbItem* firstItem();
+ ThumbItem* lastItem();
+ ThumbItem* findItem(const QPoint& pos);
+ ThumbItem* findItem(const QString& text);
+
+ int count();
+ int index(ThumbItem* item);
+
+ virtual void clear(bool update=true);
+ void rearrangeItems(bool update=true);
+
+ void clearSelection();
+ void selectAll();
+ void invertSelection();
+
+ void selectItem(ThumbItem* item, bool select);
+
+ virtual void insertItem(ThumbItem *item);
+ virtual void takeItem(ThumbItem *item);
+ void updateItemContainer(ThumbItem *item);
+ QRect contentsRectToViewport(const QRect& r);
+
+ void ensureItemVisible(ThumbItem *item);
+ ThumbItem *findFirstVisibleItem(const QRect &r ) const;
+ ThumbItem *findLastVisibleItem(const QRect &r ) const;
+
+ void sort();
+
+protected:
+
+ virtual void contentsMousePressEvent(QMouseEvent *e);
+ virtual void contentsMouseMoveEvent(QMouseEvent *e);
+ virtual void contentsMouseReleaseEvent(QMouseEvent *e);
+ virtual void contentsMouseDoubleClickEvent(QMouseEvent *e);
+
+ virtual void viewportPaintEvent(QPaintEvent *pe);
+ virtual void resizeEvent(QResizeEvent* e);
+
+ virtual void keyPressEvent(QKeyEvent *e);
+
+ virtual void startDrag();
+ virtual void contentsDropEvent(QDropEvent *e);
+
+private:
+
+ void drawRubber(QPainter *p);
+
+ void rebuildContainers();
+ void appendContainer();
+ void deleteContainers();
+
+private:
+
+ ThumbItem* makeRow(ThumbItem *begin, int &y, bool &changed);
+ void emitRenamed(ThumbItem *item);
+
+private:
+
+
+ ThumbViewPrivate *d;
+ ThumbItem *renamingItem;
+
+signals:
+
+ void signalSelectionChanged();
+ void signalRightButtonClicked(const QPoint &pos);
+ void signalRightButtonClicked(ThumbItem *item, const QPoint &pos);
+ void signalDoubleClicked(ThumbItem *item);
+ void signalReturnPressed(ThumbItem *item);
+ void signalItemRenamed(ThumbItem *item);
+
+public slots:
+
+ void slotUpdate();
+
+};
+
+} // NameSpace KIPIKameraKlientPlugin
+
+#endif
diff --git a/kipi-plugins/kipi-plugins.lsm b/kipi-plugins/kipi-plugins.lsm
new file mode 100644
index 0000000..242587f
--- /dev/null
+++ b/kipi-plugins/kipi-plugins.lsm
@@ -0,0 +1,17 @@
+Begin4
+Title: kipi-plugins
+Version: 0.1.8
+Entered-date: 2009-xx-xx
+Description: Plugins for KIPI, the KDE Image Plugin Interface
+Keywords: kde image plugins, digiKam, photo management
+Author: renchi at pooh.tam.uiuc.edu (Renchi Raju)
+ caulier dot gilles at gmail dot com (Gilles Caulier)
+ blackie at kde.org (Jesper K. Pedersen)
+ aurelien dot gateau at free.fr (Aurelien Gateau)
+Maintained-by:
+Primary-site: http://www.kipi-plugins.org
+Alternate-site: http://www.digiKam.org
+Original-site:
+Platforms:
+Copying-policy: GPL
+End
diff --git a/kipi-plugins/kipiplugins.kdevelop b/kipi-plugins/kipiplugins.kdevelop
new file mode 100644
index 0000000..832d565
--- /dev/null
+++ b/kipi-plugins/kipiplugins.kdevelop
@@ -0,0 +1,217 @@
+<?xml version = '1.0'?>
+<kdevelop>
+ <general>
+ <author>KIPI dev. team</author>
+ <email/>
+ <version>$VERSION$</version>
+ <projectmanagement>KDevKDEAutoProject</projectmanagement>
+ <primarylanguage>C++</primarylanguage>
+ <keywords>
+ <keyword>Qt</keyword>
+ <keyword>KDE</keyword>
+ </keywords>
+ <projectdirectory>.</projectdirectory>
+ <absoluteprojectpath>false</absoluteprojectpath>
+ <description/>
+ <ignoreparts/>
+ <secondaryLanguages/>
+ <projectname>kipiplugins</projectname>
+ <defaultencoding/>
+ </general>
+ <kdevfileview>
+ <groups>
+ <group pattern="*.cpp;*.cxx;*.h" name="Sources" />
+ <group pattern="*.ui" name="User Interface" />
+ <group pattern="*.png" name="Icons" />
+ <group pattern="*.po;*.ts" name="Translations" />
+ <group pattern="*" name="Others" />
+ <hidenonprojectfiles>false</hidenonprojectfiles>
+ <hidenonlocation>false</hidenonlocation>
+ </groups>
+ <tree>
+ <hidepatterns>*.o,*.lo,CVS</hidepatterns>
+ <showvcsfields>false</showvcsfields>
+ <hidenonprojectfiles>false</hidenonprojectfiles>
+ </tree>
+ </kdevfileview>
+ <kdevdoctreeview>
+ <ignoretocs>
+ <toc>ada</toc>
+ <toc>ada_bugs_gcc</toc>
+ <toc>bash</toc>
+ <toc>bash_bugs</toc>
+ <toc>clanlib</toc>
+ <toc>fortran_bugs_gcc</toc>
+ <toc>gnome1</toc>
+ <toc>gnustep</toc>
+ <toc>gtk</toc>
+ <toc>gtk_bugs</toc>
+ <toc>haskell</toc>
+ <toc>haskell_bugs_ghc</toc>
+ <toc>java_bugs_gcc</toc>
+ <toc>java_bugs_sun</toc>
+ <toc>opengl</toc>
+ <toc>pascal_bugs_fp</toc>
+ <toc>php</toc>
+ <toc>php_bugs</toc>
+ <toc>perl</toc>
+ <toc>perl_bugs</toc>
+ <toc>python</toc>
+ <toc>python_bugs</toc>
+ <toc>ruby</toc>
+ <toc>ruby_bugs</toc>
+ <toc>sdl</toc>
+ <toc>stl</toc>
+ <toc>sw</toc>
+ <toc>w3c-dom-level2-html</toc>
+ <toc>w3c-svg</toc>
+ <toc>w3c-uaag10</toc>
+ <toc>wxwindows_bugs</toc>
+ </ignoretocs>
+ <ignoreqt_xml>
+ <toc>qmake User Guide</toc>
+ </ignoreqt_xml>
+ </kdevdoctreeview>
+ <kdevdebugger>
+ <general>
+ <dbgshell>libtool</dbgshell>
+ <programargs>-v -5 ./photo.mrw</programargs>
+ <gdbpath/>
+ <configGdbScript/>
+ <runShellScript/>
+ <runGdbScript/>
+ <breakonloadinglibs>true</breakonloadinglibs>
+ <separatetty>false</separatetty>
+ <floatingtoolbar>false</floatingtoolbar>
+ </general>
+ <display>
+ <staticmembers>false</staticmembers>
+ <demanglenames>true</demanglenames>
+ <outputradix>10</outputradix>
+ </display>
+ </kdevdebugger>
+ <kdevfilecreate>
+ <useglobaltypes>
+ <type ext="ui" />
+ <type ext="cpp" />
+ <type ext="h" />
+ </useglobaltypes>
+ </kdevfilecreate>
+ <kdevautoproject>
+ <make>
+ <envvars>
+ <envvar value="1" name="WANT_AUTOCONF_2_5" />
+ <envvar value="1" name="WANT_AUTOMAKE_1_6" />
+ </envvars>
+ <abortonerror>false</abortonerror>
+ <numberofjobs>1</numberofjobs>
+ <dontact>false</dontact>
+ <makebin/>
+ <prio>0</prio>
+ </make>
+ <run>
+ <directoryradio>custom</directoryradio>
+ <customdirectory>/home/gilles/Documents/Devel/SVN/trunk/extragear/libs/libkdcraw/dcraw/</customdirectory>
+ <mainprogram>/usr/bin/digikam</mainprogram>
+ <programargs/>
+ <terminal>false</terminal>
+ <autocompile>false</autocompile>
+ <envvars/>
+ <globaldebugarguments/>
+ <globalcwd/>
+ <useglobalprogram>true</useglobalprogram>
+ <autoinstall>false</autoinstall>
+ <autokdesu>false</autokdesu>
+ </run>
+ <general>
+ <useconfiguration>default</useconfiguration>
+ </general>
+ <configurations>
+ <default>
+ <configargs>--enable-debug=full --enable-opengl</configargs>
+ <builddir/>
+ <topsourcedir>../</topsourcedir>
+ <cppflags/>
+ <ldflags/>
+ <ccompiler>kdevgccoptions</ccompiler>
+ <cxxcompiler>kdevgppoptions</cxxcompiler>
+ <f77compiler>kdevpgf77options</f77compiler>
+ <ccompilerbinary/>
+ <cxxcompilerbinary/>
+ <f77compilerbinary/>
+ <cflags/>
+ <cxxflags/>
+ <f77flags/>
+ <envvars/>
+ </default>
+ </configurations>
+ </kdevautoproject>
+ <cppsupportpart>
+ <filetemplates>
+ <interfacesuffix>.h</interfacesuffix>
+ <implementationsuffix>.cpp</implementationsuffix>
+ </filetemplates>
+ </cppsupportpart>
+ <kdevcppsupport>
+ <codecompletion>
+ <includeGlobalFunctions>true</includeGlobalFunctions>
+ <includeTypes>true</includeTypes>
+ <includeEnums>true</includeEnums>
+ <includeTypedefs>false</includeTypedefs>
+ <automaticCodeCompletion>true</automaticCodeCompletion>
+ <automaticArgumentsHint>true</automaticArgumentsHint>
+ <automaticHeaderCompletion>true</automaticHeaderCompletion>
+ <codeCompletionDelay>250</codeCompletionDelay>
+ <argumentsHintDelay>400</argumentsHintDelay>
+ <headerCompletionDelay>250</headerCompletionDelay>
+ <showOnlyAccessibleItems>false</showOnlyAccessibleItems>
+ <completionBoxItemOrder>0</completionBoxItemOrder>
+ <howEvaluationContextMenu>true</howEvaluationContextMenu>
+ <showCommentWithArgumentHint>true</showCommentWithArgumentHint>
+ <statusBarTypeEvaluation>false</statusBarTypeEvaluation>
+ <namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
+ <processPrimaryTypes>true</processPrimaryTypes>
+ <processFunctionArguments>false</processFunctionArguments>
+ <preProcessAllHeaders>false</preProcessAllHeaders>
+ <parseMissingHeaders>false</parseMissingHeaders>
+ <resolveIncludePaths>true</resolveIncludePaths>
+ <alwaysParseInBackground>true</alwaysParseInBackground>
+ <usePermanentCaching>true</usePermanentCaching>
+ <alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
+ <includePaths>.;</includePaths>
+ <parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
+ <resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
+ </codecompletion>
+ <references/>
+ <creategettersetter>
+ <prefixGet/>
+ <prefixSet>set</prefixSet>
+ <prefixVariable>m_,_</prefixVariable>
+ <parameterName>theValue</parameterName>
+ <inlineGet>true</inlineGet>
+ <inlineSet>true</inlineSet>
+ </creategettersetter>
+ <qt>
+ <used>false</used>
+ <version>3</version>
+ <root>/usr/lib/qt3</root>
+ <includestyle>3</includestyle>
+ <designerintegration>EmbeddedKDevDesigner</designerintegration>
+ <qmake>/usr/lib/qt3/bin/qmake</qmake>
+ <designer>/usr/bin/designer-qt3</designer>
+ <designerpluginpaths/>
+ </qt>
+ <splitheadersource>
+ <enabled>false</enabled>
+ <synchronize>true</synchronize>
+ <orientation>Vertical</orientation>
+ </splitheadersource>
+ </kdevcppsupport>
+ <kdevcvsservice>
+ <recursivewhenupdate>true</recursivewhenupdate>
+ <prunedirswhenupdate>true</prunedirswhenupdate>
+ <createdirswhenupdate>true</createdirswhenupdate>
+ <recursivewhencommitremove>true</recursivewhencommitremove>
+ <revertoptions>-C</revertoptions>
+ </kdevcvsservice>
+</kdevelop>
diff --git a/kipi-plugins/metadataedit/Makefile.am b/kipi-plugins/metadataedit/Makefile.am
new file mode 100644
index 0000000..6f4a63b
--- /dev/null
+++ b/kipi-plugins/metadataedit/Makefile.am
@@ -0,0 +1,38 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKEXIV2_CFLAGS) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_metadataedit.la
+
+kipiplugin_metadataedit_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP)
+
+# Srcs for the plugin
+kipiplugin_metadataedit_la_SOURCES = plugin_metadataedit.cpp metadatacheckbox.cpp \
+ exifeditdialog.cpp exifcaption.cpp \
+ exifdatetime.cpp exifadjust.cpp \
+ exiflens.cpp exifdevice.cpp exiflight.cpp \
+ iptceditdialog.cpp iptccaption.cpp iptcsubjects.cpp \
+ iptccredits.cpp iptcstatus.cpp iptcorigin.cpp \
+ iptcdatetime.cpp iptckeywords.cpp iptccategories.cpp \
+ commenteditdialog.cpp commentremovedialog.cpp
+
+# Libs needed by the plugin
+kipiplugin_metadataedit_la_LIBADD = $(LIBKEXIV2_LIBS) \
+ -lkipiplugins $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_metadataedit_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries)
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_metadataedit.desktop
+
+# Icons set for the plugin.
+kipiplugin_metadataediticondir = $(kde_datadir)/kipiplugin_metadataedit/icons
+kipiplugin_metadataediticon_ICON = AUTO
+
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_metadataedit.pot
+
diff --git a/kipi-plugins/metadataedit/commenteditdialog.cpp b/kipi-plugins/metadataedit/commenteditdialog.cpp
new file mode 100644
index 0000000..ba13195
--- /dev/null
+++ b/kipi-plugins/metadataedit/commenteditdialog.cpp
@@ -0,0 +1,221 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-11-20
+ * Description : a dialog to batch edit comments
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qlabel.h>
+#include <qframe.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qwhatsthis.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <ktextedit.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "kpaboutdata.h"
+#include "commenteditdialog.h"
+#include "commenteditdialog.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class CommentEditDialogDialogPrivate
+{
+
+public:
+
+ CommentEditDialogDialogPrivate()
+ {
+ userCommentEdit = 0;
+ about = 0;
+ syncJFIFCommentCheck = 0;
+ syncEXIFCommentCheck = 0;
+ syncIPTCCaptionCheck = 0;
+ }
+
+ QCheckBox *syncJFIFCommentCheck;
+ QCheckBox *syncEXIFCommentCheck;
+ QCheckBox *syncIPTCCaptionCheck;
+
+ KTextEdit *userCommentEdit;
+
+ KIPIPlugins::KPAboutData *about;
+};
+
+CommentEditDialog::CommentEditDialog(QWidget* parent)
+ : KDialogBase(Plain, i18n("Edit Image Caption"),
+ Help|Ok|Cancel, Ok,
+ parent, 0, true, true)
+{
+ d = new CommentEditDialogDialogPrivate;
+
+ // ---------------------------------------------------------------
+ // About data and help button.
+
+ d->about = new KIPIPlugins::KPAboutData(I18N_NOOP("Edit Metadata"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Plugin to edit images' metadata"),
+ "(c) 2006-2008, Gilles Caulier");
+
+ d->about->addAuthor("Gilles Caulier", I18N_NOOP("Author and Maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, d->about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"),
+ this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // ------------------------------------------------------------
+
+ QVBoxLayout *vlay = new QVBoxLayout(plainPage(), 0, KDialog::spacingHint());
+
+ QLabel *title = new QLabel(i18n("<p>Enter the image caption hosted by <b>%1</b>. "
+ "This field is not limited (excepted with IPTC). UTF-8 encoding "
+ "will be used to save text.")
+ .arg(KApplication::kApplication()->aboutData()->appName()),
+ plainPage());
+
+ d->userCommentEdit = new KTextEdit(plainPage());
+
+ d->syncJFIFCommentCheck = new QCheckBox(i18n("Sync JFIF Comment section"), plainPage());
+ d->syncEXIFCommentCheck = new QCheckBox(i18n("Sync EXIF Comment"), plainPage());
+ d->syncIPTCCaptionCheck = new QCheckBox(i18n("Sync IPTC caption (warning: limited to 2000 printable "
+ "Ascii characters set)"), plainPage());
+
+ QLabel *note = new QLabel(i18n("<b>Note: captions from currently selected images "
+ "will be permanently replaced.</b>"), plainPage());
+
+ // ------------------------------------------------------------
+
+ vlay->addWidget(title);
+ vlay->addWidget(d->userCommentEdit);
+ vlay->addWidget(d->syncJFIFCommentCheck);
+ vlay->addWidget(d->syncEXIFCommentCheck);
+ vlay->addWidget(d->syncIPTCCaptionCheck);
+ vlay->addWidget(note);
+
+ // ------------------------------------------------------------
+
+ readSettings();
+}
+
+CommentEditDialog::~CommentEditDialog()
+{
+ delete d->about;
+ delete d;
+}
+
+void CommentEditDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("metadataedit", "kipi-plugins");
+}
+
+void CommentEditDialog::closeEvent(QCloseEvent *e)
+{
+ if (!e) return;
+ saveSettings();
+ e->accept();
+}
+
+void CommentEditDialog::slotCancel()
+{
+ saveSettings();
+ KDialogBase::slotCancel();
+}
+
+void CommentEditDialog::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Comments Edit Settings");
+ setCheckedSyncJFIFComment(config.readBoolEntry("Sync JFIF Comment", true));
+ setCheckedSyncEXIFComment(config.readBoolEntry("Sync EXIF Comment", true));
+ setCheckedSyncIPTCCaption(config.readBoolEntry("Sync IPTC Caption", true));
+ resize(configDialogSize(config, QString("Comments Edit Dialog")));
+}
+
+void CommentEditDialog::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Comments Edit Settings");
+ config.writeEntry("Sync JFIF Comment", syncJFIFCommentIsChecked());
+ config.writeEntry("Sync EXIF Comment", syncEXIFCommentIsChecked());
+ config.writeEntry("Sync IPTC Caption", syncIPTCCaptionIsChecked());
+ saveDialogSize(config, QString("Comments Edit Dialog"));
+ config.sync();
+}
+
+void CommentEditDialog::slotOk()
+{
+ saveSettings();
+ accept();
+}
+
+bool CommentEditDialog::syncJFIFCommentIsChecked()
+{
+ return d->syncJFIFCommentCheck->isChecked();
+}
+
+bool CommentEditDialog::syncEXIFCommentIsChecked()
+{
+ return d->syncEXIFCommentCheck->isChecked();
+}
+
+bool CommentEditDialog::syncIPTCCaptionIsChecked()
+{
+ return d->syncIPTCCaptionCheck->isChecked();
+}
+
+QString CommentEditDialog::getComments()
+{
+ return d->userCommentEdit->text();
+}
+
+void CommentEditDialog::setCheckedSyncJFIFComment(bool c)
+{
+ d->syncJFIFCommentCheck->setChecked(c);
+}
+
+void CommentEditDialog::setCheckedSyncEXIFComment(bool c)
+{
+ d->syncEXIFCommentCheck->setChecked(c);
+}
+
+void CommentEditDialog::setCheckedSyncIPTCCaption(bool c)
+{
+ d->syncIPTCCaptionCheck->setChecked(c);
+}
+
+} // namespace KIPIMetadataEditPlugin
diff --git a/kipi-plugins/metadataedit/commenteditdialog.h b/kipi-plugins/metadataedit/commenteditdialog.h
new file mode 100644
index 0000000..876d64a
--- /dev/null
+++ b/kipi-plugins/metadataedit/commenteditdialog.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-11-20
+ * Description : a dialog to batch edit comments
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 COMMENTEDITDIALOG_H
+#define COMMENTEDITDIALOG_H
+
+// Qt includes.
+
+#include <qstring.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class CommentEditDialogDialogPrivate;
+
+class CommentEditDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ CommentEditDialog(QWidget* parent);
+ ~CommentEditDialog();
+
+ bool syncJFIFCommentIsChecked();
+ bool syncEXIFCommentIsChecked();
+ bool syncIPTCCaptionIsChecked();
+
+ void setCheckedSyncJFIFComment(bool c);
+ void setCheckedSyncEXIFComment(bool c);
+ void setCheckedSyncIPTCCaption(bool c);
+
+ QString getComments();
+
+protected slots:
+
+ void slotOk();
+ void slotHelp();
+ void slotCancel();
+
+protected:
+
+ void closeEvent(QCloseEvent *);
+
+private:
+
+ void readSettings();
+ void saveSettings();
+
+private:
+
+ CommentEditDialogDialogPrivate *d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif /* COMMENTEDITDIALOG_H */
diff --git a/kipi-plugins/metadataedit/commentremovedialog.cpp b/kipi-plugins/metadataedit/commentremovedialog.cpp
new file mode 100644
index 0000000..de18d0e
--- /dev/null
+++ b/kipi-plugins/metadataedit/commentremovedialog.cpp
@@ -0,0 +1,219 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-11-20
+ * Description : a dialog to batch remove comments
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qlabel.h>
+#include <qframe.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qwhatsthis.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "kpaboutdata.h"
+#include "commentremovedialog.h"
+#include "commentremovedialog.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class CommentRemoveDialogDialogPrivate
+{
+
+public:
+
+ CommentRemoveDialogDialogPrivate()
+ {
+ about = 0;
+ removeHOSTCommentCheck = 0;
+ removeJFIFCommentCheck = 0;
+ removeEXIFCommentCheck = 0;
+ removeIPTCCaptionCheck = 0;
+ }
+
+ QCheckBox *removeHOSTCommentCheck;
+ QCheckBox *removeJFIFCommentCheck;
+ QCheckBox *removeEXIFCommentCheck;
+ QCheckBox *removeIPTCCaptionCheck;
+
+ KIPIPlugins::KPAboutData *about;
+};
+
+CommentRemoveDialog::CommentRemoveDialog(QWidget* parent)
+ : KDialogBase(Plain, i18n("Remove Image Captions"),
+ Help|Ok|Cancel, Ok,
+ parent, 0, true, true)
+{
+ d = new CommentRemoveDialogDialogPrivate;
+
+ // ---------------------------------------------------------------
+ // About data and help button.
+
+ d->about = new KIPIPlugins::KPAboutData(I18N_NOOP("Edit Metadata"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Plugin to edit pictures metadata"),
+ "(c) 2006-2008, Gilles Caulier");
+
+ d->about->addAuthor("Gilles Caulier", I18N_NOOP("Author and Maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, d->about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"),
+ this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // ------------------------------------------------------------
+
+ QVBoxLayout *vlay = new QVBoxLayout(plainPage(), 0, KDialog::spacingHint());
+
+ d->removeHOSTCommentCheck = new QCheckBox(i18n("Remove caption created by %1")
+ .arg(KApplication::kApplication()->aboutData()->appName()),
+ plainPage());
+ d->removeJFIFCommentCheck = new QCheckBox(i18n("Remove JFIF Comment section"), plainPage());
+ d->removeEXIFCommentCheck = new QCheckBox(i18n("Remove EXIF Comment"), plainPage());
+ d->removeIPTCCaptionCheck = new QCheckBox(i18n("Remove IPTC caption"), plainPage());
+
+ QLabel *note = new QLabel(i18n("<b>Note: Captions from currently selected images "
+ "will be permanently removed.</b>"), plainPage());
+
+ // ------------------------------------------------------------
+
+ vlay->addWidget(d->removeHOSTCommentCheck);
+ vlay->addWidget(d->removeJFIFCommentCheck);
+ vlay->addWidget(d->removeEXIFCommentCheck);
+ vlay->addWidget(d->removeIPTCCaptionCheck);
+ vlay->addWidget(note);
+
+ // ------------------------------------------------------------
+
+ readSettings();
+}
+
+CommentRemoveDialog::~CommentRemoveDialog()
+{
+ delete d->about;
+ delete d;
+}
+
+void CommentRemoveDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("metadataedit", "kipi-plugins");
+}
+
+void CommentRemoveDialog::closeEvent(QCloseEvent *e)
+{
+ if (!e) return;
+ saveSettings();
+ e->accept();
+}
+
+void CommentRemoveDialog::slotCancel()
+{
+ saveSettings();
+ KDialogBase::slotCancel();
+}
+
+void CommentRemoveDialog::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Comments Remove Settings");
+ setCheckedRemoveHOSTComment(config.readBoolEntry("Remove HOST Comment", true));
+ setCheckedRemoveJFIFComment(config.readBoolEntry("Remove JFIF Comment", true));
+ setCheckedRemoveEXIFComment(config.readBoolEntry("Remove EXIF Comment", true));
+ setCheckedRemoveIPTCCaption(config.readBoolEntry("Remove IPTC Caption", true));
+ resize(configDialogSize(config, QString("Comments Remove Dialog")));
+}
+
+void CommentRemoveDialog::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Comments Remove Settings");
+ config.writeEntry("Remove HOST Comment", removeHOSTCommentIsChecked());
+ config.writeEntry("Remove JFIF Comment", removeJFIFCommentIsChecked());
+ config.writeEntry("Remove EXIF Comment", removeEXIFCommentIsChecked());
+ config.writeEntry("Remove IPTC Caption", removeIPTCCaptionIsChecked());
+ saveDialogSize(config, QString("Comments Remove Dialog"));
+ config.sync();
+}
+
+void CommentRemoveDialog::slotOk()
+{
+ saveSettings();
+ accept();
+}
+
+bool CommentRemoveDialog::removeHOSTCommentIsChecked()
+{
+ return d->removeHOSTCommentCheck->isChecked();
+}
+
+bool CommentRemoveDialog::removeJFIFCommentIsChecked()
+{
+ return d->removeJFIFCommentCheck->isChecked();
+}
+
+bool CommentRemoveDialog::removeEXIFCommentIsChecked()
+{
+ return d->removeEXIFCommentCheck->isChecked();
+}
+
+bool CommentRemoveDialog::removeIPTCCaptionIsChecked()
+{
+ return d->removeIPTCCaptionCheck->isChecked();
+}
+
+void CommentRemoveDialog::setCheckedRemoveHOSTComment(bool c)
+{
+ d->removeHOSTCommentCheck->setChecked(c);
+}
+
+void CommentRemoveDialog::setCheckedRemoveJFIFComment(bool c)
+{
+ d->removeJFIFCommentCheck->setChecked(c);
+}
+
+void CommentRemoveDialog::setCheckedRemoveEXIFComment(bool c)
+{
+ d->removeEXIFCommentCheck->setChecked(c);
+}
+
+void CommentRemoveDialog::setCheckedRemoveIPTCCaption(bool c)
+{
+ d->removeIPTCCaptionCheck->setChecked(c);
+}
+
+} // namespace KIPIMetadataEditPlugin
diff --git a/kipi-plugins/metadataedit/commentremovedialog.h b/kipi-plugins/metadataedit/commentremovedialog.h
new file mode 100644
index 0000000..4d812dc
--- /dev/null
+++ b/kipi-plugins/metadataedit/commentremovedialog.h
@@ -0,0 +1,76 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-11-20
+ * Description : a dialog to batch remove comments
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 COMMENTREMOVEDIALOG_H
+#define COMMENTREMOVEDIALOG_H
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class CommentRemoveDialogDialogPrivate;
+
+class CommentRemoveDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ CommentRemoveDialog(QWidget* parent);
+ ~CommentRemoveDialog();
+
+ bool removeHOSTCommentIsChecked();
+ bool removeJFIFCommentIsChecked();
+ bool removeEXIFCommentIsChecked();
+ bool removeIPTCCaptionIsChecked();
+
+ void setCheckedRemoveHOSTComment(bool c);
+ void setCheckedRemoveJFIFComment(bool c);
+ void setCheckedRemoveEXIFComment(bool c);
+ void setCheckedRemoveIPTCCaption(bool c);
+
+protected slots:
+
+ void slotOk();
+ void slotHelp();
+ void slotCancel();
+
+protected:
+
+ void closeEvent(QCloseEvent *);
+
+private:
+
+ void readSettings();
+ void saveSettings();
+
+private:
+
+ CommentRemoveDialogDialogPrivate *d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif /* COMMENTREMOVEDIALOG_H */
diff --git a/kipi-plugins/metadataedit/exifadjust.cpp b/kipi-plugins/metadataedit/exifadjust.cpp
new file mode 100644
index 0000000..f80320a
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifadjust.cpp
@@ -0,0 +1,369 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF adjustments settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qcombobox.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <knuminput.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "metadatacheckbox.h"
+#include "exifadjust.h"
+#include "exifadjust.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFAdjustPriv
+{
+public:
+
+ EXIFAdjustPriv()
+ {
+ brightnessCheck = 0;
+ gainControlCheck = 0;
+ contrastCheck = 0;
+ saturationCheck = 0;
+ sharpnessCheck = 0;
+ customRenderedCheck = 0;
+ brightnessEdit = 0;
+ gainControlCB = 0;
+ contrastCB = 0;
+ saturationCB = 0;
+ sharpnessCB = 0;
+ customRenderedCB = 0;
+ }
+
+ QCheckBox *brightnessCheck;
+
+ QComboBox *gainControlCB;
+ QComboBox *contrastCB;
+ QComboBox *saturationCB;
+ QComboBox *sharpnessCB;
+ QComboBox *customRenderedCB;
+
+ KDoubleSpinBox *brightnessEdit;
+
+ MetadataCheckBox *gainControlCheck;
+ MetadataCheckBox *contrastCheck;
+ MetadataCheckBox *saturationCheck;
+ MetadataCheckBox *sharpnessCheck;
+ MetadataCheckBox *customRenderedCheck;
+};
+
+EXIFAdjust::EXIFAdjust(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new EXIFAdjustPriv;
+
+ QGridLayout* grid = new QGridLayout(parent, 6, 2, KDialog::spacingHint());
+
+ // --------------------------------------------------------
+
+ d->brightnessCheck = new QCheckBox(i18n("Brightness (APEX):"), parent);
+ d->brightnessEdit = new KDoubleSpinBox(-99.99, 99.99, 0.1, 0.0, 2, parent);
+ grid->addMultiCellWidget(d->brightnessCheck, 0, 0, 0, 0);
+ grid->addMultiCellWidget(d->brightnessEdit, 0, 0, 2, 2);
+ QWhatsThis::add(d->brightnessEdit, i18n("<p>Set here the brightness adjustment value in APEX unit "
+ "used by camera to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->gainControlCheck = new MetadataCheckBox(i18n("Gain Control:"), parent);
+ d->gainControlCB = new QComboBox(false, parent);
+ d->gainControlCB->insertItem(i18n("None"), 0);
+ d->gainControlCB->insertItem(i18n("Low gain up"), 1);
+ d->gainControlCB->insertItem(i18n("High gain up"), 2);
+ d->gainControlCB->insertItem(i18n("Low gain down"), 3);
+ d->gainControlCB->insertItem(i18n("High gain down"), 4);
+ grid->addMultiCellWidget(d->gainControlCheck, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->gainControlCB, 1, 1, 2, 2);
+ QWhatsThis::add(d->gainControlCB, i18n("<p>Set here the degree of overall image gain adjustment "
+ "used by camera to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->contrastCheck = new MetadataCheckBox(i18n("Contrast:"), parent);
+ d->contrastCB = new QComboBox(false, parent);
+ d->contrastCB->insertItem(i18n("Normal"), 0);
+ d->contrastCB->insertItem(i18n("Soft"), 1);
+ d->contrastCB->insertItem(i18n("Hard"), 2);
+ grid->addMultiCellWidget(d->contrastCheck, 2, 2, 0, 0);
+ grid->addMultiCellWidget(d->contrastCB, 2, 2, 2, 2);
+ QWhatsThis::add(d->contrastCB, i18n("<p>Set here the direction of contrast processing "
+ "applied by the camera to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->saturationCheck = new MetadataCheckBox(i18n("Saturation:"), parent);
+ d->saturationCB = new QComboBox(false, parent);
+ d->saturationCB->insertItem(i18n("Normal"), 0);
+ d->saturationCB->insertItem(i18n("Low"), 1);
+ d->saturationCB->insertItem(i18n("High"), 2);
+ grid->addMultiCellWidget(d->saturationCheck, 3, 3, 0, 0);
+ grid->addMultiCellWidget(d->saturationCB, 3, 3, 2, 2);
+ QWhatsThis::add(d->saturationCB, i18n("<p>Set here the direction of saturation processing "
+ "applied by the camera to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->sharpnessCheck = new MetadataCheckBox(i18n("Sharpness:"), parent);
+ d->sharpnessCB = new QComboBox(false, parent);
+ d->sharpnessCB->insertItem(i18n("Normal"), 0);
+ d->sharpnessCB->insertItem(i18n("Soft"), 1);
+ d->sharpnessCB->insertItem(i18n("Hard"), 2);
+ grid->addMultiCellWidget(d->sharpnessCheck, 4, 4, 0, 0);
+ grid->addMultiCellWidget(d->sharpnessCB, 4, 4, 2, 2);
+ QWhatsThis::add(d->sharpnessCB, i18n("<p>Set here the direction of sharpness processing "
+ "applied by the camera to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->customRenderedCheck = new MetadataCheckBox(i18n("Custom rendered:"), parent);
+ d->customRenderedCB = new QComboBox(false, parent);
+ d->customRenderedCB->insertItem(i18n("Normal process"), 0);
+ d->customRenderedCB->insertItem(i18n("Custom process"), 1);
+ grid->addMultiCellWidget(d->customRenderedCheck, 5, 5, 0, 0);
+ grid->addMultiCellWidget(d->customRenderedCB, 5, 5, 2, 2);
+ QWhatsThis::add(d->customRenderedCB, i18n("<p>Set here the use of special processing on "
+ "image data, such as rendering geared to output."));
+
+ grid->setColStretch(1, 10);
+ grid->setRowStretch(6, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->brightnessCheck, SIGNAL(toggled(bool)),
+ d->brightnessEdit, SLOT(setEnabled(bool)));
+
+ connect(d->gainControlCheck, SIGNAL(toggled(bool)),
+ d->gainControlCB, SLOT(setEnabled(bool)));
+
+ connect(d->contrastCheck, SIGNAL(toggled(bool)),
+ d->contrastCB, SLOT(setEnabled(bool)));
+
+ connect(d->saturationCheck, SIGNAL(toggled(bool)),
+ d->saturationCB, SLOT(setEnabled(bool)));
+
+ connect(d->sharpnessCheck, SIGNAL(toggled(bool)),
+ d->sharpnessCB, SLOT(setEnabled(bool)));
+
+ connect(d->customRenderedCheck, SIGNAL(toggled(bool)),
+ d->customRenderedCB, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->brightnessCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->gainControlCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->contrastCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->saturationCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sharpnessCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->customRenderedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->gainControlCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->contrastCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->saturationCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sharpnessCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->customRenderedCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->brightnessEdit, SIGNAL(valueChanged(double)),
+ this, SIGNAL(signalModified()));
+}
+
+EXIFAdjust::~EXIFAdjust()
+{
+ delete d;
+}
+
+void EXIFAdjust::readMetadata(QByteArray& exifData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ long int num=1, den=1;
+ long val=0;
+
+ d->brightnessEdit->setValue(0.0);
+ d->brightnessCheck->setChecked(false);
+ if (exiv2Iface.getExifTagRational("Exif.Photo.BrightnessValue", num, den))
+ {
+ d->brightnessEdit->setValue((double)(num) / (double)(den));
+ d->brightnessCheck->setChecked(true);
+ }
+ d->brightnessEdit->setEnabled(d->brightnessCheck->isChecked());
+
+ d->gainControlCB->setCurrentItem(0);
+ d->gainControlCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.GainControl", val))
+ {
+ if (val >= 0 && val <= 4)
+ {
+ d->gainControlCB->setCurrentItem(val);
+ d->gainControlCheck->setChecked(true);
+ }
+ else
+ d->gainControlCheck->setValid(false);
+ }
+ d->gainControlCB->setEnabled(d->gainControlCheck->isChecked());
+
+ d->contrastCB->setCurrentItem(0);
+ d->contrastCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.Contrast", val))
+ {
+ if (val >= 0 && val <= 2)
+ {
+ d->contrastCB->setCurrentItem(val);
+ d->contrastCheck->setChecked(true);
+ }
+ else
+ d->contrastCheck->setValid(false);
+ }
+ d->contrastCB->setEnabled(d->contrastCheck->isChecked());
+
+ d->saturationCB->setCurrentItem(0);
+ d->saturationCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.Saturation", val))
+ {
+ if (val >= 0 && val <= 2)
+ {
+ d->saturationCB->setCurrentItem(val);
+ d->saturationCheck->setChecked(true);
+ }
+ else
+ d->saturationCheck->setValid(false);
+ }
+ d->saturationCB->setEnabled(d->saturationCheck->isChecked());
+
+ d->sharpnessCB->setCurrentItem(0);
+ d->sharpnessCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.Sharpness", val))
+ {
+ if (val >= 0 && val <= 2)
+ {
+ d->sharpnessCB->setCurrentItem(val);
+ d->sharpnessCheck->setChecked(true);
+ }
+ else
+ d->sharpnessCheck->setValid(false);
+ }
+ d->sharpnessCB->setEnabled(d->sharpnessCheck->isChecked());
+
+ d->customRenderedCB->setCurrentItem(0);
+ d->customRenderedCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.CustomRendered", val))
+ {
+ if (val >= 0 && val <= 1)
+ {
+ d->customRenderedCB->setCurrentItem(val);
+ d->customRenderedCheck->setChecked(true);
+ }
+ else
+ d->customRenderedCheck->setValid(false);
+ }
+ d->customRenderedCB->setEnabled(d->customRenderedCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void EXIFAdjust::applyMetadata(QByteArray& exifData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ long int num=1, den=1;
+
+ if (d->brightnessCheck->isChecked())
+ {
+ exiv2Iface.convertToRational(d->brightnessEdit->value(), &num, &den, 1);
+ exiv2Iface.setExifTagRational("Exif.Photo.BrightnessValue", num, den);
+ }
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.BrightnessValue");
+
+ if (d->gainControlCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.GainControl", d->gainControlCB->currentItem());
+ else if (d->gainControlCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.GainControl");
+
+ if (d->contrastCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.Contrast", d->contrastCB->currentItem());
+ else if (d->contrastCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.Contrast");
+
+ if (d->saturationCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.Saturation", d->saturationCB->currentItem());
+ else if (d->saturationCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.Saturation");
+
+ if (d->sharpnessCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.Sharpness", d->sharpnessCB->currentItem());
+ else if (d->sharpnessCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.Sharpness");
+
+ if (d->customRenderedCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.CustomRendered", d->customRenderedCB->currentItem());
+ else if (d->customRenderedCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.CustomRendered");
+
+ exifData = exiv2Iface.getExif();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/exifadjust.h b/kipi-plugins/metadataedit/exifadjust.h
new file mode 100644
index 0000000..bf7be12
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifadjust.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF adjustments settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 EXIF_ADJUST_H
+#define EXIF_ADJUST_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFAdjustPriv;
+
+class EXIFAdjust : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ EXIFAdjust(QWidget* parent);
+ ~EXIFAdjust();
+
+ void applyMetadata(QByteArray& exifData);
+ void readMetadata(QByteArray& exifData);
+
+signals:
+
+ void signalModified();
+
+private:
+
+ EXIFAdjustPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // EXIF_ADJUST_H
diff --git a/kipi-plugins/metadataedit/exifcaption.cpp b/kipi-plugins/metadataedit/exifcaption.cpp
new file mode 100644
index 0000000..abab570
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifcaption.cpp
@@ -0,0 +1,385 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : EXIF caption settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qhgroupbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qcheckbox.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <klineedit.h>
+#include <ktextedit.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kactivelabel.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "exifcaption.h"
+#include "exifcaption.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFCaptionPriv
+{
+public:
+
+ EXIFCaptionPriv()
+ {
+ documentNameEdit = 0;
+ imageDescEdit = 0;
+ artistEdit = 0;
+ copyrightEdit = 0;
+ userCommentEdit = 0;
+ userCommentCheck = 0;
+ documentNameCheck = 0;
+ imageDescCheck = 0;
+ artistCheck = 0;
+ copyrightCheck = 0;
+ syncJFIFCommentCheck = 0;
+ syncHOSTCommentCheck = 0;
+ syncIPTCCaptionCheck = 0;
+ }
+
+ QCheckBox *documentNameCheck;
+ QCheckBox *imageDescCheck;
+ QCheckBox *artistCheck;
+ QCheckBox *copyrightCheck;
+ QCheckBox *userCommentCheck;
+ QCheckBox *syncJFIFCommentCheck;
+ QCheckBox *syncHOSTCommentCheck;
+ QCheckBox *syncIPTCCaptionCheck;
+
+ KTextEdit *userCommentEdit;
+
+ KLineEdit *documentNameEdit;
+ KLineEdit *imageDescEdit;
+ KLineEdit *artistEdit;
+ KLineEdit *copyrightEdit;
+};
+
+EXIFCaption::EXIFCaption(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new EXIFCaptionPriv;
+ QVBoxLayout *vlay = new QVBoxLayout( parent, 0, KDialog::spacingHint() );
+
+ // EXIF only accept printable Ascii char.
+ QRegExp asciiRx("[\x20-\x7F]+$");
+ QValidator *asciiValidator = new QRegExpValidator(asciiRx, this);
+
+ // --------------------------------------------------------
+
+ d->documentNameCheck = new QCheckBox(i18n("Document name (*):"), parent);
+ d->documentNameEdit = new KLineEdit(parent);
+ d->documentNameEdit->setValidator(asciiValidator);
+ vlay->addWidget(d->documentNameCheck);
+ vlay->addWidget(d->documentNameEdit);
+ QWhatsThis::add(d->documentNameEdit, i18n("<p>Enter the name of the document from which "
+ "this image was been scanned. This field is limited "
+ "to ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->imageDescCheck = new QCheckBox(i18n("Image description (*):"), parent);
+ d->imageDescEdit = new KLineEdit(parent);
+ d->imageDescEdit->setValidator(asciiValidator);
+ vlay->addWidget(d->imageDescCheck);
+ vlay->addWidget(d->imageDescEdit);
+ QWhatsThis::add(d->imageDescEdit, i18n("<p>Enter the image title. This field is limited "
+ "to ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->artistCheck = new QCheckBox(i18n("Artist (*):"), parent);
+ d->artistEdit = new KLineEdit(parent);
+ d->artistEdit->setValidator(asciiValidator);
+ vlay->addWidget(d->artistCheck);
+ vlay->addWidget(d->artistEdit);
+ QWhatsThis::add(d->artistEdit, i18n("<p>Enter the image author's name. "
+ "This field is limited to ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->copyrightCheck = new QCheckBox(i18n("Copyright (*):"), parent);
+ d->copyrightEdit = new KLineEdit(parent);
+ d->copyrightEdit->setValidator(asciiValidator);
+ vlay->addWidget(d->copyrightCheck);
+ vlay->addWidget(d->copyrightEdit);
+ QWhatsThis::add(d->copyrightEdit, i18n("<p>Enter the copyright owner of the image. "
+ "This field is limited to ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->userCommentCheck = new QCheckBox(i18n("Caption:"), parent);
+ d->userCommentEdit = new KTextEdit(parent);
+ QWhatsThis::add(d->userCommentEdit, i18n("<p>Enter the image's caption. "
+ "This field is not limited. UTF8 encoding "
+ "will be used to save the text."));
+
+ d->syncHOSTCommentCheck = new QCheckBox(i18n("Sync captions entered through %1")
+ .arg(KApplication::kApplication()->aboutData()->appName()),
+ parent);
+ d->syncJFIFCommentCheck = new QCheckBox(i18n("Sync JFIF Comment section"), parent);
+ d->syncIPTCCaptionCheck = new QCheckBox(i18n("Sync IPTC caption (warning: limited to 2000 printable "
+ "Ascii characters set)"), parent);
+
+ vlay->addWidget(d->userCommentCheck);
+ vlay->addWidget(d->userCommentEdit);
+ vlay->addWidget(d->syncHOSTCommentCheck);
+ vlay->addWidget(d->syncJFIFCommentCheck);
+ vlay->addWidget(d->syncIPTCCaptionCheck);
+
+ // --------------------------------------------------------
+
+ KActiveLabel *note = new KActiveLabel(i18n("<b>Note: "
+ "<b><a href='http://en.wikipedia.org/wiki/EXIF'>EXIF</a></b> "
+ "text tags marked by (*) only support printable "
+ "<b><a href='http://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
+ "characters set.</b>"), parent);
+ vlay->addWidget(note);
+ vlay->addStretch();
+
+ // --------------------------------------------------------
+
+ connect(d->documentNameCheck, SIGNAL(toggled(bool)),
+ d->documentNameEdit, SLOT(setEnabled(bool)));
+
+ connect(d->imageDescCheck, SIGNAL(toggled(bool)),
+ d->imageDescEdit, SLOT(setEnabled(bool)));
+
+ connect(d->artistCheck, SIGNAL(toggled(bool)),
+ d->artistEdit, SLOT(setEnabled(bool)));
+
+ connect(d->copyrightCheck, SIGNAL(toggled(bool)),
+ d->copyrightEdit, SLOT(setEnabled(bool)));
+
+ connect(d->userCommentCheck, SIGNAL(toggled(bool)),
+ d->userCommentEdit, SLOT(setEnabled(bool)));
+
+ connect(d->userCommentCheck, SIGNAL(toggled(bool)),
+ d->syncJFIFCommentCheck, SLOT(setEnabled(bool)));
+
+ connect(d->userCommentCheck, SIGNAL(toggled(bool)),
+ d->syncHOSTCommentCheck, SLOT(setEnabled(bool)));
+
+ connect(d->userCommentCheck, SIGNAL(toggled(bool)),
+ d->syncIPTCCaptionCheck, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->documentNameCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->imageDescCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->artistCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->copyrightCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->userCommentCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->userCommentEdit, SIGNAL(textChanged()),
+ this, SIGNAL(signalModified()));
+
+ connect(d->documentNameEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->imageDescEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->artistEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->copyrightEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+}
+
+EXIFCaption::~EXIFCaption()
+{
+ delete d;
+}
+
+bool EXIFCaption::syncJFIFCommentIsChecked()
+{
+ return d->syncJFIFCommentCheck->isChecked();
+}
+
+bool EXIFCaption::syncHOSTCommentIsChecked()
+{
+ return d->syncHOSTCommentCheck->isChecked();
+}
+
+bool EXIFCaption::syncIPTCCaptionIsChecked()
+{
+ return d->syncIPTCCaptionCheck->isChecked();
+}
+
+QString EXIFCaption::getEXIFUserComments()
+{
+ return d->userCommentEdit->text();
+}
+
+void EXIFCaption::setCheckedSyncJFIFComment(bool c)
+{
+ d->syncJFIFCommentCheck->setChecked(c);
+}
+
+void EXIFCaption::setCheckedSyncHOSTComment(bool c)
+{
+ d->syncHOSTCommentCheck->setChecked(c);
+}
+
+void EXIFCaption::setCheckedSyncIPTCCaption(bool c)
+{
+ d->syncIPTCCaptionCheck->setChecked(c);
+}
+
+void EXIFCaption::readMetadata(QByteArray& exifData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ QString data;
+
+ d->documentNameEdit->clear();
+ d->documentNameCheck->setChecked(false);
+ data = exiv2Iface.getExifTagString("Exif.Image.DocumentName", false);
+ if (!data.isNull())
+ {
+ d->documentNameEdit->setText(data);
+ d->documentNameCheck->setChecked(true);
+ }
+ d->documentNameEdit->setEnabled(d->documentNameCheck->isChecked());
+
+ d->imageDescEdit->clear();
+ d->imageDescCheck->setChecked(false);
+ data = exiv2Iface.getExifTagString("Exif.Image.ImageDescription", false);
+ if (!data.isNull())
+ {
+ d->imageDescEdit->setText(data);
+ d->imageDescCheck->setChecked(true);
+ }
+ d->imageDescEdit->setEnabled(d->imageDescCheck->isChecked());
+
+ d->artistEdit->clear();
+ d->artistCheck->setChecked(false);
+ data = exiv2Iface.getExifTagString("Exif.Image.Artist", false);
+ if (!data.isNull())
+ {
+ d->artistEdit->setText(data);
+ d->artistCheck->setChecked(true);
+ }
+ d->artistEdit->setEnabled(d->artistCheck->isChecked());
+
+ d->copyrightEdit->clear();
+ d->copyrightCheck->setChecked(false);
+ data = exiv2Iface.getExifTagString("Exif.Image.Copyright", false);
+ if (!data.isNull())
+ {
+ d->copyrightEdit->setText(data);
+ d->copyrightCheck->setChecked(true);
+ }
+ d->copyrightEdit->setEnabled(d->copyrightCheck->isChecked());
+
+ d->userCommentEdit->clear();
+ d->userCommentCheck->setChecked(false);
+ data = exiv2Iface.getExifComment();
+ if (!data.isNull())
+ {
+ d->userCommentEdit->setText(data);
+ d->userCommentCheck->setChecked(true);
+ }
+ d->userCommentEdit->setEnabled(d->userCommentCheck->isChecked());
+ d->syncJFIFCommentCheck->setEnabled(d->userCommentCheck->isChecked());
+ d->syncHOSTCommentCheck->setEnabled(d->userCommentCheck->isChecked());
+ d->syncIPTCCaptionCheck->setEnabled(d->userCommentCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void EXIFCaption::applyMetadata(QByteArray& exifData, QByteArray& iptcData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ exiv2Iface.setIptc(iptcData);
+
+ if (d->documentNameCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Image.DocumentName", d->documentNameEdit->text());
+ else
+ exiv2Iface.removeExifTag("Exif.Image.DocumentName");
+
+ if (d->imageDescCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Image.ImageDescription", d->imageDescEdit->text());
+ else
+ exiv2Iface.removeExifTag("Exif.Image.ImageDescription");
+
+ if (d->artistCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Image.Artist", d->artistEdit->text());
+ else
+ exiv2Iface.removeExifTag("Exif.Image.Artist");
+
+ if (d->copyrightCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Image.Copyright", d->copyrightEdit->text());
+ else
+ exiv2Iface.removeExifTag("Exif.Image.Copyright");
+
+ if (d->userCommentCheck->isChecked())
+ {
+ exiv2Iface.setExifComment(d->userCommentEdit->text());
+
+ if (syncJFIFCommentIsChecked())
+ exiv2Iface.setComments(d->userCommentEdit->text().utf8());
+
+ if (syncIPTCCaptionIsChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Caption", d->userCommentEdit->text());
+ }
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.UserComment");
+
+ exiv2Iface.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+
+ exifData = exiv2Iface.getExif();
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
diff --git a/kipi-plugins/metadataedit/exifcaption.h b/kipi-plugins/metadataedit/exifcaption.h
new file mode 100644
index 0000000..5aa52c0
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifcaption.h
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : EXIF caption settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 EXIF_CAPTION_H
+#define EXIF_CAPTION_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+#include <qstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFCaptionPriv;
+
+class EXIFCaption : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ EXIFCaption(QWidget* parent);
+ ~EXIFCaption();
+
+ void applyMetadata(QByteArray& exifData, QByteArray& iptcData);
+ void readMetadata(QByteArray& exifData);
+
+ bool syncJFIFCommentIsChecked();
+ bool syncHOSTCommentIsChecked();
+ bool syncIPTCCaptionIsChecked();
+
+ void setCheckedSyncJFIFComment(bool c);
+ void setCheckedSyncHOSTComment(bool c);
+ void setCheckedSyncIPTCCaption(bool c);
+
+ QString getEXIFUserComments();
+
+signals:
+
+ void signalModified();
+
+private:
+
+ EXIFCaptionPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // EXIF_CAPTION_H
diff --git a/kipi-plugins/metadataedit/exifdatetime.cpp b/kipi-plugins/metadataedit/exifdatetime.cpp
new file mode 100644
index 0000000..7388703
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifdatetime.cpp
@@ -0,0 +1,421 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF date and time settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qcheckbox.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <kdatetimewidget.h>
+#include <knuminput.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kseparator.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "exifdatetime.h"
+#include "exifdatetime.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFDateTimePriv
+{
+public:
+
+ EXIFDateTimePriv()
+ {
+ dateCreatedSel = 0;
+ dateOriginalSel = 0;
+ dateDigitalizedSel = 0;
+ dateCreatedSubSecEdit = 0;
+ dateOriginalSubSecEdit = 0;
+ dateDigitalizedSubSecEdit = 0;
+
+ dateCreatedCheck = 0;
+ dateOriginalCheck = 0;
+ dateDigitalizedCheck = 0;
+ dateCreatedSubSecCheck = 0;
+ dateOriginalSubSecCheck = 0;
+ dateDigitalizedSubSecCheck = 0;
+ syncHOSTDateCheck = 0;
+ syncIPTCDateCheck = 0;
+ }
+
+ QCheckBox *dateCreatedCheck;
+ QCheckBox *dateOriginalCheck;
+ QCheckBox *dateDigitalizedCheck;
+ QCheckBox *dateCreatedSubSecCheck;
+ QCheckBox *dateOriginalSubSecCheck;
+ QCheckBox *dateDigitalizedSubSecCheck;
+ QCheckBox *syncHOSTDateCheck;
+ QCheckBox *syncIPTCDateCheck;
+
+ KIntSpinBox *dateCreatedSubSecEdit;
+ KIntSpinBox *dateOriginalSubSecEdit;
+ KIntSpinBox *dateDigitalizedSubSecEdit;
+
+ KDateTimeWidget *dateCreatedSel;
+ KDateTimeWidget *dateOriginalSel;
+ KDateTimeWidget *dateDigitalizedSel;
+};
+
+EXIFDateTime::EXIFDateTime(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new EXIFDateTimePriv;
+
+ QGridLayout* grid = new QGridLayout(parent, 9, 3, KDialog::spacingHint());
+
+ // --------------------------------------------------------
+
+ d->dateCreatedCheck = new QCheckBox(i18n("Creation date and time"), parent);
+ d->dateCreatedSubSecCheck = new QCheckBox(i18n("Creation sub-second"), parent);
+ d->dateCreatedSel = new KDateTimeWidget(parent);
+ d->dateCreatedSubSecEdit = new KIntSpinBox(0, 999, 1, 0, 10, parent);
+ d->dateCreatedSel->setDateTime(QDateTime::currentDateTime());
+ d->syncHOSTDateCheck = new QCheckBox(i18n("Sync creation date entered through %1")
+ .arg(KApplication::kApplication()->aboutData()->appName()),
+ parent);
+ d->syncIPTCDateCheck = new QCheckBox(i18n("Sync IPTC creation date"), parent);
+ KSeparator *line = new KSeparator(Horizontal, parent);
+
+ grid->addMultiCellWidget(d->dateCreatedCheck, 0, 0, 0, 0);
+ grid->addMultiCellWidget(d->dateCreatedSubSecCheck, 0, 0, 1, 2);
+ grid->addMultiCellWidget(d->dateCreatedSel, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->dateCreatedSubSecEdit, 1, 1, 1, 1);
+ grid->addMultiCellWidget(d->syncHOSTDateCheck, 2, 2, 0, 3);
+ grid->addMultiCellWidget(d->syncIPTCDateCheck, 3, 3, 0, 3);
+ grid->addMultiCellWidget(line, 4, 4, 0, 3);
+
+ QWhatsThis::add(d->dateCreatedSel, i18n("<p>Set here the date and time of image creation. "
+ "In this standard it is the date and time the file was changed."));
+ QWhatsThis::add(d->dateCreatedSubSecEdit, i18n("<p>Set here the fractions of seconds for the date "
+ "and time of image creation."));
+
+ // --------------------------------------------------------
+
+ d->dateOriginalCheck = new QCheckBox(i18n("Original date and time"), parent);
+ d->dateOriginalSubSecCheck = new QCheckBox(i18n("Original sub-second"), parent);
+ d->dateOriginalSel = new KDateTimeWidget(parent);
+ d->dateOriginalSubSecEdit = new KIntSpinBox(0, 999, 1, 0, 10, parent);
+ d->dateOriginalSel->setDateTime(QDateTime::currentDateTime());
+ grid->addMultiCellWidget(d->dateOriginalCheck, 5, 5, 0, 0);
+ grid->addMultiCellWidget(d->dateOriginalSubSecCheck, 5, 5, 1, 2);
+ grid->addMultiCellWidget(d->dateOriginalSel, 6, 6, 0, 0);
+ grid->addMultiCellWidget(d->dateOriginalSubSecEdit, 6, 6, 1, 1);
+ QWhatsThis::add(d->dateOriginalSel, i18n("<p>Set here the date and time when the original image "
+ "data was generated. For a digital still camera the date and "
+ "time the picture was taken are recorded."));
+ QWhatsThis::add(d->dateOriginalSubSecEdit, i18n("<p>Set here the fractions of seconds for the date "
+ "and time when the original image data was generated."));
+
+ // --------------------------------------------------------
+
+ d->dateDigitalizedCheck = new QCheckBox(i18n("Digitization date and time"), parent);
+ d->dateDigitalizedSubSecCheck = new QCheckBox(i18n("Digitization sub-second"), parent);
+ d->dateDigitalizedSel = new KDateTimeWidget(parent);
+ d->dateDigitalizedSubSecEdit = new KIntSpinBox(0, 999, 1, 0, 10, parent);
+ d->dateDigitalizedSel->setDateTime(QDateTime::currentDateTime());
+ grid->addMultiCellWidget(d->dateDigitalizedCheck, 7, 7, 0, 0);
+ grid->addMultiCellWidget(d->dateDigitalizedSubSecCheck, 7, 7, 1, 2);
+ grid->addMultiCellWidget(d->dateDigitalizedSel, 8, 8, 0, 0);
+ grid->addMultiCellWidget(d->dateDigitalizedSubSecEdit, 8, 8, 1, 1);
+ QWhatsThis::add(d->dateDigitalizedSel, i18n("<p>Set here the date and time when the image was "
+ "stored as digital data. If, for example, an image was "
+ "captured by a digital still camera and at the same "
+ "time the file was recorded, then Original and Digitization "
+ "date and time will have the same contents."));
+ QWhatsThis::add(d->dateDigitalizedSubSecEdit, i18n("<p>Set here the fractions of seconds for the date "
+ "and time when the image was stored as digital data."));
+
+ grid->setColStretch(3, 10);
+ grid->setRowStretch(9, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->dateCreatedCheck, SIGNAL(toggled(bool)),
+ d->dateCreatedSel, SLOT(setEnabled(bool)));
+
+ connect(d->dateOriginalCheck, SIGNAL(toggled(bool)),
+ d->dateOriginalSel, SLOT(setEnabled(bool)));
+
+ connect(d->dateDigitalizedCheck, SIGNAL(toggled(bool)),
+ d->dateDigitalizedSel, SLOT(setEnabled(bool)));
+
+ connect(d->dateCreatedSubSecCheck, SIGNAL(toggled(bool)),
+ d->dateCreatedSubSecEdit, SLOT(setEnabled(bool)));
+
+ connect(d->dateOriginalSubSecCheck, SIGNAL(toggled(bool)),
+ d->dateOriginalSubSecEdit, SLOT(setEnabled(bool)));
+
+ connect(d->dateDigitalizedSubSecCheck, SIGNAL(toggled(bool)),
+ d->dateDigitalizedSubSecEdit, SLOT(setEnabled(bool)));
+
+ connect(d->dateCreatedCheck, SIGNAL(toggled(bool)),
+ d->syncHOSTDateCheck, SLOT(setEnabled(bool)));
+
+ connect(d->dateCreatedCheck, SIGNAL(toggled(bool)),
+ d->syncIPTCDateCheck, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->dateCreatedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateOriginalCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateDigitalizedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateCreatedSubSecCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateOriginalSubSecCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateDigitalizedSubSecCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->dateCreatedSubSecEdit, SIGNAL(valueChanged(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateOriginalSubSecEdit, SIGNAL(valueChanged(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateDigitalizedSubSecEdit, SIGNAL(valueChanged(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateCreatedSel, SIGNAL(valueChanged (const QDateTime &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateOriginalSel, SIGNAL(valueChanged (const QDateTime &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateDigitalizedSel, SIGNAL(valueChanged (const QDateTime &)),
+ this, SIGNAL(signalModified()));
+}
+
+EXIFDateTime::~EXIFDateTime()
+{
+ delete d;
+}
+
+bool EXIFDateTime::syncHOSTDateIsChecked()
+{
+ return d->syncHOSTDateCheck->isChecked();
+}
+
+bool EXIFDateTime::syncIPTCDateIsChecked()
+{
+ return d->syncIPTCDateCheck->isChecked();
+}
+
+void EXIFDateTime::setCheckedSyncHOSTDate(bool c)
+{
+ d->syncHOSTDateCheck->setChecked(c);
+}
+
+void EXIFDateTime::setCheckedSyncIPTCDate(bool c)
+{
+ d->syncIPTCDateCheck->setChecked(c);
+}
+
+QDateTime EXIFDateTime::getEXIFCreationDate()
+{
+ return d->dateCreatedSel->dateTime();
+}
+
+void EXIFDateTime::readMetadata(QByteArray& exifData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+
+ QDateTime datetime;
+ QString datetimeStr, data;
+
+ d->dateCreatedSel->setDateTime(QDateTime::currentDateTime());
+ d->dateCreatedCheck->setChecked(false);
+ datetimeStr = exiv2Iface.getExifTagString("Exif.Image.DateTime", false);
+ if (!datetimeStr.isEmpty())
+ {
+ datetime = QDateTime::fromString(datetimeStr, Qt::ISODate);
+ if (datetime.isValid())
+ {
+ d->dateCreatedSel->setDateTime(datetime);
+ d->dateCreatedCheck->setChecked(true);
+ }
+ }
+ d->dateCreatedSel->setEnabled(d->dateCreatedCheck->isChecked());
+ d->syncHOSTDateCheck->setEnabled(d->dateCreatedCheck->isChecked());
+ d->syncIPTCDateCheck->setEnabled(d->dateCreatedCheck->isChecked());
+
+ d->dateCreatedSubSecEdit->setValue(0);
+ d->dateCreatedSubSecCheck->setChecked(false);
+ data = exiv2Iface.getExifTagString("Exif.Photo.SubSecTime", false);
+ if (!data.isNull())
+ {
+ bool ok = false;
+ int subsec = data.toInt(&ok);
+ if (ok)
+ {
+ d->dateCreatedSubSecEdit->setValue(subsec);
+ d->dateCreatedSubSecCheck->setChecked(true);
+ }
+ }
+ d->dateCreatedSubSecEdit->setEnabled(d->dateCreatedSubSecCheck->isChecked());
+
+ d->dateOriginalSel->setDateTime(QDateTime::currentDateTime());
+ d->dateOriginalCheck->setChecked(false);
+ datetimeStr = exiv2Iface.getExifTagString("Exif.Photo.DateTimeOriginal", false);
+ if (!datetimeStr.isEmpty())
+ {
+ datetime = QDateTime::fromString(datetimeStr, Qt::ISODate);
+ if (datetime.isValid())
+ {
+ d->dateOriginalSel->setDateTime(datetime);
+ d->dateOriginalCheck->setChecked(true);
+ }
+ }
+ d->dateOriginalSel->setEnabled(d->dateOriginalCheck->isChecked());
+
+ d->dateOriginalSubSecEdit->setValue(0);
+ d->dateOriginalSubSecCheck->setChecked(false);
+ data = exiv2Iface.getExifTagString("Exif.Photo.SubSecTimeOriginal", false);
+ if (!data.isNull())
+ {
+ bool ok = false;
+ int subsec = data.toInt(&ok);
+ if (ok)
+ {
+ d->dateOriginalSubSecEdit->setValue(subsec);
+ d->dateOriginalSubSecCheck->setChecked(true);
+ }
+ }
+ d->dateOriginalSubSecEdit->setEnabled(d->dateOriginalSubSecCheck->isChecked());
+
+ d->dateDigitalizedSel->setDateTime(QDateTime::currentDateTime());
+ d->dateDigitalizedCheck->setChecked(false);
+ datetimeStr = exiv2Iface.getExifTagString("Exif.Photo.DateTimeDigitized", false);
+ if (!datetimeStr.isEmpty())
+ {
+ datetime = QDateTime::fromString(datetimeStr, Qt::ISODate);
+ if (datetime.isValid())
+ {
+ d->dateDigitalizedSel->setDateTime(datetime);
+ d->dateDigitalizedCheck->setChecked(true);
+ }
+ }
+ d->dateDigitalizedSel->setEnabled(d->dateDigitalizedCheck->isChecked());
+
+ d->dateDigitalizedSubSecEdit->setValue(0);
+ d->dateDigitalizedSubSecCheck->setChecked(false);
+ data = exiv2Iface.getExifTagString("Exif.Photo.SubSecTimeDigitized", false);
+ if (!data.isNull())
+ {
+ bool ok = false;
+ int subsec = data.toInt(&ok);
+ if (ok)
+ {
+ d->dateDigitalizedSubSecEdit->setValue(subsec);
+ d->dateDigitalizedSubSecCheck->setChecked(true);
+ }
+ }
+ d->dateDigitalizedSubSecEdit->setEnabled(d->dateDigitalizedSubSecCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void EXIFDateTime::applyMetadata(QByteArray& exifData, QByteArray& iptcData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ exiv2Iface.setIptc(iptcData);
+
+ if (d->dateCreatedCheck->isChecked())
+ {
+ exiv2Iface.setExifTagString("Exif.Image.DateTime",
+ d->dateCreatedSel->dateTime().toString(QString("yyyy:MM:dd hh:mm:ss")).ascii());
+
+ if (syncIPTCDateIsChecked())
+ {
+ exiv2Iface.setIptcTagString("Iptc.Application2.DateCreated",
+ d->dateCreatedSel->dateTime().date().toString(Qt::ISODate));
+ exiv2Iface.setIptcTagString("Iptc.Application2.TimeCreated",
+ d->dateCreatedSel->dateTime().time().toString(Qt::ISODate));
+ }
+ }
+ else
+ exiv2Iface.removeExifTag("Exif.Image.DateTime");
+
+ if (d->dateCreatedSubSecCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Photo.SubSecTime",
+ QString::number(d->dateCreatedSubSecEdit->value()).ascii());
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.SubSecTime");
+
+ if (d->dateOriginalCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Photo.DateTimeOriginal",
+ d->dateOriginalSel->dateTime().toString(QString("yyyy:MM:dd hh:mm:ss")).ascii());
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.DateTimeOriginal");
+
+ if (d->dateOriginalSubSecCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Photo.SubSecTimeOriginal",
+ QString::number(d->dateOriginalSubSecEdit->value()).ascii());
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.SubSecTimeOriginal");
+
+ if (d->dateDigitalizedCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Photo.DateTimeDigitized",
+ d->dateDigitalizedSel->dateTime().toString(QString("yyyy:MM:dd hh:mm:ss")).ascii());
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.DateTimeDigitized");
+
+ if (d->dateDigitalizedSubSecCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Photo.SubSecTimeDigitized",
+ QString::number(d->dateDigitalizedSubSecEdit->value()).ascii());
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.SubSecTimeDigitized");
+
+ exifData = exiv2Iface.getExif();
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/exifdatetime.h b/kipi-plugins/metadataedit/exifdatetime.h
new file mode 100644
index 0000000..254b007
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifdatetime.h
@@ -0,0 +1,68 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF date and time settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 EXIF_DATETIME_H
+#define EXIF_DATETIME_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+#include <qdatetime.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFDateTimePriv;
+
+class EXIFDateTime : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ EXIFDateTime(QWidget* parent);
+ ~EXIFDateTime();
+
+ void applyMetadata(QByteArray& exifData, QByteArray& iptcData);
+ void readMetadata(QByteArray& exifData);
+
+ bool syncHOSTDateIsChecked();
+ bool syncIPTCDateIsChecked();
+
+ void setCheckedSyncHOSTDate(bool c);
+ void setCheckedSyncIPTCDate(bool c);
+
+ QDateTime getEXIFCreationDate();
+
+signals:
+
+ void signalModified();
+
+private:
+
+ EXIFDateTimePriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // EXIF_DATETIME_H
diff --git a/kipi-plugins/metadataedit/exifdevice.cpp b/kipi-plugins/metadataedit/exifdevice.cpp
new file mode 100644
index 0000000..fde3a1b
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifdevice.cpp
@@ -0,0 +1,772 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF device settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qcombobox.h>
+#include <qvalidator.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <knuminput.h>
+#include <klineedit.h>
+#include <kseparator.h>
+#include <kactivelabel.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "metadatacheckbox.h"
+#include "exifdevice.h"
+#include "exifdevice.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFDevicePriv
+{
+public:
+
+ EXIFDevicePriv()
+ {
+ makeCheck = 0;
+ modelCheck = 0;
+ deviceTypeCheck = 0;
+ exposureTimeCheck = 0;
+ exposureProgramCheck = 0;
+ exposureModeCheck = 0;
+ exposureBiasCheck = 0;
+ ISOSpeedCheck = 0;
+ meteringModeCheck = 0;
+ sensingMethodCheck = 0;
+ sceneTypeCheck = 0;
+ subjectDistanceTypeCheck = 0;
+ exposureProgramCB = 0;
+ exposureModeCB = 0;
+ ISOSpeedCB = 0;
+ meteringModeCB = 0;
+ sensingMethodCB = 0;
+ sceneTypeCB = 0;
+ subjectDistanceTypeCB = 0;
+ exposureTimeNumEdit = 0;
+ exposureTimeDenEdit = 0;
+ exposureBiasEdit = 0;
+ makeEdit = 0;
+ modelEdit = 0;
+ }
+
+ QCheckBox *makeCheck;
+ QCheckBox *modelCheck;
+ QCheckBox *exposureTimeCheck;
+ QCheckBox *exposureBiasCheck;
+
+ QComboBox *deviceTypeCB;
+ QComboBox *exposureProgramCB;
+ QComboBox *exposureModeCB;
+ QComboBox *ISOSpeedCB;
+ QComboBox *meteringModeCB;
+ QComboBox *sensingMethodCB;
+ QComboBox *sceneTypeCB;
+ QComboBox *subjectDistanceTypeCB;
+
+ KLineEdit *makeEdit;
+ KLineEdit *modelEdit;
+
+ KIntSpinBox *exposureTimeNumEdit;
+ KIntSpinBox *exposureTimeDenEdit;
+
+ KDoubleSpinBox *exposureBiasEdit;
+
+ MetadataCheckBox *deviceTypeCheck;
+ MetadataCheckBox *exposureProgramCheck;
+ MetadataCheckBox *exposureModeCheck;
+ MetadataCheckBox *meteringModeCheck;
+ MetadataCheckBox *ISOSpeedCheck;
+ MetadataCheckBox *sensingMethodCheck;
+ MetadataCheckBox *sceneTypeCheck;
+ MetadataCheckBox *subjectDistanceTypeCheck;
+};
+
+EXIFDevice::EXIFDevice(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new EXIFDevicePriv;
+
+ QGridLayout* grid = new QGridLayout(parent, 16, 5, KDialog::spacingHint());
+
+ // EXIF only accept printable Ascii char.
+ QRegExp asciiRx("[\x20-\x7F]+$");
+ QValidator *asciiValidator = new QRegExpValidator(asciiRx, this);
+
+ // --------------------------------------------------------
+
+ d->makeCheck = new QCheckBox(i18n("Device manufacturer (*):"), parent);
+ d->makeEdit = new KLineEdit(parent);
+ d->makeEdit->setValidator(asciiValidator);
+ grid->addMultiCellWidget(d->makeCheck, 0, 0, 0, 0);
+ grid->addMultiCellWidget(d->makeEdit, 0, 0, 2, 5);
+ QWhatsThis::add(d->makeEdit, i18n("<p>Set here the manufacturer of image input equipment used to "
+ "take the picture. This field is limited to ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->modelCheck = new QCheckBox(i18n("Device model (*):"), parent);
+ d->modelEdit = new KLineEdit(parent);
+ d->modelEdit->setValidator(asciiValidator);
+ grid->addMultiCellWidget(d->modelCheck, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->modelEdit, 1, 1, 2, 5);
+ QWhatsThis::add(d->modelEdit, i18n("<p>Set here the model of image input equipment used to "
+ "take the picture. This field is limited to ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->deviceTypeCheck = new MetadataCheckBox(i18n("Device type:"), parent);
+ d->deviceTypeCB = new QComboBox(false, parent);
+ d->deviceTypeCB->insertItem(i18n("Film scanner"), 0);
+ d->deviceTypeCB->insertItem(i18n("Reflection print scanner"), 1);
+ d->deviceTypeCB->insertItem(i18n("Digital still camera"), 2);
+ grid->addMultiCellWidget(d->deviceTypeCheck, 2, 2, 0, 0);
+ grid->addMultiCellWidget(d->deviceTypeCB, 2, 2, 2, 5);
+ QWhatsThis::add(d->deviceTypeCB, i18n("<p>Select here the image input equipment type used to "
+ "take the picture."));
+
+ KActiveLabel *warning = new KActiveLabel(i18n("<b>Warning: EXIF <b><a href="
+ "'http://en.wikipedia.org/wiki/Exchangeable_image_file_format#MakerNote_Information'>"
+ "Makernotes</a></b> can be unreadable if you set "
+ "wrong device manufacturer/model description.</b>"), parent);
+
+ KSeparator *line = new KSeparator(Horizontal, parent);
+ grid->addMultiCellWidget(warning, 3, 3, 0, 5);
+ grid->addMultiCellWidget(line, 4, 4, 0, 5);
+
+ // --------------------------------------------------------
+
+ d->exposureTimeCheck = new QCheckBox(i18n("Exposure time (seconds):"), parent);
+ d->exposureTimeNumEdit = new KIntSpinBox(1, 100000, 1, 1, 10, parent);
+ d->exposureTimeDenEdit = new KIntSpinBox(1, 100000, 1, 1, 10, parent);
+ QLabel *exposureLabel = new QLabel("/", parent);
+ exposureLabel->setAlignment (Qt::AlignRight|Qt::AlignVCenter);
+ grid->addMultiCellWidget(d->exposureTimeCheck, 5, 5, 0, 0);
+ grid->addMultiCellWidget(d->exposureTimeNumEdit, 5, 5, 2, 2);
+ grid->addMultiCellWidget(exposureLabel, 5, 5, 3, 3);
+ grid->addMultiCellWidget(d->exposureTimeDenEdit, 5, 5, 4, 4);
+ QWhatsThis::add(d->exposureTimeCheck, i18n("<p>Set on this option to set the exposure time "
+ "of picture, given in seconds."));
+
+ // --------------------------------------------------------
+
+ d->exposureProgramCheck = new MetadataCheckBox(i18n("Exposure program:"), parent);
+ d->exposureProgramCB = new QComboBox(false, parent);
+ d->exposureProgramCB->insertItem(i18n("Not defined"), 0);
+ d->exposureProgramCB->insertItem(i18n("Manual"), 1);
+ d->exposureProgramCB->insertItem(i18n("Auto"), 2);
+ d->exposureProgramCB->insertItem(i18n("Aperture priority"), 3);
+ d->exposureProgramCB->insertItem(i18n("Shutter priority"), 4);
+ d->exposureProgramCB->insertItem(i18n("Creative program"), 5);
+ d->exposureProgramCB->insertItem(i18n("Action program"), 6);
+ d->exposureProgramCB->insertItem(i18n("Portrait mode"), 7);
+ d->exposureProgramCB->insertItem(i18n("Landscape mode"), 8);
+ grid->addMultiCellWidget(d->exposureProgramCheck, 6, 6, 0, 0);
+ grid->addMultiCellWidget(d->exposureProgramCB, 6, 6, 2, 5);
+ QWhatsThis::add(d->exposureProgramCB, i18n("<p>Select here the program used by the camera "
+ "to set exposure when the picture have been taken."));
+
+ // --------------------------------------------------------
+
+ d->exposureModeCheck = new MetadataCheckBox(i18n("Exposure mode:"), parent);
+ d->exposureModeCB = new QComboBox(false, parent);
+ d->exposureModeCB->insertItem(i18n("Auto"), 0);
+ d->exposureModeCB->insertItem(i18n("Manual"), 1);
+ d->exposureModeCB->insertItem(i18n("Auto bracket"), 2);
+ grid->addMultiCellWidget(d->exposureModeCheck, 7, 7, 0, 0);
+ grid->addMultiCellWidget(d->exposureModeCB, 7, 7, 2, 5);
+ QWhatsThis::add(d->exposureModeCB, i18n("<p>Select here the mode used by the camera "
+ "to set exposure when the picture have been shot. "
+ "In auto-bracketing mode, the camera shoots a "
+ "series of frames of the same scene at different "
+ "exposure settings."));
+
+ // --------------------------------------------------------
+
+ d->exposureBiasCheck = new QCheckBox(i18n("Exposure bias (APEX):"), parent);
+ d->exposureBiasEdit = new KDoubleSpinBox(-99.99, 99.99, 0.1, 0.0, 2, parent);
+ grid->addMultiCellWidget(d->exposureBiasCheck, 8, 8, 0, 0);
+ grid->addMultiCellWidget(d->exposureBiasEdit, 8, 8, 2, 2);
+ QWhatsThis::add(d->exposureBiasEdit, i18n("<p>Set here the exposure bias value in APEX unit "
+ "used by camera to take the picture."));
+
+ KSeparator *line2 = new KSeparator(Horizontal, parent);
+ grid->addMultiCellWidget(line2, 9, 9, 0, 5);
+
+ // --------------------------------------------------------
+
+ d->meteringModeCheck = new MetadataCheckBox(i18n("Metering mode:"), parent);
+ d->meteringModeCB = new QComboBox(false, parent);
+ d->meteringModeCB->insertItem(i18n("Unknown"), 0);
+ d->meteringModeCB->insertItem(i18n("Average"), 1);
+ d->meteringModeCB->insertItem(i18n("Center weighted average"), 2);
+ d->meteringModeCB->insertItem(i18n("Spot"), 3);
+ d->meteringModeCB->insertItem(i18n("Multi-spot"), 4);
+ d->meteringModeCB->insertItem(i18n("Multi-segment"), 5);
+ d->meteringModeCB->insertItem(i18n("Partial"), 6);
+ d->meteringModeCB->insertItem(i18n("Other"), 7);
+ grid->addMultiCellWidget(d->meteringModeCheck, 10, 10, 0, 0);
+ grid->addMultiCellWidget(d->meteringModeCB, 10, 10, 2, 5);
+ QWhatsThis::add(d->meteringModeCB, i18n("<p>Select here the metering mode used by the camera "
+ "to set exposure when the picture have been shot."));
+
+ // --------------------------------------------------------
+
+ d->ISOSpeedCheck = new MetadataCheckBox(i18n("Sensitivity (ISO):"), parent);
+ d->ISOSpeedCB = new QComboBox(false, parent);
+ d->ISOSpeedCB->insertItem("10", 0);
+ d->ISOSpeedCB->insertItem("12", 1);
+ d->ISOSpeedCB->insertItem("16", 2);
+ d->ISOSpeedCB->insertItem("20", 3);
+ d->ISOSpeedCB->insertItem("25", 4);
+ d->ISOSpeedCB->insertItem("32", 5);
+ d->ISOSpeedCB->insertItem("40", 6);
+ d->ISOSpeedCB->insertItem("50", 7);
+ d->ISOSpeedCB->insertItem("64", 8);
+ d->ISOSpeedCB->insertItem("80", 9);
+ d->ISOSpeedCB->insertItem("100", 10);
+ d->ISOSpeedCB->insertItem("125", 11);
+ d->ISOSpeedCB->insertItem("160", 12);
+ d->ISOSpeedCB->insertItem("200", 13);
+ d->ISOSpeedCB->insertItem("250", 14);
+ d->ISOSpeedCB->insertItem("320", 15);
+ d->ISOSpeedCB->insertItem("400", 16);
+ d->ISOSpeedCB->insertItem("500", 17);
+ d->ISOSpeedCB->insertItem("640", 18);
+ d->ISOSpeedCB->insertItem("800", 19);
+ d->ISOSpeedCB->insertItem("1000", 20);
+ d->ISOSpeedCB->insertItem("1250", 21);
+ d->ISOSpeedCB->insertItem("1600", 22);
+ d->ISOSpeedCB->insertItem("2000", 23);
+ d->ISOSpeedCB->insertItem("2500", 24);
+ d->ISOSpeedCB->insertItem("3200", 25);
+ d->ISOSpeedCB->insertItem("4000", 26);
+ d->ISOSpeedCB->insertItem("5000", 27);
+ d->ISOSpeedCB->insertItem("6400", 28);
+ d->ISOSpeedCB->insertItem("8000", 29);
+ d->ISOSpeedCB->insertItem("10000", 30);
+ d->ISOSpeedCB->insertItem("12500", 31);
+ d->ISOSpeedCB->insertItem("16000", 32);
+ d->ISOSpeedCB->insertItem("20000", 33);
+ d->ISOSpeedCB->insertItem("25000", 34);
+ d->ISOSpeedCB->insertItem("32000", 35);
+ grid->addMultiCellWidget(d->ISOSpeedCheck, 11, 11, 0, 0);
+ grid->addMultiCellWidget(d->ISOSpeedCB, 11, 11, 2, 5);
+ QWhatsThis::add(d->ISOSpeedCB, i18n("<p>Select here the ISO Speed of the camera "
+ "witch have taken the picture."));
+
+ // --------------------------------------------------------
+
+ d->sensingMethodCheck = new MetadataCheckBox(i18n("Sensing method:"), parent);
+ d->sensingMethodCB = new QComboBox(false, parent);
+ d->sensingMethodCB->insertItem(i18n("Not defined"), 0);
+ d->sensingMethodCB->insertItem(i18n("One-chip color area"), 1);
+ d->sensingMethodCB->insertItem(i18n("Two-chip color area"), 2);
+ d->sensingMethodCB->insertItem(i18n("Three-chip color area"), 3);
+ d->sensingMethodCB->insertItem(i18n("Color sequential area"), 4);
+ d->sensingMethodCB->insertItem(i18n("Trilinear sensor"), 5);
+ d->sensingMethodCB->insertItem(i18n("Color sequential linear"), 6);
+ grid->addMultiCellWidget(d->sensingMethodCheck, 12, 12, 0, 0);
+ grid->addMultiCellWidget(d->sensingMethodCB, 12, 12, 2, 5);
+ QWhatsThis::add(d->sensingMethodCB, i18n("<p>Select here the image sensor type used by the camera "
+ "to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->sceneTypeCheck = new MetadataCheckBox(i18n("Scene capture type:"), parent);
+ d->sceneTypeCB = new QComboBox(false, parent);
+ d->sceneTypeCB->insertItem(i18n("Standard"), 0);
+ d->sceneTypeCB->insertItem(i18n("Landscape"), 1);
+ d->sceneTypeCB->insertItem(i18n("Portrait"), 2);
+ d->sceneTypeCB->insertItem(i18n("Night scene"), 3);
+ grid->addMultiCellWidget(d->sceneTypeCheck, 13, 13, 0, 0);
+ grid->addMultiCellWidget(d->sceneTypeCB, 13, 13, 2, 5);
+ QWhatsThis::add(d->sceneTypeCB, i18n("<p>Select here the type of scene used by the camera "
+ "to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->subjectDistanceTypeCheck = new MetadataCheckBox(i18n("Subject distance type:"), parent);
+ d->subjectDistanceTypeCB = new QComboBox(false, parent);
+ d->subjectDistanceTypeCB->insertItem(i18n("Unknow"), 0);
+ d->subjectDistanceTypeCB->insertItem(i18n("Macro"), 1);
+ d->subjectDistanceTypeCB->insertItem(i18n("Close view"), 2);
+ d->subjectDistanceTypeCB->insertItem(i18n("Distant view"), 3);
+ grid->addMultiCellWidget(d->subjectDistanceTypeCheck, 14, 14, 0, 0);
+ grid->addMultiCellWidget(d->subjectDistanceTypeCB, 14, 14, 2, 5);
+ QWhatsThis::add(d->subjectDistanceTypeCB, i18n("<p>Select here the type of distance between "
+ "the subject and the image input equipment."));
+
+ // --------------------------------------------------------
+
+ KActiveLabel *note = new KActiveLabel(i18n("<b>Note: "
+ "<b><a href='http://en.wikipedia.org/wiki/EXIF'>EXIF</a></b> "
+ "text tags marked by (*) only support printable "
+ "<b><a href='http://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
+ "characters set.</b>"), parent);
+
+ grid->addMultiCellWidget(note, 15, 15, 0, 5);
+ grid->setColStretch(1, 10);
+ grid->setColStretch(5, 10);
+ grid->setRowStretch(16, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->makeCheck, SIGNAL(toggled(bool)),
+ d->makeEdit, SLOT(setEnabled(bool)));
+
+ connect(d->modelCheck, SIGNAL(toggled(bool)),
+ d->modelEdit, SLOT(setEnabled(bool)));
+
+ connect(d->deviceTypeCheck, SIGNAL(toggled(bool)),
+ d->deviceTypeCB, SLOT(setEnabled(bool)));
+
+ connect(d->exposureTimeCheck, SIGNAL(toggled(bool)),
+ d->exposureTimeNumEdit, SLOT(setEnabled(bool)));
+
+ connect(d->exposureTimeCheck, SIGNAL(toggled(bool)),
+ d->exposureTimeDenEdit, SLOT(setEnabled(bool)));
+
+ connect(d->exposureProgramCheck, SIGNAL(toggled(bool)),
+ d->exposureProgramCB, SLOT(setEnabled(bool)));
+
+ connect(d->exposureModeCheck, SIGNAL(toggled(bool)),
+ d->exposureModeCB, SLOT(setEnabled(bool)));
+
+ connect(d->exposureBiasCheck, SIGNAL(toggled(bool)),
+ d->exposureBiasEdit, SLOT(setEnabled(bool)));
+
+ connect(d->meteringModeCheck, SIGNAL(toggled(bool)),
+ d->meteringModeCB, SLOT(setEnabled(bool)));
+
+ connect(d->ISOSpeedCheck, SIGNAL(toggled(bool)),
+ d->ISOSpeedCB, SLOT(setEnabled(bool)));
+
+ connect(d->sensingMethodCheck, SIGNAL(toggled(bool)),
+ d->sensingMethodCB, SLOT(setEnabled(bool)));
+
+ connect(d->sceneTypeCheck, SIGNAL(toggled(bool)),
+ d->sceneTypeCB, SLOT(setEnabled(bool)));
+
+ connect(d->subjectDistanceTypeCheck, SIGNAL(toggled(bool)),
+ d->subjectDistanceTypeCB, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->makeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->modelCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->exposureTimeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->exposureBiasCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->deviceTypeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->exposureProgramCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->exposureModeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->meteringModeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->ISOSpeedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sensingMethodCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sceneTypeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->subjectDistanceTypeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->deviceTypeCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->exposureProgramCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->exposureModeCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->ISOSpeedCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->meteringModeCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sensingMethodCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sceneTypeCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->subjectDistanceTypeCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->makeEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->modelEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->exposureTimeNumEdit, SIGNAL(valueChanged(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->exposureTimeDenEdit, SIGNAL(valueChanged(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->exposureBiasEdit, SIGNAL(valueChanged(double)),
+ this, SIGNAL(signalModified()));
+}
+
+EXIFDevice::~EXIFDevice()
+{
+ delete d;
+}
+
+void EXIFDevice::readMetadata(QByteArray& exifData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ long int num=1, den=1;
+ long val=0;
+ QString data;
+
+ d->makeEdit->clear();
+ d->makeCheck->setChecked(false);
+ data = exiv2Iface.getExifTagString("Exif.Image.Make", false);
+ if (!data.isNull())
+ {
+ d->makeEdit->setText(data);
+ d->makeCheck->setChecked(true);
+ }
+ d->makeEdit->setEnabled(d->makeCheck->isChecked());
+
+ d->modelEdit->clear();
+ d->modelCheck->setChecked(false);
+ data = exiv2Iface.getExifTagString("Exif.Image.Model", false);
+ if (!data.isNull())
+ {
+ d->modelEdit->setText(data);
+ d->modelCheck->setChecked(true);
+ }
+ d->modelEdit->setEnabled(d->modelCheck->isChecked());
+
+ d->deviceTypeCB->setCurrentItem(2); // DSC
+ d->deviceTypeCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.FileSource", val))
+ {
+ if (val>0 && val<4)
+ {
+ d->deviceTypeCB->setCurrentItem(val-1);
+ d->deviceTypeCheck->setChecked(true);
+ }
+ else
+ d->deviceTypeCheck->setValid(false);
+ }
+ d->deviceTypeCB->setEnabled(d->deviceTypeCheck->isChecked());
+
+ d->exposureTimeNumEdit->setValue(1);
+ d->exposureTimeDenEdit->setValue(1);
+ d->exposureTimeCheck->setChecked(false);
+ if (exiv2Iface.getExifTagRational("Exif.Photo.ExposureTime", num, den))
+ {
+ d->exposureTimeNumEdit->setValue(num);
+ d->exposureTimeDenEdit->setValue(den);
+ d->exposureTimeCheck->setChecked(true);
+ }
+ else if (exiv2Iface.getExifTagRational("Exif.Photo.ShutterSpeedValue", num, den))
+ {
+ double tmp = exp(log(2.0) * (double)(num)/(double)(den));
+ if (tmp > 1.0)
+ num = (long int)(tmp + 0.5);
+ else
+ den = (long int)(1.0/tmp + 0.5);
+
+ d->exposureTimeNumEdit->setValue(num);
+ d->exposureTimeDenEdit->setValue(den);
+ d->exposureTimeCheck->setChecked(true);
+ }
+ d->exposureTimeNumEdit->setEnabled(d->exposureTimeCheck->isChecked());
+ d->exposureTimeDenEdit->setEnabled(d->exposureTimeCheck->isChecked());
+
+ d->exposureProgramCB->setCurrentItem(0);
+ d->exposureProgramCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.ExposureProgram", val))
+ {
+ if (val>=0 && val <=8)
+ {
+ d->exposureProgramCB->setCurrentItem(val);
+ d->exposureProgramCheck->setChecked(true);
+ }
+ else
+ d->exposureProgramCheck->setValid(false);
+ }
+ d->exposureProgramCB->setEnabled(d->exposureProgramCheck->isChecked());
+
+ d->exposureModeCB->setCurrentItem(0);
+ d->exposureModeCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.ExposureMode", val))
+ {
+ if (val>=0 && val <=2)
+ {
+ d->exposureModeCB->setCurrentItem(val);
+ d->exposureModeCheck->setChecked(true);
+ }
+ else
+ d->exposureModeCheck->setValid(false);
+ }
+ d->exposureModeCB->setEnabled(d->exposureModeCheck->isChecked());
+
+ d->exposureBiasEdit->setValue(0.0);
+ d->exposureBiasCheck->setChecked(false);
+ if (exiv2Iface.getExifTagRational("Exif.Photo.ExposureBiasValue", num, den))
+ {
+ d->exposureBiasEdit->setValue((double)(num) / (double)(den));
+ d->exposureBiasCheck->setChecked(true);
+ }
+ d->exposureBiasEdit->setEnabled(d->exposureBiasCheck->isChecked());
+
+ d->meteringModeCB->setCurrentItem(0);
+ d->meteringModeCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.MeteringMode", val))
+ {
+ if ((val>= 0 && val <=6) || val == 255)
+ {
+ d->meteringModeCB->setCurrentItem(val == 255 ? 7 : val);
+ d->meteringModeCheck->setChecked(true);
+ }
+ else
+ d->meteringModeCheck->setValid(false);
+ }
+ d->meteringModeCB->setEnabled(d->meteringModeCheck->isChecked());
+
+ d->ISOSpeedCB->setCurrentItem(10); // 100 ISO
+ d->ISOSpeedCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.ISOSpeedRatings", val))
+ {
+ int item = -1;
+ for (int i = 0 ; i < d->ISOSpeedCB->count() ; i++)
+ if (d->ISOSpeedCB->text(i) == QString::number(val))
+ item = i;
+
+ if (item != -1)
+ {
+ d->ISOSpeedCB->setCurrentItem(item);
+ d->ISOSpeedCheck->setChecked(true);
+ }
+ else
+ d->ISOSpeedCheck->setValid(false);
+ }
+ else if (exiv2Iface.getExifTagRational("Exif.Photo.ExposureIndex", num, den))
+ {
+ val = num / den;
+ int item = -1;
+ for (int i = 0 ; i < d->ISOSpeedCB->count() ; i++)
+ if (d->ISOSpeedCB->text(i) == QString::number(val))
+ item = i;
+
+ if (item != -1)
+ {
+ d->ISOSpeedCB->setCurrentItem(item);
+ d->ISOSpeedCheck->setChecked(true);
+ }
+ else
+ d->ISOSpeedCheck->setValid(false);
+ }
+ d->ISOSpeedCB->setEnabled(d->ISOSpeedCheck->isChecked());
+
+ d->sensingMethodCB->setCurrentItem(0);
+ d->sensingMethodCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.SensingMethod", val))
+ {
+ if (val>=1 && val<=8 && val!=6)
+ {
+ d->sensingMethodCB->setCurrentItem(val > 6 ? val-2 : val-1);
+ d->sensingMethodCheck->setChecked(true);
+ }
+ else
+ d->sensingMethodCheck->setValid(false);
+ }
+ d->sensingMethodCB->setEnabled(d->sensingMethodCheck->isChecked());
+
+ d->sceneTypeCB->setCurrentItem(0);
+ d->sceneTypeCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.SceneCaptureType", val))
+ {
+ if (val>=0 && val<=3)
+ {
+ d->sceneTypeCB->setCurrentItem(val);
+ d->sceneTypeCheck->setChecked(true);
+ }
+ else
+ d->sceneTypeCheck->setValid(false);
+ }
+ d->sceneTypeCB->setEnabled(d->sceneTypeCheck->isChecked());
+
+ d->subjectDistanceTypeCB->setCurrentItem(0);
+ d->subjectDistanceTypeCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.SubjectDistanceRange", val))
+ {
+ if (val>=0 && val<=3)
+ {
+ d->subjectDistanceTypeCB->setCurrentItem(val);
+ d->subjectDistanceTypeCheck->setChecked(true);
+ }
+ else
+ d->subjectDistanceTypeCheck->setValid(false);
+ }
+ d->subjectDistanceTypeCB->setEnabled(d->subjectDistanceTypeCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void EXIFDevice::applyMetadata(QByteArray& exifData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ long int num=1, den=1;
+
+ if (d->makeCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Image.Make", d->makeEdit->text());
+ else
+ exiv2Iface.removeExifTag("Exif.Image.Make");
+
+ if (d->modelCheck->isChecked())
+ exiv2Iface.setExifTagString("Exif.Image.Model", d->modelEdit->text());
+ else
+ exiv2Iface.removeExifTag("Exif.Image.Model");
+
+ if (d->deviceTypeCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.FileSource", d->deviceTypeCB->currentItem()+1);
+ else if (d->deviceTypeCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.FileSource");
+
+ if (d->exposureTimeCheck->isChecked())
+ {
+ exiv2Iface.setExifTagRational("Exif.Photo.ExposureTime", d->exposureTimeNumEdit->value(),
+ d->exposureTimeDenEdit->value());
+
+ double exposureTime = (double)(d->exposureTimeNumEdit->value())/
+ (double)(d->exposureTimeDenEdit->value());
+ double shutterSpeed = (-1.0)*(log(exposureTime)/log(2.0));
+ exiv2Iface.convertToRational(shutterSpeed, &num, &den, 8);
+ exiv2Iface.setExifTagRational("Exif.Photo.ShutterSpeedValue", num, den);
+ }
+ else
+ {
+ exiv2Iface.removeExifTag("Exif.Photo.ExposureTime");
+ exiv2Iface.removeExifTag("Exif.Photo.ShutterSpeedValue");
+ }
+
+ if (d->exposureProgramCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.ExposureProgram", d->exposureProgramCB->currentItem());
+ else if (d->exposureProgramCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.ExposureProgram");
+
+ if (d->exposureModeCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.ExposureMode", d->exposureModeCB->currentItem());
+ else if (d->exposureModeCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.ExposureMode");
+
+ if (d->exposureBiasCheck->isChecked())
+ {
+ exiv2Iface.convertToRational(d->exposureBiasEdit->value(), &num, &den, 1);
+ exiv2Iface.setExifTagRational("Exif.Photo.ExposureBiasValue", num, den);
+ }
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.ExposureBiasValue");
+
+ if (d->meteringModeCheck->isChecked())
+ {
+ long met = d->meteringModeCB->currentItem();
+ exiv2Iface.setExifTagLong("Exif.Photo.MeteringMode", met > 6 ? 255 : met);
+ }
+ else if (d->meteringModeCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.MeteringMode");
+
+ if (d->ISOSpeedCheck->isChecked())
+ {
+ exiv2Iface.setExifTagLong("Exif.Photo.ISOSpeedRatings", d->ISOSpeedCB->currentText().toLong());
+
+ exiv2Iface.convertToRational(d->ISOSpeedCB->currentText().toDouble(), &num, &den, 1);
+ exiv2Iface.setExifTagRational("Exif.Photo.ExposureIndex", num, den);
+ }
+ else if (d->ISOSpeedCheck->isValid())
+ {
+ exiv2Iface.removeExifTag("Exif.Photo.ISOSpeedRatings");
+ exiv2Iface.removeExifTag("Exif.Photo.ExposureIndex");
+ }
+
+ if (d->sensingMethodCheck->isChecked())
+ {
+ long sem = d->sensingMethodCB->currentItem();
+ exiv2Iface.setExifTagLong("Exif.Photo.SensingMethod", sem > 4 ? sem+2 : sem+1);
+ }
+ else if (d->sensingMethodCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.SensingMethod");
+
+ if (d->sceneTypeCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.SceneCaptureType", d->sceneTypeCB->currentItem());
+ else if (d->sceneTypeCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.SceneCaptureType");
+
+ if (d->subjectDistanceTypeCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.SubjectDistanceRange", d->subjectDistanceTypeCB->currentItem());
+ else if (d->subjectDistanceTypeCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.SubjectDistanceRange");
+
+ exifData = exiv2Iface.getExif();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/exifdevice.h b/kipi-plugins/metadataedit/exifdevice.h
new file mode 100644
index 0000000..0e8b204
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifdevice.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF device settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 EXIF_DEVICE_H
+#define EXIF_DEVICE_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFDevicePriv;
+
+class EXIFDevice : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ EXIFDevice(QWidget* parent);
+ ~EXIFDevice();
+
+ void applyMetadata(QByteArray& exifData);
+ void readMetadata(QByteArray& exifData);
+
+signals:
+
+ void signalModified();
+
+private:
+
+ EXIFDevicePriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // EXIF_DEVICE_H
diff --git a/kipi-plugins/metadataedit/exifeditdialog.cpp b/kipi-plugins/metadataedit/exifeditdialog.cpp
new file mode 100644
index 0000000..9a86113
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifeditdialog.cpp
@@ -0,0 +1,384 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : a dialog to edit EXIF metadata
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qtimer.h>
+#include <qframe.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+
+// LibKIPI includes.
+
+#include <libkipi/imagecollection.h>
+#include <libkipi/plugin.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "exifcaption.h"
+#include "exifdatetime.h"
+#include "exiflens.h"
+#include "exifdevice.h"
+#include "exiflight.h"
+#include "exifadjust.h"
+#include "exifeditdialog.h"
+#include "exifeditdialog.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFEditDialogDialogPrivate
+{
+
+public:
+
+ EXIFEditDialogDialogPrivate()
+ {
+ modified = false;
+ isReadOnly = false;
+ interface = 0;
+
+ about = 0;
+
+ page_caption = 0;
+ page_datetime = 0;
+ page_lens = 0;
+ page_device = 0;
+ page_light = 0;
+ page_adjust = 0;
+
+ captionPage = 0;
+ datetimePage = 0;
+ lensPage = 0;
+ devicePage = 0;
+ lightPage = 0;
+ adjustPage = 0;
+ }
+
+ bool modified;
+ bool isReadOnly;
+
+ QByteArray exifData;
+ QByteArray iptcData;
+
+ QFrame *page_caption;
+ QFrame *page_datetime;
+ QFrame *page_lens;
+ QFrame *page_device;
+ QFrame *page_light;
+ QFrame *page_adjust;
+
+ KURL::List urls;
+
+ KURL::List::iterator currItem;
+
+ EXIFCaption *captionPage;
+ EXIFDateTime *datetimePage;
+ EXIFLens *lensPage;
+ EXIFDevice *devicePage;
+ EXIFLight *lightPage;
+ EXIFAdjust *adjustPage;
+
+ KIPI::Interface *interface;
+
+ KIPIPlugins::KPAboutData *about;
+};
+
+EXIFEditDialog::EXIFEditDialog(QWidget* parent, KURL::List urls, KIPI::Interface *iface)
+ : KDialogBase(IconList, QString::null,
+ urls.count() > 1 ? Help|User1|User2|Stretch|Ok|Apply|Close
+ : Help|Stretch|Ok|Apply|Close,
+ Ok, parent, 0, true, true,
+ KStdGuiItem::guiItem(KStdGuiItem::Forward),
+ KStdGuiItem::guiItem(KStdGuiItem::Back) )
+{
+ d = new EXIFEditDialogDialogPrivate;
+ d->urls = urls;
+ d->interface = iface;
+ d->currItem = d->urls.begin();
+
+ // ---------------------------------------------------------------
+
+ d->page_caption = addPage(i18n("Caption"), i18n("Caption Information"),
+ BarIcon("editclear", KIcon::SizeMedium));
+ d->captionPage = new EXIFCaption(d->page_caption);
+
+ d->page_datetime = addPage(i18n("Date & Time"), i18n("Date and Time"),
+ BarIcon("today", KIcon::SizeMedium));
+ d->datetimePage = new EXIFDateTime(d->page_datetime);
+
+ d->page_lens = addPage(i18n("Lens"), i18n("Lens Settings"),
+ BarIcon("camera", KIcon::SizeMedium));
+ d->lensPage = new EXIFLens(d->page_lens);
+
+ d->page_device = addPage(i18n("Device"), i18n("Capture Device Settings"),
+ BarIcon("scanner", KIcon::SizeMedium));
+ d->devicePage = new EXIFDevice(d->page_device);
+
+ d->page_light = addPage(i18n("Light"), i18n("Light Source Information"),
+ BarIcon("idea", KIcon::SizeMedium));
+ d->lightPage = new EXIFLight(d->page_light);
+
+ d->page_adjust = addPage(i18n("Adjustments"), i18n("Pictures Adjustments"),
+ BarIcon("blend", KIcon::SizeMedium));
+ d->adjustPage = new EXIFAdjust(d->page_adjust);
+
+ // ---------------------------------------------------------------
+ // About data and help button.
+
+ d->about = new KIPIPlugins::KPAboutData(I18N_NOOP("Edit Metadata"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Plugin to edit pictures metadata"),
+ "(c) 2006-2008, Gilles Caulier");
+
+ d->about->addAuthor("Gilles Caulier", I18N_NOOP("Author and Maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, d->about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"),
+ this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // ------------------------------------------------------------
+
+ connect(d->captionPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->datetimePage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->lensPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->devicePage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->lightPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->adjustPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ // ------------------------------------------------------------
+
+ readSettings();
+ slotItemChanged();
+}
+
+EXIFEditDialog::~EXIFEditDialog()
+{
+ delete d->about;
+ delete d;
+}
+
+void EXIFEditDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("metadataedit", "kipi-plugins");
+}
+
+void EXIFEditDialog::closeEvent(QCloseEvent *e)
+{
+ if (!e) return;
+ saveSettings();
+ e->accept();
+}
+
+void EXIFEditDialog::slotClose()
+{
+ saveSettings();
+ KDialogBase::slotClose();
+}
+
+void EXIFEditDialog::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Metadata Edit Settings");
+ showPage(config.readNumEntry("EXIF Edit Page", 0));
+ d->captionPage->setCheckedSyncJFIFComment(config.readBoolEntry("Sync JFIF Comment", true));
+ d->captionPage->setCheckedSyncHOSTComment(config.readBoolEntry("Sync Host Comment", true));
+ d->captionPage->setCheckedSyncIPTCCaption(config.readBoolEntry("Sync IPTC Caption", true));
+ d->datetimePage->setCheckedSyncHOSTDate(config.readBoolEntry("Sync Host Date", true));
+ d->datetimePage->setCheckedSyncIPTCDate(config.readBoolEntry("Sync IPTC Date", true));
+ resize(configDialogSize(config, QString("EXIF Edit Dialog")));
+}
+
+void EXIFEditDialog::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Metadata Edit Settings");
+ config.writeEntry("EXIF Edit Page", activePageIndex());
+ config.writeEntry("Sync JFIF Comment", d->captionPage->syncJFIFCommentIsChecked());
+ config.writeEntry("Sync Host Comment", d->captionPage->syncHOSTCommentIsChecked());
+ config.writeEntry("Sync IPTC Caption", d->captionPage->syncIPTCCaptionIsChecked());
+ config.writeEntry("Sync Host Date", d->datetimePage->syncHOSTDateIsChecked());
+ config.writeEntry("Sync IPTC Date", d->datetimePage->syncIPTCDateIsChecked());
+ saveDialogSize(config, QString("EXIF Edit Dialog"));
+ config.sync();
+}
+
+void EXIFEditDialog::slotItemChanged()
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.load((*d->currItem).path());
+ d->exifData = exiv2Iface.getExif();
+ d->iptcData = exiv2Iface.getIptc();
+ d->captionPage->readMetadata(d->exifData);
+ d->datetimePage->readMetadata(d->exifData);
+ d->lensPage->readMetadata(d->exifData);
+ d->devicePage->readMetadata(d->exifData);
+ d->lightPage->readMetadata(d->exifData);
+ d->adjustPage->readMetadata(d->exifData);
+
+ d->isReadOnly = KExiv2Iface::KExiv2::isReadOnly((*d->currItem).path());
+ d->page_caption->setEnabled(!d->isReadOnly);
+ d->page_datetime->setEnabled(!d->isReadOnly);
+ d->page_lens->setEnabled(!d->isReadOnly);
+ d->page_device->setEnabled(!d->isReadOnly);
+ d->page_light->setEnabled(!d->isReadOnly);
+ d->page_adjust->setEnabled(!d->isReadOnly);
+ enableButton(Apply, !d->isReadOnly);
+
+ setCaption(QString("%1 (%2/%3) - %4")
+ .arg((*d->currItem).filename())
+ .arg(d->urls.findIndex(*(d->currItem))+1)
+ .arg(d->urls.count())
+ .arg(i18n("Edit EXIF Metadata")) +
+ (d->isReadOnly ? QString(" - ") + i18n("(read only)") : QString::null));
+ enableButton(User1, *(d->currItem) != d->urls.last());
+ enableButton(User2, *(d->currItem) != d->urls.first());
+ enableButton(Apply, false);
+}
+
+void EXIFEditDialog::slotApply()
+{
+ if (d->modified && !d->isReadOnly)
+ {
+ KIPI::ImageInfo info = d->interface->info(*d->currItem);
+
+ if (d->captionPage->syncHOSTCommentIsChecked())
+ {
+ info.setDescription(d->captionPage->getEXIFUserComments());
+ }
+ d->captionPage->applyMetadata(d->exifData, d->iptcData);
+
+ if (d->datetimePage->syncHOSTDateIsChecked())
+ {
+ info.setTime(d->datetimePage->getEXIFCreationDate());
+ }
+ d->datetimePage->applyMetadata(d->exifData, d->iptcData);
+
+ d->lensPage->applyMetadata(d->exifData);
+ d->devicePage->applyMetadata(d->exifData);
+ d->lightPage->applyMetadata(d->exifData);
+ d->adjustPage->applyMetadata(d->exifData);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.load((*d->currItem).path());
+ exiv2Iface.setExif(d->exifData);
+ exiv2Iface.setIptc(d->iptcData);
+ exiv2Iface.save((*d->currItem).path());
+ d->modified = false;
+ }
+}
+
+void EXIFEditDialog::slotUser1()
+{
+ slotApply();
+ d->currItem++;
+ slotItemChanged();
+}
+
+void EXIFEditDialog::slotUser2()
+{
+ slotApply();
+ d->currItem--;
+ slotItemChanged();
+}
+
+void EXIFEditDialog::slotModified()
+{
+ if (!d->isReadOnly)
+ {
+ enableButton(Apply, true);
+ d->modified = true;
+ }
+}
+
+void EXIFEditDialog::slotOk()
+{
+ slotApply();
+ saveSettings();
+ accept();
+}
+
+bool EXIFEditDialog::eventFilter(QObject *, QEvent *e)
+{
+ if ( e->type() == QEvent::KeyPress )
+ {
+ QKeyEvent *k = (QKeyEvent *)e;
+
+ if (k->state() == Qt::ControlButton &&
+ (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return))
+ {
+ slotApply();
+
+ if (actionButton(User1)->isEnabled())
+ slotUser1();
+
+ return true;
+ }
+ else if (k->state() == Qt::ShiftButton &&
+ (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return))
+ {
+ slotApply();
+
+ if (actionButton(User2)->isEnabled())
+ slotUser2();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
+} // namespace KIPIMetadataEditPlugin
diff --git a/kipi-plugins/metadataedit/exifeditdialog.h b/kipi-plugins/metadataedit/exifeditdialog.h
new file mode 100644
index 0000000..f325a6e
--- /dev/null
+++ b/kipi-plugins/metadataedit/exifeditdialog.h
@@ -0,0 +1,88 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : a dialog to edit EXIF metadata
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 EXIFEDITDIALOG_H
+#define EXIFEDITDIALOG_H
+
+// Qt includes.
+
+#include <qcstring.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <kurl.h>
+
+namespace KIPI
+{
+ class Interface;
+}
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFEditDialogDialogPrivate;
+
+class EXIFEditDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ EXIFEditDialog(QWidget* parent, KURL::List urls, KIPI::Interface *iface);
+ ~EXIFEditDialog();
+
+public slots:
+
+ void slotModified();
+
+protected slots:
+
+ void slotOk();
+ void slotHelp();
+ void slotClose();
+
+protected:
+
+ void closeEvent(QCloseEvent *);
+ bool eventFilter(QObject *, QEvent *);
+
+private slots:
+
+ void slotItemChanged();
+ void slotApply();
+ void slotUser1();
+ void slotUser2();
+
+private:
+
+ void readSettings();
+ void saveSettings();
+
+private:
+
+ EXIFEditDialogDialogPrivate *d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif /* EXIFEDITDIALOG_H */
diff --git a/kipi-plugins/metadataedit/exiflens.cpp b/kipi-plugins/metadataedit/exiflens.cpp
new file mode 100644
index 0000000..ecd6a82
--- /dev/null
+++ b/kipi-plugins/metadataedit/exiflens.cpp
@@ -0,0 +1,425 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF lens settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qcombobox.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <knuminput.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "metadatacheckbox.h"
+#include "exiflens.h"
+#include "exiflens.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFLensPriv
+{
+public:
+
+ EXIFLensPriv()
+ {
+ apertureCheck = 0;
+ maxApertureCheck = 0;
+ focalLength35mmCheck = 0;
+ focalLengthCheck = 0;
+ digitalZoomRatioCheck = 0;
+ apertureCB = 0;
+ maxApertureCB = 0;
+ focalLength35mmEdit = 0;
+ focalLengthEdit = 0;
+ digitalZoomRatioEdit = 0;
+
+ apertureValues.append("f/1.0");
+ apertureValues.append("f/1.1");
+ apertureValues.append("f/1.2");
+ apertureValues.append("f/1.3");
+ apertureValues.append("f/1.4");
+ apertureValues.append("f/1.6");
+ apertureValues.append("f/1.8");
+ apertureValues.append("f/2.0");
+ apertureValues.append("f/2.2");
+ apertureValues.append("f/2.5");
+ apertureValues.append("f/2.8");
+ apertureValues.append("f/3.2");
+ apertureValues.append("f/3.5");
+ apertureValues.append("f/3.6");
+ apertureValues.append("f/4.0");
+ apertureValues.append("f/4.5");
+ apertureValues.append("f/4.9");
+ apertureValues.append("f/5.0");
+ apertureValues.append("f/5.6");
+ apertureValues.append("f/5.7");
+ apertureValues.append("f/6.3");
+ apertureValues.append("f/7.0");
+ apertureValues.append("f/7.1");
+ apertureValues.append("f/8.0");
+ apertureValues.append("f/9.0");
+ apertureValues.append("f/10.0");
+ apertureValues.append("f/10.1");
+ apertureValues.append("f/11.0");
+ apertureValues.append("f/11.3");
+ apertureValues.append("f/12.0");
+ apertureValues.append("f/12.7");
+ apertureValues.append("f/13.0");
+ apertureValues.append("f/14.0");
+ apertureValues.append("f/14.3");
+ apertureValues.append("f/16.0");
+ apertureValues.append("f/18.0");
+ apertureValues.append("f/20.0");
+ apertureValues.append("f/20.2");
+ apertureValues.append("f/22.0");
+ apertureValues.append("f/22.6");
+ apertureValues.append("f/25.0");
+ apertureValues.append("f/25.4");
+ apertureValues.append("f/28.5");
+ apertureValues.append("f/29.0");
+ apertureValues.append("f/32.0");
+ apertureValues.append("f/35.9");
+ apertureValues.append("f/36.0");
+ apertureValues.append("f/40.0");
+ apertureValues.append("f/40.3");
+ apertureValues.append("f/45.0");
+ apertureValues.append("f/45.3");
+ apertureValues.append("f/50.8");
+ apertureValues.append("f/51.0");
+ apertureValues.append("f/57.0");
+ apertureValues.append("f/64.0");
+ apertureValues.append("f/72.0");
+ apertureValues.append("f/81.0");
+ apertureValues.append("f/91.0");
+ }
+
+ QStringList apertureValues;
+
+ QCheckBox *focalLength35mmCheck;
+ QCheckBox *focalLengthCheck;
+ QCheckBox *digitalZoomRatioCheck;
+
+ QComboBox *apertureCB;
+ QComboBox *maxApertureCB;
+
+ KIntSpinBox *focalLength35mmEdit;
+
+ KDoubleSpinBox *focalLengthEdit;
+ KDoubleSpinBox *digitalZoomRatioEdit;
+
+ MetadataCheckBox *apertureCheck;
+ MetadataCheckBox *maxApertureCheck;
+};
+
+EXIFLens::EXIFLens(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new EXIFLensPriv;
+
+ QGridLayout* grid = new QGridLayout(parent, 5, 2, KDialog::spacingHint());
+
+ // --------------------------------------------------------
+
+ d->focalLengthCheck = new QCheckBox(i18n("Focal length (mm):"), parent);
+ d->focalLengthEdit = new KDoubleSpinBox(1.0, 10000.0, 1.0, 50.0, 1, parent);
+ grid->addMultiCellWidget(d->focalLengthCheck, 0, 0, 0, 0);
+ grid->addMultiCellWidget(d->focalLengthEdit, 0, 0, 2, 2);
+ QWhatsThis::add(d->focalLengthEdit, i18n("<p>Set here the lens focal length in milimeters "
+ "used by camera to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->focalLength35mmCheck = new QCheckBox(i18n("Focal length in 35mm film (mm):"), parent);
+ d->focalLength35mmEdit = new KIntSpinBox(1, 10000, 1, 1, 10, parent);
+ grid->addMultiCellWidget(d->focalLength35mmCheck, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->focalLength35mmEdit, 1, 1, 2, 2);
+ QWhatsThis::add(d->focalLength35mmEdit, i18n("<p>Set here equivalent focal length assuming "
+ "a 35mm film camera, in mm. A value of 0 means the focal "
+ "length is unknown."));
+
+ // --------------------------------------------------------
+
+ d->digitalZoomRatioCheck = new QCheckBox(i18n("Digital zoom ratio:"), parent);
+ d->digitalZoomRatioEdit = new KDoubleSpinBox(0.0, 100.0, 0.1, 1.0, 1, parent);
+ grid->addMultiCellWidget(d->digitalZoomRatioCheck, 2, 2, 0, 0);
+ grid->addMultiCellWidget(d->digitalZoomRatioEdit, 2, 2, 2, 2);
+ QWhatsThis::add(d->digitalZoomRatioEdit, i18n("<p>Set here the digital zoom ratio "
+ "used by camera to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->apertureCheck = new MetadataCheckBox(i18n("Lens aperture (f-number):"), parent);
+ d->apertureCB = new QComboBox(false, parent);
+ d->apertureCB->insertStringList(d->apertureValues);
+ grid->addMultiCellWidget(d->apertureCheck, 3, 3, 0, 0);
+ grid->addMultiCellWidget(d->apertureCB, 3, 3, 2, 2);
+ QWhatsThis::add(d->apertureCB, i18n("<p>Select here the lens aperture used by camera "
+ "to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->maxApertureCheck = new MetadataCheckBox(i18n("Max. lens aperture (f-number):"), parent);
+ d->maxApertureCB = new QComboBox(false, parent);
+ d->maxApertureCB->insertStringList(d->apertureValues);
+ grid->addMultiCellWidget(d->maxApertureCheck, 4, 4, 0, 0);
+ grid->addMultiCellWidget(d->maxApertureCB, 4, 4, 2, 2);
+ QWhatsThis::add(d->maxApertureCB, i18n("<p>Select here the smallest aperture of the lens used by camera "
+ "to take the picture."));
+
+ grid->setColStretch(1, 10);
+ grid->setRowStretch(5, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->focalLengthCheck, SIGNAL(toggled(bool)),
+ d->focalLengthEdit, SLOT(setEnabled(bool)));
+
+ connect(d->focalLength35mmCheck, SIGNAL(toggled(bool)),
+ d->focalLength35mmEdit, SLOT(setEnabled(bool)));
+
+ connect(d->digitalZoomRatioCheck, SIGNAL(toggled(bool)),
+ d->digitalZoomRatioEdit, SLOT(setEnabled(bool)));
+
+ connect(d->apertureCheck, SIGNAL(toggled(bool)),
+ d->apertureCB, SLOT(setEnabled(bool)));
+
+ connect(d->maxApertureCheck, SIGNAL(toggled(bool)),
+ d->maxApertureCB, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->focalLength35mmCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->focalLengthCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->digitalZoomRatioCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->apertureCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->maxApertureCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->apertureCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->maxApertureCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->focalLength35mmEdit, SIGNAL(valueChanged(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->focalLengthEdit, SIGNAL(valueChanged(double)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->digitalZoomRatioEdit, SIGNAL(valueChanged(double)),
+ this, SIGNAL(signalModified()));
+}
+
+EXIFLens::~EXIFLens()
+{
+ delete d;
+}
+
+void EXIFLens::readMetadata(QByteArray& exifData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ long int num=1, den=1;
+ long val=0;
+
+ d->focalLengthEdit->setValue(50.0);
+ d->focalLengthCheck->setChecked(false);
+ if (exiv2Iface.getExifTagRational("Exif.Photo.FocalLength", num, den))
+ {
+ d->focalLengthEdit->setValue((double)(num) / (double)(den));
+ d->focalLengthCheck->setChecked(true);
+ }
+ d->focalLengthEdit->setEnabled(d->focalLengthCheck->isChecked());
+
+ d->focalLength35mmEdit->setValue(10);
+ d->focalLength35mmCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.FocalLengthIn35mmFilm", val))
+ {
+ d->focalLength35mmEdit->setValue(val);
+ d->focalLength35mmCheck->setChecked(true);
+ }
+ d->focalLength35mmEdit->setEnabled(d->focalLength35mmCheck->isChecked());
+
+ d->digitalZoomRatioEdit->setValue(1.0);
+ d->digitalZoomRatioCheck->setChecked(false);
+ if (exiv2Iface.getExifTagRational("Exif.Photo.DigitalZoomRatio", num, den))
+ {
+ d->digitalZoomRatioEdit->setValue((num == 0) ? 0.0 : (double)(num) / (double)(den));
+ d->digitalZoomRatioCheck->setChecked(true);
+ }
+ d->digitalZoomRatioEdit->setEnabled(d->digitalZoomRatioCheck->isChecked());
+
+ d->apertureCB->setCurrentItem(0);
+ d->apertureCheck->setChecked(false);
+ if (exiv2Iface.getExifTagRational("Exif.Photo.FNumber", num, den))
+ {
+ QString fnumber = QString::number((double)(num)/(double)(den), 'f', 1);
+
+ int item = -1;
+ for (int i = 0 ; i < d->apertureCB->count() ; i++)
+ {
+ if (d->apertureCB->text(i).remove(0, 2) == fnumber)
+ item = i;
+ }
+
+ if (item != -1)
+ {
+ d->apertureCB->setCurrentItem(item);
+ d->apertureCheck->setChecked(true);
+ }
+ }
+ else if (exiv2Iface.getExifTagRational("Exif.Photo.ApertureValue", num, den))
+ {
+ double aperture = pow(2.0, ((double)(num)/(double)(den))/2.0);
+
+ QString fnumber = QString::number(aperture, 'f', 1);
+
+ int item = -1;
+ for (int i = 0 ; i < d->apertureCB->count() ; i++)
+ {
+ if (d->apertureCB->text(i).remove(0, 2) == fnumber)
+ item = i;
+ }
+
+ if (item != -1)
+ {
+ d->apertureCB->setCurrentItem(item);
+ d->apertureCheck->setChecked(true);
+ }
+ else
+ d->apertureCheck->setValid(false);
+ }
+ d->apertureCB->setEnabled(d->apertureCheck->isChecked());
+
+ d->maxApertureCB->setCurrentItem(0);
+ d->maxApertureCheck->setChecked(false);
+ if (exiv2Iface.getExifTagRational("Exif.Photo.MaxApertureValue", num, den))
+ {
+ double maxAperture = pow(2.0, ((double)(num)/(double)(den))/2.0);
+
+ QString fnumber = QString::number(maxAperture, 'f', 1);
+
+ int item = -1;
+ for (int i = 0 ; i < d->apertureCB->count() ; i++)
+ {
+ if (d->maxApertureCB->text(i).remove(0, 2) == fnumber)
+ item = i;
+ }
+
+ if (item != -1)
+ {
+ d->maxApertureCB->setCurrentItem(item);
+ d->maxApertureCheck->setChecked(true);
+ }
+ else
+ d->maxApertureCheck->setValid(false);
+ }
+ d->maxApertureCB->setEnabled(d->maxApertureCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void EXIFLens::applyMetadata(QByteArray& exifData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ long int num=1, den=1;
+
+ if (d->focalLengthCheck->isChecked())
+ {
+ exiv2Iface.convertToRational(d->focalLengthEdit->value(), &num, &den, 1);
+ exiv2Iface.setExifTagRational("Exif.Photo.FocalLength", num, den);
+ }
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.FocalLength");
+
+ if (d->focalLength35mmCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.FocalLengthIn35mmFilm", d->focalLength35mmEdit->value());
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.FocalLengthIn35mmFilm");
+
+ if (d->digitalZoomRatioCheck->isChecked())
+ {
+ exiv2Iface.convertToRational(d->digitalZoomRatioEdit->value(), &num, &den, 1);
+ exiv2Iface.setExifTagRational("Exif.Photo.DigitalZoomRatio", num, den);
+ }
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.DigitalZoomRatio");
+
+ if (d->apertureCheck->isChecked())
+ {
+ exiv2Iface.convertToRational(d->apertureCB->currentText().remove(0, 2).toDouble(), &num, &den, 1);
+ exiv2Iface.setExifTagRational("Exif.Photo.FNumber", num, den);
+
+ double fnumber = d->apertureCB->currentText().remove(0, 2).toDouble();
+ double aperture = 2.0*(log(fnumber)/log(2.0));
+ exiv2Iface.convertToRational(aperture, &num, &den, 8);
+ exiv2Iface.setExifTagRational("Exif.Photo.ApertureValue", num, den);
+ }
+ else if (d->apertureCheck->isValid())
+ {
+ exiv2Iface.removeExifTag("Exif.Photo.FNumber");
+ exiv2Iface.removeExifTag("Exif.Photo.ApertureValue");
+ }
+
+ if (d->maxApertureCheck->isChecked())
+ {
+ double fnumber = d->maxApertureCB->currentText().remove(0, 2).toDouble();
+ double aperture = 2.0*(log(fnumber)/log(2.0));
+ exiv2Iface.convertToRational(aperture, &num, &den, 8);
+ exiv2Iface.setExifTagRational("Exif.Photo.MaxApertureValue", num, den);
+ }
+ else if (d->maxApertureCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.MaxApertureValue");
+
+ exifData = exiv2Iface.getExif();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/exiflens.h b/kipi-plugins/metadataedit/exiflens.h
new file mode 100644
index 0000000..de91970
--- /dev/null
+++ b/kipi-plugins/metadataedit/exiflens.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF lens settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 EXIF_LENS_H
+#define EXIF_LENS_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFLensPriv;
+
+class EXIFLens : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ EXIFLens(QWidget* parent);
+ ~EXIFLens();
+
+ void applyMetadata(QByteArray& exifData);
+ void readMetadata(QByteArray& exifData);
+
+signals:
+
+ void signalModified();
+
+private:
+
+ EXIFLensPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // EXIF_LENS_H
diff --git a/kipi-plugins/metadataedit/exiflight.cpp b/kipi-plugins/metadataedit/exiflight.cpp
new file mode 100644
index 0000000..e0a6d06
--- /dev/null
+++ b/kipi-plugins/metadataedit/exiflight.cpp
@@ -0,0 +1,375 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF light settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qcombobox.h>
+#include <qmap.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <knuminput.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "metadatacheckbox.h"
+#include "exiflight.h"
+#include "exiflight.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+ class FlashMode
+ {
+ public:
+
+ FlashMode() {}
+ FlashMode(int id, const QString& desc) : m_id(id), m_desc(desc) {}
+
+ int id() const { return m_id; }
+ QString desc() const { return m_desc; }
+
+ private:
+
+ int m_id;
+ QString m_desc;
+ };
+
+class EXIFLightPriv
+{
+public:
+
+ EXIFLightPriv()
+ {
+ lightSourceCheck = 0;
+ flashModeCheck = 0;
+ flashEnergyCheck = 0;
+ whiteBalanceCheck = 0;
+ lightSourceCB = 0;
+ flashEnergyEdit = 0;
+ flashModeCB = 0;
+ whiteBalanceCB = 0;
+
+ flashModeMap.insert(0, FlashMode( 0x00, i18n("No flash") ));
+ flashModeMap.insert(1, FlashMode( 0x01, i18n("Fired") ));
+ flashModeMap.insert(2, FlashMode( 0x05, i18n("Fired, no strobe return light") ));
+ flashModeMap.insert(3, FlashMode( 0x07, i18n("Fired, strobe return light") ));
+ flashModeMap.insert(4, FlashMode( 0x09, i18n("Yes, compulsory") ));
+ flashModeMap.insert(5, FlashMode( 0x0d, i18n("Yes, compulsory, no return light") ));
+ flashModeMap.insert(6, FlashMode( 0x0f, i18n("Yes, compulsory, return light") ));
+ flashModeMap.insert(7, FlashMode( 0x10, i18n("No, compulsory") ));
+ flashModeMap.insert(8, FlashMode( 0x18, i18n("No, auto") ));
+ flashModeMap.insert(9, FlashMode( 0x19, i18n("Yes, auto") ));
+ flashModeMap.insert(10, FlashMode( 0x1d, i18n("Yes, auto, no return light") ));
+ flashModeMap.insert(11, FlashMode( 0x1f, i18n("Yes, auto, return light") ));
+ flashModeMap.insert(12, FlashMode( 0x20, i18n("No flash function") ));
+ flashModeMap.insert(13, FlashMode( 0x41, i18n("Yes, red-eye") ));
+ flashModeMap.insert(14, FlashMode( 0x45, i18n("Yes, red-eye, no return light") ));
+ flashModeMap.insert(15, FlashMode( 0x47, i18n("Yes, red-eye, return light") ));
+ flashModeMap.insert(16, FlashMode( 0x49, i18n("Yes, compulsory, red-eye") ));
+ flashModeMap.insert(17, FlashMode( 0x4d, i18n("Yes, compulsory, red-eye, no return light") ));
+ flashModeMap.insert(18, FlashMode( 0x4f, i18n("Yes, compulsory, red-eye, return light") ));
+ flashModeMap.insert(19, FlashMode( 0x59, i18n("Yes, auto, red-eye") ));
+ flashModeMap.insert(20, FlashMode( 0x5d, i18n("Yes, auto, red-eye, no return light") ));
+ flashModeMap.insert(21, FlashMode( 0x5f, i18n("Yes, auto, red-eye, return light") ));
+ }
+
+ typedef QMap<int, FlashMode> FlashModeMap;
+
+ FlashModeMap flashModeMap;
+
+ QCheckBox *flashEnergyCheck;
+
+ QComboBox *lightSourceCB;
+ QComboBox *flashModeCB;
+ QComboBox *whiteBalanceCB;
+
+ KDoubleSpinBox *flashEnergyEdit;
+
+ MetadataCheckBox *lightSourceCheck;
+ MetadataCheckBox *flashModeCheck;
+ MetadataCheckBox *whiteBalanceCheck;
+};
+
+EXIFLight::EXIFLight(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new EXIFLightPriv;
+
+ QGridLayout* grid = new QGridLayout(parent, 4, 3, KDialog::spacingHint());
+
+ // --------------------------------------------------------
+
+ d->lightSourceCheck = new MetadataCheckBox(i18n("Light source:"), parent);
+ d->lightSourceCB = new QComboBox(false, parent);
+ d->lightSourceCB->insertItem(i18n("Unknown"), 0);
+ d->lightSourceCB->insertItem(i18n("Daylight"), 1);
+ d->lightSourceCB->insertItem(i18n("Fluorescent"), 2);
+ d->lightSourceCB->insertItem(i18n("Tungsten (incandescent light)"), 3);
+ d->lightSourceCB->insertItem(i18n("Flash"), 4);
+ d->lightSourceCB->insertItem(i18n("Fine weather"), 5);
+ d->lightSourceCB->insertItem(i18n("Cloudy weather"), 6);
+ d->lightSourceCB->insertItem(i18n("Shade"), 7);
+ d->lightSourceCB->insertItem(i18n("Daylight fluorescent (D 5700 - 7100K)"), 8);
+ d->lightSourceCB->insertItem(i18n("Day white fluorescent (N 4600 - 5400K)"), 9);
+ d->lightSourceCB->insertItem(i18n("Cool white fluorescent (W 3900 - 4500K)"), 10);
+ d->lightSourceCB->insertItem(i18n("White fluorescent (WW 3200 - 3700K)"), 11);
+ d->lightSourceCB->insertItem(i18n("Standard light A"), 12);
+ d->lightSourceCB->insertItem(i18n("Standard light B"), 13);
+ d->lightSourceCB->insertItem(i18n("Standard light C"), 14);
+ d->lightSourceCB->insertItem(i18n("D55"), 15);
+ d->lightSourceCB->insertItem(i18n("D65"), 16);
+ d->lightSourceCB->insertItem(i18n("D75"), 17);
+ d->lightSourceCB->insertItem(i18n("D50"), 18);
+ d->lightSourceCB->insertItem(i18n("ISO studio tungsten"), 19);
+ d->lightSourceCB->insertItem(i18n("Other light source"), 20);
+ grid->addMultiCellWidget(d->lightSourceCheck, 0, 0, 0, 0);
+ grid->addMultiCellWidget(d->lightSourceCB, 0, 0, 2, 3);
+ QWhatsThis::add(d->lightSourceCB, i18n("<p>Select here the kind of light source used "
+ "to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->flashModeCheck = new MetadataCheckBox(i18n("Flash mode:"), parent);
+ d->flashModeCB = new QComboBox(false, parent);
+
+ for (EXIFLightPriv::FlashModeMap::Iterator it = d->flashModeMap.begin();
+ it != d->flashModeMap.end(); ++it )
+ d->flashModeCB->insertItem(it.data().desc());
+
+ grid->addMultiCellWidget(d->flashModeCheck, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->flashModeCB, 1, 1, 2, 3);
+ QWhatsThis::add(d->flashModeCB, i18n("<p>Select here the flash program mode used by camera "
+ "to take the picture."));
+
+ // --------------------------------------------------------
+
+ d->flashEnergyCheck = new QCheckBox(i18n("Flash energy (BCPS):"), parent);
+ d->flashEnergyEdit = new KDoubleSpinBox(1.0, 10000.0, 1.0, 1.0, 1, parent);
+ grid->addMultiCellWidget(d->flashEnergyCheck, 2, 2, 0, 0);
+ grid->addMultiCellWidget(d->flashEnergyEdit, 2, 2, 2, 2);
+ QWhatsThis::add(d->flashEnergyEdit, i18n("<p>Set here the flash energy used to take the picture "
+ "in BCPS unit. Beam Candle Power Seconds is the measure "
+ "of effective intensity of a light source when it is "
+ "focused into a beam by a reflector or lens. This value "
+ "is the effective intensity for a period of one second."));
+
+ // --------------------------------------------------------
+
+ d->whiteBalanceCheck = new MetadataCheckBox(i18n("White balance:"), parent);
+ d->whiteBalanceCB = new QComboBox(false, parent);
+ d->whiteBalanceCB->insertItem(i18n("Auto"), 0);
+ d->whiteBalanceCB->insertItem(i18n("Manual"), 1);
+ grid->addMultiCellWidget(d->whiteBalanceCheck, 3, 3, 0, 0);
+ grid->addMultiCellWidget(d->whiteBalanceCB, 3, 3, 2, 2);
+ QWhatsThis::add(d->whiteBalanceCB, i18n("<p>Select here the white balance mode set by camera when "
+ "the picture have been shot."));
+
+
+ grid->setColStretch(1, 10);
+ grid->setRowStretch(4, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->lightSourceCheck, SIGNAL(toggled(bool)),
+ d->lightSourceCB, SLOT(setEnabled(bool)));
+
+ connect(d->flashModeCheck, SIGNAL(toggled(bool)),
+ d->flashModeCB, SLOT(setEnabled(bool)));
+
+ connect(d->flashEnergyCheck, SIGNAL(toggled(bool)),
+ d->flashEnergyEdit, SLOT(setEnabled(bool)));
+
+ connect(d->whiteBalanceCheck, SIGNAL(toggled(bool)),
+ d->whiteBalanceCB, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->flashEnergyCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->lightSourceCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->flashModeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->whiteBalanceCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->lightSourceCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->flashModeCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->whiteBalanceCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->flashEnergyEdit, SIGNAL(valueChanged(double)),
+ this, SIGNAL(signalModified()));
+}
+
+EXIFLight::~EXIFLight()
+{
+ delete d;
+}
+
+void EXIFLight::readMetadata(QByteArray& exifData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ long int num=1, den=1;
+ long val=0;
+
+ d->lightSourceCB->setCurrentItem(0);
+ d->lightSourceCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.LightSource", val))
+ {
+ if ((val>=0 && val <=4) || (val> 8 && val <16) || (val> 16 && val <25) || val == 255)
+ {
+ if (val > 8 && val < 16)
+ val = val - 4;
+ else if (val > 16 && val < 25)
+ val = val - 5;
+ else if (val == 255)
+ val = 20;
+
+ d->lightSourceCB->setCurrentItem(val);
+ d->lightSourceCheck->setChecked(true);
+ }
+ else
+ d->lightSourceCheck->setValid(false);
+ }
+ d->lightSourceCB->setEnabled(d->lightSourceCheck->isChecked());
+
+ d->flashModeCB->setCurrentItem(0);
+ d->flashModeCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.Flash", val))
+ {
+ int item = -1;
+ for (EXIFLightPriv::FlashModeMap::Iterator it = d->flashModeMap.begin();
+ it != d->flashModeMap.end(); ++it )
+ {
+ if (it.data().id() == val)
+ item = it.key();
+ }
+
+ if (item != -1)
+ {
+ d->flashModeCB->setCurrentItem(item);
+ d->flashModeCheck->setChecked(true);
+ }
+ else
+ d->flashModeCheck->setValid(false);
+ }
+ d->flashModeCB->setEnabled(d->flashModeCheck->isChecked());
+
+ d->flashEnergyEdit->setValue(1.0);
+ d->flashEnergyCheck->setChecked(false);
+ if (exiv2Iface.getExifTagRational("Exif.Photo.FlashEnergy", num, den))
+ {
+ d->flashEnergyEdit->setValue((double)(num) / (double)(den));
+ d->flashEnergyCheck->setChecked(true);
+ }
+ d->flashEnergyEdit->setEnabled(d->flashEnergyCheck->isChecked());
+
+ d->whiteBalanceCB->setCurrentItem(0);
+ d->whiteBalanceCheck->setChecked(false);
+ if (exiv2Iface.getExifTagLong("Exif.Photo.WhiteBalance", val))
+ {
+ if (val>=0 && val<=1)
+ {
+ d->whiteBalanceCB->setCurrentItem(val);
+ d->whiteBalanceCheck->setChecked(true);
+ }
+ else
+ d->whiteBalanceCheck->setValid(false);
+ }
+ d->whiteBalanceCB->setEnabled(d->whiteBalanceCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void EXIFLight::applyMetadata(QByteArray& exifData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ long int num=1, den=1;
+
+ if (d->lightSourceCheck->isChecked())
+ {
+ long val = d->lightSourceCB->currentItem();
+ if (val > 4 && val < 12)
+ val = val + 4;
+ else if (val > 11 && val < 20)
+ val = val + 5;
+ else if (val == 20)
+ val = 255;
+
+ exiv2Iface.setExifTagLong("Exif.Photo.LightSource", val);
+ }
+ else if (d->lightSourceCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.LightSource");
+
+ if (d->flashModeCheck->isChecked())
+ {
+ long val = d->flashModeCB->currentItem();
+ exiv2Iface.setExifTagLong("Exif.Photo.Flash", d->flashModeMap[val].id());
+ }
+ else if (d->flashModeCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.Flash");
+
+ if (d->flashEnergyCheck->isChecked())
+ {
+ exiv2Iface.convertToRational(d->flashEnergyEdit->value(), &num, &den, 1);
+ exiv2Iface.setExifTagRational("Exif.Photo.FlashEnergy", num, den);
+ }
+ else
+ exiv2Iface.removeExifTag("Exif.Photo.FlashEnergy");
+
+ if (d->whiteBalanceCheck->isChecked())
+ exiv2Iface.setExifTagLong("Exif.Photo.WhiteBalance", d->whiteBalanceCB->currentItem());
+ else if (d->whiteBalanceCheck->isValid())
+ exiv2Iface.removeExifTag("Exif.Photo.WhiteBalance");
+
+ exifData = exiv2Iface.getExif();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/exiflight.h b/kipi-plugins/metadataedit/exiflight.h
new file mode 100644
index 0000000..7b2f05c
--- /dev/null
+++ b/kipi-plugins/metadataedit/exiflight.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : EXIF light settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 EXIF_LIGHT_H
+#define EXIF_LIGHT_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class EXIFLightPriv;
+
+class EXIFLight : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ EXIFLight(QWidget* parent);
+ ~EXIFLight();
+
+ void applyMetadata(QByteArray& exifData);
+ void readMetadata(QByteArray& exifData);
+
+signals:
+
+ void signalModified();
+
+private:
+
+ EXIFLightPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // EXIF_LIGHT_H
diff --git a/kipi-plugins/metadataedit/iptccaption.cpp b/kipi-plugins/metadataedit/iptccaption.cpp
new file mode 100644
index 0000000..3569e95
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptccaption.cpp
@@ -0,0 +1,350 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : IPTC caption settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qhgroupbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qcheckbox.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <klineedit.h>
+#include <ktextedit.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kseparator.h>
+#include <kactivelabel.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "iptccaption.h"
+#include "iptccaption.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCCaptionPriv
+{
+public:
+
+ IPTCCaptionPriv()
+ {
+ captionEdit = 0;
+ writerEdit = 0;
+ headlineEdit = 0;
+ specialInstructionEdit = 0;
+ captionCheck = 0;
+ specialInstructionCheck = 0;
+ writerCheck = 0;
+ headlineCheck = 0;
+ syncJFIFCommentCheck = 0;
+ syncHOSTCommentCheck = 0;
+ syncEXIFCommentCheck = 0;
+ }
+
+ QCheckBox *captionCheck;
+ QCheckBox *specialInstructionCheck;
+ QCheckBox *writerCheck;
+ QCheckBox *headlineCheck;
+ QCheckBox *syncJFIFCommentCheck;
+ QCheckBox *syncHOSTCommentCheck;
+ QCheckBox *syncEXIFCommentCheck;
+
+ KTextEdit *captionEdit;
+ KTextEdit *specialInstructionEdit;
+
+ KLineEdit *writerEdit;
+ KLineEdit *headlineEdit;
+};
+
+IPTCCaption::IPTCCaption(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new IPTCCaptionPriv;
+ QVBoxLayout *vlay = new QVBoxLayout( parent, 0, KDialog::spacingHint() );
+
+ // IPTC only accept printable Ascii char.
+ QRegExp asciiRx("[\x20-\x7F]+$");
+ QValidator *asciiValidator = new QRegExpValidator(asciiRx, this);
+
+ // --------------------------------------------------------
+
+ d->captionCheck = new QCheckBox(i18n("Caption:"), parent);
+ d->captionEdit = new KTextEdit(parent);
+ d->syncJFIFCommentCheck = new QCheckBox(i18n("Sync JFIF Comment section"), parent);
+ d->syncHOSTCommentCheck = new QCheckBox(i18n("Sync caption entered through %1")
+ .arg(KApplication::kApplication()->aboutData()->appName()),
+ parent);
+ d->syncEXIFCommentCheck = new QCheckBox(i18n("Sync EXIF Comment"), parent);
+ KSeparator *line = new KSeparator(Horizontal, parent);
+
+/* d->captionEdit->setValidator(asciiValidator);
+ d->captionEdit->setMaxLength(2000);*/
+ vlay->addWidget(d->captionCheck);
+ vlay->addWidget(d->captionEdit);
+ vlay->addWidget(d->syncJFIFCommentCheck);
+ vlay->addWidget(d->syncHOSTCommentCheck);
+ vlay->addWidget(d->syncEXIFCommentCheck);
+ vlay->addWidget(line);
+ QWhatsThis::add(d->captionEdit, i18n("<p>Enter the content description. This field is limited "
+ "to 2000 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->writerCheck = new QCheckBox(i18n("Caption Writer:"), parent);
+ d->writerEdit = new KLineEdit(parent);
+ d->writerEdit->setValidator(asciiValidator);
+ d->writerEdit->setMaxLength(32);
+ vlay->addWidget(d->writerCheck);
+ vlay->addWidget(d->writerEdit);
+ QWhatsThis::add(d->writerEdit, i18n("<p>Enter the name of the caption author. This field is limited "
+ "to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->headlineCheck = new QCheckBox(i18n("Headline:"), parent);
+ d->headlineEdit = new KLineEdit(parent);
+ d->headlineEdit->setValidator(asciiValidator);
+ d->headlineEdit->setMaxLength(256);
+ vlay->addWidget(d->headlineCheck);
+ vlay->addWidget(d->headlineEdit);
+ QWhatsThis::add(d->headlineEdit, i18n("<p>Enter here the content synopsis. This field is limited "
+ "to 256 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->specialInstructionCheck = new QCheckBox(i18n("Special Instructions:"), parent);
+ d->specialInstructionEdit = new KTextEdit(parent);
+/* d->specialInstructionEdit->setValidator(asciiValidator);
+ d->specialInstructionEdit->setMaxLength(256);*/
+ vlay->addWidget(d->specialInstructionCheck);
+ vlay->addWidget(d->specialInstructionEdit);
+ QWhatsThis::add(d->specialInstructionEdit, i18n("<p>Enter the editorial usage instructions. "
+ "This field is limited to 256 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ KActiveLabel *note = new KActiveLabel(i18n("<b>Note: "
+ "<b><a href='http://en.wikipedia.org/wiki/IPTC'>IPTC</a></b> "
+ "text tags only support the printable "
+ "<b><a href='http://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
+ "characters set and limit strings size. "
+ "Use contextual help for details.</b>"), parent);
+ vlay->addWidget(note);
+ vlay->addStretch();
+
+ // --------------------------------------------------------
+
+ connect(d->captionCheck, SIGNAL(toggled(bool)),
+ d->captionEdit, SLOT(setEnabled(bool)));
+
+ connect(d->captionCheck, SIGNAL(toggled(bool)),
+ d->syncJFIFCommentCheck, SLOT(setEnabled(bool)));
+
+ connect(d->captionCheck, SIGNAL(toggled(bool)),
+ d->syncHOSTCommentCheck, SLOT(setEnabled(bool)));
+
+ connect(d->captionCheck, SIGNAL(toggled(bool)),
+ d->syncEXIFCommentCheck, SLOT(setEnabled(bool)));
+
+ connect(d->writerCheck, SIGNAL(toggled(bool)),
+ d->writerEdit, SLOT(setEnabled(bool)));
+
+ connect(d->headlineCheck, SIGNAL(toggled(bool)),
+ d->headlineEdit, SLOT(setEnabled(bool)));
+
+ connect(d->specialInstructionCheck, SIGNAL(toggled(bool)),
+ d->specialInstructionEdit, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->captionCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->writerCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->headlineCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->specialInstructionCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->captionEdit, SIGNAL(textChanged()),
+ this, SIGNAL(signalModified()));
+
+ connect(d->specialInstructionEdit, SIGNAL(textChanged()),
+ this, SIGNAL(signalModified()));
+
+ connect(d->writerEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->headlineEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+}
+
+IPTCCaption::~IPTCCaption()
+{
+ delete d;
+}
+
+bool IPTCCaption::syncJFIFCommentIsChecked()
+{
+ return d->syncJFIFCommentCheck->isChecked();
+}
+
+bool IPTCCaption::syncHOSTCommentIsChecked()
+{
+ return d->syncHOSTCommentCheck->isChecked();
+}
+
+bool IPTCCaption::syncEXIFCommentIsChecked()
+{
+ return d->syncEXIFCommentCheck->isChecked();
+}
+
+QString IPTCCaption::getIPTCCaption()
+{
+ return d->captionEdit->text();
+}
+
+void IPTCCaption::setCheckedSyncJFIFComment(bool c)
+{
+ d->syncJFIFCommentCheck->setChecked(c);
+}
+
+void IPTCCaption::setCheckedSyncHOSTComment(bool c)
+{
+ d->syncHOSTCommentCheck->setChecked(c);
+}
+
+void IPTCCaption::setCheckedSyncEXIFComment(bool c)
+{
+ d->syncEXIFCommentCheck->setChecked(c);
+}
+
+void IPTCCaption::readMetadata(QByteArray& iptcData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+ QString data;
+
+ d->captionEdit->clear();
+ d->captionCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Caption", false);
+ if (!data.isNull())
+ {
+ d->captionEdit->setText(data);
+ d->captionCheck->setChecked(true);
+ }
+ d->captionEdit->setEnabled(d->captionCheck->isChecked());
+ d->syncJFIFCommentCheck->setEnabled(d->captionCheck->isChecked());
+ d->syncHOSTCommentCheck->setEnabled(d->captionCheck->isChecked());
+ d->syncEXIFCommentCheck->setEnabled(d->captionCheck->isChecked());
+
+ d->writerEdit->clear();
+ d->writerCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Writer", false);
+ if (!data.isNull())
+ {
+ d->writerEdit->setText(data);
+ d->writerCheck->setChecked(true);
+ }
+ d->writerEdit->setEnabled(d->writerCheck->isChecked());
+
+ d->headlineEdit->clear();
+ d->headlineCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Headline", false);
+ if (!data.isNull())
+ {
+ d->headlineEdit->setText(data);
+ d->headlineCheck->setChecked(true);
+ }
+ d->headlineEdit->setEnabled(d->headlineCheck->isChecked());
+
+ d->specialInstructionEdit->clear();
+ d->specialInstructionCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.SpecialInstructions", false);
+ if (!data.isNull())
+ {
+ d->specialInstructionEdit->setText(data);
+ d->specialInstructionCheck->setChecked(true);
+ }
+ d->specialInstructionEdit->setEnabled(d->specialInstructionCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void IPTCCaption::applyMetadata(QByteArray& exifData, QByteArray& iptcData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ exiv2Iface.setIptc(iptcData);
+
+ if (d->captionCheck->isChecked())
+ {
+ exiv2Iface.setIptcTagString("Iptc.Application2.Caption", d->captionEdit->text());
+
+ if (syncEXIFCommentIsChecked())
+ exiv2Iface.setExifComment(d->captionEdit->text());
+
+ if (syncJFIFCommentIsChecked())
+ exiv2Iface.setComments(d->captionEdit->text().utf8());
+ }
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.Caption");
+
+ if (d->writerCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Writer", d->writerEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.Writer");
+
+ if (d->headlineCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Headline", d->headlineEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.Headline");
+
+ if (d->specialInstructionCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.SpecialInstructions", d->specialInstructionEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.SpecialInstructions");
+
+ exifData = exiv2Iface.getExif();
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/iptccaption.h b/kipi-plugins/metadataedit/iptccaption.h
new file mode 100644
index 0000000..cc93fad
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptccaption.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : IPTC caption settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IPTC_CAPTION_H
+#define IPTC_CAPTION_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCCaptionPriv;
+
+class IPTCCaption : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ IPTCCaption(QWidget* parent);
+ ~IPTCCaption();
+
+ void applyMetadata(QByteArray& exifData, QByteArray& iptcData);
+ void readMetadata(QByteArray& iptcData);
+
+ bool syncJFIFCommentIsChecked();
+ bool syncHOSTCommentIsChecked();
+ bool syncEXIFCommentIsChecked();
+
+ void setCheckedSyncJFIFComment(bool c);
+ void setCheckedSyncHOSTComment(bool c);
+ void setCheckedSyncEXIFComment(bool c);
+
+ QString getIPTCCaption();
+
+signals:
+
+ void signalModified();
+
+private:
+
+ IPTCCaptionPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // IPTC_CAPTION_H
diff --git a/kipi-plugins/metadataedit/iptccategories.cpp b/kipi-plugins/metadataedit/iptccategories.cpp
new file mode 100644
index 0000000..1172663
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptccategories.cpp
@@ -0,0 +1,309 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-15
+ * Description : IPTC categories settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <klistbox.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+#include <kactivelabel.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "iptccategories.h"
+#include "iptccategories.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCCategoriesPriv
+{
+public:
+
+ IPTCCategoriesPriv()
+ {
+ addSubCategoryButton = 0;
+ delSubCategoryButton = 0;
+ subCategoriesBox = 0;
+ subCategoriesCheck = 0;
+ categoryCheck = 0;
+ categoryEdit = 0;
+ subCategoryEdit = 0;
+ }
+
+ QStringList oldSubCategories;
+
+ QPushButton *addSubCategoryButton;
+ QPushButton *delSubCategoryButton;
+
+ QCheckBox *subCategoriesCheck;
+ QCheckBox *categoryCheck;
+
+ KLineEdit *categoryEdit;
+ KLineEdit *subCategoryEdit;
+
+ KListBox *subCategoriesBox;
+};
+
+IPTCCategories::IPTCCategories(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new IPTCCategoriesPriv;
+ QGridLayout *grid = new QGridLayout(parent, 6, 1, 0, KDialog::spacingHint());
+ grid->setAlignment( Qt::AlignTop );
+
+ // IPTC only accept printable Ascii char.
+ QRegExp asciiRx("[\x20-\x7F]+$");
+ QValidator *asciiValidator = new QRegExpValidator(asciiRx, this);
+
+ // --------------------------------------------------------
+
+ d->categoryCheck = new QCheckBox(i18n("Identify subject of content (3 chars max):"), parent);
+ d->categoryEdit = new KLineEdit(parent);
+ d->categoryEdit->setValidator(asciiValidator);
+ d->categoryEdit->setMaxLength(3);
+ QWhatsThis::add(d->categoryEdit, i18n("<p>Set here the category of content. This field is limited "
+ "to 3 ASCII characters."));
+
+ d->subCategoriesCheck = new QCheckBox(i18n("Supplemental categories:"), parent);
+
+ d->subCategoryEdit = new KLineEdit(parent);
+ d->subCategoryEdit->setValidator(asciiValidator);
+ d->subCategoryEdit->setMaxLength(32);
+ QWhatsThis::add(d->subCategoryEdit, i18n("<p>Enter here a new supplemental category of content. "
+ "This field is limited to 32 ASCII characters."));
+
+ d->subCategoriesBox = new KListBox(parent);
+ d->subCategoriesBox->setVScrollBarMode(QScrollView::AlwaysOn);
+
+ d->addSubCategoryButton = new QPushButton( i18n("&Add"), parent);
+ d->delSubCategoryButton = new QPushButton( i18n("&Delete"), parent);
+ d->addSubCategoryButton->setIconSet(SmallIcon("add"));
+ d->delSubCategoryButton->setIconSet(SmallIcon("remove"));
+ d->delSubCategoryButton->setEnabled(false);
+
+ grid->addMultiCellWidget(d->categoryCheck, 0, 0, 0, 1);
+ grid->addMultiCellWidget(d->categoryEdit, 0, 0, 1, 1);
+ grid->addMultiCellWidget(d->subCategoriesCheck, 1, 1, 0, 1);
+ grid->addMultiCellWidget(d->subCategoryEdit, 2, 2, 0, 0);
+ grid->addMultiCellWidget(d->subCategoriesBox, 3, 6, 0, 0);
+ grid->addMultiCellWidget(d->addSubCategoryButton, 3, 3, 1, 1);
+ grid->addMultiCellWidget(d->delSubCategoryButton, 4, 4, 1, 1);
+
+ // --------------------------------------------------------
+
+ KActiveLabel *note = new KActiveLabel(i18n("<b>Note: "
+ "<b><a href='http://en.wikipedia.org/wiki/IPTC'>IPTC</a></b> "
+ "text tags only support the printable "
+ "<b><a href='http://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
+ "characters set and limit strings size. "
+ "Use contextual help for details.</b>"), parent);
+ note->setMaximumWidth(150);
+
+ grid->addMultiCellWidget(note, 5, 5, 1, 1);
+ grid->setColStretch(0, 10);
+ grid->setRowStretch(6, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->categoryCheck, SIGNAL(toggled(bool)),
+ d->categoryEdit, SLOT(setEnabled(bool)));
+
+ connect(d->categoryCheck, SIGNAL(toggled(bool)),
+ d->subCategoriesBox, SLOT(setEnabled(bool)));
+
+ connect(d->categoryCheck, SIGNAL(toggled(bool)),
+ d->subCategoriesCheck, SLOT(setEnabled(bool)));
+
+ connect(d->categoryCheck, SIGNAL(toggled(bool)),
+ d->subCategoryEdit, SLOT(setEnabled(bool)));
+
+ connect(d->categoryCheck, SIGNAL(toggled(bool)),
+ d->subCategoriesBox, SLOT(setEnabled(bool)));
+
+ connect(d->categoryCheck, SIGNAL(toggled(bool)),
+ d->addSubCategoryButton, SLOT(setEnabled(bool)));
+
+ connect(d->categoryCheck, SIGNAL(toggled(bool)),
+ d->delSubCategoryButton, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->subCategoriesCheck, SIGNAL(toggled(bool)),
+ d->subCategoryEdit, SLOT(setEnabled(bool)));
+
+ connect(d->subCategoriesCheck, SIGNAL(toggled(bool)),
+ d->subCategoriesBox, SLOT(setEnabled(bool)));
+
+ connect(d->subCategoriesCheck, SIGNAL(toggled(bool)),
+ d->addSubCategoryButton, SLOT(setEnabled(bool)));
+
+ connect(d->subCategoriesCheck, SIGNAL(toggled(bool)),
+ d->delSubCategoryButton, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->subCategoriesBox, SIGNAL(selectionChanged()),
+ this, SLOT(slotCategorySelectionChanged()));
+
+ connect(d->addSubCategoryButton, SIGNAL(clicked()),
+ this, SLOT(slotAddCategory()));
+
+ connect(d->delSubCategoryButton, SIGNAL(clicked()),
+ this, SLOT(slotDelCategory()));
+
+ // --------------------------------------------------------
+
+ connect(d->categoryCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->subCategoriesCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->addSubCategoryButton, SIGNAL(clicked()),
+ this, SIGNAL(signalModified()));
+
+ connect(d->delSubCategoryButton, SIGNAL(clicked()),
+ this, SIGNAL(signalModified()));
+
+ connect(d->categoryEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+}
+
+IPTCCategories::~IPTCCategories()
+{
+ delete d;
+}
+
+void IPTCCategories::slotDelCategory()
+{
+ int index = d->subCategoriesBox->currentItem();
+ if (index == -1)
+ return;
+
+ QListBoxItem* item = d->subCategoriesBox->item(index);
+ if (!item) return;
+ delete item;
+}
+
+void IPTCCategories::slotCategorySelectionChanged()
+{
+ if (d->subCategoriesBox->currentItem() != -1)
+ d->delSubCategoryButton->setEnabled(true);
+ else
+ d->delSubCategoryButton->setEnabled(false);
+}
+
+void IPTCCategories::slotAddCategory()
+{
+ QString newCategory = d->subCategoryEdit->text();
+ if (newCategory.isEmpty()) return;
+
+ bool found = false;
+ for (QListBoxItem *item = d->subCategoriesBox->firstItem();
+ item; item = item->next())
+ {
+ if (newCategory == item->text())
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ d->subCategoriesBox->insertItem(newCategory);
+}
+
+void IPTCCategories::readMetadata(QByteArray& iptcData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+ QString data;
+
+ d->categoryEdit->clear();
+ d->categoryCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Category", false);
+ if (!data.isNull())
+ {
+ d->categoryEdit->setText(data);
+ d->categoryCheck->setChecked(true);
+ }
+ d->categoryEdit->setEnabled(d->categoryCheck->isChecked());
+ d->subCategoriesCheck->setEnabled(d->categoryCheck->isChecked());
+
+ d->subCategoriesBox->clear();
+ d->subCategoriesCheck->setChecked(false);
+ d->oldSubCategories = exiv2Iface.getImageSubCategories();
+ if (!d->oldSubCategories.isEmpty())
+ {
+ d->subCategoriesBox->insertStringList(d->oldSubCategories);
+ d->subCategoriesCheck->setChecked(true);
+ }
+ d->subCategoryEdit->setEnabled(d->categoryCheck->isChecked() && d->subCategoriesCheck->isChecked());
+ d->subCategoriesBox->setEnabled(d->categoryCheck->isChecked() && d->subCategoriesCheck->isChecked());
+ d->addSubCategoryButton->setEnabled(d->categoryCheck->isChecked() && d->subCategoriesCheck->isChecked());
+ d->delSubCategoryButton->setEnabled(d->categoryCheck->isChecked() && d->subCategoriesCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void IPTCCategories::applyMetadata(QByteArray& iptcData)
+{
+ QStringList newCategories;
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+
+ if (d->categoryCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Category", d->categoryEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.Category");
+
+ for (QListBoxItem *item = d->subCategoriesBox->firstItem();
+ item; item = item->next())
+ newCategories.append(item->text());
+
+ if (d->categoryCheck->isChecked() && d->subCategoriesCheck->isChecked())
+ exiv2Iface.setImageSubCategories(d->oldSubCategories, newCategories);
+ else
+ exiv2Iface.setImageSubCategories(d->oldSubCategories, QStringList());
+
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/iptccategories.h b/kipi-plugins/metadataedit/iptccategories.h
new file mode 100644
index 0000000..1d63c86
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptccategories.h
@@ -0,0 +1,65 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-15
+ * Description : IPTC categories settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IPTC_CATEGORIES_H
+#define IPTC_CATEGORIES_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCCategoriesPriv;
+
+class IPTCCategories : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ IPTCCategories(QWidget* parent);
+ ~IPTCCategories();
+
+ void applyMetadata(QByteArray& iptcData);
+ void readMetadata(QByteArray& iptcData);
+
+signals:
+
+ void signalModified();
+
+private slots:
+
+ void slotCategorySelectionChanged();
+ void slotAddCategory();
+ void slotDelCategory();
+
+private:
+
+ IPTCCategoriesPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // IPTC_CATEGORIES_H
diff --git a/kipi-plugins/metadataedit/iptccredits.cpp b/kipi-plugins/metadataedit/iptccredits.cpp
new file mode 100644
index 0000000..6f5701b
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptccredits.cpp
@@ -0,0 +1,350 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : IPTC credits settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qhgroupbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qcheckbox.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <klineedit.h>
+#include <kactivelabel.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "iptccredits.h"
+#include "iptccredits.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCCreditsPriv
+{
+public:
+
+ IPTCCreditsPriv()
+ {
+ copyrightEdit = 0;
+ bylineEdit = 0;
+ bylineTitleEdit = 0;
+ creditEdit = 0;
+ sourceEdit = 0;
+ contactEdit = 0;
+ copyrightCheck = 0;
+ bylineCheck = 0;
+ bylineTitleCheck = 0;
+ creditCheck = 0;
+ sourceCheck = 0;
+ contactCheck = 0;
+ }
+
+ QCheckBox *copyrightCheck;
+ QCheckBox *bylineCheck;
+ QCheckBox *bylineTitleCheck;
+ QCheckBox *creditCheck;
+ QCheckBox *sourceCheck;
+ QCheckBox *contactCheck;
+
+ KLineEdit *copyrightEdit;
+ KLineEdit *bylineEdit;
+ KLineEdit *bylineTitleEdit;
+ KLineEdit *creditEdit;
+ KLineEdit *sourceEdit;
+ KLineEdit *contactEdit;
+};
+
+IPTCCredits::IPTCCredits(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new IPTCCreditsPriv;
+ QVBoxLayout *vlay = new QVBoxLayout( parent, 0, KDialog::spacingHint() );
+
+ // IPTC only accept printable Ascii char.
+ QRegExp asciiRx("[\x20-\x7F]+$");
+ QValidator *asciiValidator = new QRegExpValidator(asciiRx, this);
+
+ // --------------------------------------------------------
+
+ d->copyrightCheck = new QCheckBox(i18n("Copyright:"), parent);
+ d->copyrightEdit = new KLineEdit(parent);
+ d->copyrightEdit->setValidator(asciiValidator);
+ d->copyrightEdit->setMaxLength(128);
+ vlay->addWidget(d->copyrightCheck);
+ vlay->addWidget(d->copyrightEdit);
+ QWhatsThis::add(d->copyrightEdit, i18n("<p>Set here the necessary copyright notice. This field is limited "
+ "to 128 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->bylineCheck = new QCheckBox(i18n("Byline:"), parent);
+ d->bylineEdit = new KLineEdit(parent);
+ d->bylineEdit->setValidator(asciiValidator);
+ d->bylineEdit->setMaxLength(32);
+ vlay->addWidget(d->bylineCheck);
+ vlay->addWidget(d->bylineEdit);
+ QWhatsThis::add(d->bylineEdit, i18n("<p>Set here the name of content creator. This field is limited "
+ "to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->bylineTitleCheck = new QCheckBox(i18n("Byline Title:"), parent);
+ d->bylineTitleEdit = new KLineEdit(parent);
+ d->bylineTitleEdit->setValidator(asciiValidator);
+ d->bylineTitleEdit->setMaxLength(32);
+ vlay->addWidget(d->bylineTitleCheck);
+ vlay->addWidget(d->bylineTitleEdit);
+ QWhatsThis::add(d->bylineTitleEdit, i18n("<p>Set here the title of content creator. This field is limited "
+ "to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->creditCheck = new QCheckBox(i18n("Credit:"), parent);
+ d->creditEdit = new KLineEdit(parent);
+ d->creditEdit->setValidator(asciiValidator);
+ d->creditEdit->setMaxLength(32);
+ vlay->addWidget(d->creditCheck);
+ vlay->addWidget(d->creditEdit);
+ QWhatsThis::add(d->creditEdit, i18n("<p>Set here the content provider. "
+ "This field is limited to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->sourceCheck = new QCheckBox(i18n("Source:"), parent);
+ d->sourceEdit = new KLineEdit(parent);
+ d->sourceEdit->setValidator(asciiValidator);
+ d->sourceEdit->setMaxLength(32);
+ vlay->addWidget(d->sourceCheck);
+ vlay->addWidget(d->sourceEdit);
+ QWhatsThis::add(d->sourceEdit, i18n("<p>Set here the original owner of content. "
+ "This field is limited to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->contactCheck = new QCheckBox(i18n("Contact:"), parent);
+ d->contactEdit = new KLineEdit(parent);
+ d->contactEdit->setValidator(asciiValidator);
+ d->contactEdit->setMaxLength(128);
+ vlay->addWidget(d->contactCheck);
+ vlay->addWidget(d->contactEdit);
+ QWhatsThis::add(d->contactEdit, i18n("<p>Set here the person or organisation to contact. "
+ "This field is limited to 128 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ KActiveLabel *note = new KActiveLabel(i18n("<b>Note: "
+ "<b><a href='http://en.wikipedia.org/wiki/IPTC'>IPTC</a></b> "
+ "text tags only support the printable "
+ "<b><a href='http://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
+ "characters set and limit strings size. "
+ "Use contextual help for details.</b>"), parent);
+
+ vlay->addWidget(note);
+ vlay->addStretch();
+
+ // --------------------------------------------------------
+
+ connect(d->copyrightCheck, SIGNAL(toggled(bool)),
+ d->copyrightEdit, SLOT(setEnabled(bool)));
+
+ connect(d->bylineCheck, SIGNAL(toggled(bool)),
+ d->bylineEdit, SLOT(setEnabled(bool)));
+
+ connect(d->bylineTitleCheck, SIGNAL(toggled(bool)),
+ d->bylineTitleEdit, SLOT(setEnabled(bool)));
+
+ connect(d->creditCheck, SIGNAL(toggled(bool)),
+ d->creditEdit, SLOT(setEnabled(bool)));
+
+ connect(d->sourceCheck, SIGNAL(toggled(bool)),
+ d->sourceEdit, SLOT(setEnabled(bool)));
+
+ connect(d->contactCheck, SIGNAL(toggled(bool)),
+ d->contactEdit, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->copyrightCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->bylineCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->bylineTitleCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->creditCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sourceCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->contactCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->copyrightEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->bylineEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->bylineTitleEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->creditEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sourceEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->contactEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+}
+
+IPTCCredits::~IPTCCredits()
+{
+ delete d;
+}
+
+void IPTCCredits::readMetadata(QByteArray& iptcData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+ QString data;
+
+ d->copyrightEdit->clear();
+ d->copyrightCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Copyright", false);
+ if (!data.isNull())
+ {
+ d->copyrightEdit->setText(data);
+ d->copyrightCheck->setChecked(true);
+ }
+ d->copyrightEdit->setEnabled(d->copyrightCheck->isChecked());
+
+ d->bylineEdit->clear();
+ d->bylineCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Byline", false);
+ if (!data.isNull())
+ {
+ d->bylineEdit->setText(data);
+ d->bylineCheck->setChecked(true);
+ }
+ d->bylineEdit->setEnabled(d->bylineCheck->isChecked());
+
+ d->bylineTitleEdit->clear();
+ d->bylineTitleCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.BylineTitle", false);
+ if (!data.isNull())
+ {
+ d->bylineTitleEdit->setText(data);
+ d->bylineTitleCheck->setChecked(true);
+ }
+ d->bylineTitleEdit->setEnabled(d->bylineTitleCheck->isChecked());
+
+ d->creditEdit->clear();
+ d->creditCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Credit", false);
+ if (!data.isNull())
+ {
+ d->creditEdit->setText(data);
+ d->creditCheck->setChecked(true);
+ }
+ d->creditEdit->setEnabled(d->creditCheck->isChecked());
+
+ d->sourceEdit->clear();
+ d->sourceCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Source", false);
+ if (!data.isNull())
+ {
+ d->sourceEdit->setText(data);
+ d->sourceCheck->setChecked(true);
+ }
+ d->sourceEdit->setEnabled(d->sourceCheck->isChecked());
+
+ d->contactEdit->clear();
+ d->contactCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Contact", false);
+ if (!data.isNull())
+ {
+ d->contactEdit->setText(data);
+ d->contactCheck->setChecked(true);
+ }
+ d->contactEdit->setEnabled(d->contactCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void IPTCCredits::applyMetadata(QByteArray& iptcData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+
+ if (d->copyrightCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Copyright", d->copyrightEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.Copyright");
+
+ if (d->bylineCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Byline", d->bylineEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.Byline");
+
+ if (d->bylineTitleCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.BylineTitle", d->bylineTitleEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.BylineTitle");
+
+ if (d->creditCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Credit", d->creditEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.Credit");
+
+ if (d->sourceCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Source", d->sourceEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.Source");
+
+ if (d->contactCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Contact", d->contactEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.Contact");
+
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/iptccredits.h b/kipi-plugins/metadataedit/iptccredits.h
new file mode 100644
index 0000000..710d000
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptccredits.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : IPTC credits settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IPTC_CREDITS_H
+#define IPTC_CREDITS_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCCreditsPriv;
+
+class IPTCCredits : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ IPTCCredits(QWidget* parent);
+ ~IPTCCredits();
+
+ void applyMetadata(QByteArray& iptcData);
+ void readMetadata(QByteArray& iptcData);
+
+signals:
+
+ void signalModified();
+
+private:
+
+ IPTCCreditsPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // IPTC_CREDITS_H
diff --git a/kipi-plugins/metadataedit/iptcdatetime.cpp b/kipi-plugins/metadataedit/iptcdatetime.cpp
new file mode 100644
index 0000000..7889805
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptcdatetime.cpp
@@ -0,0 +1,501 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : IPTC date and time settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qdatetime.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qcheckbox.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <kdatewidget.h>
+#include <ktimewidget.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kseparator.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "iptcdatetime.h"
+#include "iptcdatetime.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCDateTimePriv
+{
+public:
+
+ IPTCDateTimePriv()
+ {
+ dateCreatedSel = 0;
+ dateReleasedSel = 0;
+ dateExpiredSel = 0;
+ dateDigitalizedSel = 0;
+ timeCreatedSel = 0;
+ timeReleasedSel = 0;
+ timeExpiredSel = 0;
+ timeDigitalizedSel = 0;
+
+ dateCreatedCheck = 0;
+ dateReleasedCheck = 0;
+ dateExpiredCheck = 0;
+ dateDigitalizedCheck = 0;
+ timeCreatedCheck = 0;
+ timeReleasedCheck = 0;
+ timeExpiredCheck = 0;
+ timeDigitalizedCheck = 0;
+ syncHOSTDateCheck = 0;
+ syncEXIFDateCheck = 0;
+ }
+
+ QCheckBox *dateCreatedCheck;
+ QCheckBox *dateReleasedCheck;
+ QCheckBox *dateExpiredCheck;
+ QCheckBox *dateDigitalizedCheck;
+ QCheckBox *timeCreatedCheck;
+ QCheckBox *timeReleasedCheck;
+ QCheckBox *timeExpiredCheck;
+ QCheckBox *timeDigitalizedCheck;
+ QCheckBox *syncHOSTDateCheck;
+ QCheckBox *syncEXIFDateCheck;
+
+ KDateWidget *dateCreatedSel;
+ KDateWidget *dateReleasedSel;
+ KDateWidget *dateExpiredSel;
+ KDateWidget *dateDigitalizedSel;
+
+ KTimeWidget *timeCreatedSel;
+ KTimeWidget *timeReleasedSel;
+ KTimeWidget *timeExpiredSel;
+ KTimeWidget *timeDigitalizedSel;
+};
+
+IPTCDateTime::IPTCDateTime(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new IPTCDateTimePriv;
+
+ QGridLayout* grid = new QGridLayout(parent, 11, 2, KDialog::spacingHint());
+
+ // --------------------------------------------------------
+
+ d->dateCreatedCheck = new QCheckBox(i18n("Creation date"), parent);
+ d->timeCreatedCheck = new QCheckBox(i18n("Creation time"), parent);
+ d->dateCreatedSel = new KDateWidget(parent);
+ d->timeCreatedSel = new KTimeWidget(parent);
+ d->syncHOSTDateCheck = new QCheckBox(i18n("Sync creation date entered through %1")
+ .arg(KApplication::kApplication()->aboutData()->appName()),
+ parent);
+ d->syncEXIFDateCheck = new QCheckBox(i18n("Sync EXIF creation date"), parent);
+ KSeparator *line = new KSeparator(Horizontal, parent);
+ d->dateCreatedSel->setDate(QDate::currentDate());
+ d->timeCreatedSel->setTime(QTime::currentTime());
+ grid->addMultiCellWidget(d->dateCreatedCheck, 0, 0, 0, 0);
+ grid->addMultiCellWidget(d->timeCreatedCheck, 0, 0, 1, 2);
+ grid->addMultiCellWidget(d->dateCreatedSel, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->timeCreatedSel, 1, 1, 1, 1);
+ grid->addMultiCellWidget(d->syncHOSTDateCheck, 2, 2, 0, 2);
+ grid->addMultiCellWidget(d->syncEXIFDateCheck, 3, 3, 0, 2);
+ grid->addMultiCellWidget(line, 4, 4, 0, 2);
+ QWhatsThis::add(d->dateCreatedSel, i18n("<p>Set here the creation date of "
+ "intellectual content."));
+ QWhatsThis::add(d->timeCreatedSel, i18n("<p>Set here the creation time of "
+ "intellectual content."));
+
+ // --------------------------------------------------------
+
+ d->dateReleasedCheck = new QCheckBox(i18n("Release date"), parent);
+ d->timeReleasedCheck = new QCheckBox(i18n("Release time"), parent);
+ d->dateReleasedSel = new KDateWidget(parent);
+ d->timeReleasedSel = new KTimeWidget(parent);
+ d->dateReleasedSel->setDate(QDate::currentDate());
+ d->timeReleasedSel->setTime(QTime::currentTime());
+ grid->addMultiCellWidget(d->dateReleasedCheck, 5, 5, 0, 0);
+ grid->addMultiCellWidget(d->timeReleasedCheck, 5, 5, 1, 2);
+ grid->addMultiCellWidget(d->dateReleasedSel, 6, 6, 0, 0);
+ grid->addMultiCellWidget(d->timeReleasedSel, 6, 6, 1, 1);
+ QWhatsThis::add(d->dateReleasedSel, i18n("<p>Set here the earliest intended usable date of "
+ "intellectual content."));
+ QWhatsThis::add(d->timeReleasedSel, i18n("<p>Set here the earliest intended usable time of "
+ "intellectual content."));
+
+ // --------------------------------------------------------
+
+ d->dateExpiredCheck = new QCheckBox(i18n("Expiration date"), parent);
+ d->timeExpiredCheck = new QCheckBox(i18n("Expiration time"), parent);
+ d->dateExpiredSel = new KDateWidget(parent);
+ d->timeExpiredSel = new KTimeWidget(parent);
+ d->dateExpiredSel->setDate(QDate::currentDate());
+ d->timeExpiredSel->setTime(QTime::currentTime());
+ grid->addMultiCellWidget(d->dateExpiredCheck, 7, 7, 0, 0);
+ grid->addMultiCellWidget(d->timeExpiredCheck, 7, 7, 1, 2);
+ grid->addMultiCellWidget(d->dateExpiredSel, 8, 8, 0, 0);
+ grid->addMultiCellWidget(d->timeExpiredSel, 8, 8, 1, 1);
+ QWhatsThis::add(d->dateExpiredSel, i18n("<p>Set here the latest intended usable date of "
+ "intellectual content."));
+ QWhatsThis::add(d->timeExpiredSel, i18n("<p>Set here the latest intended usable time of "
+ "intellectual content."));
+
+ // --------------------------------------------------------
+
+ d->dateDigitalizedCheck = new QCheckBox(i18n("Digitization date"), parent);
+ d->timeDigitalizedCheck = new QCheckBox(i18n("Digitization time"), parent);
+ d->dateDigitalizedSel = new KDateWidget(parent);
+ d->timeDigitalizedSel = new KTimeWidget(parent);
+ d->dateDigitalizedSel->setDate(QDate::currentDate());
+ d->timeDigitalizedSel->setTime(QTime::currentTime());
+ grid->addMultiCellWidget(d->dateDigitalizedCheck, 9, 9, 0, 0);
+ grid->addMultiCellWidget(d->timeDigitalizedCheck, 9, 9, 1, 2);
+ grid->addMultiCellWidget(d->dateDigitalizedSel, 10, 10, 0, 0);
+ grid->addMultiCellWidget(d->timeDigitalizedSel, 10, 10, 1, 1);
+ QWhatsThis::add(d->dateDigitalizedSel, i18n("<p>Set here the creation date of "
+ "digital representation."));
+ QWhatsThis::add(d->timeDigitalizedSel, i18n("<p>Set here the creation time of "
+ "digital representation."));
+
+ grid->setColStretch(2, 10);
+ grid->setRowStretch(11, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->dateCreatedCheck, SIGNAL(toggled(bool)),
+ d->dateCreatedSel, SLOT(setEnabled(bool)));
+
+ connect(d->dateReleasedCheck, SIGNAL(toggled(bool)),
+ d->dateReleasedSel, SLOT(setEnabled(bool)));
+
+ connect(d->dateExpiredCheck, SIGNAL(toggled(bool)),
+ d->dateExpiredSel, SLOT(setEnabled(bool)));
+
+ connect(d->dateDigitalizedCheck, SIGNAL(toggled(bool)),
+ d->dateDigitalizedSel, SLOT(setEnabled(bool)));
+
+ connect(d->timeCreatedCheck, SIGNAL(toggled(bool)),
+ d->timeCreatedSel, SLOT(setEnabled(bool)));
+
+ connect(d->timeReleasedCheck, SIGNAL(toggled(bool)),
+ d->timeReleasedSel, SLOT(setEnabled(bool)));
+
+ connect(d->timeExpiredCheck, SIGNAL(toggled(bool)),
+ d->timeExpiredSel, SLOT(setEnabled(bool)));
+
+ connect(d->timeDigitalizedCheck, SIGNAL(toggled(bool)),
+ d->timeDigitalizedSel, SLOT(setEnabled(bool)));
+
+ connect(d->dateCreatedCheck, SIGNAL(toggled(bool)),
+ d->syncHOSTDateCheck, SLOT(setEnabled(bool)));
+
+ connect(d->dateCreatedCheck, SIGNAL(toggled(bool)),
+ d->syncEXIFDateCheck, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->dateCreatedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateReleasedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateExpiredCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateDigitalizedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->timeCreatedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->timeReleasedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->timeExpiredCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->timeDigitalizedCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->dateCreatedSel, SIGNAL(changed(QDate)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateReleasedSel, SIGNAL(changed(QDate)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateExpiredSel, SIGNAL(changed(QDate)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->dateDigitalizedSel, SIGNAL(changed(QDate)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->timeCreatedSel, SIGNAL(valueChanged(const QTime &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->timeReleasedSel, SIGNAL(valueChanged(const QTime &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->timeExpiredSel, SIGNAL(valueChanged(const QTime &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->timeDigitalizedSel, SIGNAL(valueChanged(const QTime &)),
+ this, SIGNAL(signalModified()));
+}
+
+IPTCDateTime::~IPTCDateTime()
+{
+ delete d;
+}
+
+bool IPTCDateTime::syncHOSTDateIsChecked()
+{
+ return d->syncHOSTDateCheck->isChecked();
+}
+
+bool IPTCDateTime::syncEXIFDateIsChecked()
+{
+ return d->syncEXIFDateCheck->isChecked();
+}
+
+void IPTCDateTime::setCheckedSyncHOSTDate(bool c)
+{
+ d->syncHOSTDateCheck->setChecked(c);
+}
+
+void IPTCDateTime::setCheckedSyncEXIFDate(bool c)
+{
+ d->syncEXIFDateCheck->setChecked(c);
+}
+
+QDateTime IPTCDateTime::getIPTCCreationDate()
+{
+ return QDateTime(d->dateCreatedSel->date(), d->timeCreatedSel->time());
+}
+
+void IPTCDateTime::readMetadata(QByteArray& iptcData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+
+ QDate date;
+ QTime time;
+ QString dateStr, timeStr;
+
+ dateStr = exiv2Iface.getIptcTagString("Iptc.Application2.DateCreated", false);
+ timeStr = exiv2Iface.getIptcTagString("Iptc.Application2.TimeCreated", false);
+
+ d->dateCreatedSel->setDate(QDate::currentDate());
+ d->dateCreatedCheck->setChecked(false);
+ if (!dateStr.isEmpty())
+ {
+ date = QDate::fromString(dateStr, Qt::ISODate);
+ if (date.isValid())
+ {
+ d->dateCreatedSel->setDate(date);
+ d->dateCreatedCheck->setChecked(true);
+ }
+ }
+ d->dateCreatedSel->setEnabled(d->dateCreatedCheck->isChecked());
+ d->syncHOSTDateCheck->setEnabled(d->dateCreatedCheck->isChecked());
+ d->syncEXIFDateCheck->setEnabled(d->dateCreatedCheck->isChecked());
+
+ d->timeCreatedSel->setTime(QTime::currentTime());
+ d->timeCreatedCheck->setChecked(false);
+ if (!timeStr.isEmpty())
+ {
+ time = QTime::fromString(timeStr, Qt::ISODate);
+ if (time.isValid())
+ {
+ d->timeCreatedSel->setTime(time);
+ d->timeCreatedCheck->setChecked(true);
+ }
+ }
+ d->timeCreatedSel->setEnabled(d->timeCreatedCheck->isChecked());
+
+ dateStr = exiv2Iface.getIptcTagString("Iptc.Application2.ReleaseDate", false);
+ timeStr = exiv2Iface.getIptcTagString("Iptc.Application2.ReleaseTime", false);
+
+ d->dateReleasedSel->setDate(QDate::currentDate());
+ d->dateReleasedCheck->setChecked(false);
+ if (!dateStr.isEmpty())
+ {
+ date = QDate::fromString(dateStr, Qt::ISODate);
+ if (date.isValid())
+ {
+ d->dateReleasedSel->setDate(date);
+ d->dateReleasedCheck->setChecked(true);
+ }
+ }
+ d->dateReleasedSel->setEnabled(d->dateReleasedCheck->isChecked());
+
+ d->timeReleasedSel->setTime(QTime::currentTime());
+ d->timeReleasedCheck->setChecked(false);
+ if (!timeStr.isEmpty())
+ {
+ time = QTime::fromString(timeStr, Qt::ISODate);
+ if (time.isValid())
+ {
+ d->timeReleasedSel->setTime(time);
+ d->timeReleasedCheck->setChecked(true);
+ }
+ }
+ d->timeReleasedSel->setEnabled(d->timeReleasedCheck->isChecked());
+
+ dateStr = exiv2Iface.getIptcTagString("Iptc.Application2.ExpirationDate", false);
+ timeStr = exiv2Iface.getIptcTagString("Iptc.Application2.ExpirationTime", false);
+
+ d->dateExpiredSel->setDate(QDate::currentDate());
+ d->dateExpiredCheck->setChecked(false);
+ if (!dateStr.isEmpty())
+ {
+ date = QDate::fromString(dateStr, Qt::ISODate);
+ if (date.isValid())
+ {
+ d->dateExpiredSel->setDate(date);
+ d->dateExpiredCheck->setChecked(true);
+ }
+ }
+ d->dateExpiredSel->setEnabled(d->dateExpiredCheck->isChecked());
+
+ d->timeExpiredSel->setTime(QTime::currentTime());
+ d->timeExpiredCheck->setChecked(false);
+ if (!timeStr.isEmpty())
+ {
+ time = QTime::fromString(timeStr, Qt::ISODate);
+ if (time.isValid())
+ {
+ d->timeExpiredSel->setTime(time);
+ d->timeExpiredCheck->setChecked(true);
+ }
+ }
+ d->timeExpiredSel->setEnabled(d->timeExpiredCheck->isChecked());
+
+ dateStr = exiv2Iface.getIptcTagString("Iptc.Application2.DigitizationDate", false);
+ timeStr = exiv2Iface.getIptcTagString("Iptc.Application2.DigitizationTime", false);
+
+ d->dateDigitalizedSel->setDate(QDate::currentDate());
+ d->dateDigitalizedCheck->setChecked(false);
+ if (!dateStr.isEmpty())
+ {
+ date = QDate::fromString(dateStr, Qt::ISODate);
+ if (date.isValid())
+ {
+ d->dateDigitalizedSel->setDate(date);
+ d->dateDigitalizedCheck->setChecked(true);
+ }
+ }
+ d->dateDigitalizedSel->setEnabled(d->dateDigitalizedCheck->isChecked());
+
+ d->timeDigitalizedSel->setTime(QTime::currentTime());
+ d->timeDigitalizedCheck->setChecked(false);
+ if (!timeStr.isEmpty())
+ {
+ time = QTime::fromString(timeStr, Qt::ISODate);
+ if (time.isValid())
+ {
+ d->timeDigitalizedSel->setTime(time);
+ d->timeDigitalizedCheck->setChecked(true);
+ }
+ }
+ d->timeDigitalizedSel->setEnabled(d->timeDigitalizedCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void IPTCDateTime::applyMetadata(QByteArray& exifData, QByteArray& iptcData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setExif(exifData);
+ exiv2Iface.setIptc(iptcData);
+
+ if (d->dateCreatedCheck->isChecked())
+ {
+ exiv2Iface.setIptcTagString("Iptc.Application2.DateCreated",
+ d->dateCreatedSel->date().toString(Qt::ISODate));
+ if (syncEXIFDateIsChecked())
+ {
+ exiv2Iface.setExifTagString("Exif.Image.DateTime",
+ getIPTCCreationDate().toString(QString("yyyy:MM:dd hh:mm:ss")).ascii());
+ }
+ }
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.DateCreated");
+
+ if (d->dateReleasedCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.ReleaseDate",
+ d->dateReleasedSel->date().toString(Qt::ISODate));
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.ReleaseDate");
+
+ if (d->dateExpiredCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.ExpirationDate",
+ d->dateExpiredSel->date().toString(Qt::ISODate));
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.ExpirationDate");
+
+ if (d->dateDigitalizedCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.DigitizationDate",
+ d->dateDigitalizedSel->date().toString(Qt::ISODate));
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.DigitizationDate");
+
+ if (d->timeCreatedCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.TimeCreated",
+ d->timeCreatedSel->time().toString(Qt::ISODate));
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.TimeCreated");
+
+ if (d->timeReleasedCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.ReleaseTime",
+ d->timeReleasedSel->time().toString(Qt::ISODate));
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.ReleaseTime");
+
+ if (d->timeExpiredCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.ExpirationTime",
+ d->timeExpiredSel->time().toString(Qt::ISODate));
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.ExpirationTime");
+
+ if (d->timeDigitalizedCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.DigitizationTime",
+ d->timeDigitalizedSel->time().toString(Qt::ISODate));
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.DigitizationTime");
+
+ exifData = exiv2Iface.getExif();
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/iptcdatetime.h b/kipi-plugins/metadataedit/iptcdatetime.h
new file mode 100644
index 0000000..b30ffb5
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptcdatetime.h
@@ -0,0 +1,67 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : IPTC date and time settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IPTC_DATETIME_H
+#define IPTC_DATETIME_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCDateTimePriv;
+
+class IPTCDateTime : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ IPTCDateTime(QWidget* parent);
+ ~IPTCDateTime();
+
+ void applyMetadata(QByteArray& exifData, QByteArray& iptcData);
+ void readMetadata(QByteArray& iptcData);
+
+ bool syncHOSTDateIsChecked();
+ bool syncEXIFDateIsChecked();
+
+ void setCheckedSyncHOSTDate(bool c);
+ void setCheckedSyncEXIFDate(bool c);
+
+ QDateTime getIPTCCreationDate();
+
+signals:
+
+ void signalModified();
+
+private:
+
+ IPTCDateTimePriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // IPTC_DATETIME_H
diff --git a/kipi-plugins/metadataedit/iptceditdialog.cpp b/kipi-plugins/metadataedit/iptceditdialog.cpp
new file mode 100644
index 0000000..4713aea
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptceditdialog.cpp
@@ -0,0 +1,412 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : a dialog to edit IPTC metadata
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qtimer.h>
+#include <qframe.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+
+// LibKIPI includes.
+
+#include <libkipi/imagecollection.h>
+#include <libkipi/plugin.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "iptccaption.h"
+#include "iptccredits.h"
+#include "iptcstatus.h"
+#include "iptcorigin.h"
+#include "iptcdatetime.h"
+#include "iptckeywords.h"
+#include "iptcsubjects.h"
+#include "iptccategories.h"
+#include "iptceditdialog.h"
+#include "iptceditdialog.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCEditDialogDialogPrivate
+{
+
+public:
+
+ IPTCEditDialogDialogPrivate()
+ {
+ modified = false;
+ isReadOnly = false;
+ page_caption = 0;
+ page_datetime = 0;
+ page_subjects = 0;
+ page_keywords = 0;
+ page_categories = 0;
+ page_credits = 0;
+ page_status = 0;
+ page_origin = 0;
+
+ about = 0;
+
+ captionPage = 0;
+ datetimePage = 0;
+ subjectsPage = 0;
+ keywordsPage = 0;
+ categoriesPage = 0;
+ creditsPage = 0;
+ statusPage = 0;
+ originPage = 0;
+ }
+
+ bool modified;
+ bool isReadOnly;
+
+ QByteArray exifData;
+ QByteArray iptcData;
+
+ QFrame *page_caption;
+ QFrame *page_datetime;
+ QFrame *page_subjects;
+ QFrame *page_keywords;
+ QFrame *page_categories;
+ QFrame *page_credits;
+ QFrame *page_status;
+ QFrame *page_origin;
+
+ KURL::List urls;
+
+ KURL::List::iterator currItem;
+
+ IPTCCaption *captionPage;
+ IPTCDateTime *datetimePage;
+ IPTCSubjects *subjectsPage;
+ IPTCKeywords *keywordsPage;
+ IPTCCategories *categoriesPage;
+ IPTCCredits *creditsPage;
+ IPTCStatus *statusPage;
+ IPTCOrigin *originPage;
+
+ KIPI::Interface *interface;
+
+ KIPIPlugins::KPAboutData *about;
+};
+
+IPTCEditDialog::IPTCEditDialog(QWidget* parent, KURL::List urls, KIPI::Interface *iface)
+ : KDialogBase(IconList, QString::null,
+ urls.count() > 1 ? Help|User1|User2|Stretch|Ok|Apply|Close
+ : Help|Stretch|Ok|Apply|Close,
+ Ok, parent, 0, true, true,
+ KStdGuiItem::guiItem(KStdGuiItem::Forward),
+ KStdGuiItem::guiItem(KStdGuiItem::Back) )
+{
+ d = new IPTCEditDialogDialogPrivate;
+ d->urls = urls;
+ d->interface = iface;
+ d->currItem = d->urls.begin();
+
+ // ---------------------------------------------------------------
+
+ d->page_caption = addPage(i18n("Caption"), i18n("Caption Information"),
+ BarIcon("editclear", KIcon::SizeMedium));
+ d->captionPage = new IPTCCaption(d->page_caption);
+
+ d->page_datetime = addPage(i18n("Date & Time"), i18n("Date and Time Information"),
+ BarIcon("today", KIcon::SizeMedium));
+ d->datetimePage = new IPTCDateTime(d->page_datetime);
+
+ d->page_subjects = addPage(i18n("Subjects"), i18n("Subjects Information"),
+ BarIcon("cookie", KIcon::SizeMedium));
+ d->subjectsPage = new IPTCSubjects(d->page_subjects);
+
+ d->page_keywords = addPage(i18n("Keywords"), i18n("Keywords Information"),
+ BarIcon("bookmark", KIcon::SizeMedium));
+ d->keywordsPage = new IPTCKeywords(d->page_keywords);
+
+ d->page_categories = addPage(i18n("Categories"), i18n("Categories Information"),
+ BarIcon("bookmark_folder", KIcon::SizeMedium));
+ d->categoriesPage = new IPTCCategories(d->page_categories);
+
+ d->page_credits = addPage(i18n("Credits"), i18n("Credits Information"),
+ BarIcon("identity", KIcon::SizeMedium));
+ d->creditsPage = new IPTCCredits(d->page_credits);
+
+ d->page_status = addPage(i18n("Status"), i18n("Status Information"),
+ BarIcon("messagebox_info", KIcon::SizeMedium));
+ d->statusPage = new IPTCStatus(d->page_status);
+
+ d->page_origin = addPage(i18n("Origin"), i18n("Origin Information"),
+ BarIcon("www", KIcon::SizeMedium));
+ d->originPage = new IPTCOrigin(d->page_origin);
+
+ // ---------------------------------------------------------------
+ // About data and help button.
+
+ d->about = new KIPIPlugins::KPAboutData(I18N_NOOP("Edit Metadata"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Plugin to edit image metadata"),
+ "(c) 2006-2008, Gilles Caulier");
+
+ d->about->addAuthor("Gilles Caulier", I18N_NOOP("Author and Maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, d->about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"),
+ this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // ------------------------------------------------------------
+
+ connect(d->captionPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->datetimePage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->subjectsPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->keywordsPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->categoriesPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->creditsPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->statusPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ connect(d->originPage, SIGNAL(signalModified()),
+ this, SLOT(slotModified()));
+
+ // ------------------------------------------------------------
+
+ readSettings();
+ slotItemChanged();
+}
+
+IPTCEditDialog::~IPTCEditDialog()
+{
+ delete d->about;
+ delete d;
+}
+
+void IPTCEditDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("metadataedit", "kipi-plugins");
+}
+
+void IPTCEditDialog::closeEvent(QCloseEvent *e)
+{
+ if (!e) return;
+ saveSettings();
+ e->accept();
+}
+
+void IPTCEditDialog::slotClose()
+{
+ saveSettings();
+ KDialogBase::slotClose();
+}
+
+void IPTCEditDialog::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Metadata Edit Settings");
+ showPage(config.readNumEntry("IPTC Edit Page", 0));
+ d->captionPage->setCheckedSyncJFIFComment(config.readBoolEntry("Sync JFIF Comment", true));
+ d->captionPage->setCheckedSyncHOSTComment(config.readBoolEntry("Sync Host Comment", true));
+ d->captionPage->setCheckedSyncEXIFComment(config.readBoolEntry("Sync EXIF Comment", true));
+ d->datetimePage->setCheckedSyncHOSTDate(config.readBoolEntry("Sync Host Date", true));
+ d->datetimePage->setCheckedSyncEXIFDate(config.readBoolEntry("Sync EXIF Date", true));
+ resize(configDialogSize(config, QString("IPTC Edit Dialog")));
+}
+
+void IPTCEditDialog::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Metadata Edit Settings");
+ config.writeEntry("IPTC Edit Page", activePageIndex());
+ config.writeEntry("Sync JFIF Comment", d->captionPage->syncJFIFCommentIsChecked());
+ config.writeEntry("Sync Host Comment", d->captionPage->syncHOSTCommentIsChecked());
+ config.writeEntry("Sync EXIF Comment", d->captionPage->syncEXIFCommentIsChecked());
+ config.writeEntry("Sync Host Date", d->datetimePage->syncHOSTDateIsChecked());
+ config.writeEntry("Sync EXIF Date", d->datetimePage->syncEXIFDateIsChecked());
+ saveDialogSize(config, QString("IPTC Edit Dialog"));
+ config.sync();
+}
+
+void IPTCEditDialog::slotItemChanged()
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.load((*d->currItem).path());
+ d->exifData = exiv2Iface.getExif();
+ d->iptcData = exiv2Iface.getIptc();
+ d->captionPage->readMetadata(d->iptcData);
+ d->datetimePage->readMetadata(d->iptcData);
+ d->subjectsPage->readMetadata(d->iptcData);
+ d->keywordsPage->readMetadata(d->iptcData);
+ d->categoriesPage->readMetadata(d->iptcData);
+ d->creditsPage->readMetadata(d->iptcData);
+ d->statusPage->readMetadata(d->iptcData);
+ d->originPage->readMetadata(d->iptcData);
+
+ d->isReadOnly = KExiv2Iface::KExiv2::isReadOnly((*d->currItem).path());
+ d->page_caption->setEnabled(!d->isReadOnly);
+ d->page_datetime->setEnabled(!d->isReadOnly);
+ d->page_subjects->setEnabled(!d->isReadOnly);
+ d->page_keywords->setEnabled(!d->isReadOnly);
+ d->page_categories->setEnabled(!d->isReadOnly);
+ d->page_credits->setEnabled(!d->isReadOnly);
+ d->page_status->setEnabled(!d->isReadOnly);
+ d->page_origin->setEnabled(!d->isReadOnly);
+ enableButton(Apply, !d->isReadOnly);
+
+ setCaption(QString("%1 (%2/%3) - %4")
+ .arg((*d->currItem).filename())
+ .arg(d->urls.findIndex(*(d->currItem))+1)
+ .arg(d->urls.count())
+ .arg(i18n("Edit IPTC Metadata")) +
+ (d->isReadOnly ? QString(" - ") + i18n("(read only)") : QString::null));
+ enableButton(User1, *(d->currItem) != d->urls.last());
+ enableButton(User2, *(d->currItem) != d->urls.first());
+ enableButton(Apply, false);
+}
+
+void IPTCEditDialog::slotApply()
+{
+ if (d->modified && !d->isReadOnly)
+ {
+ KIPI::ImageInfo info = d->interface->info(*d->currItem);
+
+ if (d->captionPage->syncHOSTCommentIsChecked())
+ {
+ info.setDescription(d->captionPage->getIPTCCaption());
+ }
+ d->captionPage->applyMetadata(d->exifData, d->iptcData);
+
+ if (d->datetimePage->syncHOSTDateIsChecked())
+ {
+ info.setTime(d->datetimePage->getIPTCCreationDate());
+ }
+ d->datetimePage->applyMetadata(d->exifData, d->iptcData);
+
+ d->subjectsPage->applyMetadata(d->iptcData);
+ d->keywordsPage->applyMetadata(d->iptcData);
+ d->categoriesPage->applyMetadata(d->iptcData);
+ d->creditsPage->applyMetadata(d->iptcData);
+ d->statusPage->applyMetadata(d->iptcData);
+ d->originPage->applyMetadata(d->iptcData);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.load((*d->currItem).path());
+ exiv2Iface.setExif(d->exifData);
+ exiv2Iface.setIptc(d->iptcData);
+ exiv2Iface.save((*d->currItem).path());
+ d->modified = false;
+ }
+}
+
+void IPTCEditDialog::slotUser1()
+{
+ slotApply();
+ d->currItem++;
+ slotItemChanged();
+}
+
+void IPTCEditDialog::slotUser2()
+{
+ slotApply();
+ d->currItem--;
+ slotItemChanged();
+}
+
+void IPTCEditDialog::slotModified()
+{
+ if (!d->isReadOnly)
+ {
+ enableButton(Apply, true);
+ d->modified = true;
+ }
+}
+
+void IPTCEditDialog::slotOk()
+{
+ slotApply();
+ saveSettings();
+ accept();
+}
+
+bool IPTCEditDialog::eventFilter(QObject *, QEvent *e)
+{
+ if ( e->type() == QEvent::KeyPress )
+ {
+ QKeyEvent *k = (QKeyEvent *)e;
+
+ if (k->state() == Qt::ControlButton &&
+ (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return))
+ {
+ slotApply();
+
+ if (actionButton(User1)->isEnabled())
+ slotUser1();
+
+ return true;
+ }
+ else if (k->state() == Qt::ShiftButton &&
+ (k->key() == Qt::Key_Enter || k->key() == Qt::Key_Return))
+ {
+ slotApply();
+
+ if (actionButton(User2)->isEnabled())
+ slotUser2();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
+} // namespace KIPIMetadataEditPlugin
diff --git a/kipi-plugins/metadataedit/iptceditdialog.h b/kipi-plugins/metadataedit/iptceditdialog.h
new file mode 100644
index 0000000..7db7df6
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptceditdialog.h
@@ -0,0 +1,83 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : a dialog to edit IPTC metadata
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IPTCEDITDIALOG_H
+#define IPTCEDITDIALOG_H
+
+// Qt includes.
+
+#include <qcstring.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <kurl.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCEditDialogDialogPrivate;
+
+class IPTCEditDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ IPTCEditDialog(QWidget* parent, KURL::List urls, KIPI::Interface *iface);
+ ~IPTCEditDialog();
+
+public slots:
+
+ void slotModified();
+
+protected slots:
+
+ void slotOk();
+ void slotHelp();
+ void slotClose();
+
+protected:
+
+ void closeEvent(QCloseEvent *);
+ bool eventFilter(QObject *, QEvent *);
+
+private slots:
+
+ void slotItemChanged();
+ void slotApply();
+ void slotUser1();
+ void slotUser2();
+
+private:
+
+ void readSettings();
+ void saveSettings();
+
+private:
+
+ IPTCEditDialogDialogPrivate *d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif /* IPTCEDITDIALOG_H */
diff --git a/kipi-plugins/metadataedit/iptckeywords.cpp b/kipi-plugins/metadataedit/iptckeywords.cpp
new file mode 100644
index 0000000..1307cbb
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptckeywords.cpp
@@ -0,0 +1,250 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-15
+ * Description : IPTC keywords settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <klistbox.h>
+#include <klineedit.h>
+#include <kactivelabel.h>
+#include <kiconloader.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "iptckeywords.h"
+#include "iptckeywords.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCKeywordsPriv
+{
+public:
+
+ IPTCKeywordsPriv()
+ {
+ addKeywordButton = 0;
+ delKeywordButton = 0;
+ keywordsBox = 0;
+ keywordsCheck = 0;
+ keywordEdit = 0;
+ }
+
+ QStringList oldKeywords;
+
+ QPushButton *addKeywordButton;
+ QPushButton *delKeywordButton;
+
+ QCheckBox *keywordsCheck;
+
+ KLineEdit *keywordEdit;
+
+ KListBox *keywordsBox;
+};
+
+IPTCKeywords::IPTCKeywords(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new IPTCKeywordsPriv;
+ QGridLayout *grid = new QGridLayout(parent, 5, 2, 0, KDialog::spacingHint());
+ grid->setAlignment( Qt::AlignTop );
+
+ // IPTC only accept printable Ascii char.
+ QRegExp asciiRx("[\x20-\x7F]+$");
+ QValidator *asciiValidator = new QRegExpValidator(asciiRx, this);
+
+ // --------------------------------------------------------
+
+ d->keywordsCheck = new QCheckBox(i18n("Use information retrieval words:"), parent);
+
+ d->keywordEdit = new KLineEdit(parent);
+ d->keywordEdit->setValidator(asciiValidator);
+ d->keywordEdit->setMaxLength(64);
+ QWhatsThis::add(d->keywordEdit, i18n("<p>Enter here a new keyword. "
+ "This field is limited to 64 ASCII characters."));
+
+ d->keywordsBox = new KListBox(parent);
+ d->keywordsBox->setVScrollBarMode(QScrollView::AlwaysOn);
+
+ d->addKeywordButton = new QPushButton( i18n("&Add"), parent);
+ d->delKeywordButton = new QPushButton( i18n("&Delete"), parent);
+ d->addKeywordButton->setIconSet(SmallIcon("add"));
+ d->delKeywordButton->setIconSet(SmallIcon("remove"));
+ d->delKeywordButton->setEnabled(false);
+
+ grid->addMultiCellWidget(d->keywordsCheck, 0, 0, 0, 1);
+ grid->addMultiCellWidget(d->keywordEdit, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->keywordsBox, 2, 5, 0, 0);
+ grid->addMultiCellWidget(d->addKeywordButton, 2, 2, 1, 1);
+ grid->addMultiCellWidget(d->delKeywordButton, 3, 3, 1, 1);
+
+ // --------------------------------------------------------
+
+ KActiveLabel *note = new KActiveLabel(i18n("<b>Note: "
+ "<b><a href='http://en.wikipedia.org/wiki/IPTC'>IPTC</a></b> "
+ "text tags only support the printable "
+ "<b><a href='http://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
+ "characters set and limit strings size. "
+ "Use contextual help for details.</b>"), parent);
+ note->setMaximumWidth(150);
+
+ grid->addMultiCellWidget(note, 4, 4, 1, 1);
+ grid->setColStretch(0, 10);
+ grid->setRowStretch(5, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->keywordsBox, SIGNAL(selectionChanged()),
+ this, SLOT(slotKeywordSelectionChanged()));
+
+ connect(d->addKeywordButton, SIGNAL(clicked()),
+ this, SLOT(slotAddKeyword()));
+
+ connect(d->delKeywordButton, SIGNAL(clicked()),
+ this, SLOT(slotDelKeyword()));
+
+ // --------------------------------------------------------
+
+ connect(d->keywordsCheck, SIGNAL(toggled(bool)),
+ d->keywordEdit, SLOT(setEnabled(bool)));
+
+ connect(d->keywordsCheck, SIGNAL(toggled(bool)),
+ d->keywordsBox, SLOT(setEnabled(bool)));
+
+ connect(d->keywordsCheck, SIGNAL(toggled(bool)),
+ d->addKeywordButton, SLOT(setEnabled(bool)));
+
+ connect(d->keywordsCheck, SIGNAL(toggled(bool)),
+ d->delKeywordButton, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->keywordsCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->addKeywordButton, SIGNAL(clicked()),
+ this, SIGNAL(signalModified()));
+
+ connect(d->delKeywordButton, SIGNAL(clicked()),
+ this, SIGNAL(signalModified()));
+}
+
+IPTCKeywords::~IPTCKeywords()
+{
+ delete d;
+}
+
+void IPTCKeywords::slotDelKeyword()
+{
+ int index = d->keywordsBox->currentItem();
+ if (index == -1)
+ return;
+
+ QListBoxItem* item = d->keywordsBox->item(index);
+ if (!item) return;
+ delete item;
+}
+
+void IPTCKeywords::slotKeywordSelectionChanged()
+{
+ if (d->keywordsBox->currentItem() != -1)
+ d->delKeywordButton->setEnabled(true);
+ else
+ d->delKeywordButton->setEnabled(false);
+}
+
+void IPTCKeywords::slotAddKeyword()
+{
+ QString newKeyword = d->keywordEdit->text();
+ if (newKeyword.isEmpty()) return;
+
+ bool found = false;
+ for (QListBoxItem *item = d->keywordsBox->firstItem();
+ item; item = item->next())
+ {
+ if (newKeyword == item->text())
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ d->keywordsBox->insertItem(newKeyword);
+}
+
+void IPTCKeywords::readMetadata(QByteArray& iptcData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+ d->oldKeywords = exiv2Iface.getImageKeywords();
+
+ d->keywordsBox->clear();
+ d->keywordsCheck->setChecked(false);
+ if (!d->oldKeywords.isEmpty())
+ {
+ d->keywordsBox->insertStringList(d->oldKeywords);
+ d->keywordsCheck->setChecked(true);
+ }
+ d->keywordEdit->setEnabled(d->keywordsCheck->isChecked());
+ d->keywordsBox->setEnabled(d->keywordsCheck->isChecked());
+ d->addKeywordButton->setEnabled(d->keywordsCheck->isChecked());
+ d->delKeywordButton->setEnabled(d->keywordsCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void IPTCKeywords::applyMetadata(QByteArray& iptcData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+ QStringList newKeywords;
+
+ for (QListBoxItem *item = d->keywordsBox->firstItem();
+ item; item = item->next())
+ newKeywords.append(item->text());
+
+ if (d->keywordsCheck->isChecked())
+ exiv2Iface.setImageKeywords(d->oldKeywords, newKeywords);
+ else
+ exiv2Iface.setImageKeywords(d->oldKeywords, QStringList());
+
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/iptckeywords.h b/kipi-plugins/metadataedit/iptckeywords.h
new file mode 100644
index 0000000..3518adb
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptckeywords.h
@@ -0,0 +1,65 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-15
+ * Description : IPTC keywords settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IPTC_KEYWORDS_H
+#define IPTC_KEYWORDS_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCKeywordsPriv;
+
+class IPTCKeywords : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ IPTCKeywords(QWidget* parent);
+ ~IPTCKeywords();
+
+ void applyMetadata(QByteArray& iptcData);
+ void readMetadata(QByteArray& iptcData);
+
+signals:
+
+ void signalModified();
+
+private slots:
+
+ void slotKeywordSelectionChanged();
+ void slotAddKeyword();
+ void slotDelKeyword();
+
+private:
+
+ IPTCKeywordsPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // IPTC_KEYWORDS_H
diff --git a/kipi-plugins/metadataedit/iptcorigin.cpp b/kipi-plugins/metadataedit/iptcorigin.cpp
new file mode 100644
index 0000000..df8d569
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptcorigin.cpp
@@ -0,0 +1,683 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-13
+ * Description : IPTC origin settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qlistbox.h>
+#include <qcombobox.h>
+#include <qmap.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <klineedit.h>
+#include <kactivelabel.h>
+#include <kseparator.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "metadatacheckbox.h"
+#include "iptcorigin.h"
+#include "iptcorigin.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCOriginPriv
+{
+public:
+
+ IPTCOriginPriv()
+ {
+ objectNameEdit = 0;
+ cityEdit = 0;
+ sublocationEdit = 0;
+ provinceEdit = 0;
+ locationEdit = 0;
+ originalTransEdit = 0;
+ objectNameCheck = 0;
+ cityCheck = 0;
+ sublocationCheck = 0;
+ provinceCheck = 0;
+ countryCheck = 0;
+ locationCheck = 0;
+ originalTransCheck = 0;
+
+ // Standard ISO 3166 country codes.
+
+ countryCodeMap.insert( "AFG", i18n("Afghanistan") );
+ countryCodeMap.insert( "ALB", i18n("Albania") );
+ countryCodeMap.insert( "DZA", i18n("Algeria") );
+ countryCodeMap.insert( "ASM", i18n("American Samoa") );
+ countryCodeMap.insert( "AND", i18n("Andorra") );
+ countryCodeMap.insert( "AGO", i18n("Angola") );
+ countryCodeMap.insert( "AIA", i18n("Anguilla") );
+ countryCodeMap.insert( "AGO", i18n("Angola") );
+ countryCodeMap.insert( "ATA", i18n("Antarctica") );
+ countryCodeMap.insert( "ATG", i18n("Antigua and Barbuda") );
+ countryCodeMap.insert( "ARG", i18n("Argentina") );
+ countryCodeMap.insert( "ARM", i18n("Armenia") );
+ countryCodeMap.insert( "ABW", i18n("Aruba") );
+ countryCodeMap.insert( "AUS", i18n("Australia") );
+ countryCodeMap.insert( "AUT", i18n("Austria") );
+ countryCodeMap.insert( "AZE", i18n("Azerbaijan") );
+ countryCodeMap.insert( "BHS", i18n("Bahamas") );
+ countryCodeMap.insert( "BHR", i18n("Bahrain") );
+ countryCodeMap.insert( "BGD", i18n("Bangladesh") );
+ countryCodeMap.insert( "BRB", i18n("Barbados") );
+ countryCodeMap.insert( "BLR", i18n("Belarus") );
+ countryCodeMap.insert( "BEL", i18n("Belgium") );
+ countryCodeMap.insert( "BLZ", i18n("Belize") );
+ countryCodeMap.insert( "BEN", i18n("Benin") );
+ countryCodeMap.insert( "BMU", i18n("Bermuda") );
+ countryCodeMap.insert( "BTN", i18n("Bhutan") );
+ countryCodeMap.insert( "BOL", i18n("Bolivia") );
+ countryCodeMap.insert( "BIH", i18n("Bosnia and Herzegovina") );
+ countryCodeMap.insert( "BWA", i18n("Botswana") );
+ countryCodeMap.insert( "BVT", i18n("Bouvet Island") );
+ countryCodeMap.insert( "BRA", i18n("Brazil") );
+ countryCodeMap.insert( "IOT", i18n("British Indian Ocean Territory") );
+ countryCodeMap.insert( "VGB", i18n("British Virgin Islands") );
+ countryCodeMap.insert( "BRN", i18n("Brunei Darussalam") );
+ countryCodeMap.insert( "BGR", i18n("Bulgaria") );
+ countryCodeMap.insert( "BFA", i18n("Burkina Faso") );
+ countryCodeMap.insert( "BDI", i18n("Burundi") );
+ countryCodeMap.insert( "KHM", i18n("Cambodia") );
+ countryCodeMap.insert( "CMR", i18n("Cameroon") );
+ countryCodeMap.insert( "CAN", i18n("Canada") );
+ countryCodeMap.insert( "CPV", i18n("Cape Verde") );
+ countryCodeMap.insert( "CYM", i18n("Cayman Islands") );
+ countryCodeMap.insert( "CAF", i18n("Central African Republic") );
+ countryCodeMap.insert( "TCD", i18n("Chad") );
+ countryCodeMap.insert( "CHL", i18n("Chile") );
+ countryCodeMap.insert( "CHN", i18n("China") );
+ countryCodeMap.insert( "CXR", i18n("Christmas Island ") );
+ countryCodeMap.insert( "CCK", i18n("Cocos Islands") );
+ countryCodeMap.insert( "COL", i18n("Colombia") );
+ countryCodeMap.insert( "COM", i18n("Comoros") );
+ countryCodeMap.insert( "COD", i18n("Zaire") );
+ countryCodeMap.insert( "COG", i18n("Congo") );
+ countryCodeMap.insert( "COK", i18n("Cook Islands") );
+ countryCodeMap.insert( "CRI", i18n("Costa Rica") );
+ countryCodeMap.insert( "CIV", i18n("Ivory Coast") );
+ countryCodeMap.insert( "CUB", i18n("Cuba") );
+ countryCodeMap.insert( "CYP", i18n("Cyprus") );
+ countryCodeMap.insert( "CZE", i18n("Czech Republic") );
+ countryCodeMap.insert( "DNK", i18n("Denmark") );
+ countryCodeMap.insert( "DJI", i18n("Djibouti") );
+ countryCodeMap.insert( "DMA", i18n("Dominica") );
+ countryCodeMap.insert( "DOM", i18n("Dominican Republic") );
+ countryCodeMap.insert( "ECU", i18n("Ecuador") );
+ countryCodeMap.insert( "EGY", i18n("Egypt") );
+ countryCodeMap.insert( "SLV", i18n("El Salvador") );
+ countryCodeMap.insert( "GNQ", i18n("Equatorial Guinea") );
+ countryCodeMap.insert( "ERI", i18n("Eritrea") );
+ countryCodeMap.insert( "EST", i18n("Estonia") );
+ countryCodeMap.insert( "ETH", i18n("Ethiopia") );
+ countryCodeMap.insert( "FRO", i18n("Faeroe Islands") );
+ countryCodeMap.insert( "FLK", i18n("Falkland Islands") );
+ countryCodeMap.insert( "FJI", i18n("Fiji Islands") );
+ countryCodeMap.insert( "FIN", i18n("Finland") );
+ countryCodeMap.insert( "FRA", i18n("France") );
+ countryCodeMap.insert( "GUF", i18n("French Guiana") );
+ countryCodeMap.insert( "PYF", i18n("French Polynesia") );
+ countryCodeMap.insert( "ATF", i18n("French Southern Territories") );
+ countryCodeMap.insert( "GAB", i18n("Gabon") );
+ countryCodeMap.insert( "GMB", i18n("Gambia") );
+ countryCodeMap.insert( "GEO", i18n("Georgia") );
+ countryCodeMap.insert( "DEU", i18n("Germany") );
+ countryCodeMap.insert( "GHA", i18n("Ghana") );
+ countryCodeMap.insert( "GIB", i18n("Gibraltar") );
+ countryCodeMap.insert( "GRC", i18n("Greece") );
+ countryCodeMap.insert( "GRL", i18n("Greenland") );
+ countryCodeMap.insert( "GRD", i18n("Grenada") );
+ countryCodeMap.insert( "GLP", i18n("Guadaloupe") );
+ countryCodeMap.insert( "GUM", i18n("Guam") );
+ countryCodeMap.insert( "GTM", i18n("Guatemala") );
+ countryCodeMap.insert( "GIN", i18n("Guinea") );
+ countryCodeMap.insert( "GNB", i18n("Guinea-Bissau") );
+ countryCodeMap.insert( "GUY", i18n("Guyana") );
+ countryCodeMap.insert( "HTI", i18n("Haiti") );
+ countryCodeMap.insert( "HMD", i18n("Heard and McDonald Islands") );
+ countryCodeMap.insert( "VAT", i18n("Vatican") );
+ countryCodeMap.insert( "HND", i18n("Honduras") );
+ countryCodeMap.insert( "HKG", i18n("Hong Kong") );
+ countryCodeMap.insert( "HRV", i18n("Croatia") );
+ countryCodeMap.insert( "HUN", i18n("Hungary") );
+ countryCodeMap.insert( "ISL", i18n("Iceland") );
+ countryCodeMap.insert( "IND", i18n("India") );
+ countryCodeMap.insert( "IDN", i18n("Indonesia") );
+ countryCodeMap.insert( "IRN", i18n("Iran") );
+ countryCodeMap.insert( "IRQ", i18n("Iraq") );
+ countryCodeMap.insert( "IRL", i18n("Ireland") );
+ countryCodeMap.insert( "ISR", i18n("Israel") );
+ countryCodeMap.insert( "ITA", i18n("Italy") );
+ countryCodeMap.insert( "JAM", i18n("Jamaica") );
+ countryCodeMap.insert( "JPN", i18n("Japan") );
+ countryCodeMap.insert( "JOR", i18n("Jordan") );
+ countryCodeMap.insert( "KAZ", i18n("Kazakhstan") );
+ countryCodeMap.insert( "KEN", i18n("Kenya") );
+ countryCodeMap.insert( "KIR", i18n("Kiribati") );
+ countryCodeMap.insert( "PRK", i18n("Korea") );
+ countryCodeMap.insert( "KOR", i18n("Korea") );
+ countryCodeMap.insert( "KWT", i18n("Kuwait") );
+ countryCodeMap.insert( "KGZ", i18n("Kyrgyz Republic") );
+ countryCodeMap.insert( "LAO", i18n("Lao") );
+ countryCodeMap.insert( "LVA", i18n("Latvia") );
+ countryCodeMap.insert( "LBN", i18n("Lebanon") );
+ countryCodeMap.insert( "LSO", i18n("Lesotho") );
+ countryCodeMap.insert( "LBR", i18n("Liberia") );
+ countryCodeMap.insert( "LBY", i18n("Libyan Arab Jamahiriya") );
+ countryCodeMap.insert( "LIE", i18n("Liechtenstein") );
+ countryCodeMap.insert( "LTU", i18n("Lithuania") );
+ countryCodeMap.insert( "LUX", i18n("Luxembourg") );
+ countryCodeMap.insert( "MAC", i18n("Macao") );
+ countryCodeMap.insert( "MKD", i18n("Macedonia") );
+ countryCodeMap.insert( "MDG", i18n("Madagascar") );
+ countryCodeMap.insert( "MWI", i18n("Malawi") );
+ countryCodeMap.insert( "MYS", i18n("Malaysia") );
+ countryCodeMap.insert( "MDV", i18n("Maldives") );
+ countryCodeMap.insert( "MLI", i18n("Mali") );
+ countryCodeMap.insert( "MLT", i18n("Malta") );
+ countryCodeMap.insert( "MHL", i18n("Marshall Islands") );
+ countryCodeMap.insert( "MTQ", i18n("Martinique") );
+ countryCodeMap.insert( "MRT", i18n("Mauritania") );
+ countryCodeMap.insert( "MUS", i18n("Mauritius") );
+ countryCodeMap.insert( "MYT", i18n("Mayotte") );
+ countryCodeMap.insert( "MEX", i18n("Mexico") );
+ countryCodeMap.insert( "FSM", i18n("Micronesia") );
+ countryCodeMap.insert( "MDA", i18n("Moldova") );
+ countryCodeMap.insert( "MCO", i18n("Monaco") );
+ countryCodeMap.insert( "MNG", i18n("Mongolia") );
+ countryCodeMap.insert( "MSR", i18n("Montserrat") );
+ countryCodeMap.insert( "MAR", i18n("Morocco") );
+ countryCodeMap.insert( "MOZ", i18n("Mozambique") );
+ countryCodeMap.insert( "MMR", i18n("Myanmar") );
+ countryCodeMap.insert( "NAM", i18n("Namibia") );
+ countryCodeMap.insert( "NRU", i18n("Nauru") );
+ countryCodeMap.insert( "NPL", i18n("Nepal") );
+ countryCodeMap.insert( "ANT", i18n("Netherlands Antilles") );
+ countryCodeMap.insert( "NLD", i18n("Netherlands") );
+ countryCodeMap.insert( "NCL", i18n("New Caledonia") );
+ countryCodeMap.insert( "NZL", i18n("New Zealand") );
+ countryCodeMap.insert( "NIC", i18n("Nicaragua") );
+ countryCodeMap.insert( "NER", i18n("Niger") );
+ countryCodeMap.insert( "NGA", i18n("Nigeria") );
+ countryCodeMap.insert( "NIU", i18n("Niue") );
+ countryCodeMap.insert( "NFK", i18n("Norfolk Island") );
+ countryCodeMap.insert( "MNP", i18n("Northern Mariana Islands") );
+ countryCodeMap.insert( "NOR", i18n("Norway") );
+ countryCodeMap.insert( "OMN", i18n("Oman") );
+ countryCodeMap.insert( "PAK", i18n("Pakistan") );
+ countryCodeMap.insert( "PLW", i18n("Palau") );
+ countryCodeMap.insert( "PSE", i18n("Palestinian Territory") );
+ countryCodeMap.insert( "PAN", i18n("Panama") );
+ countryCodeMap.insert( "PNG", i18n("Papua New Guinea") );
+ countryCodeMap.insert( "PRY", i18n("Paraguay") );
+ countryCodeMap.insert( "PER", i18n("Peru") );
+ countryCodeMap.insert( "PHL", i18n("Philippines") );
+ countryCodeMap.insert( "PCN", i18n("Pitcairn Island") );
+ countryCodeMap.insert( "POL", i18n("Poland") );
+ countryCodeMap.insert( "PRT", i18n("Portugal") );
+ countryCodeMap.insert( "PRI", i18n("Puerto Rico") );
+ countryCodeMap.insert( "QAT", i18n("Qatar") );
+ countryCodeMap.insert( "REU", i18n("Reunion") );
+ countryCodeMap.insert( "ROU", i18n("Romania") );
+ countryCodeMap.insert( "RUS", i18n("Russian Federation") );
+ countryCodeMap.insert( "RWA", i18n("Rwanda") );
+ countryCodeMap.insert( "SHN", i18n("St. Helena") );
+ countryCodeMap.insert( "KNA", i18n("St. Kitts and Nevis") );
+ countryCodeMap.insert( "LCA", i18n("St. Lucia") );
+ countryCodeMap.insert( "SPM", i18n("St. Pierre and Miquelon") );
+ countryCodeMap.insert( "VCT", i18n("St. Vincent and the Grenadines") );
+ countryCodeMap.insert( "WSM", i18n("Samoa") );
+ countryCodeMap.insert( "SMR", i18n("San Marino") );
+ countryCodeMap.insert( "STP", i18n("Sao Tome and Principe") );
+ countryCodeMap.insert( "SAU", i18n("Saudi Arabia") );
+ countryCodeMap.insert( "SEN", i18n("Senegal") );
+ countryCodeMap.insert( "SCG", i18n("Serbia and Montenegro") );
+ countryCodeMap.insert( "SYC", i18n("Seychelles") );
+ countryCodeMap.insert( "SLE", i18n("Sierra Leone") );
+ countryCodeMap.insert( "SGP", i18n("Singapore") );
+ countryCodeMap.insert( "SVK", i18n("Slovakia") );
+ countryCodeMap.insert( "SVN", i18n("Slovenia") );
+ countryCodeMap.insert( "SLB", i18n("Solomon Islands") );
+ countryCodeMap.insert( "SOM", i18n("Somalia") );
+ countryCodeMap.insert( "ZAF", i18n("South Africa") );
+ countryCodeMap.insert( "SGS", i18n("South Georgia and the South Sandwich Islands") );
+ countryCodeMap.insert( "ESP", i18n("Spain") );
+ countryCodeMap.insert( "LKA", i18n("Sri Lanka") );
+ countryCodeMap.insert( "SDN", i18n("Sudan") );
+ countryCodeMap.insert( "SUR", i18n("Suriname") );
+ countryCodeMap.insert( "SJM", i18n("Svalbard & Jan Mayen Islands") );
+ countryCodeMap.insert( "SWZ", i18n("Swaziland") );
+ countryCodeMap.insert( "SWE", i18n("Sweden") );
+ countryCodeMap.insert( "CHE", i18n("Switzerland") );
+ countryCodeMap.insert( "SYR", i18n("Syrian Arab Republic") );
+ countryCodeMap.insert( "TWN", i18n("Taiwan") );
+ countryCodeMap.insert( "TJK", i18n("Tajikistan") );
+ countryCodeMap.insert( "TZA", i18n("Tanzania") );
+ countryCodeMap.insert( "THA", i18n("Thailand") );
+ countryCodeMap.insert( "TLS", i18n("Timor-Leste") );
+ countryCodeMap.insert( "TGO", i18n("Togo") );
+ countryCodeMap.insert( "TKL", i18n("Tokelau Islands") );
+ countryCodeMap.insert( "TON", i18n("Tonga") );
+ countryCodeMap.insert( "TTO", i18n("Trinidad and Tobago") );
+ countryCodeMap.insert( "TUN", i18n("Tunisia") );
+ countryCodeMap.insert( "TUR", i18n("Turkey") );
+ countryCodeMap.insert( "TKM", i18n("Turkmenistan") );
+ countryCodeMap.insert( "TCA", i18n("Turks and Caicos Islands") );
+ countryCodeMap.insert( "TUV", i18n("Tuvalu") );
+ countryCodeMap.insert( "VIR", i18n("US Virgin Islands") );
+ countryCodeMap.insert( "UGA", i18n("Uganda") );
+ countryCodeMap.insert( "UKR", i18n("Ukraine") );
+ countryCodeMap.insert( "ARE", i18n("United Arab Emirates") );
+ countryCodeMap.insert( "GBR", i18n("United Kingdom") );
+ countryCodeMap.insert( "UMI", i18n("United States Minor Outlying Islands") );
+ countryCodeMap.insert( "USA", i18n("United States of America") );
+ countryCodeMap.insert( "URY", i18n("Uruguay, Eastern Republic of") );
+ countryCodeMap.insert( "UZB", i18n("Uzbekistan") );
+ countryCodeMap.insert( "VUT", i18n("Vanuatu") );
+ countryCodeMap.insert( "VEN", i18n("Venezuela") );
+ countryCodeMap.insert( "VNM", i18n("Viet Nam") );
+ countryCodeMap.insert( "WLF", i18n("Wallis and Futuna Islands ") );
+ countryCodeMap.insert( "ESH", i18n("Western Sahara") );
+ countryCodeMap.insert( "YEM", i18n("Yemen") );
+ countryCodeMap.insert( "ZMB", i18n("Zambia") );
+ countryCodeMap.insert( "ZWE", i18n("Zimbabwe") );
+
+ // Supplemental IPTC country codes.
+
+ countryCodeMap.insert( "XUN", i18n("United Nations") );
+ countryCodeMap.insert( "XEU", i18n("European Union") );
+ countryCodeMap.insert( "XSP", i18n("Space") );
+ countryCodeMap.insert( "XSE", i18n("At Sea") );
+ countryCodeMap.insert( "XIF", i18n("In Flight") );
+ countryCodeMap.insert( "XEN", i18n("England") );
+ countryCodeMap.insert( "XSC", i18n("Scotland") );
+ countryCodeMap.insert( "XNI", i18n("Northern Ireland") );
+ countryCodeMap.insert( "XWA", i18n("Wales") );
+ countryCodeMap.insert( "PSE", i18n("Palestine") );
+ countryCodeMap.insert( "GZA", i18n("Gaza") );
+ countryCodeMap.insert( "JRO", i18n("Jericho") );
+ }
+
+ typedef QMap<QString, QString> CountryCodeMap;
+
+ CountryCodeMap countryCodeMap;
+
+ QComboBox *countryCB;
+
+ QCheckBox *objectNameCheck;
+ QCheckBox *cityCheck;
+ QCheckBox *sublocationCheck;
+ QCheckBox *provinceCheck;
+ QCheckBox *locationCheck;
+ QCheckBox *originalTransCheck;
+
+ KLineEdit *objectNameEdit;
+ KLineEdit *cityEdit;
+ KLineEdit *sublocationEdit;
+ KLineEdit *provinceEdit;
+ KLineEdit *locationEdit;
+ KLineEdit *originalTransEdit;
+
+ MetadataCheckBox *countryCheck;
+};
+
+IPTCOrigin::IPTCOrigin(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new IPTCOriginPriv;
+
+ QGridLayout* grid = new QGridLayout(parent, 12, 2, KDialog::spacingHint());
+
+ // IPTC only accept printable Ascii char.
+ QRegExp asciiRx("[\x20-\x7F]+$");
+ QValidator *asciiValidator = new QRegExpValidator(asciiRx, this);
+
+ // --------------------------------------------------------
+
+ d->objectNameCheck = new QCheckBox(i18n("Object name:"), parent);
+ d->objectNameEdit = new KLineEdit(parent);
+ d->objectNameEdit->setValidator(asciiValidator);
+ d->objectNameEdit->setMaxLength(64);
+ QWhatsThis::add(d->objectNameEdit, i18n("<p>Set here the shorthand reference of content. "
+ "This field is limited to 64 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->locationCheck = new QCheckBox(i18n("Location:"), parent);
+ d->locationEdit = new KLineEdit(parent);
+ d->locationEdit->setValidator(asciiValidator);
+ d->locationEdit->setMaxLength(64);
+ QWhatsThis::add(d->locationEdit, i18n("<p>Set here the full country name referenced by the content. "
+ "This field is limited to 64 ASCII characters."));
+
+
+ // --------------------------------------------------------
+
+ d->cityCheck = new QCheckBox(i18n("City:"), parent);
+ d->cityEdit = new KLineEdit(parent);
+ d->cityEdit->setValidator(asciiValidator);
+ d->cityEdit->setMaxLength(32);
+ QWhatsThis::add(d->cityEdit, i18n("<p>Set here the city of content origin. "
+ "This field is limited to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->sublocationCheck = new QCheckBox(i18n("Sublocation:"), parent);
+ d->sublocationEdit = new KLineEdit(parent);
+ d->sublocationEdit->setValidator(asciiValidator);
+ d->sublocationEdit->setMaxLength(32);
+ QWhatsThis::add(d->sublocationEdit, i18n("<p>Set here the content location within city. "
+ "This field is limited to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->provinceCheck = new QCheckBox(i18n("State/Province:"), parent);
+ d->provinceEdit = new KLineEdit(parent);
+ d->provinceEdit->setValidator(asciiValidator);
+ d->provinceEdit->setMaxLength(32);
+ QWhatsThis::add(d->provinceEdit, i18n("<p>Set here the Province or State of content origin. "
+ "This field is limited to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->countryCheck = new MetadataCheckBox(i18n("Country:"), parent);
+ d->countryCB = new QComboBox(false, parent);
+
+ for (IPTCOriginPriv::CountryCodeMap::Iterator it = d->countryCodeMap.begin();
+ it != d->countryCodeMap.end(); ++it )
+ d->countryCB->insertItem(QString("%1 - %2").arg(it.key()).arg(it.data()));
+
+ d->countryCB->listBox()->sort();
+
+ QWhatsThis::add(d->countryCB, i18n("<p>Select here country name of content origin."));
+
+ // --------------------------------------------------------
+
+ d->originalTransCheck = new QCheckBox(i18n("Original transmission reference:"), parent);
+ d->originalTransEdit = new KLineEdit(parent);
+ d->originalTransEdit->setValidator(asciiValidator);
+ d->originalTransEdit->setMaxLength(32);
+ QWhatsThis::add(d->originalTransEdit, i18n("<p>Set here the location of original content transmission. "
+ "This field is limited to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ KActiveLabel *note = new KActiveLabel(i18n("<b>Note: "
+ "<b><a href='http://en.wikipedia.org/wiki/IPTC'>IPTC</a></b> "
+ "text tags only support the printable "
+ "<b><a href='http://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
+ "characters set and limit strings size. "
+ "Use contextual help for details.</b>"), parent);
+
+ // --------------------------------------------------------
+
+ grid->addMultiCellWidget(d->objectNameCheck, 0, 0, 0, 2);
+ grid->addMultiCellWidget(d->objectNameEdit, 1, 1, 0, 2);
+ grid->addMultiCellWidget(d->locationCheck, 2, 2, 0, 0);
+ grid->addMultiCellWidget(d->locationEdit, 2, 2, 1, 2);
+ grid->addMultiCellWidget(new KSeparator(Qt::Horizontal, parent), 3, 3, 0, 2);
+ grid->addMultiCellWidget(d->cityCheck, 4, 4, 0, 0);
+ grid->addMultiCellWidget(d->cityEdit, 4, 4, 1, 2);
+ grid->addMultiCellWidget(d->sublocationCheck, 5, 5, 0, 0);
+ grid->addMultiCellWidget(d->sublocationEdit, 5, 5, 1, 2);
+ grid->addMultiCellWidget(d->provinceCheck, 6, 6, 0, 0);
+ grid->addMultiCellWidget(d->provinceEdit, 6, 6, 1, 2);
+ grid->addMultiCellWidget(d->countryCheck, 7, 7, 0, 0);
+ grid->addMultiCellWidget(d->countryCB, 7, 7, 1, 2);
+ grid->addMultiCellWidget(new KSeparator(Qt::Horizontal, parent), 8, 8, 0, 2);
+ grid->addMultiCellWidget(d->originalTransCheck, 9, 9, 0, 2);
+ grid->addMultiCellWidget(d->originalTransEdit, 10, 10, 0, 2);
+ grid->addMultiCellWidget(note, 11, 11, 0, 2);
+ grid->setColStretch(2, 10);
+ grid->setRowStretch(12, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->objectNameCheck, SIGNAL(toggled(bool)),
+ d->objectNameEdit, SLOT(setEnabled(bool)));
+
+ connect(d->cityCheck, SIGNAL(toggled(bool)),
+ d->cityEdit, SLOT(setEnabled(bool)));
+
+ connect(d->sublocationCheck, SIGNAL(toggled(bool)),
+ d->sublocationEdit, SLOT(setEnabled(bool)));
+
+ connect(d->provinceCheck, SIGNAL(toggled(bool)),
+ d->provinceEdit, SLOT(setEnabled(bool)));
+
+ connect(d->countryCheck, SIGNAL(toggled(bool)),
+ d->countryCB, SLOT(setEnabled(bool)));
+
+ connect(d->locationCheck, SIGNAL(toggled(bool)),
+ d->locationEdit, SLOT(setEnabled(bool)));
+
+ connect(d->originalTransCheck, SIGNAL(toggled(bool)),
+ d->originalTransEdit, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->objectNameCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->cityCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sublocationCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->provinceCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->countryCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->locationCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->originalTransCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->countryCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectNameEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->cityEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->sublocationEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->provinceEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->locationEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->originalTransEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+}
+
+IPTCOrigin::~IPTCOrigin()
+{
+ delete d;
+}
+
+void IPTCOrigin::readMetadata(QByteArray& iptcData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+ QString data;
+
+ d->objectNameEdit->clear();
+ d->objectNameCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.ObjectName", false);
+ if (!data.isNull())
+ {
+ d->objectNameEdit->setText(data);
+ d->objectNameCheck->setChecked(true);
+ }
+ d->objectNameEdit->setEnabled(d->objectNameCheck->isChecked());
+
+ d->locationEdit->clear();
+ d->locationCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.LocationName", false);
+ if (!data.isNull())
+ {
+ d->locationEdit->setText(data);
+ d->locationCheck->setChecked(true);
+ }
+ d->locationEdit->setEnabled(d->locationCheck->isChecked());
+
+ d->cityEdit->clear();
+ d->cityCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.City", false);
+ if (!data.isNull())
+ {
+ d->cityEdit->setText(data);
+ d->cityCheck->setChecked(true);
+ }
+ d->cityEdit->setEnabled(d->cityCheck->isChecked());
+
+ d->sublocationEdit->clear();
+ d->sublocationCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.SubLocation", false);
+ if (!data.isNull())
+ {
+ d->sublocationEdit->setText(data);
+ d->sublocationCheck->setChecked(true);
+ }
+ d->sublocationEdit->setEnabled(d->sublocationCheck->isChecked());
+
+ d->provinceEdit->clear();
+ d->provinceCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.ProvinceState", false);
+ if (!data.isNull())
+ {
+ d->provinceEdit->setText(data);
+ d->provinceCheck->setChecked(true);
+ }
+ d->provinceEdit->setEnabled(d->provinceCheck->isChecked());
+
+ d->countryCB->setCurrentItem(0);
+ d->countryCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.CountryCode", false);
+ if (!data.isNull())
+ {
+ int item = -1;
+ for (int i = 0 ; i < d->countryCB->count() ; i++)
+ if (d->countryCB->text(i).left(3) == data)
+ item = i;
+
+ if (item != -1)
+ {
+ d->countryCB->setCurrentItem(item);
+ d->countryCheck->setChecked(true);
+ }
+ else
+ d->countryCheck->setValid(false);
+ }
+ d->countryCB->setEnabled(d->countryCheck->isChecked());
+
+ d->originalTransEdit->clear();
+ d->originalTransCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.TransmissionReference", false);
+ if (!data.isNull())
+ {
+ d->originalTransEdit->setText(data);
+ d->originalTransCheck->setChecked(true);
+ }
+ d->originalTransEdit->setEnabled(d->originalTransCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void IPTCOrigin::applyMetadata(QByteArray& iptcData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+
+ if (d->objectNameCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.ObjectName", d->objectNameEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.ObjectName");
+
+ if (d->locationCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.LocationName", d->locationEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.LocationName");
+
+ if (d->cityCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.City", d->cityEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.City");
+
+ if (d->sublocationCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.SubLocation", d->sublocationEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.SubLocation");
+
+ if (d->provinceCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.ProvinceState", d->provinceEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.ProvinceState");
+
+ if (d->countryCheck->isChecked())
+ {
+ QString countryName = d->countryCB->currentText().mid(6);
+ QString countryCode = d->countryCB->currentText().left(3);
+ exiv2Iface.setIptcTagString("Iptc.Application2.CountryCode", countryCode);
+ exiv2Iface.setIptcTagString("Iptc.Application2.CountryName", countryName);
+ }
+ else if (d->countryCheck->isValid())
+ {
+ exiv2Iface.removeIptcTag("Iptc.Application2.CountryCode");
+ exiv2Iface.removeIptcTag("Iptc.Application2.CountryName");
+ }
+
+ if (d->originalTransCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.TransmissionReference", d->originalTransEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.TransmissionReference");
+
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/iptcorigin.h b/kipi-plugins/metadataedit/iptcorigin.h
new file mode 100644
index 0000000..77cc193
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptcorigin.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-13
+ * Description : IPTC origin settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IPTC_ORIGIN_H
+#define IPTC_ORIGIN_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCOriginPriv;
+
+class IPTCOrigin : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ IPTCOrigin(QWidget* parent);
+ ~IPTCOrigin();
+
+ void applyMetadata(QByteArray& iptcData);
+ void readMetadata(QByteArray& iptcData);
+
+signals:
+
+ void signalModified();
+
+private:
+
+ IPTCOriginPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // IPTC_ORIGIN_H
diff --git a/kipi-plugins/metadataedit/iptcstatus.cpp b/kipi-plugins/metadataedit/iptcstatus.cpp
new file mode 100644
index 0000000..4b86c83
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptcstatus.cpp
@@ -0,0 +1,485 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : IPTC status settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <klineedit.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kactivelabel.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "metadatacheckbox.h"
+#include "pluginsversion.h"
+#include "iptcstatus.h"
+#include "iptcstatus.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCStatusPriv
+{
+public:
+
+ IPTCStatusPriv()
+ {
+ priorityCB = 0;
+ objectCycleCB = 0;
+ objectTypeCB = 0;
+ statusEdit = 0;
+ JobIDEdit = 0;
+ priorityCheck = 0;
+ objectCycleCheck = 0;
+ objectTypeCheck = 0;
+ statusCheck = 0;
+ JobIDCheck = 0;
+ }
+
+ QCheckBox *statusCheck;
+ QCheckBox *JobIDCheck;
+
+ QComboBox *priorityCB;
+ QComboBox *objectCycleCB;
+ QComboBox *objectTypeCB;
+ QComboBox *objectAttributeCB;
+
+ KLineEdit *statusEdit;
+ KLineEdit *objectTypeDescEdit;
+ KLineEdit *objectAttributeDescEdit;
+ KLineEdit *JobIDEdit;
+
+ MetadataCheckBox *priorityCheck;
+ MetadataCheckBox *objectCycleCheck;
+ MetadataCheckBox *objectTypeCheck;
+ MetadataCheckBox *objectAttributeCheck;
+};
+
+IPTCStatus::IPTCStatus(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new IPTCStatusPriv;
+
+ QGridLayout* grid = new QGridLayout(parent, 11, 2, KDialog::spacingHint());
+
+ // IPTC only accept printable Ascii char.
+ QRegExp asciiRx("[\x20-\x7F]+$");
+ QValidator *asciiValidator = new QRegExpValidator(asciiRx, this);
+
+ // --------------------------------------------------------
+
+ d->statusCheck = new QCheckBox(i18n("Edit Status:"), parent);
+ d->statusEdit = new KLineEdit(parent);
+ d->statusEdit->setValidator(asciiValidator);
+ d->statusEdit->setMaxLength(64);
+ grid->addMultiCellWidget(d->statusCheck, 0, 0, 0, 2);
+ grid->addMultiCellWidget(d->statusEdit, 1, 1, 0, 2);
+ QWhatsThis::add(d->statusEdit, i18n("<p>Set here the content status. This field is limited "
+ "to 64 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->priorityCheck = new MetadataCheckBox(i18n("Priority:"), parent);
+ d->priorityCB = new QComboBox(false, parent);
+ d->priorityCB->insertItem(i18n("0: None"), 0);
+ d->priorityCB->insertItem(i18n("1: High"), 1);
+ d->priorityCB->insertItem("2", 2);
+ d->priorityCB->insertItem("3", 3);
+ d->priorityCB->insertItem("4", 4);
+ d->priorityCB->insertItem(i18n("5: Normal"), 5);
+ d->priorityCB->insertItem("6", 6);
+ d->priorityCB->insertItem("7", 7);
+ d->priorityCB->insertItem(i18n("8: Low"), 8);
+ grid->addMultiCellWidget(d->priorityCheck, 2, 2, 0, 0);
+ grid->addMultiCellWidget(d->priorityCB, 2, 2, 1, 1);
+ QWhatsThis::add(d->priorityCB, i18n("<p>Select here the editorial urgency of content."));
+
+ // --------------------------------------------------------
+
+ d->objectCycleCheck = new MetadataCheckBox(i18n("Object Cycle:"), parent);
+ d->objectCycleCB = new QComboBox(false, parent);
+ d->objectCycleCB->insertItem(i18n("Morning"), 0);
+ d->objectCycleCB->insertItem(i18n("Afternoon"), 1);
+ d->objectCycleCB->insertItem(i18n("Evening"), 2);
+ grid->addMultiCellWidget(d->objectCycleCheck, 3, 3, 0, 0);
+ grid->addMultiCellWidget(d->objectCycleCB, 3, 3, 1, 1);
+ QWhatsThis::add(d->objectCycleCB, i18n("<p>Select here the editorial cycle of content."));
+
+ // --------------------------------------------------------
+
+ d->objectTypeCheck = new MetadataCheckBox(i18n("Object Type:"), parent);
+ d->objectTypeCB = new QComboBox(false, parent);
+ d->objectTypeDescEdit = new KLineEdit(parent);
+ d->objectTypeDescEdit->setValidator(asciiValidator);
+ d->objectTypeDescEdit->setMaxLength(64);
+ d->objectTypeCB->insertItem(i18n("News"), 0);
+ d->objectTypeCB->insertItem(i18n("Data"), 1);
+ d->objectTypeCB->insertItem(i18n("Advisory"), 2);
+ grid->addMultiCellWidget(d->objectTypeCheck, 4, 4, 0, 0);
+ grid->addMultiCellWidget(d->objectTypeCB, 4, 4, 1, 1);
+ grid->addMultiCellWidget(d->objectTypeDescEdit, 5, 5, 0, 2);
+ QWhatsThis::add(d->objectTypeCB, i18n("<p>Select here the editorial type of content."));
+ QWhatsThis::add(d->objectTypeDescEdit, i18n("<p>Set here the editorial type description of content. "
+ "This field is limited to 64 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->objectAttributeCheck = new MetadataCheckBox(i18n("Object Attribute:"), parent);
+ d->objectAttributeCB = new QComboBox(false, parent);
+ d->objectAttributeDescEdit = new KLineEdit(parent);
+ d->objectAttributeDescEdit->setValidator(asciiValidator);
+ d->objectAttributeDescEdit->setMaxLength(64);
+ d->objectAttributeCB->insertItem(i18n("Current"), 0);
+ d->objectAttributeCB->insertItem(i18n("Analysis"), 1);
+ d->objectAttributeCB->insertItem(i18n("Archive material"), 2);
+ d->objectAttributeCB->insertItem(i18n("Background"), 3);
+ d->objectAttributeCB->insertItem(i18n("Feature"), 4);
+ d->objectAttributeCB->insertItem(i18n("Forecast"), 5);
+ d->objectAttributeCB->insertItem(i18n("History"), 6);
+ d->objectAttributeCB->insertItem(i18n("Obituary"), 7);
+ d->objectAttributeCB->insertItem(i18n("Opinion"), 8);
+ d->objectAttributeCB->insertItem(i18n("Polls & Surveys"), 9);
+ d->objectAttributeCB->insertItem(i18n("Profile"), 10);
+ d->objectAttributeCB->insertItem(i18n("Results Listings & Table"), 11);
+ d->objectAttributeCB->insertItem(i18n("Side bar & Supporting information"), 12);
+ d->objectAttributeCB->insertItem(i18n("Summary"), 13);
+ d->objectAttributeCB->insertItem(i18n("Transcript & Verbatim"), 14);
+ d->objectAttributeCB->insertItem(i18n("Interview"), 15);
+ d->objectAttributeCB->insertItem(i18n("From the Scene"), 16);
+ d->objectAttributeCB->insertItem(i18n("Retrospective"), 17);
+ d->objectAttributeCB->insertItem(i18n("Statistics"), 18);
+ d->objectAttributeCB->insertItem(i18n("Update"), 19);
+ d->objectAttributeCB->insertItem(i18n("Wrap-up"), 20);
+ d->objectAttributeCB->insertItem(i18n("Press Release"), 21);
+ grid->addMultiCellWidget(d->objectAttributeCheck, 6, 6, 0, 0);
+ grid->addMultiCellWidget(d->objectAttributeCB, 6, 6, 1, 2);
+ grid->addMultiCellWidget(d->objectAttributeDescEdit, 7, 7, 0, 2);
+ QWhatsThis::add(d->objectAttributeCB, i18n("<p>Select here the editorial attribute of content."));
+ QWhatsThis::add(d->objectAttributeDescEdit, i18n("<p>Set here the editorial attribute description of "
+ "content. This field is limited to 64 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ d->JobIDCheck = new QCheckBox(i18n("Job Identification:"), parent);
+ d->JobIDEdit = new KLineEdit(parent);
+ d->JobIDEdit->setValidator(asciiValidator);
+ d->JobIDEdit->setMaxLength(32);
+ grid->addMultiCellWidget(d->JobIDCheck, 8, 8, 0, 2);
+ grid->addMultiCellWidget(d->JobIDEdit, 9, 9, 0, 2);
+ QWhatsThis::add(d->JobIDEdit, i18n("<p>Set here the string that identifies content that recurs. "
+ "This field is limited to 32 ASCII characters."));
+
+ // --------------------------------------------------------
+
+ KActiveLabel *note = new KActiveLabel(i18n("<b>Note: "
+ "<b><a href='http://en.wikipedia.org/wiki/IPTC'>IPTC</a></b> "
+ "text tags only support the printable "
+ "<b><a href='http://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
+ "characters set and limit strings size. "
+ "Use contextual help for details.</b>"), parent);
+
+ grid->addMultiCellWidget(note, 10, 10, 0, 2);
+ grid->setColStretch(2, 10);
+ grid->setRowStretch(11, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->priorityCheck, SIGNAL(toggled(bool)),
+ d->priorityCB, SLOT(setEnabled(bool)));
+
+ connect(d->objectCycleCheck, SIGNAL(toggled(bool)),
+ d->objectCycleCB, SLOT(setEnabled(bool)));
+
+ connect(d->objectTypeCheck, SIGNAL(toggled(bool)),
+ d->objectTypeCB, SLOT(setEnabled(bool)));
+
+ connect(d->objectTypeCheck, SIGNAL(toggled(bool)),
+ d->objectTypeDescEdit, SLOT(setEnabled(bool)));
+
+ connect(d->objectAttributeCheck, SIGNAL(toggled(bool)),
+ d->objectAttributeCB, SLOT(setEnabled(bool)));
+
+ connect(d->objectAttributeCheck, SIGNAL(toggled(bool)),
+ d->objectAttributeDescEdit, SLOT(setEnabled(bool)));
+
+ connect(d->statusCheck, SIGNAL(toggled(bool)),
+ d->statusEdit, SLOT(setEnabled(bool)));
+
+ connect(d->JobIDCheck, SIGNAL(toggled(bool)),
+ d->JobIDEdit, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->priorityCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectCycleCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectTypeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectTypeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectAttributeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectAttributeCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->statusCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->JobIDCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ // --------------------------------------------------------
+
+ connect(d->priorityCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectCycleCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectTypeCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectAttributeCB, SIGNAL(activated(int)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->statusEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectTypeDescEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->objectAttributeDescEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->JobIDEdit, SIGNAL(textChanged(const QString &)),
+ this, SIGNAL(signalModified()));
+}
+
+IPTCStatus::~IPTCStatus()
+{
+ delete d;
+}
+
+void IPTCStatus::readMetadata(QByteArray& iptcData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+ QString data;
+ int val;
+
+ d->statusEdit->clear();
+ d->statusCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.EditStatus", false);
+ if (!data.isNull())
+ {
+ d->statusEdit->setText(data);
+ d->statusCheck->setChecked(true);
+ }
+ d->statusEdit->setEnabled(d->statusCheck->isChecked());
+
+ d->priorityCB->setCurrentItem(0);
+ d->priorityCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.Urgency", false);
+ if (!data.isNull())
+ {
+ val = data.toInt();
+ if (val >= 0 && val <= 8)
+ {
+ d->priorityCB->setCurrentItem(val);
+ d->priorityCheck->setChecked(true);
+ }
+ else
+ d->priorityCheck->setValid(false);
+ }
+ d->priorityCB->setEnabled(d->priorityCheck->isChecked());
+
+ d->objectCycleCB->setCurrentItem(0);
+ d->objectCycleCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.ObjectCycle", false);
+ if (!data.isNull())
+ {
+ if (data == QString("a"))
+ {
+ d->objectCycleCB->setCurrentItem(0);
+ d->objectCycleCheck->setChecked(true);
+ }
+ else if (data == QString("b"))
+ {
+ d->objectCycleCB->setCurrentItem(1);
+ d->objectCycleCheck->setChecked(true);
+ }
+ else if (data == QString("c"))
+ {
+ d->objectCycleCB->setCurrentItem(2);
+ d->objectCycleCheck->setChecked(true);
+ }
+ else
+ d->objectCycleCheck->setValid(false);
+ }
+ d->objectCycleCB->setEnabled(d->objectCycleCheck->isChecked());
+
+ d->objectTypeCB->setCurrentItem(0);
+ d->objectTypeDescEdit->clear();
+ d->objectTypeCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.ObjectType", false);
+ if (!data.isNull())
+ {
+ QString typeSec = data.section(":", 0, 0);
+ if (!typeSec.isEmpty())
+ {
+ int type = typeSec.toInt()-1;
+ if (type >= 0 && type < 3)
+ {
+ d->objectTypeCB->setCurrentItem(type);
+ d->objectTypeDescEdit->setText(data.section(":", -1));
+ d->objectTypeCheck->setChecked(true);
+ }
+ else
+ d->objectTypeCheck->setValid(false);
+ }
+ }
+ d->objectTypeCB->setEnabled(d->objectTypeCheck->isChecked());
+ d->objectTypeDescEdit->setEnabled(d->objectTypeCheck->isChecked());
+
+ d->objectAttributeCB->setCurrentItem(0);
+ d->objectAttributeDescEdit->clear();
+ d->objectAttributeCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.ObjectAttribute", false);
+ if (!data.isNull())
+ {
+ QString attSec = data.section(":", 0, 0);
+ if (!attSec.isEmpty())
+ {
+ int att = attSec.toInt()-1;
+ if (att >= 0 && att < 21)
+ {
+ d->objectAttributeCB->setCurrentItem(att);
+ d->objectAttributeDescEdit->setText(data.section(":", -1));
+ d->objectAttributeCheck->setChecked(true);
+ }
+ else
+ d->objectAttributeCheck->setValid(false);
+ }
+ }
+ d->objectAttributeCB->setEnabled(d->objectAttributeCheck->isChecked());
+ d->objectAttributeDescEdit->setEnabled(d->objectAttributeCheck->isChecked());
+
+ d->JobIDEdit->clear();
+ d->JobIDCheck->setChecked(false);
+ data = exiv2Iface.getIptcTagString("Iptc.Application2.FixtureId", false);
+ if (!data.isNull())
+ {
+ d->JobIDEdit->setText(data);
+ d->JobIDCheck->setChecked(true);
+ }
+ d->JobIDEdit->setEnabled(d->JobIDCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void IPTCStatus::applyMetadata(QByteArray& iptcData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+
+ if (d->statusCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.EditStatus", d->statusEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.EditStatus");
+
+ if (d->priorityCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.Urgency", QString::number(d->priorityCB->currentItem()));
+ else if (d->priorityCheck->isValid())
+ exiv2Iface.removeIptcTag("Iptc.Application2.Urgency");
+
+ if (d->objectCycleCheck->isChecked())
+ {
+ switch (d->objectCycleCB->currentItem())
+ {
+ case(0):
+ exiv2Iface.setIptcTagString("Iptc.Application2.ObjectCycle", QString("a"));
+ break;
+
+ case(1):
+ exiv2Iface.setIptcTagString("Iptc.Application2.ObjectCycle", QString("b"));
+ break;
+
+ case(2):
+ exiv2Iface.setIptcTagString("Iptc.Application2.ObjectCycle", QString("c"));
+ break;
+ }
+ }
+ else if (d->objectCycleCheck->isValid())
+ exiv2Iface.removeIptcTag("Iptc.Application2.ObjectCycle");
+
+ if (d->objectTypeCheck->isChecked())
+ {
+ QString objectType;
+ objectType.sprintf("%2d", d->objectTypeCB->currentItem()+1);
+ objectType.append(QString(":%1").arg(d->objectTypeDescEdit->text()));
+ exiv2Iface.setIptcTagString("Iptc.Application2.ObjectType", objectType);
+ }
+ else if (d->objectTypeCheck->isValid())
+ exiv2Iface.removeIptcTag("Iptc.Application2.ObjectType");
+
+ if (d->objectAttributeCheck->isChecked())
+ {
+ QString objectAttribute;
+ objectAttribute.sprintf("%3d", d->objectAttributeCB->currentItem()+1);
+ objectAttribute.append(QString(":%1").arg(d->objectAttributeDescEdit->text()));
+ exiv2Iface.setIptcTagString("Iptc.Application2.ObjectAttribute", objectAttribute);
+ }
+ else if (d->objectAttributeCheck->isValid())
+ exiv2Iface.removeIptcTag("Iptc.Application2.ObjectAttribute");
+
+ if (d->JobIDCheck->isChecked())
+ exiv2Iface.setIptcTagString("Iptc.Application2.FixtureId", d->JobIDEdit->text());
+ else
+ exiv2Iface.removeIptcTag("Iptc.Application2.FixtureId");
+
+ exiv2Iface.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
diff --git a/kipi-plugins/metadataedit/iptcstatus.h b/kipi-plugins/metadataedit/iptcstatus.h
new file mode 100644
index 0000000..ea0f537
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptcstatus.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-12
+ * Description : IPTC status settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IPTC_STATUS_H
+#define IPTC_STATUS_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCStatusPriv;
+
+class IPTCStatus : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ IPTCStatus(QWidget* parent);
+ ~IPTCStatus();
+
+ void applyMetadata(QByteArray& iptcData);
+ void readMetadata(QByteArray& iptcData);
+
+signals:
+
+ void signalModified();
+
+private:
+
+ IPTCStatusPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // IPTC_STATUS_H
diff --git a/kipi-plugins/metadataedit/iptcsubjects.cpp b/kipi-plugins/metadataedit/iptcsubjects.cpp
new file mode 100644
index 0000000..f1bb14c
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptcsubjects.cpp
@@ -0,0 +1,250 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-15
+ * Description : IPTC subjects settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes.
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qvalidator.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <klistbox.h>
+#include <klineedit.h>
+#include <kactivelabel.h>
+#include <kiconloader.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "iptcsubjects.h"
+#include "iptcsubjects.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCSubjectsPriv
+{
+public:
+
+ IPTCSubjectsPriv()
+ {
+ addSubjectButton = 0;
+ delSubjectButton = 0;
+ subjectsBox = 0;
+ subjectsCheck = 0;
+ subjectEdit = 0;
+ }
+
+ QStringList oldSubjects;
+
+ QPushButton *addSubjectButton;
+ QPushButton *delSubjectButton;
+
+ QCheckBox *subjectsCheck;
+
+ KLineEdit *subjectEdit;
+
+ KListBox *subjectsBox;
+};
+
+IPTCSubjects::IPTCSubjects(QWidget* parent)
+ : QWidget(parent)
+{
+ d = new IPTCSubjectsPriv;
+ QGridLayout *grid = new QGridLayout(parent, 5, 2, 0, KDialog::spacingHint());
+ grid->setAlignment( Qt::AlignTop );
+
+ // IPTC only accept printable Ascii char.
+ QRegExp asciiRx("[\x20-\x7F]+$");
+ QValidator *asciiValidator = new QRegExpValidator(asciiRx, this);
+
+ // --------------------------------------------------------
+
+ d->subjectsCheck = new QCheckBox(i18n("Use structured definition of the subject matter:"), parent);
+
+ d->subjectEdit = new KLineEdit(parent);
+ d->subjectEdit->setValidator(asciiValidator);
+ d->subjectEdit->setMaxLength(236);
+ QWhatsThis::add(d->subjectEdit, i18n("<p>Enter here a new subject. "
+ "This field is limited to 236 ASCII characters."));
+
+ d->subjectsBox = new KListBox(parent);
+ d->subjectsBox->setVScrollBarMode(QScrollView::AlwaysOn);
+
+ d->addSubjectButton = new QPushButton( i18n("&Add"), parent);
+ d->delSubjectButton = new QPushButton( i18n("&Delete"), parent);
+ d->addSubjectButton->setIconSet(SmallIcon("add"));
+ d->delSubjectButton->setIconSet(SmallIcon("remove"));
+ d->delSubjectButton->setEnabled(false);
+
+ grid->addMultiCellWidget(d->subjectsCheck, 0, 0, 0, 1);
+ grid->addMultiCellWidget(d->subjectEdit, 1, 1, 0, 0);
+ grid->addMultiCellWidget(d->subjectsBox, 2, 5, 0, 0);
+ grid->addMultiCellWidget(d->addSubjectButton, 2, 2, 1, 1);
+ grid->addMultiCellWidget(d->delSubjectButton, 3, 3, 1, 1);
+
+ // --------------------------------------------------------
+
+ KActiveLabel *note = new KActiveLabel(i18n("<b>Note: "
+ "<b><a href='http://en.wikipedia.org/wiki/IPTC'>IPTC</a></b> "
+ "text tags only support the printable "
+ "<b><a href='http://en.wikipedia.org/wiki/Ascii'>ASCII</a></b> "
+ "characters set and limit strings size. "
+ "Use contextual help for details.</b>"), parent);
+ note->setMaximumWidth(150);
+
+ grid->addMultiCellWidget(note, 4, 4, 1, 1);
+ grid->setColStretch(0, 10);
+ grid->setRowStretch(5, 10);
+
+ // --------------------------------------------------------
+
+ connect(d->subjectsBox, SIGNAL(selectionChanged()),
+ this, SLOT(slotSubjectSelectionChanged()));
+
+ connect(d->addSubjectButton, SIGNAL(clicked()),
+ this, SLOT(slotAddSubject()));
+
+ connect(d->delSubjectButton, SIGNAL(clicked()),
+ this, SLOT(slotDelSubject()));
+
+ // --------------------------------------------------------
+
+ connect(d->subjectsCheck, SIGNAL(toggled(bool)),
+ d->subjectEdit, SLOT(setEnabled(bool)));
+
+ connect(d->subjectsCheck, SIGNAL(toggled(bool)),
+ d->subjectsBox, SLOT(setEnabled(bool)));
+
+ connect(d->subjectsCheck, SIGNAL(toggled(bool)),
+ d->addSubjectButton, SLOT(setEnabled(bool)));
+
+ connect(d->subjectsCheck, SIGNAL(toggled(bool)),
+ d->delSubjectButton, SLOT(setEnabled(bool)));
+
+ // --------------------------------------------------------
+
+ connect(d->subjectsCheck, SIGNAL(toggled(bool)),
+ this, SIGNAL(signalModified()));
+
+ connect(d->addSubjectButton, SIGNAL(clicked()),
+ this, SIGNAL(signalModified()));
+
+ connect(d->delSubjectButton, SIGNAL(clicked()),
+ this, SIGNAL(signalModified()));
+}
+
+IPTCSubjects::~IPTCSubjects()
+{
+ delete d;
+}
+
+void IPTCSubjects::slotDelSubject()
+{
+ int index = d->subjectsBox->currentItem();
+ if (index == -1)
+ return;
+
+ QListBoxItem* item = d->subjectsBox->item(index);
+ if (!item) return;
+ delete item;
+}
+
+void IPTCSubjects::slotSubjectSelectionChanged()
+{
+ if (d->subjectsBox->currentItem() != -1)
+ d->delSubjectButton->setEnabled(true);
+ else
+ d->delSubjectButton->setEnabled(false);
+}
+
+void IPTCSubjects::slotAddSubject()
+{
+ QString newSubject = d->subjectEdit->text();
+ if (newSubject.isEmpty()) return;
+
+ bool found = false;
+ for (QListBoxItem *item = d->subjectsBox->firstItem();
+ item; item = item->next())
+ {
+ if (newSubject == item->text())
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ d->subjectsBox->insertItem(newSubject);
+}
+
+void IPTCSubjects::readMetadata(QByteArray& iptcData)
+{
+ blockSignals(true);
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+ d->oldSubjects = exiv2Iface.getImageSubjects();
+
+ d->subjectsBox->clear();
+ d->subjectsCheck->setChecked(false);
+ if (!d->oldSubjects.isEmpty())
+ {
+ d->subjectsBox->insertStringList(d->oldSubjects);
+ d->subjectsCheck->setChecked(true);
+ }
+ d->subjectEdit->setEnabled(d->subjectsCheck->isChecked());
+ d->subjectsBox->setEnabled(d->subjectsCheck->isChecked());
+ d->addSubjectButton->setEnabled(d->subjectsCheck->isChecked());
+ d->delSubjectButton->setEnabled(d->subjectsCheck->isChecked());
+
+ blockSignals(false);
+}
+
+void IPTCSubjects::applyMetadata(QByteArray& iptcData)
+{
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.setIptc(iptcData);
+ QStringList newSubjects;
+
+ for (QListBoxItem *item = d->subjectsBox->firstItem();
+ item; item = item->next())
+ newSubjects.append(item->text());
+
+ if (d->subjectsCheck->isChecked())
+ exiv2Iface.setImageSubjects(d->oldSubjects, newSubjects);
+ else
+ exiv2Iface.setImageSubjects(d->oldSubjects, QStringList());
+
+ iptcData = exiv2Iface.getIptc();
+}
+
+} // namespace KIPIMetadataEditPlugin
+
diff --git a/kipi-plugins/metadataedit/iptcsubjects.h b/kipi-plugins/metadataedit/iptcsubjects.h
new file mode 100644
index 0000000..2c0d566
--- /dev/null
+++ b/kipi-plugins/metadataedit/iptcsubjects.h
@@ -0,0 +1,65 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-15
+ * Description : IPTC subjects settings page.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IPTC_SUBJECTS_H
+#define IPTC_SUBJECTS_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qcstring.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class IPTCSubjectsPriv;
+
+class IPTCSubjects : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ IPTCSubjects(QWidget* parent);
+ ~IPTCSubjects();
+
+ void applyMetadata(QByteArray& iptcData);
+ void readMetadata(QByteArray& iptcData);
+
+signals:
+
+ void signalModified();
+
+private slots:
+
+ void slotSubjectSelectionChanged();
+ void slotAddSubject();
+ void slotDelSubject();
+
+private:
+
+ IPTCSubjectsPriv* d;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // IPTC_SUBJECTS_H
diff --git a/kipi-plugins/metadataedit/kipiplugin_metadataedit.desktop b/kipi-plugins/metadataedit/kipiplugin_metadataedit.desktop
new file mode 100644
index 0000000..6b6b845
--- /dev/null
+++ b/kipi-plugins/metadataedit/kipiplugin_metadataedit.desktop
@@ -0,0 +1,46 @@
+[Desktop Entry]
+Comment=KIPI Pictures Metadata Editor
+Comment[ca]=Editor del KIPI de les metadades de les fotografies
+Comment[da]=KIPI-editor for metadata i billeder
+Comment[de]=Ein KIPI-Modul zum Bearbeiten der Metadaten
+Comment[el]=Επεξεργαστής μεταπληροφοριών εικόνων του KIPI
+Comment[es]=Editor de metadatos de imágenes de KIPI
+Comment[et]=KIPI piltide metaandmete redaktor
+Comment[fi]=Kipi-liitännäinen kuvatiedostojen metatietojen asetusta varten
+Comment[fr]=Module externe KIPI pour éditer les métadonnées
+Comment[is]=KIPI Metagagnaritill fyrir myndir
+Comment[it]=Editor dei dati aggiuntivi delle immagini di KIPI
+Comment[ja]=Kipi 画像のメタデータエディタ
+Comment[nds]=KIPI-Editor för Bild-Metadaten
+Comment[nl]=KIPI-plugin voor het bewerken van metadata
+Comment[pa]=KIPI ਤਸਵੀਰ ਮੈਟਾਡਾਟਾ ਸੰਪਾਦਕ
+Comment[pl]=Wtyczka KIPI - Edytor metadanych zdjęć
+Comment[pt]=Editor de Meta-Dados das Imagens do KIPI
+Comment[pt_BR]=Editor de Metadados de Figuras do KIPI
+Comment[sr]=KIPI-јев уређивач метаподатака слике
+Comment[sr@Latn]=KIPI-jev uređivač metapodataka slike
+Comment[sv]=KIPI-editor för metadata i bilder
+Comment[xx]=xxKIPI Pictures Metadata Editorxx
+Comment[zh_CN]=KIPI 图片和元数据编辑器
+Encoding=UTF-8
+Icon=
+Name=MetadataEdit
+Name[ca]=Edició de metadades
+Name[da]=Metadataeditor
+Name[de]=Metadata-Editor
+Name[es]=Editar metadatos
+Name[et]=Metaandmete redaktor
+Name[fi]=Metadata-editori
+Name[it]=ModificaDatiAggiuntivi
+Name[nds]=Metadaten-Editor
+Name[pl]=Edytor metadanych
+Name[pt]=Edição de Meta-Dados
+Name[sr]=Уређивач метаподатака
+Name[sr@Latn]=Uređivač metapodataka
+Name[sv]=Metadataeditor
+Name[xx]=xxMetadataEditxx
+Name[zh_CN]=元数据编辑
+ServiceTypes=KIPI/Plugin
+Type=Service
+X-KDE-Library=kipiplugin_metadataedit
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/kipi-plugins/metadataedit/metadatacheckbox.cpp b/kipi-plugins/metadataedit/metadatacheckbox.cpp
new file mode 100644
index 0000000..5dd33c9
--- /dev/null
+++ b/kipi-plugins/metadataedit/metadatacheckbox.cpp
@@ -0,0 +1,62 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : a checkbox with a boolean valid parameter.
+ * The boolean statement is used to check if
+ * a metadata value from a picture have a know
+ * value registered by EXIF/IPTC spec.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "metadatacheckbox.h"
+#include "metadatacheckbox.moc"
+
+namespace KIPIMetadataEditPlugin
+{
+
+MetadataCheckBox::MetadataCheckBox(const QString& text, QWidget* parent)
+ : QCheckBox(text, parent)
+{
+ m_valid = true;
+
+ connect(this, SIGNAL(toggled(bool)),
+ this, SLOT(slotValid()));
+}
+
+MetadataCheckBox::~MetadataCheckBox()
+{
+}
+
+void MetadataCheckBox::setValid(bool v)
+{
+ m_valid = v;
+}
+
+bool MetadataCheckBox::isValid() const
+{
+ return m_valid;
+}
+
+void MetadataCheckBox::slotValid()
+{
+ setValid(true);
+}
+
+} // namespace KIPIMetadataEditPlugin
diff --git a/kipi-plugins/metadataedit/metadatacheckbox.h b/kipi-plugins/metadataedit/metadatacheckbox.h
new file mode 100644
index 0000000..82a5dc6
--- /dev/null
+++ b/kipi-plugins/metadataedit/metadatacheckbox.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-18
+ * Description : a checkbox with a boolean valid parameter.
+ * The boolean statement is used to check if
+ * a metadata value from a picture have a know
+ * value registered by EXIF/IPTC spec.
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 METADATA_CHECKBOX_H
+#define METADATA_CHECKBOX_H
+
+// QT includes.
+
+#include <qcheckbox.h>
+
+namespace KIPIMetadataEditPlugin
+{
+
+class MetadataCheckBox : public QCheckBox
+{
+ Q_OBJECT
+
+public:
+
+ MetadataCheckBox(const QString& text, QWidget* parent);
+ ~MetadataCheckBox();
+
+ void setValid(bool v);
+ bool isValid() const;
+
+private slots:
+
+ void slotValid();
+
+private:
+
+ bool m_valid;
+};
+
+} // namespace KIPIMetadataEditPlugin
+
+#endif // METADATA_CHECKBOX_H
diff --git a/kipi-plugins/metadataedit/plugin_metadataedit.cpp b/kipi-plugins/metadataedit/plugin_metadataedit.cpp
new file mode 100644
index 0000000..64f8a39
--- /dev/null
+++ b/kipi-plugins/metadataedit/plugin_metadataedit.cpp
@@ -0,0 +1,588 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-11
+ * Description : a plugin to edit pictures metadata
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kpopupmenu.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <kglobalsettings.h>
+
+// LibKIPI includes.
+
+#include <libkipi/imagecollection.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "exifeditdialog.h"
+#include "iptceditdialog.h"
+#include "commenteditdialog.h"
+#include "commentremovedialog.h"
+#include "plugin_metadataedit.h"
+#include "plugin_metadataedit.moc"
+
+typedef KGenericFactory<Plugin_MetadataEdit> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_metadataedit, Factory("kipiplugin_metadataedit"))
+
+Plugin_MetadataEdit::Plugin_MetadataEdit(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "MetadataEdit")
+{
+ kdDebug( 51001 ) << "Plugin_MetadataEdit plugin loaded" << endl;
+}
+
+void Plugin_MetadataEdit::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_actionMetadataEdit = new KActionMenu(i18n("Metadata"),
+ 0,
+ actionCollection(),
+ "metadataedit");
+
+ m_actionMetadataEdit->insert(new KAction (i18n("Edit EXIF..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotEditExif()),
+ actionCollection(),
+ "editexif"));
+
+ m_actionMetadataEdit->insert(new KAction (i18n("Remove EXIF..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotRemoveExif()),
+ actionCollection(),
+ "removeexif"));
+
+ m_actionMetadataEdit->insert(new KAction (i18n("Import EXIF..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotImportExif()),
+ actionCollection(),
+ "importexif"));
+
+ m_actionMetadataEdit->popupMenu()->insertSeparator();
+
+ m_actionMetadataEdit->insert(new KAction (i18n("Edit IPTC..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotEditIptc()),
+ actionCollection(),
+ "editiptc"));
+
+ m_actionMetadataEdit->insert(new KAction (i18n("Remove IPTC..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotRemoveIptc()),
+ actionCollection(),
+ "removeiptc"));
+
+ m_actionMetadataEdit->insert(new KAction (i18n("Import IPTC..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotImportIptc()),
+ actionCollection(),
+ "importiptc"));
+
+ m_actionMetadataEdit->popupMenu()->insertSeparator();
+
+ m_actionMetadataEdit->insert(new KAction (i18n("Edit Captions..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotEditComments()),
+ actionCollection(),
+ "editcomments"));
+
+ m_actionMetadataEdit->insert(new KAction (i18n("Remove Captions..."),
+ 0,
+ 0,
+ this,
+ SLOT(slotRemoveComments()),
+ actionCollection(),
+ "removecomments"));
+
+ addAction( m_actionMetadataEdit );
+
+ m_interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection selection = m_interface->currentSelection();
+ m_actionMetadataEdit->setEnabled( selection.isValid() && !selection.images().isEmpty() );
+
+ connect( m_interface, SIGNAL(selectionChanged(bool)),
+ m_actionMetadataEdit, SLOT(setEnabled(bool)));
+}
+
+void Plugin_MetadataEdit::slotEditExif()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ KIPIMetadataEditPlugin::EXIFEditDialog dialog(kapp->activeWindow(), images.images(), m_interface);
+ dialog.exec();
+ m_interface->refreshImages(images.images());
+}
+
+void Plugin_MetadataEdit::slotRemoveExif()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ if (KMessageBox::warningYesNo(
+ kapp->activeWindow(),
+ i18n("EXIF metadata will be permanently removed from all current selected pictures.\n"
+ "Do you want to continue ?"),
+ i18n("Remove EXIF Metadata")) != KMessageBox::Yes)
+ return;
+
+ KURL::List imageURLs = images.images();
+ KURL::List updatedURLs;
+ QStringList errorFiles;
+
+ for( KURL::List::iterator it = imageURLs.begin() ;
+ it != imageURLs.end(); ++it)
+ {
+ KURL url = *it;
+ bool ret = false;
+
+ if (!KExiv2Iface::KExiv2::isReadOnly(url.path()))
+ {
+ ret = true;
+ KExiv2Iface::KExiv2 exiv2Iface;
+ ret &= exiv2Iface.load(url.path());
+ ret &= exiv2Iface.clearExif();
+ ret &= exiv2Iface.save(url.path());
+ }
+
+ if (!ret)
+ errorFiles.append(url.fileName());
+ else
+ updatedURLs.append(url);
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-read.
+
+ m_interface->refreshImages(updatedURLs);
+
+ if (!errorFiles.isEmpty())
+ {
+ KMessageBox::errorList(
+ kapp->activeWindow(),
+ i18n("Unable to remove EXIF metadata from:"),
+ errorFiles,
+ i18n("Remove EXIF Metadata"));
+ }
+}
+
+void Plugin_MetadataEdit::slotImportExif()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ KURL importEXIFFile = KFileDialog::getOpenURL(KGlobalSettings::documentPath(),
+ QString::null, kapp->activeWindow(),
+ i18n("Select File to Import EXIF metadata") );
+ if( importEXIFFile.isEmpty() )
+ return;
+
+ KExiv2Iface::KExiv2 exiv2Iface;
+ if (!exiv2Iface.load(importEXIFFile.path()))
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot load metadata from \"%1\"").arg(importEXIFFile.fileName()),
+ i18n("Import EXIF Metadata"));
+ return;
+ }
+
+ QByteArray exifData = exiv2Iface.getExif();
+ if (exifData.isEmpty())
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" do not have EXIF metadata").arg(importEXIFFile.fileName()),
+ i18n("Import EXIF Metadata"));
+ return;
+ }
+
+ if (KMessageBox::warningYesNo(
+ kapp->activeWindow(),
+ i18n("EXIF metadata from current selected pictures will be permanently "
+ "replaced by the EXIF content of \"%1\".\n"
+ "Do you want to continue ?").arg(importEXIFFile.fileName()),
+ i18n("Import EXIF Metadata")) != KMessageBox::Yes)
+ return;
+
+
+ KURL::List imageURLs = images.images();
+ KURL::List updatedURLs;
+ QStringList errorFiles;
+
+ for( KURL::List::iterator it = imageURLs.begin() ;
+ it != imageURLs.end(); ++it)
+ {
+ KURL url = *it;
+ bool ret = false;
+
+ if (!KExiv2Iface::KExiv2::isReadOnly(url.path()))
+ {
+ ret = true;
+ KExiv2Iface::KExiv2 exiv2Iface;
+ ret &= exiv2Iface.load(url.path());
+ ret &= exiv2Iface.setExif(exifData);
+ ret &= exiv2Iface.save(url.path());
+ }
+
+ if (!ret)
+ errorFiles.append(url.fileName());
+ else
+ updatedURLs.append(url);
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-read.
+
+ m_interface->refreshImages(updatedURLs);
+
+ if (!errorFiles.isEmpty())
+ {
+ KMessageBox::errorList(
+ kapp->activeWindow(),
+ i18n("Unable to set EXIF metadata from:"),
+ errorFiles,
+ i18n("Import EXIF Metadata"));
+ }
+}
+
+void Plugin_MetadataEdit::slotEditIptc()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ KIPIMetadataEditPlugin::IPTCEditDialog dialog(kapp->activeWindow(), images.images(), m_interface);
+ dialog.exec();
+ m_interface->refreshImages(images.images());
+}
+
+void Plugin_MetadataEdit::slotRemoveIptc()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ if (KMessageBox::warningYesNo(
+ kapp->activeWindow(),
+ i18n("IPTC metadata will be permanently removed from all current selected pictures.\n"
+ "Do you want to continue ?"),
+ i18n("Remove IPTC Metadata")) != KMessageBox::Yes)
+ return;
+
+ KURL::List imageURLs = images.images();
+ KURL::List updatedURLs;
+ QStringList errorFiles;
+
+ for( KURL::List::iterator it = imageURLs.begin() ;
+ it != imageURLs.end(); ++it)
+ {
+ KURL url = *it;
+ bool ret = false;
+
+ if (!KExiv2Iface::KExiv2::isReadOnly(url.path()))
+ {
+ ret = true;
+ KExiv2Iface::KExiv2 exiv2Iface;
+ ret &= exiv2Iface.load(url.path());
+ ret &= exiv2Iface.clearIptc();
+ ret &= exiv2Iface.save(url.path());
+ }
+
+ if (!ret)
+ errorFiles.append(url.fileName());
+ else
+ updatedURLs.append(url);
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-read.
+
+ m_interface->refreshImages(updatedURLs);
+
+ if (!errorFiles.isEmpty())
+ {
+ KMessageBox::errorList(
+ kapp->activeWindow(),
+ i18n("Unable to remove IPTC metadata from:"),
+ errorFiles,
+ i18n("Remove IPTC Metadata"));
+ }
+}
+
+void Plugin_MetadataEdit::slotImportIptc()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ KURL importIPTCFile = KFileDialog::getOpenURL(KGlobalSettings::documentPath(),
+ QString::null, kapp->activeWindow(),
+ i18n("Select File to Import IPTC metadata") );
+ if( importIPTCFile.isEmpty() )
+ return;
+
+ KExiv2Iface::KExiv2 exiv2Iface;
+ if (!exiv2Iface.load(importIPTCFile.path()))
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot load metadata from \"%1\"").arg(importIPTCFile.fileName()),
+ i18n("Import IPTC Metadata"));
+ return;
+ }
+
+ QByteArray iptcData = exiv2Iface.getIptc();
+ if (iptcData.isEmpty())
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" do not have IPTC metadata").arg(importIPTCFile.fileName()),
+ i18n("Import IPTC Metadata"));
+ return;
+ }
+
+ if (KMessageBox::warningYesNo(
+ kapp->activeWindow(),
+ i18n("IPTC metadata from current selected pictures will be permanently "
+ "replaced by the IPTC content of \"%1\".\n"
+ "Do you want to continue ?").arg(importIPTCFile.fileName()),
+ i18n("Import IPTC Metadata")) != KMessageBox::Yes)
+ return;
+
+
+ KURL::List imageURLs = images.images();
+ KURL::List updatedURLs;
+ QStringList errorFiles;
+
+ for( KURL::List::iterator it = imageURLs.begin() ;
+ it != imageURLs.end(); ++it)
+ {
+ KURL url = *it;
+ bool ret = false;
+
+ if (!KExiv2Iface::KExiv2::isReadOnly(url.path()))
+ {
+ ret = true;
+ KExiv2Iface::KExiv2 exiv2Iface;
+ ret &= exiv2Iface.load(url.path());
+ ret &= exiv2Iface.setIptc(iptcData);
+ ret &= exiv2Iface.save(url.path());
+ }
+
+ if (!ret)
+ errorFiles.append(url.fileName());
+ else
+ updatedURLs.append(url);
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-read.
+
+ m_interface->refreshImages(updatedURLs);
+
+ if (!errorFiles.isEmpty())
+ {
+ KMessageBox::errorList(
+ kapp->activeWindow(),
+ i18n("Unable to set IPTC metadata from:"),
+ errorFiles,
+ i18n("Import IPTC Metadata"));
+ }
+}
+
+void Plugin_MetadataEdit::slotEditComments()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ KIPIMetadataEditPlugin::CommentEditDialog dlg(kapp->activeWindow());
+
+ if (dlg.exec() != KMessageBox::Ok)
+ return;
+
+ KURL::List imageURLs = images.images();
+ KURL::List updatedURLs;
+ QStringList errorFiles;
+
+ for( KURL::List::iterator it = imageURLs.begin() ;
+ it != imageURLs.end(); ++it)
+ {
+ KURL url = *it;
+ bool ret = false;
+
+ KIPI::ImageInfo info = m_interface->info(url);
+ info.setDescription(dlg.getComments());
+
+ if (!KExiv2Iface::KExiv2::isReadOnly(url.path()))
+ {
+ ret = true;
+ KExiv2Iface::KExiv2 exiv2Iface;
+ ret &= exiv2Iface.load(url.path());
+
+ if (dlg.syncEXIFCommentIsChecked())
+ ret &= exiv2Iface.setExifComment(dlg.getComments());
+
+ if (dlg.syncJFIFCommentIsChecked())
+ ret &= exiv2Iface.setComments(dlg.getComments().utf8());
+
+ if (dlg.syncIPTCCaptionIsChecked())
+ ret &= exiv2Iface.setIptcTagString("Iptc.Application2.Caption", dlg.getComments());
+
+ ret &= exiv2Iface.save(url.path());
+ }
+
+ if (!ret)
+ errorFiles.append(url.fileName());
+ else
+ updatedURLs.append(url);
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-read.
+
+ m_interface->refreshImages(updatedURLs);
+
+ if (!errorFiles.isEmpty())
+ {
+ KMessageBox::informationList(
+ kapp->activeWindow(),
+ i18n("Unable to set captions as image metadata from:"),
+ errorFiles,
+ i18n("Edit Image Caption"));
+ }
+}
+
+void Plugin_MetadataEdit::slotRemoveComments()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ KIPIMetadataEditPlugin::CommentRemoveDialog dlg(kapp->activeWindow());
+
+ if (dlg.exec() != KMessageBox::Ok)
+ return;
+
+ KURL::List imageURLs = images.images();
+ KURL::List updatedURLs;
+ QStringList errorFiles;
+
+ for( KURL::List::iterator it = imageURLs.begin() ;
+ it != imageURLs.end(); ++it)
+ {
+ KURL url = *it;
+ bool ret = false;
+
+ if (dlg.removeHOSTCommentIsChecked())
+ {
+ KIPI::ImageInfo info = m_interface->info(url);
+ info.setDescription(QString::null);
+ }
+
+ if (!KExiv2Iface::KExiv2::isReadOnly(url.path()))
+ {
+ ret = true;
+ KExiv2Iface::KExiv2 exiv2Iface;
+ ret &= exiv2Iface.load(url.path());
+
+ if (dlg.removeEXIFCommentIsChecked())
+ ret &= exiv2Iface.removeExifTag("Exif.Photo.UserComment");
+
+ if (dlg.removeJFIFCommentIsChecked())
+ ret &= exiv2Iface.setComments(QByteArray());
+
+ if (dlg.removeIPTCCaptionIsChecked())
+ ret &= exiv2Iface.removeIptcTag("Iptc.Application2.Caption");
+
+ ret &= exiv2Iface.save(url.path());
+ }
+
+ if (!ret)
+ errorFiles.append(url.fileName());
+ else
+ updatedURLs.append(url);
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-read.
+
+ m_interface->refreshImages(updatedURLs);
+
+ if (!errorFiles.isEmpty())
+ {
+ KMessageBox::informationList(
+ kapp->activeWindow(),
+ i18n("Unable to remove caption as image metadata from:"),
+ errorFiles,
+ i18n("Remove Image Caption"));
+ }
+}
+
+KIPI::Category Plugin_MetadataEdit::category( KAction* action ) const
+{
+ if ( action == m_actionMetadataEdit )
+ return KIPI::IMAGESPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMAGESPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/metadataedit/plugin_metadataedit.h b/kipi-plugins/metadataedit/plugin_metadataedit.h
new file mode 100644
index 0000000..28c8d79
--- /dev/null
+++ b/kipi-plugins/metadataedit/plugin_metadataedit.h
@@ -0,0 +1,63 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-10-11
+ * Description : a plugin to edit pictures metadata
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_METADATAEDIT_H
+#define PLUGIN_METADATAEDIT_H
+
+// LibKIPI includes.
+
+#include <libkipi/plugin.h>
+
+class KActionMenu;
+
+class Plugin_MetadataEdit : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_MetadataEdit(QObject *parent, const char* name, const QStringList &args);
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* );
+
+protected slots:
+
+ void slotEditExif();
+ void slotRemoveExif();
+ void slotImportExif();
+
+ void slotEditIptc();
+ void slotRemoveIptc();
+ void slotImportIptc();
+
+ void slotEditComments();
+ void slotRemoveComments();
+
+private:
+
+ KActionMenu *m_actionMetadataEdit;
+
+ KIPI::Interface *m_interface;
+};
+
+#endif // PLUGIN_METADATAEDIT_H
diff --git a/kipi-plugins/mpegencoder/Makefile.am b/kipi-plugins/mpegencoder/Makefile.am
new file mode 100644
index 0000000..8b841c6
--- /dev/null
+++ b/kipi-plugins/mpegencoder/Makefile.am
@@ -0,0 +1,29 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_mpegencoder.la
+kipiplugin_mpegencoder_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+# Srcs for the plugin
+kipiplugin_mpegencoder_la_SOURCES = plugin_mpegencoder.cpp kimg2mpgbase.ui\
+ kimg2mpg.cpp kshowdebuggingoutput.cpp \
+ optionsdialog.cpp checkbinprog.cpp
+
+# Libs needed by the plugin
+kipiplugin_mpegencoder_la_LIBADD = $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_mpegencoder_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_mpegencoder.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_mpegencoder.pot
+
+####### This script name should probably be more 'namespaced'. Think about distros putting everything in /usr/bin...
+bin_SCRIPTS = images2mpg
+man_MANS = images2mpg.1
+
diff --git a/kipi-plugins/mpegencoder/checkbinprog.cpp b/kipi-plugins/mpegencoder/checkbinprog.cpp
new file mode 100644
index 0000000..1d6e2f2
--- /dev/null
+++ b/kipi-plugins/mpegencoder/checkbinprog.cpp
@@ -0,0 +1,133 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// CHECKBINPROG.CPP
+//
+// Copyright (C) 2003 Gilles CAULIER <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include "checkbinprog.h"
+
+// Qt includes
+
+#include <qwidget.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+
+// KDElib includes
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+
+namespace KIPIMPEGEncoderPlugin
+{
+
+///////////////////////////////// CONSTRUCTOR ///////////////////////////////////////////////
+
+CheckBinProg::CheckBinProg(QObject *parent)
+{
+ config = new KConfig("kipirc");
+ config->setGroup("MPEGEncoder Settings");
+ ImageMagickPath = config->readPathEntry("ImageMagickBinFolder");
+ MjpegToolsPath = config->readPathEntry("MjpegToolsBinFolder");
+}
+
+
+/////////////////////////////// DESTRUCTOR //////////////////////////////////////////////////
+
+CheckBinProg::~CheckBinProg()
+{
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+int CheckBinProg::findExecutables( void )
+{
+ QFile montage, composite, convert, identify, ppmtoy4m, yuvscaler, mpeg2enc, mp2enc, mplex;
+ int ValRet = 0;
+
+ if (ImageMagickPath.isEmpty())
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("Your 'ImageMagick' binary program path is empty.\nSetting to default value. Check option's setting."));
+ return (ValRet);
+ }
+
+if (MjpegToolsPath.isEmpty())
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("Your 'MjpegTools' binary programs path is empty.\nSetting to default value. Check option's setting."));
+ return (ValRet);
+ }
+
+ QString str = "";
+
+ // ImageMagick external programs.
+
+ if (montage.exists(QString (ImageMagickPath+"/montage")) == FALSE)
+ str = i18n("Cannot find 'montage' binary program from ImageMagick package. Please install it.");
+
+ if (composite.exists(QString (ImageMagickPath+"/composite")) == FALSE)
+ str = i18n("Cannot find 'composite' binary program from ImageMagick package. Please install it.");
+
+ if (convert.exists(QString (ImageMagickPath+"/convert")) == FALSE)
+ str = i18n("Cannot find 'convert' binary program from ImageMagick package. Please install it.");
+
+ if (identify.exists(QString (ImageMagickPath+"/identify")) == FALSE)
+ str = i18n("Cannot find 'identify' binary program from ImageMagick package. Please install it.");
+
+ // MjpegTools external programs.
+
+ if (ppmtoy4m.exists(QString (MjpegToolsPath+"/ppmtoy4m")) == FALSE)
+ str = i18n("Cannot find 'ppmtoy4m' binary program from MjpegTools package. Please install it.");
+
+ if (yuvscaler.exists(QString (MjpegToolsPath+"/yuvscaler")) == FALSE)
+ str = i18n("Cannot find 'yuvscaler' binary program from MjpegTools package. Please install it.");
+
+ if (mpeg2enc.exists(QString (MjpegToolsPath+"/mpeg2enc")) == FALSE)
+ str = i18n("Cannot find 'mpeg2enc' binary program from MjpegTools package. Please install it.");
+
+ if ( mplex.exists(QString (MjpegToolsPath+"/mplex")) == FALSE)
+ str = i18n("Cannot find 'mplex' binary program from MjpegTools package. Please install it.");
+
+ if (mp2enc.exists(QString (MjpegToolsPath+"/mp2enc")) == FALSE)
+ {
+ str = i18n("Cannot find 'mp2enc' binary program from MjpegTools package. Please install it.\n"
+ "Audio capabilities will be disabled.");
+ ValRet = 2;
+ }
+
+ if ( !str.isEmpty() )
+ {
+ str += i18n("\nCheck your installation and this plugin's options settings."
+ "\n\nVisit these URLs for more information:"
+ "\nImageMagick package: http://www.imagemagick.org/"
+ "\nMjpegTools package: http://mjpeg.sourceforge.net/");
+ KMessageBox::error(kapp->activeWindow(), str);
+ return (ValRet);
+ }
+
+ return (1);
+}
+
+} // NameSpace KIPIMPEGEncoderPlugin
+
+#include "checkbinprog.moc"
diff --git a/kipi-plugins/mpegencoder/checkbinprog.h b/kipi-plugins/mpegencoder/checkbinprog.h
new file mode 100644
index 0000000..30e7783
--- /dev/null
+++ b/kipi-plugins/mpegencoder/checkbinprog.h
@@ -0,0 +1,52 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// CHECKBINPROG.H
+//
+// Copyright (C) 2003 Gilles CAULIER <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef CheckBinProg_included
+#define CheckBinProg_included
+
+#include <qobject.h>
+#include <qstring.h>
+
+class KConfig;
+
+namespace KIPIMPEGEncoderPlugin
+{
+
+class CheckBinProg : public QObject
+{
+Q_OBJECT
+
+public:
+ CheckBinProg(QObject *parent=0);
+ virtual ~CheckBinProg();
+ int findExecutables( void );
+
+private:
+ KConfig* config;
+ QString ImageMagickPath;
+ QString MjpegToolsPath;
+};
+
+} // NameSpace KIPIMPEGEncoderPlugin
+
+#endif // CheckBinProg_included
+
diff --git a/kipi-plugins/mpegencoder/images2mpg b/kipi-plugins/mpegencoder/images2mpg
new file mode 100755
index 0000000..0c0d3f1
--- /dev/null
+++ b/kipi-plugins/mpegencoder/images2mpg
@@ -0,0 +1,957 @@
+#!/bin/bash
+
+# -------------------------------------------------------------------------------------------------------
+# DESCRIPTION :
+#
+# IMAGES2MPG : convert images sequence on a MPEG files for create a VCD/SVCD/XVCD/DVD portfolio (with vcdimager)
+#
+# This script use this packages : 'ImageMagick' ver >= 5.4.8 [http://www.imagemagick.org/]
+# 'MjpegTools' ver >= 1.6.0 [http://mjpeg.sourceforge.net/]
+#
+# You give the images files names on the command line (see the options '--help').
+# The images formats must be reconized by ImageMagick program.
+#
+# This script used this externals binary programs :
+#
+# - 'montage' from ImageMagick for resize the images for the TV screen size.
+# - 'composite' from ImageMagick for make the transition between images.
+# - 'convert' from ImageMagick for convert the images before MPEG encoding.
+# - 'identify' from ImageMagick for check the background image file size.
+# - 'ppmtoy4m' from MjpegTools for create a video stream from the image.
+# - 'yuvscaler' from MjpegTools for adapt the video stream size before MPEG encoding.
+# - 'mpeg2enc' from MjpegTools for encode the video stream in MPEG file.
+# - 'ogg123' from vorbis-utils to transcode an ogg-audio file to wav
+# - 'mpg123' to transcode an mp3-audio file to wav
+# - 'mp2enc' from MjpegTools to transcode a WAV sound file to a MP2 file.
+# - 'mplex' from MjpegTools for multiplexe the MPEG file and the MP2 sound and convert
+# the final MPEG file to a DVD/XVCD/SVCD/VCD format compatible with vcdimager program.
+#
+# You can use the 'KIPI' KDE frontend with this script. Look this URL : http://extragear.kde.org/apps/kipi
+#
+# Return value : 0 -> Process finish succefuly.
+# 1 -> Error.
+#
+# -------------------------------------------------------------------------------------------------------
+#
+# ABOUT VIDEO TYPES AND FORMATS SUPPORTED BY THIS SCRIPT :
+#
+# Video type :: VCD : SVCD : XVCD : DVD :
+# :: : : : : : : : :
+# Video format :: PAL/SECAM: NTSC : PAL/SECAM: NTSC : PAL/SECAM: NTSC : PAL/SECAM: NTSC :
+# :: : : : : : : : :
+# Resolution :: 352x288 : 352x240 : 576x480 : 480x480 : 720x576 : 720x480 : 720x576 : 720x480 :
+# :: : : : : : : : :
+# Frame/s :: 25 : 30 : 25 : 30 : 25 : 30 : 25 : 30 :
+# :: : : : :
+# MPEG type :: MPEG1 : MPEG2 : MPEG2 : MPEG2 :
+# :: : : : :
+# Video CDR :: 74 mn : 60 mn : 50 mn : 15 mn :
+# duration :: : : : :
+# :: : : : :
+# Video :: 1,150 kbit/s : 2,500 kbit/s : 2,500 kbit/s : 8,000 kbit/s :
+# bitrate :: : : : :
+# :: : : : :
+# Sound format :: MP2 : MP2 : MP2 : MP2 :
+# :: : : : :
+# Audio :: 224 kbit/s : 224 kbit/s : 224 kbit/s : 224 kbit/s :
+# biterate :: : : : :
+# :: : : : :
+# DVD player :: excelent : good : medium : excelent :
+# compatibility:: : : : :
+# :: : : : :
+# Image :: medium : good : excelent : excelent :
+# restitution :: : : : :
+#
+# Notes : - The XVCD resolution is the same of DVD !
+#
+# -------------------------------------------------------------------------------------------------------
+#
+# AUTHOR : CAULIER gilles <caulier dot gilles at gmail dot com>
+#
+# -------------------------------------------------------------------------------------------------------
+#
+# TODO :
+#
+# * Add an option for select PAL or NTSC video format.
+# * Add transitions betwen the images in the MPEG sequence.
+# * Write a man page file with some examples and more informations.
+# * Don't use an default external black 'PNG' background image file.
+# * Add an option with the RVB color for the background image color.
+# * Add a trap signal fonction : clear temporary files when killed.
+# * Add an option for a specific temporary folder.
+# - Add DIVX support.
+#
+# -------------------------------------------------------------------------------------------------------
+# LICENSE :
+#
+# This program is free software; you can redistribute 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 Steet, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# -------------------------------------------------------------------------------------------------------
+# CHANGELOG :
+#
+# March 2002 : Original release by Gilles CAULIER <caulier.gilles@free.fr>.
+# November 2002 : Add a convert image format fonction with ImageMagick.
+# Add resize the image for the TV screen with ImageMagick.
+# Add Endoding time measurement.
+# Add many images files on the same MPEG file.
+# Add using of temporary files.
+# Add some command line options.
+# Add encoding sound on the MPEG file.
+# December 2002 : Fix some bugs.
+# Add some command line parameters controls.
+# Add some English comments.
+# Add a video type command line option (PAL, NTSC, SECAM).
+# Remove '-F' option (frame rate value -> fixed by video type option)
+# Add an exiting test of input image files before encoding.
+# Add an exiting test of input audio files and mask file before encoding.
+# Add an exiting test if verbosity level is unknown.
+# Add image sequence duration value test.
+# Add an implementation for don't used a default 'black.png' file. ImageMagick create a
+# temporary PNG file for this.
+# Add warning if total duration is <=3 s.
+# Remove 3s image duration limitation.
+# Add test about image background size.
+# Add an option for define the background image RGB color.
+# Add a trap fonction for remove the temporary files.
+# Add a transition fonction with 'composite' binary program from ImageMagick package.
+# Add a final transition for the sequence.
+# Add this script to the MjpegTools project on sourceforge repository.
+# January 2003 : Add a manual page (on MjpegTools project package).
+# Add an option for use a temporary folder.
+# Add '--with-gui' option for run with 'kimg2mpg' KDE gui frontend program.
+# Change the IFS variable for a correct interpretation of the whitespaces in the path
+# files names.
+# Add DVD video format option.
+# Change trap fonction.
+# Change some console messages for the KDE GUI.
+# February 2003 : Update 'Kimg2mpg' KDE frontend WEB site URL.
+# September 2003: Moving to the Digikam project (http://digikam.sourceforge.net).
+# Add options for ImageMagick and MjpegTools binary folders informations.
+# October 2003 : Rename this file to 'images2mpg'.
+#
+# -------------------------------------------------------------------------------------------------------
+
+# --------------------------------------FONCTIONS--------------------------------------------------------
+
+#Clean the temporary file and exit. Used by the Trap fonction and at end of this script.
+CleanUp()
+{
+if [ $WITHGUI = 0 ]; then
+ echo -e "Removing temporary files..."
+fi
+
+if [ -e "$TMPFILENAME.tmp.m2v" ]; then
+ rm "$TMPFILENAME.tmp.m2v"
+fi
+
+if [ -e "$TMPFILENAME.tmp.jpg" ]; then
+ rm "$TMPFILENAME.tmp.jpg"
+fi
+
+if [ -e "$TMPFILENAME.tmp.pnm" ]; then
+ rm "$TMPFILENAME.tmp.pnm"
+fi
+if [ "$AUDIO_WAV" ]; then
+ if [ -e "$TMPFILENAME.tmp.wav" ]; then
+ rm "$TMPFILENAME.tmp.wav"
+ fi
+
+ if [ -e "$TMPFILENAME.tmp.mp2" ]; then
+ rm "$TMPFILENAME.tmp.mp2"
+ fi
+fi
+
+if [ "$MASK"="$TMPFILENAME.black.tmp.png" ]; then
+ if [ -e "$MASK" ]; then
+ rm "$MASK"
+ fi
+fi
+
+if [ $TRANSITIONENABLE = 1 ]; then
+ if [ -e "$TMPFILENAME.prev_trans.tmp.pnm" ]; then
+ rm "$TMPFILENAME.prev_trans.tmp.pnm"
+ fi
+ if [ -e "$TMPFILENAME.next_trans.tmp.pnm" ]; then
+ rm "$TMPFILENAME.next_trans.tmp.pnm"
+ fi
+fi
+
+exit 0
+}
+
+
+# ------------------------------------END OF FONCTIONS---------------------------------------------------
+
+# --------------------------------------MAIN-------------------------------------------------------------
+
+# Trap shell signals fonction.
+
+trap CleanUp 2
+
+# Default parameters values.
+
+# Default MPEG video format.
+VIDEO_FORMAT="XVCD"
+
+# Default video type.
+VIDEO_TYPE="PAL"
+
+#Default Chroma subsampling mode (ppmtoy4m)
+PPMTOY4M_CHROMA_OPT="-S 420mpeg2"
+
+# Default verbosity level .
+# 0 -> Just the error messages or warnings.
+# 1 -> level 0 + informations messages.
+# 2 -> level 1 + debug messages.
+VERBOSE=0
+
+# Default duration for one image in the MPEG sequence. Minimal value is 1s.
+IMAGEDURATION=10
+
+# Default transition parameters.
+TRANSITIONENABLE=0
+TRANSITIONDURATION=0
+
+# Default temporary folder is local folder.
+TEMPORARYFOLDER=""
+
+# Default ImageMagick binary folder -> using PATH variable.
+IMBINFOLDER=""
+
+# Default MJPEGTools binary folder -> using PATH variable.
+MJPEGTBINFOLDER=""
+
+# Not running with 'KIPI' KDE gui frontend.
+WITHGUI=0
+
+# Command line parameters analyse...
+CPT_IMG_FILE=0
+
+if [ $# == 0 ]; then
+ echo -e "No option specified... 'images2mpg -h' for more informations."
+ exit 1
+fi
+
+while test $# -gt 0; do
+ OPTIONMESSAGE=$1
+
+ case $1 in
+
+ # Verbosity...
+ -v)
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ VERBOSE=$1
+ ;;
+
+ # Running with 'KIPI' KDE frontend...
+ --with-gui)
+ WITHGUI=1
+ ;;
+
+ # Temporary folder...
+ -T)
+ OLD_IFS=$IFS
+ IFS="\""
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ TEMPORARYFOLDER=$1
+ IFS=$OLD_IFS
+ ;;
+
+ # Transition between images...
+ -t)
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+
+ if [ $[$1 == 1 || $1 == 2 || $1 == 4 || $1 == 5 || $1 == 10 || $1 == 20] = 1 ]; then
+ # Increment value for dissolving the images with the transition.
+ DISSOLVEVALUEINC=$1
+ TRANSITIONENABLE=1
+ else
+ echo -e "Bad transition speed value (must be 1, 2, 4, 5, 10, or 20) !"
+ exit -1
+ fi
+ ;;
+
+ # Video format...
+ -f)
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ VIDEO_FORMAT=$1
+ ;;
+
+ # Video type...
+ -n)
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ VIDEO_TYPE=$1
+ ;;
+
+ # Chroma subsampling mode (ppmtoy4m option)...
+ -S)
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ PPMTOY4M_CHROMA_OPT="-S $1"
+ ;;
+
+ # Background image file...
+ -b)
+ OLD_IFS=$IFS
+ IFS="\""
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ if [ -s $1 ]; then
+ MASKGEOMETRY=`$IDENTIFY_BIN -verbose $1 |grep Geometry |awk '{print $2}'`
+ if [ $MASKGEOMETRY != "768x576" ]; then
+ echo -e "The size of background image file '$1' isn't 768x576 pixels [$MASKGEOMETRY]!!!"
+ exit -1
+ else
+ MASK=$1
+ fi
+ else
+ echo -e "The background image file '$1' don't exist or can't be open !!!"
+ exit -1
+ fi
+ IFS=$OLD_IFS
+ ;;
+
+ # Background color...
+ -c)
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ else
+ BACKGROUNDCOLOR=$1
+ fi
+ ;;
+
+ # Images duration...
+ -d)
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ IMAGEDURATION=$1
+ if [ $[$IMAGEDURATION == 0] = 1 ]; then
+ echo -e "Image duration value must be >= 1 !"
+ exit -1
+ fi
+ ;;
+
+ # MP2 audio file...
+ -a)
+ OLD_IFS=$IFS
+ IFS="\""
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ if [ -s $1 ]; then
+ AUDIO_MPEG=$1
+ else
+ echo -e "The MP2 audio file '$1' don't exist or can't be open !!!"
+ exit -1
+ fi
+ IFS=$OLD_IFS
+ ;;
+
+ # WAV/MP3/OGG audio file...
+ -w)
+ OLD_IFS=$IFS
+ IFS="\""
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ if [ -s $1 ]; then
+ AUDIO_WAV=$1
+ else
+ echo -e "The WAV/OGG/MP3 audio file '$1' don't exist or can't be open !!!"
+ exit -1
+ fi
+ IFS=$OLD_IFS
+ ;;
+
+ # MPEG output file...
+ -o)
+ OLD_IFS=$IFS
+ IFS="\""
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ OUTPUT_MPEG_FILE=$1
+ IFS=$OLD_IFS
+ ;;
+
+ # Image input files...
+ -i)
+ OLD_IFS=$IFS
+ IFS="\""
+ shift
+ while [ $1 ]; do
+ INPUT_IMAGE_FILES[CPT_IMG_FILE]=$1
+ CPT_IMG_FILE=`echo $(($CPT_IMG_FILE+1))`
+ shift
+ done
+ IFS=$OLD_IFS
+ ;;
+
+ # MJPEGTools binary folder...
+ -M)
+ OLD_IFS=$IFS
+ IFS="\""
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ MJPEGTBINFOLDER=$1
+ IFS=$OLD_IFS
+ ;;
+
+ # ImageMagick binary folder...
+ -I)
+ OLD_IFS=$IFS
+ IFS="\""
+ shift
+ if [ -z $1 ]; then
+ echo -e "Missing parameter after '$OPTIONMESSAGE' option !"
+ exit -1
+ fi
+ IMBINFOLDER=$1
+ IFS=$OLD_IFS
+ ;;
+
+ # Help...
+ -h | --help)
+ cat << EOF
+
+IMAGES2MPG [KIPI Project] - MPEG portfolio images multiplexer.
+
+Usage: images2mpg [options] -o <output MPEG file> -i <input image files>
+
+Options:
+ -v <num> : verbose level [0:none=default, 1:infos+warnings, 2:debug].
+ --with-gui : running with 'KIPI' KDE GUI frontend [see http://extragear.kde.org/apps/kipi].
+ -t <num> : enable transition between images with the speed [1=slow, 2, 4, 5, 10, 20=fast].
+ -T <Temporary folder> : use a specific folder for creating the temporary files (ex: '/tmp').
+ -f <Video format> : video format [DVD, XVCD=default, SVCD, VCD].
+ -S <mode> : Set chroma subsampling mode. (default value depends on ppmtoy4m version)
+ [444 - 4:4:4 (no subsampling)
+ 420jpeg - 4:2:0 JPEG/MPEG-1, interstitial cositing
+ 420mpeg2 - 4:2:0 MPEG-2, horizontal cositing]
+ -n <Video type> : video type [PAL=default, NTSC, SECAM].
+ -b <background file> : 768x576 pixels background image file name [black color = default].
+ -c <RGB color> : hex RGB color for background image (ex: AA001F).
+ -d <num> : duration for each image in MPEG file [10s = default, 1s = mini].
+ -a <MP2 audio file> : MP2 audio file to merge with the video sequence.
+ -w <wav|ogg|mp3 audio file> : WAV/OGG/MP3 audio file to convert in MP2 and to merge with the video sequence.
+ -o <output MPEG file> : the ouput MPEG file name [temporary file name = default].
+ -i <input images files> : images files name to merge in MPEG.
+ -I <ImageMagick bin folder> : folder for ImageMagick binary programs.
+ -M <MjpegTools bin folder> : folder for MjpegTools binary programs.
+ -h | --help : this help.
+
+The 'images2mpg' bash script convert some images on MPEG sequences with a specific
+duration and merge all images on an single MPEG file. It use the 'MjpegTools' &
+'ImageMagick' packages.
+You can use this for to build some DVD/XVCD/SVCD/VCD portfolios for your home DVD player.
+Use 'vcdimager' for create this...
+
+Notes :
+
+ - The input images files with the '-i' option must be the last command line parameters.
+ - If you use some whitespaces in the path folders/files, use '"' around the complete path string.
+ - With mjpegtools > 1.6.2 ppmtoy4m seems to have changed the default behavior for chroma subsampling
+ mode so '-S' option is needed
+
+Examples :
+
+#./images2mpg -f SVCD -d 15 -S 420mpeg2 -w Music.wav -o MyPortfolio.mpg -i 01.jpg 02.jpg 03.jpg 04.jpg
+
+ Build PAL (default) SVCD MPEG file with the 'Music.wav' sound file and this image files sequence :
+
+ 01.jpg
+ 02.jpg
+ 03.jpg
+ 04.jpg
+
+ For each image on the portfolio, the screen show duration is 15 seconds. The output file
+ is 'MyPortfolio.mpg'. There isn't transition between images.
+
+#./images2mpg -n NTSC -t 2 -o MyPortfolio.mpg -i *.png
+
+ Build XVCD (default) NTSC MPEG file with a transition between image (speed 2) and all
+ local PNG images files. The image files sequence use the local filesystem sort.
+
+Author:
+ CAULIER Gilles <caulier.gilles@free.fr>
+
+Visit :
+ URL PROJECT : http://extragear.kde.org/apps/kipi
+ WEBSVN : http://websvn.kde.org/trunk/extragear/libs/kipi-plugins/mpegencoder
+
+EOF
+ exit 0
+ ;;
+
+ # Unknown option...
+ -?*)
+ echo "Option '$1' not recognized..."
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+if [ $WITHGUI = 1 ]; then
+ echo -e "Initialising...\n" >&2
+fi
+
+# Initialising full binary programs paths for ImageMagick and MJPEGTools.
+
+if [ -z "$IMBINFOLDER" ]; then
+ MONTAGE_BIN="montage"
+ COMPOSITE_BIN="composite"
+ CONVERT_BIN="convert"
+ IDENTIFY_BIN="identify"
+ #TODO add a check also when they are in the path mayby using which command
+else
+ MONTAGE_BIN="$IMBINFOLDER/montage"
+ COMPOSITE_BIN="$IMBINFOLDER/composite"
+ CONVERT_BIN="$IMBINFOLDER/convert"
+ IDENTIFY_BIN="$IMBINFOLDER/identify"
+
+ # check if programs are installed
+ if [ ! -e $MONTAGE_BIN ]; then
+ echo -e "\nCan't find $MONTAGE_BIN, please install it or check -I parameter"
+ exit -1
+ fi
+ if [ ! -e $COMPOSITE_BIN ]; then
+ echo -e "\nCan't find $COMPOSITE_BIN, please install it or check -I parameter"
+ exit -1
+ fi
+ if [ ! -e $CONVERT_BIN ]; then
+ echo -e "\nCan't find $CONVERT_BIN, please install it or check -I parameter"
+ exit -1
+ fi
+ if [ ! -e $IDENTIFY_BIN ]; then
+ echo -e "\nCan't find $IDENTIFY_BIN, please install it or check -I parameter"
+ exit -1
+ fi
+fi
+
+
+if [ -z "$MJPEGTBINFOLDER" ]; then
+ PPMTOY4M_BIN="ppmtoy4m"
+ YUVSCALER_BIN="yuvscaler"
+ MPEG2ENC_BIN="mpeg2enc"
+ MP2ENC_BIN="mp2enc"
+ OGG_BIN="ogg123"
+ MP3_BIN="mpg123"
+ MPLEX_BIN="mplex"
+else
+ PPMTOY4M_BIN="$MJPEGTBINFOLDER/ppmtoy4m"
+ YUVSCALER_BIN="$MJPEGTBINFOLDER/yuvscaler"
+ MPEG2ENC_BIN="$MJPEGTBINFOLDER/mpeg2enc"
+ MP2ENC_BIN="$MJPEGTBINFOLDER/mp2enc"
+ OGG_BIN="$MJPEGTBINFOLDER/ogg123"
+ MP3_BIN="$MJPEGTBINFOLDER/mpg123"
+ MPLEX_BIN="$MJPEGTBINFOLDER/mplex"
+fi
+# check if programs are installed
+if [ ! -e $PPMTOY4M_BIN ]; then
+ echo -e "\nCan't find $PPMTOY4M_BIN, please install it or check -M parameter"
+ exit -1
+fi
+if [ ! -e $YUVSCALER_BIN ]; then
+ echo -e "\nCan't find $YUVSCALER_BIN, please install it or check -M parameter"
+ exit -1
+fi
+if [ ! -e $MPEG2ENC_BIN ]; then
+ echo -e "\nCan't find $MPEG2ENC_BIN, please install it or check -M parameter"
+ exit -1
+fi
+if [ ! -e $MP2ENC_BIN ]; then
+ echo -e "\nCan't find $MP2ENC_BIN, please install it or check -M parameter"
+ exit -1
+fi
+if [ ! -e $OGG_BIN ]; then
+ echo -e "\nCan't find $OGG_BIN, please install it or check -M parameter"
+ exit -1
+fi
+if [ ! -e $MP3_BIN ]; then
+ echo -e "\nCan't find $MP3_BIN, please install it or check -M parameter"
+ exit -1
+fi
+if [ ! -e $MPLEX_BIN ]; then
+ echo -e "\nCan't find $MPLEX_BIN, please install it or check -M parameter"
+ exit -1
+fi
+
+# Verify if some images file have been given on the command line.
+if [ $CPT_IMG_FILE = 0 ]; then
+ echo -e "\nNo image file to convert !!!"
+ exit -1
+else
+ if [ $WITHGUI = 0 ]; then
+ echo -e "------------------------------------------------"
+ echo -e "\nNumber of image file(s) : $CPT_IMG_FILE."
+ echo -e "Processing sequence :"
+ fi
+
+ CPT=$CPT_IMG_FILE
+
+ while test $CPT -gt 0; do
+ INPUT_FILE_NAME="${INPUT_IMAGE_FILES[`echo $(($CPT_IMG_FILE-CPT))`]}"
+ if [ $WITHGUI = 0 ]; then
+ echo -e "$INPUT_FILE_NAME"
+ fi
+ if [ -s "$INPUT_FILE_NAME" ]; then
+ CPT=`echo $(($CPT-1))`
+ else
+ echo -e "The image file '$INPUT_FILE_NAME' don't exist or can't be open !!!"
+ exit -1
+ fi
+ done
+fi
+
+# Start encoding time mesurement.
+DATE_DEBUT=`date +%s`
+
+# For the mutisessions of this script, we use the number of seconds behind 1970 for the temporary name files.
+if [ -z "$TEMPORARYFOLDER" ]; then
+ TMPFILENAME="$DATE_DEBUT"
+else
+ TMPFILENAME="$TEMPORARYFOLDER/$DATE_DEBUT"
+fi
+
+# Number of video type for MjpegTools. The possibles values are :
+#
+# 0 -> MPEG1 generic. -> not used.
+# 1 -> VCD standard MPEG1 (PAL/SECAM:352x288 - NTSC:352x240). -> VCD.
+# 2 -> VCD no standard. -> not used.
+# 3 -> MPEG2 generic. -> not used.
+# 4 -> VCD standard MPEG2 (PAL/SECAM:576x480 - NTSC:480x480). -> SVCD.
+# 5 -> SVCD no standard (PAL/SECAM:720x576 - NTSC:720x480). -> XVCD.
+# 6 -> VCD with fixed images (Still Frame). -> not used.
+# 7 -> SVCD with fixed images (Still Frame). -> not used.
+# 8 -> DVD MPEG2 (PAL/SECAM:720x576 - NTSC:720x480). -> DVD.
+
+case $VIDEO_TYPE in
+ PAL)
+ VIDEO_TYPE_LETTER="p"
+ IMAGES_SEC=25
+ IMAGES_SEC_FORMAT="25:1"
+ ;;
+ NTSC)
+ VIDEO_TYPE_LETTER="n"
+ IMAGES_SEC=30
+ IMAGES_SEC_FORMAT="30000:1001"
+ ;;
+ SECAM)
+ VIDEO_TYPE_LETTER="s"
+ IMAGES_SEC=25
+ IMAGES_SEC_FORMAT="25:1"
+ ;;
+ *)
+ echo "Video type '$VIDEO_TYPE' not recognized..."
+ exit 1
+ ;;
+esac
+
+case $VIDEO_FORMAT in
+ VCD)
+ VIDEO_FORMAT_NUMBER=1
+ BIT_RATE=1150
+ BUFFER_SIZE=46
+ VIDEOFORMAT_MESSAGE="VCD"
+ AUDIO_WAVE_CONVERSION="-V"
+ ;;
+ SVCD)
+ VIDEO_FORMAT_NUMBER=4
+ BIT_RATE=2500
+ BUFFER_SIZE=230
+ VIDEOFORMAT_MESSAGE="SVCD"
+ AUDIO_WAVE_CONVERSION="-V"
+ ;;
+ XVCD)
+ VIDEO_FORMAT_NUMBER=5
+ if [ $VIDEO_TYPE = "NTSC" ]; then
+ VIDEO_FORMAT="SIZE_720x480"
+ else
+ VIDEO_FORMAT="SIZE_720x576"
+ fi
+ BIT_RATE=2500
+ BUFFER_SIZE=230
+ VIDEOFORMAT_MESSAGE="XVCD"
+ AUDIO_WAVE_CONVERSION="-V"
+ ;;
+ DVD)
+ VIDEO_FORMAT_NUMBER=8
+ if [ $VIDEO_TYPE = "NTSC" ]; then
+ VIDEO_FORMAT="SIZE_720x480"
+ else
+ VIDEO_FORMAT="SIZE_720x576"
+ fi
+ BIT_RATE=8000
+ BUFFER_SIZE=230
+ VIDEOFORMAT_MESSAGE="DVD"
+ AUDIO_WAVE_CONVERSION="-b 224 -r 48000 -s"
+ ;;
+ *)
+ echo "Video format '$VIDEO_FORMAT' not recognized..."
+ exit 1
+ ;;
+esac
+
+case $VERBOSE in
+ 0)
+ VERBOSITY="none"
+ ;;
+ 1)
+ VERBOSITY="errors & warning"
+ ;;
+ 2)
+ VERBOSITY="debug"
+ ;;
+ *)
+ echo "Invalid verbosity level '$VERBOSE'..."
+ exit 1
+ ;;
+esac
+
+# Creating the temporary default background file image. It's used by ImageMagick when it
+# resizing image for the TV screen dimensions. ImageMagick add a border around the image with this.
+# ImageMagick create this temporary background image file only if you don't give a specific backgroung
+# image name on the command line.
+
+if [ -z "$MASK" ]; then
+ if [ -z $BACKGROUNDCOLOR ]; then
+ BACKGROUNDCOLOR="000000"
+ fi
+ MASK="$TMPFILENAME.black.tmp.png"
+ RET=`$CONVERT_BIN xc:#$BACKGROUNDCOLOR -resize '768x576!' "$MASK"`
+fi
+
+# Calculating the number of frames for one image sequence duration and the images number.
+# Append all images on a MPEG file.
+
+NBFRAMEIMAGE=`echo $(($IMAGEDURATION*$IMAGES_SEC))`
+if [ $TRANSITIONENABLE = 1 ]; then
+ NBFRAMETRANSITION=`echo $((100/$DISSOLVEVALUEINC))`
+else
+ NBFRAMETRANSITION=0
+fi
+TRANSITIONDURATION=`echo $(($NBFRAMETRANSITION/$IMAGES_SEC))`
+NBFRAMETOTAL=`echo $(((($NBFRAMEIMAGE+$NBFRAMETRANSITION)*$CPT_IMG_FILE)+$NBFRAMETRANSITION))`
+TOTALDURATION=`echo $(((($IMAGEDURATION+$TRANSITIONDURATION)*$CPT_IMG_FILE)+$TRANSITIONDURATION))`
+
+WARNINGTOTALDURATION=""
+if [ $[$TOTALDURATION <= 3] = 1 ]; then
+ WARNINGTOTALDURATION="(WARNING : total duration <= 3s !!!)"
+fi
+
+if [ $WITHGUI = 0 ]; then
+ echo -e "Video format : '$VIDEOFORMAT_MESSAGE'."
+ echo -e "Video type : '$VIDEO_TYPE'."
+ if [ "$AUDIO_MPEG" ]; then
+ echo -e "MPEG audio file : '$AUDIO_MPEG'."
+ fi
+ if [ "$AUDIO_WAV" ]; then
+ echo -e "WAV audio file : '$AUDIO_WAV'."
+ fi
+ echo -e "Frames per second : '$IMAGES_SEC'."
+ echo -e "Image duration : $IMAGEDURATION s."
+ echo -e "Total video sequence duration : $TOTALDURATION s $WARNINGTOTALDURATION."
+ if [ $TRANSITIONENABLE = 1 ]; then
+ echo -e "Transition frames : $NBFRAMETRANSITION."
+ fi
+ echo -e "Total frames processing : $NBFRAMETOTAL."
+ echo -e "Background image file : '$MASK'."
+ echo -e "Verbosity : '$VERBOSITY'.\n"
+ echo -e "------------------------------------------------"
+fi
+
+# Creating a MPEG flux with the images.
+
+if [ $WITHGUI = 0 ]; then
+ echo -e "Encoding $CPT_IMG_FILE image(s) MPEG sequence with ImageMagick and MjpegTools.\n"
+else
+ echo -e "Encoding image files...\n" >&2
+fi
+
+# Counter of frames for the MPEG conversion.
+CPT=0
+
+# Counter of image input files for the MPEG conversion.
+CPF=1
+
+# Counter of dissolve values.
+CPD=0
+
+# Initial dissolve value (%).
+DISSOLVEVALUE=99
+
+if [ $TRANSITIONENABLE = 1 ]; then
+ $CONVERT_BIN -type TrueColor -quality 100 "$MASK" "$TMPFILENAME.prev_trans.tmp.pnm"
+ INPUT_IMAGE_FILES[`echo $(($CPT_IMG_FILE))`]="$MASK"
+ CPT_IMG_FILE=`echo $(($CPT_IMG_FILE+1))`
+fi
+
+while test $CPT -lt $NBFRAMETOTAL;\
+ do
+ CPT=`echo $(($CPT+1))`
+
+ # For debugging...
+ # echo -ne "Frame Num. $CPT / $NBFRAMETOTAL - DISSOLVE=$DISSOLVEVALUE - Image Num. $CPF / $CPT_IMG_FILE ["${INPUT_IMAGE_FILES[`echo $(($CPF-1))`]}"] \n" >&2
+
+ if [ $WITHGUI = 0 ]; then
+ echo -ne "Frame Num. $CPT / $NBFRAMETOTAL \r" >&2
+ else
+ COUNTERGUI=`echo $((($CPT*100)/$NBFRAMETOTAL))`
+ echo -ne "Images encoding (%) : $COUNTERGUI [`echo $(($CPF-1))` \n" >&2
+ fi
+
+ if [ $TRANSITIONENABLE = 0 ]; then
+ if [ $CPT = `echo $((($CPF*$NBFRAMEIMAGE)-$NBFRAMEIMAGE+1))` ]; then
+
+ # Conversion and resizing the curent image file with ImageMagick.
+ $MONTAGE_BIN -type TrueColor -quality 100 -geometry 768x576 -texture "$MASK" "${INPUT_IMAGE_FILES[`echo $(($CPF-1))`]}" "$TMPFILENAME.tmp.jpg"
+ $CONVERT_BIN -type TrueColor -quality 100 "$TMPFILENAME.tmp.jpg" "$TMPFILENAME.tmp.pnm"
+
+ # Next input image...
+ CPF=`echo $(($CPF+1))`
+ fi
+
+ else
+ if [ $[$CPT >= `echo $((($CPF*($NBFRAMEIMAGE+$NBFRAMETRANSITION)-$NBFRAMEIMAGE-$NBFRAMETRANSITION)))`] = 1 ]; then
+ if [ $[$CPT <= `echo $((($CPF*($NBFRAMEIMAGE+$NBFRAMETRANSITION)-$NBFRAMEIMAGE)))`] = 1 ]; then
+
+ if [ $DISSOLVEVALUE = 99 ]; then
+ $MONTAGE_BIN -type TrueColor -quality 100 -geometry 768x576 -texture "$MASK" "${INPUT_IMAGE_FILES[`echo $(($CPF-1))`]}" "$TMPFILENAME.tmp.jpg"
+ $CONVERT_BIN -type TrueColor -quality 100 "$TMPFILENAME.tmp.jpg" "$TMPFILENAME.next_trans.tmp.pnm"
+ fi
+
+ $COMPOSITE_BIN "$TMPFILENAME.prev_trans.tmp.pnm" "$TMPFILENAME.next_trans.tmp.pnm" -type TrueColor -quality 100 -dissolve $DISSOLVEVALUE "$TMPFILENAME.tmp.pnm"
+
+ if [ $CPD = `echo $(($NBFRAMETRANSITION-1))` ]; then
+
+ # Next input image...
+ CPF=`echo $(($CPF+1))`
+
+ DISSOLVEVALUE=99
+ CPD=0
+ cp -f "$TMPFILENAME.next_trans.tmp.pnm" "$TMPFILENAME.prev_trans.tmp.pnm"
+ mv -f "$TMPFILENAME.next_trans.tmp.pnm" "$TMPFILENAME.tmp.pnm"
+ else
+ CPD=`echo $(($CPD+1))`
+ DISSOLVEVALUE=`echo $((100-($CPD*$DISSOLVEVALUEINC)))`
+ fi
+ fi
+ fi
+ fi
+
+ # MjpegTools MPEG encoding with the number of frames and the current image.
+ $CONVERT_BIN -depth 8 ppm:"$TMPFILENAME.tmp.pnm" - | cat
+
+ done | $PPMTOY4M_BIN -v $VERBOSE -n $NBFRAMETOTAL -F $IMAGES_SEC_FORMAT $PPMTOY4M_CHROMA_OPT | $YUVSCALER_BIN -v $VERBOSE -n $VIDEO_TYPE_LETTER -O $VIDEO_FORMAT | $MPEG2ENC_BIN -v $VERBOSE -n $VIDEO_TYPE_LETTER -b $BIT_RATE -V $BUFFER_SIZE -f $VIDEO_FORMAT_NUMBER -o "$TMPFILENAME.tmp.m2v"
+
+DATE_FIN=`date +%s`
+TEMPSCALCUL=`echo $(($DATE_FIN-DATE_DEBUT))`
+
+if [ $WITHGUI = 0 ]; then
+ echo -e "\nMPEG encoding terminated [$NBFRAMETOTAL frames - Encoding time : $TEMPSCALCUL s]."
+fi
+
+# Building sound track if necessary...
+
+AUDIOFILENAME=""
+
+if [ "$AUDIO_MPEG" ]; then
+ AUDIOFILENAME="$AUDIO_MPEG"
+else
+ if [ "$AUDIO_WAV" ]; then
+ if [ $WITHGUI = 0 ]; then
+ echo -e "\nEncoding MPG layer 2 audio file from $AUDIO_WAV WAV file with MjpegTools."
+ else
+ echo -e "\nEncoding audio file...\n" >&2
+ fi
+ file -i "$AUDIO_WAV" | grep "audio/x-wav" && cp -f "$AUDIO_WAV" "$TMPFILENAME.tmp.wav"
+ file -i "$AUDIO_WAV" | grep "application/ogg" && $OGG_BIN -q -d wav -f "$TMPFILENAME.tmp.wav" "$AUDIO_WAV"
+ file -i "$AUDIO_WAV" | grep "audio/mpeg" && $MP3_BIN -q -w "$TMPFILENAME.tmp.wav" "$AUDIO_WAV"
+ cat "$TMPFILENAME.tmp.wav" | $MP2ENC_BIN -v $VERBOSE $AUDIO_WAVE_CONVERSION -o "$TMPFILENAME.tmp.mp2"
+ AUDIOFILENAME="$TMPFILENAME.tmp.mp2"
+ fi
+fi
+
+# Video and audio streams final merge for VCDImager compatibility.
+
+if [ $WITHGUI = 0 ]; then
+ echo -e "\nMerging MPEG flux with MjpegTools."
+else
+ echo -e "\nMerging MPEG flux..." >&2
+fi
+
+# No output MPEG file name on command line -> take a temporary file.
+if [ -z "$OUTPUT_MPEG_FILE" ]; then
+ OUTPUT_MPEG_FILE="$TMPFILENAME.mpg"
+fi
+
+if [ "$AUDIOFILENAME" ]; then
+ $MPLEX_BIN -v $VERBOSE -f $VIDEO_FORMAT_NUMBER -b $BUFFER_SIZE "$AUDIOFILENAME" "$TMPFILENAME.tmp.m2v" -o "$OUTPUT_MPEG_FILE"
+else
+ $MPLEX_BIN -v $VERBOSE -f $VIDEO_FORMAT_NUMBER -b $BUFFER_SIZE "$TMPFILENAME.tmp.m2v" -o "$OUTPUT_MPEG_FILE"
+fi
+
+if [ $WITHGUI = 0 ]; then
+ echo -e "\nThe video MPEG output file is '$OUTPUT_MPEG_FILE'."
+else
+ echo -e "\nEncoding terminated..." >&2
+fi
+
+# Clean up & Bye...
+CleanUp
+
+# --------------------------------------END OF MAIN----------------------------------------------------------
diff --git a/kipi-plugins/mpegencoder/images2mpg.1 b/kipi-plugins/mpegencoder/images2mpg.1
new file mode 100644
index 0000000..33ea511
--- /dev/null
+++ b/kipi-plugins/mpegencoder/images2mpg.1
@@ -0,0 +1,192 @@
+.\" MPEG portfolio images multiplexer from Digikam package
+.TH "images2mpg" "1" "29 September 2003" "Gilles CAULIER" "Digikam tools manual"
+.SH "NAME"
+.LP
+images2mpg \- MPEG portfolio images multiplexer
+.SH "SYNTAX"
+.LP
+images2mpg [\fI options \fP] \fB\-o\fR <\fIoutput MPEG file\fP> \fB\-i\fR <\fIinput image files\fP>
+.SH "REQUIREMENTS"
+.LP
+This script use this packages :
+.LP
+ImageMagick version >= 5.4.8 [ http://www.imagemagick.org/ ]
+.br
+MjpegTools version >= 1.6.0 [ http://mjpeg.sourceforge.net/ ]
+.LP
+With this packages, 'images2mpg' use this externals binary programs :
+
+\- 'montage' from ImageMagick for resize the images for the TV screen size.
+.br
+\- 'composite' from ImageMagick for make the transition between images.
+.br
+\- 'convert' from ImageMagick for convert the images before MPEG encoding.
+.br
+\- 'identify' from ImageMagick for check the background image file size.
+.br
+\- 'ppmtoy4m' from MjpegTools for create a video stream from the image.
+.br
+\- 'yuvscaler' from MjpegTools for adapt the video stream size before MPEG encoding.
+.br
+\- 'mpeg2enc' from MjpegTools for encode the video stream in MPEG file.
+.br
+\- 'mp2enc' from MjpegTools for encode on a MP2 file a WAV sound file if necessary.
+.br
+\- 'mplex' from MjpegTools for multiplex the MPEG file and the MP2 sound and convert the final MPEG file to a DVD/XVCD/SVCD/VCD format compatible with vcdimager program.
+.SH "DESCRIPTION"
+.LP
+The 'images2mpg' bash script convert some images on MPEG sequences with a specific duration and merge all images on an single MPEG file. It use the MjpegTools and ImageMagick packages.
+.LP
+Between the images, you can insert a basic transition. You can also add an audio track on the images sequence with a MP2 or WAV file.
+.LP
+All images will be automatically scaling to the good size for the video format. Also a specific background color or a image file could be used.
+.LP
+You can use this for to build some DVD/XVCD/SVCD/VCD portfolios for your home DVD player. Use 'vcdimager' for create this...
+.LP
+The video types and formats supported by this script are :
+.LP
+\fBVCD\fR :
+.LP
+ Resolution : 352x288 (PAL/SECAM) / 352x240 (NTSC).
+ Frames / s : 25 (PAL/SECAM) / 30 (NTSC).
+ MPEG type : MPEG\-1.
+ Video CDR duration (650Mb) : 74 minutes.
+ Video bitrate : 1,150 kbit/s.
+ Sound format : MP2.
+ Audio bitrate : 224 kbit/s.
+ DVD player compatibility : medium.
+ Image restitution : medium.
+.LP
+\fBSVCD\fR :
+.LP
+ Resolution : 576x480 (PAL/SECAM) / 480x480 (NTSC).
+ Frames / s : 25 (PAL/SECAM) / 30 (NTSC).
+ MPEG type : MPEG\-2.
+ Video CDR duration (650Mb): 60 minutes.
+ Video bitrate : 2,500 kbit/s.
+ Sound format : MP2.
+ Audio bitrate : 224 kbit/s.
+ DVD player compatibility : good.
+ Image restitution : good.
+.LP
+\fBXVCD\fR :
+.LP
+ Resolution : 720x576 (PAL/SECAM) / 720x480 (NTSC).
+ Frames / s : 25 (PAL/SECAM) / 30 (NTSC).
+ MPEG type : MPEG\-2.
+ Video CDR duration (650Mb) : 50 minutes.
+ Video bitrate : 2,500 kbit/s.
+ Sound format : MP2.
+ Audio bitrate : 224 kbit/s.
+ DVD player compatibility : medium.
+ Image restitution : excelent.
+.LP
+\fBDVD\fR :
+.LP
+ Resolution : 720x576 (PAL/SECAM) / 720x480 (NTSC).
+ Frames / s : 25 (PAL/SECAM) / 30 (NTSC).
+ MPEG type : MPEG\-2.
+ Video CDR duration (650Mb) : 15 minutes.
+ Video bitrate : 8,000 kbit/s.
+ Sound format : MP2.
+ Audio bitrate : 224 kbit/s.
+ DVD player compatibility : excelent.
+ Image restitution : excelent.
+
+Note : The XVCD resolution is the same of DVD !
+.SH "OPTIONS"
+.LP
+\fB\-v\fR <\fInum\fP> : verbose level on the console. The possible values are '0' for none (default), '1' for informations and warnings, or '2' for debug messages.
+
+\fB\-\-with\-gui\fR : running with the 'Digikam' KDE GUI frontend. Specifics messages will be showing on the console. For more informations about Digikam, see this URL : http://digikam.sourceforge.net
+
+\fB\-t\fR <\fInum\fP> : enable transition between images with a specific speed. The possible speed values are '1' for slow, '2', '4', '5', '10', or '20' for fast. When you enable this option, the script make with ImageMagick package a beautiful merging transition between images. Warning : it's a long calculating process.
+
+The transitions durations are :
+
+Speed '1' : PAL/SECAM (25 f/s) = 4000 ms | NTSC (30 f/s) = 3333 ms.
+.br
+Speed '2' : PAL/SECAM (25 f/s) = 2000 ms | NTSC (30 f/s) = 1666 ms.
+.br
+Speed '4' : PAL/SECAM (25 f/s) = 1000 ms | NTSC (30 f/s) = 0833 ms.
+.br
+Speed '5' : PAL/SECAM (25 f/s) = 0800 ms | NTSC (30 f/s) = 0666 ms.
+.br
+Speed '10' : PAL/SECAM (25 f/s) = 0400 ms | NTSC (30 f/s) = 0333 ms.
+.br
+Speed '20' : PAL/SECAM (25 f/s) = 0200 ms | NTSC (30 f/s) = 0166 ms.
+
+\fB\-T\fR <\fITemporary folder\fP> : use a specific folder for create the temporary files ('/tmp' for example). If you don't use this option, all temporary files will be created in the current active folder.
+
+\fB\-f\fR <\fIVideo format\fP> : MPEG video format. The possible values are 'DVD', 'XVCD' (default), 'SVCD', or 'VCD'. See the DESCRIPTION section for more details.
+
+\fB\-n\fR <\fIVideo type\fP> : video type for your TV screen. The possible values are 'PAL' (default), 'NTSC', or 'SECAM'.
+
+\fB\-b\fR <\fIbackground file\fP> : specify the 768x576 pixels background image file name. If you don't use this option, a default temporary black image file will be used.
+
+\fB\-c\fR <\fIRGB color\fP> : if you don't use the background image file, you can change the default background color (black = default). Use an hexadecimal RGB color value (example : AA001F).
+
+\fB\-d\fR <\fInum\fP> : duration for each image in MPEG file. The default value is 10 secondes. The minimal value is 1 secondes.
+
+\fB\-a\fR <\fIMPEG audio file\fP> : MP2 audio file to merge with the video sequence.
+
+\fB\-w\fR <\fIwav audio file\fP> : WAV audio file will be converted in MP2 file and merging with the video sequence.
+
+\fB\-o\fR <\fIoutput MPEG file\fP> : the ouput MPEG file name. If you don't use this option, a temporary file will be created.
+
+\fB\-i\fR <\fIinput images files\fP> : images files name to merge in MPEG.
+
+\fB\-I\fR <\fIImageMagick bin folder\fP> : folder for ImageMagick binary programs.
+
+\fB\-M\fR <\fIMjpegtools bin folder\fP> : folder for MjpegTools binary programs.
+
+\fB\-h | \-\-help\fR : output help information and exit.
+
+Notes :
+
+\- The \fB\-i\fR option must be the last option in the command line.
+.br
+\- If you use some whitespaces in the path folders/files, use '"' around the complete path string.
+.br
+.SH "RETURN VALUES"
+.LP
+0 \-> Process finish succefuly.
+.br
+1 \-> Error.
+.SH "EXAMPLES"
+.LP
+\fB# images2mpg \-f SVCD \-d 15 \-w Music.wav \-o MyPortfolio.mpg \-i 01.jpg 02.jpg 03.jpg 04.jpg\fR
+
+Build PAL (default) SVCD MPEG file with the 'Music.wav' sound file and this image files sequence :
+
+01.jpg
+02.jpg
+03.jpg
+04.jpg
+
+For each image on the portfolio, the screen show duration is 15 seconds. The output file is 'MyPortfolio.mpg'.
+There isn't transition between images.
+.LP
+\fB# images2mpg \-n NTSC \-t 2 \-o MyPortfolio.mpg \-i *.png\fR
+
+Build XVCD (default) NTSC MPEG file with a transition between images (speed 2) with all local PNG image files.
+The image files sequence use the local filesystem sort.
+.LP
+.SH "AUTHORS"
+.LP
+This man page was written by Gilles CAULIER.
+.br
+If you have questions, remarks, problems or you just want to contact
+the author :
+ \fIcaulier.gilles@free.fr\fP
+
+The main mailing list for the Digikam project is:
+ \fIdigikam\-users@lists.sourceforge.net\fP
+
+For more info, see our website at
+ \fIhttp://digikam.sourceforge.net\fP
+.SH "SEE ALSO"
+.LP
+ImageMagick(1), mjpegtools(1), vcdimager(1)
+.LP
+Digikam GUI WEB site project : http://digikam.sourceforge.net
diff --git a/kipi-plugins/mpegencoder/kimg2mpg.cpp b/kipi-plugins/mpegencoder/kimg2mpg.cpp
new file mode 100644
index 0000000..947c430
--- /dev/null
+++ b/kipi-plugins/mpegencoder/kimg2mpg.cpp
@@ -0,0 +1,1238 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// KIMG2MPG.CPP
+//
+// Copyright (C) 2003 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// C Ansi includes
+
+extern "C"
+{
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+}
+
+// C++ includes
+
+#include <iostream>
+
+// Qt includes
+
+#include <qwidget.h>
+#include <qpixmap.h>
+#include <qbuttongroup.h>
+#include <qcombobox.h>
+#include <qframe.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qradiobutton.h>
+#include <qlabel.h>
+#include <qdialog.h>
+#include <qprogressbar.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qcheckbox.h>
+#include <qlineedit.h>
+#include <qspinbox.h>
+#include <qlistbox.h>
+#include <qheader.h>
+#include <qwhatsthis.h>
+#include <qprocess.h>
+#include <qdatetime.h>
+#include <qlayout.h>
+#include <qdragobject.h>
+#include <qmessagebox.h>
+
+// KDElib includes
+
+#include <kprogress.h>
+#include <kprocess.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kfiledialog.h>
+#include <kcolordialog.h>
+#include <klineedit.h>
+#include <kcolorbutton.h>
+#include <klistbox.h>
+#include <kbuttonbox.h>
+#include <kurl.h>
+#include <kimageio.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+
+// KIPI include files
+
+#include <libkipi/imagedialog.h>
+
+// Local includes
+
+#include "pluginsversion.h"
+#include "kpaboutdata.h"
+#include "kshowdebuggingoutput.h"
+#include "optionsdialog.h"
+#include "checkbinprog.h"
+#include "kimg2mpgbase.h"
+#include "kimg2mpg.h"
+#include "kimg2mpg.moc"
+
+namespace KIPIMPEGEncoderPlugin
+{
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+class ImageItem : public QListBoxText
+{
+public:
+ ImageItem(QListBox * parent, QString const & name, QString const & comments, QString const & path,
+ QString const & album)
+ : QListBoxText(parent), _name(name), _comments(comments), _path(path), _album(album)
+ {}
+
+ QString comments() { return _comments; }
+ QString name() { return _name; }
+ QString path() { return _path; }
+ QString album() { return _album; }
+ void setName(const QString &newName) { setText(newName); }
+
+private:
+ QString _name;
+ QString _comments;
+ QString _path;
+ QString _album;
+};
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+ListImageItems::ListImageItems(QWidget *parent, const char *name)
+ : KListBox(parent, name)
+{
+ setSelectionMode (QListBox::Extended);
+ setAcceptDrops(true);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void ListImageItems::dragEnterEvent(QDragEnterEvent *e)
+{
+ e->accept(QUriDrag::canDecode(e));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void ListImageItems::dropEvent(QDropEvent *e)
+{
+ QStrList strList;
+ KURL::List filesUrl;
+
+ if ( !QUriDrag::decode(e, strList) ) return;
+
+ QStrList stringList;
+ QStrListIterator it(strList);
+ char *str;
+
+ while ( (str = it.current()) != 0 )
+ {
+ QString filePath = QUriDrag::uriToLocalFile(str);
+ QFileInfo fileInfo(filePath);
+
+ if (fileInfo.isFile() && fileInfo.exists())
+ {
+ KURL url(fileInfo.filePath());
+ filesUrl.append(url);
+ }
+
+ ++it;
+ }
+
+ if (filesUrl.isEmpty() == false)
+ emit addedDropItems(filesUrl);
+}
+
+
+/////////////////////////////// CONSTRUCTOR /////////////////////////////////////////////////
+
+KImg2mpgData::KImg2mpgData(KIPI::Interface* interface, QWidget *parent, const char *name)
+ : KImg2mpgBase(parent, name), m_interface( interface )
+{
+ m_TmpFolderConfig = "";
+ m_Proc = 0L;
+ m_thumbJob = 0L;
+ m_Encoding = false;
+ m_Abort = false;
+
+ m_Icons = new KIconLoader( QString( "kipi" ) );
+ m_NoneLabel = i18n ("none");
+
+ // Set buttons icon
+
+ m_MPEGOutputBUTTONFilename->setIconSet( SmallIconSet( "fileopen" ) );
+ m_AudioInputBUTTONFilename->setIconSet( SmallIconSet( "fileopen" ) );
+
+ // Signal/Slot connections
+
+ connect( m_VideoTypeComboBox, SIGNAL( activated(int ) ),
+ this, SLOT( SlotPortfolioDurationChanged (int) ) );
+
+ connect( m_DurationImageSpinBox, SIGNAL( valueChanged(int ) ),
+ this, SLOT( SlotPortfolioDurationChanged (int) ) );
+
+ connect( m_TransitionComboBox, SIGNAL( activated(int ) ),
+ this, SLOT( SlotPortfolioDurationChanged (int) ) );
+
+ connect( m_MPEGOutputBUTTONFilename, SIGNAL( clicked() ),
+ this, SLOT( slotMPEGFilenameDialog() ) );
+
+ connect( m_AudioInputBUTTONFilename, SIGNAL( clicked() ),
+ this, SLOT( slotAudioFilenameDialog() ) );
+
+ connect( m_ImagesFilesListBox, SIGNAL( currentChanged( QListBoxItem * ) ),
+ this, SLOT( slotImagesFilesSelected(QListBoxItem *) ) );
+
+ connect(m_ImagesFilesListBox, SIGNAL( addedDropItems(KURL::List) ),
+ this, SLOT( slotAddDropItems(KURL::List)));
+
+ connect( m_ImagesFilesButtonAdd, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonAdd() ) );
+
+ connect( m_ImagesFilesButtonDelete, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonDelete() ) );
+
+ connect( m_ImagesFilesButtonUp, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonUp() ) );
+
+ connect( m_ImagesFilesButtonDown, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonDown() ) );
+
+ connect(m_Encodebutton, SIGNAL(clicked()),
+ this, SLOT(slotEncode()));
+
+ connect(m_optionsbutton, SIGNAL(clicked()),
+ this, SLOT(slotOptions()));
+
+ connect(m_quitbutton, SIGNAL(clicked()),
+ this, SLOT(slotClose()));
+
+ // About data and help button.
+
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("MPEG Slideshow"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for encoding images to an MPEG file."),
+ "(c) 2003-2004, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author"),
+ "caulier dot gilles at gmail dot com");
+
+ m_about->addAuthor("Angelo Naselli", I18N_NOOP("Maintainer"),
+ "anaselli at linux dot it");
+
+ m_about->addAuthor("Valerio Fuoglio", I18N_NOOP("Maintainer"),
+ "valerio dot fuoglio at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ readSettings();
+
+ int maxW = QMAX( m_VideoFormatComboBox->sizeHint().width(),
+ m_ChromaComboBox->sizeHint().width() );
+
+ m_ChromaComboBox->setMinimumWidth( maxW );
+ m_VideoFormatComboBox->setMinimumWidth( maxW );
+ m_VideoTypeComboBox->setMinimumWidth( maxW );
+ m_TransitionComboBox->setMinimumWidth( maxW );
+}
+
+
+/////////////////////////////// DESTRUCTOR //////////////////////////////////////////////////
+
+KImg2mpgData::~KImg2mpgData()
+{
+ if ( m_thumbJob ) delete m_thumbJob;
+
+ delete m_about;
+}
+
+
+///////////////////////////////////////// SLOTS /////////////////////////////////////////////
+
+void KImg2mpgData::SlotPortfolioDurationChanged ( int )
+{
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotAddDropItems(KURL::List filesUrl)
+{
+ addItems(filesUrl);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotMPEGFilenameDialog( void )
+{
+ QString temp;
+
+ temp = KFileDialog::getOpenFileName(KGlobalSettings::documentPath(),
+ QString( "*.mpg" ),
+ this,
+ i18n("Select MPEG Output File") );
+ if( temp.isEmpty() )
+ return;
+
+ m_MPEGOutputEDITFilename->setText( temp );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotAudioFilenameDialog( void )
+{
+ QString temp;
+
+ temp = KFileDialog::getOpenFileName(KGlobalSettings::documentPath(),
+ QString( "*.wav *.mp2 *.mp3 *.ogg" ),
+ this,
+ i18n("Select Audio Input File") );
+ if( temp.isEmpty() )
+ return;
+
+ m_AudioInputEDITFilename->setText( temp );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotImagesFilesButtonAdd( void )
+{
+ KURL::List ImageFilesList =
+ KIPI::ImageDialog::getImageURLs( this, m_interface );
+ if ( !ImageFilesList.isEmpty() )
+ addItems( ImageFilesList );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotImagesFilesButtonDelete( void )
+{
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ {
+ if (m_ImagesFilesListBox->isSelected(i))
+ {
+ m_ImagesFilesListBox->removeItem(i);
+ m_ImagesFilesListBox->setCurrentItem(i);
+ --i;
+ }
+ }
+
+ m_ImagesFilesListBox->setSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()), true);
+ slotImagesFilesSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()));
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotImagesFilesButtonUp( void )
+{
+ int Cpt = 0;
+
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ if (m_ImagesFilesListBox->isSelected(i))
+ ++Cpt;
+
+ if (Cpt == 0)
+ return;
+
+ if (Cpt > 1)
+ {
+ KMessageBox::error(this, i18n("You can only move up one image file at once."));
+ return;
+ }
+
+ unsigned int Index = m_ImagesFilesListBox->currentItem();
+
+ if (Index == 0)
+ return;
+
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(Index) );
+ QString path(pitem->path());
+ QString comment(pitem->comments());
+ QString name(pitem->name());
+ QString album(pitem->album());
+ m_ImagesFilesListBox->removeItem(Index);
+ ImageItem *item = new ImageItem( 0, name, comment, path, album );
+ item->setName( name );
+ m_ImagesFilesListBox->insertItem(item, Index-1);
+ m_ImagesFilesListBox->setSelected(Index-1, true);
+ m_ImagesFilesListBox->setCurrentItem(Index-1);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void KImg2mpgData::slotImagesFilesSelected( QListBoxItem *item )
+{
+ if ( !item || m_ImagesFilesListBox->count() == 0 )
+ {
+ m_label7->setText("");
+ m_ImageLabel->clear();
+ return;
+ }
+
+ ImageItem *pitem = static_cast<ImageItem*>( item );
+
+ if ( !pitem ) return;
+
+ KURL url;
+ url.setPath(pitem->path());
+
+ m_ImageLabel->clear();
+
+ if ( m_thumbJob ) delete m_thumbJob;
+
+ m_thumbJob = KIO::filePreview( url, m_ImageLabel->width() );
+
+ connect(m_thumbJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ SLOT(slotGotPreview(const KFileItem*, const QPixmap&)));
+ connect(m_thumbJob, SIGNAL(failed(const KFileItem*)),
+ SLOT(slotFailedPreview(const KFileItem*)));
+
+ int index = m_ImagesFilesListBox->index ( item );
+ m_label7->setText(i18n("Image no. %1").arg(index + 1));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotGotPreview(const KFileItem*, const QPixmap &pixmap)
+{
+ m_ImageLabel->setPixmap(pixmap);
+ m_thumbJob = 0L;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotFailedPreview(const KFileItem*)
+{
+ m_thumbJob = 0L;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotImagesFilesButtonDown( void )
+{
+ int Cpt = 0;
+
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ if (m_ImagesFilesListBox->isSelected(i))
+ ++Cpt;
+
+ if (Cpt == 0)
+ return;
+
+ if (Cpt > 1)
+ {
+ KMessageBox::error(this, i18n("You can only move down one image file at once."));
+ return;
+ }
+
+ unsigned int Index = m_ImagesFilesListBox->currentItem();
+
+ if (Index == m_ImagesFilesListBox->count())
+ return;
+
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(Index) );
+ QString path(pitem->path());
+ QString comment(pitem->comments());
+ QString name(pitem->name());
+ QString album(pitem->name());
+ m_ImagesFilesListBox->removeItem(Index);
+ ImageItem *item = new ImageItem( 0, name, comment, path, album );
+ item->setName( name );
+ m_ImagesFilesListBox->insertItem(item, Index+1);
+ m_ImagesFilesListBox->setSelected(Index+1, true);
+ m_ImagesFilesListBox->setCurrentItem(Index+1);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotClose()
+{
+ close();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotEncode( void )
+{
+ m_Proc = new KProcess;
+ QColor BackGroundColor;
+ QString HexColor;
+ QString Temp;
+ QString OutputFileName, InputAudioFileName;
+ bool ResultOk;
+
+ if (m_Encoding)
+ {
+ int Ret = KMessageBox::questionYesNo(this,
+ i18n("Do you really abort this encoding process ?\n\n"
+ "Warning: all work so-far will be lost."));
+ if (Ret == KMessageBox::Yes)
+ {
+ m_Abort = true;
+ reset();
+ }
+ return;
+ }
+
+ if (m_ChromaComboBox->currentText() == i18n("Default"))
+ {
+ int Ret= KMessageBox::warningContinueCancel( this,
+ i18n( "Default chroma mode option works only with Mjpegtools version < 1.6.3\n"),
+ i18n( "Check your Mjpegtools version" ),
+ KStdGuiItem::cont(),
+ i18n( "KIPImpegencoderChromaWarning"));
+ if (Ret == KMessageBox::Cancel)
+ {
+ m_Abort = true;
+ reset();
+ return;
+ }
+ }
+
+ // Init. Tmp folder
+ KStandardDirs dir;
+ m_TmpFolderConfig = dir.saveLocation("tmp", "kipi-mpegencoderplugin-" +
+ QString::number(getpid()) );
+
+ m_DebugOuputMessages = "";
+ m_DurationTime.start();
+ InputAudioFileName = m_AudioInputEDITFilename->text();
+
+ if (InputAudioFileName.isEmpty() == false && !QFile::exists(InputAudioFileName))
+ {
+ KMessageBox::error(this, i18n("You must specify an existing audio file."));
+ return;
+ }
+
+ OutputFileName = m_MPEGOutputEDITFilename->text();
+ QFileInfo fileInfo(OutputFileName);
+ if (OutputFileName.isEmpty() || fileInfo.isDir())
+ {
+ KMessageBox::error(this, i18n("You must specify an MPEG output file name."));
+ return;
+ }
+
+ QFileInfo dirInfo(fileInfo.dir().path());
+ if (!dirInfo.exists () || !dirInfo.isWritable())
+ {
+ KMessageBox::error(this, i18n("You must specify a writable path for your output file."));
+ return;
+ }
+
+ if (m_ImagesFilesListBox->count() == 0)
+ {
+ KMessageBox::error(this, i18n("You must specify some input images files in the portfolio."));
+ return;
+ }
+
+ if (QFile::exists(OutputFileName))
+ {
+ int Ret=KMessageBox::questionYesNo(this, i18n("The output MPEG file '%1' already exists.\n"
+ "Do you want overwrite this file?").arg(OutputFileName));
+ if (Ret == KMessageBox::No)
+ return;
+ }
+
+ m_ImagesFilesListBox->clearSelection();
+ m_Encodebutton->setText(i18n("A&bort"));
+ QWhatsThis::add( m_Encodebutton, i18n( "Abort the portfolio MPEG encoding. "
+ "Warning: all work so-far will be lost...." ) );
+
+ m_optionsbutton->setEnabled(false);
+ m_VideoFormatComboBox->setEnabled(false);
+ m_VideoTypeComboBox->setEnabled(false);
+ m_ChromaComboBox->setEnabled(false);
+ m_DurationImageSpinBox->setEnabled(false);
+ m_TransitionComboBox->setEnabled(false);
+ m_MPEGOutputEDITFilename->setEnabled(false);
+ m_MPEGOutputBUTTONFilename->setEnabled(false);
+ m_BackgroundColorButton->setEnabled(false);
+ m_AudioInputEDITFilename->setEnabled(false);
+ m_AudioInputBUTTONFilename->setEnabled(false);
+ m_ImagesFilesListBox->setEnabled(false);
+ m_ImagesFilesButtonBox->setEnabled(false);
+
+ m_Abort = false;
+ m_Encoding = true;
+
+ m_progress->setTotalSteps(100);
+ m_progress->setValue(0);
+
+ BackGroundColor = m_BackgroundColorButton->color();
+ HexColor = "";
+ Temp.setNum (BackGroundColor.red(), 16);
+ HexColor = HexColor + Temp.rightJustify(2,'0');
+ Temp.setNum (BackGroundColor.green(), 16);
+ HexColor = HexColor + Temp.rightJustify(2,'0');
+ Temp.setNum (BackGroundColor.blue(), 16);
+ HexColor = HexColor + Temp.rightJustify(2,'0');
+
+ // This is for debugging output in debug dialog box.
+
+ m_CommandLine = i18n("THE COMMAND LINE IS :\n\n");
+ m_CommandLine = m_CommandLine + "images2mpg --with-gui ";
+
+ *m_Proc << "images2mpg"; // The script...
+ *m_Proc << "--with-gui"; // Running with the GUI.
+ *m_Proc << "-f" << m_VideoFormatComboBox->currentText(); // Video format option.
+ m_CommandLine = m_CommandLine + " -f " + m_VideoFormatComboBox->currentText();
+
+ *m_Proc << "-n" << m_VideoTypeComboBox->currentText(); // Video type option.
+ m_CommandLine = m_CommandLine + " -n " + m_VideoTypeComboBox->currentText();
+
+ if (m_ChromaComboBox->currentText() != i18n("Default"))
+ {
+ *m_Proc << "-S" << m_ChromaComboBox->currentText(); // Chroma subsampling mode option.
+ m_CommandLine = m_CommandLine + " -S " + m_ChromaComboBox->currentText();
+ }
+
+ *m_Proc << "-d" << m_DurationImageSpinBox->text(); // Image duration.
+ m_CommandLine = m_CommandLine + " -d " + m_DurationImageSpinBox->text();
+
+ m_TransitionComboBox->currentText().toInt(&ResultOk);
+
+ if (ResultOk == true)
+ {
+ *m_Proc << "-t" << m_TransitionComboBox->currentText(); // Transitions duration.
+ m_CommandLine = m_CommandLine + " -t " + m_TransitionComboBox->currentText();
+ }
+
+ *m_Proc << "-c" << HexColor; // Background color.
+ m_CommandLine = m_CommandLine + " -c " + HexColor;
+
+ *m_Proc << "-T" << m_TmpFolderConfig; // Temporary folder.
+ m_CommandLine = m_CommandLine + " -T " + m_TmpFolderConfig;
+
+ *m_Proc << "-M" << m_MJBinFolderConfig; // MJPEGTools binary folder.
+ m_CommandLine = m_CommandLine + " -M " + m_MJBinFolderConfig;
+
+ *m_Proc << "-I" << m_IMBinFolderConfig; // ImageMagick binary folder.
+ m_CommandLine = m_CommandLine + " -I " + m_IMBinFolderConfig;
+
+
+ if ( InputAudioFileName.isEmpty() == false )
+ {
+ if ( InputAudioFileName.findRev(".mp2", -1, false) == -1 )
+ {
+ *m_Proc << "-w" << InputAudioFileName; // Input WAV/OGG/MP3 audio file name.
+ m_CommandLine = m_CommandLine + " -w \"" + InputAudioFileName + "\"";
+ }
+ else
+ {
+ *m_Proc << "-a" << InputAudioFileName; // Input MP2 audio file name.
+ m_CommandLine = m_CommandLine + " -a \"" + InputAudioFileName + "\"";
+ }
+ }
+
+ *m_Proc << "-o" << OutputFileName; // Output MPEG file.
+ m_CommandLine = m_CommandLine + " -o \"" + OutputFileName + "\"";
+
+ *m_Proc << "-i"; // Input images option.
+ m_CommandLine = m_CommandLine + " -i ";
+
+ for (uint i=0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ {
+ QString FileName="";
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(i) );
+ FileName.append (pitem->path()); // Input images files.
+ if (!QFile::exists(FileName))
+ {
+ KMessageBox::error(this,
+ i18n("Cannot access to file %1, please check the path is right.").arg(FileName));
+ m_Abort = true;
+ reset();
+ return;
+ }
+ *m_Proc << FileName;
+ m_CommandLine = m_CommandLine + " \"" + FileName + "\" ";
+ }
+
+ connect(m_Proc, SIGNAL(processExited(KProcess *)),this,
+ SLOT(EncodeDone(KProcess*)));
+
+ connect(m_Proc, SIGNAL(receivedStderr(KProcess *,char*,int)),this,
+ SLOT(readStderr(KProcess*,char*,int)));
+
+ m_Img2mpgPidNum = -1;
+ bool result = m_Proc->start(KProcess::NotifyOnExit , KProcess::All);
+
+ if(!result)
+ {
+ QString str = i18n("Cannot start 'images2mpg' bash script : fork failed.");
+ KMessageBox::error(this, str);
+ reset();
+ }
+
+ m_Img2mpgPidNum = m_Proc->pid();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotOptions( void )
+{
+ m_OptionDlg = new OptionsDialog(this);
+ m_OptionDlg->IMBinFolderEditFilename->setText(m_IMBinFolderConfig);
+ m_OptionDlg->MJBinFolderEditFilename->setText(m_MJBinFolderConfig);
+ m_OptionDlg->show();
+
+ connect( m_OptionDlg, SIGNAL( okClicked () ),
+ this, SLOT( slotOptionDlgOkClicked() ));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotOptionDlgOkClicked( void )
+{
+ m_Encodebutton->setEnabled(true);
+
+ m_IMBinFolderConfig = m_OptionDlg->IMBinFolderEditFilename->text();
+
+ if (m_IMBinFolderConfig.endsWith("/"))
+ m_IMBinFolderConfig.truncate(m_IMBinFolderConfig.length()-1);
+
+ m_MJBinFolderConfig = m_OptionDlg->MJBinFolderEditFilename->text();
+
+ if (m_MJBinFolderConfig.endsWith("/"))
+ m_MJBinFolderConfig.truncate(m_MJBinFolderConfig.length()-1);
+
+ writeSettings();
+ CheckBinProg* CheckExternalPrograms = new CheckBinProg(this);
+ int ValRet = CheckExternalPrograms->findExecutables();
+
+ m_Encodebutton->setEnabled(true);
+ m_AudioInputFilename->setEnabled(true);
+
+ if (ValRet == 0)
+ m_Encodebutton->setEnabled(false);
+
+ if (ValRet == 2)
+ m_AudioInputFilename->setEnabled(false);
+
+ disconnect( m_OptionDlg, SIGNAL( okClicked() ),
+ this, SLOT( slotOptionDlgOkClicked() ));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("mpegencoder",
+ "kipi-plugins");
+}
+
+
+////////////////////////////// FONCTIONS ///////////////////////////////////////////////////
+
+void KImg2mpgData::ShowNumberImages( int Number )
+{
+ QTime TotalDuration (0, 0, 0);
+ bool ResultOk;
+ int TransitionDuration;
+
+ int DurationImage = m_DurationImageSpinBox->text().toInt();
+ int TransitionSpeed = m_TransitionComboBox->currentText().toInt(&ResultOk);
+
+ if (ResultOk == false)
+ TransitionDuration = 0;
+ else
+ {
+ QString VidFormat=m_VideoTypeComboBox->currentText();
+
+ if (VidFormat == "NTSC")
+ TransitionDuration = (int)((((float)100 / (float)TransitionSpeed) / (float)30) * (float)1000); // in ms
+ else
+ TransitionDuration = (int)((((float)100 / (float)TransitionSpeed) / (float)25) * (float)1000); // in ms
+ }
+
+ TotalDuration = TotalDuration.addSecs(Number*DurationImage);
+ TotalDuration = TotalDuration.addMSecs((Number+1)*TransitionDuration);
+
+ if ( Number < 2)
+ m_label6->setText(i18n("%1 image [%2]").arg(Number).arg(TotalDuration.toString()));
+ else
+ m_label6->setText(i18n("%1 images [%2]").arg(Number).arg(TotalDuration.toString()));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::readStderr(KProcess *, char *buffer, int buflen)
+{
+ QString NewString2;
+ int ImgNum;
+ m_EncodeString = QString::fromLocal8Bit(buffer, buflen);
+
+ QString BufferTmp = buffer;
+
+ m_DebugOuputMessages.append(BufferTmp.left(buflen));
+
+ if (m_EncodeString.contains("Images encoding (%) :"))
+ {
+ int pos1 = m_EncodeString.find(':');
+
+ if (pos1 != -1)
+ {
+ QString newstring = m_EncodeString.mid(pos1+1, 4);
+ m_progress->setValue(newstring.toUInt());
+ }
+
+ int pos2 = m_EncodeString.find('[');
+
+ if (pos2 != -1)
+ {
+ NewString2 = m_EncodeString.mid(pos2+1, 4);
+ ImgNum = NewString2.toInt();
+
+ if (ImgNum == 0)
+ ImgNum = 1;
+
+ m_frame->setText(i18n("Encoding image file [%1/%2]...")
+ .arg(ImgNum).arg(m_ImagesFilesListBox->count()));
+
+ if (ImgNum > 1)
+ m_ImagesFilesListBox->setSelected(ImgNum-2, false);
+
+ m_ImagesFilesListBox->setSelected(ImgNum-1, true);
+ m_ImagesFilesListBox->setCurrentItem(ImgNum-1);
+ }
+ }
+ else
+ {
+ // Print on the GUI the actual 'images2mpg' process.
+
+ if (m_EncodeString.contains("Initialising..."))
+ m_frame->setText(i18n("Initialising..."));
+
+ if (m_EncodeString.contains("Merging MPEG flux..."))
+ {
+ m_frame->setText(i18n("Merging MPEG flux..."));
+ m_progress->setValue(100);
+ }
+
+ if (m_EncodeString.contains("Encoding audio file..."))
+ {
+ m_frame->setText(i18n("Encoding audio file..."));
+ m_progress->setValue(100);
+ }
+
+ // Or errors detections...
+
+ if (m_EncodeString.contains("cat:") ||
+ m_EncodeString.contains("ERROR:") ||
+ m_EncodeString.contains("Broken pipe") ||
+ m_EncodeString.contains("No such file or directory"))
+ {
+
+ m_Abort = true;
+ reset();
+ int Ret=KMessageBox::warningYesNo(this,
+ i18n("The 'images2mpg' script has returned an error during the MPEG encoding;\n"
+ "the process has been aborted.\n\n"
+ "Send a mail to the author..."),
+ i18n("'images2mpg' Script-Execution Problem"),
+ i18n("&OK"),
+ i18n("Show Debugging Output"));
+ if (Ret == KMessageBox::No)
+ {
+ m_DebuggingDialog = new KShowDebuggingOutput(m_DebugOuputMessages, m_CommandLine,
+ i18n ("\nEXIT STATUS : error during encoding process."), this);
+ m_DebuggingDialog->exec();
+ }
+ }
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::EncodeDone(KProcess*)
+{
+ reset();
+
+ int msecDur = m_DurationTime.elapsed();
+ m_EncodingDuration.setHMS(0, 0, 0);
+ QTime Duration = m_EncodingDuration.addMSecs (msecDur);
+ QString Encoding = Duration.toString("hh:mm:ss");
+
+ if ( m_Abort == false )
+ {
+ m_frame->setText(i18n("Encoding terminated..."));
+ int Ret=KMessageBox::warningYesNo(this,
+ i18n("The encoding process has terminated...\n\n"
+ "Encoding duration: %1").arg(Encoding),
+ i18n("'images2mpg' Script Execution Terminated"),
+ i18n("&OK"),
+ i18n("Show Process Messages"));
+
+ if (Ret == KMessageBox::No)
+ {
+ m_DebuggingDialog = new KShowDebuggingOutput(m_DebugOuputMessages, m_CommandLine,
+ i18n ("\nEXIT STATUS : encoding process finished successfully."),
+ this);
+ m_DebuggingDialog->exec();
+ }
+ }
+ else
+ {
+ m_frame->setText(i18n("Encoding aborted..."));
+ int Ret=KMessageBox::warningYesNo(this,
+ i18n("The encoding process has been aborted...\n\n"
+ "Encoding duration: %1").arg(Encoding),
+ i18n("'images2mpg' Script Execution Aborted"),
+ i18n("&OK"),
+ i18n("Show Process Messages"));
+
+ if (Ret == KMessageBox::No)
+ {
+ m_DebuggingDialog = new KShowDebuggingOutput(m_DebugOuputMessages, m_CommandLine,
+ i18n ("\nEXIT STATUS : encoding process aborted by user."), this);
+ m_DebuggingDialog->exec();
+ }
+ }
+
+ RemoveTmpFiles();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+QPixmap KImg2mpgData::LoadIcon( QString Name, int Group )
+{
+ return m_Icons->loadIcon( Name, (KIcon::Group)Group );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::closeEvent(QCloseEvent* e)
+{
+ if (!e) return;
+
+ if (m_Encoding)
+ {
+ int Ret =
+ KMessageBox::questionYesNo(this, i18n("An encoding process is active;\n"
+ "abort this process and exit ?"));
+ if (Ret == KMessageBox::Yes)
+ {
+ m_Abort = true;
+ reset();
+ }
+ else {
+ e->ignore();
+ return;
+ }
+ }
+
+ RemoveTmpFiles();
+ writeSettings();
+ e->accept();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void KImg2mpgData::show()
+{
+ setCaption(i18n("Create MPEG Slideshow"));
+ QDialog::show();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::reset()
+ {
+ m_Encoding = false;
+
+ if (m_Proc && m_Img2mpgPidNum > 0)
+ {
+ ::kill(m_Img2mpgPidNum, SIGKILL);
+ }
+
+ delete m_Proc;
+ m_Proc = 0L;
+
+ m_progress->setValue(0);
+ m_frame->clear();
+
+ m_Encodebutton->setText(i18n("&Encode"));
+ m_optionsbutton->setEnabled(true);
+ m_VideoFormatComboBox->setEnabled(true);
+ m_ChromaComboBox->setEnabled(true);
+ m_VideoTypeComboBox->setEnabled(true);
+ m_DurationImageSpinBox->setEnabled(true);
+ m_TransitionComboBox->setEnabled(true);
+ m_MPEGOutputEDITFilename->setEnabled(true);
+ m_MPEGOutputBUTTONFilename->setEnabled(true);
+ m_BackgroundColorButton->setEnabled(true);
+ m_AudioInputEDITFilename->setEnabled(true);
+ m_AudioInputBUTTONFilename->setEnabled(true);
+ m_ImagesFilesListBox->setEnabled(true);
+ m_ImagesFilesButtonBox->setEnabled(true);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::writeSettings()
+{
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("MPEGEncoder Settings");
+
+ m_VideoFormatConfig = m_VideoFormatComboBox->currentText();
+ m_config->writeEntry("VideoFormat", m_VideoFormatConfig);
+
+ m_VideoTypeConfig = m_VideoTypeComboBox->currentText();
+ m_config->writeEntry("VideoType", m_VideoTypeConfig);
+
+ m_ChromaConfig = m_ChromaComboBox->currentText();
+ m_config->writeEntry("ChromaMode", m_ChromaConfig);
+
+ m_ImageDurationConfig = m_DurationImageSpinBox->text();
+ m_config->writeEntry("ImageDuration", m_ImageDurationConfig);
+
+ m_TransitionSpeedConfig = m_TransitionComboBox->currentText();
+ m_config->writeEntry("TransitionSpeed", m_TransitionSpeedConfig);
+
+ m_BackgroundColorConfig = m_BackgroundColorButton->color();
+ m_config->writeEntry("BackgroundColor", m_BackgroundColorConfig);
+
+ m_AudioInputFileConfig = m_AudioInputEDITFilename->text();
+ m_config->writePathEntry("AudioInputFile", m_AudioInputFileConfig);
+
+ m_MPEGOutputFileConfig = m_MPEGOutputEDITFilename->text();
+ m_config->writePathEntry("MPEGOutputFile", m_MPEGOutputFileConfig);
+
+ m_config->writePathEntry("ImageMagickBinFolder", m_IMBinFolderConfig);
+ m_config->writePathEntry("MjpegToolsBinFolder", m_MJBinFolderConfig);
+
+ m_config->sync();
+ delete m_config;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::readSettings()
+{
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("MPEGEncoder Settings");
+
+ m_VideoFormatConfig = m_config->readEntry("VideoFormat", "XVCD");
+
+ for (int i = 0 ; i < m_VideoFormatComboBox->count() ; ++i)
+ if ( (QString) m_VideoFormatComboBox->text(i) == m_VideoFormatConfig)
+ m_VideoFormatComboBox->setCurrentItem(i);
+
+ m_VideoTypeConfig = m_config->readEntry("VideoType", "PAL");
+
+ for (int i = 0 ; i < m_VideoTypeComboBox->count() ; ++i)
+ if ( (QString) m_VideoTypeComboBox->text(i) == m_VideoTypeConfig)
+ m_VideoTypeComboBox->setCurrentItem(i);
+
+ m_ChromaConfig = m_config->readEntry("ChromaMode", "420mpeg2");
+
+ for (int i = 0 ; i < m_ChromaComboBox->count() ; ++i)
+ if ( (QString) m_ChromaComboBox->text(i) == m_ChromaConfig)
+ m_ChromaComboBox->setCurrentItem(i);
+
+ m_ImageDurationConfig = m_config->readEntry("ImageDuration", "10");
+ m_DurationImageSpinBox->setValue(m_ImageDurationConfig.toInt());
+
+ m_TransitionSpeedConfig = m_config->readEntry("TransitionSpeed", m_NoneLabel);
+
+ for (int i = 0 ; i < m_TransitionComboBox->count() ; ++i)
+ if ( (QString) m_TransitionComboBox->text(i) == m_TransitionSpeedConfig)
+ m_TransitionComboBox->setCurrentItem(i);
+
+ QColor *ColorB = new QColor( 0, 0, 0 );
+ m_BackgroundColorConfig = m_config->readColorEntry("BackgroundColor", ColorB);
+ m_BackgroundColorButton->setColor(m_BackgroundColorConfig);
+
+ m_AudioInputFileConfig = m_config->readPathEntry("AudioInputFile");
+ m_AudioInputEDITFilename->setText(m_AudioInputFileConfig);
+
+ m_MPEGOutputFileConfig = m_config->readPathEntry("MPEGOutputFile", KGlobalSettings::documentPath() + "output.mpg");
+ m_MPEGOutputEDITFilename->setText(m_MPEGOutputFileConfig);
+
+ m_IMBinFolderConfig = m_config->readPathEntry("ImageMagickBinFolder", "/usr/bin");
+ m_MJBinFolderConfig = m_config->readPathEntry("MjpegToolsBinFolder", "/usr/bin");
+
+ delete ColorB;
+ delete m_config;
+
+ // Get the image files filters from the hosts app.
+
+ m_ImagesFilesSort = m_interface->fileExtensions();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::RemoveTmpFiles(void)
+{
+ QDir tmpFolder(m_TmpFolderConfig);
+
+ if (m_TmpFolderConfig.isEmpty() != true && tmpFolder.exists() == true)
+ if (DeleteDir(m_TmpFolderConfig) == false)
+ KMessageBox::error(this, i18n("Cannot remove temporary folder %1!").arg(m_TmpFolderConfig));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KImg2mpgData::addItems(const KURL::List& fileList)
+{
+ if (fileList.isEmpty()) return;
+
+ KURL::List Files = fileList;
+
+ for ( KURL::List::Iterator it = Files.begin() ; it != Files.end() ; ++it )
+ {
+ KURL currentFile = *it;
+
+ QFileInfo fi(currentFile.path());
+ QString Temp = fi.dirPath();
+ QString albumName = Temp.section('/', -1);
+
+ KIPI::ImageInfo info = m_interface->info(currentFile);
+ QString comments = info.description();
+
+ ImageItem *item = new ImageItem( m_ImagesFilesListBox,
+ currentFile.path().section('/', -1 ), // File name with extension.
+ comments, // Image comments.
+ currentFile.path().section('/', 0, -1), // Complete path with file name.
+ albumName // Album name.
+ );
+
+ item->setName( currentFile.path().section('/', -1) );
+ }
+
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+ m_ImagesFilesListBox->setCurrentItem( m_ImagesFilesListBox->count()-1) ;
+ slotImagesFilesSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()));
+ m_ImagesFilesListBox->centerCurrentItem();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool KImg2mpgData::DeleteDir(QString dirname)
+{
+if ( !dirname.isEmpty() )
+ {
+ QDir dir;
+
+ if (dir.exists ( dirname ) == true)
+ {
+ if (deldir(dirname) == false)
+ return false;
+
+ if (dir.rmdir( dirname ) == false )
+ return false;
+ }
+ else
+ return false;
+ }
+else
+ return false;
+
+return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool KImg2mpgData::deldir(QString dirname)
+{
+QDir *dir = new QDir(dirname);
+dir->setFilter ( QDir::Dirs | QDir::Files | QDir::NoSymLinks );
+
+const QFileInfoList* fileinfolist = dir->entryInfoList();
+QFileInfoListIterator it(*fileinfolist);
+QFileInfo* fi;
+
+while( (fi = it.current() ) )
+ {
+ if(fi->fileName() == "." || fi->fileName() == ".." )
+ {
+ ++it;
+ continue;
+ }
+
+ if( fi->isDir() )
+ {
+ if (deldir( fi->absFilePath() ) == false)
+ return false;
+ if (dir->rmdir( fi->absFilePath() ) == false)
+ return false;
+ }
+ else
+ if( fi->isFile() )
+ if (dir->remove(fi->absFilePath() ) == false)
+ return false;
+
+ kapp->processEvents();
+ ++it;
+ }
+
+return true;
+}
+
+} // NameSpace KIPIMPEGEncoderPlugin
+
diff --git a/kipi-plugins/mpegencoder/kimg2mpg.h b/kipi-plugins/mpegencoder/kimg2mpg.h
new file mode 100644
index 0000000..8d668f5
--- /dev/null
+++ b/kipi-plugins/mpegencoder/kimg2mpg.h
@@ -0,0 +1,183 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// KIMG2MPG.H
+//
+// Copyright (C) 2003 Gilles Caulier <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef KImg2mpgData_included
+#define KImg2mpgData_included
+
+// Include files for Qt
+
+#include <qstring.h>
+#include <qcolor.h>
+#include <qtimer.h>
+#include <qguardedptr.h>
+#include <qdatetime.h>
+
+// Include files for KDE
+
+#include <kdialog.h>
+#include <klistbox.h>
+#include <kprocess.h>
+#include <kio/previewjob.h>
+
+// Include files for KIPI
+
+#include "kpaboutdata.h"
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "kimg2mpgbase.h"
+
+class KFileItem;
+class QPushButton;
+class QComboBox;
+class QSpinBox;
+class QGroupBox;
+class QListBoxItem;
+class QLabel;
+class QWidget;
+class QPixmap;
+
+class KConfig;
+class KProcess;
+class KLineEdit;
+class KIconLoader;
+class KColorButton;
+class KListBox;
+class KButtonBox;
+class KProgress;
+class KURL::List;
+
+namespace KIPIMPEGEncoderPlugin
+{
+
+class KShowDebuggingOutput;
+class OptionsDialog;
+
+class ListImageItems : public KListBox
+{
+Q_OBJECT
+
+public:
+ ListImageItems(QWidget *parent=0, const char *name=0);
+
+signals:
+ void addedDropItems(KURL::List filesUrl);
+
+protected:
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dropEvent(QDropEvent *e);
+};
+
+
+class KImg2mpgData : public KImg2mpgBase
+{
+Q_OBJECT
+
+public:
+
+ KImg2mpgData( KIPI::Interface* interface, QWidget* parent = 0, const char * name = 0 );
+ virtual ~KImg2mpgData();
+
+ void show();
+ void ShowNumberImages( int Number );
+ void closeEvent(QCloseEvent*);
+ QPixmap LoadIcon( QString Name, int Group );
+ void addItems(const KURL::List& fileList);
+ void writeSettings();
+ void readSettings();
+
+ OptionsDialog* m_OptionDlg;
+
+public slots:
+
+ void reset();
+ void readStderr(KProcess *proc, char *buffer, int buflen);
+ void EncodeDone(KProcess* );
+ void slotMPEGFilenameDialog( void );
+ void slotAudioFilenameDialog( void );
+ void slotImagesFilesButtonAdd( void );
+ void slotImagesFilesButtonDelete( void );
+ void slotImagesFilesButtonUp( void );
+ void slotImagesFilesButtonDown( void );
+ void slotEncode( void );
+ void slotOptions( void );
+ void slotClose( void );
+ void slotHelp( void );
+ void slotImagesFilesSelected( QListBoxItem *item );
+ void SlotPortfolioDurationChanged ( int );
+ void slotOptionDlgOkClicked( void );
+ void slotGotPreview(const KFileItem* , const QPixmap &pixmap);
+ void slotFailedPreview(const KFileItem*);
+ void slotAddDropItems(KURL::List filesUrl);
+
+private:
+
+ QString m_VideoFormatConfig;
+ QString m_VideoTypeConfig;
+ QString m_ChromaConfig;
+ QString m_ImageDurationConfig;
+ QString m_TransitionSpeedConfig;
+ QString m_MPEGOutputFileConfig;
+ QString m_AudioInputFileConfig;
+ QString m_IMBinFolderConfig;
+ QString m_MJBinFolderConfig;
+ QString m_TmpFolderConfig;
+ QString m_NoneLabel;
+ QString m_EncodeString;
+ QString m_DebugOuputMessages;
+ QString m_CommandLine;
+ QString m_ImagesFilesSort;
+
+ QColor m_BackgroundColorConfig;
+
+ KConfig* m_config;
+
+ KIO::PreviewJob* m_thumbJob;
+
+ QTime m_EncodingDuration;
+ QTime m_DurationTime;
+
+ bool m_Abort;
+ bool m_Encoding;
+
+ pid_t m_Img2mpgPidNum;
+
+ KProcess* m_Proc;
+
+ KIconLoader* m_Icons;
+
+ KIPI::Interface* m_interface;
+
+ KIPIPlugins::KPAboutData* m_about;
+
+ class KShowDebuggingOutput* m_DebuggingDialog;
+
+ void RemoveTmpFiles( void );
+ bool DeleteDir(QString dirname);
+ bool deldir(QString dirname);
+};
+
+} // NameSpace KIPIMPEGEncoderPlugin
+
+#endif // KImg2mpgData_included
diff --git a/kipi-plugins/mpegencoder/kimg2mpgbase.ui b/kipi-plugins/mpegencoder/kimg2mpgbase.ui
new file mode 100644
index 0000000..ef91f1b
--- /dev/null
+++ b/kipi-plugins/mpegencoder/kimg2mpgbase.ui
@@ -0,0 +1,1341 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KIPIMPEGEncoderPlugin::KImg2mpgBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>Kimg2mpgBase</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>705</width>
+ <height>540</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Kimg2mpgBase</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout26</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Encoder Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer10_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout16</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout29</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Video Format</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>XVCD</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>SVCD</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>VCD</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>DVD</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_VideoFormatComboBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This option specifies the video format for your MPEG file.
+For a high photographic resolution on a TV screen, select 'XVCD' (it is the same DVD resolution) although some old DVD players cannot read this format. 'VCD'/'SVCD' are more compatible with DVD players, but they are only medium resolution.
+DVD is an experimental option.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout30</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Video Type</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>PAL</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>NTSC</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>SECAM</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_VideoTypeComboBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This option specifies the video type for your MPEG file.
+NTSC is an American TV standard; PAL/SECAM is European.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout31</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3_3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Chroma Mode</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>Default</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>444</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>420jpeg</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>420mpeg2</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_ChromaComboBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This option specifies the chroma subsampling mode.
+Change it if you have problems with the default value.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer10</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Image Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer17_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout25</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout33</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Image duration</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout32</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_DurationImageSpinBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This option specifies the duration for each image in your MPEG file.
+10 seconds is a good value for an image portfolio.
+
+&lt;b&gt;Warning&lt;/b&gt;: you may have some problems with your DVD player if the total MPEG duration is under 3 seconds.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>sec.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout44</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Transition speed</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>none</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>10</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>20</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_TransitionComboBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This option specifies the transition speed between images in your MPEG file.
+'1' is a slow transition and '20' is a very fast transition.
+'2' is a good value for an image portfolio.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout45</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Background color</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_BackgroundColorButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>You can select here the background color for your portfolio.
+This color is used to pad the image size to fit the TV screen size.
+Black is a good value for this.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer17_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_ImagesFilesGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Image Files in Portfolio</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Preview the currently selected image.</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIPIMPEGEncoderPlugin::ListImageItems">
+ <property name="name">
+ <cstring>m_ImagesFilesListBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the list of the image files for your portfolio.
+The portfolio's first image is on the top; the last image is on the bottom.
+If you want to add some images, click on the 'Add' button or use the drag-and-drop.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_label6</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>textLabel1</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Total number of images in the portfolio and sequence duration.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer19_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonBox</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonAdd</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Add...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Add some image files to the portfolio list.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonDelete</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Delete</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Remove some image files from the portfolio list.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonUp</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Image &amp;Up</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Moving the current image up on the portfolio list.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonDown</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Image D&amp;own</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Moving the current image down on the portfolio list.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer17</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_ImageLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>128</width>
+ <height>128</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Preview the currently selected image.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_label7</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>textLabel2</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Currently selected image in the portfolio list.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout28</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout27</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_MPEGOutputFilename</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>MPEG Output Filename</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_MPEGOutputEDITFilename</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>You can specify here the output MPEG filename.
+
+&lt;b&gt;Warning &lt;/b&gt;: MPEG files are very big (if you have many images in your portfolio). Select a folder with a sufficient free disk space.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6_3_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_MPEGOutputBUTTONFilename</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>22</width>
+ <height>22</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_AudioInputFilename</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Audio Input Filename</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_AudioInputEDITFilename</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>You can specify here the input audio file name.
+This audio file name will be multiplexed with the portfolio video.
+
+&lt;b&gt;Warning&lt;/b&gt;: if the audio duration is too long, it will be truncated.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_AudioInputBUTTONFilename</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>22</width>
+ <height>22</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_frame</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>50</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Current encoding task.</string>
+ </property>
+ </widget>
+ <widget class="KProgress">
+ <property name="name">
+ <cstring>m_progress</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>27</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Encoding progress bar.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer11</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout21</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_Encodebutton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Encode</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Start the portfolio MPEG encoding.
+The program uses the 'images2mpg' bash script.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>51</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_optionsbutton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>62</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Settings</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer13</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>51</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_helpButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Help</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_quitbutton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Close</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Abort the current encoding and exit.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KIPIMPEGEncoderPlugin::ListImageItems</class>
+ <header location="local">kimg2mpg.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image1</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="13969">89504e470d0a1a0a0000000d4948445200000080000000800806000000c33e61cb0000200049444154789ced9d77785cc5b9ff3fa7ecaeb4eabd59cd1d775cc102dc30d52114d10288d0434202f64d4808218d7b93c0bd84248484104288136ac0178c31bd1830dd185cb071b7254b966c6955b6ef39677e7f9cddd5566955b0b93ffc7d9ef39c3667e69cf9bef3ce3b33efcc91388a94b162e9b27c4992a6e49665970b43741b86d1e577073aceb8fdd79b8ff4bb0d16d2917e812f33562c5d9667b35baf43e23a9fcb5f4d92fc921559a467a7b5dbd22d9f671566bc5836b6f83fcbeb1ac4617edd41e1a80024c08aa5cb0a54abfaa8e6d7160fe679d5aa88bcf29cf74a47172d1d73e675ef0ff7fb0d278e0a400c56fdf887dfd6fcfaef0cddb0445ecfabaaa478cc18b24af249cbcc40b5d9f0bbba71b61da2f3401b8ec603380f1e421846f8195991c9afc8d99a57967df9e48b6efce0b07f4c0a382a001158f9a39b7fa7f9b41b43e7b2aa3276e10246cf3b094bba1d8440204004370422e258f3ba68dfb98d1d6f7fc0a15dfbc2f12a1685a2eabc753925d9674cacbfa1ed087c5a521c15802056fef0073fd4fcfa6f42e7c563c732fda20b49cfcd352ff4437eecfd80d74dd3c7ebd8fcc2eb189a0e80cd6e350a2a73ff5932b2f0dada53aef61f81cf8cc3510100562c5d361f783d743eeaa4139972f6d9bd01844008237c6c926f441c03c2202c0811421170f7b0fd8d37d9f9eefa6078b0e7a67baa26955d39e1bc1b1e3b3c5f981c5f790158b17499a258941d7a40af012839663cc75f7d359214cc9a21901fa911bcdd5d6c787a156d3bf60220c9124535f91f1755e79f3ceeaceb1d87f9b3c3908f54c25f16c88a7c6d88fcf4bc5c6637340c3bf908812d2b8b59975ec88cf34f435615842168dbd53e7dcffaa6d68f97fff69ac3ffe526bed21a60c5d26559b222371bba910930e78a2b289f3cc9bc398ce487cf837b6f673beb573c4747632b00b2225131bee4d98a634aebcbeb1a0eab6df095d600b2227f2b447ed198d126f942803082e4f71e87c90f911d3c17b1e48b24e487c31ad872f29873f9c51cb3681600862e68dc7ce06b3b3f6adcb7efb507c71fce3cf8ca6a80154b97c98a4569d6037a8924cb2c58b694ecb2328829ad91e4c6113ae0b0bd1ac50c6be0d8bb9b754fbe48c0e30320bb384bab9a5476ced8af7d6bd5e1c887afb20638550fe82500d573669be447a8f894c91703203f2aac799e5b59cd89d75c44de886200badb7ad41d1fec5db9e9893ffce47064c257560054ab720b80a4281c73eaa908c38852dfb1c7890935ab09113a8eaa2e82e71810653bf49e87d2b0666432fb1be7523dc3d4fe5ea74fdaf951e3edeb1ebaebb1e6b5cbbf502dfd951480154b97156a7ebd0ea062ca14ac191908c308d687d11d3c894b768850620cc3e41d4342248837326e4962fca2794c387926007a4067df86e60b9bb7b5bdd5bc76b9ed8bca8bafa40020712ec16faf9d7b7c906448484c42f283a163c927494b80e8f8e204251c06461c7b2c934f9b832449082168dcd852d7b2e3e0a75f94107c250540b5aa5703e4545490575585d075a448f58c11b6d823557b587593a855d047f591e81e912d88882a01289b34892967cc41924d21d8f769f3b8966d6d1f36af5d9e36dc79f1956b05ac58baac006803e469f5f554ce980e4220ab520431906a1bdfdbb985271efc25bb0f2a14955410f0b938d4ba97f6d6dda8aa4a6141018b4f3e9919732f464e2f4ca0058c60d4a1348c703a07b76d65c3eaf73174034992a89c5cf649f9d8e239c3d957a00e5744ff6720712e02d9929646f994c908219024064cbef3c047ac7aea8f94574fe0bc4b6fc0220790f46e64dd89e4cca463c72e9adbbdb47434b27ecd035c7ff31f38767c2e0b4e98c9c5d7fe1e53f9864a3ec4928f10148d1ecb94d3fc7cbafae35075300d78b779edf2e3caeb1a02c3931d5f31acfce1cdef697e6d4ecd9c394cfafa5908c3405165242975f23f597d33ba7d0cb38e9f876c3841eb3137dd055a37b876205a9f8b4ad7ed3378e4352f7f5deda1ba3c9bdffcea2eca6b8f4b4a7eb88a3074f67fbc8ead6f6d35239260e48caa778b6af3eb2ae60eddebe82b6503ac58ba2c5f0b68b3002a674c47e83a2082f57f0409c9ea6dc3cfaa07afa672e242e6d42d44161ed0dca07b4cf27517e86e107a4cca02bb4de2ead3d379edbff350848b53cfbb8a375ff80b10b23112a729215131752a23269487a262efa7fb8f771e74fd6c38f2e42b2500c03908e4ecb232b2cbcac2ea3f69074f5433d0e05ffff335e69c720d2515e37ac9365ca03941f782e63205424416cce8429a9126f18f9bb329cd93f98f5fdc8ba36d6fdfcd4704c80aa3e64e27bb3013309b888d9b5b6e6b7af3a121771b7fa50440b5aad741b0f40b81300c64594a817cc1e637ff884f29a6acb4c4245a0f12afb9c0f080ee3405427783e10ba69858435b15899f5d9a49578fc69dbf5e16df248c7b1f03353d8363164c41b12800741f74ca2ddb0e3edfbc76f990ecb8af8c00ac58baac44f36b332d6969544c9d6a76fcc890acdd1ed501a47bb9f3ee3f70e925df30c936426adf1d3c764554036e44c04132f24397678db32049f0bfaf6d47d3b4089bc388233ff43ef6a23246cea80947b57f6b6b8dbbdb7beb50f265d85b01f5f5f569c02460e230c43f64232784669f7754b92d4daa9a350bc562411802459523323b79efdeba57efa5bd4b909157132ce9bd64a305052174aebb2090c0bf23e64bac168124491886a0b3d341417e3ed1fd01f11d479224513e691c6dbbdae86aebc1d00d9ab7b6feb879edf27bcbeb1a0e0d265f864d00eaebeb47003703d7025f58d7e560e1d4b503b2aa523d6736c230335696a5947af7366dfc98821cb9b7d4c794f8decd83d05de08fe1224e8c051f7eae6118e68d4ec7410af273fb243f742c5bd2187ddc38d63dfb110838d4e8b01654e6dd035c3c987c191601a8afaf3f1d7802c8cccfcda5acb8989cec6c4c0babd7aa0ee543a4c52b42e7e68de86ba11299e89960f86471879e75bbdd34b7b6a2084a2ba64cc16acf4008034595a24a7ec22a20782c2b36d66ded46efda8c925668aa79cd851412022da8fa75a759fa75576fe64491df7bf2e7551e00f273ed5455d7c6373b230521e6fd324b4ac82fcfa5637f270868d9d67661f3dae53f2baf6bd83650ee862c00f5f5f517008fa9aacaf44993185156164598882129d97506183ed5b0465010244932fbfd0d1d21048a62494c7ee479703f79fa3c5cdee778fce1fbf8c6e5df05c3876444ab7da105fb003c8dbd999384fc475ff7b27693d99977d629c7615194b8929e8c7c1048b24af5b1a3e8d8bf0e80ee834ea9a3b9eb6ee0cc81f2372423b0bebebe0ef857467a3aa7ce9b277dd9c80f5d0728a8a9253d373748be045282cc4d40be1082a9732f62dab87c6eb9773b2f3cfe6be85a0fde9660c9ef41f80f82771fb87680d0cccc4942fe9b1b03fcf25fa6865055858b2ebc2e45f27b8d418420bbb484dcd29c70bc1dfbbb4e6d5ebb3c77a01c0e5a03d4d7d7e7032f288aa2cc9d354bb259ad83261f20dd6ec766b361b5d968debfbfcf78422365a90a0a40e9f871849a7e4aba2565f243c70ffc7d35679db5806bfea785d2bf3dc6826956164db372c2642bf6588b2701f95ebfe02fcf79f8ed536e84008b45e19e3b7e1156fffd916f1e87f2cb0049a27ada483a5f580f40c7fe4ec537a1f46ae07f06c2e350aa80ef0399d3274d222b2363c0e4cf98338731e3c79366b361b15aa322bef777bf0b3b68248a67e1e2c54c9e3a95e6fdfbd9b7772f7bf7eca1a9a9092d104898268062b522741dc522234182cc36c2192ca25a05022120b7a09855abdfe2e69b2ee69577b6f3e8eb1e1e7ddd832c49cc1aa7525ea0509a27539a27539227539c2bd3ead0693c68b0eb80ce136b7c61a34f9615eef8f92d9c74d229096c8e50b5440cf9f1f6494e592199f919383b5c189a417b53e7520e8700d4d7d7170337e664658911e5e5d2604a7e56561659595909e3ef2b9ec953a7326dfa74002aabaaa8acaaa2eec413d1759dc67dfbd8bd6b176fbff5569c00844857adca80c90f91929595cb9fffb69add3b3673cfdd3fe5a5b7b7e2f3fb797f6b0008c494fc0490244e9831869b6eba8509e32712f2118c233ff8ce7d910f026485aac9957cb6c61c27686f749407078ade4b95cbc16a809b01fb3163c6843f60306a3f1992c553565ecea2534e49f88ca228d4d4d6b2fee38fe3d2045300144bc8e41938f99142533bf218eebae7091082a6a6263e5df70a9fae7f8f4d5b77a2697af039f3f990119a694f63d9d2db9834694a449d3e78f243c7f95525586c3b08f8345c9d1e1c2d5d3f06ce4a95c8010b407d7d7d19f09ddcec6c515652220d86fcf07112248a27232383b3ce3d174551923eb7e68d37d8b86143620190242c568578f243c7c490df876116713ea2a29c8af2cb3863c9a571cff5868df401ec238db8e7e28f7b05d5dc64d54a6e590e07f7b403d0b1bfebf4e6b5cb73caeb1aba52e173301ae00740da84b1630755f2c3a4f4a10562e3916599b3ce3d97cccccca4cf6cdab89135afbf9ef05d0014e146ef3980303484a183a143f058080d9091240521c948b20c928c242b0842c7b2794f52a2fa3708698d505a41c253263492fc0402d717f92101ceaf2cea1580a64e75c484d22b81bb5321734002505f5f2f031767666488e2c2c2f8d21fcc84d163c7929199c9fa8f3e4a487e7f1a209499a16dd129a7505e5191346ce3be7dac7cfae9c482180cf3ec1f6ee44dfffea8e7168f8402fb4072009024d28f399dac13bf879a5f7dc4c94708724b7a5b7fba66d0d5daf3c50800701c505a515a9ab4e44f9a368d59c71d0740654d0dafbdf4129d0e479c00f485c870e3c68f67cab46949c33a1c0e1e7ff45102a11640024d04a05528f82d6ab0be87cc341871aa8c640873d38080b9179a40d20504005d849f4198b378dcdb9ec7bbfd350acebf0f6be5cc08bbe68b22df88681544930f028bdd863d371d77a7d9bbe8eef18e6d5ebb5c29af6b88754c88c3403b82ce05282b2e4e5cf2c78d0b930f50545ccc79175dc4ece38f27dd6e475155264e999272e9cfccca62f1e9a7270da7691a8ffceb5fb85cae3eab21003907e44205b94046c997a99c28a356c8a865326a898c5a2c612991514b24ac2512d62289b402415a31a495405a29a495817d0414cc16a8693e3a56dc80eeeda4d7713401f92211a149c80f911d477eafed104b7ee8fbf22bf2c3f9e27678ac988371fd62a01ae05c7b7abac8ceca921265762235adaa2ac7ce9cc9b133672284c0300c367cf2499f5a2074eff4254b484b4bee08fbfc73cf71e8e0c1bec98f4a478412c06e939104511b4220456cc92029903d51d0febe0bcfc69564ccb824258b3dec001a476e50cbc46890beaa80a87304b96539346d36ab3897c38da11bc7031b927e4410296b80fafafa69406d59717142f28510bcb7762d1e8f2779c605a75da75205cc9c3d9bea9a9aa461366fdac4c7ebd6f54b7e282d2998c95230699b353a334df28952f77d41b68092a6a0b5ef3ee2e40b21c82ac84292cdfcd535839e7657e2f6720c06a201be0e501a52ff31992d84c0ed72b1e6d557396dc9928411b85c2e5e7be9a50425331a8545459c387f7ed2fb0e87836757ae4c89fc702a91eeaf02fc3e7a89360061762f4bc17329d0b704183ed03d1a96b28983235fe8ec7efd9f6cdbb31f455550550baaaaa02a2a16ab85a9d36721178e0bbe6edfe423049222634bb7e07599834cee2eef9c3e3f20888108c05c4551446e76769f3d7f7b77efe6b38d1b99307972d4c3fbf6ece1e5175e60cef1c7b36bc78e3e0bd892af7f3d697b5fd7759efaf7bff17a3c29911fab01429bd345d479dcd60fbcad8024631b75524c09edbb83470ab8f868f5df59fbc62ba886871cbb8da2aab118c28fcfe360f781831ce83178e4f127e9f149d45414336bda24662f389dcca29a84e48340022c5102e0296f5ebb3cabbcaea1a7afef484900eaebeb2560764e569644e4404c82128810ac5db38611555564e798a355cd4d4dbcf9da6b5c74d965f47477f75b0514141626bdf7daabafd2d4d89832f9bd6989703d8f10b477082423a2156000e1e3bedfcfb517dcfbc03ef56ce4b49c18f2a389e9255fb071e5ef59b1f279ae3bdece4f2e998b54bb10b2cac1d70dfe1e445723e2d3e584245037e0f9cf1dfcf5e957f8d9df5e62e985759cddf03db34f2241b563b3dbe8c11c6974393c12300378a3af6f4955038c0672737372fa253f64e8c9b2695e747775f1e2ead57ced9c73d8b7670fafbcf0422a052c29f6eed93320f24302a06fd6f007b470e93e00ec6f136459217c312c2b12c1d183decb912f2d0419b32e23ebc41b239a677d906ff879e12fb7221fdcc45d3fbc028e39170c0dfc3de0eb01cd8308b8c37184a0c8b064bc9525e3adbcba23c04d8fbfcd932f7fc87fdf7e0b65b5137ac9377484a163b1f56a4d7797075d3366334c02300b20272bab5ff285104c9c3285cce040cf9bafbfce717575b41e38c0cbcf3f9fa064c643d3345435f1ab9d7bde79dc7bcf3df863dafdc9c80fa573d2c233a8ca33e31498f4e6e7d849b75906249002b0148fc33a627a30ddbebb7685b79b7b7e720d8baa7dccbdfea7503d0fe1eb41d23c10f040c08df0bbcde3d8f904112fb668b48567afc8e6d407bab8e9d63bf8e7437f41956584a185ed294b5ad4da96683eadb4bfef49550066430201209e7c4992387696b9f489a3a3834e8783a2e2621ef9c73f52221fe0ed37df64fec28509efe51714b068f162563ff75c4ae487d21a39bf8171636a139214abaa7bdbdc84ebf1e461632cf6c87885e0897b7f4e555a3773affb1be48d848013026ef0bb107e2752c00d0157f0ba076415742de1b7d7e449dcb2209d9fbde4e61ff7fe0f577e7b69d47d6b7a8c0004f4bc3e339ad49b81b32d168b919696169fb911c7aaaab2f88c33c27df69fac5bc7e469d3f8e8fdf7d1753d4e7892e1bd77dee1c0810349ef1f3f772e232a2b53261f4092e17093dfd3f829cfbdf529972c39010ac622026e84cf85a4b920e0420ab81181e06492902024a4a437ee85a3cd32fbc0f31be30a52ac06d0037abf1e42a90ac0949cac2c3936738b4a4a983c6d1af34e3e99b3cf3f9f6b6eb88151c1216280fd4d4d545557f3f9962d09ebeb64d0759d679f79062362dddd484892c4b9e79d8712f4a54b467e5843011252827a3a62ea7714f9a1e3a1f5ee3df8a7df715cb58a3af51208b891348fa9fafd26e12244badf650a80cf097ae49c4f81889c360614d8252409029a4167b7332a5f544b74cb49d7f4ecfe88ed570082ce1f19e931a5df66b371ee051730f7a4933866e244ca627a018510b85c2e7c3e5f7ce9efa70a1040f3fefdbcf7eebb49c3141717b370e1c27ec90fa524857c00c37576ec387f30a3fbea7c49a441e21c4bcd6561843058b7ed00e579e9c1d2ef4204891661f2dd613b00bf1b3c1d043b25c2c4c7e2ddbd5ab8ec74767646ddd302d15587ae89c41e37114845038c048815002589911682d3e9242323c36cf69180a43e9e0d8579ed95577038922fa2397fe142aaaaaa92931f216c1221377048e4e411579a1334b3e28ffbe9dd93243e6e0a80bf0729e03155bedf89140896f8282170219c2d7d1610dd803fbd6b4e3b2bc8b631a2a23ceabee68b36220d5d4f3e7e1e44ea02909e3ea0be1229326c2431293c1b0aef0f0458f9f4d3c9d390242eb9ec32323233a3e34f50d548e156dd61221f83638fa9e1f9cd4e3ab6bf6b121c70236911aa3fe002bf13e1eb41781c084f6782afecc57deff958d764927cf682e958d46895aff9a33580a18b7e07bb531680580330e0f7f7a9caed1919389d4eb212351dfbb10122c36ddfbe9d0fde4ffecf859c9c1c2ebdf4d2684fe104d58d04bdea3a499d1e4bbe08139ec87688a84ee2dcb74cf57dc9d5df0549e294ebee64cfee5d41a32f6803f8dd087fb05af074203a7691ac6808017f79cfc7dd6f790148b32a9c73ee7971e102710260f42b00a934034d0d60b34565aac7e3e1ef7ff90b452525141416925f504071490979f9f94892842ccbd8ed762c160baaaae2f7fbe3b44132c4aaf155cf3e4bc588115424710a19357a34672e59c233cf3c93b4aa31c7a19295e6484d10ef959b3c6c020d1211b6b0bc96fb7efd7daebbe52e4e6af82927d5cd664e6d3693cb542697409e7110e171803bf1b43e21e0bd7d1af7beebe3eddd26b9b99956eefdd50f29298eef2d8dad02148be28a0b14835404a0c6a2aa862ccb71ad0097cb8573e74eb36f3f782d333b9b6baebf1e805163c6b067f76e468e1ecd96cf3e1b9406104210080478f89fffe4bb37de487a7a7ac267e62f58c09e3d7b58bf7e7d9c2d00200735c4e1223fa441a61d379f979f9ac8f2fbef61f90b1fb2e62db3652349509c29519e2d539c29539c2951922993972ed1dc6db0a3dde08d5d017c118d8282ec34eefbef9f50533522611ec4560136bb6567dfd4a6260039aaaac6b97f4102c34e08babbba686b6da5b8a484c953a6f0f8238f70de0517b063c70e7c5e6fd4f3c990c868ece8e8e089c71fa7e1f2cb7b57f38ec1c5dff806cdcdcdb4b4b444910f20741fc2e74408dd5c19c4d041e8611f41499240921192123c36cfcdadd7993465f2858eee73a1fbdda4a9826bbf7d03977cd3cd138f3cccc79fed64fdce43b4f668b4f6e840df8e3bb999362e3b6b1ee79f5f4f7a9a3569b880375a00ecd9e9fdfa03a42200998aa2a42c0002d8ba650bc52525e4e4e652535bcb8eeddb597cca293c1ba9a2fb4830364e4992c8cdcb63f3a64dbcb9660df3920c15abaacac44993686e89b7a61ffd493d697a7754f8f9b5509058a1c423281092a2621bb318fbaccb91338be285c2d0d0bd4ef480274ecb65d8ed5c71f5355c113cdfbbbf8dcf37ae63efbe460cc308ca4e306f8339644f4fe3924b1bb058faa7caddddeb8b61b1a958d32dfdfece2e1501c8521425be051052b1b19b10ecddb327fcf0490b16f08f071fe4f433cf64f4d8b16cfbfcf338f20dc3a0a3a30387c381a3a323981966fc16ab9599336670f0d0215c4e27cfad5a45555515b52347026677f3e6cd9bd9b46913dbb66f376d8d182105708f90d164353c2268b749542c964c6f20a3d70750d240e8024913a011e11328001d43d3f16c7d0edf8ed7c85972274ac9044020f400bab707ddef0de550bfa8ae28a6ba22b9cbdb40e0f704a234802dd306b0a3bfe752d300b21c572ac30290400be4e7f7faa7a5a5a5f18d4b2f65f9430f71d6d96733a2b292375e7b8d0f3ff8800fde7f1f87c34177708838762b2e2961d6ac596cdcb081abafbd96a6c646fefca73ff1c0030fb060c1023efef863f647ce238c789f58c8c5b2e963101cfaadaa014bad8ca499644b41875034732f0540f625ee89b457083a3778e85efd63722e5e8ea16be87e770a59f9c5c1d519ed89959669851404209566a05d0e75b946929f6403386eeedca808b2b2b3b9e4b2cb58bd6a155e8f87ebaebf1e5996d9b7776f42f2b373723873c912468f1ecda64d9bf8e6955762b55a19396a14a79f79266eb79b55ab56a54c3e10525bc16341469a34789f40157226090c5f0fee0d2b8e38f940d823388434bb2d0034f7f75c9f1aa0bebe3e1d5062350009323db4cd9c3327a143476e5e1e575e730defbef30e0ffeed6f4c9a3c9925679d85c7e361f7ae5d288a426e6e2e1e8f87d6d656d6ac59435d5d1dd77ffbdb51f12c5cb8105992a8a9ade5d1471ea1b9b9b97ff20139d80b18ed1348541fc0807c02ada0d8648caea6be031e26b83aa385d092ae1e48e5efa5fd55019900722201209efcc2c242e62d589034328bc5c249f3e631e7b8e3d8ba650b2fbff4121d1d1d6163c962b5525850c0e4a9533973c992a4d6fefc601a575e751577dc71073e9fafdf964514a302fc7e7a891e8c4fa01f74af8e9a57dd4fba8707b15540469e3da53f96a62400093500f102b060f1e2a48e1cefbdf30ec74c98404e6e2e369b8da9d3a631b58f091fa9a0a4a48433cf3c93a79e7a2ab507224ab7cb197d3ea07e6ec0db0648126ac5f4c1bcfab042f3ebf85cbdcb07dbec5632f3ec2b537936350d10d10a8088763ad179b6f1d34f19396a5454045d5d5d3cfaf0c3b43437b37af56a66cc9cc949f3e6919797dc57211008b079d326b66fdfcefbefbf4f4e6e2e8b162d62ce9c3971cea27b225a1c8910d20c9230a27c023b1c83f70974379a7e816af55ca4b49c3ec31e0e74b644376fb38b3221e23f887d61c05540940148b416d8b47123e9763ba79c761a604ed85cb572259e90072f84adfffa0b2ee0d8638f8d4bd0300c6ebbf55673aa5730fef6438778fcb1c778fbadb768b8fc724a8353d31e7bec31d6ad5b97ca7712586ffacd858cc166a0a50332ad44947a296a1f6a9147ee10207403cb9845d8a65f96343d49d7d8f0bf66215454054555515515c562eef3f2b2c9983c2dd4473d247434474f04ceccb7b796d735a4649cf427003e206a3cbf2f011042f0febbefe2743a5114257aae7e4cd8d5ab563175ead4b0f36808870e1e8c223f726b6c6ce457bffa15679c71068d8d8dac5fbf3ed53ce2e4f98bb1abf4722c203dcf4e7a9a6a9a20a15f05ea7ab013c7e8bd08114449c879d5a8e589ab2fbdb989971ffe37ef7df239858585548c1a4b5e5131c2e741eb6963e307efd2e63368f30bac8acc98f2428e9d389aa9c7cfa060f2149007365bcfd00dba5aa335405661c6aba93edf9f006c050cb7db2da72a000212ced18f0ddbd3d3c3eeddbb19155365b4b6b626ed5f1080a1ebac5c9952f516858967dd44a63d9da45db78646c0e540f73949be0241727876efe499fb97a33adab978511d975ff00d28ab018f0bdcdde6ded383e1fa0c34b3be16c09af66efef9dabbdcf2efb7985992c92d4bbfc9885933534eb7abcd89aef5f657a465dab0e7a43f9beaf37d8adb934f3ee9063e7074760abfdfdf3ff9c9b624611b1b1be3d26c89e8c64d16c76010fa1f5022f2356f0fbecefde83e67df912441e38b2ff0b75fdec5158b4ee486fb1f23ffd2ff40aa1c0b3e2ff8dce00fee7d1eb0f4f6e54bc0fc0295bf4dc9e09313b3a9c0c7f9b7fc913fffe897783b3a524adb11a3feb3cc05a5df48f5dd53d137ff650821ed899c8c3140a293856ddebf3f2eb18402c0d0c88790434834f986e6c7d7d542c0790891c4ffb0cf38758d37eefe03ef3cf33cb7df731f39177e0f6c7624af1bbc2ef07b4cd2839bf0ba4149ac74b35589bb27d8f96e8d8dbf7fb88babaeb915771fde50000870b4c4084081bda9bcae21b9476d0cfa1580279f7c7215f04c6757178da14e1712b702a208ebefba10ecdcb913b7db8dd7ebc5ebf5e276bbd9bd7b777cf821901f6e059827e6b961107075e0ebdc8f11f00e2a5e8057eebe87773fdac88dbffd338c9c84f079103e37047c089f07bcee0801f09afb24378f76a20000164c494441540210c28d35699c536a615ba7873b6ebbabcfb0dd879c51fdff8a2a93579ef3e040be21d579011703efb71e3c38d9edf1505d5969f60d90bcae4ee57a576727b7dd7a6b4ae1870ad3234c60047cf8bb5b11fad0feb8d2f3d926fef1d626567def62a89988e47182df6b0a419078e1f32005054184aa8014705d958d1507023cbfa5896fed69a4aca63261b8d69dd18e247915b9c2625307240029999c4f3ef9a407980b3cd1e374f2d9d6ada2a9b9196fb0076e30e43380f0c3014902cddd89af73ff90c94708fe78d75f39bfd48275ded9617243c4874abe14ac0244443580b75f271dc6d895b04fe5aead89c773fc9e001dfba3d57f7e45cefaf2ba86bd03f9949467073ff9e4934ee0c2f3ebeb1fc954d5c7da1d8eb47687839cec6cac562b1655c562b1600d2efa986ca14723746e1883223f1581880c139a5b10e86e450effc86168300eece799bd5d9c373d074a6b903c3d08af1bc9ef41f83da6d1e7f7823796fca041d80fb6b9f470b783e3506263b075e7a1a8efb46558c92bcbfec340bf65c0ab845d5c59e505d20ef97c6cf37ad8e774269dc0f1658211f0202bc3f37f8c832d6de8029c86045e67b8b40b8f0bbc1ed3e20fd7ffeea031e846b43787c73dfac2b36dbd1aca921ddfd368e806adbbdaa3ae1556e5f925497a72a0df32600150adcacf35bf4ea1cdc6ac050b183173061ddd0eda1ded1c686be3406b1bba6eba5849f4ae0a2249a66fbe149c781b3a0ede25ec85150c2c91f89c88ebbdf782bf7e233a9ce137bd7025091479f87e9056386a24aa044f36ba387dd3bb4895634df51f6aee79dd26e191ad008f0bbadafb8dfba32e8dbfec3335559eddc6fcd3e6c58539b4cf11e7ff975f91fb6c795d43fff54b0c0624002b962e9ba4f9f5f02a50c563c7a2aa2a35b523a8a9ade8ed5409b5b763dbdca1e388fb51e789c246dc37c3c6afa8191bd6d0fcf8bb5a31b4e151f9b1507272f9fa84113cb5b9893ffffe6eaeffc18fc16a3389f67bcd5680df1bb4fcbde0ee4134ed483ae93384169fc1351bdd68c14f3b77e14c6c564b5cb8033ba28dbfeca24c3272d3ff38a86f1948e06f9c74c26f84218e05c82a2ea66ad64c2c36c55c82f54b42bee6e9c6d7652e08f94562ca8c49ac79f94d56edeb66cf076b48777752ac68a83e0f04fcd0e300471be2d07e68de65ae07d0079e6e0d70d506375d41f6a7d694f2c39fde8835c617d0d1dcc5811d07a3ae554c2c6d1a73e675370ee63b52d68b2b962e9314556ed735230f60e409275039fd58d2b36d31ffde192cb982212dba280c7cdd6de8de3e57441956b437b7b0ec0777f2d901b3c3460246d965e6e6a99c90af52619329b2c9145b1367f3019fc1eab600ffdb1a60634faf67f0dc63aab9e3ae5b49b3457b000b43f0e9cb5bf1f6f46a367b4e1a93178dbbb8e2c4cb1f1bcc370ca40a981e221fcc7a5008611a567d1213128cfe17478e132212909f409b0843c3d7d932a44e9dc1a0a0bc8c7f3c7c372faf58cdfd8f3dcf9ef61e76b80d76b8fd2cdfdf3b3e2f01f91689629b4c8145a2d56fb0db6d84557d088a2273f9e973b9f6c62b51120c0ab5ee3a14453e40d998e22649969e18ec37a42c00b2229f67e82689b2aa62cbca4256a4debf6ef6477eb079174f7e02c20740be11f0e1eb6a197adb7e08587cee192c3ef70c3edfba93ed9f6c62db961d6cd9d3c296d64e7c010d01b40704ed81c4feff19360bf50b6771d1951752989fd8bf400be8347dd61a75cd9e93466155decde5750d836e86a52c008a2a2f0a09405a561618c2fcf152927ada1c4f8f243f816d9080dca48210577d18e83e17beaed6b07639d218377e14e3c6478f6eeededd445bf301821912d678e1bd21987de22cd43e564107d8bfa535cef20f96fec787f2ce290b80a11be12f4bcbcec6fcf3964cbf46da17447ec0e520e0ecbf5975a4515b3b82dadac453b95285d7e58b33fc86a3f4438a02b062e9b20c5d33c2cefeb6ac2cf3cf9bc111b678f2fb217128e40b1d7f771bda301a7b02c18b6deff1abbf3f8ee3800b599150541959955014194595c9ceb2b368f654ce9fb1801a5bd9b0a59d0a76ad6b0cfeebb017c351fa21750d504b448bc19a918130823f5e3e8ce40b2330ecc6decbad1ff0fb179fe2a0a7938a53f2b974e23728cdae20dd6aa753ebe0e56dcfb06bf74edc87ba7972c31aeefbfdcb648fb632ffb8c9fce2f42bc8563386ed5d12a16d773bdd6dd17e0a9979760aabf36f1c6ae987d40520aa82d2037e7ad7d58927374e1806d2c687601cd16d7c43f3e173ec37fdfa86015ee1e382bfff9c565f07b32e9fc0b7aabecb31b9c7e2d1dcb835276edd49a69e415e7936d999bdd9547a968db697fdac7c741d2bffb58e0baf389e5f9d76edb0bc53dc3b3a7decfd34da674292252aa794bf517142c38ae14823550188d23f7e971ba11b18ba8ea2ca29901b2294a87abcaf367e645cbadf83bfb339287443c721ad934bfefe9fa4cd94b8fdb4ff645afe5c5c811ebcba3b6e93a5e8e698629728fbba8dd2afd9d8f367378ffce91d366dd9c7d337de6efe897c98208460c707fba2dcbd004a4717fa728a32937ba30e10a90a40d45bf8dd2e843030340359918695fcc79fd670743ab059156c5605ab1c40357a484fb371fc342f8a2c180a1a7dad5cfc87ffa2ec3c3bb79f7c1f85b6125c5a0f3edd835b77e2d1dd780d375edd834773232719319764a8fdb61dc3e762c3eb4d7ca7f877fcf992a509c30e06fbb7b4e2ec88eeda4fcbb45131bee487a97afca682540520cadc0eb83d08c340f30750ad664b20be8307c2e447d6eb4904e58db53adfffd9d3ec6bfa08f3ff3d3624ac8005dd3880aeef44c24a7eee2cc68f1cc99d3f984455c5c0dafe02c1657ffc35b6591ab7ccff6f8a6ca5b834a759da83a4fb740f5edd13d600823e044e82ea6bec6cfe410fcf3ff1291f9df83933abc60de89d12c1d9e166ff96d6b8ebd553ca37a956f59e212710819404e0dcbb7fdbf2f4f7bfef34742313c0ef72210c81cfed272dd33a24f2b76c177cf7476fb06d672e1919cbf8e63773a8aa92282a0287c3e0edb70d3efcc0acf70da39340e07ddefde437d45dbc9cda11a7f2e06f1630ba2a35bbe0895dafd2d1e9e4a245a75393390e8feec26798847b747790fc5ef5ef333c7d0b00a06649e4cdb170e8753f77af7c8a876ff8714aef920c7a4067fbfb7b7a9bd24114d5e4eb79e539170c87e117895407c8559fa185d54ec0ebc579e810018f1f43d763c88f50fbb1d67d0cf92fbeeee794fa076969bd9c73ce69e09e7bf239e71c85f1e325ac564156a6447ec4042259cec5663b9582fc57c8cafc257b9b3f66e1653fe6fe27dafafd001d9ddf3ffc0cc5a7d898577a265edd8d477385c9f6682e73d3cd6b1edd1d3608fb435a85998d4d4da979f22683a10bb6aedd1535cd0bcc1540474c28bdb3bcae61cb901248805404200398d7e2706c8dbc7870c7760cc3c0dde52125f263ba7657bee0e59a9b9e62e2c4dff0d707f2b9ea2a858c0c81db656e1e37b893ceba56484b3b9fbcdc6790e591dcfec7dff3b77ff7dd29b4b66d03cd1ff590556ba336737c9878b7e6c21d26dd8527782d74ee0c74f7192f80ee364babab7b68cdd39d1feda3e75074bd2f4912b5d347ecb4d9ad3f1f52e449d09f006401f300fb4beb3f7d39f28663ef5e74bf1f57a71b438ffed191e8a35d2f84e085d75c5cf71f7f62e1c29f72efbd99646682cb257039cdbdd32970b9c0e90a5527495e5ece2337e721c0ca6feeff174e7772edb861df6ef38372324c834f73e18e29f1bd75bf69007a74174ead7f0170ed30ab209f6bf043d08d9b5a686f8c77031f31a1b43bbf3ce7a4f2ba067f82c7868cbe04c0069c085801567ff2c91e5d16e16a400f68b4efd98311d0e939e48c57f351e7bd1a41d3e03b37ff9551236fe3c7b766e0f1083c1ecc92ef3670b983e7c1bdd64f9eca720119f6ebf17a5bf8fe1d9b9286b32b361070706b37dd0147c2269f272c082e3cba932e7f07817efc08dd7b757a369b2f396e7c799f6193e1e09e0ef66f8d37fa0a2a738d8a634a4e2baf6be877a187c1229900c8985ec0514b287db863e7a391e72d9b36e3f7b87139dc78ba3dfd74f098d7eefb7b1b2eb795af9f3d8a40c024dae534707b4c95ef719b5ac0ed36efe929983c56eb7c005e7a2bf994b1136ba682042dabdd7cea782faeb967967e531b9855828783de96be1316b0efef9ef032ff0d0b17f7ffb231e839e462d7baf8195219b9e9d44cadb8b1bcae21f982c9c38064023001288abdf8bbe756bf8e2a853be175bf9fa68fd7230c03474b17016f80687b20fa9fb9866ef0bbbf3c4e76f6059c78a28cdb0d2e17b8dce00aaafd48f25d2e70f6f4dfee5714d36f3ea039e97626361cc6e48d60f4ac623ad705f8c743cb69f53406897747d5ff1ecd85577373c0d388bf9fd2bfef210fee5d26fb59d9699c392ba5ff3485d1d9dac396b776c659fcaa5565e48cca47aa175d352837af81209100a403c7240aecd734e3950d1b7f1d79ada7b5958ebd7b317483f6c60e0ccd88273f58fa77ed95e970bc4a5ddd3854d524d9ed1678dc02b7877075e0f19842e0f1081c7d2f9f0b80ae076b2601073b9293f6a7ebbe8b2d5b65d7f24e7ebdecb7bcf9c69b3439f6d215e8c0abb9e9f277d0e66d66b7f3735c5af2c126c327d8f50737875e37ab658b45e18f3ffc7642278e64e8d8dfc5e76b7761c4a83849921839a37273469efd8a248f0e2b12f5034c0e5e4fd8b8fed38b2f7d78dcf8b1ef64cad6f04a5007366fc69699812d2b8bf646070555b9718e2220f8ecf37640273fdf86cb65e072054bba1b530882eadfd40ae6beabb37f0d10d0826b0448e0f525371ac61655f2d0ed4bb9fae7bfa7fd432f4f7df82ac890395a21e7580bf61a85ac096a524739df4183f637fcb4bfe927d065be972c4bfcd74d0dcc9b3ca5dff70ce1d03e073b3fdc1757f20146ceac74e657e42cfea28cbe58c40a800cd4f4f7d0cf1f7de2d7775ddef084d08c7430a76ceffde0432a674cc7d0b2d0760628aace0b77138704a1acc4fc0b6867e7263ceef9410d40781f52ff2e97c01dac0ebabafa160021bcb8dd0f00909d59c884d1c9ff3806707ced445ebfe74e7ef08ffb79ebb52d18bac0b94dc7b92d28ef12a4572ac836506c12729a84bfddc077d04077c6a86a55e127dfb9900b4e9cd75f9685d1b6ab9d5deb1b49d4bf5435b9bcbda83a7f46795d433fc6c7f021d60da5141883f97a493787cbe5cbcdcad830a6a4f4544468216e03675b1b19f97920645c9d6ed2336da61004b5405181c4effffa3a9d9dbba93be19c20c944b402a285e0e041414f3fc3fe6ecf9ff0fb5e0160f109f358b2a0a6df8fceb0a571ce9c3abebef07802197e1c9e1e9c9dde30275a9720d021f0b519789b0d029d0211511e154566f1a2a93c72db8fa89b90d22f7a01736877d7c7f1061f40e5a4b28e8af12533063ab56ba8885576d3804998eabfdfed17179fbf687259e54f23a559b158289b3c095b4606920cc535f9a465da10868eaf733f57defc212fbef908679f7d1bb3e75c69aafb50bb3f62dfd525686a12f435e92810f888ceae2b40f8902478ee81654c1e5b3ca88ce876ba59bf7b071fefddce9e03ad18c20877690b41b84b5842e2a7f5975252d0efff98c21002f66dd84fcbf68309ef574e2eeba8185732a3bcae61cfa05e7e08881580e330ff1198920000fa3dd75e79494546eef551914a12f935356497962284813d5b253bc70742c3e7379875de3fe9eafe9c69c79ecc8ce9e7601813f07a47e00c76041d386096febec8f7781fc3e9fc05081d24b8b1e15cbe7ff5ec61ca96e183a1196cff606fdc420e21544e2a73548c2f997e24c88778013809a862000200e8f77de7dacb8b6d99df8aadd7ec7979a4e7e6d0b1672f695936464eaf24ab3083e6362f5fbffe090eb47d06405a9a8d8ccc52a09e406034aa321e4589ff3780aeefc1ef5f83dbb31c436f0c7fc1e9279dc4fdff79c6b064c87022e00db075ed6e5c8ec44dd3ca89658e8a634a6694d735ec3eccaf1646ac00cc06c632400100f4df5e75f9d76af30a6f15bae8b32d543cb280aa49e5c8aacccffef0190faf7c8a40203e8324c98e24e7997bc986a67d46acf7af2cc379a79dc65d3f9a977451c92385ce03ddecfca831d837120d5996a83976444b716dc19cf2ba86c446c16142ac11980594d38f1198687b71fda75b6aca8a3faa2e2c3a5d1822a98fb3cbe1e1e09e0e1455e66ba755f3cdf3e6a0c8151cea9470badb22d47e00217a10460786d14694d92c41cd88513cf89b4bb8e2bc295f2af2f580ceeef54decdbd08ca1c5d761d6740ba36657bf54589957575ed770c4dd9a6373ae00389d416880d076d6ec9945d79cb2e8c1802b9078598b0858d32c948f2fa6b8b6005991d1749dcf77b5f0e6875d341de821e4082b823e06a1767355b9cc0d971ed747cc4706dd6d4eb67fb03761a907c82cc81023a78ff82f7b4efa4f5359c7f7702051d15982a909062d048a2c1bfffcfef796d90de54a4317fd16cf5841f8bf0697c34de3a6163a5b93b7598b6b0b7c5593caceab5a78e57387f1d5fa4522552d03650ca21a086d4208e3a9b5efbdad29e2d13993c7cd0b7802f9f1c9f442d70c3a0ff4d0b6bb1dcdaf61cbb4a25a07bc74c16187a7dbcbee8f9bd8fbe97ebcaec41d77922c513db97c7fd5e4f2d923e67d33a5059c0f2712954e05b31ab033042d10b93df4fd1bce294acffca9cfe9eff75fb621e41467513cb280fcf21ca461f4b61d320474b6f5d0baf350d2a65d08b60c2bd5532b1ecc2fcfb9aebcaee18b9daf3e4824cbd952cc26e1b00800a05b54d578f4969bae4bd395fff07b02fdfecf2e04599129aec927af2297eca28c2366f0f9dd01daf6b473704f073e77dfddf492245132aad0593eaef8b29a93af4afee7cb2f01facacd69c02886510800bd223f9ffb6fbaee36ddad5fa3f9b4e4bfc04a00c5a2905392455e5936b9a5d9586c5f5c352184c0d9e1a6abb587ced61e5c1dee848337b148cf4aa37272d973f9e5399796d735a430967964d1970048983d83250cb31000faec31a3955f5c76c103de2edfd784d177df413264e4a563cfe9dd32f2d2e3fea09d12843901d3d3ed3537a78f43fb1c71f3f1fa82244914d5e6f7544e2c5b52bdf0ca3707fe124706fde95319a80372f9028400d0e74f9a28df76f9f9cb3477e07a57a7a764a81f644db760cf49475165148b62ee5505c5aa606806baa6a30774f48041c0af11f06ae6efd606d928535499c2ea7c47514dfeed9979f67b0fd730ee7021950a55068ee50bd204115b60cd6f6fafd3fcda9dce0ed7717ac0f852b70755ab42514d415b5175fe4fec39690f96d735e847fa9d06838158541381117c8102104ae8b53b7e9e25abf2afdc9d9e06afd3973d84ef1b76641566889ce2ac8d65638bef5354f9be2f4b87ce60315093ba08d35d4ce10b148048bcf3c75fd56901fd3b5e977f81bbd35362e8c6616d06489244666186915d98b131b724fbfeacc28c7f95d735f4ef2bfe7f0483c94c0ba6100cb75dd0ef44bf0ffe7aa73de0d3bee5f7042ef47b0213dc9d9ecce15a4b38045991c9c84d17b64ceb81b44cdba6d25145ffab5a9507caeb1a8edc22445f2086529af231ddc7ac1c26018845f3dae56acbf683c707bc81f99a5f9b11f0e9e302de4099a18b74433714c33064a10b49d78cb0f3a56a5351ad0aaa450928aae29355d9ad58e4ceb44cdbcef4acb4d7f3ca7356cbb2b465b8e7e07d593154752a01c5982388128759005241cbdae592806c2043d78c4c45950f95d7350c6d12dfff4718aefa54c6d408f90c5e23fc7fa962bfec18ccff911241006ecc75049c988265616083485f0995fb65c317d197ea0e6e0a41d5cbf0699aa318660c970648040178816e4cf52e05d33baa01be4438dc2553c2d43a2abdd3d28eda004710475a354b440bc2511cc5511cc5511cc5511cc5511cc5517cd1f87fdfa54b2570e59fed0000000049454e44ae426082</data>
+ </image>
+ <image name="image1">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<includes>
+ <include location="global" impldecl="in declaration">klineedit.h</include>
+ <include location="global" impldecl="in declaration">libkipi/interface.h</include>
+ <include location="global" impldecl="in declaration">kprocess.h</include>
+ <include location="global" impldecl="in declaration">kio/previewjob.h</include>
+ <include location="global" impldecl="in declaration">klistbox.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">libkipi/interface.h</include>
+ <include location="global" impldecl="in implementation">kprocess.h</include>
+ <include location="global" impldecl="in implementation">kio/previewjob.h</include>
+ <include location="global" impldecl="in implementation">klistbox.h</include>
+</includes>
+<slots>
+ <slot specifier="non virtual">reset()</slot>
+ <slot specifier="non virtual">readStderr( KProcess * proc, char * buffer, int buflen )</slot>
+ <slot specifier="non virtual">EncodeDone( KProcess * )</slot>
+ <slot specifier="non virtual">slotMPEGFilenameDialog( void )</slot>
+ <slot specifier="non virtual">slotAudioFilenameDialog( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonUp( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonAdd( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonDown()</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonDelete( void )</slot>
+ <slot specifier="non virtual">slotEncode( void )</slot>
+ <slot specifier="non virtual">slotOptions( void )</slot>
+ <slot specifier="non virtual">slotClose( void )</slot>
+ <slot specifier="non virtual">slotHelp( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesSelected( QListBoxItem * item )</slot>
+ <slot specifier="non virtual">SlotPortfolioDurationChanged( int )</slot>
+ <slot specifier="non virtual">slotOptionDlgOkClicked( void )</slot>
+ <slot specifier="non virtual">slotGotPreview( const KFileItem *, const QPixmap &amp; pixmap )</slot>
+ <slot specifier="non virtual">slotFailedPreview( const KFileItem * )</slot>
+ <slot specifier="non virtual">slotAddDropItems( KURL::List filesUrl )</slot>
+ <slot>m_AudioInputFilename_toggled( bool )</slot>
+</slots>
+<functions>
+ <function access="protected" specifier="non virtual">RemoveTmpFiles( void )</function>
+ <function access="protected" specifier="non virtual" returnType="bool">DeleteDir( QString dirname )</function>
+ <function access="protected" specifier="non virtual" returnType="bool">deldir( QString dirname )</function>
+ <function specifier="non virtual">show()</function>
+ <function specifier="non virtual">ShowNumberImages( int Number )</function>
+ <function specifier="non virtual">closeEvent( QCloseEvent * )</function>
+ <function specifier="non virtual" returnType="QPixmap">LoadIcon( QString Name, int Group )</function>
+ <function specifier="non virtual">addItems( const KURL::List &amp; fileList )</function>
+ <function specifier="non virtual">writeSettings()</function>
+ <function specifier="non virtual">readSettings()</function>
+</functions>
+<layoutdefaults spacing="6" margin="6"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kimg2mpg.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kprogress.h</includehint>
+</includehints>
+</UI>
diff --git a/kipi-plugins/mpegencoder/kipiplugin_mpegencoder.desktop b/kipi-plugins/mpegencoder/kipiplugin_mpegencoder.desktop
new file mode 100644
index 0000000..7ce89ef
--- /dev/null
+++ b/kipi-plugins/mpegencoder/kipiplugin_mpegencoder.desktop
@@ -0,0 +1,54 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=MPEGEncoder
+Name[ca]=Codificador MPEG
+Name[da]=MPEG-kodning
+Name[de]=MPEG-Kodierung
+Name[el]=MPEGΚωδικοποιητής
+Name[es]=Codificador MPEG
+Name[et]=MPEG kodeerija
+Name[fi]=MPEG-pakkaaja
+Name[gl]=Codificador MPEG
+Name[it]=CodificaMPEG
+Name[nds]=MPEG-Koderen
+Name[nl]=MPEG-diavoorstelling
+Name[pl]=Koder MPEG
+Name[pt]=Codificador MPEG
+Name[sr]=MPEG кодер
+Name[sr@Latn]=MPEG koder
+Name[sv]=MPEG-kodning
+Name[tg]=РамзгузорииMPEG
+Name[tr]=MPEGKodlayıcı
+Name[xx]=xxMPEGEncoderxx
+Name[zh_CN]=MPEG 编码器
+Comment=KIPI Images MPEG Encoder Plugin
+Comment[ca]=Connector del KIPI per codificar MPEG d'imatges
+Comment[cs]=KIPI modul MPEG enkóderu
+Comment[da]=KIPI-plugin: MPEG-kodning
+Comment[de]=Ein KIPI-Modul zum Erstellen eines MPEG-Films aus Bildern
+Comment[el]=Πρόσθετο του KIPI για κωδικοποίηση εικόνων MPEG
+Comment[es]=Complemento de KIPI para codificar imágenes MPEG
+Comment[et]=KIPI piltide MPEG kodeerimise plugin
+Comment[fi]=Kipi-liitännäinen mpeg-videoiden luontia varten
+Comment[fr]=Module externe KIPI pour créer une vidéo à partir d'une liste d'images
+Comment[gl]=Plugin de KIPI para Codificazón de Imaxes en MPEG
+Comment[it]=Plugin di codifica MPEG delle immagini di KIPI
+Comment[ja]=Kipi 画像 MPEG エンコーダプラグイン
+Comment[nds]=KIPI-Moduul för't Koderen vun Biller mit MPEG
+Comment[nl]=KIPI-plugin voor het maken van MPEG-diavoorstellingen
+Comment[pa]=KIPI ਚਿੱਤਰ MPEG ਇੰਕੋਡਰ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Koder MPEG
+Comment[pt]='Plugin' do KIPI de Codificação de Imagens em MPEG
+Comment[pt_BR]=Plugin para codificação MPEG de imagens do KIPI
+Comment[sr]=KIPI прикључак за MPEG кодовање слика
+Comment[sr@Latn]=KIPI priključak za MPEG kodovanje slika
+Comment[sv]=KIPI-insticksprogram: MPEG-kodning
+Comment[tg]=Модули KIPI барои рамзгузории тасвирҳои MPEG
+Comment[tr]=KIPI Resimler MPEG Kodlayıcı Eklentisi
+Comment[xx]=xxKIPI Images MPEG Encoder Pluginxx
+Comment[zh_CN]=KIPI 图像 MPEG 编码器插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_mpegencoder
+author=Gilles Caulier, caulier dot gilles at gmail dot com
+X-KIPI-MergeMenu=true
diff --git a/kipi-plugins/mpegencoder/kshowdebuggingoutput.cpp b/kipi-plugins/mpegencoder/kshowdebuggingoutput.cpp
new file mode 100644
index 0000000..b492f57
--- /dev/null
+++ b/kipi-plugins/mpegencoder/kshowdebuggingoutput.cpp
@@ -0,0 +1,82 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// KSHOWDEBUGGINGOUTPUT.CPP
+//
+// Copyright (C) 2003 Gilles CAULIER <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// Local includes.
+
+#include "kshowdebuggingoutput.h"
+
+namespace KIPIMPEGEncoderPlugin
+{
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+KShowDebuggingOutput::KShowDebuggingOutput(QString Messages, QString Header, QString Foot, QWidget* parent )
+ : KDialog( parent, "debugViewDialog", true )
+{
+ setCaption( i18n("Debugging Output") );
+
+ okButton = new QPushButton( i18n("&OK"), this );
+ ClipBoardCopy = new QPushButton( i18n("Copy to Clip&board"), this );
+ debugView = new QTextView( this );
+ grid = new QGridLayout( this );
+
+ grid->addMultiCellWidget( debugView, 0, 0, 0, 2 );
+ grid->addWidget( okButton, 1, 1 );
+ grid->addWidget( ClipBoardCopy, 1, 2 );
+ grid->setSpacing( spacingHint() );
+ grid->setMargin( marginHint() );
+ grid->setColStretch( 0, 1 );
+
+ connect( okButton, SIGNAL(pressed()), this, SLOT(accept()) );
+ connect( ClipBoardCopy, SIGNAL(pressed()), this, SLOT(slotCopyToCliboard()) );
+
+ // add the debugging output
+
+ debugView->append( Header );
+ debugView->append( "-----------------------------------------------\n" );
+ debugView->append( Messages );
+ debugView->append( "-----------------------------------------------\n" );
+ debugView->append( Foot );
+
+ resize( 600, 300 );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+KShowDebuggingOutput::~KShowDebuggingOutput()
+{
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+void KShowDebuggingOutput::slotCopyToCliboard( void )
+{
+ debugView->selectAll(TRUE);
+ debugView->copy();
+ debugView->selectAll(FALSE);
+}
+
+} // NameSpace KIPIMPEGEncoderPlugin
+
+#include "kshowdebuggingoutput.moc"
diff --git a/kipi-plugins/mpegencoder/kshowdebuggingoutput.h b/kipi-plugins/mpegencoder/kshowdebuggingoutput.h
new file mode 100644
index 0000000..eecb0f0
--- /dev/null
+++ b/kipi-plugins/mpegencoder/kshowdebuggingoutput.h
@@ -0,0 +1,62 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// KSHOWDEBUGGINGOUTPUT.H
+//
+// Copyright (C) 2003 Gilles CAULIER <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef KShowDebuggingOutput_included
+#define KShowDebuggingOutput_included
+
+// Qt includes
+
+#include <qpushbutton.h>
+#include <qtextview.h>
+#include <qlayout.h>
+
+// KDElib includes
+
+#include <kdialog.h>
+#include <klocale.h>
+
+namespace KIPIMPEGEncoderPlugin
+{
+
+class KShowDebuggingOutput : public KDialog
+{
+Q_OBJECT
+
+public:
+ KShowDebuggingOutput( QString Messages, QString Header, QString Foot, QWidget* parent );
+ ~KShowDebuggingOutput();
+
+public slots:
+ void slotCopyToCliboard( void );
+
+private:
+ QPushButton* okButton;
+ QPushButton* ClipBoardCopy;
+ QTextView* debugView;
+ QGridLayout* grid;
+};
+
+} // NameSpace KIPIMPEGEncoderPlugin
+
+#endif // KShowDebuggingOutput_included
+
diff --git a/kipi-plugins/mpegencoder/optionsdialog.cpp b/kipi-plugins/mpegencoder/optionsdialog.cpp
new file mode 100644
index 0000000..615c321
--- /dev/null
+++ b/kipi-plugins/mpegencoder/optionsdialog.cpp
@@ -0,0 +1,134 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// OPTIONSDIALOG.CPP
+//
+// Copyright (C) 2003 Gilles CAULIER <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// Include files for Qt
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qstring.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+
+// Local includes.
+
+#include "optionsdialog.h"
+#include "kimg2mpg.h"
+
+namespace KIPIMPEGEncoderPlugin
+{
+
+////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////
+
+OptionsDialog::OptionsDialog(QWidget *parent)
+ : KDialogBase( parent, "MPEGEncoderOptionsDialog", true,
+ i18n("MPEG Encoder Plugin Settings"), Ok|Cancel, Ok, false)
+{
+ Icons = new KIconLoader( QString( "MenuDlg" ) );
+
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout* vbox = new QVBoxLayout (box, 10);
+ QHBoxLayout* h1 = new QHBoxLayout( vbox );
+ QVBoxLayout* v1 = new QVBoxLayout( h1 );
+ h1->addSpacing( 5 );
+ QGridLayout* g1 = new QGridLayout( v1, 3, 3 );
+
+ // ImageMagick binary programs folder
+
+ QGroupBox* IMBinFolderGroup = new QGroupBox( 3, Qt::Horizontal, i18n( "ImageMagick Binary Programs Path" ), box);
+ g1->addWidget( IMBinFolderGroup, 1, 1, Qt::AlignLeft);
+ IMBinFolderEditFilename = new KLineEdit( IMBinFolderGroup );
+ IMBinFolderEditFilename->setMinimumWidth( 300 );
+ QPushButton* IMBinFolderButtonFilename = new QPushButton( IMBinFolderGroup );
+ IMBinFolderButtonFilename->setPixmap( LoadIcon( QString( "fileopen" ), KIcon::Toolbar ) );
+ connect( IMBinFolderButtonFilename, SIGNAL( clicked() ), this, SLOT( slotIMBinFolderFilenameDialog()));
+
+ // MjpegTools binary programs folder
+
+ QGroupBox* MJBinFolderGroup = new QGroupBox( 3, Qt::Horizontal, i18n( "MjpegTools Binary Programs Path" ), box);
+ g1->addWidget( MJBinFolderGroup, 2, 1, Qt::AlignLeft);
+ MJBinFolderEditFilename = new KLineEdit( MJBinFolderGroup );
+ MJBinFolderEditFilename->setMinimumWidth( 300 );
+ QPushButton* MJBinFolderButtonFilename = new QPushButton( MJBinFolderGroup );
+ MJBinFolderButtonFilename->setPixmap( LoadIcon( QString( "fileopen" ), KIcon::Toolbar ) );
+ connect( MJBinFolderButtonFilename, SIGNAL( clicked() ), this, SLOT( slotMJBinFolderFilenameDialog()));
+}
+
+
+//////////////////////////////////// DESTRUCTOR /////////////////////////////////////////////
+
+OptionsDialog::~OptionsDialog()
+{
+}
+
+
+//////////////////////////////////// FONCTIONS //////////////////////////////////////////////
+
+QPixmap OptionsDialog::LoadIcon( QString Name, int Group )
+{
+ return Icons->loadIcon( Name, (KIcon::Group)Group );
+}
+
+////////////////////////////////// SLOTS ////////////////////////////////////////////////////
+
+
+void OptionsDialog::slotIMBinFolderFilenameDialog( void )
+{
+ QString temp;
+
+ temp = KFileDialog::getExistingDirectory(IMBinFolderEditFilename->text(),
+ this,
+ i18n("Select path to ImageMagick binary programs..."));
+
+ if( temp.isEmpty() )
+ return;
+
+ IMBinFolderEditFilename->setText( temp );
+}
+
+
+void OptionsDialog::slotMJBinFolderFilenameDialog( void )
+{
+ QString temp;
+
+ temp = KFileDialog::getExistingDirectory(MJBinFolderEditFilename->text(),
+ this,
+ i18n("Select path to MjpegTools binary programs..."));
+
+ if( temp.isEmpty() )
+ return;
+
+ MJBinFolderEditFilename->setText( temp );
+}
+
+} // NameSpace KIPIMPEGEncoderPlugin
+
+#include "optionsdialog.moc"
diff --git a/kipi-plugins/mpegencoder/optionsdialog.h b/kipi-plugins/mpegencoder/optionsdialog.h
new file mode 100644
index 0000000..e5a1f92
--- /dev/null
+++ b/kipi-plugins/mpegencoder/optionsdialog.h
@@ -0,0 +1,63 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// OPTIONSDIALOG.H
+//
+// Copyright (C) 2003 Gilles CAULIER <caulier dot gilles at gmail dot 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, Cambridge, MA 02110-1301, USA.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef OptionsDialog_H
+#define OptionsDialog_H
+
+// Qt includes.
+
+#include <qpixmap.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+class KLineEdit;
+class KIconLoader;
+
+namespace KIPIMPEGEncoderPlugin
+{
+
+class OptionsDialog : public KDialogBase
+{
+Q_OBJECT
+
+ public:
+ OptionsDialog(QWidget *parent=0);
+ ~OptionsDialog();
+
+ KLineEdit* IMBinFolderEditFilename;
+ KLineEdit* MJBinFolderEditFilename;
+
+ private slots:
+ void slotIMBinFolderFilenameDialog(void);
+ void slotMJBinFolderFilenameDialog(void);
+
+ private:
+ KIconLoader* Icons;
+ QPixmap LoadIcon( QString Name, int Group );
+};
+
+} // NameSpace KIPIMPEGEncoderPlugin
+
+#endif // OptionsDialog.H
diff --git a/kipi-plugins/mpegencoder/plugin_mpegencoder.cpp b/kipi-plugins/mpegencoder/plugin_mpegencoder.cpp
new file mode 100644
index 0000000..101df43
--- /dev/null
+++ b/kipi-plugins/mpegencoder/plugin_mpegencoder.cpp
@@ -0,0 +1,119 @@
+/* ============================================================
+ * File : plugin_mpegencoder.cpp
+ * Author: Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Date : 2003-09-02
+ * Description : Images MPEG encoder plugin ('kimg2mpeg'
+ * program from 'kvcdtools' project
+ * (http://kvcdtools.free.fr)
+ *
+ * Copyright 2003 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+// Local includes
+
+#include "checkbinprog.h"
+#include "kimg2mpg.h"
+#include "plugin_mpegencoder.h"
+#include "plugin_mpegencoder.moc"
+
+typedef KGenericFactory<Plugin_Mpegencoder> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_mpegencoder,
+ Factory("kipiplugin_mpegencoder"))
+
+Plugin_Mpegencoder::Plugin_Mpegencoder(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "MPEGEncoder")
+{
+ kdDebug( 51001 ) << "Plugin_Mpegencoder plugin loaded" << endl;
+}
+
+void Plugin_Mpegencoder::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_actionMPEGEncoder = new KAction (i18n("Create MPEG Slide Show..."),
+ "video",
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "mpeg_encoder");
+
+ addAction( m_actionMPEGEncoder );
+}
+
+Plugin_Mpegencoder::~Plugin_Mpegencoder()
+{
+}
+
+void Plugin_Mpegencoder::slotActivate()
+{
+ KIPI::Interface* interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPIMPEGEncoderPlugin::KImg2mpgData *MPEGconverterDialog =
+ new KIPIMPEGEncoderPlugin::KImg2mpgData( interface, kapp->activeWindow() );
+
+ KIPIMPEGEncoderPlugin::CheckBinProg* CheckExternalPrograms =
+ new KIPIMPEGEncoderPlugin::CheckBinProg(this);
+
+ int ValRet = CheckExternalPrograms->findExecutables();
+
+ MPEGconverterDialog->show();
+
+ if (ValRet == 0)
+ MPEGconverterDialog->m_Encodebutton->setEnabled(false);
+
+ if (ValRet == 2)
+ MPEGconverterDialog->m_AudioInputFilename->setEnabled(false);
+
+ KIPI::ImageCollection images = interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ // PENDING(blackie) extend this plugin to handle URLS rather than just strings
+ MPEGconverterDialog->addItems( images.images().toStringList());
+}
+
+KIPI::Category Plugin_Mpegencoder::category( KAction* action ) const
+{
+ if ( action == m_actionMPEGEncoder )
+ return KIPI::EXPORTPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::TOOLSPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/mpegencoder/plugin_mpegencoder.h b/kipi-plugins/mpegencoder/plugin_mpegencoder.h
new file mode 100644
index 0000000..fcd5d4f
--- /dev/null
+++ b/kipi-plugins/mpegencoder/plugin_mpegencoder.h
@@ -0,0 +1,51 @@
+/* ============================================================
+ * File : plugin_mpegencoder.h
+ * Author: Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Date : 2003-09-02
+ * Description :
+ *
+ * Copyright 2003 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_MPEGENCODER_H
+#define PLUGIN_MPEGENCODER_H
+
+// KIPI includes
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+class Plugin_Mpegencoder : public KIPI::Plugin
+{
+Q_OBJECT
+
+public:
+
+ Plugin_Mpegencoder(QObject *parent, const char* name, const QStringList &args);
+ virtual ~Plugin_Mpegencoder();
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+public slots:
+
+ void slotActivate();
+
+private:
+ KAction* m_actionMPEGEncoder;
+};
+
+
+#endif /* PLUGIN_MPEGENCODER_H */
diff --git a/kipi-plugins/picasawebexport/Makefile.am b/kipi-plugins/picasawebexport/Makefile.am
new file mode 100644
index 0000000..118921e
--- /dev/null
+++ b/kipi-plugins/picasawebexport/Makefile.am
@@ -0,0 +1,22 @@
+METASOURCES = AUTO
+
+INCLUDES = $(LIBKEXIV2_CFLAGS) $(LIBKDCRAW_CFLAGS) $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(all_includes)
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_picasawebexport.la
+
+kipiplugin_picasawebexport_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+
+kipiplugin_picasawebexport_la_SOURCES = plugin_picasawebexport.cpp \
+ picasawebwindow.cpp picasaweblogin.cpp picasawebtalker.cpp \
+ picasawebwidget.cpp mpform.cpp picasawebviewitem.cpp \
+ PicasawebNewAlbumDialog.ui uploadwidget.ui
+
+kipiplugin_picasawebexport_la_LIBADD = $(LIBKEXIV2_LIBS) $(LIBKDCRAW_LIBS) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_picasawebexport_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+kde_services_DATA = kipiplugin_picasawebexport.desktop
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_picasawebexport.pot
diff --git a/kipi-plugins/picasawebexport/PicasawebNewAlbumDialog.ui b/kipi-plugins/picasawebexport/PicasawebNewAlbumDialog.ui
new file mode 100644
index 0000000..6de4039
--- /dev/null
+++ b/kipi-plugins/picasawebexport/PicasawebNewAlbumDialog.ui
@@ -0,0 +1,237 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KIPIPicasawebExportPlugin::NewAlbumDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>NewAlbumDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>504</width>
+ <height>339</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>New Album Dialog</string>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>20</y>
+ <width>111</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Title</string>
+ </property>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>m_accessRadioButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>160</x>
+ <y>220</y>
+ <width>300</width>
+ <height>71</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>Access Level</string>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_isUnlistedRadioButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>40</y>
+ <width>111</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Unlisted </string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_isPublicRadioButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>141</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Public</string>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_cancelButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>400</x>
+ <y>300</y>
+ <width>71</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>50</y>
+ <width>71</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Date</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>90</y>
+ <width>91</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Description</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>200</y>
+ <width>121</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Place Taken</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_titleLineEdit</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>160</x>
+ <y>20</y>
+ <width>251</width>
+ <height>21</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_locationLineEdit</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>160</x>
+ <y>200</y>
+ <width>291</width>
+ <height>21</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QDateTimeEdit">
+ <property name="name">
+ <cstring>m_dateAndTimeEdit</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>160</x>
+ <y>50</y>
+ <width>261</width>
+ <height>22</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QTextEdit">
+ <property name="name">
+ <cstring>m_descriptionTextBox</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>160</x>
+ <y>90</y>
+ <width>301</width>
+ <height>91</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_createAlbumButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>290</x>
+ <y>300</y>
+ <width>101</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Create</string>
+ </property>
+ </widget>
+</widget>
+<connections>
+ <connection>
+ <sender>m_createAlbumButton</sender>
+ <signal>clicked()</signal>
+ <receiver>NewAlbumDialog</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>m_cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>NewAlbumDialog</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">PicasawebNewAlbumDialog.ui.h</include>
+</includes>
+<slots>
+ <slot access="protected" specifier="non virtual">creatAlbumSlot()</slot>
+ <slot access="protected" specifier="non virtual">cancelWindowSlot()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kipi-plugins/picasawebexport/kipiplugin_picasawebexport.desktop b/kipi-plugins/picasawebexport/kipiplugin_picasawebexport.desktop
new file mode 100644
index 0000000..2afaa31
--- /dev/null
+++ b/kipi-plugins/picasawebexport/kipiplugin_picasawebexport.desktop
@@ -0,0 +1,42 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Picasaweb Exporter
+Name[ca]=Exportador a Picasaweb
+Name[de]=Picasaweb-Export
+Name[es]=Exportador para Picasaweb
+Name[et]=Picasaweb eksport
+Name[fi]=Picasa-vienti
+Name[is]=Picasa Útflutningur
+Name[it]=Esportazione a Picasa Web
+Name[nds]=Picasaweb-Exporteren
+Name[pl]=Eksporter PicasaWeb
+Name[pt]=Exportação para o Picasaweb
+Name[sr]=Picasaweb извозник
+Name[sr@Latn]=Picasaweb izvoznik
+Name[sv]=Export till Picasa webbalbum
+Name[xx]=xxPicasaweb Exporterxx
+Name[zh_CN]=Picasaweb 导出器
+Comment=KIPI Remote Picasaweb Export Plugin
+Comment[ca]=Connector del KIPI d'exportació remota a Picasaweb
+Comment[de]=Ein KIPI-Modul zum Exportieren von Bildern zu Picasaweb
+Comment[es]=Complemento de KIPI para exportación remota a Picasaweb
+Comment[et]=KIPI Picasawebi ekspordiplugin
+Comment[fi]=Kipi-liitännäinen Picasa-vientiä varten
+Comment[fr]=Module externe KIPI pour exporter des images vers le site Picasaweb
+Comment[is]=KIPI íforrit til útflutnings á fjarlæga Picasa vefþjóna
+Comment[it]=Plugin per l'esportazione remota a Picasa Web di KIPI
+Comment[ja]=Kipi リモート Picasaweb エクスポートプラグイン
+Comment[nds]=KIPI-Moduul för't Exporteren na Picasaweb
+Comment[nl]=KIPI-plugin voor het exporteren naar Picasaweb
+Comment[pl]=Wtyczka KIPI - Eksport do usługi sieciowej PicasaWeb
+Comment[pt]='Plugin' do KIPI de Exportação para o Picasaweb Remoto
+Comment[pt_BR]=Plugin de Exportação Remota para o Picasaweb do KIPI
+Comment[sr]=KIPI прикључак за извоз у удаљени Picasaweb
+Comment[sr@Latn]=KIPI priključak za izvoz u udaljeni Picasaweb
+Comment[sv]=KIPI-insticksprogram för fjärrexport till Picasa webbalbum
+Comment[xx]=xxKIPI Remote Picasaweb Export Pluginxx
+Comment[zh_CN]=KIPI 远程 Picasaweb 导出插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_picasawebexport
+author=Vardhman Jain, vardhman@gmail.com
diff --git a/kipi-plugins/picasawebexport/mpform.cpp b/kipi-plugins/picasawebexport/mpform.cpp
new file mode 100644
index 0000000..4730bec
--- /dev/null
+++ b/kipi-plugins/picasawebexport/mpform.cpp
@@ -0,0 +1,181 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Caulier Gilles <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstring>
+#include <cstdio>
+
+// Qt includes.
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+
+// KDE includes.
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kurl.h>
+
+// Local includes.
+
+#include "mpform.h"
+
+namespace KIPIPicasawebExportPlugin
+{
+
+MPForm::MPForm()
+{
+ m_boundary = "----------";
+ m_boundary += KApplication::randomString(42 + 13).ascii();
+}
+
+MPForm::~MPForm()
+{
+}
+
+void MPForm::reset()
+{
+ m_buffer.resize(0);
+}
+
+void MPForm::finish()
+{
+ QCString str;
+ str += "--";
+ str += m_boundary;
+ str += "--";
+
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << str;
+}
+
+bool MPForm::addPair(const QString& name, const QString& value, const QString& contentType)
+{
+ QCString str;
+ QString content_length = QString("%1").arg(value.length());
+ str += "--";
+ str += m_boundary;
+ str += "\r\n";
+
+ if (!name.isEmpty())
+ {
+ str += "Content-Disposition: form-data; name=\"";
+ str += name.ascii();
+ str += "\"\r\n";
+ }
+
+ if (!contentType.isEmpty())
+ {
+ str += "Content-Type: "+ QCString(contentType.ascii());
+ str += "\r\n";
+ str += "Mime-version: 1.0 ";
+ str += "\r\n";
+ }
+
+ str += "Content-Length: " ;
+ str += content_length.ascii();
+ str += "\r\n\r\n";
+ str += value.utf8();
+ str += "\r\n";
+
+ //uint oldSize = m_buffer.size();
+ //m_buffer.resize(oldSize + str.size());
+ //memcpy(m_buffer.data() + oldSize, str.data(), str.size());
+
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << QString::fromUtf8(str);
+
+ return true;
+}
+
+bool MPForm::addFile(const QString& name,const QString& path)
+{
+ KMimeType::Ptr ptr = KMimeType::findByURL(path);
+ QString mime = ptr->name();
+ if (mime.isEmpty())
+ {
+ // if we ourselves can't determine the mime of the local file,
+ // very unlikely the remote site will be able to identify it
+ return false;
+ }
+
+ QFile imageFile(path);
+ if (!imageFile.open(IO_ReadOnly))
+ return false;
+
+ QByteArray imageData = imageFile.readAll();
+
+ QCString str;
+ QString file_size = QString("%1").arg(imageFile.size());
+
+ str += "--";
+ str += m_boundary;
+ str += "\r\n";
+ str += "Content-Disposition: form-data; name=\"";
+ str += name.ascii();
+ str += "\"; ";
+ str += "filename=\"";
+ str += QFile::encodeName(KURL(path).filename());
+ str += "\"\r\n";
+ str += "Content-Length: " ;
+ str += file_size.ascii();
+ str += "\r\n";
+ str += "Content-Type: ";
+ str += mime.ascii();
+ str += "\r\n\r\n";
+
+ imageFile.close();
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << str;
+
+ int oldSize = m_buffer.size();
+ m_buffer.resize(oldSize + imageData.size() + 2);
+ memcpy(m_buffer.data() + oldSize, imageData.data(), imageData.size());
+ m_buffer[m_buffer.size()-2] = '\r';
+ m_buffer[m_buffer.size()-1] = '\n';
+
+ return true;
+}
+
+QString MPForm::contentType() const
+{
+ return QString("Content-Type: multipart/related; boundary=" + m_boundary);
+}
+
+QString MPForm::boundary() const
+{
+ return m_boundary;
+}
+
+QByteArray MPForm::formData() const
+{
+ return m_buffer;
+}
+
+} // namespace KIPIPicasawebExportPlugin
diff --git a/kipi-plugins/picasawebexport/mpform.h b/kipi-plugins/picasawebexport/mpform.h
new file mode 100644
index 0000000..edfa558
--- /dev/null
+++ b/kipi-plugins/picasawebexport/mpform.h
@@ -0,0 +1,61 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-07-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Caulier Gilles <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 MPFORM_H
+#define MPFORM_H
+
+// Qt includes
+
+#include <qcstring.h>
+#include <qstring.h>
+
+namespace KIPIPicasawebExportPlugin
+{
+
+class MPForm
+{
+
+public:
+
+ MPForm();
+ ~MPForm();
+
+ void finish();
+ void reset();
+
+ bool addPair(const QString& name, const QString& value, const QString& contentType=QString());
+ bool addFile(const QString& name, const QString& path);
+
+ QString contentType() const;
+ QByteArray formData() const;
+ QString boundary() const;
+
+private:
+
+ QByteArray m_buffer;
+ QCString m_boundary;
+};
+
+} // namespace KIPIPicasawebExportPlugin
+
+#endif /* MPFORM_H */
diff --git a/kipi-plugins/picasawebexport/picasawebitem.h b/kipi-plugins/picasawebexport/picasawebitem.h
new file mode 100644
index 0000000..2984053
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasawebitem.h
@@ -0,0 +1,135 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-16-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PICASAWEBITEM_H
+#define PICASAWEBITEM_H
+
+// Qt includes.
+
+#include <qstring.h>
+
+namespace KIPIPicasawebExportPlugin
+{
+
+class GPhoto
+{
+
+public:
+
+ GPhoto()
+ {
+ //ref_num = -1;
+ }
+
+ bool is_public;
+ bool is_private;
+ bool is_family;
+
+ int ref_num;
+
+ QStrList tags;
+ QString title;
+ QString description;
+};
+
+// ------------------------------------------------------
+
+class FPhotoInfo
+{
+
+public:
+
+ FPhotoInfo()
+ {
+ is_public = false;
+ is_family = false;
+ is_friend = false;
+ }
+
+ bool is_public;
+ bool is_friend;
+ bool is_family;
+
+ QString title;
+ QString description;
+ QStringList tags;
+};
+
+// ------------------------------------------------------
+
+class GAlbum
+{
+
+public:
+
+ GAlbum()
+ {
+ ref_num = -1;
+ parent_ref_num = -1;
+
+ add = false;
+ write = false;
+ del_item = false;
+ del_alb = false;
+ create_sub = false;
+ }
+
+ int ref_num;
+ int parent_ref_num;
+
+ bool add;
+ bool write;
+ bool del_item;
+ bool del_alb;
+ bool create_sub;
+
+ QString name;
+ QString parentName;
+ QString title;
+ QString summary;
+ QString baseurl;
+};
+
+// ------------------------------------------------------
+
+class PicasaWebAlbum
+{
+
+public:
+
+ PicasaWebAlbum()
+ {
+ id="-1";
+ }
+
+ QString id;
+ QString primary; //="2483"
+ QString secret; //="abcdef"
+ QString server;
+ QString photos;
+ QString title;
+ QString description;
+};
+
+} // namespace KIPIPicasawebExportPlugin
+
+#endif /* PICASAWEBITEM_H */
diff --git a/kipi-plugins/picasawebexport/picasaweblogin.cpp b/kipi-plugins/picasawebexport/picasaweblogin.cpp
new file mode 100644
index 0000000..cb65ec6
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasaweblogin.cpp
@@ -0,0 +1,145 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-16-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qlabel.h>
+#include <qframe.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+
+// KDE includes.
+
+#include <kdebug.h>
+#include <klocale.h>
+
+// Local includes.
+
+#include "picasaweblogin.h"
+#include "picasaweblogin.moc"
+
+namespace KIPIPicasawebExportPlugin
+{
+
+PicasawebLogin::PicasawebLogin(QWidget* parent, const QString& header,
+ const QString& _name, const QString& _passwd)
+ : QDialog(parent)
+{
+ setSizeGripEnabled(false);
+
+ QVBoxLayout* vbox = new QVBoxLayout( this, 5, 5, "vbox");
+
+ m_headerLabel = new QLabel(this);
+ m_headerLabel->setSizePolicy(QSizePolicy(QSizePolicy::Minimum,
+ QSizePolicy::Fixed));
+ m_headerLabel->setText(header);
+ vbox->addWidget( m_headerLabel );
+
+ QFrame* hline = new QFrame( this, "hline" );
+ hline->setFrameShape( QFrame::HLine );
+ hline->setFrameShadow( QFrame::Sunken );
+ hline->setFrameShape( QFrame::HLine );
+ vbox->addWidget( hline );
+
+ QGridLayout* centerLayout = new QGridLayout(0, 1, 1, 5, 5);
+
+ m_nameEdit = new QLineEdit( this );
+ centerLayout->addWidget(m_nameEdit, 0, 1);
+
+ m_passwdEdit = new QLineEdit( this );
+ m_passwdEdit->setEchoMode(QLineEdit::Password);
+ centerLayout->addWidget(m_passwdEdit, 1, 1);
+
+ QLabel* nameLabel = new QLabel(this);
+ nameLabel->setText(i18n( "Username:" ));
+ centerLayout->addWidget(nameLabel, 0, 0);
+
+ QLabel* passwdLabel = new QLabel(this);
+ passwdLabel->setText(i18n( "Password:" ));
+ centerLayout->addWidget(passwdLabel, 1, 0);
+
+ vbox->addLayout( centerLayout );
+
+ QHBoxLayout* btnLayout = new QHBoxLayout(0, 0, 5);
+ btnLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding,
+ QSizePolicy::Minimum ) );
+
+ QPushButton *okBtn = new QPushButton( this );
+ okBtn->setAutoDefault( true );
+ okBtn->setDefault( true );
+ okBtn->setText( i18n( "&OK" ) );
+ btnLayout->addWidget( okBtn );
+
+ QPushButton *cancelBtn = new QPushButton( this );
+ cancelBtn->setText( i18n( "&Cancel" ) );
+ btnLayout->addWidget( cancelBtn );
+
+ vbox->addLayout( btnLayout );
+
+ resize( QSize(300, 150).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+
+ m_nameEdit->setText(_name);
+ m_passwdEdit->setText(_passwd);
+
+ // signals and slots connections
+
+ connect(okBtn, SIGNAL(clicked()),
+ this, SLOT(accept()));
+
+ connect(cancelBtn, SIGNAL(clicked()),
+ this, SLOT(reject()));
+}
+
+PicasawebLogin::~PicasawebLogin()
+{
+}
+
+QString PicasawebLogin::name() const
+{
+ return m_nameEdit->text();
+}
+
+QString PicasawebLogin::password() const
+{
+ return m_passwdEdit->text();
+}
+
+QString PicasawebLogin::username() const
+{
+ return m_nameEdit->text();
+}
+
+void PicasawebLogin::setUsername(const QString& username)
+{
+ kdDebug()<<" The username passed to me is "<<username <<endl;
+ m_nameEdit->setText(username);
+ kdDebug()<<" The username passed to me is "<<username <<endl;
+}
+
+void PicasawebLogin::setPassword(const QString& password)
+{
+ m_passwdEdit->setText(password);
+}
+
+} // namespace KIPIPicasawebExportPlugin
diff --git a/kipi-plugins/picasawebexport/picasaweblogin.h b/kipi-plugins/picasawebexport/picasaweblogin.h
new file mode 100644
index 0000000..f689773
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasaweblogin.h
@@ -0,0 +1,61 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-16-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PICASAWEBLOGIN_H
+#define PICASAWEBLOGIN_H
+
+// Qt includes.
+
+#include <qdialog.h>
+
+class QLabel;
+class QLineEdit;
+
+namespace KIPIPicasawebExportPlugin
+{
+
+class PicasawebLogin : public QDialog
+{
+ Q_OBJECT
+
+public:
+
+ PicasawebLogin(QWidget* parent, const QString& header, const QString& _name=QString(),
+ const QString& _passwd=QString());
+ ~PicasawebLogin();
+
+ QString name() const;
+ QString password() const;
+ QString username() const;
+ void setUsername(const QString&);
+ void setPassword(const QString&);
+
+private:
+
+ QLabel* m_headerLabel;
+ QLineEdit* m_nameEdit;
+ QLineEdit* m_passwdEdit;
+};
+
+} // namespace KIPIPicasawebExportPlugin
+
+#endif // PICASAWEBLOGIN_H
diff --git a/kipi-plugins/picasawebexport/picasawebtalker.cpp b/kipi-plugins/picasawebexport/picasawebtalker.cpp
new file mode 100644
index 0000000..693b81e
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasawebtalker.cpp
@@ -0,0 +1,959 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-16-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstring>
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+// Qt includes.
+
+#include <qcstring.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qimage.h>
+#include <qstringlist.h>
+#include <qurl.h>
+#include <qlineedit.h>
+#include <qmessagebox.h>
+#include <qdom.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kio/job.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kstandarddirs.h>
+#include <kmdcodec.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kio/jobclasses.h>
+#include <kurl.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "mpform.h"
+#include "picasawebitem.h"
+#include "picasawebtalker.h"
+#include "picasawebwindow.h"
+#include "picasaweblogin.h"
+#include "picasawebtalker.moc"
+
+class PicasawebLogin;
+
+namespace KIPIPicasawebExportPlugin
+{
+
+PicasawebTalker::PicasawebTalker( QWidget* parent )
+ : m_parent( parent ), m_job( 0 )
+ {
+ m_apikey="49d585bafa0758cb5c58ab67198bf632";
+ m_secret="34b39925e6273ffd";
+
+ connect(this, SIGNAL(signalError(const QString&)),
+ this, SLOT(slotError(const QString&)));
+
+ authProgressDlg=new QProgressDialog();
+ }
+
+PicasawebTalker::~PicasawebTalker()
+{
+ if (m_job)
+ m_job->kill();
+}
+
+QString PicasawebTalker::getApiSig(QString secret, QStringList headers)
+{
+ QStringList compressed ;//= new List<string>(headers.Length);
+
+ for ( QStringList::Iterator it = headers.begin(); it != headers.end(); ++it ) {
+ QStringList str=QStringList::split("=",(*it));
+ compressed.append(str[0].stripWhiteSpace()+str[1].stripWhiteSpace());
+ }
+
+ compressed.sort();
+ QString merged=compressed.join("");
+ QString final = secret + merged;
+ const char *test=final.ascii();
+ KMD5 context (test);
+ //kdDebug()<< "Test Hex Digest output: " << context.hexDigest().data() << endl;
+ return context.hexDigest().data();
+}
+
+void PicasawebTalker::getToken(const QString& username, const QString& password )
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ QString url = "https://www.google.com/accounts/ClientLogin";
+
+ PicasawebLogin *loginDialog = new PicasawebLogin(kapp->activeWindow(), QString("LoginWindow"), username, password);
+ /*if (username!=NULL && username.length() > 0){
+ // kdDebug()<<"Showing stored username"<< username << endl;
+ loginDialog->setUsername(username);
+ if (password != NULL && password.length() > 0){
+ // kdDebug()<<"Showing stored password"<< password << endl;
+ loginDialog->setPassword(password);
+ // kdDebug()<<"Showing stored password"<< password << endl;
+ }
+ }
+ */
+
+ QString username_edit, password_edit;
+
+ if (!loginDialog)
+ {
+ kdDebug()<<" Out of memory error "<< endl;
+ }
+
+ if (loginDialog->exec() == QDialog::Accepted)
+ {
+ username_edit = loginDialog->username();
+ password_edit = loginDialog->password();
+ }
+ else
+ {
+ //Return something which say authentication needed.
+ return ;
+ }
+
+ m_username = username_edit;
+ username_edit = username;
+ QString accountType = "GOOGLE";
+
+ if (!(username_edit.endsWith("@gmail.com")))
+ username_edit += "@gmail.com";
+
+ QByteArray buffer;
+ QStringList qsl;
+ qsl.append("Email="+username_edit);
+ qsl.append("Passwd="+password_edit);
+ qsl.append("accountType="+accountType);
+ qsl.append("service=lh2");
+ qsl.append("source=kipi-picasaweb-client");
+ QString dataParameters = qsl.join("&");
+
+ QTextStream ts(buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << dataParameters;
+
+ KIO::TransferJob* job = KIO::http_post(url, buffer, false);
+ job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
+ m_state = FE_GETTOKEN;
+ authProgressDlg->setLabelText(i18n("Getting the token"));
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+}
+
+void PicasawebTalker::authenticate(const QString& token, const QString& username, const QString& password)
+{
+ if (!token || token.length() < 1)
+ {
+ checkToken(token);
+ m_username = username;
+ m_password = password; //this would be needed if the checktoken failed
+ //we would need to reauthenticate using auth
+ }
+ else
+ {
+ getToken(username, password);
+ }
+}
+
+void PicasawebTalker::checkToken(const QString& /*token*/)
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ QString url = "https://www.google.com/accounts/ClientLogin";
+ QString auth_string = "GoogleLogin auth=" + m_token;
+ QByteArray tmp;
+ KIO::TransferJob* job = KIO::http_post(url, tmp, false);
+ job->addMetaData("customHTTPHeader", "Authorization: " + auth_string);
+
+ job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded");
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_CHECKTOKEN;
+ authProgressDlg->setLabelText(i18n("Checking if previous token is still valid"));
+ authProgressDlg->setProgress(1,4);
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+}
+
+/** PicasaWeb's Album listing request/response
+ * First a request is sent to the url below and then we might(?) get a redirect URL
+ * WE then need to send the GET request to the Redirect url (this however gets taken care off by the
+ * KIO libraries.
+ * This uses the authenticated album list fetching to get all the albums included the unlisted-albums
+ * which is not returned for an unauthorised request as done without the Authorization header.
+*/
+void PicasawebTalker::listAllAlbums() {
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ QString url = "http://picasaweb.google.com/data/feed/api/user/" + m_username + "?kind=album";
+ QByteArray tmp;
+ QString auth_string = "GoogleLogin auth=" + m_token;
+ KIO::TransferJob* job = KIO::get(url, tmp, false);
+ job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
+ job->addMetaData("customHTTPHeader", "Authorization: " + auth_string );
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_LISTALBUMS;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+
+}
+
+void PicasawebTalker::getPhotoProperty(const QString& method,const QString& argList)
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ QString url="http://www.picasaweb.com/services/rest/?";
+ QStringList headers;
+ headers.append("api_key="+ m_apikey);
+ headers.append("method="+method);
+ headers.append("frob="+ m_frob);
+ headers.append(argList);
+ QString md5=getApiSig(m_secret,headers);
+ headers.append("api_sig="+ md5);
+ QString queryStr=headers.join("&");
+ QString postUrl=url+queryStr;
+ QByteArray tmp;
+ KIO::TransferJob* job = KIO::http_post(postUrl, tmp, false);
+ job->addMetaData("content-type", "Content-Type: application/x-www-form-urlencoded" );
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_GETPHOTOPROPERTY;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy( true );
+ //authProgressDlg->setLabelText("Getting the Token from the server");
+ //authProgressDlg->setProgress(3,4);
+}
+
+void PicasawebTalker::addPhotoTag(const QString& photoURI, const QString& tag)
+{
+ //if (m_job && m_state != FE_ADDTAG){ //we shouldn't kill the old tag request
+ // m_job->kill();
+ // m_job = 0;
+ //}
+
+ QString addTagXML = QString("<entry xmlns='http://www.w3.org/2005/Atom'> "
+ "<title>%1</title> "
+ "<category scheme='http://schemas.google.com/g/2005#kind' "
+ "term='http://schemas.google.com/photos/2007#tag'/> "
+ "</entry>").arg(tag);
+ QString postUrl = QString("%1").arg(photoURI);
+ QByteArray buffer;
+ QTextStream ts(buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << addTagXML;
+
+ QString auth_string = "GoogleLogin auth=" + m_token;
+ KIO::TransferJob* job = KIO::http_post(postUrl, buffer, false);
+ job->addMetaData("content-type", "Content-Type: application/atom+xml");
+ job->addMetaData("content-length", QString("Content-Length: %1").arg(addTagXML.length()));
+ job->addMetaData("customHTTPHeader", "Authorization: " + auth_string );
+
+ //connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ // this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_ADDTAG;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy(true);
+}
+
+void PicasawebTalker::listPhotos(const QString& /*albumName*/)
+{
+ // TODO
+}
+
+void PicasawebTalker::createAlbum(const QString& albumTitle, const QString& albumDesc,
+ const QString& location, uint timestamp, const QString& access,
+ const QString& media_keywords, bool isCommentsEnabled)
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ QString newAlbumXML = QString("<entry xmlns='http://www.w3.org/2005/Atom' "
+ "xmlns:media='http://search.yahoo.com/mrss/' "
+ "xmlns:gphoto='http://schemas.google.com/photos/2007'> "
+ "<title type='text'>%1</title> "
+ "<summary type='text'>%2</summary> "
+ "<gphoto:location>%3</gphoto:location> "
+ "<gphoto:access>%4</gphoto:access> "
+ "<gphoto:commentingEnabled>%5</gphoto:commentingEnabled> "
+ "<gphoto:timestamp>%6</gphoto:timestamp> "
+ "<media:group> "
+ "<media:keywords>%7</media:keywords> "
+ "</media:group> "
+ "<category scheme='http://schemas.google.com/g/2005#kind' "
+ "term='http://schemas.google.com/photos/2007#album'></category> "
+ "</entry> ").arg(albumTitle)
+ .arg(albumDesc)
+ .arg(location)
+ .arg(access)
+ .arg(isCommentsEnabled==true?"true":"false")
+ .arg(timestamp)
+ .arg(media_keywords);
+
+ QByteArray buffer;
+ QTextStream ts(buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << newAlbumXML;
+
+ MPForm form;
+ QString postUrl = "http://www.picasaweb.google.com/data/feed/api/user/" + m_username ;
+ QString auth_string = "GoogleLogin auth=" + m_token;
+ KIO::TransferJob* job = KIO::http_post(postUrl, buffer, false);
+ job->addMetaData("content-type", "Content-Type: application/atom+xml");
+ job->addMetaData("content-length", QString("Content-Length: %1").arg(newAlbumXML.length()));
+ job->addMetaData("customHTTPHeader", "Authorization: " + auth_string );
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_CREATEALBUM;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy(true);
+}
+
+bool PicasawebTalker::addPhoto(const QString& photoPath, FPhotoInfo& info,
+ const QString& albumId, bool rescale,
+ int maxDim, int imageQuality)
+{
+ // Disabling this totally may be checking the m_state and doing selecting
+ // disabling is a better idea
+ /*if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }*/
+
+ QString album_id = albumId;
+
+ if (album_id.length() == 0)
+ album_id = "test";
+
+ QString postUrl = "http://www.picasaweb.google.com/data/feed/api/user/" + KURL::encode_string(m_username) + "/albumid/" + album_id;
+ QString path = postUrl;
+ QStringList headers;
+ MPForm form;
+ QString auth_string = "GoogleLogin auth=" + m_token;
+
+ //form.addPair("Authorization", auth_string);
+
+ //Create the Body in atom-xml
+ QStringList body_xml;
+ body_xml.append("<entry xmlns=\'http://www.w3.org/2005/Atom\'>");
+ body_xml.append("<title>"+ info.title +"</title>");
+ body_xml.append("<summary>"+ info.description +"</summary>");
+ body_xml.append("<category scheme=\"http://schemas.google.com/g/2005#kind\" "
+ "term=\"http://schemas.google.com/photos/2007#photo\" />");
+ body_xml.append("</entry>");
+
+ QString body = body_xml.join("");
+
+ form.addPair("test", body, "application/atom+xml");
+
+ // save the tags for this photo in to the tags hashmap
+ tags_map.insert(info.title, info.tags);
+ QImage image;
+
+ // Check if RAW file.
+#if KDCRAW_VERSION < 0x000106
+ QString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles());
+#else
+ QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
+#endif
+ QFileInfo fileInfo(photoPath);
+ if (rawFilesExt.upper().contains(fileInfo.extension(false).upper()))
+ KDcrawIface::KDcraw::loadDcrawPreview(image, photoPath);
+ else
+ image.load(photoPath);
+
+ if (!image.isNull())
+ {
+ path = locateLocal("tmp", QFileInfo(photoPath).baseName().stripWhiteSpace() + ".jpg");
+
+ if (rescale && (image.width() > maxDim || image.height() > maxDim))
+ image = image.smoothScale(maxDim, maxDim, QImage::ScaleMin);
+
+ image.save(path, "JPEG", imageQuality);
+
+ // Restore all metadata.
+
+ KExiv2Iface::KExiv2 exiv2Iface;
+
+ if (exiv2Iface.load(photoPath))
+ {
+ exiv2Iface.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+ exiv2Iface.setImageDimensions(image.size());
+ exiv2Iface.save(path);
+ }
+ else
+ {
+ kdWarning(51000) << "(picasawebExport::Image doesn't have exif data)" << endl;
+ }
+
+ kdDebug() << "Resizing and saving to temp file: " << path << endl;
+ }
+
+ if (!form.addFile("photo", path))
+ return false;
+
+ form.finish();
+
+ KIO::TransferJob* job = KIO::http_post(postUrl, form.formData(), false);
+ job->addMetaData("content-type", form.contentType());
+ job->addMetaData("customHTTPHeader", "Authorization: " + auth_string );
+
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ this, SLOT(data(KIO::Job*, const QByteArray&)));
+
+ connect(job, SIGNAL(result(KIO::Job *)),
+ this, SLOT(slotResult(KIO::Job *)));
+
+ m_state = FE_ADDPHOTO;
+ m_job = job;
+ m_buffer.resize(0);
+ emit signalBusy(true);
+ return true;
+}
+
+QString PicasawebTalker::getUserName()
+{
+ return m_username;
+}
+
+QString PicasawebTalker::getUserId()
+{
+ return m_userId;
+}
+
+void PicasawebTalker::cancel()
+{
+ if (m_job)
+ {
+ m_job->kill();
+ m_job = 0;
+ }
+
+ if (authProgressDlg && !authProgressDlg->isHidden())
+ authProgressDlg->hide();
+}
+
+void PicasawebTalker::info(KIO::Job* /*job*/, const QString& /*str*/)
+{
+}
+
+void PicasawebTalker::data(KIO::Job*, const QByteArray& data)
+{
+ if (data.isEmpty())
+ return;
+
+ int oldSize = m_buffer.size();
+ m_buffer.resize(m_buffer.size() + data.size());
+ QString output_data = QString(data);
+ memcpy(m_buffer.data()+oldSize, data.data(), data.size());
+}
+
+void PicasawebTalker::slotError(const QString & error)
+{
+ QString transError;
+ int errorNo = 0;
+
+ if (!error.isEmpty())
+ errorNo = atoi(error.latin1());
+
+ switch (errorNo)
+ {
+ case 2:
+ transError=i18n("No photo specified");break;
+ case 3:
+ transError=i18n("General upload failure");break;
+ case 4:
+ transError=i18n("Filesize was zero");break;
+ case 5:
+ transError=i18n("Filetype was not recognised");break;
+ case 6:
+ transError=i18n("User exceeded upload limit");break;
+ case 96:
+ transError=i18n("Invalid signature"); break;
+ case 97:
+ transError=i18n("Missing signature"); break;
+ case 98:
+ transError=i18n("Login Failed / Invalid auth token"); break;
+ case 100:
+ transError=i18n("Invalid API Key"); break;
+ case 105:
+ transError=i18n("Service currently unavailable");break;
+ case 108:
+ transError=i18n("Invalid Frob");break;
+ case 111:
+ transError=i18n("Format \"xxx\" not found"); break;
+ case 112:
+ transError=i18n("Method \"xxx\" not found"); break;
+ case 114:
+ transError=i18n("Invalid SOAP envelope");break;
+ case 115:
+ transError=i18n("Invalid XML-RPC Method Call");break;
+ case 116:
+ transError=i18n("The POST method is now required for all setters"); break;
+ default:
+ transError=i18n("Unknown error");
+ };
+
+ KMessageBox::error(kapp->activeWindow(), i18n("Error Occured: %1\n We can not proceed further").arg(transError));
+ //kdDebug()<<"Not handling the error now will see it later"<<endl;
+}
+
+void PicasawebTalker::slotResult(KIO::Job *job)
+{
+ m_job = 0;
+ emit signalBusy(false);
+
+ if (job->error())
+ {
+ if (m_state == FE_ADDPHOTO)
+ {
+ emit signalAddPhotoFailed(job->errorString());
+ }
+ else
+ {
+ job->showErrorDialog(m_parent);
+ }
+
+ return;
+ }
+
+ switch(m_state)
+ {
+ case(FE_LOGIN):
+ //parseResponseLogin(m_buffer);
+ break;
+ case(FE_CREATEALBUM):
+ parseResponseCreateAlbum(m_buffer);
+ break;
+ case(FE_LISTALBUMS):
+ parseResponseListAlbums(m_buffer);
+ break;
+ case(FE_GETFROB):
+ break;
+ case(FE_GETTOKEN):
+ parseResponseGetToken(m_buffer);
+ break;
+ case(FE_CHECKTOKEN):
+ parseResponseCheckToken(m_buffer);
+ break;
+ case(FE_GETAUTHORIZED):
+ break;
+ case(FE_LISTPHOTOS):
+ parseResponseListPhotos(m_buffer);
+ break;
+ case(FE_GETPHOTOPROPERTY):
+ parseResponsePhotoProperty(m_buffer);
+ break;
+ case(FE_ADDPHOTO):
+ parseResponseAddPhoto(m_buffer);
+ break;
+ case(FE_ADDTAG):
+ parseResponseAddTag(m_buffer);
+ break;
+ }
+}
+
+void PicasawebTalker::parseResponseCheckToken(const QByteArray &data)
+{
+ bool success = false;
+ QString errorString;
+ QString username;
+ QString transReturn(data);
+ // If checktoken failed.
+ // getToken ...
+
+ if(transReturn.startsWith("Error="))
+ success = false;
+ else
+ success = true;
+
+ if(!success)
+ getToken(m_username, m_password);
+ //emit signalError(errorString);
+}
+
+void PicasawebTalker::parseResponseGetToken(const QByteArray &data)
+{
+ bool success = false;
+ QString errorString;
+ QString str(data);
+ //Check the response code should it be 200, proceed
+ //if it is 403 handle the error mesg
+ //figure out the auth string from this response
+
+ if (str.find("Auth="))
+ {
+ QStringList strList = QStringList::split("Auth=", str);
+ m_token = strList[1];
+ success = 1;
+ }
+
+ if(success)
+ {
+ authProgressDlg->hide();
+ emit signalTokenObtained(m_token);
+ }
+ else
+ {
+ emit signalError(errorString);
+ }
+
+ emit signalBusy(false);
+}
+
+void PicasawebTalker::getHTMLResponseCode(const QString& /*str*/)
+{
+}
+
+void PicasawebTalker::parseResponseListAlbums(const QByteArray &data)
+{
+ bool success = false;
+ QString str(data);
+ QDomDocument doc( "feed" );
+ if ( !doc.setContent( data ) )
+ {
+ return;
+ }
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+ QDomElement e;
+ QString feed_id, feed_updated, feed_title, feed_subtitle;
+ QString feed_icon_url, feed_link_url;
+ QString feed_username, feed_user_uri;
+
+ QString album_id, album_title, album_description;
+ m_albumsList = new QValueList <PicasaWebAlbum>();
+
+ while(!node.isNull())
+ {
+ if (node.isElement() && node.nodeName() == "entry")
+ {
+ success = true;
+ e = node.toElement();
+ QDomNode details=e.firstChild();
+ PicasaWebAlbum fps;
+ QDomNode detailsNode = details;
+
+ while(!detailsNode.isNull())
+ {
+ if(detailsNode.isElement())
+ {
+ if(detailsNode.nodeName() == "id")
+ {
+ // The node data is a URL of which album id is the string following the last /
+ // like <id>http://www.picasaweb.google.com/.../AlbumID<id>
+ QString albumIdUrl = detailsNode.toElement().text();
+ int index = albumIdUrl.findRev("/");
+ int length = albumIdUrl.length();
+ QString album_id = albumIdUrl.right(length - index - 1);
+ fps.id = album_id;
+ }
+
+ if(detailsNode.nodeName() == "title")
+ {
+ album_title = "Not fetched";
+
+ if(detailsNode.toElement().attribute("type")=="text")
+ album_title = detailsNode.toElement().text();
+
+ //this is what is obtained from data.
+ fps.title = album_title;
+ }
+
+ if(detailsNode.nodeName()=="gphoto:name")
+ {
+ QString name = detailsNode.toElement().text();
+ }
+ }
+
+ detailsNode = detailsNode.nextSibling();
+ }
+
+ m_albumsList->append(fps);
+ }
+
+ node = node.nextSibling();
+ }
+
+ if (!success)
+ {
+ emit signalGetAlbumsListFailed(i18n("Failed to fetch photoSets List"));
+ m_albumsList = NULL;
+ }
+ else
+ {
+ emit signalGetAlbumsListSucceeded();
+ }
+}
+
+void PicasawebTalker::parseResponseListPhotos(const QByteArray &data)
+{
+ QDomDocument doc( "getPhotosList" );
+ if ( !doc.setContent( data ) )
+ {
+ return;
+ }
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+ //QDomElement e;
+ // TODO
+}
+
+void PicasawebTalker::parseResponseCreateAlbum(const QByteArray &data)
+{
+ bool success = false;
+ QString errorString;
+ QString response(data);
+ QDomDocument doc( "AddPhoto Response" );
+ // parse the new album name
+ QDomElement docElem = doc.documentElement();
+ QString title, photo_id, album_id, photoURI;
+ QDomNode node = docElem.firstChild(); //this should mean <entry>
+ QDomElement e;
+
+ while( !node.isNull() )
+ {
+ if ( node.isElement())
+ {
+ QString node_name = node.nodeName();
+ QString node_value = node.toElement().text();
+ if(node_name == "title")
+ {
+ success = true;
+ title = node_value;
+ }
+ else if (node_name == "id")
+ photoURI = node_value;
+ else if(node_name == "gphoto:id")
+ photo_id = node_value;
+ else if(node_name == "gphoto:albumid")
+ album_id = node_value;
+ }
+
+ node = node.nextSibling();
+ }
+
+ // Raise a popup informing success
+}
+
+void PicasawebTalker::parseResponseAddTag(const QByteArray &data)
+{
+ QString str(data);
+ remaining_tags_count -= 1;
+ emit signalBusy( false );
+ m_buffer.resize(0);
+
+ if (remaining_tags_count == 0)
+ emit signalAddPhotoSucceeded();
+}
+
+void PicasawebTalker::parseResponseAddPhoto(const QByteArray &data)
+{
+ bool success = false;
+ QString line;
+ QString str(data);
+ success = 1;
+ QDomDocument doc( "AddPhoto Response" );
+
+ if ( !doc.setContent( data ) )
+ {
+ return;
+ }
+
+ QDomElement docElem = doc.documentElement();
+ QString title, photo_id, album_id, photoURI;
+ QDomNode node = docElem.firstChild(); //this should mean <entry>
+ QDomElement e;
+
+ while( !node.isNull() )
+ {
+ if ( node.isElement())
+ {
+ QString node_name = node.nodeName();
+ QString node_value = node.toElement().text();
+ if(node_name == "title")
+ {
+ success = true;
+ title = node_value;
+ }
+ else if (node_name == "id")
+ photoURI = node_value;
+ else if(node_name == "gphoto:id")
+ photo_id = node_value;
+ else if(node_name == "gphoto:albumid")
+ album_id = node_value;
+ }
+
+ node = node.nextSibling();
+ }
+
+ if (!success)
+ {
+ emit signalAddPhotoFailed(i18n("Failed to upload photo"));
+ }
+ else
+ {
+ // Update the tags information from the tags_map
+ QStringList tags = tags_map[title];
+ remaining_tags_count = tags.count();
+
+ if (tags.count() == 0)
+ emit signalAddPhotoSucceeded();
+
+ for ( QStringList::Iterator it = tags.begin(); it != tags.end(); ++it )
+ {
+ QString photoURI= QString("http://picasaweb.google.com/data/feed/api/user/"
+ "%1/albumid/%2/photoid/%3").arg(m_username).arg(album_id).arg(photo_id);
+ addPhotoTag( photoURI, *it);
+ }
+ }
+}
+
+void PicasawebTalker::parseResponsePhotoProperty(const QByteArray &data)
+{
+ bool success = false;
+ QString line;
+ QDomDocument doc( "Photos Properties" );
+
+ if ( !doc.setContent( data ) )
+ {
+ return;
+ }
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode node = docElem.firstChild();
+ QDomElement e;
+
+ while( !node.isNull() )
+ {
+ if ( node.isElement() && node.nodeName() == "photoid" )
+ {
+ e = node.toElement(); // try to convert the node to an element.
+ QDomNode details=e.firstChild();
+ success=true;
+ }
+
+ if ( node.isElement() && node.nodeName() == "err" )
+ {
+ kdDebug()<<"Checking Error in response"<<endl;
+ QString code=node.toElement().attribute("code");
+ kdDebug()<<"Error code="<<code<<endl;
+ kdDebug()<<"Msg="<<node.toElement().attribute("msg")<<endl;
+ emit signalError(code);
+ }
+ node = node.nextSibling();
+ }
+
+ kdDebug()<<"GetToken finished"<<endl;
+ if (!success)
+ {
+ emit signalAddPhotoFailed(i18n("Failed to query photo information"));
+ }
+ else
+ {
+ //emit signalAddPhotoSucceeded();
+ }
+}
+
+} // KIPIPicasawebExportPlugin
diff --git a/kipi-plugins/picasawebexport/picasawebtalker.h b/kipi-plugins/picasawebexport/picasawebtalker.h
new file mode 100644
index 0000000..c59f71a
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasawebtalker.h
@@ -0,0 +1,165 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-16-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PICASAWEBTALKER_H
+#define PICASAWEBTALKER_H
+
+// Qt includes.
+
+#include <qvaluelist.h>
+#include <qobject.h>
+#include <qprogressdialog.h>
+#include <qmap.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <kio/jobclasses.h>
+
+namespace KIO
+{
+ class Job;
+}
+
+class KURL;
+
+namespace KIPIPicasawebExportPlugin
+{
+
+class GAlbum;
+class GPhoto;
+class FPhotoInfo;
+class PicasaWebAlbum;
+
+class PicasawebTalker : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ enum State
+ {
+ FE_LOGIN = 0,
+ FE_LISTALBUMS,
+ FE_ADDTAG,
+ FE_LISTPHOTOS,
+ FE_GETPHOTOPROPERTY,
+ FE_ADDPHOTO,
+ FE_GETFROB,
+ FE_CHECKTOKEN,
+ FE_GETTOKEN,
+ FE_CREATEALBUM,
+ FE_GETAUTHORIZED
+ };
+
+public:
+
+ PicasawebTalker(QWidget* parent);
+ ~PicasawebTalker();
+
+ QValueList <PicasaWebAlbum> * m_albumsList;
+ QString getApiSig(QString,QStringList) ;
+ void addPhotoTag(const QString& photoURI, const QString& tag);
+ void getToken(const QString& user, const QString& passwd) ;
+ void checkToken(const QString& token) ;
+ void authenticate(const QString& token=NULL, const QString& username=NULL, const QString& password=NULL) ;
+ void getPhotoProperty(const QString& method, const QString& argList) ;
+ void getHTMLResponseCode(const QString& str);
+ void listAllAlbums();
+ void listPhotos( const QString& albumName );
+ void createAlbum( const QString& albumTitle, const QString& albumDesc, const QString& location,
+ uint timestamp, const QString& access, const QString& media_keywords, bool isCommentEnabled=true);
+ bool addPhoto( const QString& photoPath,
+ FPhotoInfo& info, const QString& albumname,
+ bool rescale=false, int maxDim=600 , int imageQuality=85 );
+ QString getUserName();
+ QString getUserId();
+ void cancel();
+
+public:
+
+ QProgressDialog *authProgressDlg;
+
+signals:
+
+ void signalError( const QString& msg );
+// void signalLoginFailed( const QString& msg );
+ void signalBusy( bool val );
+ void signalAlbums( const QValueList<GAlbum>& albumList );
+ void signalPhotos( const QValueList<GPhoto>& photoList );
+ void signalAddPhotoSucceeded( );
+ void signalGetAlbumsListSucceeded();
+ void signalGetAlbumsListFailed( const QString& msg );
+ void signalAddPhotoFailed( const QString& msg );
+ void signalAuthenticate() ;
+ void signalTokenObtained(const QString& token);
+
+private:
+
+// void parseResponseLogin(const QByteArray &data);
+ void parseResponseListAlbums(const QByteArray &data);
+ void parseResponseListPhotos(const QByteArray &data);
+ void parseResponseCreateAlbum(const QByteArray &data);
+ void parseResponseAddPhoto(const QByteArray &data);
+ void parseResponseAddTag(const QByteArray &data);
+ void parseResponseGetToken(const QByteArray &data);
+ void parseResponseCheckToken(const QByteArray &data);
+ void parseResponsePhotoProperty(const QByteArray &data);
+
+private slots:
+
+ void slotError( const QString& msg );
+// void slotAuthenticate() ;
+ void data(KIO::Job *job, const QByteArray &data);
+ void info(KIO::Job *job, const QString& str);
+ void slotResult (KIO::Job *job);
+
+private:
+
+ int remaining_tags_count;
+
+ QWidget* m_parent;
+
+ QByteArray m_buffer;
+
+// QString m_cookie;
+ QString m_apikey;
+ QString m_secret;
+ QString m_frob;
+ QString m_token;
+ QString m_username;
+ QString m_password;
+ QString m_userId;
+
+ QMap<QString, QStringList > tags_map;
+
+// KURL m_url;
+ KIO::Job* m_job;
+
+ State m_state;
+
+};
+
+} // namespace KIPIPicasawebExportPlugin
+
+#endif /* PICASAWEBTALKER_H */
diff --git a/kipi-plugins/picasawebexport/picasawebviewitem.cpp b/kipi-plugins/picasawebexport/picasawebviewitem.cpp
new file mode 100644
index 0000000..817b3ff
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasawebviewitem.cpp
@@ -0,0 +1,87 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-12-01
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qpainter.h>
+#include <qpixmap.h>
+
+// Local includes.
+
+#include "picasawebviewitem.h"
+
+namespace KIPIPicasawebExportPlugin
+{
+
+void GAlbumViewItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int)
+{
+ if (!p)
+ return;
+
+ QListView *lv = listView();
+ if (!lv)
+ return;
+
+ QFontMetrics fm(p->fontMetrics());
+
+ if (isSelected())
+ p->fillRect(0, 0, width, height(), cg.highlight());
+ else
+ p->fillRect(0, 0, width, height(), cg.base());
+
+ const QPixmap * icon = pixmap( column );
+
+ int iconWidth = 0;
+ if (icon)
+ {
+ iconWidth = icon->width() + lv->itemMargin();
+ int xo = lv->itemMargin();
+ int yo = (height() - icon->height())/2;
+ p->drawPixmap( xo, yo, *icon );
+ }
+
+ if (isSelected())
+ p->setPen( cg.highlightedText() );
+ else
+ p->setPen( cg.text() );
+
+ int r = lv->itemMargin() + iconWidth;
+ int h = lv->fontMetrics().height() + 2;
+ p->drawText(r, 0, width-r, h, Qt::AlignVCenter, album.title);
+
+ QFont fn(lv->font());
+ fn.setPointSize(fn.pointSize()-2);
+ fn.setItalic(true);
+ p->setFont(fn);
+ p->setPen(isSelected() ? cg.highlightedText() : Qt::gray);
+ p->drawText(r, h, width-r, h, Qt::AlignVCenter, album.name);
+}
+
+void GAlbumViewItem::setup()
+{
+ int h = listView()->fontMetrics().height();
+ int margin = 4;
+ setHeight(QMAX(2*h + margin, 32));
+}
+
+} // namespace KIPIPicasawebExportPlugin
diff --git a/kipi-plugins/picasawebexport/picasawebviewitem.h b/kipi-plugins/picasawebexport/picasawebviewitem.h
new file mode 100644
index 0000000..28904a7
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasawebviewitem.h
@@ -0,0 +1,65 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-12-01
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PICASAWEBVIEWITEM_H
+#define PICASAWEBVIEWITEM_H
+
+// Qt includes.
+
+#include <qlistview.h>
+
+// Local includes.
+
+#include "picasawebitem.h"
+
+namespace KIPIPicasawebExportPlugin
+{
+
+class GAlbumViewItem : public QListViewItem
+{
+
+public:
+
+ GAlbumViewItem(QListView* parent, const QString& name, const GAlbum& _album)
+ : QListViewItem(parent, name), album(_album) {};
+
+ GAlbumViewItem(QListViewItem* parent, const QString& name, const GAlbum& _album)
+ : QListViewItem(parent, name), album(_album) {};
+
+ ~GAlbumViewItem() {};
+
+public:
+
+ GAlbum album;
+
+protected:
+
+ void paintCell(QPainter *p, const QColorGroup& cg, int column, int width, int);
+ void paintFocus (QPainter*, const QColorGroup&, const QRect&) {}
+
+ void setup();
+};
+
+} // namespace KIPIPicasawebExportPlugin
+
+#endif /* PICASAWEBVIEWITEM_H */
diff --git a/kipi-plugins/picasawebexport/picasawebwidget.cpp b/kipi-plugins/picasawebexport/picasawebwidget.cpp
new file mode 100644
index 0000000..f76e180
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasawebwidget.cpp
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-16-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qframe.h>
+#include <qheader.h>
+#include <qlistview.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qgroupbox.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qsplitter.h>
+#include <qwhatsthis.h>
+#include <qlineedit.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+
+// Local includes.
+
+#include "picasawebwidget.h"
+#include "picasawebwidget.moc"
+
+namespace KIPIPicasawebExportPlugin
+{
+
+PicasawebWidget::PicasawebWidget(QWidget* parent, const char* name, WFlags fl)
+ : UploadWidget(parent, name, fl)
+{
+ if ( !name )
+ setName("PicasawebWidget");
+
+ //resize( QSize(600, 400).expandedTo(minimumSizeHint()) );
+ //clearWState( WState_Polished );
+}
+
+PicasawebWidget::~PicasawebWidget()
+{
+}
+
+void PicasawebWidget::slotSelectionChecked()
+{
+// kdDebug()<<"Slot Selection Checked "<<endl;
+// m_addPhotoBtn->setEnabled(m_selectImagesButton->isChecked());
+}
+
+void PicasawebWidget::slotResizeChecked()
+{
+// m_dimensionSpinBox->setEnabled(m_resizeCheckBox->isChecked());
+}
+
+} // namespace KIPIPicasawebExportPlugin
diff --git a/kipi-plugins/picasawebexport/picasawebwidget.h b/kipi-plugins/picasawebexport/picasawebwidget.h
new file mode 100644
index 0000000..b6ba85d
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasawebwidget.h
@@ -0,0 +1,78 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-16-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PICASAWEBWIDGET_H
+#define PICASAWEBWIDGET_H
+
+// Qt includes.
+
+#include <qwidget.h>
+
+// Local includes.
+
+#include "uploadwidget.h"
+
+class QListView;
+class QPushButton;
+class QSpinBox;
+class QCheckBox;
+class QLineEdit;
+class QRadioButton;
+
+class KHTMLPart;
+
+namespace KIPIPicasawebExportPlugin
+{
+
+class UploadWidget;
+
+class PicasawebWidget : public UploadWidget
+{
+ Q_OBJECT
+
+public:
+
+ PicasawebWidget(QWidget* parent=0, const char* name=0, WFlags fl= 0);
+ ~PicasawebWidget();
+
+private slots:
+
+ void slotResizeChecked();
+ void slotSelectionChecked();
+
+private:
+
+ QListView* m_tagView;
+
+ QButtonGroup* m_fileSrcButtonGroup;
+
+// QCheckBox* m_resizeCheckBox;
+// QCheckBox* m_exportApplicationTags;
+
+ KHTMLPart* m_photoView;
+
+ friend class PicasawebWindow;
+};
+
+} // namespace KIPIPicasawebExportPlugin
+
+#endif // PICASAWEBWIDGET_H
diff --git a/kipi-plugins/picasawebexport/picasawebwindow.cpp b/kipi-plugins/picasawebexport/picasawebwindow.cpp
new file mode 100644
index 0000000..9e796a3
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasawebwindow.cpp
@@ -0,0 +1,594 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-16-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qcombobox.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qlineedit.h>
+#include <qprogressdialog.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qstringlist.h>
+#include <qradiobutton.h>
+#include <qdatetimeedit.h>
+#include <qdatetime.h>
+#include <qtextedit.h>
+
+// KDE includes.
+
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+#include <krun.h>
+#include <kdebug.h>
+#include <ksimpleconfig.h>
+#include <kdeversion.h>
+#if KDE_IS_VERSION(3,2,0)
+#include <kwallet.h>
+#endif
+
+// Libkipi includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "uploadwidget.h"
+#include "picasawebtalker.h"
+#include "picasawebitem.h"
+#include "picasawebviewitem.h"
+#include "picasaweblogin.h"
+#include "picasawebwidget.h"
+#include "PicasawebNewAlbumDialog.h"
+#include "picasaweblogin.h"
+#include "picasawebwindow.h"
+#include "picasawebwindow.moc"
+
+namespace KIPIPicasawebExportPlugin
+{
+
+PicasawebWindow::PicasawebWindow(KIPI::Interface* interface, const QString &tmpFolder, QWidget* /*parent*/)
+ : KDialogBase(0, 0, false, i18n("Export to Picasa Web Service"), Help|Close, Close, false),
+ m_tmp(tmpFolder)
+{
+ m_interface = interface;
+ m_uploadCount = 0;
+ m_uploadTotal = 0;
+// m_wallet = 0;
+ m_urls = 0;
+ m_widget = new PicasawebWidget(this);
+ m_tagView = m_widget->m_tagView;
+ m_photoView = m_widget->m_photoView;
+ m_newAlbumButton = m_widget->m_newAlbumButton;
+ m_addPhotoButton = m_widget->m_selectPhotosButton;
+ m_albumsListComboBox = m_widget->m_albumsListComboBox;
+ m_dimensionSpinBox = m_widget->m_dimensionSpinBox;
+ m_imageQualitySpinBox = m_widget->m_imageQualitySpinBox;
+ m_resizeCheckBox = m_widget->m_resizeCheckBox;
+ m_tagsLineEdit = m_widget->m_tagsLineEdit;
+ m_exportApplicationTags = m_widget->m_exportApplicationTags;
+ m_startUploadButton = m_widget->m_startUploadButton;
+ m_changeUserButton = m_widget->m_changeUserButton;
+ m_userNameDisplayLabel = m_widget->m_userNameDisplayLabel;
+ m_reloadAlbumsListButton = m_widget->m_reloadAlbumsListButton;
+
+ setMainWidget(m_widget);
+ m_widget->setMinimumSize(620, 300);
+ m_widget->m_currentSelectionButton->setChecked(true);
+
+ if(!m_interface->hasFeature(KIPI::HostSupportsTags))
+ m_exportApplicationTags->setEnabled(false);
+
+ // ------------------------------------------------------------
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Picasaweb Export"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to export image collection to "
+ "Picasaweb web service."),
+ "(c) 2007-2008, Vardhman Jain\n"
+ "(c) 2008, Gilles Caulier");
+
+ m_about->addAuthor("Vardhman Jain", I18N_NOOP("Author and maintainer"),
+ "Vardhman at gmail dot com");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Developer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup(helpMenu->menu());
+
+ // ------------------------------------------------------------
+
+ m_talker = new PicasawebTalker(this);
+
+ connect(m_talker, SIGNAL(signalBusy(bool)),
+ this, SLOT(slotBusy( bool)));
+
+ connect(m_talker, SIGNAL(signalAddPhotoSucceeded()),
+ this, SLOT(slotAddPhotoSucceeded()));
+
+ connect(m_talker, SIGNAL(signalGetAlbumsListSucceeded()),
+ this, SLOT(slotGetAlbumsListSucceeded()));
+
+ connect(m_talker, SIGNAL(signalGetAlbumsListFailed(const QString&)),
+ this, SLOT(slotGetAlbumsListFailed(const QString&)));
+
+ connect(m_talker, SIGNAL( signalAddPhotoFailed(const QString&)),
+ this, SLOT(slotAddPhotoFailed(const QString&)));
+
+// connect(m_talker, SIGNAL( signalListPhotoSetsSucceeded( const QValueList<FPhotoSet>& ) ),
+// this, SLOT( slotListPhotoSetsResponse( const QValueList<FPhotoSet>& ) ) );
+
+ // ------------------------------------------------------------
+
+ m_progressDlg = new QProgressDialog(this, 0, true);
+ m_progressDlg->setAutoReset(true);
+ m_progressDlg->setAutoClose(true);
+
+ connect(m_progressDlg, SIGNAL(canceled()),
+ this, SLOT(slotAddPhotoCancel()));
+
+ connect(m_changeUserButton, SIGNAL(clicked()),
+ this, SLOT(slotUserChangeRequest()));
+
+ connect(m_reloadAlbumsListButton, SIGNAL(clicked()),
+ this, SLOT(slotUpdateAlbumsList()));
+
+ connect(m_newAlbumButton, SIGNAL(clicked()),
+ this, SLOT(slotCreateNewAlbum()));
+
+ connect(m_talker, SIGNAL(signalTokenObtained(const QString&)),
+ this, SLOT(slotTokenObtained(const QString&)));
+
+ connect(m_addPhotoButton, SIGNAL(clicked()),
+ this, SLOT(slotAddPhotos()));
+
+ connect(m_startUploadButton, SIGNAL(clicked()),
+ this, SLOT(slotUploadImages()));
+
+ connect(m_resizeCheckBox, SIGNAL(toggled(bool )),
+ this, SLOT(slotRefreshSizeButtons(bool)));
+
+ // ------------------------------------------------------------
+ // read config
+
+ KSimpleConfig config("kipirc");
+ config.setGroup("PicasawebExport Settings");
+ m_token = config.readEntry("token");
+ QString username = config.readEntry("username");
+ QString password = config.readEntry("password");
+
+ //no saving password rt now
+ if (config.readBoolEntry("Resize", false))
+ m_resizeCheckBox->setChecked(true);
+
+ m_dimensionSpinBox->setValue(config.readNumEntry("Maximum Width", 1600));
+ m_imageQualitySpinBox->setValue(config.readNumEntry("Image Quality", 85));
+
+ // ------------------------------------------------------------
+
+ m_authProgressDlg = new QProgressDialog( this, 0, true );
+ m_authProgressDlg->setAutoReset( true );
+ m_authProgressDlg->setAutoClose( true );
+
+ connect(m_authProgressDlg, SIGNAL(canceled()),
+ this, SLOT(slotAuthCancel()));
+
+ m_talker->authProgressDlg = m_authProgressDlg;
+ m_widget->setEnabled(false);
+
+ // All these three values can be null too.
+ // If m_token is ot null, username would be not null too.
+ // if (!(!m_token || m_token.length() < 1))
+ //getToken(username, password);
+
+ m_talker->authenticate(m_token, username, password);
+}
+
+void PicasawebWindow::slotRefreshSizeButtons(bool /*st*/)
+{
+ if(m_resizeCheckBox->isChecked())
+ {
+ m_dimensionSpinBox->setEnabled(true);
+ m_imageQualitySpinBox->setEnabled(true);
+ }
+ else
+ {
+ m_dimensionSpinBox->setEnabled(false);
+ m_imageQualitySpinBox->setEnabled(false);
+ }
+}
+
+void PicasawebWindow::slotUpdateAlbumsList()
+{
+ m_talker->listAllAlbums();
+}
+
+void PicasawebWindow::slotClose()
+{
+ //handle the close of the window that is calling the destructor.
+ delete this;
+}
+
+PicasawebWindow::~PicasawebWindow()
+{
+#if KDE_IS_VERSION(3,2,0)
+ // if (m_wallet)
+ // delete m_wallet;
+#endif
+
+ // write config
+ KSimpleConfig config("kipirc");
+ config.setGroup("PicasawebExport Settings");
+ config.writeEntry("token", m_token);
+ config.writeEntry("username", m_username);
+ config.writeEntry("Resize", m_resizeCheckBox->isChecked());
+ config.writeEntry("Maximum Width", m_dimensionSpinBox->value());
+ config.writeEntry("Image Quality", m_imageQualitySpinBox->value());
+
+ if(m_urls!=NULL)
+ delete m_urls;
+
+ delete m_progressDlg;
+ delete m_authProgressDlg;
+ delete m_talker;
+ delete m_widget;
+
+ delete m_about;
+}
+
+void PicasawebWindow::getToken(QString& username, QString& password)
+{
+ PicasawebLogin *loginDialog = new PicasawebLogin(this, QString("LoginWindow"), username, password);
+ if (!loginDialog)
+ {
+ return;
+ }
+
+ /*if (username!=NULL && username.length() > 0){
+ kdDebug()<<"Showing stored username"<< username << endl;
+ loginDialog->setUsername(username);
+ if (password != NULL && password.length() > 0){
+ kdDebug()<<"Showing stored password"<< password << endl;
+ loginDialog->setPassword(password);
+ kdDebug()<<"Showing stored password"<< password << endl;
+ }
+ }*/
+
+ QString username_edit, password_edit;
+
+ if (loginDialog->exec() == QDialog::Accepted)
+ {
+ username_edit = loginDialog->username();
+ password_edit = loginDialog->password();
+ }
+ else
+ {
+ //Return something which say authentication needed.
+ return ;
+ }
+}
+
+void PicasawebWindow::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("picasawebexport", "kipi-plugins");
+}
+
+void PicasawebWindow::slotGetAlbumsListSucceeded()
+{
+ if (m_talker && m_talker->m_albumsList)
+ {
+ QValueList <PicasaWebAlbum> *list = m_talker->m_albumsList;
+ m_albumsListComboBox->clear();
+ QValueList<PicasaWebAlbum>::iterator it = list->begin();
+
+ while(it != list->end())
+ {
+ PicasaWebAlbum pwa=*it;
+ QString name = pwa.title;
+ m_albumsListComboBox->insertItem(name);
+ it++;
+ }
+ }
+}
+
+void PicasawebWindow::slotDoLogin()
+{
+}
+
+void PicasawebWindow::slotTokenObtained( const QString& token )
+{
+ m_token=token;
+ m_username=m_talker->getUserName();
+ m_userId=m_talker->getUserId();
+ m_userNameDisplayLabel->setText(m_username);
+ m_widget->setEnabled(true);
+ m_talker->listAllAlbums();
+}
+
+void PicasawebWindow::slotBusy( bool val )
+{
+ if ( val )
+ {
+ setCursor(QCursor::WaitCursor);
+ }
+ else
+ {
+ setCursor(QCursor::ArrowCursor);
+ }
+}
+
+void PicasawebWindow::slotError( const QString& msg )
+{
+ KMessageBox::error(this, msg);
+}
+
+void PicasawebWindow::slotUserChangeRequest()
+{
+ kdDebug()<<"Slot Change User Request "<<endl;
+ m_talker->authenticate();
+}
+
+void PicasawebWindow::slotAuthCancel()
+{
+ m_talker->cancel();
+ m_authProgressDlg->hide();
+}
+
+void PicasawebWindow::slotCreateNewAlbum()
+{
+ NewAlbumDialog *dlg = new NewAlbumDialog(kapp->activeWindow());
+ dlg->m_dateAndTimeEdit->setDateTime(QDateTime::currentDateTime());
+ QString test;
+ int t = dlg->exec();
+
+ if(t == QDialog::Accepted)
+ {
+ if (dlg->m_isPublicRadioButton->isChecked())
+ test = QString("public");
+ else
+ test = QString("unlisted");
+
+ m_talker->createAlbum(dlg->m_titleLineEdit->text(), dlg->m_descriptionTextBox->text(),
+ dlg->m_locationLineEdit->text(), dlg->m_dateAndTimeEdit->dateTime().toTime_t(),
+ test, QString(), true);
+ }
+ else
+ {
+ if (t == QDialog::Rejected)
+ {
+ kdDebug()<<"Album Creation cancelled" <<endl;
+ }
+ }
+}
+/*
+void PicasawebWindow::slotPhotos( const QValueList<GPhoto>& photoList)
+{
+ // TODO
+}
+
+void PicasawebWindow::slotTagSelected()
+{
+ // TODO
+}
+
+void PicasawebWindow::slotOpenPhoto( const KURL& url )
+{
+ new KRun(url);
+}
+*/
+
+void PicasawebWindow::slotListPhotoSetsResponse(const QValueList <FPhotoSet>& /*photoSetList*/)
+{
+}
+
+void PicasawebWindow::slotAddPhotos()
+{
+ //m_talker->listPhotoSets();
+ m_urls = new KURL::List(KIPI::ImageDialog::getImageURLs( this, m_interface ));
+}
+
+void PicasawebWindow::slotUploadImages()
+{
+ if(m_widget->m_currentSelectionButton->isChecked())
+ {
+ if (m_urls!=NULL)
+ delete m_urls;
+
+ m_urls=new KURL::List(m_interface->currentSelection().images());
+ }
+
+ if (m_urls == NULL || m_urls->isEmpty())
+ return;
+
+ typedef QPair<QString,FPhotoInfo> Pair;
+
+ m_uploadQueue.clear();
+
+ for (KURL::List::iterator it = m_urls->begin(); it != m_urls->end(); ++it)
+ {
+ KIPI::ImageInfo info = m_interface->info( *it );
+ FPhotoInfo temp;
+
+ temp.title=info.title();
+ temp.description=info.description();
+
+ QStringList allTags;
+
+ QStringList tagsFromDialog = QStringList::split(" ", m_tagsLineEdit->text(), false);
+ QStringList::Iterator itTags;
+
+ //Tags from the interface
+ itTags= tagsFromDialog.begin();
+
+ while( itTags != tagsFromDialog.end() )
+ {
+ allTags.append( *itTags );
+ ++itTags;
+ }
+
+ //Tags from the database
+ QMap <QString, QVariant> attribs = info.attributes();
+ QStringList tagsFromDatabase;
+
+ if(m_exportApplicationTags->isChecked())
+ {
+ // tagsFromDatabase=attribs["tags"].asStringList();
+ }
+
+ itTags = tagsFromDatabase.begin();
+
+ while( itTags != tagsFromDatabase.end() )
+ {
+ allTags.append( *itTags );
+ ++itTags;
+ }
+
+ itTags = allTags.begin();
+
+ while( itTags != allTags.end() )
+ {
+ ++itTags;
+ }
+
+ temp.tags=allTags;
+ m_uploadQueue.append( Pair( (*it).path(), temp) );
+ }
+
+ m_uploadTotal = m_uploadQueue.count();
+ m_uploadCount = 0;
+ m_progressDlg->reset();
+ slotAddPhotoNext();
+}
+
+
+void PicasawebWindow::slotAddPhotoNext()
+{
+ if ( m_uploadQueue.isEmpty() )
+ {
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+ //slotAlbumSelected();
+ return;
+ }
+
+ typedef QPair<QString,FPhotoInfo> Pair;
+ Pair pathComments = m_uploadQueue.first();
+ FPhotoInfo info=pathComments.second;
+ m_uploadQueue.pop_front();
+
+/* int upload_image_size;
+ int upload_image_quality;*/
+
+ // Get the albums' Id from the name.
+ QString albumId = "";
+ QString selectedAlbumName = m_albumsListComboBox->currentText();
+
+ QValueList<PicasaWebAlbum>::iterator it = m_talker->m_albumsList->begin();
+ while(it != m_talker->m_albumsList->end()) {
+ PicasaWebAlbum pwa=*it;
+ QString name = pwa.title;
+ if (name == selectedAlbumName) {
+ albumId = pwa.id;
+ break;
+ }
+ it++;
+ }
+
+ bool res = m_talker->addPhoto(pathComments.first, //the file path
+ info, albumId,
+ m_resizeCheckBox->isChecked(),
+ m_dimensionSpinBox->value(), m_imageQualitySpinBox->value());
+ if (!res)
+ {
+ slotAddPhotoFailed("");
+ return;
+ }
+
+ m_progressDlg->setLabelText(i18n("Uploading file %1 ").arg( KURL(pathComments.first).filename()));
+
+ if (m_progressDlg->isHidden())
+ m_progressDlg->show();
+}
+
+void PicasawebWindow::slotAddPhotoSucceeded()
+{
+ m_uploadCount++;
+ m_progressDlg->setProgress( m_uploadCount, m_uploadTotal );
+ slotAddPhotoNext();
+}
+
+void PicasawebWindow::slotAddPhotoFailed(const QString& msg)
+{
+ if ( KMessageBox::warningContinueCancel(this,
+ i18n("Failed to upload photo into Picasaweb. %1\nDo you want to continue?")
+ .arg( msg )) != KMessageBox::Continue)
+ {
+ m_uploadQueue.clear();
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+ // refresh the thumbnails
+ //slotTagSelected();
+ }
+ else
+ {
+ m_uploadTotal--;
+ m_progressDlg->setProgress(m_uploadCount, m_uploadTotal);
+ slotAddPhotoNext();
+ }
+}
+
+void PicasawebWindow::slotGetAlbumsListFailed(const QString& /*msg*/)
+{
+ // Raise some errors
+}
+
+void PicasawebWindow::slotAddPhotoCancel()
+{
+ m_uploadQueue.clear();
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+
+ m_talker->cancel();
+
+ // refresh the thumbnails
+ //slotTagSelected();
+}
+
+} // namespace KIPIPicasawebExportPlugin
diff --git a/kipi-plugins/picasawebexport/picasawebwindow.h b/kipi-plugins/picasawebexport/picasawebwindow.h
new file mode 100644
index 0000000..215dd79
--- /dev/null
+++ b/kipi-plugins/picasawebexport/picasawebwindow.h
@@ -0,0 +1,173 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-16-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot com>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PICASAWEBWINDOW_H
+#define PICASAWEBWINDOW_H
+
+// Qt includes.
+
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qintdict.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Libkipi includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QListView;
+class QPushButton;
+class QRadioButton;
+class QSpinBox;
+class QCheckBox;
+class QProgressDialog;
+class KHTMLPart;
+class KURL;
+class QLineEdit;
+class QComboBox;
+
+namespace KIPI
+{
+class Interface;
+}
+
+namespace KWallet
+{
+class Wallet;
+}
+
+namespace KIPIPicasawebExportPlugin
+{
+class PicasawebWidget;
+class PicasawebTalker;
+class GAlbum;
+class GPhoto;
+class FPhotoInfo;
+class FPhotoSet;
+class GAlbumViewItem;
+
+class PicasawebWindow : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ PicasawebWindow(KIPI::Interface *interface, const QString &tmpFolder,QWidget *parent);
+ ~PicasawebWindow();
+
+ void getToken(QString& username, QString& password);
+
+private:
+
+ unsigned int m_uploadCount;
+ unsigned int m_uploadTotal;
+
+ QListView *m_tagView;
+
+ QSpinBox *m_dimensionSpinBox;
+ QSpinBox *m_imageQualitySpinBox;
+
+ QPushButton *m_newAlbumButton;
+ QPushButton *m_addPhotoButton;
+ QPushButton *m_startUploadButton;
+ QPushButton *m_reloadAlbumsListButton;
+ QPushButton *m_changeUserButton;
+
+ QString m_tmp;
+ QString m_token;
+ QString m_username;
+ QString m_userId;
+ QString m_lastSelectedAlbum;
+
+ QCheckBox *m_resizeCheckBox;
+
+ QLineEdit *m_tagsLineEdit;
+
+ QRadioButton *m_exportApplicationTags;
+
+ QProgressDialog *m_progressDlg;
+ QProgressDialog *m_authProgressDlg;
+
+ QComboBox *m_albumsListComboBox;
+
+ QLabel *m_userNameDisplayLabel;
+
+// KWallet::Wallet *m_wallet;
+
+ KHTMLPart *m_photoView;
+ KURL::List *m_urls;
+
+ PicasawebWidget *m_widget;
+ PicasawebTalker *m_talker;
+
+ QIntDict<GAlbumViewItem> m_albumDict;
+
+ QValueList< QPair<QString,FPhotoInfo> > m_uploadQueue;
+
+ KIPI::Interface *m_interface;
+ KIPIPlugins::KPAboutData *m_about;
+
+private slots:
+
+ void slotTokenObtained(const QString& token);
+ void slotDoLogin();
+// void slotLoginFailed( const QString& msg );
+ void slotBusy( bool val );
+ void slotError( const QString& msg );
+// void slotAlbums( const QValueList<GAlbum>& albumList );
+// void slotPhotos( const QValueList<GPhoto>& photoList );
+// void slotTagSelected();
+// void slotOpenPhoto( const KURL& url );
+ void slotUpdateAlbumsList();
+ void slotUserChangeRequest();
+ void slotListPhotoSetsResponse(const QValueList <FPhotoSet>& photoSetList);
+ void slotAddPhotos();
+ void slotUploadImages();
+ void slotAddPhotoNext();
+ void slotAddPhotoSucceeded();
+ void slotAddPhotoFailed( const QString& msg );
+ void slotAddPhotoCancel();
+ void slotAuthCancel();
+ void slotHelp();
+ void slotCreateNewAlbum();
+ void slotGetAlbumsListSucceeded();
+ void slotGetAlbumsListFailed(const QString& msg);
+ void slotRefreshSizeButtons(bool);
+// void slotHandleLogin();
+
+protected:
+
+ void slotClose();
+};
+
+} // namespace KIPIPicasawebExportPlugin
+
+#endif /* PICASAWEBWINDOW_H */
diff --git a/kipi-plugins/picasawebexport/plugin_picasawebexport.cpp b/kipi-plugins/picasawebexport/plugin_picasawebexport.cpp
new file mode 100644
index 0000000..99d1c99
--- /dev/null
+++ b/kipi-plugins/picasawebexport/plugin_picasawebexport.cpp
@@ -0,0 +1,114 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-17-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C ansi includes.
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+
+// libkipi includes.
+
+#include <libkipi/interface.h>
+
+// Local includes.
+
+#include "picasawebwindow.h"
+#include "plugin_picasawebexport.h"
+#include "plugin_picasawebexport.moc"
+
+typedef KGenericFactory<Plugin_PicasawebExport> Factory;
+
+K_EXPORT_COMPONENT_FACTORY(kipiplugin_picasawebexport, Factory("kipiplugin_picasawebexport"))
+
+
+Plugin_PicasawebExport::Plugin_PicasawebExport(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin(Factory::instance(), parent, "PicasawebExport")
+{
+ kdDebug(51001) << "Plugin_PicasawebExport plugin loaded" << endl;
+}
+
+void Plugin_PicasawebExport::setup(QWidget* widget)
+{
+ KIPI::Plugin::setup(widget);
+
+ m_action = new KAction(i18n("Export to Picasaweb..."),
+ "www",
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "picasawebexport");
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ m_action->setEnabled(false);
+ return;
+ }
+
+ m_action->setEnabled(true);
+ addAction(m_action);
+}
+
+Plugin_PicasawebExport::~Plugin_PicasawebExport()
+{
+}
+
+void Plugin_PicasawebExport::slotActivate()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError(51000) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KStandardDirs dir;
+ QString Tmp = dir.saveLocation("tmp", "kipi-picasawebexportplugin-" + QString::number(getpid()) + "/");
+
+ m_dlg = new KIPIPicasawebExportPlugin::PicasawebWindow(interface,Tmp,kapp->activeWindow());
+ m_dlg->show();
+}
+
+KIPI::Category Plugin_PicasawebExport::category( KAction* action ) const
+{
+ if (action == m_action)
+ return KIPI::EXPORTPLUGIN;
+
+ kdWarning(51000) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::EXPORTPLUGIN;
+}
diff --git a/kipi-plugins/picasawebexport/plugin_picasawebexport.h b/kipi-plugins/picasawebexport/plugin_picasawebexport.h
new file mode 100644
index 0000000..ddf2fc0
--- /dev/null
+++ b/kipi-plugins/picasawebexport/plugin_picasawebexport.h
@@ -0,0 +1,60 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-17-07
+ * Description : a kipi plugin to export images to Picasa web service
+ *
+ * Copyright (C) 2007-2008 by Vardhman Jain <vardhman at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_PICASAWEBEXPORT_H
+#define PLUGIN_PICASAWEBEXPORT_H
+
+// Libkipi includes.
+
+#include <libkipi/plugin.h>
+
+// Local includes.
+
+#include "picasawebwindow.h"
+
+class KAction;
+
+using namespace KIPIPicasawebExportPlugin;
+
+class Plugin_PicasawebExport : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_PicasawebExport(QObject *parent, const char* name, const QStringList &args);
+ ~Plugin_PicasawebExport();
+
+ virtual KIPI::Category category(KAction* action) const;
+ virtual void setup(QWidget*);
+
+public slots:
+
+ void slotActivate();
+
+private:
+
+ PicasawebWindow *m_dlg;
+ KAction *m_action;
+};
+
+#endif // PLUGIN_PICASAWEBEXPORT_H
diff --git a/kipi-plugins/picasawebexport/uploadwidget.ui b/kipi-plugins/picasawebexport/uploadwidget.ui
new file mode 100644
index 0000000..d290d2f
--- /dev/null
+++ b/kipi-plugins/picasawebexport/uploadwidget.ui
@@ -0,0 +1,442 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KIPIPicasawebExportPlugin::UploadWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>UploadWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>618</width>
+ <height>299</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>42</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>PicasaWeb Exporter Upload</string>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>m_selectionFrame</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>390</x>
+ <y>50</y>
+ <width>220</width>
+ <height>140</height>
+ </rect>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>200</width>
+ <height>70</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>Images to upload</string>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_selectImagesButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>40</y>
+ <width>180</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Select Images for Upload</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_currentSelectionButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>187</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Currentl&amp;y Selected Images</string>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_selectPhotosButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>60</x>
+ <y>100</y>
+ <width>101</width>
+ <height>30</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Select Photos</string>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>390</x>
+ <y>200</y>
+ <width>220</width>
+ <height>90</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>Account Details</string>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_changeUserButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>90</x>
+ <y>50</y>
+ <width>110</width>
+ <height>30</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Change User</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>70</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Username:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_userNameDisplayLabel</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>90</x>
+ <y>20</y>
+ <width>120</width>
+ <height>17</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_WidgetLabel</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>240</width>
+ <height>30</height>
+ </rect>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>18</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>PicasaWeb Uploader</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_startUploadButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>490</x>
+ <y>10</y>
+ <width>120</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Start Uploading</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>50</y>
+ <width>370</width>
+ <height>240</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>tagsTxtLabel</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>80</y>
+ <width>42</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Tags:&lt;p align="center"&gt;&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_newAlbumButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>20</y>
+ <width>80</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>New &amp;Album</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_reloadAlbumsListButton</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>20</y>
+ <width>60</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Reload</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>50</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Album:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_tagsLineEdit</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>60</x>
+ <y>80</y>
+ <width>300</width>
+ <height>23</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_exportApplicationTags</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>60</x>
+ <y>110</y>
+ <width>180</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>E&amp;xport Application Tags</string>
+ </property>
+ <property name="accel">
+ <string>Alt+X</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>m_albumsListComboBox</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>60</x>
+ <y>20</y>
+ <width>140</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_resizeGroupBox</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>150</y>
+ <width>350</width>
+ <height>70</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_resizeCheckBox</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>151</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Resi&amp;ze</string>
+ </property>
+ <property name="accel">
+ <string>Alt+Z</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>40</y>
+ <width>90</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Size (pixels):</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>180</x>
+ <y>40</y>
+ <width>91</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Compression:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_dimensionSpinBox</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>100</x>
+ <y>40</y>
+ <width>71</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="maxValue">
+ <number>3200</number>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_imageQualitySpinBox</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>40</y>
+ <width>60</width>
+ <height>20</height>
+ </rect>
+ </property>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kipi-plugins/printwizard/Makefile.am b/kipi-plugins/printwizard/Makefile.am
new file mode 100644
index 0000000..abb7e57
--- /dev/null
+++ b/kipi-plugins/printwizard/Makefile.am
@@ -0,0 +1,20 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKEXIV2_CFLAGS) $(LIBKIPI_CFLAGS) $(LIBKDCRAW_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_printwizard.la
+kipiplugin_printwizard_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+kipiplugin_printwizard_la_SOURCES = frmprintwizardbase.ui plugin_printwizard.cpp frmprintwizard.cpp cropframe.cpp tphoto.cpp utils.cpp
+
+#LIBKIPI_LIBS = $(top_builddir)/libkipi/libkipi/libkipi.la
+kipiplugin_printwizard_la_LIBADD = $(LIBKEXIV2_LIBS) $(LIBKDCRAW_LIBS) -lkipiplugins \
+ $(LIB_KDEPRINT) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_printwizard_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries)
+
+kde_services_DATA = kipiplugin_printwizard.desktop
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_printwizard.pot
+
diff --git a/kipi-plugins/printwizard/cropframe.cpp b/kipi-plugins/printwizard/cropframe.cpp
new file mode 100644
index 0000000..60eb532
--- /dev/null
+++ b/kipi-plugins/printwizard/cropframe.cpp
@@ -0,0 +1,315 @@
+/***************************************************************************
+ cropframe.cpp - description
+ -------------------
+ begin : Mon Sep 30 2002
+ copyright : (C) 2002 by Todd Shoemaker
+ email : jtshoe11@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. *
+ * *
+ ***************************************************************************/
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <math.h>
+#include <stdio.h>
+}
+
+// Qt includes.
+
+#include <qpainter.h>
+#include <qimage.h>
+
+// Local includes.
+
+#include "cropframe.h"
+#include "utils.h"
+
+namespace KIPIPrintWizardPlugin
+{
+
+CropFrame::CropFrame(QWidget *parent=0, const char *name=0)
+ : QWidget(parent, name)
+{
+ m_mouseDown = false;
+}
+
+// FIXME: This method is doing way too much. The cropFrame initialization
+// should be a TPhoto method, and should not require the scaling of
+// pixmaps to get the desired effect, which are too slow.
+
+void CropFrame::init(TPhoto *photo, int width, int height, bool autoRotate, bool paint)
+{
+ m_photo = photo;
+ QImage scaledImg = m_photo->thumbnail().convertToImage();
+
+ // has the cropRegion been set yet?
+ bool resetCropRegion = (m_photo->cropRegion == QRect(-1, -1, -1, -1));
+ if (resetCropRegion)
+ {
+ // first, let's see if we should rotate
+ if (autoRotate) {
+ if (m_photo->rotation == 0 && ((width > height &&
+ m_photo->thumbnail().height() > m_photo->thumbnail().width()) ||
+ (height > width &&
+ m_photo->thumbnail().width() > m_photo->thumbnail().height())) )
+ {
+ // rotate
+ m_photo->rotation = 90;
+ }
+ }
+ }
+ else
+ {
+ // does the crop region need updating (but the image shouldn't be rotated)?
+ resetCropRegion = (m_photo->cropRegion == QRect(-2, -2, -2, -2));
+ }
+
+ // rotate
+ QWMatrix matrix;
+ matrix.rotate(m_photo->rotation);
+ scaledImg = scaledImg.xForm(matrix);
+
+ scaledImg = scaledImg.smoothScale(this->width(), this->height(), QImage::ScaleMin);
+
+ m_pixmap = new QPixmap();
+ m_pixmap->convertFromImage(scaledImg);
+ m_pixmapX = (this->width() / 2) - (m_pixmap->width() / 2);
+ m_pixmapY = (this->height() / 2) - (m_pixmap->height() / 2);
+
+ m_color = Qt::red;
+ // size the rectangle based on the minimum image dimension
+ int w = m_pixmap->width();
+ int h = m_pixmap->height();;
+ if (w < h)
+ {
+ h = NINT((double)w * ((double)height / (double)width));
+ if (h > m_pixmap->height())
+ {
+ h = m_pixmap->height();
+ w = NINT((double)h * ((double)width / (double)height));
+ }
+ }
+ else
+ {
+ w = NINT((double)h * ((double)width / (double)height));
+ if (w > m_pixmap->width())
+ {
+ w = m_pixmap->width();
+ h = NINT((double)w * ((double)height / (double)width));
+ }
+ }
+
+ if (resetCropRegion)
+ {
+ m_cropRegion.setRect((this->width() / 2) - (w / 2), (this->height() / 2) - (h / 2), w, h);
+
+ m_photo->cropRegion = _screenToPhotoRect(m_cropRegion);
+ }
+ else
+ m_cropRegion = _photoToScreenRect(m_photo->cropRegion);
+
+ if (paint)
+ repaint(false);
+}
+
+QRect CropFrame::_screenToPhotoRect(QRect r)
+{
+ // r is given in screen coordinates, and we want to convert that
+ // to photo coordinates
+ double xRatio = 0.0;
+ double yRatio = 0.0;
+
+ // flip the photo dimensions if rotated
+ int photoW;
+ int photoH;
+
+ if (m_photo->rotation == 0 || m_photo->rotation == 180)
+ {
+ photoW = m_photo->width();
+ photoH = m_photo->height();
+ }
+ else
+ {
+ photoW = m_photo->height();
+ photoH = m_photo->width();
+ }
+ if (m_pixmap->width() > 0)
+ xRatio = (double) photoW / (double) m_pixmap->width();
+
+ if (m_pixmap->height() > 0)
+ yRatio = (double) photoH / (double) m_pixmap->height();
+
+
+ int x1 = NINT((r.left() - m_pixmapX) * xRatio);
+ int y1 = NINT((r.top() - m_pixmapY) * yRatio);
+
+ int w = NINT(r.width() * xRatio);
+ int h = NINT(r.height() * yRatio);
+
+ QRect result;
+ result.setRect(x1, y1, w, h);
+ return result;
+}
+
+QRect CropFrame::_photoToScreenRect(QRect r)
+{
+ // r is given in photo coordinates, and we want to convert that
+ // to screen coordinates
+ double xRatio = 0.0;
+ double yRatio = 0.0;
+
+ // flip the photo dimensions if rotated
+ int photoW;
+ int photoH;
+
+ if (m_photo->rotation == 0 || m_photo->rotation == 180)
+ {
+ photoW = m_photo->width();
+ photoH = m_photo->height();
+ }
+ else
+ {
+ photoW = m_photo->height();
+ photoH = m_photo->width();
+ }
+
+ if (m_photo->width() > 0)
+ xRatio = (double) m_pixmap->width() / (double) photoW;
+
+ if (m_photo->height() > 0)
+ yRatio = (double)m_pixmap->height() / (double)photoH;
+
+
+ int x1 = NINT(r.left() * xRatio + m_pixmapX);
+ int y1 = NINT(r.top() * yRatio + m_pixmapY);
+
+ int w = NINT(r.width() * xRatio);
+ int h = NINT(r.height() * yRatio);
+
+ QRect result;
+ result.setRect(x1, y1, w, h);
+ return result;
+}
+
+CropFrame::~CropFrame()
+{
+}
+void CropFrame::paintEvent (QPaintEvent *)
+{
+
+ QPixmap bmp(this->width(), this->height());
+ QPainter p;
+ p.begin(&bmp);
+
+ p.eraseRect(0, 0, this->width(), this->height());
+
+ // draw the background pixmap
+ p.drawPixmap(m_pixmapX, m_pixmapY, *m_pixmap);
+
+ // draw the rectangle
+ p.setPen(QPen(m_color, 2));
+ p.drawRect(m_cropRegion);
+ // draw the crosshairs
+ int midX = m_cropRegion.left() + m_cropRegion.width() / 2;
+ int midY = m_cropRegion.top() + m_cropRegion.height() / 2;
+ p.drawLine(midX - 10, midY, midX + 10, midY);
+ p.drawLine(midX, midY - 10, midX, midY + 10);
+ p.end();
+
+ QPainter newp(this);
+ newp.drawPixmap(0, 0, bmp);
+}
+
+void CropFrame::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() == QMouseEvent::LeftButton)
+ {
+ m_mouseDown = true;
+ this->mouseMoveEvent(e);
+ }
+
+}
+
+void CropFrame::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() == QMouseEvent::LeftButton)
+ m_mouseDown = false;
+}
+
+void CropFrame::mouseMoveEvent(QMouseEvent *e)
+{
+ if (m_mouseDown)
+ {
+ // don't let the rectangle float off the image.
+ int newW = m_cropRegion.width();
+ int newH = m_cropRegion.height();
+
+ int newX = e->x() - (newW / 2);
+ newX = MAX(m_pixmapX, newX);
+ newX = MIN(m_pixmapX + m_pixmap->width() - newW, newX);
+
+ int newY = e->y() - (newH / 2);
+ newY = MAX(m_pixmapY, newY);
+ newY = MIN(m_pixmapY + m_pixmap->height() - newH, newY);
+
+ m_cropRegion.setRect(newX, newY, newW, newH);
+ m_photo->cropRegion = _screenToPhotoRect(m_cropRegion);
+ repaint(false);
+ }
+}
+
+void CropFrame::keyPressEvent(QKeyEvent *e)
+{
+ int newX = m_cropRegion.x();
+ int newY = m_cropRegion.y();
+
+ switch (e->key()) {
+ case Qt::Key_Up : newY--;
+ break;
+ case Qt::Key_Down : newY++;
+ break;
+ case Qt::Key_Left : newX--;
+ break;
+ case Qt::Key_Right : newX++;
+ break;
+ }
+
+ // keep inside the pixmap
+ int w = m_cropRegion.width();
+ int h = m_cropRegion.height();
+
+ newX = MAX(m_pixmapX, newX);
+ newX = MIN(m_pixmapX + m_pixmap->width() - w, newX);
+
+ newY = MAX(m_pixmapY, newY);
+ newY = MIN(m_pixmapY + m_pixmap->height() - h, newY);
+
+ m_cropRegion.setRect(newX, newY, w, h);
+ m_photo->cropRegion = _screenToPhotoRect(m_cropRegion);
+ repaint(false);
+
+}
+
+void CropFrame::setColor(QColor c)
+{
+ m_color = c;
+ repaint(false);
+}
+
+QColor CropFrame::color()
+{
+ return m_color;
+}
+
+} // NameSpace KIPIPrintWizardPlugin
+
+#include "cropframe.moc"
diff --git a/kipi-plugins/printwizard/cropframe.h b/kipi-plugins/printwizard/cropframe.h
new file mode 100644
index 0000000..ce90b5d
--- /dev/null
+++ b/kipi-plugins/printwizard/cropframe.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ cropframe.h - description
+ -------------------
+ begin : Mon Sep 30 2002
+ copyright : (C) 2002 by Todd Shoemaker
+ email : jtshoe11@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 CROPFRAME_H
+#define CROPFRAME_H
+
+// Qt includes.
+
+#include <qwidget.h>
+#include <qpixmap.h>
+
+// Local includes.
+
+#include "tphoto.h"
+
+namespace KIPIPrintWizardPlugin
+{
+
+class CropFrame : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ CropFrame(QWidget *parent, const char *name);
+ ~CropFrame();
+ void init(TPhoto *photo, int width, int height, bool autoRotate, bool paint = true);
+ void setColor(QColor);
+ QColor color();
+
+ private:
+ TPhoto *m_photo;
+ bool m_mouseDown;
+ QPixmap *m_pixmap;
+ int m_pixmapX;
+ int m_pixmapY;
+
+ QColor m_color;
+
+ QRect m_cropRegion;
+
+
+ QRect _screenToPhotoRect(QRect r);
+ QRect _photoToScreenRect(QRect r);
+
+ protected:
+ void paintEvent (QPaintEvent *);
+ void mousePressEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void keyPressEvent(QKeyEvent *);
+};
+
+} // NameSpace KIPIPrintWizardPlugin
+
+#endif // CROPFRAME_H
diff --git a/kipi-plugins/printwizard/frmprintwizard.cpp b/kipi-plugins/printwizard/frmprintwizard.cpp
new file mode 100644
index 0000000..52fbeb0
--- /dev/null
+++ b/kipi-plugins/printwizard/frmprintwizard.cpp
@@ -0,0 +1,1988 @@
+/***************************************************************************
+ frmprintwizard.cpp - description
+ -------------------
+ begin : Mon Sep 30 2002
+ copyright : (C) 2002 by Todd Shoemaker
+ : (C) 2007 Angelo Naselli
+ email : todd@theshoemakers.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. *
+ * *
+ ***************************************************************************/
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// Include files for Qt
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qpainter.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qdir.h>
+#include <qslider.h>
+
+// Include files for KDE
+
+#include <kprogress.h>
+#include <kprocess.h>
+#include <ksimpleconfig.h>
+#include <klistbox.h>
+#include <kprinter.h>
+#include <klocale.h>
+#include <klineedit.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kcombobox.h>
+#include <kprogress.h>
+#include <kurllabel.h>
+#include <kfiledialog.h>
+#include <kpushbutton.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kdeversion.h>
+#include <kfontcombo.h>
+#include <kcolorcombo.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "utils.h"
+#include "cropframe.h"
+#include "frmprintwizard.h"
+#include "frmprintwizard.moc"
+
+namespace KIPIPrintWizardPlugin
+{
+
+#if QT_VERSION<0x030200
+// This function emulates int QButtonGroup::selectedId() which does not exist
+// in Qt 3.1
+inline int buttonGroupSelectedId(const QButtonGroup* group)
+{
+ QButton* button=group->selected();
+ if (!button) return -1;
+ return group->id(button);
+}
+#else
+inline int buttonGroupSelectedId(const QButtonGroup* group)
+{
+ return group->selectedId();
+}
+#endif
+
+
+FrmPrintWizard::FrmPrintWizard(QWidget *parent, const char *name )
+ : FrmPrintWizardBase(parent, name)
+{
+ // enable help buttons
+ for(int i = 0; i < pageCount(); ++i)
+ setHelpEnabled(page(i), true);
+
+ // ---------------------------------------------------------------
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Print Wizard"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A KIPI plugin to print images"),
+ "(c) 2003-2004, Todd Shoemaker\n(c) 2007-2008, Angelo Naselli");
+
+ m_about->addAuthor("Todd Shoemaker", I18N_NOOP("Author"),
+ "todd@theshoemakers.net");
+ m_about->addAuthor("Angelo Naselli", I18N_NOOP("Developer and maintainer"),
+ "anaselli@linux.it");
+ m_about->addAuthor("Valerio Fuoglio", I18N_NOOP("Contributor"),
+ "valerio.fuoglio@gmail.com");
+
+ // setting-up icons on buttons
+ BtnBrowseOutputPath->setText("");
+ BtnBrowseOutputPath->setIconSet( SmallIconSet( "fileopen" ) );
+ BtnPrintOrderDown->setText("");
+ BtnPrintOrderDown->setIconSet( SmallIconSet( "down" ) );
+ BtnPrintOrderUp->setText("");
+ BtnPrintOrderUp->setIconSet( SmallIconSet( "up" ) );
+ BtnPreviewPageUp->setText("");
+ BtnPreviewPageUp->setIconSet( SmallIconSet( "next" ) );
+ BtnPreviewPageDown->setText("");
+ BtnPreviewPageDown->setIconSet( SmallIconSet( "previous" ) );
+ BtnCropPrev->setText("");
+ BtnCropPrev->setIconSet( SmallIconSet( "previous" ) );
+ BtnCropNext->setText("");
+ BtnCropNext->setIconSet( SmallIconSet( "next" ) );
+ BtnCropRotate->setText("");
+ BtnCropRotate->setIconSet( SmallIconSet( "rotate" ) );
+
+ // wizard buttons
+ QPushButton *pBtn = backButton ();
+ pBtn->setText("");
+ pBtn->setIconSet( SmallIconSet( "previous" ) );
+ pBtn = nextButton ();
+ pBtn->setText("");
+ pBtn->setIconSet( SmallIconSet( "next" ) );
+
+ m_helpButton = helpButton();
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ // NOTE does it work????
+ setModal(false);
+ // ---------------------------------------------------------------
+ // turn off back button for first and last page
+ setBackEnabled(page(0), false);
+
+ m_currentPreviewPage = 0;
+ //TODO fix next two steps
+ m_pageSize = Unknown; // select a different page to force a refresh in initPhotoSizes.
+ initPhotoSizes(A4); // default to A4 for now.
+
+ EditOutputPath->setText(QDir::homeDirPath());
+
+ connect(this, SIGNAL(selected(const QString &)),
+ this, SLOT(FrmPrintWizardBaseSelected(const QString &)));
+
+ connect(GrpOutputSettings, SIGNAL(clicked(int)),
+ this, SLOT(GrpOutputSettings_clicked(int)));
+
+ connect(m_captions, SIGNAL(activated(int)),
+ this, SLOT(CaptionChanged(int)));
+
+ connect(EditOutputPath, SIGNAL(textChanged(const QString &)),
+ this, SLOT(EditOutputPath_textChanged(const QString &)));
+
+ connect(BtnBrowseOutputPath, SIGNAL(clicked(void)),
+ this, SLOT(BtnBrowseOutputPath_clicked(void)));
+
+ CmbPaperSize->setCurrentItem(0);
+
+ connect(CmbPaperSize, SIGNAL(activated(int)),
+ this, SLOT(CmbPaperSize_activated(int)));
+
+ connect(BtnPrintOrderDown, SIGNAL(clicked(void)),
+ this, SLOT(BtnPrintOrderDown_clicked(void)));
+ connect(BtnPrintOrderUp, SIGNAL(clicked(void)),
+ this, SLOT(BtnPrintOrderUp_clicked(void)));
+ connect(BtnPreviewPageUp, SIGNAL(clicked(void)),
+ this, SLOT(BtnPreviewPageUp_clicked(void)));
+ connect(BtnPreviewPageDown, SIGNAL(clicked(void)),
+ this, SLOT(BtnPreviewPageDown_clicked(void)));
+
+ connect(BtnCropPrev, SIGNAL(clicked()),
+ this, SLOT(BtnCropPrev_clicked()));
+ connect(BtnCropNext, SIGNAL(clicked()),
+ this, SLOT(BtnCropNext_clicked()));
+
+ connect(BtnCropRotate, SIGNAL(clicked()),
+ this, SLOT(BtnCropRotate_clicked()));
+
+ loadSettings();
+
+ m_Proc = new KProcess;
+ *m_Proc << "kjobviewer" << "--all";
+}
+
+FrmPrintWizard::~FrmPrintWizard()
+{
+ for(unsigned int i=0; i < m_photos.count(); i++)
+ if (m_photos.at(i))
+ delete m_photos.at(i);
+ m_photos.clear();
+
+ for(unsigned int i=0; i < m_photoSizes.count(); i++)
+ if (m_photoSizes.at(i))
+ delete m_photoSizes.at(i);
+ m_photoSizes.clear();
+
+ delete m_about;
+}
+
+void FrmPrintWizard::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("printwizard","kipi-plugins");
+}
+
+void FrmPrintWizard::print( KURL::List fileList, QString tempPath)
+{
+ for(unsigned int i=0; i < m_photos.count(); i++)
+ if (m_photos.at(i))
+ delete m_photos.at(i);
+ m_photos.clear();
+ ListPrintOrder->clear();
+
+ for(unsigned int i=0; i < fileList.count(); i++)
+ {
+ TPhoto *photo = new TPhoto(150);
+ photo->filename = fileList[i];
+ m_photos.append(photo);
+ // load the print order listbox
+ ListPrintOrder->insertItem(photo->filename.filename());
+ }
+ ListPrintOrder->setCurrentItem(0);
+
+ m_tempPath = tempPath;
+ LblPhotoCount->setText(QString::number(m_photos.count()));
+
+ BtnCropPrev->setEnabled(false);
+
+ if (m_photos.count() == 1)
+ BtnCropNext->setEnabled(false);
+}
+
+void FrmPrintWizard::BtnCropRotate_clicked()
+{
+ // by definition, the cropRegion should be set by now,
+ // which means that after our rotation it will become invalid,
+ // so we will initialize it to -2 in an awful hack (this
+ // tells the cropFrame to reset the crop region, but don't
+ // automagically rotate the image to fit.
+ TPhoto *photo = m_photos.current();
+ photo->cropRegion = QRect(-2, -2, -2, -2);
+ photo->rotation = (photo->rotation + 90) % 360;
+
+ updateCropFrame(photo, m_photos.at());
+
+}
+
+void FrmPrintWizard::setBtnCropEnabled()
+{
+ if (m_photos.at() == 0)
+ BtnCropPrev->setEnabled(false);
+ else
+ BtnCropPrev->setEnabled(true);
+
+ if (m_photos.at() == (int)m_photos.count() - 1)
+ BtnCropNext->setEnabled(false);
+ else
+ BtnCropNext->setEnabled(true);
+}
+
+void FrmPrintWizard::BtnCropNext_clicked()
+{
+ TPhoto *photo = 0;
+ photo = m_photos.next();
+ setBtnCropEnabled();
+ if (photo == 0)
+ {
+ m_photos.last();
+ return;
+ }
+ updateCropFrame(photo, m_photos.at());
+}
+
+void FrmPrintWizard::updateCropFrame(TPhoto *photo, int photoIndex)
+{
+ TPhotoSize *s = m_photoSizes.at(ListPhotoSizes->currentItem());
+ cropFrame->init(photo, getLayout(photoIndex)->width(), getLayout(photoIndex)->height(), s->autoRotate);
+ LblCropPhoto->setText(i18n("Photo %1 of %2").arg( QString::number(m_photos.at() + 1) ).arg( QString::number(m_photos.count()) ));
+}
+
+void FrmPrintWizard::BtnCropPrev_clicked()
+{
+ TPhoto *photo = 0;
+ photo = m_photos.prev();
+
+ setBtnCropEnabled();
+
+ if (photo == 0)
+ {
+ m_photos.first();
+ return;
+ }
+ updateCropFrame(photo, m_photos.at());
+}
+
+void FrmPrintWizard::FrmPrintWizardBaseSelected(const QString &)
+{
+ QString pageName = this->currentPage()->name();
+ if (pageName == "pgPrinter")
+ {
+ // use this method to enable/disable the next button
+ GrpOutputSettings_clicked(GrpOutputSettings->id(GrpOutputSettings->selected()));
+ }
+ else
+ if (pageName == "pgLayout")
+ {
+ // create our photo sizes list
+ initPhotoSizes(m_pageSize);
+ previewPhotos();
+ }
+ else
+ if (pageName == "pgCrop")
+ {
+ TPhoto *photo = m_photos.first();
+ setBtnCropEnabled();
+ updateCropFrame(photo, m_photos.at());
+ } else
+ if (pageName == "pgFinished")
+ {
+ this->finishButton()->setEnabled(true);
+
+ // set the default crop regions if not already set
+ TPhotoSize *s = m_photoSizes.at(ListPhotoSizes->currentItem());
+ int i = 0;
+ for (TPhoto *photo = m_photos.first(); photo != 0; photo = m_photos.next())
+ {
+ if (photo->cropRegion == QRect(-1, -1, -1, -1))
+ cropFrame->init(photo, getLayout(i)->width(), getLayout(i)->height(), s->autoRotate);
+ i++;
+ }
+
+ if (RdoOutputPrinter->isChecked())
+ {
+ KPrinter printer(false);
+ switch(m_pageSize)
+ {
+ case Letter : printer.setPageSize(KPrinter::Letter);
+ break;
+ case A4 : printer.setPageSize(KPrinter::A4);
+ break;
+ case A6 : printer.setPageSize(KPrinter::A6);
+ break;
+ default:
+ break;
+ }
+ if (m_fullbleed->isChecked())
+ {
+ printer.setFullPage(true);
+ printer.setMargins (0, 0, 0, 0);
+ }
+
+#if KDE_IS_VERSION(3,2,0)
+ printer.setUsePrinterResolution(true);
+#endif
+ if (printer.setup())
+ printPhotos(m_photos, s->layouts, printer);
+ }
+ else
+ if (RdoOutputFile->isChecked())
+ {
+ // now output the items
+ QString path = EditOutputPath->text();
+ if (path.right(1) != "/")
+ path = path + "/";
+ path = path + "kipi_printwizard_";
+ printPhotosToFile(m_photos, path, s);
+ } else
+ if (RdoOutputGimp->isChecked())
+ {
+ // now output the items
+ QString path = m_tempPath;
+ if (!checkTempPath(this, path))
+ return;
+ path = path + "kipi_tmp_";
+ if (m_gimpFiles.count() > 0)
+ removeGimpFiles();
+ m_gimpFiles = printPhotosToFile(m_photos, path, s);
+ QStringList args;
+ args << "gimp-remote";
+ for(QStringList::Iterator it = m_gimpFiles.begin(); it != m_gimpFiles.end(); ++it)
+ args << (*it);
+ if (!launchExternalApp(args))
+ {
+ KMessageBox::sorry(this, i18n("There was an error launching the Gimp. Please make sure it is properly installed."), i18n("KIPI")); return;
+ }
+
+ }
+ }
+}
+
+double getMaxDPI(QPtrList<TPhoto> photos, QPtrList<QRect> layouts, unsigned int current)
+{
+ Q_ASSERT(layouts.count() > 1);
+
+ QRect *layout = layouts.at(1);
+
+ double maxDPI = 0.0;
+
+ for(; current < photos.count(); current++)
+ {
+ TPhoto *photo = photos.at(current);
+ double dpi = ((double)photo->cropRegion.width() + (double)photo->cropRegion.height()) /
+ (((double)layout->width() / 1000.0) + ((double)layout->height() / 1000.0));
+ if (dpi > maxDPI)
+ maxDPI = dpi;
+ // iterate to the next position
+ layout = layouts.next();
+ if (layout == 0)
+ {
+ break;
+ }
+ }
+ return maxDPI;
+}
+
+QRect * FrmPrintWizard::getLayout(int photoIndex)
+{
+ TPhotoSize *s = m_photoSizes.at(ListPhotoSizes->currentItem());
+
+ // how many photos would actually be printed, including copies?
+ int photoCount = (photoIndex + 1);
+ // how many pages? Recall that the first layout item is the paper size
+ int photosPerPage = s->layouts.count() - 1;
+ int remainder = photoCount % photosPerPage;
+
+ int retVal = remainder;
+ if (remainder == 0)
+ retVal = photosPerPage;
+ return s->layouts.at(retVal);
+}
+
+int FrmPrintWizard::getPageCount()
+{
+ // get the selected layout
+ TPhotoSize *s = m_photoSizes.at(ListPhotoSizes->currentItem());
+
+ int photoCount = m_photos.count();
+ // how many pages? Recall that the first layout item is the paper size
+ int photosPerPage = s->layouts.count() - 1;
+ int remainder = photoCount % photosPerPage;
+ int emptySlots = 0;
+ if (remainder > 0)
+ emptySlots = photosPerPage - remainder;
+ int pageCount = photoCount / photosPerPage;
+ if (emptySlots > 0)
+ pageCount++;
+ return pageCount;
+}
+
+
+const float FONT_HEIGHT_RATIO = 0.8;
+
+void FrmPrintWizard::printCaption(QPainter &p, TPhoto*photo, int captionW, int captionH, QString caption)
+{
+ // PENDING anaselli TPhoto*photo will be needed to add a per photo caption management
+ QStringList captionByLines;
+
+ uint captionIndex = 0;
+
+ while (captionIndex < caption.length())
+ {
+ QString newLine;
+ bool breakLine = false; // End Of Line found
+ uint currIndex; // Caption QString current index
+
+ // Check minimal lines dimension
+ //TODO fix length, maybe useless
+ uint captionLineLocalLength = 40;
+
+ for ( currIndex = captionIndex; currIndex < caption.length() && !breakLine; currIndex++ )
+ if( caption[currIndex] == QChar('\n') || caption[currIndex].isSpace() )
+ breakLine = true;
+
+ if (captionLineLocalLength <= (currIndex - captionIndex))
+ captionLineLocalLength = (currIndex - captionIndex);
+
+ breakLine = false;
+
+ for ( currIndex = captionIndex;
+ currIndex <= captionIndex + captionLineLocalLength &&
+ currIndex < caption.length() && !breakLine;
+ currIndex++ )
+ {
+ breakLine = (caption[currIndex] == QChar('\n')) ? true : false;
+
+ if (breakLine)
+ newLine.append( ' ' );
+ else
+ newLine.append( caption[currIndex] );
+ }
+
+ captionIndex = currIndex; // The line is ended
+
+ if ( captionIndex != caption.length() )
+ while ( !newLine.endsWith(" ") )
+ {
+ newLine.truncate(newLine.length() - 1);
+ captionIndex--;
+ }
+
+ captionByLines.prepend(newLine.stripWhiteSpace());
+ }
+
+ QFont font(m_font_name->currentFont());
+ font.setStyleHint(QFont::SansSerif);
+ font.setPixelSize( (int)(captionH * FONT_HEIGHT_RATIO) );
+ font.setWeight(QFont::Normal);
+
+ QFontMetrics fm( font );
+ int pixelsHigh = fm.height();
+
+ p.setFont(font);
+ p.setPen(m_font_color->color());
+ kdDebug( 51000 ) << "Number of lines " << (int)captionByLines.count() << endl;
+
+ // Now draw the caption
+ // TODO allow printing captions per photo and on top, bottom and vertically
+ for ( int lineNumber = 0; lineNumber < (int)captionByLines.count(); lineNumber++ )
+ {
+ if (lineNumber > 0)
+ p.translate(0, -(int)(pixelsHigh));
+ QRect r(0, 0, captionW, captionH);
+ p.drawText(r, Qt::AlignLeft, captionByLines[lineNumber], -1, &r);
+ }
+}
+
+
+
+QString FrmPrintWizard::captionFormatter(TPhoto *photo, const QString& format)
+{
+ QString str=format;
+
+ QFileInfo fi(photo->filename.path());
+ QString resolution;
+ QSize imageSize = photo->exiv2Iface()->getImageDimensions();
+ if (imageSize.isValid()) {
+ resolution = QString( "%1x%2" ).arg( imageSize.width()).arg( imageSize.height());
+ }
+ str.replace("\\n", "\n");
+
+ // %f filename
+ // %c comment
+ // %d date-time
+ // %t exposure time
+ // %i iso
+ // %r resolution
+ // %a aperture
+ // %l focal length
+ str.replace("%f", fi.fileName());
+ str.replace("%c", photo->exiv2Iface()->getExifComment());
+ str.replace("%d", KGlobal::locale()->formatDateTime(photo->exiv2Iface()->getImageDateTime(),
+ false, false));
+ str.replace("%t", photo->exiv2Iface()->getExifTagString("Exif.Photo.ExposureTime"));
+ str.replace("%i", photo->exiv2Iface()->getExifTagString("Exif.Photo.ISOSpeedRatings"));
+ str.replace("%r", resolution);
+ str.replace("%a", photo->exiv2Iface()->getExifTagString("Exif.Photo.FNumber"));
+ str.replace("%l", photo->exiv2Iface()->getExifTagString("Exif.Photo.FocalLength"));
+
+ return str;
+}
+
+bool FrmPrintWizard::paintOnePage(QPainter &p, QPtrList<TPhoto> photos, QPtrList<QRect> layouts,
+ int captionType, unsigned int &current, bool useThumbnails)
+{
+ Q_ASSERT(layouts.count() > 1);
+
+ if (photos.count() == 0) return true; // no photos => last photo
+
+ QRect *srcPage = layouts.at(0);
+ QRect *layout = layouts.at(1);
+
+ // scale the page size to best fit the painter
+ // size the rectangle based on the minimum image dimension
+ int destW = p.window().width();
+ int destH = p.window().height();
+
+ int srcW = srcPage->width();
+ int srcH = srcPage->height();
+ if (destW < destH)
+ {
+ destH = NINT((double)destW * ((double)srcH / (double)srcW));
+ if (destH > p.window().height())
+ {
+ destH = p.window().height();
+ destW = NINT((double)destH * ((double)srcW / (double)srcH));
+ }
+ }
+ else
+ {
+ destW = NINT((double)destH * ((double)srcW / (double)srcH));
+ if (destW > p.window().width())
+ {
+ destW = p.window().width();
+ destH = NINT((double)destW * ((double)srcH / (double)srcW));
+ }
+ }
+
+ double xRatio = (double)destW / (double)srcPage->width();
+ double yRatio = (double)destH / (double)srcPage->height();
+
+ int left = (p.window().width() - destW) / 2;
+ int top = (p.window().height() - destH) / 2;
+
+ // FIXME: may not want to erase the background page
+ p.eraseRect(left, top,
+ NINT((double)srcPage->width() * xRatio),
+ NINT((double)srcPage->height() * yRatio));
+
+ for(; current < photos.count(); current++)
+ {
+ TPhoto *photo = photos.at(current);
+ // crop
+ QImage img;
+ if (useThumbnails)
+ img = photo->thumbnail().convertToImage();
+ else
+ img = photo->loadPhoto();
+
+ // next, do we rotate?
+ if (photo->rotation != 0)
+ {
+ // rotate
+ QWMatrix matrix;
+ matrix.rotate(photo->rotation);
+ img = img.xForm(matrix);
+ }
+
+ if (useThumbnails)
+ {
+ // scale the crop region to thumbnail coords
+ double xRatio = 0.0;
+ double yRatio = 0.0;
+
+ if (photo->thumbnail().width() != 0)
+ xRatio = (double)photo->thumbnail().width() / (double) photo->width();
+ if (photo->thumbnail().height() != 0)
+ yRatio = (double)photo->thumbnail().height() / (double) photo->height();
+
+ int x1 = NINT((double)photo->cropRegion.left() * xRatio);
+ int y1 = NINT((double)photo->cropRegion.top() * yRatio);
+
+ int w = NINT((double)photo->cropRegion.width() * xRatio);
+ int h = NINT((double)photo->cropRegion.height() * yRatio);
+
+ img = img.copy(QRect(x1, y1, w, h));
+ }
+ else
+ img = img.copy(photo->cropRegion);
+
+ int x1 = NINT((double)layout->left() * xRatio);
+ int y1 = NINT((double)layout->top() * yRatio);
+ int w = NINT((double)layout->width() * xRatio);
+ int h = NINT((double)layout->height() * yRatio);
+
+ p.drawImage( QRect(x1 + left, y1 + top, w, h), img );
+
+ if (captionType > 0)
+ {
+ p.save();
+ QString caption;
+ QString format;
+ switch (captionType)
+ {
+ case FileNames:
+ format = "%f";
+ break;
+ case ExifDateTime:
+ format = "%d";
+ break;
+ case Comment:
+ format = "%c";
+ break;
+ case Free:
+ format = m_FreeCaptionFormat->text();
+ break;
+ default:
+ kdWarning( 51000 ) << "UNKNOWN caption type " << captionType << endl;
+ break;
+ }
+ caption = captionFormatter(photo, format);
+ kdDebug( 51000 ) << "Caption " << caption << endl;
+
+ // draw the text at (0,0), but we will translate and rotate the world
+ // before drawing so the text will be in the correct location
+ // next, do we rotate?
+ int captionW = w-2;
+ double ratio = m_font_size->value() * 0.01;
+ int captionH = (int)(QMIN(w, h) * ratio);
+
+ int exifOrientation = photo->exiv2Iface()->getImageOrientation();
+ int orientatation = photo->rotation;
+
+
+ //ORIENTATION_ROT_90_HFLIP .. ORIENTATION_ROT_270
+ if (exifOrientation == KExiv2Iface::KExiv2::ORIENTATION_ROT_90_HFLIP ||
+ exifOrientation == KExiv2Iface::KExiv2::ORIENTATION_ROT_90 ||
+ exifOrientation == KExiv2Iface::KExiv2::ORIENTATION_ROT_90_VFLIP ||
+ exifOrientation == KExiv2Iface::KExiv2::ORIENTATION_ROT_270)
+ orientatation = (photo->rotation + 270) % 360; // -90 degrees
+
+ if(orientatation == 90 || orientatation == 270)
+ {
+ captionW = h;
+ }
+ p.rotate(orientatation);
+ kdDebug( 51000 ) << "rotation " << photo->rotation << " orientation " << orientatation << endl;
+ int tx = left;
+ int ty = top;
+
+ switch(orientatation) {
+ case 0 : {
+ tx += x1 + 1;
+ ty += y1 + (h - captionH - 1);
+ break;
+ }
+ case 90 : {
+ tx = top + y1 + 1;
+ ty = -left - x1 - captionH - 1;
+ break;
+ }
+ case 180 : {
+ tx = -left - x1 - w + 1;
+ ty = -top -y1 - (captionH + 1);
+ break;
+ }
+ case 270 : {
+ tx = -top - y1 - h + 1;
+ ty = left + x1 + (w - captionH)- 1;
+ break;
+ }
+ }
+ p.translate(tx, ty);
+ printCaption(p, photo, captionW, captionH, caption);
+ p.restore();
+ } // caption
+
+ // iterate to the next position
+ layout = layouts.next();
+ if (layout == 0)
+ {
+ current++;
+ break;
+ }
+ }
+ // did we print the last photo?
+ return (current < photos.count());
+}
+
+
+// Like above, but outputs to an initialized QImage. UseThumbnails is
+// not an option.
+// We have to use QImage for saving to a file, otherwise we would have
+// to use a QPixmap, which will have the same bit depth as the display.
+// So someone with an 8-bit display would not be able to save 24-bit
+// images!
+bool FrmPrintWizard::paintOnePage(QImage &p, QPtrList<TPhoto> photos, QPtrList<QRect> layouts,
+ int captionType, unsigned int &current)
+{
+ Q_ASSERT(layouts.count() > 1);
+
+ QRect *srcPage = layouts.at(0);
+ QRect *layout = layouts.at(1);
+
+ // scale the page size to best fit the painter
+ // size the rectangle based on the minimum image dimension
+ int destW = p.width();
+ int destH = p.height();
+
+ int srcW = srcPage->width();
+ int srcH = srcPage->height();
+ if (destW < destH)
+ {
+ destH = NINT((double)destW * ((double)srcH / (double)srcW));
+ if (destH > p.height())
+ {
+ destH = p.height();
+ destW = NINT((double)destH * ((double)srcW / (double)srcH));
+ }
+ }
+ else
+ {
+ destW = NINT((double)destH * ((double)srcW / (double)srcH));
+ if (destW > p.width())
+ {
+ destW = p.width();
+ destH = NINT((double)destW * ((double)srcH / (double)srcW));
+ }
+ }
+
+ double xRatio = (double)destW / (double)srcPage->width();
+ double yRatio = (double)destH / (double)srcPage->height();
+
+ int left = (p.width() - destW) / 2;
+ int top = (p.height() - destH) / 2;
+
+
+ p.fill(0xffffff);
+
+ for(; current < photos.count(); current++)
+ {
+ TPhoto *photo = photos.at(current);
+ // crop
+ QImage img;
+ img = photo->loadPhoto();
+
+ // next, do we rotate?
+ if (photo->rotation != 0)
+ {
+ // rotate
+ QWMatrix matrix;
+ matrix.rotate(photo->rotation);
+ img = img.xForm(matrix);
+ }
+
+ img = img.copy(photo->cropRegion);
+
+ int x1 = NINT((double)layout->left() * xRatio);
+ int y1 = NINT((double)layout->top() * yRatio);
+ int w = NINT((double)layout->width() * xRatio);
+ int h = NINT((double)layout->height() * yRatio);
+
+ // We can use scaleFree because the crop frame should have the proper dimensions.
+ img = img.smoothScale(w, h, QImage::ScaleFree);
+ // don't have drawimage, so we copy the pixels over manually
+ for(int srcY = 0; srcY < img.height(); srcY++)
+ for(int srcX = 0; srcX < img.width(); srcX++)
+ {
+ p.setPixel(x1 + left + srcX, y1 + top + srcY, img.pixel(srcX, srcY));
+ }
+
+ if (captionType != NoCaptions)
+ {
+ // Now draw the caption
+ QString caption;
+ QString format;
+ switch (captionType)
+ {
+ case FileNames:
+ format = "%f";
+ break;
+ case ExifDateTime:
+ format = "%d";
+ break;
+ case Comment:
+ format = "%c";
+ break;
+ case Free:
+ format = m_FreeCaptionFormat->text();
+ break;
+ default:
+ kdWarning( 51000 ) << "UNKNOWN caption type " << captionType << endl;
+ break;
+ }
+ caption = captionFormatter(photo, format);
+ kdDebug( 51000 ) << "Caption " << caption << endl;
+
+ int captionW = w-2;
+ double ratio = m_font_size->value() * 0.01;
+ int captionH = (int)(QMIN(w, h) * ratio);
+
+ int exifOrientation = photo->exiv2Iface()->getImageOrientation();
+ int orientatation = photo->rotation;
+
+ //ORIENTATION_ROT_90_HFLIP .. ORIENTATION_ROT_270
+ if (exifOrientation == KExiv2Iface::KExiv2::ORIENTATION_ROT_90_HFLIP ||
+ exifOrientation == KExiv2Iface::KExiv2::ORIENTATION_ROT_90 ||
+ exifOrientation == KExiv2Iface::KExiv2::ORIENTATION_ROT_90_VFLIP ||
+ exifOrientation == KExiv2Iface::KExiv2::ORIENTATION_ROT_270)
+ orientatation = (photo->rotation + 270) % 360; // -90 degrees
+
+ if (orientatation == 90 || orientatation == 270)
+ {
+ captionW = h;
+ }
+
+ QPixmap pixmap(w-2, img.height()-2);
+ //TODO black is not ok if font is black...
+ pixmap.fill(Qt::black);
+ QPainter painter;
+ painter.begin(&pixmap);
+ painter.rotate(orientatation);
+ kdDebug( 51000 ) << "rotation " << photo->rotation << " orientation " << orientatation << endl;
+ int tx = left;
+ int ty = top;
+
+ switch(orientatation) {
+ case 0 : {
+ tx += x1 + 1;
+ ty += y1 + (h - captionH - 1);
+ break;
+ }
+ case 90 : {
+ tx = top + y1 + 1;
+ ty = -left - x1 - captionH - 1;
+ break;
+ }
+ case 180 : {
+ tx = -left - x1 - w + 1;
+ ty = -top -y1 - (captionH + 1);
+ break;
+ }
+ case 270 : {
+ tx = -top - y1 - h + 1;
+ ty = left + x1 + (w - captionH)- 1;
+ break;
+ }
+ }
+
+ painter.translate(tx, ty);
+ printCaption(painter, photo, captionW, captionH, caption);
+ painter.end();
+
+ // now put it on picture
+ QImage fontImage = pixmap.convertToImage();
+ QRgb black = QColor(0, 0, 0).rgb();
+ for(int srcY = 0; srcY < fontImage.height(); srcY++)
+ for(int srcX = 0; srcX < fontImage.width(); srcX++)
+ {
+ if (fontImage.pixel(srcX, srcY) != black)
+ p.setPixel(srcX, srcY, fontImage.pixel(srcX, srcY));
+ }
+ } // caption
+
+ // iterate to the next position
+ layout = layouts.next();
+ if (layout == 0)
+ {
+ current++;
+ break;
+ }
+ }
+ // did we print the last photo?
+ return (current < photos.count());
+}
+
+
+// update the pages to be printed and preview first/last pages
+void FrmPrintWizard::previewPhotos()
+{
+ // get the selected layout
+ TPhotoSize *s = m_photoSizes.at(ListPhotoSizes->currentItem());
+
+ int photoCount = m_photos.count();
+ // how many pages? Recall that the first layout item is the paper size
+ int photosPerPage = s->layouts.count() - 1;
+ int remainder = photoCount % photosPerPage;
+ int emptySlots = 0;
+ if (remainder > 0)
+ emptySlots = photosPerPage - remainder;
+ int pageCount = photoCount / photosPerPage;
+ if (emptySlots > 0)
+ pageCount++;
+
+ LblPhotoCount->setText(QString::number(photoCount));
+ LblSheetsPrinted->setText(QString::number(pageCount));
+ LblEmptySlots->setText(QString::number(emptySlots));
+
+ // photo previews
+ // preview the first page.
+ // find the first page of photos
+ int count = 0;
+ int page = 0;
+ unsigned int current = 0;
+ for (TPhoto *photo = m_photos.first(); photo != 0; photo = m_photos.next())
+ {
+ if (page == m_currentPreviewPage) {
+ photo->cropRegion.setRect(-1, -1, -1, -1);
+ photo->rotation = 0;
+ int w = s->layouts.at(count+1)->width();
+ int h = s->layouts.at(count+1)->height();
+ cropFrame->init(photo, w, h, s->autoRotate, false);
+ }
+ count++;
+ if (count >= photosPerPage)
+ {
+ if (page == m_currentPreviewPage)
+ break;
+ page++;
+ current += photosPerPage;
+ count = 0;
+ }
+ }
+
+ // send this photo list to the painter
+ QPixmap img(BmpFirstPagePreview->width(), BmpFirstPagePreview->height());
+ QPainter p;
+ p.begin(&img);
+ p.fillRect(0, 0, img.width(), img.height(), this->paletteBackgroundColor());
+ paintOnePage(p, m_photos, s->layouts, m_captions->currentItem(), current, true);
+ p.end();
+ BmpFirstPagePreview->setPixmap(img);
+ LblPreview->setText(i18n("Page ") + QString::number(m_currentPreviewPage + 1) + i18n(" of ") + QString::number(getPageCount()));
+ LblPreview->setText(i18n("Page %1 of %2").arg(m_currentPreviewPage + 1).arg(getPageCount()));
+
+ manageBtnPreviewPage();
+ manageBtnPrintOrder();
+}
+
+void FrmPrintWizard::ListPhotoSizes_highlighted ( int )
+{
+ m_currentPreviewPage = 0;
+ for (TPhoto *photo = m_photos.first(); photo != 0; photo = m_photos.next())
+ {
+ photo->cropRegion.setRect(-1, -1, -1, -1);
+ photo->rotation = 0;
+ }
+ previewPhotos();
+}
+
+void FrmPrintWizard::ListPhotoSizes_selected( QListBoxItem * )
+{
+ previewPhotos();
+}
+
+void FrmPrintWizard::manageBtnPreviewPage()
+{
+ BtnPreviewPageDown->setEnabled(true);
+ BtnPreviewPageUp->setEnabled(true);
+ if (m_currentPreviewPage == 0)
+ {
+ BtnPreviewPageDown->setEnabled(false);
+ }
+
+ if ((m_currentPreviewPage + 1) == getPageCount())
+ {
+ BtnPreviewPageUp->setEnabled(false);
+ }
+}
+
+void FrmPrintWizard::manageBtnPrintOrder()
+{
+ if (ListPrintOrder->currentItem() == -1)
+ return;
+
+ BtnPrintOrderDown->setEnabled(true);
+ BtnPrintOrderUp->setEnabled(true);
+ if (ListPrintOrder->currentItem() == 0)
+ {
+ BtnPrintOrderUp->setEnabled(false);
+ }
+ if (uint(ListPrintOrder->currentItem() + 1) == ListPrintOrder->count())
+ {
+ BtnPrintOrderDown->setEnabled(false);
+ }
+}
+
+void FrmPrintWizard::ListPhotoOrder_highlighted ( int index )
+{
+ EditCopies->blockSignals(true);
+ EditCopies->setValue ( m_photos.at(index)->copies );
+ EditCopies->blockSignals(false);
+
+ manageBtnPrintOrder();
+}
+
+void FrmPrintWizard::ListPrintOrder_selected( QListBoxItem * )
+{
+ int currentIndex = ListPrintOrder->currentItem();
+ EditCopies->blockSignals(true);
+ EditCopies->setValue ( m_photos.at(currentIndex)->copies );
+ EditCopies->blockSignals(false);
+
+ manageBtnPrintOrder();
+}
+
+void FrmPrintWizard::EditCopies_valueChanged( int copies )
+{
+ if (copies < 1)
+ return;
+
+ int currentIndex = ListPrintOrder->currentItem();
+ QString item = ListPrintOrder->selectedItem()->text();
+ TPhoto *pCurPhoto = m_photos.at(currentIndex);
+ KURL fileName = pCurPhoto->filename;
+
+ if ( pCurPhoto->copies >= copies )
+ {
+ // removing copies
+ if (pCurPhoto->copies == 1 || pCurPhoto->copies == copies)
+ return;
+
+ ListPrintOrder->blockSignals(true);
+ ListPrintOrder->setSelected (currentIndex, false);
+ for (int removing = pCurPhoto->copies - copies; removing >0 ;removing--)
+ {
+ for (unsigned int index = 0; index < ListPrintOrder->count(); index++)
+ {
+ if (ListPrintOrder->text(index) == item)
+ {
+ TPhoto *pPhoto = m_photos.at(index);
+ m_photos.remove(index);
+ delete (pPhoto);
+ ListPrintOrder->removeItem(index);
+ break;
+ }
+ }
+ }
+ ListPrintOrder->blockSignals(false);
+ currentIndex = -1;
+ }
+ else
+ {
+ // adding copies
+ for (int adding = copies - pCurPhoto->copies; adding >0 ;adding--)
+ {
+ TPhoto *pPhoto = new TPhoto(150);
+ pPhoto->filename = pCurPhoto->filename;
+ m_photos.insert(currentIndex, pPhoto);
+ ListPrintOrder->insertItem(pPhoto->filename.filename(), currentIndex);
+ }
+ }
+
+ LblPhotoCount->setText(QString::number(m_photos.count()));
+
+ int index = 0;
+ for (TPhoto *pPhoto = m_photos.first(); pPhoto != 0; pPhoto = m_photos.next(), index++)
+ {
+ if (pPhoto->filename == fileName)
+ {
+ pPhoto->copies = copies;
+ if (currentIndex == -1)
+ currentIndex = index;
+ }
+ }
+ ListPrintOrder->blockSignals(true);
+ ListPrintOrder->setCurrentItem(currentIndex);
+ ListPrintOrder->setSelected( currentIndex, true );
+ ListPrintOrder->blockSignals(false);
+ previewPhotos();
+}
+
+void FrmPrintWizard::removeGimpFiles()
+{
+ for(QStringList::Iterator it = m_gimpFiles.begin(); it != m_gimpFiles.end(); ++it)
+ {
+ if (QFile::exists(*it))
+ {
+ if (QFile::remove(*it) == false)
+ {
+ KMessageBox::sorry(this, i18n("Could not remove the Gimp's temporary files."));
+ break;
+ }
+ }
+ }
+}
+
+// this is called when Finish is clicked.
+void FrmPrintWizard::accept()
+{
+ saveSettings();
+
+ // if we output to Gimp, we need to remove the temp files
+ if (m_gimpFiles.count() > 0)
+ removeGimpFiles();
+ QDialog::accept();
+}
+
+// this is called when Cancel is clicked.
+void FrmPrintWizard::reject()
+{
+ m_cancelPrinting = true;
+ if (m_gimpFiles.count() > 0)
+ removeGimpFiles();
+ QDialog::reject();
+}
+
+void FrmPrintWizard::printPhotos(QPtrList<TPhoto> photos, QPtrList<QRect> layouts, KPrinter &printer)
+{
+ m_cancelPrinting = false;
+ LblPrintProgress->setText("");
+ PrgPrintProgress->setProgress(0);
+ PrgPrintProgress->setTotalSteps(photos.count());
+ this->finishButton()->setEnabled(false);
+ KApplication::kApplication()->processEvents();
+
+ QPainter p;
+ p.begin(&printer);
+
+ unsigned int current = 0;
+
+ bool printing = true;
+ while(printing)
+ {
+ printing = paintOnePage(p, photos, layouts, m_captions->currentItem(), current);
+ if (printing)
+ printer.newPage();
+ PrgPrintProgress->setProgress(current);
+ KApplication::kApplication()->processEvents();
+ if (m_cancelPrinting)
+ {
+ printer.abort();
+ return;
+ }
+ }
+ p.end();
+
+ this->finishButton()->setEnabled(true);
+ if (m_kjobviewer->isChecked())
+ if ( !m_Proc->start() )
+ kdDebug( 51000 ) << "Error running kjobviewr\n";
+ LblPrintProgress->setText(i18n("Complete. Click Finish to exit the Print Wizard."));
+}
+
+QStringList FrmPrintWizard::printPhotosToFile(QPtrList<TPhoto> photos, QString &baseFilename, TPhotoSize* layouts)
+{
+ Q_ASSERT(layouts->layouts.count() > 1);
+
+ m_cancelPrinting = false;
+ LblPrintProgress->setText("");
+ PrgPrintProgress->setProgress(0);
+ PrgPrintProgress->setTotalSteps(photos.count());
+ this->finishButton()->setEnabled(false);
+ KApplication::kApplication()->processEvents();
+
+ unsigned int current = 0;
+ int pageCount = 1;
+ bool printing = true;
+ QStringList files;
+
+ QRect *srcPage = layouts->layouts.at(0);
+
+ while (printing)
+ {
+ // make a pixmap to save to file. Make it just big enough to show the
+ // highest-dpi image on the page without losing data.
+ double dpi = layouts->dpi;
+ if (dpi == 0.0)
+ dpi = getMaxDPI(photos, layouts->layouts, current) * 1.1;
+ int w = NINT(srcPage->width() / 1000.0 * dpi);
+ int h = NINT(srcPage->height() / 1000.0 * dpi);
+ QImage *img = new QImage(w, h, 32);
+ if (!img)
+ break;
+
+ // save this page out to file
+ QString filename = baseFilename + QString::number(pageCount) + ".jpeg";
+ bool saveFile = true;
+ if (QFile::exists(filename))
+ {
+ int result = KMessageBox::warningYesNoCancel( this,
+ i18n("The following file will be overwritten. Do you want to overwrite this file?") +
+ "\n\n" + filename);
+ if (result == KMessageBox::No)
+ saveFile = false;
+ else if (result == KMessageBox::Cancel)
+ {
+ delete img;
+ break;
+ }
+ }
+
+ // paint this page, even if we aren't saving it to keep the page
+ // count accurate.
+ printing = paintOnePage(*img, photos, layouts->layouts, m_captions->currentItem(), current);
+
+ if (saveFile)
+ {
+ files.append(filename);
+ img->save(filename, "JPEG");
+ }
+ delete img;
+ pageCount++;
+
+ PrgPrintProgress->setProgress(current);
+ KApplication::kApplication()->processEvents();
+ if (m_cancelPrinting)
+ break;
+ }
+ this->finishButton()->setEnabled(true);
+ // did we cancel?
+ if (printing)
+ LblPrintProgress->setText(i18n("Printing Canceled."));
+ else
+ {
+ if (m_kjobviewer->isChecked())
+ if ( !m_Proc->start() )
+ kdDebug( 51000 ) << "Error launching kjobviewr\n";
+ LblPrintProgress->setText(i18n("Complete. Click Finish to exit the Print Wizard."));
+ }
+ return files;
+}
+
+void FrmPrintWizard::loadSettings()
+{
+ KSimpleConfig config("kipirc");
+ config.setGroup("PrintWizard");
+
+ //internal PageSize
+ PageSize pageSize = (PageSize)config.readNumEntry("PageSize", (int)A4); //Default A4
+ initPhotoSizes(pageSize);
+ CmbPaperSize->setCurrentItem(int(pageSize));
+
+ //Use Margins
+ m_fullbleed->setChecked(config.readBoolEntry("NoMargins", false));
+
+ // captions
+ int captions = config.readNumEntry("ImageCaptions", 0);
+ m_captions->setCurrentItem(captions);
+ // caption color
+ QColor defColor(Qt::yellow);
+ QColor color = config.readColorEntry("CaptionColor", &defColor);
+ m_font_color->setColor(color);
+ // caption font
+ QFont defFont("Sans Serif");
+ QFont font = config.readFontEntry ( "CaptionFont", &defFont);
+ m_font_name->setCurrentFont(font.family());
+ // caption size
+ int fontSize = config.readNumEntry("CaptionSize", 4);
+ m_font_size->setValue(fontSize);
+ // free caption
+ QString captionTxt = config.readEntry("FreeCaption");
+ m_FreeCaptionFormat->setText(captionTxt);
+ //enable right caption stuff
+ CaptionChanged(captions);
+
+ // set the last output path
+ QString outputPath = config.readPathEntry("OutputPath", EditOutputPath->text());
+ EditOutputPath->setText(outputPath);
+
+ // set the proper radio button
+ int id = config.readNumEntry("PrintOutput", GrpOutputSettings->id(RdoOutputPrinter));
+ GrpOutputSettings->setButton(id);
+
+ // photo size
+ QString photoSize = config.readEntry("PhotoSize");
+ QListBoxItem *item = ListPhotoSizes->findItem(photoSize);
+ if (item)
+ ListPhotoSizes->setCurrentItem(item);
+ else
+ ListPhotoSizes->setCurrentItem(0);
+
+ // kjobviewer
+ m_kjobviewer->setChecked(config.readBoolEntry("KjobViewer", true));
+}
+
+
+// save the current wizard settings
+void FrmPrintWizard::saveSettings()
+{
+ KSimpleConfig config("kipirc");
+ config.setGroup("PrintWizard");
+
+ config.writeEntry("PageSize", (int)m_pageSize);
+ config.writeEntry("NoMargins", m_fullbleed->isChecked());
+
+ // output
+ int output = 0;
+ if (RdoOutputPrinter->isChecked())
+ output = GrpOutputSettings->id(RdoOutputPrinter);
+ else
+ if (RdoOutputFile->isChecked())
+ output = GrpOutputSettings->id(RdoOutputFile);
+ else
+ if (RdoOutputGimp->isChecked())
+ output = GrpOutputSettings->id(RdoOutputGimp);
+ config.writeEntry("PrintOutput", output);
+
+ // image captions
+ config.writeEntry("ImageCaptions", m_captions->currentItem());
+ // caption color
+ config.writeEntry("CaptionColor", m_font_color->color());
+ // caption font
+ config.writeEntry ("CaptionFont", QFont(m_font_name->currentFont()));
+ // caption size
+ config.writeEntry("CaptionSize", m_font_size->value());
+ // free caption
+ config.writeEntry("FreeCaption", m_FreeCaptionFormat->text());
+
+ // output path
+ config.writePathEntry("OutputPath", EditOutputPath->text());
+
+ // photo size
+ config.writeEntry("PhotoSize", ListPhotoSizes->currentText());
+
+ // kjobviewer
+ config.writeEntry("KjobViewer", m_kjobviewer->isChecked());
+}
+
+void FrmPrintWizard::GrpOutputSettings_clicked(int id)
+{
+ this->nextButton()->setEnabled(false);
+ // disable next buttons when appropriate
+ if (id == GrpOutputSettings->id(RdoOutputPrinter))
+ this->nextButton()->setEnabled(true);
+ else
+ if (id == GrpOutputSettings->id(RdoOutputFile))
+ {
+ if (!EditOutputPath->text().isEmpty())
+ {
+ QFileInfo fileInfo(EditOutputPath->text());
+ if (fileInfo.exists() && fileInfo.isDir())
+ this->nextButton()->setEnabled(true);
+ }
+ }
+ else
+ if (id == GrpOutputSettings->id(RdoOutputGimp))
+ {
+ this->nextButton()->setEnabled(true);
+ }
+}
+
+void FrmPrintWizard::BtnBrowseOutputPath_clicked( void )
+{
+ QString newPath = KFileDialog::getExistingDirectory(EditOutputPath->text(), this, "Select Output Folder");
+ if (newPath.isEmpty())
+ return;
+ // assume this directory exists
+ EditOutputPath->setText(newPath);
+ GrpOutputSettings_clicked(GrpOutputSettings->id(GrpOutputSettings->selected()));
+}
+
+
+void FrmPrintWizard::CaptionChanged(int captionUsed)
+{
+ switch (captionUsed)
+ {
+ case NoCaptions:
+ // disable m_font_frame and mFreeOutputFormat
+ m_font_frame->setEnabled(false);
+ m_FreeCaptionFormat->setEnabled(false);
+ m_free_label->setEnabled(false);
+ break;
+
+ case Free:
+ m_font_frame->setEnabled(true);
+ m_FreeCaptionFormat->setEnabled(true);
+ m_free_label->setEnabled(true);
+ break;
+
+ case FileNames:
+ case ExifDateTime:
+ case Comment:
+ default:
+ // disable mFreeOutputFormat
+ m_font_frame->setEnabled(true);
+ m_FreeCaptionFormat->setEnabled(false);
+ m_free_label->setEnabled(false);
+ break;
+ }
+
+}
+
+
+
+void FrmPrintWizard::EditOutputPath_textChanged(const QString &)
+{
+ GrpOutputSettings_clicked(GrpOutputSettings->id(GrpOutputSettings->selected()));
+}
+
+void FrmPrintWizard::CmbPaperSize_activated( int index )
+{
+ PageSize pageSize = (PageSize)index;
+ initPhotoSizes(pageSize);
+
+ if (pageSize > A6)
+ {
+ KMessageBox::information (this,
+ i18n("Don't forget to set up the correct page size according to your printer settings"),
+ i18n("Page size settings"), "pageSizeInfo");
+ }
+}
+
+void FrmPrintWizard::BtnPrintOrderUp_clicked() {
+ if (ListPrintOrder->currentItem() == 0)
+ return;
+
+ int currentIndex = ListPrintOrder->currentItem();
+ QString item1 = ListPrintOrder->selectedItem()->text();
+ QString item2 = ListPrintOrder->item(currentIndex - 1)->text();
+
+ // swap these items
+ ListPrintOrder->changeItem(item2, currentIndex);
+ ListPrintOrder->changeItem(item1, currentIndex - 1);
+
+ // the list box items are swapped, now swap the items in the photo list
+ TPhoto *photo1 = m_photos.at(currentIndex);
+ TPhoto *photo2 = m_photos.at(currentIndex - 1);
+ m_photos.remove(currentIndex - 1);
+ m_photos.remove(currentIndex - 1);
+ m_photos.insert(currentIndex - 1, photo2);
+ m_photos.insert(currentIndex - 1, photo1);
+ previewPhotos();
+}
+
+void FrmPrintWizard::BtnPrintOrderDown_clicked() {
+ if (ListPrintOrder->currentItem() == (signed int)ListPrintOrder->count() - 1)
+ return;
+
+ int currentIndex = ListPrintOrder->currentItem();
+ QString item1 = ListPrintOrder->selectedItem()->text();
+ QString item2 = ListPrintOrder->item(currentIndex + 1)->text();
+
+ // swap these items
+ ListPrintOrder->changeItem(item2, currentIndex);
+ ListPrintOrder->changeItem(item1, currentIndex + 1);
+
+ // the list box items are swapped, now swap the items in the photo list
+ TPhoto *photo1 = m_photos.at(currentIndex);
+ TPhoto *photo2 = m_photos.at(currentIndex + 1);
+ m_photos.remove(currentIndex);
+ m_photos.remove(currentIndex);
+ m_photos.insert(currentIndex, photo1);
+ m_photos.insert(currentIndex, photo2);
+ previewPhotos();
+}
+
+void FrmPrintWizard::BtnPreviewPageDown_clicked() {
+ if (m_currentPreviewPage == 0)
+ return;
+ m_currentPreviewPage--;
+ previewPhotos();
+}
+void FrmPrintWizard::BtnPreviewPageUp_clicked() {
+ if (m_currentPreviewPage == getPageCount() - 1)
+ return;
+ m_currentPreviewPage++;
+ previewPhotos();
+}
+
+// create a MxN grid of photos, fitting on the page
+TPhotoSize * createPhotoGrid(int pageWidth, int pageHeight, QString label, int rows, int columns) {
+ int MARGIN = (int)((pageWidth + pageHeight) / 2 * 0.04 + 0.5);
+ int GAP = MARGIN / 4;
+ int photoWidth = (pageWidth - (MARGIN * 2) - ((columns-1) * GAP)) / columns;
+ int photoHeight = (pageHeight - (MARGIN * 2) - ((rows-1) * GAP)) / rows;
+
+ TPhotoSize *p = new TPhotoSize;
+ p->label = label;
+ p->dpi = 100;
+ p->autoRotate = false;
+ p->layouts.append(new QRect(0, 0, pageWidth, pageHeight));
+
+ int row = 0;
+ for(int y=MARGIN; row < rows && y < pageHeight - MARGIN; y += photoHeight + GAP) {
+ int col = 0;
+ for(int x=MARGIN; col < columns && x < pageWidth - MARGIN; x += photoWidth + GAP) {
+ p->layouts.append(new QRect(x, y, photoWidth, photoHeight));
+ col++;
+ }
+ row++;
+ }
+ return p;
+}
+
+void FrmPrintWizard::initPhotoSizes(PageSize pageSize)
+{
+ // don't refresh anything if we haven't changed page sizes.
+ if (pageSize == m_pageSize)
+ return;
+
+ m_pageSize = pageSize;
+
+ // cleanng m_pageSize memory before invoking clear()
+ for(unsigned int i=0; i < m_photoSizes.count(); i++)
+ if (m_photoSizes.at(i))
+ delete m_photoSizes.at(i);
+ m_photoSizes.clear();
+
+ switch (pageSize)
+ {
+ // ====================== LETTER SIZE =====================
+ case Letter:
+ {
+ TPhotoSize *p;
+ // ========== 5 x 3.5
+ p = new TPhotoSize;
+ p->label = i18n("3.5 x 5\"");
+ p->dpi = 0;
+ p->autoRotate = true;
+ // page size
+ p->layouts.append(new QRect(0, 0, 8500, 11000));
+ // photo layouts
+ p->layouts.append(new QRect( 700, 500, 3500, 5000));
+ p->layouts.append(new QRect(4300, 500, 3500, 5000));
+ p->layouts.append(new QRect( 700, 5600, 3500, 5000));
+ p->layouts.append(new QRect(4300, 5600, 3500, 5000));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 4 x 6
+ p = new TPhotoSize;
+ p->label = i18n("4 x 6\"");
+ p->dpi = 0;
+ p->autoRotate = true;
+ // page size
+ p->layouts.append(new QRect(0, 0, 8500, 11000));
+ // photo layouts
+ p->layouts.append(new QRect( 225, 500, 4000, 6000));
+ p->layouts.append(new QRect(4275, 500, 4000, 6000));
+ p->layouts.append(new QRect(1250, 6600, 6000, 4000));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 4 x 6 Album
+ p = new TPhotoSize;
+ p->label = i18n("4 x 6\" Album");
+ p->dpi = 0;
+ p->autoRotate = true;
+ // page size
+ p->layouts.append(new QRect(0, 0, 8500, 11000));
+ // photo layouts
+ p->layouts.append(new QRect( 1250, 1000, 6000, 4000));
+ p->layouts.append(new QRect( 1250, 6000, 6000, 4000));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 5 x 7
+ p = new TPhotoSize;
+ p->label = i18n("5 x 7\"");
+ p->dpi = 0;
+ p->autoRotate = true;
+ // page size
+ p->layouts.append(new QRect(0, 0, 8500, 11000));
+ // photo layouts
+ p->layouts.append(new QRect( 750, 500, 7000, 5000));
+ p->layouts.append(new QRect( 750, 5750, 7000, 5000));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 8 x 10
+ p = new TPhotoSize;
+ p->label = i18n("8 x 10\"");
+ p->dpi = 0;
+ p->autoRotate = true;
+ // page size
+ p->layouts.append(new QRect(0, 0, 8500, 11000));
+ // photo layouts
+ p->layouts.append(new QRect(250, 500, 8000, 10000));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // thumbnails
+ m_photoSizes.append(createPhotoGrid(8500, 11000, i18n("Thumbnails"), 5, 4));
+
+ // small thumbnails
+ m_photoSizes.append(createPhotoGrid(8500, 11000, i18n("Small Thumbnails"), 6, 5));
+
+ // album collage 1
+ p = new TPhotoSize;
+ p->label = i18n("Album Collage 1 (9 photos)");
+ p->dpi = 0;
+ p->autoRotate = false;
+ // page size
+ p->layouts.append(new QRect(0, 0, 8500, 11000));
+ // photo layouts
+ // photo 1 is in the center, 3x4.5
+ p->layouts.append(new QRect(2750, 3250, 3000, 4500));
+ // the remaining 1.5x2 photos begin with upper left and circle around
+ // top row
+ p->layouts.append(new QRect(750, 750, 1500, 2000));
+ p->layouts.append(new QRect(3500, 750, 1500, 2000));
+ p->layouts.append(new QRect(6250, 750, 1500, 2000));
+ p->layouts.append(new QRect(6250, 4500, 1500, 2000));
+ p->layouts.append(new QRect(6250, 8250, 1500, 2000));
+ p->layouts.append(new QRect(3500, 8250, 1500, 2000));
+ p->layouts.append(new QRect(750, 8250, 1500, 2000));
+ p->layouts.append(new QRect(750, 4500, 1500, 2000));
+ m_photoSizes.append(p);
+
+ // album collage 2
+ p = new TPhotoSize;
+ p->label = i18n("Album Collage 2 (6 photos)");
+ p->dpi = 0;
+ p->autoRotate = false;
+ // page size
+ p->layouts.append(new QRect(0, 0, 8500, 11000));
+ // photo layouts
+ p->layouts.append(new QRect(1000, 1000, 3000, 3000));
+ p->layouts.append(new QRect(5000, 1000, 2500, 1250));
+ p->layouts.append(new QRect(5000, 2750, 2500, 1250));
+ p->layouts.append(new QRect(1000, 5000, 1500, 2000));
+ p->layouts.append(new QRect(2750, 5000, 4750, 2000));
+ p->layouts.append(new QRect(1000, 8000, 6500, 2000));
+ m_photoSizes.append(p);
+ } // letter
+ break;
+
+ // ====================== A4 SIZE =====================
+ case A4:
+ {
+ // A4 is 21 x 29.7cm
+ TPhotoSize *p;
+
+ // ========== 20x25cm
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("21 x 29.7cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 2100, 2970));
+ // photo layouts
+ p->layouts.append(new QRect( 0, 0, 2100, 2970));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 6x9 cm - 8 photos
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("6 x 9cm (8 photos)");
+ // page size
+ p->layouts.append(new QRect(0, 0, 2100, 2970));
+ // photo layouts
+ p->layouts.append(new QRect( 100, 100, 900, 600));
+ p->layouts.append(new QRect(1100, 100, 900, 600));
+ p->layouts.append(new QRect( 100, 800, 900, 600));
+ p->layouts.append(new QRect(1100, 800, 900, 600));
+ p->layouts.append(new QRect( 100, 1500, 900, 600));
+ p->layouts.append(new QRect(1100, 1500, 900, 600));
+ p->layouts.append(new QRect( 100, 2200, 900, 600));
+ p->layouts.append(new QRect(1100, 2200, 900, 600));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 9x13
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("9 x 13cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 2100, 2970));
+ // photo layouts
+ p->layouts.append(new QRect( 100, 100, 900, 1300));
+ p->layouts.append(new QRect(1100, 100, 900, 1300));
+ p->layouts.append(new QRect( 100, 1500, 900, 1300));
+ p->layouts.append(new QRect(1100, 1500, 900, 1300));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 10x13.33cm
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("10 x 13.33cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 2100, 2970));
+ // photo layouts
+ p->layouts.append(new QRect( 50, 100, 1000, 1333));
+ p->layouts.append(new QRect(1060, 100, 1000, 1333));
+ p->layouts.append(new QRect( 50, 1500, 1000, 1333));
+ p->layouts.append(new QRect(1060, 1500, 1000, 1333));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 10x15cm
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("10 x 15cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 2100, 2970));
+ // photo layouts
+ p->layouts.append(new QRect( 50, 150, 1000, 1500));
+ p->layouts.append(new QRect(1060, 150, 1000, 1500));
+ p->layouts.append(new QRect( 300, 1750, 1500, 1000));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 10x15cm album
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("10 x 15cm Album");
+ // page size
+ p->layouts.append(new QRect(0, 0, 2100, 2970));
+ // photo layouts
+ p->layouts.append(new QRect( 300, 350, 1500, 1000));
+ p->layouts.append(new QRect( 300, 1620, 1500, 1000));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 11.5x15cm album
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("11.5 x 15cm Album");
+ // page size
+ p->layouts.append(new QRect(0, 0, 2100, 2970));
+ // photo layouts
+ p->layouts.append(new QRect( 300, 250, 1500, 1100));
+ p->layouts.append(new QRect( 300, 1570, 1500, 1100));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 13x18cm
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("13 x 18cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 2100, 2970));
+ // photo layouts
+ p->layouts.append(new QRect( 150, 150, 1800, 1300));
+ p->layouts.append(new QRect( 150, 1520, 1800, 1300));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 20x25cm
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("20 x 25cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 2100, 2970));
+ // photo layouts
+ p->layouts.append(new QRect( 50, 230, 2000, 2500));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // thumbnails
+ m_photoSizes.append(createPhotoGrid(2100, 2970, i18n("Thumbnails"), 5, 4));
+
+ // small thumbnails
+ m_photoSizes.append(createPhotoGrid(2100, 2970, i18n("Small Thumbnails"), 6, 5));
+ } // A4
+ break;
+
+ // ====================== A6 SIZE =====================
+ case A6:
+ {
+ // A6 is 10.5 x 14.8 cm
+ TPhotoSize *p;
+ // ========== 9x13
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("9 x 13cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 1050, 1480));
+ // photo layouts
+ p->layouts.append(new QRect( 50, 100, 900, 1300));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 10x15cm
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("10.5 x 14.8cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 1050, 1480));
+ // photo layouts
+ p->layouts.append(new QRect(0, 0, 1050, 1480));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // thumbnails
+ m_photoSizes.append(createPhotoGrid(1050, 1480, i18n("Thumbnails"), 5, 4));
+
+ // small thumbnails
+ m_photoSizes.append(createPhotoGrid(1050, 1480, i18n("Small Thumbnails"), 6, 5));
+ } // A6
+ break;
+
+ // ====================== 10x15cm SIZE =====================
+ case P10X15:
+ {
+ // 10x15cm photo paper is 4x6" so the right size is 10.16 x 15.24 cm
+ TPhotoSize *p;
+ // ========== 10x15cm
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("10 x 15cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 1016, 1524));
+ // photo layouts
+ p->layouts.append(new QRect(0, 0, 1016, 1524));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 9x13
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("9 x 13cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 1016, 1524));
+ // photo layouts
+ p->layouts.append(new QRect( 50, 100, 900, 1300));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // thumbnails
+ m_photoSizes.append(createPhotoGrid(1016, 1524, i18n("Thumbnails"), 5, 4));
+
+ // small thumbnails
+ m_photoSizes.append(createPhotoGrid(1016, 1524, i18n("Small Thumbnails"), 6, 5));
+
+ } // 10x15 cm
+ break;
+
+ // ====================== 13x18cm SIZE =====================
+ case P13X18:
+ {
+ // 10x18cm photo paper is 5x7" so the right conversion
+ // is 12.7 x 17.78 cm
+ TPhotoSize *p;
+ // ========== 10x15cm
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("13 x 18cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 1270, 1778));
+ // photo layouts
+ p->layouts.append(new QRect(0, 0, 1270, 1778));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 10x15cm
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("10 x 15cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 1270, 1778));
+ // photo layouts
+ p->layouts.append(new QRect(0, 0, 1016, 1524));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // ========== 9x13
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = true;
+ p->label = i18n("9 x 13cm");
+ // page size
+ p->layouts.append(new QRect(0, 0, 1270, 1778));
+ // photo layouts
+ p->layouts.append(new QRect( 50, 100, 900, 1300));
+ // add to the list
+ m_photoSizes.append(p);
+
+ // thumbnails
+ m_photoSizes.append(createPhotoGrid(1270, 1778, i18n("Thumbnails"), 5, 4));
+
+ // small thumbnails
+ m_photoSizes.append(createPhotoGrid(1270, 1778, i18n("Small Thumbnails"), 6, 5));
+
+ } // 13x18 cm
+ break;
+
+ default:
+ {
+ kdDebug( 51000 ) << "Initializing Unsupported page layouts\n";
+ // We don't support this page size yet. Just create a default page.
+ TPhotoSize *p;
+ p = new TPhotoSize;
+ p->dpi = 0;
+ p->autoRotate = false;
+ p->label = i18n("Unsupported Paper Size");
+ // page size
+ p->layouts.append(new QRect(0, 0, 8500, 11000));
+ p->layouts.append(new QRect(0, 0, 8500, 11000));
+ // add to the list
+ m_photoSizes.append(p);
+ }
+ break;
+ };
+
+ // load the photo sizes into the listbox
+ ListPhotoSizes->clear();
+ for (TPhotoSize *s = m_photoSizes.first(); s != 0; s = m_photoSizes.next())
+ ListPhotoSizes->insertItem(s->label);
+ ListPhotoSizes->setCurrentItem(0);
+}
+
+} // NameSpace KIPIPrintWizardPlugin
+
diff --git a/kipi-plugins/printwizard/frmprintwizard.h b/kipi-plugins/printwizard/frmprintwizard.h
new file mode 100644
index 0000000..2eb25e1
--- /dev/null
+++ b/kipi-plugins/printwizard/frmprintwizard.h
@@ -0,0 +1,154 @@
+/***************************************************************************
+ frmprintwizard.h - description
+ -------------------
+ begin : Mon Sep 30 2002
+ copyright : (C) 2002 by Todd Shoemaker
+ email : jtshoe11@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 FRMPRINTWIZARD_H
+#define FRMPRINTWIZARD_H
+
+// Qt includes.
+
+#include <qwidget.h>
+
+// KDE includes.
+
+#include <kprinter.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "tphoto.h"
+#include "frmprintwizardbase.h"
+
+class QPushButton;
+class KProcess;
+
+namespace KIPIPrintWizardPlugin
+{
+
+class FrmPrintWizardBase;
+
+typedef struct _TPhotoSize {
+ QString label;
+ int dpi;
+ bool autoRotate;
+ QPtrList<QRect> layouts; // first element is page size
+} TPhotoSize;
+
+class FrmPrintWizard : public FrmPrintWizardBase
+{
+ Q_OBJECT
+
+private:
+
+ enum PageSize {
+ Unknown = -1,
+ Letter = 0,
+ A4,
+ A6,
+ P10X15,
+ P13X18
+ };
+
+ enum AvailableCaptions {
+ NoCaptions = 0,
+ FileNames,
+ ExifDateTime,
+ Comment,
+ Free
+ };
+
+ QPtrList<TPhoto> m_photos;
+ QPtrList<TPhotoSize> m_photoSizes;
+
+ PageSize m_pageSize;
+ KProcess *m_Proc;
+ QString m_tempPath;
+
+ int m_currentPreviewPage;
+ QStringList m_gimpFiles;
+
+ QPushButton *m_helpButton;
+
+ bool m_cancelPrinting;
+
+ KIPIPlugins::KPAboutData *m_about;
+
+ void updateCropFrame(TPhoto *, int);
+ void setBtnCropEnabled();
+ void removeGimpFiles();
+ void initPhotoSizes(PageSize pageSize);
+ void previewPhotos();
+ void printPhotos(QPtrList<TPhoto> photos, QPtrList<QRect> layouts, KPrinter &printer);
+ QStringList printPhotosToFile(QPtrList<TPhoto> photos, QString &baseFilename, TPhotoSize *layouts);
+ void loadSettings();
+ void saveSettings();
+
+ int getPageCount();
+
+ QString captionFormatter(TPhoto *photo, const QString& format);
+ void printCaption(QPainter &p, TPhoto*photo, int captionW, int captionH, QString caption);
+
+ bool paintOnePage(QPainter &p, QPtrList<TPhoto> photos, QPtrList<QRect> layouts,
+ int captionType, unsigned int &current, bool useThumbnails = false);
+
+ bool paintOnePage(QImage &p, QPtrList<TPhoto> photos, QPtrList<QRect> layouts,
+ int captionType, unsigned int &current);
+
+ void manageBtnPrintOrder();
+ void manageBtnPreviewPage();
+
+public:
+
+ FrmPrintWizard(QWidget *parent=0, const char *name=0);
+ ~FrmPrintWizard();
+ void print( KURL::List fileList, QString tempPath);
+ QRect * getLayout(int photoIndex);
+
+public slots:
+
+ void BtnCropRotate_clicked();
+ void BtnCropNext_clicked();
+ void BtnCropPrev_clicked();
+ void FrmPrintWizardBaseSelected(const QString &);
+ void ListPhotoSizes_selected( QListBoxItem * );
+ void ListPhotoSizes_highlighted ( int );
+ void ListPrintOrder_selected( QListBoxItem * );
+ void ListPhotoOrder_highlighted ( int );
+ void EditCopies_valueChanged( int );
+ void GrpOutputSettings_clicked(int id);
+ void EditOutputPath_textChanged(const QString &);
+ void CaptionChanged( int );
+ void BtnBrowseOutputPath_clicked();
+ void CmbPaperSize_activated( int );
+
+ void BtnPrintOrderUp_clicked();
+ void BtnPrintOrderDown_clicked();
+
+ void BtnPreviewPageDown_clicked();
+ void BtnPreviewPageUp_clicked();
+
+protected slots:
+
+ void accept();
+ void reject();
+ void slotHelp();
+};
+
+} // NameSpace KIPIPrintWizardPlugin
+
+
+#endif // FRMPRINTWIZARD_H
+
diff --git a/kipi-plugins/printwizard/frmprintwizardbase.ui b/kipi-plugins/printwizard/frmprintwizardbase.ui
new file mode 100644
index 0000000..a353296
--- /dev/null
+++ b/kipi-plugins/printwizard/frmprintwizardbase.ui
@@ -0,0 +1,2330 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KIPIPrintWizardPlugin::FrmPrintWizardBase</class>
+<widget class="QWizard">
+ <property name="name">
+ <cstring>FrmPrintWizardBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>776</width>
+ <height>627</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Print Wizard</string>
+ </property>
+ <property name="titleFont">
+ <font>
+ <pointsize>16</pointsize>
+ </font>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>pgWelcome</cstring>
+ </property>
+ <attribute name="title">
+ <string>Welcome to the Print Wizard</string>
+ </attribute>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout53</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>730</width>
+ <height>522</height>
+ </rect>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout24</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>PixmapLabel1_4</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>300</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>Line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>VLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout52</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Welcome to the Print Wizard. This wizard will walk you through the process of printing your photos.
+
+Click the 'Next' button to begin.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>381</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>pgPrinter</cstring>
+ </property>
+ <attribute name="title">
+ <string>Select Printer</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout88</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>PixmapLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>471</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout87</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>4</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Page Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout37</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout36</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Paper size:</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <item>
+ <property name="text">
+ <string>Letter</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>A4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>A6</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>10x15cm</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>13x17cm</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>CmbPaperSize</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout36</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer19</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>210</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_fullbleed</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>No margins</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Full-bleed mode</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Full-bleed mode</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout86</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_imageCaptions</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Image Captions</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KComboBox">
+ <item>
+ <property name="text">
+ <string>No captions</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Image file names</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Exif date-time</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Comments</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Free</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_captions</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>m_FreeCaptionFormat</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>%d %c</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_free_label</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>110</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>%f filename %t exposure time
+%c comment %i iso
+%d date-time %r resolution
+%a aperture %l focal length
+\n newline</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_font_frame</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Caption font</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Choose the caption font size</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KFontCombo">
+ <property name="name">
+ <cstring>m_font_name</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KColorCombo">
+ <property name="name">
+ <cstring>m_font_color</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="insertionPolicy">
+ <enum>NoInsertion</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout37</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Size</string>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>m_font_size</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minValue">
+ <number>2</number>
+ </property>
+ <property name="maxValue">
+ <number>8</number>
+ </property>
+ <property name="lineStep">
+ <number>2</number>
+ </property>
+ <property name="pageStep">
+ <number>2</number>
+ </property>
+ <property name="value">
+ <number>4</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>GrpOutputSettings</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Output Settings</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>RdoOutputPrinter</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Output to printer</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout24</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>RdoOutputGimp</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Open image using Gimp</string>
+ </property>
+ </widget>
+ <widget class="KURLLabel">
+ <property name="name">
+ <cstring>KURLLabel1</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="pixmap">
+ <pixmap>image1</pixmap>
+ </property>
+ <property name="url" stdset="0">
+ <string>http://www.gimp.org</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Visit Gimp website (www.gimp.org) using external browser</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer16</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>RdoOutputFile</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Output to image file</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout23</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>19</width>
+ <height>26</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>This wizard will output each page to this folder with the filename kipi_printwizard_1, kipi_printwizard_2, etc.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout23</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>19</width>
+ <height>26</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>EditOutputPath</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>BtnBrowseOutputPath</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Browse...</string>
+ </property>
+ <property name="accel">
+ <string>Alt+B</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>pgLayout</cstring>
+ </property>
+ <attribute name="title">
+ <string>Select Photo Layout</string>
+ </attribute>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout16</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>PixmapLabel3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="pixmap">
+ <pixmap>image2</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer10</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>Line3_2_3</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>VLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout113</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout88</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout86</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Select the photo size to print</string>
+ </property>
+ </widget>
+ <widget class="KListBox">
+ <item>
+ <property name="text">
+ <string>Photo Sizes</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>ListPhotoSizes</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>200</height>
+ </size>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout87</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Print Summary</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout90</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel4_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Photos:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>LblPhotoCount</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&lt;p align="right"&gt;0&lt;/p&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter|AlignLeft</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout91</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Sheets:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>LblSheetsPrinted</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&lt;p align="right"&gt;0&lt;/p&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter|AlignLeft</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout92</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel6</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Empty slots:</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>LblEmptySlots</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&lt;p align="right"&gt;0&lt;/p&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter|AlignLeft</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer50</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>105</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Print Order</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QListBox">
+ <item>
+ <property name="text">
+ <string>New Item</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>ListPrintOrder</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout112</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>BtnPrintOrderUp</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ </font>
+ </property>
+ <property name="text">
+ <string>Up</string>
+ <comment>Move Up</comment>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Move Up selected photo</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Move Up selected photo</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer20</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>80</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>BtnPrintOrderDown</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ </font>
+ </property>
+ <property name="text">
+ <string>Down</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Move Down selected photo</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Move Down selected photo</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout75</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>LblCopies_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Number of times to print selected photo:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>EditCopies</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Number of copies of selected photo</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Number of copies of selected photo</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout40</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox6</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>LblPreview</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Preview</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout37</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer26</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>BmpFirstPagePreview</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>260</width>
+ <height>367</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>260</width>
+ <height>367</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="pixmap">
+ <pixmap>image3</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer27</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout35</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>BtnPreviewPageDown</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&lt;</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Previous photo</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Previous photo</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer20_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>161</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>BtnPreviewPageUp</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&gt;</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Next page</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Next page</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer21</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>pgCrop</cstring>
+ </property>
+ <attribute name="title">
+ <string>Crop Photos</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout110</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>PixmapLabel1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="pixmap">
+ <pixmap>image4</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel8</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Move the box below to tell to this wizard how to crop the photos to fit inside the photo sizes you have given. You can crop each image differently, or just click 'Next' to use the default center cropping for each photo.</string>
+ </property>
+ <property name="textFormat">
+ <enum>AutoText</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop|AlignLeft</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel10</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Click and Drag the mouse</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout121</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer70</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>41</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout119</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIPIPrintWizardPlugin::CropFrame">
+ <property name="name">
+ <cstring>cropFrame</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>200</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout118</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>BtnCropRotate</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Rotate</string>
+ </property>
+ <property name="accel">
+ <string>Alt+R</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Rotate photo</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Rotate photo</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer12</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>127</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>BtnCropPrev</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;&lt; Pr&amp;evious</string>
+ </property>
+ <property name="accel">
+ <string>Alt+E</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Previous photo</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Previous photo</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>BtnCropNext</cstring>
+ </property>
+ <property name="text">
+ <string>Ne&amp;xt &gt;&gt;</string>
+ </property>
+ <property name="accel">
+ <string>Alt+X</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Next photo</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Next photo</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer13</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>127</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>LblCropPhoto</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Photo 0 of 0</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer69</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>41</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>pgPrint</cstring>
+ </property>
+ <attribute name="title">
+ <string>Print</string>
+ </attribute>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout62</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>11</y>
+ <width>742</width>
+ <height>520</height>
+ </rect>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout61</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>PixmapLabel1_3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer3_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>438</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>Line3_2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>VLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout60</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer13_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>70</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>LblPrintClickFinish</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Click the Next button to print.</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop|AlignHCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer22</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>361</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout35</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer18</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>360</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_kjobviewer</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Printer job viewer</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>pgFinished</cstring>
+ </property>
+ <attribute name="title">
+ <string>Printing</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout55</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout18_2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>PixmapLabel1_3_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer3_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>0</width>
+ <height>289</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>Line3_2_2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>VLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout54</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer13_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>70</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KProgress">
+ <property name="name">
+ <cstring>PrgPrintProgress</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>LblPrintProgress</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Complete. Click Finish to exit the Print Wizard.</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop|AlignHCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer23</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>41</width>
+ <height>371</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KIPIPrintWizardPlugin::CropFrame</class>
+ <header location="local">cropframe.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image5</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="2126">89504e470d0a1a0a0000000d49484452000000300000003008060000005702f98700000815494441546881d59a3f681cd91dc73f3aa6f80dc8300b17d096812be290c2965de4cedd1d294e22814839832dc585250cd13a86444a0adff90ad95111e42b4ce4e2b02e452419ecac0e72d8cd1135216e02b68b60a538900bc10ace30532cbc570c6c8af767de8c66add54576f003f1db9d999df97dbfbf3feffbde68e8d1a347bcc9e3adffb703ffeb78e301447507d796667a3a0789e0a8ecf4d5d5a1570160a85f0dac2db57a2b1bff341073fa580d91188ba0d0c408a0015039c491b10b173e60faeaca9183e89b42d35757865ae74f592741d559ca36a6fff1e52f1eb0b634d37b6d00fcb00cc781354e098075ba603a8e08ce17a0e2da647dc500a6afae0ecd4c9c020667baeeb8b3cb5ffc9d3b8b471b8503232051c03455c643a65d0d50aa95a2268c75f77b6d004c2d9c2931dc97e9bcf84ee53cf6fcf2e7ed23ad8581e78130f77db7b191f0162064dc16bc8fc82b18030350ba7f6e87e7a94440e7ca58ad4adf8f6a0c0460faeaead0c2c5f112e36614b9ede783d279105b3d12c5e8dcd8d70e0040d7e5b4b37971de331edadc58b1df976ffff5c8bad1c0004cf708735b2a4c3b1b30ed9c86b2b5a08f62f4951275636d69a677e3f307848dd0395bb255676d7a49243e52972f4eb2dd6dec93272bb70e27370edd1b4a5d3c643aa2d679e7b4b740a63510430e133f9f60eadc14cfbed941e78af92bf33d9d6b566e0f06e4d000f631edad46283b0ba06d77caf20c41d8d3192a53645a9166291b7737d8fc721380f6bd36f39f7e8c10d39a6bf5060171a8f580ce293b4d98db5280f02dd500ebbce890eea5ec3cdfa1f3bcc393ed6d9436e79556e8ae013d797692d11ffc108de2fad232adb9d681855e1b81d695562fcc4dc784d6b0d7cd4824415361da16e59ece505d8dd629005996917e9b92754de1a63a63e3ab2da04163c4dcbf7dafed6be0f17f9e7992ae2f2e1f18891280d65cab2791f0a7db776c9730dcb6e6667b120992a7749e775089a69124e8c83a9565902b74aed15dcd4ea783d6da442287d5fb0f4bb5d0de68979c78f6cd8e25a1a6211ca09d7c176acdb57ad717af5b9763464f1f4710b69f9b9b2789307d619a998fc61879bb49e37b09c9b0907535e9b7195966184fb566e3cb87a5eed2bed746e58a383285bbb3bb839f8ffd75462a6a54a915eb5cf187c56b7dbb53e49d5f5a2efde8f1d36d74ae78ffc7ef993cde4d696fb4993a3f85ce3533e726ec2d34ab775fcef0ce6e0789602fcffc5363379f88d558510385a6418cca41c48075b66f044e9e38d9bbbeb4ec0fd43120c0e8e9513abb29320c7114337976b2c4b06352e58a2cd37eb273adb368ad54e4467972f46a9742c2035cfbfd426d6b8d2412cf482d0356bb3c7ebacde889e3a47b2929ca386d479aa58098c2b6338588a07348ac15ebac4405f3065cd810a061af8fedf52e52fd6ae12ded9689386ba4b30b75681fff7b9bc648038920ed2aff47142e56ac33d85d096b2d5d813ddcf5aedbd5470088c5e97bb7022b40a85c13db5c75d79b0805856719f4cc233e6dc83522459a984825260207446aeb1f5b1041f3ed663d00537805f2ba1c8d2d5371243c7afa84f77e74924ed6012f230a6bc094f7854acce78573e2c0549ebff5f5967770e2a309e228a6b3db79490422d9cf5435472972144c21ab1c6229db0631caa541ae068ed4d6579bdea9a97353fef3ce6e07f23d9efceb09d3bf9cae8fc0d6d70f0178ff27630553d408b1c86d596141145651dd5a512642a8be917a1838ed982687ce5ec7e67cb18c7d690d38c4eb77d70d900fc73ce3626bc3e73eb0fd7c9be3ef1c27ebba16a969d887c4e2f68f1a18b8e50839e15665baf32225b3f3849125e57da87e5d28d2b9369d24d74c9d9b42e58acdfbe621631f4e14395ac9691f110bcedbd2f2d2d8cdfbebf54cbf48f7cf1715e69536cbd403bb90889076cda4558dc8d84f276c4e1735e2d22a71b5e28e93009ad5bf144e874ca79922cb53db2a83c54ec83cc12e884dcb9746a0da3dd00a9ddb07e7b07ebf00e21e5aa8d062265dfdf36a2dd36957050c53fa5df5f8277393d83ec1fc1fd751a5ebfb452032f221ec1a22314a9bee511f11f3f0d0e99069a515a9dd4ac1ad13827474a00558b834692288e6e3c565e22461246970edb75356826b566e6fd68ab9a193274ef68c5a74da235421b605daee610ab1a8912ad32a775aaacc74590319e6172e8e174cffee06f1b184246920c34233692289a0bb9aacab505a73edca2489188131bb58bc6b187af7f4bbbdf58d752afb0686c570d7b980b46f19e4c2ecfb7d5e301f16e8e50be39ee9f9dfdc203e262449820c3768260992c42539e3654d65e1df3a7bcabf30896edeba3934797eb2470eedcd07e59715b5fddd80906121cdb48f50b846f6ce0397cf7f1030fd09724c8cb3c342236922c3626bd0a495f2aa36d8ca0f2c955a286dabb815d9fabd7610074a2dd1d92449e8bcc86a99374e9b3bb47e6d9d1e764e37acd34ec0d99dba40ae9405a594980729bde9a9dd17726be2077f7b5074998a6e178134d301f358e7cf30f3ab79469a4d1ac38288713a11f14e3a6d540f029fa27124cc9c3de30b7ff6d3fdefd96a17f56ef936feb3f19e44427bb30d4e5d069316795a2c7e3033b248c248b3c9e83bdf4786856a6d154ed73befa4fdc2857140d73a1d8e8176e6c28884d0d317a9679e5c333b374b927768260d966fdfb1931f76260de48857a165100b97c60ffd56f3505b8bae46da9b6d44849ddd0e972fcd7ac177f3d64dffd0b5a5560f34373e5ba38840b86871e912b370699c6a6e0f3a0e05c00309f68d0edacbbcb338d393086e7c76a7b42e58b8f48b97e6f6a0e33b01f82ec345c4d5c251bdf87e6d005ed578e3ff57e28d07f05f4643b55bbeab9b920000000049454e44ae426082</data>
+ </image>
+ <image name="image1">
+ <data format="PNG" length="872">89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af40000032f494441545885ed97bd6ed35014c77f863c40063c5862a83be50e48cd6a098904f1009485b8c0d209923e01095f798426ea0ca4ee4479830609e1356cd7536e874a5e3c642c9319ec7bed266953a0a80c9cc5e72ac7e7fccfff7c5cc70ac390eb941bd71afd3f000d60b03b48af15c0df968b12ac68c5f3bc340c43eb6f04eeec74cef56b18f05b3e9ee75d59293ccf4bdbcfdb2bedce94a0ffb67f25203ccf4b47ef4728a556da56ce1e7b8689df2987a6bcffb68f3a56c8485e483fcc3120231fed60b03b487f653a34e5a226801e00c141b0f2bd330c885a808c7c64248d3ed81da4da91dff2171c0407017ecb67f47ec4706f9803e8e3aeb997026ee9bb6055b699e34cb473755cae710fe817a7d73d2e53c6853d10c7056da256a6b0878c243292a8e327a86385bbe6b2f5748bee5381bb3602a0fbaa4bf75597e9747aa9869e2b81000a9a0f3fd71179e2ba3fca146f3d73510a701fb1e502ea13009695253e9d4e595f5fbfb0a10d039d9d8e25236958905252ad4e1658d10de6ddf508bf42f76597fd0ffbd9c8b98fcce8d537ea4b03ce37b735ff3da07f945216cc08411c07384ec142b3d164b837444ac9e6c34d9a8d26ce6dc7bc139fc4461fee0de9ec74acf68b763af99e25e5b77c3a3b1d6ba107f4dceaecf5b32c9a2951134caa130e3f1f9ae0fb1ff709bf8628a5504a71343e42d404ed17ed5488a291f5645516bce7329bd5cd73369308e11b16442de0682c70d75cbebdfb6632d6f497a743839d675597e85c003a7b0d4407cf9cf880ccf745915571ee21233f9f22ff8ccdbc2cbd8e7519747000c7c918d03504bdb8649e650f5113b9decf019d1f7cf3e1260037b7b7b7971aa8a97a93248961e2e4a4c2e9a943b3d1243808a8542ac8c8c1b66d0092e40e4992e4a01cc3dae90f07fb968d7dcb2649126cdbc6b66d1eb71e5bb0640aca32d81da4711c18269635517da3be3025524a635bf48da0f73a1be1f25eb810c03c886a7542b3d14746d2ec86f1176800e3dcbe710f630b85ee38fed29b7125000d4267339bd54dfda0e872dde1e51ea96f64b6f71fdc3f77135e0ac03c101d50335206a381ac0afc5b00ca40e23860fc253b97d7ae1062e547c81f03b84af937fe98fc07709df2134112b48c0699d0860000000049454e44ae426082</data>
+ </image>
+ <image name="image2">
+ <data format="PNG" length="1807">89504e470d0a1a0a0000000d49484452000000300000003008060000005702f987000006d6494441546881ed9a4f6865571dc73f913b702e64918842225d342242aa088fea22475d6470a1b312e9c6c15577b6ae8c2e548a94812e1a4611a25098eac64e37c94330938d9d6431e37b8363f3065b7a8b0d736711e63d9c32f7e25c7a7e9803d7c539f7cffb37c94bd289427f10ee9f73ef39dfefeff7fbfece39f765aad56af1ff6c9f3a6b0027b54f089cb59d2a01ad75aeb5ce4fb3cfc32c38ad8eb4d6f9a5bb17112be82f3a12ad566beab4fa1f67a742406b9dafde7f1e2c08c2ca3f2f8005fdccc74fe4c404b4d6f9eadd0abc42012081f0c23f96dd335ff9f8889c8880d63a5fbbfb024c83b102d6f76841a13081010bcfef2e219950e8e334891c5bc45aebfccafd15d47488222444a1025592108490b07a41c1c5bf3568bc3487be78fed4847e2c025aeb7cfddf9750d3ca833555a38fa9c2b511e08801f18d2ef1ed1e4ccf9c1477691313d05ae79b1fadf6259f0abca7adbf2ec0fb6bb142f77642b49396f706fb3c6ef99d48035aebfc7abe86393035b0207d3da560fb3d1cb7bb44377b63fbbcf2468e58d07a6a628d1c9980d63adffccfaa030fb56a0358012044819d437082568122ba1113dfea39c285d0ebe09b0f7d1bacbe96bbf23b01912311d05ae7cbbbb0b5df643e58a031d7a852c48357844e0bb51e3b3b11effdbd5b1bcdc72b4b4bf02a98452c28af1703acfe262795a311992885a2b44d449bae8d990f1658fccc22a05056480bf0be8476da11f19dae9b1f0aaf5b71609f12d65ecd510ac4f1472c18ebf8898fc82f5ece1149d0fad363891cab0a45699bed0fafb2dddba29b390f2bc2323dda373ac4ef76fb5f3aa84eaffcfc21333394a9e3c80d8f53105ff9d94396bebbc928a11f7b221381ce7e9b76d6464d43e3a925e659207a37267ebf8b58711e1db0f55fe5cecbe2470f12c4cc828250c004be3004f808cdb27baf45fbdece481c131328c24be64108a40f60276a63b23661a050d4aa9017ae58d87825af4805066c8862d6f53b3086f2c7ddfd163b1f8cdf354e94422578a9c08b71644ce651d4d3a2b000aebd5a137831d979e172aef68ef73c01747abbecc4b17bd61a46d9641a10901424031ec1b52f5c62a5f73dc8948b48c6704e5bd87879f4e00e70e2676bfa2b581ab31577c7be36318112b8802470adb18600e7bfb9c0fad72ef2936019ac5fd41566e1fcb70cdb7b8624ebefaf9abd671dd973555bbb17d37c27f1eda9fb3b3101c179f911bcbdfc473f8d55b6d4986563e9022f668dfe060b7137a4d931b4f67d24ca5432e57aa9a852edfd98e69ef2daa93ba3ae92ca8e2ee2cce5fb7bdfb98e910402b7fa9440f9094a4120e88662f1d12c9d3b5d5e2f46b0800a891f40fcc075b7f059c3621096a923e7607bafebc127034e180d1e8e188156ab35d5fdf19c036f8d031c0cc4a0e68a3048687c59b1f6550537173c08aaa3852886669410598352b0f54197e6dec0c056608c78470c3bdeb4d6f947f7373db8d091b002410881100621423d4fe7812e6906f13bf758f8460d3c20e2df17a1d3113a3675e00b9207321c8531766804b4d679feafebe5b5b18630088722a07c4a15f7535134ff5c5b815ac01a075e1c78b194e7c068777a01cbfbbf9f7c2931e8f9fab100ac6020a5421281adbf8c02efc1da1a785b4484e1f9c3a610ccc09dcb6317746353689ce7cb08d48117220b14c9a384f6ad08a8d632f594a92643416c015cfa36407d15e8d64f1fbb1a1d1981bae78d17d16004fa807b4b33a17327c208c325d0321abc0826ab7f10a8e5fecd1f1dba27182fe20f2f63a6e70995c6d8a74bf0c31170424e33d8bdbddd9706e5ba470652c69af2bc6f936371020678ebb9236d681e2fe2ac4bd2db00b94ac8bd2112850e4c2a449da6c72a05e6d2aefef299fe7cf7e746a48a56e1ca730a36bf7ee46de5a16554059e48ba819a71110983c5b23d4d13a2e87577e1d3448a7428cca6342f7d1e800b3f7c1b8aa57641ca1898054c17fef4ece9ef89c5873aedc5a4c4cccc2d102a4d9ace1047971dc9ba1df447005beda6b47e360758fefef50a7c914613823f94c0e056d07958e8ed4518dba197188cf560fd33a6be8504766ef56f052b226e77b5f4ed75b70c7ff373c7fa62379640e1f53af062b5595613200cdcf8f57b45051a045fb74122c7fddc383e0256dc24e9c198429c2521575eeb1eafda60ebe6d1409df43be9580269e693d84222d5b958e3727c40a8a6f689a5f9d693f96d001e1b81fecd8988f3b81ce0aa8840a8942f8dfe190bbf7b539e1878780c8122d7454cb9d928bf3494de97da72012effe1c9828731045aadd6d497bcb8fefac6d3c3c007dfb2c24bbf4e9f387880a9c37ee82eaac4e66b730393939fb4047eb0d23b13f070040285f511a1aa3ccfbd7876e0610202851544d67f3b77e6e0e118040ad35ae7670d1e4e40e07fc53ef95783b3b6ff02cd6f40286fb55a930000000049454e44ae426082</data>
+ </image>
+ <image name="image3">
+ <data format="XPM.GZ" length="29651">789cdd7c59532bc9b6defbf9151d37df4e38f2021a8070f801108346103372f821a72a8424d0080287ffbb57ae215512709add67dbee7013d5e2a3aab2d63c6569ffe73fffb8bf68fff1cffffcc76c6ee67df7877b34d33ffee917a3d1fb7fff1fffed7ffee33fb6b7b6fe884765b7f2c7ce7ffc977ffc879afde1fe505bf81fe276c27b882b82b7f1bc394e98ce4f1997f9fe56c278dec8fa65badf4e12a6fb05efd1fda69c309ef7e93cdfaf183bba3e3c11de66fa3dd3b3cdf4d880784ff8338f09137d9960e66f3f61a2afc998d73379c274be2c98ef2f254ce71b8c993f554d989e3f17ccfcdd254cfc1f09dea1f39a31f36f6dc2b4de4230ade76b09e3f9d0134ceb29a657e4172609d37a7dc6a2df3163e6273c33167a3a116f27fd8513c67c3eb309d3fa3b8289de704858e8c99f04d3796713c6fb6d5d30f1630263a637eb0ae6fb878c451f4cafd06f98de1d7ebe358c857f7a5ee2d7d408cbf5ca3096eb1563799e66ccf7e7d711efa4f5739f30f297bd0966fbda66ccebe58384c95e0263d1c7947049e89b33e6e7852a635ecfa37c77f6d3f582459eef0993fe6e198bff3619f3f3fd1ee132afe7d01f4adbe97acf58e83d4b98d6bf202cf72b97309e776f8c793d87f22cedcbfdae4a58ee0f5709e3f9fc5630cb77ca98f9752e61f2e733c174bd7a612ccf1f244cf4bf329678354c98ecf73ee2f2b65c9f3f08667f7861ccf7abf38449dfaf82397eb40957985fbd9730d1bf605c617aee05d3fdb9dcbfcffca0bf974d45fcef817185fc2f738cf97a151226f9bf0a66fa881e53dd668ce72b3b15cff6be14bcb38ff4940957b779bd53c14cef55c224cf7dc1140ff223c6cc9fdf61cccfcb31be55809ed236debfcd98af374709137d3b82391e0b667e55c22caf2bc1747d76c9589e7f2798e95b244cfa1d0be6fb3b8477997fb59b30f17f2a98ae0f729ee90f78beba53dd2fa17cb36dc6fcbcf02a989fe705d3f56640383d6f2c98afd709e3f5c1326679da3c61f28f8a60d6578331db53b815ccf2980966fe503f55e097f91931aeb0fd38c1acdf73c6bc9eae0aa6f5bc4e98d61b0ba6fbb3e784f1bc7a65ccfab32e6192672698e95d244cf2690ae6f5493e668fe59b9505b37c30ffec96643dd3252ce7fd79c2b8be1f09a6f5cd0d639677d64a98e8d911ccd7bf316679e463c1743ec77cb76be5fefc84319fb733c642ef2461bcdec9fdcc7f4ef4db7de63f9405d3f5f659305def317eed95243f9927c61c8f6d8370baff4d30df3f642cf6b160ccfcaa5c309f3f4998ec03f3cd9e95e7eb7dc6521fd0f3addc9f4f1933bf6a9430c96f8bb0617a4d4b30d3fb9e305d7fc098e9cf6f1226fd63bc867425f57089b0acef3f18f3fdee266192575f7019cf8779c206cf1f3336fc3c2398ce67fb8c03ebfb52305fdf134cebbb1961bbc3f5434930dbeb6dc264af4e30cb73c0b8caf72f13a6f891ce73feb08c0dc79b7ac2e47f4782e9fa0cf3d7be4bf9d81396fc988f088b3ccc2963e62fbb272cf4e61f09e3f5ba2c98aeb7c384519e798531f3134682f9f91dc1242f7d2998e3d59e605a5f1d3166fe4d2f61ca4f4dc1b4be3e4998f2f1b3607e5e57303dcfbd300eec1f8b8429fe2e05f3faef09537e4898d677e709d3faa42fe7d85ef430615aff4030e7cbcb84c91eb618b3bdb8c38449ff0f82f9fe5bc62c1f8bf1ddc4728dec274f98e45316ccf1bcca58ea892bc2a26f759230f9d783e00af6ebd98231eb331c0ba6fbfd5bc278bf2b09a6fbed3563d6a72d0be6fcd116ccf698ae67ff0f09e3fafe4e30d327f4b0bedd6dc2248f7bc15cef7413267b3e10ccf45c264cf49c0b66fbda12ccfcf71346fa0cd39fec639630d9c74030dbdf24613a7f2c98edbb9930c5af8a608e9f7b09937e1a8299be9b84913ecdf48bfde990303d5f0966fa5cc274fe5530cbab9c30c9a72f98eb0bd6af637fd76709d37a8f82f9792f09537d2bf2647bc9585f8ef5adae1226fbde15ccf57037618a2f44bfdbe37a397c1016fbcbab82495ea12698ed6d9030f94b9731db433e4f98fc615f30dd9ff37aa27f5f4d98e8cf0473bd7f9930d1b710ccf9a79f30c95f0b66fd6f274cfea304133d2e67ccfa768f0993bc9e05733d759f30e59b2bc1448f6e274cf17f2998f3edb1607abe6f30667b500782d91efa09537cae0be679522d61f2d707c15c3fcd13267aba82891e7d9b30f9c72963891f7782593e070913bd4f82b97e2f0966ff6c254cfae3e77b8e07ea4630e7b723c1ec4f689fb6bcc7f5be7184a55ed5bb8c39bebb1dc6d2df2ac19caf4f098b7e5c10ccf692274cf9bfc598e519ba0993fe0f04b37ea709937f5405b3ff3c264ceb5f3066795a2f98e3df76c2541f6e09e67ec1244cf48c04b33faa84293e77087bf61f7f9230e9ef90b1c4338cb7d6ef73ff96dd08e6785467ccfd86237abde17ed99d08e67eec3c617a5e5ff05e09f97b27ec385e84c784a9be25fd79cffaf1a87f5791fade5f1396e7f9c384297f3c0966f96d31e6fe2cc8fd5c9ffb63c14cdf6dc216e5db63ccfe19fa82d93f797dcffe9e6f33667bf098df9c977e3418c2a9bfec30667a32a2df0b3d619a30d213de191b3a9f7d248ce7b30963f1df4c30dbd78b60ba5f9d268cf77b2f78bf8ccf7b209cfa018c97be92fad543c6d27f633cf741fac350219ceca5c358e641e7842d3fdf8d084b7ef09960969f4a98e2614530cb07eb8550957ed279c272bf7d14ccfc8d1376c8cf8c31c70f7fc698fd3fbb63ccf2f3fb84bdf453747f10fbb223c29ef355b62598ed2b08a6e7ab37c6525fcc05b33f9c0aa6eb5d9331c72fa30807ae771cfa4f5695fe327f27ec391edadd84299f2f19f37a6a3b61d2e79b608e8713c1eccffb82893e3364ccf14b3d0a26f9ab07c281f345b811ccfc5f244cf1a429989e6ff61873bd679b09533c3b13ccf9619230e5ff743fe77f9647907aee2861f2a73bc19cbf3f122679b71973fde6e709537ed782b93eeb10ceb89ecece1326fad1ffb34cec27cf0553bcf48eb1e8e35d30f7272dc681f57128d8a0fc334338483df62498fb9356c2643f2f8279fd0bc1b45e3e4c189fe7eb8c59fe613b61d2f75230fbfb6dc2e4dfb23efba3be12ccfef49a30e58f2098e91b0826fa545a8fe8cb2f19b3bed547c2445f5b30c7ab9784299f0b3d52bfd712a6787b2098e3e53261cae77782b95f1d264cf545ba9ef34b2698e24f7e2c98e3d78e60e2d7cd19cbbc6085a9be1a09667b1e274ce7df0473bdd24898e28117ccf1a79d309d2f09e678534b98ea95f43ce66f5730e703b1478e17e63261e437cc0413bfe122619247a2dfd2fd146f32f137dd4b98f8f582591e36613a9f0be678f19130e59b8560ee175a0993fd7604737d7e9330d9ef8960f26f5d134cfa762b8cf2b1897e928f2e096679dc254cf2b8174cf20867825d059f5f612cfd739630f16f04937cbaf384e9fc9360f68746c2e40f8782393f1e254ce7d3f3b95ebf4898e2dd9560b60fe1bfcaf6719630e5d363c1240fff9c30c9235d4ff2c886829d47fc22d8a37c72cd98e3857f4998f817fe385ea8fb84e9bc3c5fe67bf584c97e9460b69f743fe7cf7dc1ec4f1f09537c16fd4b3e4ef4b2fd6409a3fcf48e60929f7f4c98f285d83fc713534d98fc6f2098e5d74b18e597a7f57c40fa453e19c7d3e784493e53c19c0f5a0913ffb27ec6fde745c274fe5d30d707cb84c99fc41f32ce0fe27f19d7bf0782491e4eec23637eb70413bfddb956da68f5573fb5d50e8ecdcf3f3be8dec2f1efd281b251daffe6c3fee0f04841404e7ecb73294efddb32098523fd1dcfd93fd1e96fd249fcfc2d7a093a5be346641d7ebbbeff542fbf4326490fe6f3513ccfba5af94daeddef78fe6ff4974d3ff09f74f4ddf5ae70cfdfc15f0ab1e93bddf0f1c9affe76fef2758cfa2c6fe222dbf0afbf9bbf3c4acc82cfbe7e421d0da22ff0efd127f0887f87cf417c3a7ff6ff66fee2f5508f80b2a80bf97c02ae9ef50b5bdf408ff1ef2ff0b749fc1db9b67ceddfc75fa640a127ea108ff48c3d7ea8e77ac13a1b70dc7a8563a2df90a32573f577f2178fd6122dedb1e003334d39661175851636d6effa03397965eb3b80737f237f01d9077d085c44aa8fe0e068cbfe41c713505fd3c7c0c509ea25ea6484f79dfeae58f65bf47206149d214591ea3a50dcd04dddd26dddd1e7fa4277e1b8d457fa5adfe85b7d077fbfd70fa897785fef77c5b2dfe22f877a0b2852e0d5db7a07282de9b2aee8aaded57b7a5f69a59451f13fab9cf22aa84ce5ea51f5f5bd7ad2560dfeafe6975566f37a3db74bce9883c534745b0dd5483dab17a07aac266a8ac754cd0a47fcdb04ceced542bdaa37b554efa0c7687576e3199bf1ed4fe3dd4ffc058e68418fc9fea9861aa80f75a00ed5911ea99a3a5627ea549da93a50db409aa7aac99f2dd5866386c78aa37874d4b9aeaa0bd5051d5deab9ba52877a086b4f74aeaee1394bd0db4da12f921cf657fd0573b5bae5bb901b75079cdceb857a80cf9eda52db6a07745102ea67aa0c9457e068c3efc563869ff45301beaac855e447ab5db5a7f6f5abd110c53d44f8278c790eac16cc53ffa4a6f8b9bfa05e12260e21371863ac2e1b67bc09ac03e0c46470e4406933e966865cc2a779444ee8a72c3a327df36406666846e06f27910b9054a438d610cba23efe4d7ff95c099e9928af17d537633331642f4479b5a087e91707eac6cc9897b62a9bdccccd02391a9b57f3a6f6ccd2bc63b48ecf1d4124afff4a1cfb498c28c82446d185f93007e6d01c999a9a820eca40518eba98910ed6f422fe221c452b134b84c31cab8a99a37e4ef4ae393567aad68d39cba803fd64eadfd5de7f2dbf142c6b0b7ce748d7d5d234f49ee9a344911aa4b05a885b2bea57feb33ad72af84e05b9895200ef314dd3326dd381670ed1b247c936fea4aefe89bf708d4b3ac9e033074ecec1d72728f76a92f10c71d4495bfc86cf559255010f66013f73d44f0b3e89af0a7e62343017a66b2ecd15f8cd4c67e65a7fd1f3fc457f91f821abe5ba6d6e20bc44f956d90372a02a4fbe22f26e6ffcac7ca9459fc8c98c75b9f2b3a9b9356fe6cedcc373b7ccc3a75942f844dfcff34b8c90b152f1a6673e40275b663bc524e0c6ec1007a644d6823e90938e90ca46ca9a101d4c197c7dc55fcb94d37524018ad4755331555533bb58afcd388e0ecddebfe92f319fc42a70817e7203d5c89465da260f409d44bbdf37945fc82f2616529d2a991365ac014d7620034de5c75af69916e69a49f435b4ce0a4a68a2ac75a66d3d70936889911aa3f55fafc79ea0a28f31255ad73973f2885a99d9c0765f627f402bb11ae29bb599cdeda3eddb27b56707766847f6d9bed8b1b905ae484f2d3b61bf2fd33af05941df89dc4eed0cf2d7317775b1ffe96fc4d4351dfdc85f16b8d2d8ceed023c7ecab95d72f98ce48bba89f495808657fb6697f6dd7ea8be3dd04d88e0f7f6503fd823ddb6357b6c4feca93db328155bc78cd3663f42cb339243bd6d405d7d5c988e0c0afd4ef8ac973ff317db8415decc956dd936c833fa491975d2510dcc2a15935b4b36a55eecb9bdb05dddb297f6ca5e432c8a328ddd70eca2e331b13790df4ba0af5ba8df3a14b3ed5dcc50290244ab6bc06a137b6f1f6c0fb8891d5cec817253df9c45ff92bf3cdaa6ddd237761bf2c92ce5f6980b3902472aac32db76c79674c796b9031e70b74cf5740fe72f6788c7e6dd566cd5eedabd986d71b52a6a05d7a7ac0b24472def3b7058ec47a9bb7e2ec4aeb5f9db4ffc056a57a58e9dc1a736292e453f01fda0bf381b9feb9cf32eb82cfa96cbbb733c1ed12a80932ecd6a1e795df8bbba341faeef9ecca91bb821fa20e9a59aea872a560d1d37d20f2e73cf20a163ecaebf98c37de32feb3528f0ed5e540f2a0baad41bc94b66ec230de464ec266e6aafdc4cf7dc8b9b63af3fe099cc2cd50eb1bf8f9d34e5f34577aeaedd02b87945df99b2df552536625c9bba37b78422f60a7433c66e7bb3b70a9ffd85bb5cac4fa17a040a207665708cddbbfbc0ca7155a580d4a2df449d40953bb003b5d435d443712dd96739d3cfee007e7fd487ee30760bdc3d283d7247aee68edd49e406ea8119e7a6294568a81d4082eed49d814ec8ebfb6beb7fe52fa1c0099d9de393eb9021efd5b66b603d5fe1acd62cf42425b5eb9aae653e701ab1d0f34f31e6ccb5b1c35290a796fa49d55cc79dbb0bfd0e56d8d547a0ab86bb7457987d5a6b751bd70beedaddb885bbd53d7590fa595fd891fa4e2f8e2bc999ba77777aeeee8d553b2660766c631e6c225f14371beec10e5c0bfc64c2def8c98e410fc144bd400c733db7e5b64dd3ede86bdd825e0565ad2edd992bb9325b5a8bac57ea3ab0b2a1abb800be32d0539abdb1c5baa25fafe925b0bf446f1da285c5aae1439731ab3459664d9656b4ea89abba5db707f1e58027448fdd79613d9219541fea06fefeaededd3e3c628cf570c52be8f54fc0fa0ee1be637de38d1bc43ccb79a6b5d28b9a7aeb1d549b395898e497559df82ff4829352c14fe6c07bd47e23f5ef54fb821dfbe0339feb1acfba581abcde8a9b43f70296f4ea1f7ddf3f61468951640c3e52b5477e00d1e20eeaac1377e6873ea0d4daec3778a02d94fcc83f43b539727971ffa658036cf80bf17bc0f3c72144ce9aad4146939eb1c1fd4aace6a760113b2e407c7171dae75fc0b7e63c1fb61bf37cd489577e8c1d0f54291e6a183ff5330d710c24d173753f5735d0cd02ab1be96e44371071fcab7f03ce97dc3daf4d33bed60bc79717fcdbc8d45dcfbfc7e88f95e494f34b05aa2fe0c54cfd873f303d88da75ee3707fa39e5e555668cb3b31dffe60fa34e4cd91f012f351bfb1fe58f21862dd425581974c4fec49f9a2672534e3e2391adeecfc046eae8fdc5189674b3965f42bacae2ef4b5d777bea19576e15662934752841b55201ea7bbe8139ddf00c65cc6b65b107e535dff4b56f829f0027a9b7a1da7e6cc7b60aba19a06e5bbeed3b3c3f903ea7257d8d3ff717bebb16c33ef52f9ff268ac8b7b78555397d40b585645662ba92a076fb417feb23b5ff57d85d8427362d00b5884f357b6ebaf31b7b7529dcf5d57b45477e26fdc05e8b7a7fbfed6dff97bf4ce99e47ffc84facc3f806f8e919341617fda6df88b5dcb310e2bc1f87bc3f730864935df4a329d402ddcd56fe089bd8297d33a90fb3df483e43f6ee1b7ed183d1eeb6b9c52605786b9377264fc8e2f419d0554fab2b9832a40c71ab630cf894f8e3dc01344fe1ed714dfea456cbc3be7291b52e62bba821134e904f41375345375fba65bbe4af3928d7efc506ff917d00b70e2afa025dd454e26989fb837e14a32e68f89557ecfef43f50ad20c5a9f07654e3032b73986911466aa6317103329536ee8a5e02f36d978fcfd1dac8c6cb2e56768bd229f36775cd1c296f6525bd08bd79b7b90a7d0a347af5fea7ba0cc60444f9d34d7c2521bc7caeb24d8e07403a91b041f02cf4556b5c58ca63421831c33a2fa4efc3bcd88442f2ec51e9c4e402c8a57e65063edc2aa4d354bd57dd4cb23ac9a874788c6b4f768d6f209450188c21003b7439fad4bfa12ea1fd1ba803b907978b22f1afa9d58d1c03a47e63e0cb04f9a26ce63fd7f8799f9d456dc7d918b2ff2cb4a2f01397b065befc167270cd766f5a417a88b21fa7c8411e6e0d15a9e27698c40b7f71e6acef01cef672fae16ba2df2e8a9a9d9b1db82bc51d63954391eb22a646733d8d04b9bb2407801e37fa19ddb7498effc050e87fd75f4835c9febfdc284b5497a516d08d963a7717ec5fb900519c5fb27e0275ba11f390913964495ad8ca8c33acbd4c2d42be89e15cf90632e72b6e28731a74a97c7331ed095b90d33e8f4ec9a5ed29cbb905f6c318eb958c54cf4054d2ad20c92f5a24a616e0fa0c2f750bb8e36f2afd5c7c1fb7e58c4a8019cb4d837d6e7fd312ea9f0eab7fd2df895d10738ebc19ed357c25bcc4569ce334b7920c07f4bd4cb2a8e7dd5573ac9a5aca399ce7d1b677ab2a644e486393187907b9e39134267a5ee211fd38e9d023f51fe09ab95d8bba549114e6e3053464f71c3f01e3ec0e7e2b363d5f442eb0067357d6d4ef8b98d24458cde76100e90be1c690d9ffa17d1c724e986bceb555f59b36eb71c258dda83faf9516750e3c2b57e4efd27f62e6fb62bf9046b8f781f4fc18913f0e376380c47a1061e3f8bb1137412b959180d6b82859a3be4651591658fc084638c773eee36c167f64dbfef84578e72f1bd894bb0b159eac5452f281f888ed4c7473b1f825e6ea0165eba1e542bd7348f48b3fe36eba445b3ce68fbe1249c863337f575ec4786a89751a847bf311fa151b08769e204fccb1cc64cb0ae97357f913a4cf41277b7a3268fed13fbcb6c4d2f201f5d068f1d8245c57e052a5115e53a51fbe138345d8c7d13b3a0faa318bba4578c937137b4e3d0f297a1ed0e43c71d4257fe087a59826597f515ea85fc5426b4513adbba0cb51be9c5723efcd4bf482d1579e529a78b768b15ccbaf7c7cf8e1de98718eba46f0f6dfd0efd890ae7587755638e378f661ea9169dc81e19e038499f9a00dc5c842e449a3a74d171870aa402b579cd1ea38d5265304df572ccd003d68bfdc65f24feb8422c8befaf1c43efe2d6fc857e8f53ab671bdf4aa03ae111ec7d6296d069919fb43082b6d3ecbf5db85f66fa2d8c0a905dcc58d5a29592cf45cb3657e1323c619f44951855b47077b88222a7b111773fcd2d0b712c5a5cbf3b87eafacd5695e7eeebb110cba002815cdd86687c16f33ec8f320c6ae708d91b4aaca3c212f2b99ddc7fb674af69631c6027db1b3ab87d770a39e2026c6a907d40bf0dc56b8c5597985eb58a91726ea3cdc511c2bf4f95ff52f2bbd0c616507f9f55ddf857bac5853df8d39b80cda1edb1af814f62710cb9e21332ea8d3e2b97d8b7b0fc94ac57db1865aed4e34ac3237e1062c36e76c9d3bad76e27c89af5979dd042ae82ae79762bff5555f69531c1be09e4baedbe1812ba30acd90e31370afd49a539751270d16f2e0b6b1d39a851ed2d9a038c631394661d1d32ccdbda8d36e624596872db0ac6dc851e02f6116bbfe38a726db4cf97f1276420927e55feda316fb7dbfe62ff1f7a53d0a65eed049b6adb4eb3256233bc71e127276a8842af24c3b7955e4a5ca563ee38836e70eacb87726dd6527ec424e897396a5f950396878265db292a9ccd4f4c31e58f6db5aafb5d9bf7c9e8dbde0defa086ad67d1b9f55e6fdf816cfc820e68279dd41eeb718959b19f41c6ae227be46b107baf92af52714b1c221cab785be93a519cb4c6694aa0375e89d6e67c605f7013d4d60bb6ca21466998d512c1c835f76d32469f5bee0e67c6cd543c75c3150f7b166757b9953347d5ded3fcee20e853db37de8f7dfe3f5ee026ae24ad4209ca18ab8ccba98a13c8f32afeaa883165ad6c6fe3fd69f1d9b6701fca1857325ecbe582ff1ea06c86fe12fb22cd5f4fe477a893ab1d176413ff759ce557b819be8fd56d9dbec112a9921766f2d779cf52192c6377730bb487fa24ad95336c886d908dfcda8aa365bcf34edff538c9ac095cfd94b368e3a544df0b6471b30feb571e23fc926d91422523fe925ff623e26533ad18b74585bbaa76ad92ced2850749d4b9dabceb2b9ebe3ecdeea13b3b4555381da83e65bd233d6329d2d80d369f60a555a7d2de3ca5e3f5b2d58d25bb6ccde53b4931d44da93a9f90f7b687a3c1f0ba926dbdcaf2c7abce49a003dfb96863ec5bf922f73f581b314ecf33a76cfc55e6704b5d8489f4047d50fef182b66e427ca641f7e3bf69fbe6e2fc30572d3e03e75b52b017a46ff295124000eda96e69754bfc5951afe5597e244491d14f4f2fa699e5c9c25af8e5e76601efcd22cb311c615f2199278cbc41d24e8d4637d941d425539d4d3ecc81eba63e83815c6a6688563afb25aac67b3e3d00eddec24bcaef5a932ff9a6154a8a08466b44b957e482a253bce4eb3337750d87771a8972ffde5ab3dda18a3d40578e304bc5af2708cb73c4d34533b7435cc4bb17739700bf09bba35c08781dae03a6bace657f0d487ac99b5d2be91ec9e3347a9b668ab62351be7165337b0c77a87664438fbc9b23672633fcdc7fed57e65ee02f4df51fff14d04d97da32a64668283de5037e214555d456e624f9975fc5ed6d197ee423f66e7d833c67a2bd6130fd905781554085937ae64ed5a1d2eb57dae6685bf4facca2ea1d7998025bfb085ad66a29ff4f22ff62b9d3dcaaeb2eb385336c7185167f80e0c59c4d4eaecc61ebb33fd6af6e0098710cddfb3dbec2ebb87bebd1cf78ebbf3ec21ae07dc1c046de7594fed82574d8ad626d4176695533e62ffd0ccb64c47cf5d3dce418b7b6f5feebffc8bfd7ddf85b8be1d779338afaf621a5130c9765c49df687aefab677afa292b419ff18e7bc9b8ff02bdc9b33e036e16a0e7be1a9a41ccad3cd1dbd4cbaa269ff1fa65a831acdeca2a9801dc5a8ef9a5fdfdd036f7ded97b945bb6cadb1ca1e3bb1ffdf8edfab0a56a7ae4ea6617fbf601f42507e699abd55eb68bbfcfe35b74fa21dcf919ce5ae6386ffba49bd45dc35fb2bd6cdfb75c3dd7380b5deb5dbee95fbe3d7cc3bce42a37696a27d53cd755b1d6b40abcf359df1883fbef1e7b4eea51212a64e7b9f538fd7175ec79e2aca595bbdc537efff287669b53e83ffbd0b338de37785cdbdff9d4bffc89bfc4f9f04cef40c6dbe53dad76716f24c6a05807c4898f1fe7c1b7838fefb0c489933aa21ddc6c17b9a35da538031be4599ee78f791ff3d617fe82bcc099fc291fe4435f918ea0e02fe12ff84b9c257adf35cb7c646e291ff3dec3947328f69af896c4c4dcfa8e7f83dea60db29ce08461a4174c418c41d0cfe7cff1cdadfc25779ce3bff414e60abab51c7a255fc927b8c3b59a597efaced30fdfb7ec87b6efba5e3e7555d10cfbacec63b6d8c621eae87d779acff2b9a9baa9eee40bfa1e8caaf92b3bb71573102e4c237ff5b1769ed2cc8ce896ff8bce93df409eccdfd432d60f38b75bed55ae2ceda7efc34cf05d8751fe9c2f4dd73524d3e11b12f2ee74f14d3678ba32c6dbb6cded5bfe9e7fc477fab3667e901f669dfc08326f27dd2371f1b3660aef9a9b13e863976604516368e87d9849b234c9333fca2f3acfb2ee3caf696bb7f2e3fc846aaaf836ae5abd5598f3bbba65ec2a27f88e9182fe3740656a80b36d386a9855900b7e9fa6cd75f06ad6325bd309e9254aac0324cf20b248bdb8fafe5ff8057fb1f9336a37ee77597315eb5d4f93a6866aafbc364d0237672eab4fe27a8e71b092fac6d5fc0b7bd1b4deea686175d009b7a164ea6bfbfbc5fdef9fbd6f09de4a59cfdd43743ecdcff27aacd054c35a9c83e5eb87a2f9c56c85cdcc14fb62e6187582ef6dad7c45deb85ad30b7478b8eba7f2064875f53e8c59af1f7fe22f7953d7dd6368c73d30770b7a6a85929d19af56df3c903d5fd64f7afb437250a127655da255617ff255b6fff4ce39d4a360b3793befaceaaf35fdfc34bf78c815b9afe28e5e4f6f993debcd996dd87ba86ba2df649c3d9b6af57e72dacd03995aea4fb07fa3b9c62cedb53db28e78b7297f5af9ceda3c00b831cdfcdc5fe965f15d985fcd2ff9856d428d15e3c7dc5c9b87bc9b5f4236bcb3c3fc8a7ace35bdf08e498a4dcd0d194bdc9369914c01a731c7e7d7f8ad938d3806b95fd9a93db11ff0dcd52c4ffce58bf7c7bef597f583f734fda57bb25d37726f380d2cbc21b5166165d78175c655762bcdfc29fe5571b2b367fbf9303fe19d9bf4f62f4478a894f31b13df37801aaf40d7dafef50fbf2fb6f1ce769c6043543c76175929bbc88ff25b43b3932ad2f9795f6055d9cb546a568861683f5939dbd70d7f696bf634e61f6b713a338d71dcbc9a96eee0db70436d0afaf8e5f72d3fe9668473cd57a82a4ec07edbfed9ddb88a6bf0776048ee6555b677f6ce9464faa8a42a8d3fd5cc82df34b0f229b9417e976dd9b96fc5bc01d5cabd1f47db8de7884fff1ee79a104be57b9c7ff5fde4d551ec17f05b86f11d487b05f9e7108878f73a7f30359c644d37f4b219abf87b6366db43b682eeb7059d56dc23851a3a9fa8ae5dfa31be2331094f76eadf750738f928bc33be3617fb95fcf2690e40ef1b4365037907f22f44eb5b9d1b63aaa196cfbcf60f768a6f867ffef61b7df36da2c6e63673792fdfd2a57c1bfbf8b9deca35f6f07d7b6546f98e75406ed4c910fde48deb2f9ac3c8bce897fb974f32c06fe5e2bb9363fc76da81eeb95ba8959af6c81ce4259fdb27bb08595e0e2f503707ac616aa08310aed4b97bf5e7612f1cdb0f33b287be9b9dc55adad5b34a86fb06b80b12bbb552de807c721e6317e0a893197662a3357ac2ba5efed45f641f4a6471c4ef82937ee27cec404fadd7e3bce2ebee1e389ce89ab9b215b50cb3bc6a0740f945766507f93cdcd9aa2ee976be1b0eb89688ef1ef59952ec47f1f731f8e39e7b7619cef5e30ef823451dfafed85ff417fbf9c00e78a45fa2fdc6bd4ad9e7c7dfe9edb700b2868ac796c312a86ed84bb7b097ba110eec55dca5faf2fb9403cdef7ae21bc5237c0b78193fe3ae397233e24cb99a91fd6a7ed9f8f75fbe8d71eb9a97f7bc060529b8c2b1fe06f1fadfdd865dacddf71d9dbfe02f9b4731efacfb15d5d4aba368d7eb9febefad095e9fb3ac4be25ff8f12f7d1ff90bddaccd4236652e4fa1efec17ef2be66b792f735553d8f4aec1a64dac66631bf8c7f9655dee2b4ad7f3eeeadcfabf9560b1ef9f7cba4fd65dcd20571defea9dcf955436a5f429c7fcb01e0b9bba59d3cb37ff46d257f9794d87f9ea5d8fcde76ce6b6428f5fc46bebfe502fd917f2dfb4fbaffe5ebc3f2bf8165142faca379ef5ddf728bfd6c9aff5fbf1f36ccd96bff1173e5ce1907f35a2789ddb3c3ec52d7adeba5e0bcf4d7a8953c40ad60abfe22feb32ddac03566f8d16bc74d342bff0ab753ff8ca0ebedd9bc4df69e7624d2f3fad917fa56edbb4f99f9effee795ffad086a4fe0ffdfb63ff4f8edff4ef8ffd2d3effbfd2cbfffaaffff8df2c3931f2</data>
+ </image>
+ <image name="image4">
+ <data format="PNG" length="3339">89504e470d0a1a0a0000000d49484452000000300000003008060000005702f98700000cd2494441546881d59a6f881c659ec73f3d94f0aba3e59e820e74c9784c8504d2ae2e74c41789770799b0617712179c0982497459cd7a6824e0cec4239ab89cc6855d270aab9305cddc719a645f683c382f3958487ce13979b1302eb23ac2ca76c0601597e69e07525cfdc082b9174f75cf7426317f140e1f68a667baba9eeff7f7f7fb7b6a6a7373737c97d7d0ff37806fba0280f9b7c7168b1254a17ddf5100b48489fb2738f9f649f42b6575b2bad6fbd287ff796cf1f21b690994baf41e41d5f53f2fcaa56b9d566f4ad0c2d18c4708eb2113f74fd4b8c1559b9b9be3e46f471729c1167ef31d8f1dab008116dabf78f55a4fe2ccbf1d5d6cffdd18043270b33008afb961a19630009b83b31969d7b2f0a70500e2e1f886490400e94500c529588583cf6d6772dfb1fe453b1fdec9eceb33ccff617e71fd3deb6b5a0aaa30f6c35142b936e8cb97cd2daa8aed5a3a173a5079273211d3af4c2f4e3d3575dd2486003a4e59c8a0d385d481089c7e6bb7f7803a665f9f412b477c78eec34555877ea5a82a85161465714304a27a84a91ba24644329cd06ab570b9a37d4f9bd1bf1d65f2e7932b42f46b09b81c6203ed1161e21e61ec2ec3c696c0e7530317efd9bb074a30c32d3477b86e8aaa42c90d930825444408eb21ad752d6cd7928c24b4ef693376df187bf6eeb92e1201c0585b681a211241ea3152b744f5101190f024e7d20900a65f9eee7f31cdac4fccdc61308808059ec4f5e402784f0098ba21bb981137620046378d02b067ef9ec599dfcc7c6d380d01b4d7195a6b0cad3b239235902411cda489899b440d186b9ff4162e414be5c03307d05239f1bb135867073c71bde0979310592a06712326194918dd34caf8fde3d7f4c41040321213df1e615619cc2a43d4308402613d444c0841c844fb345a7a90079e3bd04fbc136f9da028e993e8e5c48d8454af10d8dc5e91c4d7e5c410407c7b05da44448d10a97bd06881ed16145d8bedc2e8c8bb7d125a2a877e790880993766b0aadfc81300ceb92b92d8f9e04ea65f99be228900f08001cd0b6c17287d8501412f3954a1d0a26a504b6beae75314ea2d3dfbc62c7b1edfd3cf89dedd6f8488eda6a005347d68f572a2b78ebe717471f7cf760fe4446d6e6e8ebfce9f5d44152d152d3c019b03a5072d12120670f6fc385a2a9bd6ccf1fe671bfb7931736486471f79142d95c9a7268944308dd8c7f67592d83abe95f93fce43e9fb8131becc9a5b8d7f6f22acb32b3a766d6e6e8ec5ce9ec51e68d50209f0210444757fe1e9cf3cf8477e308f9631628499b77cf269451e80129eddff2c61c00d91b0ceb2f0f9822f0ad6a1b923cd2c2e775867d15c49d394244958ee8521f025d1baa2021c124a48548738f6497dfab37100261f5c206a46881122234c1f8caa50f3c08fbf791c2d95832f1cf43991bbebee135217e2664c329c902409cdb84932929034856438211e8e894c44e78bcec0f7867aa023131219c1ac129a4993786d42d48c38f181afc9933fed604c13d330feba7a0881f0daaf923e89890726e02baf9f0e3e73b05f625deeae49220c4292e1c4573ef164e2558269b6889b114953309141731df8de10d02f9ff1ed867824266a84988661f6bdb6af36fb52a2861056b9a9aab8bc005534774cef373e84bef2d5e9d47ba728ca82a9a7a7b0ea0bc2724f5c8d4851165e629808118369c424ab0ca62e8818622368ee06be330470b6334e3c9c609ab1b772b3c9e17f49d05299de672914ff72a0b95238c53a25cb52dc058bed3a261fd27e89ddfaa3adfdb07a72ef93de13cbc2e94af9d023d56b6a61008222f590283218132181ae50c043bd8d66df4bfa567ef1555fbe5e78dc52e41eb4cb32b22c233defc8d2149765a459469a39b22f1c3685277e543531f5d5e9ecfb67a184dd8fed1ee8d8571580a542e93001480061bd098031115164a09ef4678ede0a80ca72c28157e27e879d7cb083730ecd0b0a05cd1d5af8f049bbc6eb2409a1b4b83c01165085890d70f2034155d9b86163df2bbb1edec53b27de816e8a18af467bdaa90f1e500411c59521940551dd607387885cdd033d6dd3ebb08ffe608ef44287f4f382ce17d0f97346fa85a57321253d6f71ce917515e7acff992f903ae8384873587f576f32f3f79cffc8d7f7ed0f6c5f91132c6f8ea5221540b38c5c54618e8374a95c2ff7c0a1e70f0dfc71e6bdf56c5a7316d54a1a28b85ce98d9d5aa6481d8ad2e094a50ead0eab7eb7248185054fe28ebbee007c9c4f8c4f70f2dd93a005520f3175f12402e3d16856210b91a0404b475182a987b820ee131cf040cf22877e79a85f294eff6903d905479a299d4ce97495cc292e5752aba40eb21c6cee133aed2a1d27fd79376e541b95f463bef3e70e5a2a5b7fbcd57b222f70b9faf0d1ecb2f8f69a48a44958ddca082b3c3004b0f5bead35a8b4cd32d93cefc6c9ba4ae7a2622ff9d1732155b25cc85448bb8eccf921ddd4a1352c6c58236c5c239cfdc01be5b5fd499f487c7b5c4d79cae6d1cda4ce615d41967b2ff69b2240105539e67b485885d4a0fd971dab4cdc3f51eb558f992333fdd84c192773ca42a62c74bde553071496b861688f08a3eb3ce8d6b0d21a8938fcb6434be5d8cb6d9a719353af6f1cc8317bd15b77f396cd689e416ebde7ca8a482f24cb145008a0e0ca5264e05c68d743bb6a5a2a8f3ef628bdd0021033ee67e5005a4d185dabb45b31ed616ff5d69a88248969ad4d38f8db14805347361019216c406884f9d3e37df74751d42774f7df6fc6e60e5c07cd53d0144aeb5ff83da1ea0be5d5fac0b2b5fba7bb6b3d7176fcc4f1fea677ac19ab6665e367d71121591bf9e96d95c134845dcf2ca0aa9c7a7303d47d531211045f56e7ff7d7cb02b17dee3776fdc4cea0a6cee73cc7f5e010d04290b08400359d107ae7832f7e4e34fd6547549db54d63adb69d35a1733322c447158495e43d810b6effd088033ef6e42024102f1f2bcaba873140e6cd771e64dafadb4546ab525697fefe8369cab7a8e2a5a5692a1549010ca2afeafe581de9a7a6aaab65cdbf89bc181b70ca18931c6101a41eac2d647ce4109a7dedc80e68a3a45bb1568e748bb4a7631c3598502cecc8e0ed4ffc5453f6cddbbc593b0cefabcc875593e144b84ae8700c0d4d353b59eb6e94d5e00075eb584756fe5cd3bde07e0d4913645178aae7ad0ce79d097aa3cba4530b70a120a72abf0c9ef77f4ef37e0892ddb409534571f3aea5f12ac047f4d0200079e3b50ebe9969eb6d1529978ec230fbe84777eddc63af51dfaa2432f794bcb2d82090509f08ab22e440d43d4f461f7e5c74f0cecd5f3c4dd5b76f90166b9076045f85c170180179f7fb176b9b6e925f7d1e75b64d6e1aa33d49e954dd41b058568d8103685a8699086601a11cd46846944fcef7f3fdbdf67c013639e847599af52d5badc07d77dbc7ef8e5c3b5cbb54da1053b9f9ec784ded2a62e7e5aab123b6a0ad2349846843151ffa7d485506c8548f99fbf4c0eecd5cf89b15df87358f5244abd7a23bb9e35f39b99da726dd35b5bf7cef9b0687af03d2b7bad13fad031cbb62ec1e6517f30d27c505a5fee09e7ec6097be590200b3afcfd62ed73600eb7ffcaeb772f58aaab999c08bb5225f52a1ce59d415b8cc622f386efbfe1100ce1c1f1bd8abe789cd0fec23bda8a8da15473b37f58466fd9deb57681b4a58bd7e96b00e04e227b89cfee7ce151ef4050f3abd906133c7f7b69c00e03f66da14dd94632fb6fbfb2cf7c4b69d4f5ed10b37f9884999fef5f40a6da3a512de7618d4e19cf5f342967a4b671e749a39b28b29699a72f7f8bb001cfba7365906e7332575ca4b4fb50676eb7962f72f4eac98e46efa199904303f3f0f54da4697aad35ffdcd613473d80bce03ef64645f78d0699a622f38b6fdc339005edbdf22cdd5cbf21cb26a307ae2a12512cb3d71fef3f3df0e01029040f8747ede4b8652fbda0660f5e8093a173ba4a992762da9733807aeab6cff472f3b5e7aaa35003a7560f302971764b660ec8723035bf63cf12d10f015450245c4f0e9c79f02839602d8f693736499c575953453d2ae63f70b1efce4cf5a741c74bac512e84b0559555d9338a49d84bcb6ffca9ef886049651091423f0e5a79ff4ffb6dc52bb7f718ed4292e877d2ff987794f3cd422753d4b83bb0446429255219b5a21a3eb22dac3427b4418198633b39baeba7f7033a007c6ba52bd4e91902f3ffd90dbeeb87785a50ebebad07f3fbe6d84cc1648e8e7dc56d33f938bc5faa74302a178cf4a28104410289ffc7e8cef6d39fded10b8e20a40c4f0978fcfb0fafb9b01ef89e5641e797084a81ed2ac03628845fdf14cdd104a1311456e11ff50a53484e23cc20028854fce8e9339fb2d10a88e43cefdd7d9ea77ef115bf8d3b477fef525b6ff64df0a4ffcf3efce73f460db8b3ba3102851dd00eaad2d11224069204829ca9830500a95ea990514a9236c2eddb37633ff2bb1e3e11d8b513df2c0abc1a537c0f409020b9ff9d069ddd9ea3fcc0638f6ab2622893fa8aa0b612983d37a08145094fe488752d152fc596c09ab37cd0c3e1ff82eafeffc3f7b7ce709fc1f49e081ea51c5e5f70000000049454e44ae426082</data>
+ </image>
+ <image name="image5">
+ <data format="PNG" length="1027">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003ca49444154388db595c18b1c451487bfd13ebc362b54c759e9960d6c434427249059c84131875d0824012f811cf6a8012f7af3284810fc0ff422040f1e728bb7e410c85e643610d9c941d281446b20035d98c12a4c433f42b1eba167b38eab1e040b9aa6e0d557af7eef57f57aa3d188fdf1d91797f6dc54f92f235f11befcfc466f7fde1b8d467c75fdcade78abe6c30f3e261583488a6a4b1bff6593d8fd54153ba9b04f6adcb462b85ef0c9e6b55e02d0413fa52c4bdcd31a3ff390406684729041e269a3431b8f7d04da08daa473700b89906519c492f196854de8ad9fcff72e9ebb42590e70754d3d739479cee04c89e9038943d5a2d1a331d0361ee7145b097e5aa011b409a882b61e3f0b88f1246eaaa462704fe7d0d59c8befafe1d5129a1dbc56a83a4804490404cc4a60d0afa9a7966aeb041a01da4e9e04dc5449004452fccc77d00b6bd4cd083bbb813696fa8999ebd942925214822c75fa167980f51dc6b70668032d00021dbfd329eb4b07d511d5f46bc20c1e6c0f08936ca1666381f274cde04c37cf72a53ce9a8eee60b712f01b45131cb293e56d4b31b8419ecdc3e0c1dbe07e5db2df66e41b55db2ef99e2cd1a9145b724fb8bcae3426876708dc5de2bd159ba00dd38bfcaf06c4650cb9d68b13f1698dc931d0bc89262561df553b39871278d47a34383504f8abf40876c5cd840120328c3730104ec4f0771c54a7b588a2e7785a8dd51e241c0e0f42aefac0f01edeca69eeddbe6505c762cfc0338eadc5207ba96270d9736df2515a5d51a8d35aa8a7702717e51822c687b081c1a45128348575db30297364ba0c63715412bbc5a44948dcb8af44104c474256c9fc902f845f188be03f6334caea8423db3644be06320048f2c299208c6081b973dc1d52f96bbc78b0e7a69ff1876a2787590784e9c6d51859bd703d5d4b27dcb73f3bb0cf75850ed321309983cccb516da287f0306ea47420816558b59a9d8b8fc006d5aee7c9b61ef67d0c0e8fb8cea1edddba1f5dcc78a6fc04dcc02f8e5e5d7e5ea60b046f82da2bb8e5733073192244af1968324213ddab0fc4643da6f30794def48204660b773516f37c11c0dd887198d36c4e74da7b19d549008f50f0544a53835d74ea03c6317cb1d39b025bcc85a9695f254cd786b9ef1a9357335fc9ed0ebf588cfc14d8467bfa6c82b4a7aa481ddb8f8c508bb50d786e9c382ec35a5d504f7f312ee978430837e3eef20573ebab897e725a974fedcbf4345a914b9273f7e607e3731d42e2558431ba11c04b2158fbd2fd44f20cc02d7beb9d97590e17ac178cb62968ab901bb0adb31583260d14a7f1661bc0d22d23df82190af746b7bff5733fd03180609d531ae3d950000000049454e44ae426082</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>ListPhotoSizes</sender>
+ <signal>highlighted(int)</signal>
+ <receiver>FrmPrintWizardBase</receiver>
+ <slot>ListPhotoSizes_highlighted(int)</slot>
+ </connection>
+ <connection>
+ <sender>ListPhotoSizes</sender>
+ <signal>selected(QListBoxItem*)</signal>
+ <receiver>FrmPrintWizardBase</receiver>
+ <slot>ListPhotoSizes_selected(QListBoxItem*)</slot>
+ </connection>
+ <connection>
+ <sender>ListPrintOrder</sender>
+ <signal>selected(QListBoxItem*)</signal>
+ <receiver>FrmPrintWizardBase</receiver>
+ <slot>ListPrintOrder_selected(QListBoxItem*)</slot>
+ </connection>
+ <connection>
+ <sender>ListPrintOrder</sender>
+ <signal>highlighted(int)</signal>
+ <receiver>FrmPrintWizardBase</receiver>
+ <slot>ListPhotoOrder_highlighted(int)</slot>
+ </connection>
+ <connection>
+ <sender>EditCopies</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>FrmPrintWizardBase</receiver>
+ <slot>EditCopies_valueChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>RdoOutputFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>EditOutputPath</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>RdoOutputGimp</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KURLLabel1</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>RdoOutputFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>TextLabel2_2</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>RdoOutputFile</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>BtnBrowseOutputPath</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>BtnCropNext_clicked()</slot>
+ <slot>BtnCropPrev_clicked()</slot>
+ <slot>BtnCropRotate_clicked()</slot>
+ <slot>ListPhotoSizes_selected( QListBoxItem * )</slot>
+ <slot>ListPhotoSizes_highlighted( int )</slot>
+ <slot>EditCopies_valueChanged( int )</slot>
+ <slot>ListPrintOrder_selected( QListBoxItem * )</slot>
+ <slot>ListPhotoOrder_highlighted( int )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kfontcombo.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kcolorcombo.h</includehint>
+ <includehint>kurllabel.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistbox.h</includehint>
+ <includehint>cropframe.h</includehint>
+ <includehint>kprogress.h</includehint>
+</includehints>
+</UI>
diff --git a/kipi-plugins/printwizard/kipiplugin_printwizard.desktop b/kipi-plugins/printwizard/kipiplugin_printwizard.desktop
new file mode 100644
index 0000000..cb3f750
--- /dev/null
+++ b/kipi-plugins/printwizard/kipiplugin_printwizard.desktop
@@ -0,0 +1,62 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=PrintWizard
+Name[br]=Skoazeller moulañ
+Name[ca]=Auxiliar d'impressió
+Name[cs]=Průvodcem tiskem
+Name[da]=Udskriftsguide
+Name[de]=Druckassistent
+Name[el]=ΜάγοςΕκτύπωσης
+Name[es]=Asistente de impresión
+Name[et]=Trükkimisnõustaja
+Name[fi]=Tulostus
+Name[ga]=DraoiPriontála
+Name[gl]=Asistente para a Impresión
+Name[is]=PrentÁlfur
+Name[it]=AssistenteDiStampa
+Name[nds]=Druckhölper
+Name[nl]=Afdrukassistent
+Name[pl]=Asystent drukowania
+Name[pt]=Assistente de Impressão
+Name[sk]=Sprievodca tlačou
+Name[sr]=Чаробњак штампе
+Name[sr@Latn]=Čarobnjak štampe
+Name[sv]=Utskriftsguide
+Name[tg]=Танзимоти Чопкунӣ
+Name[tr]=YazdırmaSihirbazı
+Name[xx]=xxPrintWizardxx
+Name[zh_CN]=打印向导
+Comment=KIPI Print Wizard Plugin
+Comment[br]=Lugent skoazeller moulañ evit KIPI
+Comment[ca]=Connector del KIPI auxiliar d'impressió
+Comment[cs]=KIPI modul průvodce tiskem
+Comment[da]=KIPI-plugin: Udskriftsguide
+Comment[de]=Ein KIPI-Modul zum Ausdrucken von Bildern
+Comment[el]=Πρόσθετο μάγου εκτύπωσης του KIPI
+Comment[es]=Complemento de KIPI de asistente de impresión
+Comment[et]=KIPI trükkimisnõustaja plugin
+Comment[fi]=Kipi-liitännäinen ohjattua tulostusta varten
+Comment[fr]=Module externe KIPI pour imprimer des images
+Comment[gl]=Plugin de KIPI para Asisténcia na Impresión
+Comment[is]=KIPI Prentálfsíforrit
+Comment[it]=Plugin assistente di stampa di KIPI
+Comment[ja]=Kipi 印刷ウィザードプラグイン
+Comment[nds]=KIPI-Moduul för't Utdrucken mit Hülp
+Comment[nl]=KIPI-plugin voor het afdrukken van afbeeldingen
+Comment[pa]=KIPI ਛਪਾਈ ਸਹਾਇਕ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Asystent drukowania
+Comment[pt]='Plugin' do KIPI de Assistência de Impressão
+Comment[pt_BR]=Plugin de Assistente de Impressão do KIPI
+Comment[sk]=KIPI modul sprievodca tlačou
+Comment[sr]=KIPI прикључак за чаробњака штампе
+Comment[sr@Latn]=KIPI priključak za čarobnjaka štampe
+Comment[sv]=KIPI-insticksprogram: Utskriftsguide
+Comment[tg]=Модули KIPI барои танзимоти чопкунӣ
+Comment[tr]=KIPI Yazdırma Sihirbazı Eklentisi
+Comment[xx]=xxKIPI Print Wizard Pluginxx
+Comment[zh_CN]=KIPI 打印向导插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_printwizard
+X-KIPI-MergeMenu=true
+author=Todd Shoemaker, todd@theshoemakers.net
diff --git a/kipi-plugins/printwizard/plugin_printwizard.cpp b/kipi-plugins/printwizard/plugin_printwizard.cpp
new file mode 100644
index 0000000..a82b3f2
--- /dev/null
+++ b/kipi-plugins/printwizard/plugin_printwizard.cpp
@@ -0,0 +1,128 @@
+/* ============================================================
+ * Author: Todd Shoemaker <todd@theshoemakers.net>
+ * Date : 2003-09-30
+ * Description :
+ *
+ * Copyright 2003 by Todd Shoemaker <todd@theshoemakers.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// Include files for Qt
+
+#include <qdir.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+
+// Local includes
+
+#include "frmprintwizard.h"
+#include "plugin_printwizard.h"
+#include "plugin_printwizard.moc"
+
+typedef KGenericFactory<Plugin_PrintWizard> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_printwizard,
+ Factory("kipiplugin_printwizard"))
+
+Plugin_PrintWizard::Plugin_PrintWizard(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin(Factory::instance(), parent, "PrintWizard")
+{
+ kdDebug( 51001 ) << "Plugin_PrintWizard plugin loaded"
+ << endl;
+}
+
+void Plugin_PrintWizard::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_printAction = new KAction (i18n("Print Wizard..."),
+ "fileprint",
+ CTRL+Key_P,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "printwizard");
+
+ addAction( m_printAction );
+
+ m_interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection selection = m_interface->currentSelection();
+ m_printAction->setEnabled( selection.isValid() &&
+ !selection.images().isEmpty() );
+
+ connect( m_interface, SIGNAL( selectionChanged( bool ) ),
+ m_printAction, SLOT( setEnabled( bool ) ) );
+}
+
+Plugin_PrintWizard::~Plugin_PrintWizard()
+{
+}
+
+void Plugin_PrintWizard::slotActivate()
+{
+ KIPI::ImageCollection album = m_interface->currentSelection();
+
+ if ( !album.isValid() )
+ return;
+
+ KURL::List fileList = album.images();
+
+ if (fileList.count() == 0)
+ {
+ KMessageBox::sorry(kapp->activeWindow(), i18n("Please select one or more photos to print."),
+ i18n("Print Wizard"));
+ return;
+ }
+
+ KIPIPrintWizardPlugin::FrmPrintWizard frm(kapp->activeWindow());
+ KStandardDirs dir;
+ QString tempPath = dir.saveLocation("tmp", "kipi-printwizardplugin-" + QString::number(getpid()) + "/");
+ frm.print(fileList, tempPath);
+ frm.exec();
+}
+
+KIPI::Category Plugin_PrintWizard::category( KAction* action ) const
+{
+ if ( action == m_printAction )
+ return KIPI::IMAGESPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMAGESPLUGIN; // no warning from compiler, please
+}
+
diff --git a/kipi-plugins/printwizard/plugin_printwizard.h b/kipi-plugins/printwizard/plugin_printwizard.h
new file mode 100644
index 0000000..bb84928
--- /dev/null
+++ b/kipi-plugins/printwizard/plugin_printwizard.h
@@ -0,0 +1,52 @@
+/* ============================================================
+ * Author: Todd Shoemaker <todd@theshoemakers.net>
+ * Date : 2003-09-30
+ * Description :
+ *
+ * Copyright 2003 by Todd Shoemaker <todd@theshoemakers.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_PRINTWIZARD_H
+#define PLUGIN_PRINTWIZARD_H
+
+// LibKIPI includes.
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+class Plugin_PrintWizard : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_PrintWizard(QObject *parent,
+ const char* name,
+ const QStringList &args);
+ ~Plugin_PrintWizard();
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+public slots:
+
+ void slotActivate();
+
+private:
+ KAction *m_printAction;
+ KIPI::Interface *m_interface;
+};
+
+#endif // PLUGIN_PRINTWIZARD_H
diff --git a/kipi-plugins/printwizard/tphoto.cpp b/kipi-plugins/printwizard/tphoto.cpp
new file mode 100644
index 0000000..f81a53b
--- /dev/null
+++ b/kipi-plugins/printwizard/tphoto.cpp
@@ -0,0 +1,152 @@
+/***************************************************************************
+ tphoto.cpp - description
+ -------------------
+ begin : Thu Sep 12 2002
+ copyright : (C) 2002 by Todd Shoemaker
+ : (C) 2007 Angelo Naselli
+ email : jtshoe11@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. *
+ * *
+ ***************************************************************************/
+
+// Qt includes.
+
+#include <qpainter.h>
+#include <qdir.h>
+#include <qmessagebox.h>
+#include <qdragobject.h>
+#include <qstringlist.h>
+#include <qurl.h>
+#include <qstrlist.h>
+
+// KDE includes.
+
+#include <kprinter.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+// Local includes.
+
+#include "tphoto.h"
+#include "utils.h"
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+#define IMAGE_FILE_MASK "*"
+//"*.jpg;*.jpeg;*.JPG;*.JPEG;*.png;*.PNG"
+
+namespace KIPIPrintWizardPlugin
+{
+
+TPhoto::TPhoto(int thumbnailSize)
+{
+ m_size = 0;
+ cropRegion = QRect(-1, -1, -1, -1);
+ rotation = 0;
+ copies = 1;
+
+ filename = "";
+ m_exiv2Iface = NULL;
+
+ m_thumbnail = NULL;
+
+ this->m_thumbnailSize = thumbnailSize;
+}
+
+TPhoto::~TPhoto()
+{
+ if (m_thumbnail)
+ delete m_thumbnail;
+ if (m_size)
+ delete m_size;
+ if (m_exiv2Iface)
+ delete m_exiv2Iface;
+}
+
+void TPhoto::loadCache()
+{
+ // load the thumbnail and size only once.
+ if (m_thumbnail)
+ delete m_thumbnail;
+
+
+ QImage photo = loadPhoto();
+
+ m_thumbnail = new QPixmap(QImage( photo.scale(m_thumbnailSize, m_thumbnailSize, QImage::ScaleMin) ));
+
+ if (m_size)
+ delete m_size;
+ m_size = new QSize(photo.width(), photo.height());
+}
+
+QPixmap & TPhoto::thumbnail()
+{
+ if (!m_thumbnail)
+ loadCache();
+ return *m_thumbnail;
+}
+
+QImage TPhoto::loadPhoto()
+{
+ QImage photo;
+
+ // Check if RAW file.
+#if KDCRAW_VERSION < 0x000106
+ QString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles());
+#else
+ QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
+#endif
+ QFileInfo fileInfo(filename.path());
+ if (rawFilesExt.upper().contains( fileInfo.extension(false).upper() ))
+ KDcrawIface::KDcraw::loadDcrawPreview(photo, filename.path());
+ else
+ photo.load(filename.path()); // PENDING(blackie) handle URL
+
+ return photo;
+}
+
+QSize & TPhoto::size() // private
+{
+ if (m_size == 0)
+ loadCache();
+ return *m_size;
+}
+
+KExiv2Iface::KExiv2 *TPhoto::exiv2Iface()
+{
+ if (!m_exiv2Iface && !filename.url().isEmpty())
+ {
+ m_exiv2Iface = new KExiv2Iface::KExiv2(filename.path());
+ }
+
+ return m_exiv2Iface;
+}
+
+int TPhoto::width()
+{
+ return size().width();
+}
+
+int TPhoto::height()
+{
+ return size().height();
+}
+
+} // NameSpace KIPIPrintWizardPlugin
+
+
diff --git a/kipi-plugins/printwizard/tphoto.h b/kipi-plugins/printwizard/tphoto.h
new file mode 100644
index 0000000..a71d991
--- /dev/null
+++ b/kipi-plugins/printwizard/tphoto.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ tphoto.h - description
+ -------------------
+ begin : Thu Sep 12 2002
+ copyright : (C) 2002 by Todd Shoemaker
+ : (C) 2007 Angelo Naselli
+ email : jtshoe11@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 TPHOTO_H
+#define TPHOTO_H
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qptrlist.h>
+#include <qrect.h>
+#include <qiconview.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <libkexiv2/kexiv2.h>
+
+class QImage;
+class QPixmap;
+
+class KPrinter;
+
+namespace KIPIPrintWizardPlugin
+{
+
+class TPhoto
+{
+ public:
+ TPhoto(int thumbnailSize);
+ ~TPhoto();
+
+ KURL filename; // full path
+
+ QPixmap & thumbnail();
+ QImage loadPhoto();
+
+ int m_thumbnailSize;
+
+ int width();
+ int height();
+
+ QRect cropRegion;
+ int copies;
+ int rotation;
+ KExiv2Iface::KExiv2 *exiv2Iface();
+
+ private:
+ QPixmap *m_thumbnail;
+ void loadCache();
+ QSize & size();
+ QSize * m_size;
+ KExiv2Iface::KExiv2 *m_exiv2Iface;
+};
+
+} // NameSpace KIPIPrintWizardPlugin
+
+#endif // TPHOTO_H
+
diff --git a/kipi-plugins/printwizard/utils.cpp b/kipi-plugins/printwizard/utils.cpp
new file mode 100644
index 0000000..cab5ccd
--- /dev/null
+++ b/kipi-plugins/printwizard/utils.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+ utils.cpp - description
+ -------------------
+ begin : Fri Jan 31 2003
+ copyright : (C) 2003 by Todd Shoemaker
+ email : jtshoe11@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. *
+ * *
+ ***************************************************************************/
+
+// C Ansi includes
+
+extern "C"
+{
+#include <unistd.h>
+#include <stdio.h>
+}
+
+// Include files for Qt
+
+#include <qstringlist.h>
+#include <qwidget.h>
+#include <qdir.h>
+#include <qprocess.h>
+
+// Include files for KDE
+
+#include <kurl.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kio/netaccess.h>
+
+namespace KIPIPrintWizardPlugin
+{
+
+int NINT(double n)
+{
+ return (int)(n + 0.5);
+}
+
+int MIN(int a, int b)
+{
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+int MAX(int a, int b)
+{
+ if (a > b)
+ return a;
+ else
+ return b;
+}
+
+// given a list of args, launch this app as a separate thread.
+// args[0] is the application to run.
+bool launchExternalApp(QStringList &args)
+{
+ QProcess process;
+ for(QStringList::Iterator it = args.begin(); it != args.end(); ++it)
+ {
+ process.addArgument(*it);
+ }
+
+ return process.start();
+}
+
+bool checkTempPath(QWidget *parent, QString tempPath)
+{
+ // does the temp path exist?
+ QDir tempDir(tempPath);
+ if (!tempDir.exists())
+ {
+ if (!tempDir.mkdir(tempDir.path()))
+ {
+ KMessageBox::sorry(parent,
+ i18n("Unable to create a temporary folder; "
+ "please make sure you have proper permissions to this folder and try again."));
+ return false;
+ }
+ }
+ return true;
+}
+
+} // NameSpace KIPIPrintWizardPlugin
+
diff --git a/kipi-plugins/printwizard/utils.h b/kipi-plugins/printwizard/utils.h
new file mode 100644
index 0000000..43d5fc4
--- /dev/null
+++ b/kipi-plugins/printwizard/utils.h
@@ -0,0 +1,37 @@
+/***************************************************************************
+ utils.h - description
+ -------------------
+ begin : Fri Jan 31 2003
+ copyright : (C) 2003 by Todd Shoemaker
+ email : jtshoe11@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 UTILS_H
+#define UTILS_H
+
+class QWidget;
+class QStringList;
+
+namespace KIPIPrintWizardPlugin
+{
+
+int NINT(double n);
+int MIN(int a, int b);
+int MAX(int a, int b);
+
+bool launchExternalApp(QStringList &args);
+bool checkTempPath(QWidget *parent, QString tempPath);
+
+} // NameSpace KIPIPrintWizardPlugin
+
+#endif // UTILS_H
+
diff --git a/kipi-plugins/rawconverter/Makefile.am b/kipi-plugins/rawconverter/Makefile.am
new file mode 100644
index 0000000..159dcb1
--- /dev/null
+++ b/kipi-plugins/rawconverter/Makefile.am
@@ -0,0 +1,28 @@
+METASOURCES = AUTO
+SUBDIRS = profiles pics
+
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(LIBKEXIV2_CFLAGS) \
+ $(LIBKDCRAW_CFLAGS) $(all_includes)
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_rawconverter.la
+
+kipiplugin_rawconverter_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+
+# Srcs for the plugin
+kipiplugin_rawconverter_la_SOURCES = plugin_rawconverter.cpp rawdecodingiface.cpp savesettingswidget.cpp \
+ actionthread.cpp previewwidget.cpp iccjpeg.c \
+ batchdialog.cpp singledialog.cpp
+
+# Libs needed by the plugin
+kipiplugin_rawconverter_la_LIBADD = -ljpeg -lpng $(LIBKEXIV2_LIBS) $(LIBKDCRAW_LIBS) $(LIBKIPI_LIBS) \
+ $(LIB_TIFF) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_rawconverter_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_rawconverter.desktop
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_rawconverter.pot
diff --git a/kipi-plugins/rawconverter/actions.h b/kipi-plugins/rawconverter/actions.h
new file mode 100644
index 0000000..5dd3e3e
--- /dev/null
+++ b/kipi-plugins/rawconverter/actions.h
@@ -0,0 +1,63 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-12-09
+ * Description : raw converter plugin action descriptions
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 ACTIONS_H
+#define ACTIONS_H
+
+namespace KIPIRawConverterPlugin
+{
+
+enum Action
+{
+ NONE = 0,
+ IDENTIFY,
+ IDENTIFY_FULL,
+ PREVIEW,
+ PROCESS
+};
+
+class EventData
+{
+
+public:
+
+ EventData()
+ {
+ starting = false;
+ success = false;
+ }
+
+ bool starting;
+ bool success;
+
+ QString filePath;
+ QString destPath;
+ QString message;
+
+ QImage image;
+
+ Action action;
+};
+
+} // NameSpace KIPIRawConverterPlugin
+
+#endif /* ACTIONS_H */
diff --git a/kipi-plugins/rawconverter/actionthread.cpp b/kipi-plugins/rawconverter/actionthread.cpp
new file mode 100644
index 0000000..52a41b5
--- /dev/null
+++ b/kipi-plugins/rawconverter/actionthread.cpp
@@ -0,0 +1,267 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-12-03
+ * Description : a class to manage plugin actions using threads
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * NOTE: Do not use kdDebug() in this implementation because
+ * it will be multithreaded. Use qDebug() instead.
+ * See B.K.O #133026 for details.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// Qt includes.
+
+#include <qapplication.h>
+#include <qdir.h>
+#include <qdeepcopy.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/dcrawinfocontainer.h>
+
+// Local includes.
+
+#include "actionthread.h"
+
+namespace KIPIRawConverterPlugin
+{
+
+ActionThread::ActionThread(QObject *parent)
+ : QThread(), m_parent(parent)
+{
+}
+
+ActionThread::~ActionThread()
+{
+ // cancel the thread
+ cancel();
+ // wait for the thread to finish
+ wait();
+}
+
+void ActionThread::identifyRawFile(const KURL& url, bool full)
+{
+ KURL::List oneFile;
+ oneFile.append(url);
+ identifyRawFiles(oneFile, full);
+}
+
+void ActionThread::identifyRawFiles(const KURL::List& urlList, bool full)
+{
+ for (KURL::List::const_iterator it = urlList.begin();
+ it != urlList.end(); ++it )
+ {
+ Task *t = new Task;
+ t->filePath = QDeepCopy<QString>((*it).path()); //deep copy
+ t->action = full ? IDENTIFY_FULL : IDENTIFY;
+ m_taskQueue.enqueue(t);
+ }
+}
+
+void ActionThread::processRawFile(const KURL& url)
+{
+ KURL::List oneFile;
+ oneFile.append(url);
+ processRawFiles(oneFile);
+}
+
+void ActionThread::processHalfRawFile(const KURL& url)
+{
+ KURL::List oneFile;
+ oneFile.append(url);
+ processHalfRawFiles(oneFile);
+}
+
+void ActionThread::setRawDecodingSettings(KDcrawIface::RawDecodingSettings rawDecodingSettings,
+ SaveSettingsWidget::OutputFormat outputFormat)
+{
+ m_rawDecodingSettings = rawDecodingSettings;
+ m_outputFormat = outputFormat;
+}
+
+void ActionThread::processRawFiles(const KURL::List& urlList)
+{
+ for (KURL::List::const_iterator it = urlList.begin();
+ it != urlList.end(); ++it )
+ {
+ Task *t = new Task;
+ t->filePath = QDeepCopy<QString>((*it).path()); //deep copy
+ t->outputFormat = m_outputFormat;
+ t->decodingSettings = m_rawDecodingSettings;
+ t->action = PROCESS;
+ m_taskQueue.enqueue(t);
+ }
+}
+
+void ActionThread::processHalfRawFiles(const KURL::List& urlList)
+{
+ for (KURL::List::const_iterator it = urlList.begin();
+ it != urlList.end(); ++it )
+ {
+ Task *t = new Task;
+ t->filePath = QDeepCopy<QString>((*it).path()); //deep copy
+ t->outputFormat = m_outputFormat;
+ t->decodingSettings = m_rawDecodingSettings;
+ t->action = PREVIEW;
+ m_taskQueue.enqueue(t);
+ }
+}
+
+void ActionThread::cancel()
+{
+ m_taskQueue.flush();
+ m_dcrawIface.cancel();
+}
+
+void ActionThread::run()
+{
+ while (!m_taskQueue.isEmpty())
+ {
+ Task *t = m_taskQueue.dequeue();
+ if (!t) continue;
+
+ QString errString;
+
+ EventData *d = new EventData;
+
+ switch (t->action)
+ {
+ case IDENTIFY:
+ case IDENTIFY_FULL:
+ {
+ // Get embedded RAW file thumbnail.
+ QImage image;
+ m_dcrawIface.loadDcrawPreview(image, t->filePath);
+
+ // Identify Camera model.
+ KDcrawIface::DcrawInfoContainer info;
+ m_dcrawIface.rawFileIdentify(info, t->filePath);
+
+ QString identify = i18n("Cannot identify Raw image");
+ if (info.isDecodable)
+ {
+ if (t->action == IDENTIFY)
+ identify = info.make + QString("-") + info.model;
+ else
+ {
+ identify = i18n("Make: %1\n").arg(info.make);
+ identify.append(i18n("Model: %1\n").arg(info.model));
+
+ if (info.dateTime.isValid())
+ {
+ identify.append(i18n("Created: %1\n")
+ .arg(KGlobal::locale()->formatDateTime(info.dateTime, true, true)));
+ }
+
+ if (info.aperture != -1.0)
+ {
+ identify.append(i18n("Aperture: f/%1\n").arg(QString::number(info.aperture)));
+ }
+
+ if (info.focalLength != -1.0)
+ {
+ identify.append(i18n("Focal: %1 mm\n").arg(info.focalLength));
+ }
+
+ if (info.exposureTime != -1.0)
+ {
+ identify.append(i18n("Exposure: 1/%1 s\n").arg(info.exposureTime));
+ }
+
+ if (info.sensitivity != -1)
+ {
+ identify.append(i18n("Sensitivity: %1 ISO").arg(info.sensitivity));
+ }
+ }
+ }
+
+ EventData *r = new EventData;
+ r->action = t->action;
+ r->filePath = t->filePath;
+ r->image = image;
+ r->message = identify;
+ r->success = true;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, r));
+ break;
+ }
+
+ case PREVIEW:
+ {
+ d->action = PREVIEW;
+ d->filePath = t->filePath;
+ d->starting = true;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ QString destPath;
+ bool result = m_dcrawIface.decodeHalfRAWImage(t->filePath, destPath,
+ t->outputFormat, t->decodingSettings);
+
+ EventData *r = new EventData;
+ r->action = PREVIEW;
+ r->filePath = t->filePath;
+ r->destPath = destPath;
+ r->success = result;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, r));
+ break;
+ }
+
+ case PROCESS:
+ {
+ d->action = PROCESS;
+ d->filePath = t->filePath;
+ d->starting = true;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ QString destPath;
+ bool result = m_dcrawIface.decodeRAWImage(t->filePath, destPath,
+ t->outputFormat, t->decodingSettings);
+
+ EventData *r = new EventData;
+ r->action = PROCESS;
+ r->filePath = t->filePath;
+ r->destPath = destPath;
+ r->success = result;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, r));
+ break;
+ }
+
+ default:
+ {
+ qWarning("KIPIRawConverterPlugin:ActionThread: Unknown action specified");
+ delete d;
+ }
+ }
+
+ delete t;
+ }
+}
+
+} // NameSpace KIPIRawConverterPlugin
diff --git a/kipi-plugins/rawconverter/actionthread.h b/kipi-plugins/rawconverter/actionthread.h
new file mode 100644
index 0000000..bebc7b9
--- /dev/null
+++ b/kipi-plugins/rawconverter/actionthread.h
@@ -0,0 +1,103 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-12-03
+ * Description : a class to manage plugin actions using threads
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 ACTIONTHREAD_H
+#define ACTIONTHREAD_H
+
+// Qt includes.
+
+#include <qthread.h>
+#include <qstring.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rawdecodingsettings.h>
+
+// Local includes.
+
+#include "rawdecodingiface.h"
+#include "savesettingswidget.h"
+#include "actions.h"
+#include "mtqueue.h"
+
+class QObject;
+
+namespace KIPIRawConverterPlugin
+{
+
+class ActionThread : public QThread
+{
+
+public:
+
+ ActionThread(QObject *parent);
+ ~ActionThread();
+
+ void setRawDecodingSettings(KDcrawIface::RawDecodingSettings rawDecodingSettings,
+ SaveSettingsWidget::OutputFormat outputFormat);
+
+ void identifyRawFile(const KURL& url, bool full=false);
+ void identifyRawFiles(const KURL::List& urlList, bool full=false);
+
+ void processHalfRawFile(const KURL& url);
+ void processHalfRawFiles(const KURL::List& urlList);
+
+ void processRawFile(const KURL& url);
+ void processRawFiles(const KURL::List& urlList);
+
+ void cancel();
+
+protected:
+
+ void run();
+
+private:
+
+ struct Task_
+ {
+ QString filePath;
+ Action action;
+ SaveSettingsWidget::OutputFormat outputFormat;
+ KDcrawIface::RawDecodingSettings decodingSettings;
+ };
+
+ typedef struct Task_ Task;
+
+ QObject *m_parent;
+
+ SaveSettingsWidget::OutputFormat m_outputFormat;
+
+ KDcrawIface::RawDecodingSettings m_rawDecodingSettings;
+
+ RawDecodingIface m_dcrawIface;
+
+ MTQueue<Task> m_taskQueue;
+};
+
+} // NameSpace KIPIRawConverterPlugin
+
+#endif /* ACTIONTHREAD_H */
diff --git a/kipi-plugins/rawconverter/batchdialog.cpp b/kipi-plugins/rawconverter/batchdialog.cpp
new file mode 100644
index 0000000..63447e6
--- /dev/null
+++ b/kipi-plugins/rawconverter/batchdialog.cpp
@@ -0,0 +1,661 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-24
+ * Description : Raw converter batch dialog
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+}
+
+// C++ includes.
+
+#include <cstdio>
+
+// Qt includes.
+
+#include <qframe.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qtimer.h>
+#include <qfileinfo.h>
+#include <qevent.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qfile.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <kdebug.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kiconloader.h>
+#include <kprogress.h>
+#include <kio/renamedlg.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/dcrawsettingswidget.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "rawdecodingiface.h"
+#include "savesettingswidget.h"
+#include "actionthread.h"
+#include "clistviewitem.h"
+#include "batchdialog.h"
+#include "batchdialog.moc"
+
+namespace KIPIRawConverterPlugin
+{
+
+BatchDialog::BatchDialog(QWidget* /*parent*/)
+ : KDialogBase(0, 0, false, i18n("Raw Images Batch Converter"),
+ Help|Default|User1|User2|Close, Close, true,
+ i18n("Con&vert"), i18n("&Abort"))
+{
+ m_currentConvertItem = 0;
+ m_thread = 0;
+ m_page = new QWidget( this );
+ setMainWidget( m_page );
+ QGridLayout *mainLayout = new QGridLayout(m_page, 2, 1, 0, spacingHint());
+
+ //---------------------------------------------
+
+ m_listView = new KListView(m_page);
+ m_listView->addColumn( i18n("Thumbnail") );
+ m_listView->addColumn( i18n("Raw File") );
+ m_listView->addColumn( i18n("Target File") );
+ m_listView->addColumn( i18n("Camera") );
+ m_listView->setResizeMode(QListView::AllColumns);
+ m_listView->setAllColumnsShowFocus(true);
+ m_listView->setSorting(-1);
+ m_listView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ m_listView->setSelectionMode(QListView::Single);
+ m_listView->setMinimumWidth(450);
+
+ // ---------------------------------------------------------------
+
+ m_decodingSettingsBox = new KDcrawIface::DcrawSettingsWidget(m_page, false, true, true);
+ m_saveSettingsBox = new SaveSettingsWidget(m_page);
+
+#if KDCRAW_VERSION >= 0x000105
+ m_decodingSettingsBox->addItem(m_saveSettingsBox, i18n("Save settings"));
+ m_decodingSettingsBox->updateMinimumWidth();
+#else
+ m_decodingSettingsBox->insertTab(m_saveSettingsBox, i18n("Save settings"));
+#endif
+
+ m_progressBar = new KProgress(m_page);
+ m_progressBar->setMaximumHeight( fontMetrics().height()+2 );
+ m_progressBar->hide();
+
+ mainLayout->addMultiCellWidget(m_listView, 0, 2, 0, 0);
+ mainLayout->addMultiCellWidget(m_decodingSettingsBox, 0, 0, 1, 1);
+ mainLayout->addMultiCellWidget(m_progressBar, 1, 1, 1, 1);
+ mainLayout->setColStretch(0, 10);
+ mainLayout->setRowStretch(2, 10);
+
+ // ---------------------------------------------------------------
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("RAW Image Converter"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to batch convert Raw images"),
+ "(c) 2003-2005, Renchi Raju\n"
+ "(c) 2006-2008, Gilles Caulier");
+
+ m_about->addAuthor("Renchi Raju", I18N_NOOP("Original author"),
+ "renchi at pooh dot tam dot uiuc dot edu");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"),
+ this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // ---------------------------------------------------------------
+
+ setButtonTip( User1, i18n("<p>Start converting the Raw images from current settings"));
+ setButtonTip( User2, i18n("<p>Abort the current Raw files conversion"));
+ setButtonTip( Close, i18n("<p>Exit Raw Converter"));
+
+ m_blinkConvertTimer = new QTimer(this);
+ m_thread = new ActionThread(this);
+
+ // ---------------------------------------------------------------
+
+ connect(m_blinkConvertTimer, SIGNAL(timeout()),
+ this, SLOT(slotConvertBlinkTimerDone()));
+
+ connect(m_saveSettingsBox, SIGNAL(signalSaveFormatChanged()),
+ this, SLOT(slotSaveFormatChanged()));
+
+ // ---------------------------------------------------------------
+
+ m_itemDict.setAutoDelete(true);
+ busy(false);
+ readSettings();
+}
+
+BatchDialog::~BatchDialog()
+{
+ delete m_about;
+ delete m_thread;
+}
+
+void BatchDialog::closeEvent(QCloseEvent *e)
+{
+ if (!e) return;
+ m_blinkConvertTimer->stop();
+ m_thread->cancel();
+ saveSettings();
+ e->accept();
+}
+
+void BatchDialog::slotClose()
+{
+ m_blinkConvertTimer->stop();
+ m_thread->cancel();
+ saveSettings();
+ KDialogBase::slotClose();
+}
+
+void BatchDialog::slotDefault()
+{
+ m_decodingSettingsBox->setDefaultSettings();
+ m_saveSettingsBox->setDefaultSettings();
+}
+
+void BatchDialog::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("RawConverter Settings");
+
+ m_decodingSettingsBox->setWhiteBalance((KDcrawIface::RawDecodingSettings::WhiteBalance)
+ config.readNumEntry("White Balance",
+ KDcrawIface::RawDecodingSettings::CAMERA));
+ m_decodingSettingsBox->setCustomWhiteBalance(config.readNumEntry("Custom White Balance", 6500));
+ m_decodingSettingsBox->setCustomWhiteBalanceGreen(config.readDoubleNumEntry("Custom White Balance Green", 1.0));
+ m_decodingSettingsBox->setFourColor(config.readBoolEntry("Four Color RGB", false));
+ m_decodingSettingsBox->setUnclipColor(config.readNumEntry("Unclip Color", 0));
+ m_decodingSettingsBox->setDontStretchPixels(config.readBoolEntry("Dont Stretch Pixels", false));
+ m_decodingSettingsBox->setNoiseReduction(config.readBoolEntry("Use Noise Reduction", false));
+ m_decodingSettingsBox->setBrightness(config.readDoubleNumEntry("Brightness Multiplier", 1.0));
+ m_decodingSettingsBox->setUseBlackPoint(config.readBoolEntry("Use Black Point", false));
+ m_decodingSettingsBox->setBlackPoint(config.readNumEntry("Black Point", 0));
+#if KDCRAW_VERSION >= 0x000105
+ m_decodingSettingsBox->setUseWhitePoint(config.readBoolEntry("Use White Point", false));
+ m_decodingSettingsBox->setWhitePoint(config.readNumEntry("White Point", 0));
+ m_decodingSettingsBox->setMedianFilterPasses(config.readNumEntry("Median Filter Passes", 0));
+#endif
+ m_decodingSettingsBox->setNRThreshold(config.readNumEntry("NR Threshold", 100));
+ m_decodingSettingsBox->setUseCACorrection(config.readBoolEntry("EnableCACorrection", false));
+ m_decodingSettingsBox->setcaRedMultiplier(config.readDoubleNumEntry("caRedMultiplier", 1.0));
+ m_decodingSettingsBox->setcaBlueMultiplier(config.readDoubleNumEntry("caBlueMultiplier", 1.0));
+
+ m_decodingSettingsBox->setQuality(
+ (KDcrawIface::RawDecodingSettings::DecodingQuality)config.readNumEntry("Decoding Quality",
+ (int)(KDcrawIface::RawDecodingSettings::BILINEAR)));
+
+ m_decodingSettingsBox->setOutputColorSpace(
+ (KDcrawIface::RawDecodingSettings::OutputColorSpace)config.readNumEntry("Output Color Space",
+ (int)(KDcrawIface::RawDecodingSettings::SRGB)));
+
+ m_saveSettingsBox->setFileFormat(
+ (SaveSettingsWidget::OutputFormat)config.readNumEntry("Output Format",
+ (int)(SaveSettingsWidget::OUTPUT_PNG)));
+
+ m_saveSettingsBox->setConflictRule(
+ (SaveSettingsWidget::ConflictRule)config.readNumEntry("Conflict",
+ (int)(SaveSettingsWidget::OVERWRITE)));
+
+ resize(configDialogSize(config, QString("Batch Raw Converter Dialog")));
+}
+
+void BatchDialog::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("RawConverter Settings");
+
+ config.writeEntry("White Balance", m_decodingSettingsBox->whiteBalance());
+ config.writeEntry("Custom White Balance", m_decodingSettingsBox->customWhiteBalance());
+ config.writeEntry("Custom White Balance Green", m_decodingSettingsBox->customWhiteBalanceGreen());
+ config.writeEntry("Four Color RGB", m_decodingSettingsBox->useFourColor());
+ config.writeEntry("Unclip Color", m_decodingSettingsBox->unclipColor());
+ config.writeEntry("Dont Stretch Pixels", m_decodingSettingsBox->useDontStretchPixels());
+ config.writeEntry("Use Noise Reduction", m_decodingSettingsBox->useNoiseReduction());
+ config.writeEntry("Brightness Multiplier", m_decodingSettingsBox->brightness());
+ config.writeEntry("Use Black Point", m_decodingSettingsBox->useBlackPoint());
+ config.writeEntry("Black Point", m_decodingSettingsBox->blackPoint());
+#if KDCRAW_VERSION >= 0x000105
+ config.writeEntry("Use White Point", m_decodingSettingsBox->useWhitePoint());
+ config.writeEntry("White Point", m_decodingSettingsBox->whitePoint());
+ config.writeEntry("Median Filter Passes", m_decodingSettingsBox->medianFilterPasses());
+#endif
+ config.writeEntry("NR Threshold", m_decodingSettingsBox->NRThreshold());
+ config.writeEntry("EnableCACorrection", m_decodingSettingsBox->useCACorrection());
+ config.writeEntry("caRedMultiplier", m_decodingSettingsBox->caRedMultiplier());
+ config.writeEntry("caBlueMultiplier", m_decodingSettingsBox->caBlueMultiplier());
+ config.writeEntry("Decoding Quality", (int)m_decodingSettingsBox->quality());
+ config.writeEntry("Output Color Space", (int)m_decodingSettingsBox->outputColorSpace());
+
+ config.writeEntry("Output Format", (int)m_saveSettingsBox->fileFormat());
+ config.writeEntry("Conflict", (int)m_saveSettingsBox->conflictRule());
+
+ saveDialogSize(config, QString("Batch Raw Converter Dialog"));
+ config.sync();
+}
+
+void BatchDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("rawconverter", "kipi-plugins");
+}
+
+void BatchDialog::slotUser1()
+{
+ m_fileList.clear();
+
+ QListViewItemIterator it( m_listView );
+ while ( it.current() )
+ {
+ CListViewItem *item = (CListViewItem*) it.current();
+ if (item->isEnabled())
+ {
+ item->setPixmap(1, 0);
+ m_fileList.append(item->rawItem->directory + QString("/") + item->rawItem->src);
+ }
+ ++it;
+ }
+
+ if (m_fileList.empty())
+ {
+ KMessageBox::error(this, i18n("There is no Raw file to process in the list!"));
+ busy(false);
+ slotAborted();
+ return;
+ }
+
+ m_progressBar->setTotalSteps(m_fileList.count());
+ m_progressBar->setProgress(0);
+ m_progressBar->show();
+
+ KDcrawIface::RawDecodingSettings rawDecodingSettings;
+ rawDecodingSettings.whiteBalance = m_decodingSettingsBox->whiteBalance();
+ rawDecodingSettings.customWhiteBalance = m_decodingSettingsBox->customWhiteBalance();
+ rawDecodingSettings.customWhiteBalanceGreen = m_decodingSettingsBox->customWhiteBalanceGreen();
+ rawDecodingSettings.RGBInterpolate4Colors = m_decodingSettingsBox->useFourColor();
+ rawDecodingSettings.unclipColors = m_decodingSettingsBox->unclipColor();
+ rawDecodingSettings.DontStretchPixels = m_decodingSettingsBox->useDontStretchPixels();
+ rawDecodingSettings.enableNoiseReduction = m_decodingSettingsBox->useNoiseReduction();
+ rawDecodingSettings.brightness = m_decodingSettingsBox->brightness();
+ rawDecodingSettings.enableBlackPoint = m_decodingSettingsBox->useBlackPoint();
+ rawDecodingSettings.blackPoint = m_decodingSettingsBox->blackPoint();
+#if KDCRAW_VERSION >= 0x000105
+ rawDecodingSettings.enableWhitePoint = m_decodingSettingsBox->useWhitePoint();
+ rawDecodingSettings.whitePoint = m_decodingSettingsBox->whitePoint();
+ rawDecodingSettings.medianFilterPasses = m_decodingSettingsBox->medianFilterPasses();
+#endif
+ rawDecodingSettings.NRThreshold = m_decodingSettingsBox->NRThreshold();
+ rawDecodingSettings.enableCACorrection = m_decodingSettingsBox->useCACorrection();
+ rawDecodingSettings.caMultiplier[0] = m_decodingSettingsBox->caRedMultiplier();
+ rawDecodingSettings.caMultiplier[1] = m_decodingSettingsBox->caBlueMultiplier();
+ rawDecodingSettings.RAWQuality = m_decodingSettingsBox->quality();
+ rawDecodingSettings.outputColorSpace = m_decodingSettingsBox->outputColorSpace();
+
+ m_thread->setRawDecodingSettings(rawDecodingSettings, m_saveSettingsBox->fileFormat());
+ processOne();
+}
+
+void BatchDialog::slotUser2()
+{
+ m_blinkConvertTimer->stop();
+ m_fileList.clear();
+ m_thread->cancel();
+ busy(false);
+
+ if (m_currentConvertItem)
+ m_currentConvertItem->viewItem->setPixmap(1, SmallIcon("cancel"));
+
+ QTimer::singleShot(500, this, SLOT(slotAborted()));
+}
+
+void BatchDialog::slotAborted()
+{
+ m_progressBar->setProgress(0);
+ m_progressBar->hide();
+}
+
+void BatchDialog::addItems(const QStringList& itemList)
+{
+ QString ext;
+
+ switch(m_saveSettingsBox->fileFormat())
+ {
+ case SaveSettingsWidget::OUTPUT_JPEG:
+ ext = "jpg";
+ break;
+ case SaveSettingsWidget::OUTPUT_TIFF:
+ ext = "tif";
+ break;
+ case SaveSettingsWidget::OUTPUT_PPM:
+ ext = "ppm";
+ break;
+ case SaveSettingsWidget::OUTPUT_PNG:
+ ext = "png";
+ break;
+ }
+
+ KURL::List urlList;
+
+ QPixmap pix(SmallIcon( "file_broken", KIcon::SizeLarge, KIcon::DisabledState ));
+
+ for (QStringList::const_iterator it = itemList.begin();
+ it != itemList.end(); ++it)
+ {
+ QFileInfo fi(*it);
+ if (fi.exists() && !m_itemDict.find(fi.fileName()))
+ {
+ RawItem *item = new RawItem;
+ item->directory = fi.dirPath();
+ item->src = fi.fileName();
+ item->dest = fi.baseName() + QString(".") + ext;
+ new CListViewItem(m_listView, pix, item, m_listView->lastItem());
+ m_itemDict.insert(item->src, item);
+ urlList.append(fi.absFilePath());
+ }
+ }
+
+ if (!urlList.empty())
+ {
+ m_thread->identifyRawFiles(urlList);
+ if (!m_thread->running())
+ m_thread->start();
+ }
+}
+
+void BatchDialog::slotSaveFormatChanged()
+{
+ QString ext;
+
+ switch(m_saveSettingsBox->fileFormat())
+ {
+ case SaveSettingsWidget::OUTPUT_JPEG:
+ ext = "jpg";
+ break;
+ case SaveSettingsWidget::OUTPUT_TIFF:
+ ext = "tif";
+ break;
+ case SaveSettingsWidget::OUTPUT_PPM:
+ ext = "ppm";
+ break;
+ case SaveSettingsWidget::OUTPUT_PNG:
+ ext = "png";
+ break;
+ }
+
+ QListViewItemIterator it( m_listView );
+ while ( it.current() )
+ {
+ CListViewItem *item = (CListViewItem*) it.current();
+ if (item->isEnabled())
+ {
+ RawItem *rawItem = item->rawItem;
+ QFileInfo fi(rawItem->directory + QString("/") + rawItem->src);
+ rawItem->dest = fi.baseName() + QString(".") + ext;
+ item->setText(2, rawItem->dest);
+ }
+ ++it;
+ }
+}
+
+void BatchDialog::processOne()
+{
+ if (m_fileList.empty())
+ {
+ busy(false);
+ slotAborted();
+ return;
+ }
+
+ QString file(m_fileList.first());
+ m_fileList.pop_front();
+
+ m_thread->processRawFile(KURL(file));
+ if (!m_thread->running())
+ m_thread->start();
+}
+
+void BatchDialog::busy(bool busy)
+{
+ enableButton(User1, !busy);
+ enableButton(User2, busy);
+ enableButton(Close, !busy);
+
+ m_decodingSettingsBox->setEnabled(!busy);
+ m_saveSettingsBox->setEnabled(!busy);
+ m_listView->setEnabled(!busy);
+
+ busy ? m_page->setCursor(KCursor::waitCursor()) : m_page->unsetCursor();
+}
+
+void BatchDialog::slotConvertBlinkTimerDone()
+{
+ if(m_convertBlink)
+ {
+ if (m_currentConvertItem)
+ m_currentConvertItem->viewItem->setPixmap(1, SmallIcon("1rightarrow"));
+ }
+ else
+ {
+ if (m_currentConvertItem)
+ m_currentConvertItem->viewItem->setPixmap(1, SmallIcon("2rightarrow"));
+ }
+
+ m_convertBlink = !m_convertBlink;
+ m_blinkConvertTimer->start(500);
+}
+
+void BatchDialog::processing(const QString& file)
+{
+ QString filename = QFileInfo(file).fileName();
+ m_currentConvertItem = m_itemDict.find(filename);
+ if (m_currentConvertItem)
+ {
+ m_listView->setSelected(m_currentConvertItem->viewItem, true);
+ m_listView->ensureItemVisible(m_currentConvertItem->viewItem);
+ }
+
+ m_convertBlink = false;
+ m_blinkConvertTimer->start(500);
+}
+
+void BatchDialog::processed(const QString& file, const QString& tmpFile)
+{
+ m_blinkConvertTimer->stop();
+ QString filename = QFileInfo(file).fileName();
+ QString destFile(m_currentConvertItem->directory + QString("/") + m_currentConvertItem->dest);
+
+ if (m_saveSettingsBox->conflictRule() != SaveSettingsWidget::OVERWRITE)
+ {
+ struct stat statBuf;
+ if (::stat(QFile::encodeName(destFile), &statBuf) == 0)
+ {
+ KIO::RenameDlg dlg(this, i18n("Save Raw Image converted from '%1' as")
+ .arg(m_currentConvertItem->src),
+ tmpFile, destFile,
+ KIO::RenameDlg_Mode(KIO::M_SINGLE | KIO::M_OVERWRITE | KIO::M_SKIP));
+
+ switch (dlg.exec())
+ {
+ case KIO::R_CANCEL:
+ case KIO::R_SKIP:
+ {
+ destFile = QString();
+ m_currentConvertItem->viewItem->setPixmap(1, SmallIcon("cancel"));
+ break;
+ }
+ case KIO::R_RENAME:
+ {
+ destFile = dlg.newDestURL().path();
+ break;
+ }
+ default: // Overwrite.
+ break;
+ }
+ }
+ }
+
+ if (!destFile.isEmpty())
+ {
+ if (::rename(QFile::encodeName(tmpFile), QFile::encodeName(destFile)) != 0)
+ {
+ KMessageBox::error(this, i18n("Failed to save image %1").arg( destFile ));
+ m_currentConvertItem->viewItem->setPixmap(1, SmallIcon("cancel"));
+ }
+ else
+ {
+ m_currentConvertItem->dest = QFileInfo(destFile).fileName();
+ m_currentConvertItem->viewItem->setText(2, m_currentConvertItem->dest);
+ m_currentConvertItem->viewItem->setPixmap(1, SmallIcon("ok"));
+ }
+ }
+
+ m_progressBar->advance(1);
+ m_currentConvertItem = 0;
+}
+
+void BatchDialog::processingFailed(const QString& file)
+{
+ QString filename = QFileInfo(file).fileName();
+ m_currentConvertItem->viewItem->setPixmap(1, SmallIcon("no"));
+ m_progressBar->advance(1);
+ m_currentConvertItem = 0;
+}
+
+void BatchDialog::customEvent(QCustomEvent *event)
+{
+ if (!event) return;
+
+ EventData *d = (EventData*) event->data();
+ if (!d) return;
+
+ QString text;
+
+ if (d->starting) // Something have been started...
+ {
+ switch (d->action)
+ {
+ case(IDENTIFY):
+ break;
+ case(PROCESS):
+ {
+ busy(true);
+ processing(d->filePath);
+ break;
+ }
+ default:
+ {
+ kdWarning( 51000 ) << "KIPIRawConverterPlugin: Unknown event" << endl;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (!d->success) // Something is failed...
+ {
+ switch (d->action)
+ {
+ case(IDENTIFY):
+ break;
+ case(PROCESS):
+ {
+ processingFailed(d->filePath);
+ processOne();
+ break;
+ }
+ default:
+ {
+ kdWarning( 51000 ) << "KIPIRawConverterPlugin: Unknown event" << endl;
+ break;
+ }
+ }
+ }
+ else // Something is done...
+ {
+ switch (d->action)
+ {
+ case(IDENTIFY):
+ {
+ QFileInfo fi(d->filePath);
+ RawItem *rawItem = m_itemDict.find(fi.fileName());
+ if (rawItem)
+ {
+ if (!d->image.isNull())
+ {
+ QPixmap pix = QPixmap(d->image.scale(64, 64, QImage::ScaleMin));
+ rawItem->viewItem->setThumbnail(pix);
+ }
+ rawItem->viewItem->setText(3, d->message);
+ rawItem->identity = d->message;
+ }
+ break;
+ }
+ case(PROCESS):
+ {
+ processed(d->filePath, d->destPath);
+ processOne();
+ break;
+ }
+ default:
+ {
+ kdWarning( 51000 ) << "KIPIRawConverterPlugin: Unknown event" << endl;
+ break;
+ }
+ }
+ }
+ }
+
+ delete d;
+}
+
+} // NameSpace KIPIRawConverterPlugin
diff --git a/kipi-plugins/rawconverter/batchdialog.h b/kipi-plugins/rawconverter/batchdialog.h
new file mode 100644
index 0000000..792fca6
--- /dev/null
+++ b/kipi-plugins/rawconverter/batchdialog.h
@@ -0,0 +1,130 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-24
+ * Description : Raw converter batch dialog
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 BATCHDIALOG_H
+#define BATCHDIALOG_H
+
+// Qt includes.
+
+#include <qstringlist.h>
+#include <qdict.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QTimer;
+class QWidget;
+class QCustomEvent;
+class QCloseEvent;
+
+class KListView;
+class KProgress;
+
+namespace KDcrawIface
+{
+class DcrawSettingsWidget;
+}
+
+namespace KIPIRawConverterPlugin
+{
+
+class ActionThread;
+class SaveSettingsWidget;
+struct RawItem;
+
+class BatchDialog : public KDialogBase
+{
+
+Q_OBJECT
+
+public:
+
+ BatchDialog(QWidget *parent);
+ ~BatchDialog();
+
+ void addItems(const QStringList& itemList);
+
+protected:
+
+ void customEvent(QCustomEvent *event);
+ void closeEvent(QCloseEvent *e);
+
+private:
+
+ void readSettings();
+ void saveSettings();
+
+ void busy(bool busy);
+
+ void processOne();
+ void processing(const QString& file);
+ void processed(const QString& file, const QString& tmpFile);
+ void processingFailed(const QString& file);
+
+private slots:
+
+ void slotDefault();
+ void slotClose();
+ void slotHelp();
+ void slotUser1();
+ void slotUser2();
+ void slotAborted();
+
+ void slotSaveFormatChanged();
+ void slotConvertBlinkTimerDone();
+
+private:
+
+ bool m_convertBlink;
+
+ QTimer *m_blinkConvertTimer;
+
+ QWidget *m_page;
+
+ QDict<RawItem> m_itemDict;
+
+ QStringList m_fileList;
+
+ KProgress *m_progressBar;
+
+ KListView *m_listView;
+
+ RawItem *m_currentConvertItem;
+
+ ActionThread *m_thread;
+
+ SaveSettingsWidget *m_saveSettingsBox;
+
+ KDcrawIface::DcrawSettingsWidget *m_decodingSettingsBox;
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIRawConverterPlugin
+
+#endif /* BATCHDIALOG_H */
diff --git a/kipi-plugins/rawconverter/clistviewitem.h b/kipi-plugins/rawconverter/clistviewitem.h
new file mode 100644
index 0000000..f7e3065
--- /dev/null
+++ b/kipi-plugins/rawconverter/clistviewitem.h
@@ -0,0 +1,116 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-25
+ * Description : Raw file list view used into batch converter.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 CLISTVIEWITEM_H
+#define CLISTVIEWITEM_H
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qpainter.h>
+
+// KDE includes.
+
+#include <klistview.h>
+
+class QPixmap;
+
+namespace KIPIRawConverterPlugin
+{
+
+class CListViewItem;
+
+struct RawItem
+{
+ QString src;
+ QString dest;
+ QString directory;
+ QString identity;
+
+ CListViewItem *viewItem;
+};
+
+class CListViewItem : public KListViewItem
+{
+
+public:
+
+ struct RawItem *rawItem;
+
+public:
+
+ CListViewItem(KListView *view, const QPixmap& pixmap,
+ RawItem *item, QListViewItem *after)
+ : KListViewItem(view, after), rawItem(item)
+ {
+ rawItem->viewItem = this;
+ setThumbnail(pixmap);
+ setText(1, rawItem->src);
+ setText(2, rawItem->dest);
+ setEnabled(true);
+ }
+
+ ~CListViewItem(){}
+
+ void setThumbnail(const QPixmap& pixmap)
+ {
+ setPixmap(0, pixmap);
+ }
+
+ void setEnabled(bool d)
+ {
+ m_enabled = d;
+ repaint();
+ }
+
+ bool isEnabled(void)
+ {
+ return m_enabled;
+ }
+
+protected:
+
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
+ {
+ if (m_enabled)
+ {
+ KListViewItem::paintCell(p, cg, column, width, alignment);
+ }
+ else
+ {
+ QColorGroup _cg( cg );
+ QColor c = _cg.text();
+ _cg.setColor( QColorGroup::Text, Qt::gray );
+ KListViewItem::paintCell( p, _cg, column, width, alignment );
+ _cg.setColor( QColorGroup::Text, c );
+ }
+ }
+
+private:
+
+ bool m_enabled;
+};
+
+} // NameSpace KIPIRawConverterPlugin
+
+#endif /* CLISTVIEWITEM_H */
diff --git a/kipi-plugins/rawconverter/iccjpeg.c b/kipi-plugins/rawconverter/iccjpeg.c
new file mode 100644
index 0000000..fefa950
--- /dev/null
+++ b/kipi-plugins/rawconverter/iccjpeg.c
@@ -0,0 +1,270 @@
+/*
+ * Little cms
+ * Copyright (C) 1998-2004 Marti Maria
+ *
+ * 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 OR COPYRIGHT HOLDERS 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.
+ *
+ * iccprofile.c
+ *
+ * This file provides code to read and write International Color Consortium
+ * (ICC) device profiles embedded in JFIF JPEG image files. The ICC has
+ * defined a standard format for including such data in JPEG "APP2" markers.
+ * The code given here does not know anything about the internal structure
+ * of the ICC profile data; it just knows how to put the profile data into
+ * a JPEG file being written, or get it back out when reading.
+ *
+ * This code depends on new features added to the IJG JPEG library as of
+ * IJG release 6b; it will not compile or work with older IJG versions.
+ *
+ * NOTE: this code would need surgery to work on 16-bit-int machines
+ * with ICC profiles exceeding 64K bytes in size. If you need to do that,
+ * change all the "unsigned int" variables to "INT32". You'll also need
+ * to find a malloc() replacement that can allocate more than 64K.
+ */
+
+#include "iccjpeg.h"
+#include <stdlib.h> /* define malloc() */
+
+
+/*
+ * Since an ICC profile can be larger than the maximum size of a JPEG marker
+ * (64K), we need provisions to split it into multiple markers. The format
+ * defined by the ICC specifies one or more APP2 markers containing the
+ * following data:
+ * Identifying string ASCII "ICC_PROFILE\0" (12 bytes)
+ * Marker sequence number 1 for first APP2, 2 for next, etc (1 byte)
+ * Number of markers Total number of APP2's used (1 byte)
+ * Profile data (remainder of APP2 data)
+ * Decoders should use the marker sequence numbers to reassemble the profile,
+ * rather than assuming that the APP2 markers appear in the correct sequence.
+ */
+
+#define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */
+#define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */
+#define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */
+#define MAX_DATA_BYTES_IN_MARKER (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
+
+
+/*
+ * This routine writes the given ICC profile data into a JPEG file.
+ * It *must* be called AFTER calling jpeg_start_compress() and BEFORE
+ * the first call to jpeg_write_scanlines().
+ * (This ordering ensures that the APP2 marker(s) will appear after the
+ * SOI and JFIF or Adobe markers, but before all else.)
+ */
+
+void
+write_icc_profile (j_compress_ptr cinfo,
+ const JOCTET *icc_data_ptr,
+ unsigned int icc_data_len)
+{
+ unsigned int num_markers; /* total number of markers we'll write */
+ int cur_marker = 1; /* per spec, counting starts at 1 */
+ unsigned int length; /* number of bytes to write in this marker */
+
+ /* Calculate the number of markers we'll need, rounding up of course */
+ num_markers = icc_data_len / MAX_DATA_BYTES_IN_MARKER;
+ if (num_markers * MAX_DATA_BYTES_IN_MARKER != icc_data_len)
+ num_markers++;
+
+ while (icc_data_len > 0) {
+ /* length of profile to put in this marker */
+ length = icc_data_len;
+ if (length > MAX_DATA_BYTES_IN_MARKER)
+ length = MAX_DATA_BYTES_IN_MARKER;
+ icc_data_len -= length;
+
+ /* Write the JPEG marker header (APP2 code and marker length) */
+ jpeg_write_m_header(cinfo, ICC_MARKER,
+ (unsigned int) (length + ICC_OVERHEAD_LEN));
+
+ /* Write the marker identifying string "ICC_PROFILE" (null-terminated).
+ * We code it in this less-than-transparent way so that the code works
+ * even if the local character set is not ASCII.
+ */
+ jpeg_write_m_byte(cinfo, 0x49);
+ jpeg_write_m_byte(cinfo, 0x43);
+ jpeg_write_m_byte(cinfo, 0x43);
+ jpeg_write_m_byte(cinfo, 0x5F);
+ jpeg_write_m_byte(cinfo, 0x50);
+ jpeg_write_m_byte(cinfo, 0x52);
+ jpeg_write_m_byte(cinfo, 0x4F);
+ jpeg_write_m_byte(cinfo, 0x46);
+ jpeg_write_m_byte(cinfo, 0x49);
+ jpeg_write_m_byte(cinfo, 0x4C);
+ jpeg_write_m_byte(cinfo, 0x45);
+ jpeg_write_m_byte(cinfo, 0x0);
+
+ /* Add the sequencing info */
+ jpeg_write_m_byte(cinfo, cur_marker);
+ jpeg_write_m_byte(cinfo, (int) num_markers);
+
+ /* Add the profile data */
+ while (length--) {
+ jpeg_write_m_byte(cinfo, *icc_data_ptr);
+ icc_data_ptr++;
+ }
+ cur_marker++;
+ }
+}
+
+
+/*
+ * Prepare for reading an ICC profile
+ */
+
+void
+setup_read_icc_profile (j_decompress_ptr cinfo)
+{
+ /* Tell the library to keep any APP2 data it may find */
+ jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF);
+}
+
+
+/*
+ * Handy subroutine to test whether a saved marker is an ICC profile marker.
+ */
+
+static boolean
+marker_is_icc (jpeg_saved_marker_ptr marker)
+{
+ return
+ marker->marker == ICC_MARKER &&
+ marker->data_length >= ICC_OVERHEAD_LEN &&
+ /* verify the identifying string */
+ GETJOCTET(marker->data[0]) == 0x49 &&
+ GETJOCTET(marker->data[1]) == 0x43 &&
+ GETJOCTET(marker->data[2]) == 0x43 &&
+ GETJOCTET(marker->data[3]) == 0x5F &&
+ GETJOCTET(marker->data[4]) == 0x50 &&
+ GETJOCTET(marker->data[5]) == 0x52 &&
+ GETJOCTET(marker->data[6]) == 0x4F &&
+ GETJOCTET(marker->data[7]) == 0x46 &&
+ GETJOCTET(marker->data[8]) == 0x49 &&
+ GETJOCTET(marker->data[9]) == 0x4C &&
+ GETJOCTET(marker->data[10]) == 0x45 &&
+ GETJOCTET(marker->data[11]) == 0x0;
+}
+
+
+/*
+ * See if there was an ICC profile in the JPEG file being read;
+ * if so, reassemble and return the profile data.
+ *
+ * TRUE is returned if an ICC profile was found, FALSE if not.
+ * If TRUE is returned, *icc_data_ptr is set to point to the
+ * returned data, and *icc_data_len is set to its length.
+ *
+ * IMPORTANT: the data at **icc_data_ptr has been allocated with malloc()
+ * and must be freed by the caller with free() when the caller no longer
+ * needs it. (Alternatively, we could write this routine to use the
+ * IJG library's memory allocator, so that the data would be freed implicitly
+ * at jpeg_finish_decompress() time. But it seems likely that many apps
+ * will prefer to have the data stick around after decompression finishes.)
+ *
+ * NOTE: if the file contains invalid ICC APP2 markers, we just silently
+ * return FALSE. You might want to issue an error message instead.
+ */
+
+boolean
+read_icc_profile (j_decompress_ptr cinfo,
+ JOCTET **icc_data_ptr,
+ unsigned int *icc_data_len)
+{
+ jpeg_saved_marker_ptr marker;
+ int num_markers = 0;
+ int seq_no;
+ JOCTET *icc_data;
+ unsigned int total_length;
+#define MAX_SEQ_NO 255 /* sufficient since marker numbers are bytes */
+ char marker_present[MAX_SEQ_NO+1]; /* 1 if marker found */
+ unsigned int data_length[MAX_SEQ_NO+1]; /* size of profile data in marker */
+ unsigned int data_offset[MAX_SEQ_NO+1]; /* offset for data in marker */
+
+ *icc_data_ptr = NULL; /* avoid confusion if FALSE return */
+ *icc_data_len = 0;
+
+ /* This first pass over the saved markers discovers whether there are
+ * any ICC markers and verifies the consistency of the marker numbering.
+ */
+
+ for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
+ marker_present[seq_no] = 0;
+
+ for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
+ if (marker_is_icc(marker)) {
+ if (num_markers == 0)
+ num_markers = GETJOCTET(marker->data[13]);
+ else if (num_markers != GETJOCTET(marker->data[13]))
+ return FALSE; /* inconsistent num_markers fields */
+ seq_no = GETJOCTET(marker->data[12]);
+ if (seq_no <= 0 || seq_no > num_markers)
+ return FALSE; /* bogus sequence number */
+ if (marker_present[seq_no])
+ return FALSE; /* duplicate sequence numbers */
+ marker_present[seq_no] = 1;
+ data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
+ }
+ }
+
+ if (num_markers == 0)
+ return FALSE;
+
+ /* Check for missing markers, count total space needed,
+ * compute offset of each marker's part of the data.
+ */
+
+ total_length = 0;
+ for (seq_no = 1; seq_no <= num_markers; seq_no++) {
+ if (marker_present[seq_no] == 0)
+ return FALSE; /* missing sequence number */
+ data_offset[seq_no] = total_length;
+ total_length += data_length[seq_no];
+ }
+
+ if (total_length <= 0)
+ return FALSE; /* found only empty markers? */
+
+ /* Allocate space for assembled data */
+ icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET));
+ if (icc_data == NULL)
+ return FALSE; /* oops, out of memory */
+
+ /* and fill it in */
+ for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
+ if (marker_is_icc(marker)) {
+ JOCTET FAR *src_ptr;
+ JOCTET *dst_ptr;
+ unsigned int length;
+ seq_no = GETJOCTET(marker->data[12]);
+ dst_ptr = icc_data + data_offset[seq_no];
+ src_ptr = marker->data + ICC_OVERHEAD_LEN;
+ length = data_length[seq_no];
+ while (length--) {
+ *dst_ptr++ = *src_ptr++;
+ }
+ }
+ }
+
+ *icc_data_ptr = icc_data;
+ *icc_data_len = total_length;
+
+ return TRUE;
+}
diff --git a/kipi-plugins/rawconverter/iccjpeg.h b/kipi-plugins/rawconverter/iccjpeg.h
new file mode 100644
index 0000000..78e7fdc
--- /dev/null
+++ b/kipi-plugins/rawconverter/iccjpeg.h
@@ -0,0 +1,96 @@
+/*
+ * Little cms
+ * Copyright (C) 1998-2004 Marti Maria
+ *
+ * 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 OR COPYRIGHT HOLDERS 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.
+ *
+ *
+ * iccprofile.h
+ *
+ * This file provides code to read and write International Color Consortium
+ * (ICC) device profiles embedded in JFIF JPEG image files. The ICC has
+ * defined a standard format for including such data in JPEG "APP2" markers.
+ * The code given here does not know anything about the internal structure
+ * of the ICC profile data; it just knows how to put the profile data into
+ * a JPEG file being written, or get it back out when reading.
+ *
+ * This code depends on new features added to the IJG JPEG library as of
+ * IJG release 6b; it will not compile or work with older IJG versions.
+ *
+ * NOTE: this code would need surgery to work on 16-bit-int machines
+ * with ICC profiles exceeding 64K bytes in size. See iccprofile.c
+ * for details.
+ */
+
+#include <stdio.h> /* needed to define "FILE", "NULL" */
+#include <jpeglib.h>
+
+
+/**
+ * This routine writes the given ICC profile data into a JPEG file.
+ * It *must* be called AFTER calling jpeg_start_compress() and BEFORE
+ * the first call to jpeg_write_scanlines().
+ * (This ordering ensures that the APP2 marker(s) will appear after the
+ * SOI and JFIF or Adobe markers, but before all else.)
+ */
+
+extern void write_icc_profile JPP((j_compress_ptr cinfo,
+ const JOCTET *icc_data_ptr,
+ unsigned int icc_data_len));
+
+
+/**
+ * Reading a JPEG file that may contain an ICC profile requires two steps:
+ *
+ * 1. After jpeg_create_decompress() but before jpeg_read_header(),
+ * call setup_read_icc_profile(). This routine tells the IJG library
+ * to save in memory any APP2 markers it may find in the file.
+ *
+ * 2. After jpeg_read_header(), call read_icc_profile() to find out
+ * whether there was a profile and obtain it if so.
+ */
+
+
+/**
+ * Prepare for reading an ICC profile
+ */
+
+extern void setup_read_icc_profile JPP((j_decompress_ptr cinfo));
+
+
+/**
+ * See if there was an ICC profile in the JPEG file being read;
+ * if so, reassemble and return the profile data.
+ *
+ * TRUE is returned if an ICC profile was found, FALSE if not.
+ * If TRUE is returned, *icc_data_ptr is set to point to the
+ * returned data, and *icc_data_len is set to its length.
+ *
+ * IMPORTANT: the data at **icc_data_ptr has been allocated with malloc()
+ * and must be freed by the caller with free() when the caller no longer
+ * needs it. (Alternatively, we could write this routine to use the
+ * IJG library's memory allocator, so that the data would be freed implicitly
+ * at jpeg_finish_decompress() time. But it seems likely that many apps
+ * will prefer to have the data stick around after decompression finishes.)
+ */
+
+extern boolean read_icc_profile JPP((j_decompress_ptr cinfo,
+ JOCTET **icc_data_ptr,
+ unsigned int *icc_data_len));
diff --git a/kipi-plugins/rawconverter/kipiplugin_rawconverter.desktop b/kipi-plugins/rawconverter/kipiplugin_rawconverter.desktop
new file mode 100644
index 0000000..88a3e0c
--- /dev/null
+++ b/kipi-plugins/rawconverter/kipiplugin_rawconverter.desktop
@@ -0,0 +1,55 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=RawConverter
+Name[ca]=Convertidor RAW
+Name[cs]=RAW převod
+Name[da]=Konvertering af ubehandlede billeder
+Name[de]=Raw-Konvertierung
+Name[el]=ΜετατροπέαςΑκατέργαστηςΜορφής
+Name[es]=Conversor Raw
+Name[et]=Toorpiltide teisendaja
+Name[fi]=Raw-muunnin
+Name[gl]=Conversor de RAW
+Name[it]=ConvertitoreGrezzo
+Name[nds]=Roh-Ümwanneln
+Name[nl]=Raw-conversie
+Name[pl]=Konwerter RAW
+Name[pt]=Conversor de RAW
+Name[sr]=Raw претварање
+Name[sr@Latn]=Raw pretvaranje
+Name[sv]=Konvertering av obehandlade bilder
+Name[tg]=Ковертери Raw
+Name[tr]=HamDönüştürücü
+Name[xx]=xxRawConverterxx
+Name[zh_CN]=原图转换器
+Comment=KIPI Raw Image Converter
+Comment[ca]=Convertidor KIPI d'imatges RAW
+Comment[cs]=KIPI převod RAW obrázků
+Comment[da]=KIPI-plugin: Konvertering af ubehandlede billeder
+Comment[de]=Ein KIPI-Modul zum Umwandeln von Bildern im Raw-Format
+Comment[el]=Μετατροπέας του KIPI για εικόνες ανεπεξέργαστης μορφής
+Comment[es]=Conversor de imágenes Raw para KIPI
+Comment[et]=KIPI toorpiltide teisendaja
+Comment[fi]=Kipi-liitännäinen raw-muotoisten kuvien muunnosta varten
+Comment[fr]=Module externe KIPI pour convertir des images brutes
+Comment[gl]=Conversor de Imaxes en Bruto de KIPI
+Comment[is]=KIPI RAW myndbreytir
+Comment[it]=Convertitore di immagini grezze di KIPI
+Comment[ja]=Kipi RAW 画像コンバータ
+Comment[nds]=KIPI-Moduul för't Ümwanneln vun Rohbiller
+Comment[nl]=KIPI-plugin voor het converteren van raw-afbeeldingen
+Comment[pa]=KIPI Raw ਚਿੱਤਰ ਤਬਦੀਲੀਕਾਰ
+Comment[pl]=Wtyczka KIPI - Konwerter zdjęć RAW
+Comment[pt]=Conversor de Imagens em Bruto do KIPI
+Comment[pt_BR]=Conversor de Imagens Raw do KIPI
+Comment[sr]=KIPI-јев претварач Raw слика
+Comment[sr@Latn]=KIPI-jev pretvarač Raw slika
+Comment[sv]=KIPI-insticksprogram: Konvertering av obehandlade bilder
+Comment[tg]=Конвертери Тасвирҳои KIPI Raw
+Comment[tr]=KIPI Ham Resim Dönüştürücü
+Comment[xx]=xxKIPI Raw Image Converterxx
+Comment[zh_CN]=KIPI 原始图像转换器
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_rawconverter
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/kipi-plugins/rawconverter/mtqueue.h b/kipi-plugins/rawconverter/mtqueue.h
new file mode 100644
index 0000000..14ff5f2
--- /dev/null
+++ b/kipi-plugins/rawconverter/mtqueue.h
@@ -0,0 +1,87 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-12-09
+ * Description : Multithread queue description class
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 MTQUEUE_H
+#define MTQUEUE_H
+
+// Qt includes.
+
+#include <qptrqueue.h>
+#include <qmutex.h>
+
+namespace KIPIRawConverterPlugin
+{
+
+template<class Type> class MTQueue
+{
+
+public:
+
+ MTQueue()
+ {
+ m_queue.setAutoDelete(true);
+ }
+
+ ~MTQueue()
+ {
+ flush();
+ }
+
+ bool isEmpty()
+ {
+ m_mutex.lock();
+ bool empty = m_queue.isEmpty();
+ m_mutex.unlock();
+ return empty;
+ }
+
+ void flush()
+ {
+ m_mutex.lock();
+ m_queue.clear();
+ m_mutex.unlock();
+ }
+
+ void enqueue(Type * t)
+ {
+ m_mutex.lock();
+ m_queue.enqueue(t);
+ m_mutex.unlock();
+ }
+
+ Type * dequeue()
+ {
+ m_mutex.lock();
+ Type * i = m_queue.dequeue();
+ m_mutex.unlock();
+ return i;
+ }
+
+private:
+
+ QPtrQueue<Type> m_queue;
+ QMutex m_mutex;
+};
+
+} // NameSpace KIPIRawConverterPlugin
+
+#endif // MTQUEUE_H
diff --git a/kipi-plugins/rawconverter/pics/Makefile.am b/kipi-plugins/rawconverter/pics/Makefile.am
new file mode 100644
index 0000000..773dcd4
--- /dev/null
+++ b/kipi-plugins/rawconverter/pics/Makefile.am
@@ -0,0 +1,2 @@
+kipirawconvertericondir = $(kde_datadir)/kipiplugin_rawconverter/icons
+kipirawconvertericon_ICON = AUTO
diff --git a/kipi-plugins/rawconverter/pics/hi128-action-rawconverterbatch.png b/kipi-plugins/rawconverter/pics/hi128-action-rawconverterbatch.png
new file mode 100644
index 0000000..7c224e9
--- /dev/null
+++ b/kipi-plugins/rawconverter/pics/hi128-action-rawconverterbatch.png
Binary files differ
diff --git a/kipi-plugins/rawconverter/pics/hi128-action-rawconvertersingle.png b/kipi-plugins/rawconverter/pics/hi128-action-rawconvertersingle.png
new file mode 100644
index 0000000..e51c07c
--- /dev/null
+++ b/kipi-plugins/rawconverter/pics/hi128-action-rawconvertersingle.png
Binary files differ
diff --git a/kipi-plugins/rawconverter/plugin_rawconverter.cpp b/kipi-plugins/rawconverter/plugin_rawconverter.cpp
new file mode 100644
index 0000000..e77a146
--- /dev/null
+++ b/kipi-plugins/rawconverter/plugin_rawconverter.cpp
@@ -0,0 +1,225 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-01-31
+ * Description : a kipi plugin to convert Raw file in single
+ * or batch mode.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C ANSI Includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+}
+
+// C++ includes.
+
+#include <cstdlib>
+
+// Qt Includes.
+
+#include <qprocess.h>
+#include <qfileinfo.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+// Local includes.
+
+#include "singledialog.h"
+#include "batchdialog.h"
+#include "plugin_rawconverter.h"
+#include "plugin_rawconverter.moc"
+
+typedef KGenericFactory<Plugin_RawConverter> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_rawconverter,
+ Factory("kipiplugin_rawconverter"))
+
+Plugin_RawConverter::Plugin_RawConverter(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "RawConverter")
+{
+ kdDebug( 51001 ) << "Loaded RawConverter" << endl;
+}
+
+void Plugin_RawConverter::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+ singleAction_ = new KAction (i18n("Raw Image Converter..."),
+ "rawconvertersingle",
+ 0,
+ this,
+ SLOT(slotActivateSingle()),
+ actionCollection(),
+ "raw_converter_single");
+
+ batchAction_ = new KAction (i18n("Batch Raw Converter..."),
+ "rawconverterbatch",
+ 0,
+ this,
+ SLOT(slotActivateBatch()),
+ actionCollection(),
+ "raw_converter_batch");
+
+ addAction( singleAction_ );
+ addAction( batchAction_ );
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ connect( interface, SIGNAL( selectionChanged( bool ) ),
+ singleAction_, SLOT( setEnabled( bool ) ) );
+
+ connect( interface, SIGNAL( currentAlbumChanged( bool ) ),
+ batchAction_, SLOT( setEnabled( bool ) ) );
+}
+
+Plugin_RawConverter::~Plugin_RawConverter()
+{
+}
+
+bool Plugin_RawConverter::isRAWFile(const QString& filePath)
+{
+#if KDCRAW_VERSION < 0x000106
+ QString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles());
+#else
+ QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
+#endif
+
+ QFileInfo fileInfo(filePath);
+ if (rawFilesExt.upper().contains( fileInfo.extension(false).upper() ))
+ return true;
+
+ return false;
+}
+
+bool Plugin_RawConverter::checkBinaries()
+{
+#if KDCRAW_VERSION < 0x000106
+ KDcrawIface::DcrawBinary::instance()->checkSystem();
+ KDcrawIface::DcrawBinary::instance()->checkReport();
+ return KDcrawIface::DcrawBinary::instance()->isAvailable();
+#else
+ return true;
+#endif
+}
+
+void Plugin_RawConverter::slotActivateSingle()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection images;
+ images = interface->currentSelection();
+
+ if (!images.isValid())
+ return;
+
+ if (!checkBinaries())
+ return;
+
+ if (!isRAWFile(images.images()[0].path()))
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" is not a Raw file.").arg(images.images()[0].fileName()));
+ return;
+ }
+
+ KIPIRawConverterPlugin::SingleDialog *converter =
+ new KIPIRawConverterPlugin::SingleDialog(images.images()[0].path(),
+ kapp->activeWindow());
+
+ converter->show();
+}
+
+void Plugin_RawConverter::slotActivateBatch()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection images;
+ images = interface->currentSelection();
+
+ if (!images.isValid())
+ return;
+
+ if (!checkBinaries())
+ return;
+
+ KIPIRawConverterPlugin::BatchDialog *converter =
+ new KIPIRawConverterPlugin::BatchDialog(kapp->activeWindow());
+
+ KURL::List urls = images.images();
+ QStringList files;
+
+ for( KURL::List::Iterator it = urls.begin(); it != urls.end(); ++it )
+ {
+ if (isRAWFile((*it).path()))
+ files.append( (*it).path() );
+ }
+
+ converter->addItems(files);
+ converter->show();
+}
+
+KIPI::Category Plugin_RawConverter::category( KAction* action ) const
+{
+ if ( action == singleAction_ )
+ return KIPI::TOOLSPLUGIN;
+ else if ( action == batchAction_ )
+ return KIPI::BATCHPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::TOOLSPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/rawconverter/plugin_rawconverter.h b/kipi-plugins/rawconverter/plugin_rawconverter.h
new file mode 100644
index 0000000..3b159ca
--- /dev/null
+++ b/kipi-plugins/rawconverter/plugin_rawconverter.h
@@ -0,0 +1,64 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-01-31
+ * Description : a kipi plugin to convert Raw file in single
+ * or batch mode.
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_RAWCONVERTER_H
+#define PLUGIN_RAWCONVERTER_H
+
+// LibKIPi includes.
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+class Plugin_RawConverter : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_RawConverter(QObject *parent,
+ const char* name,
+ const QStringList &args);
+ ~Plugin_RawConverter();
+
+ KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+private:
+
+ bool checkBinaries();
+ bool isRAWFile(const QString& filePath);
+
+private slots:
+
+ void slotActivateSingle();
+ void slotActivateBatch();
+
+private:
+
+ KAction *singleAction_;
+ KAction *batchAction_;
+};
+
+#endif /* PLUGIN_RAWCONVERTER_H */
diff --git a/kipi-plugins/rawconverter/previewwidget.cpp b/kipi-plugins/rawconverter/previewwidget.cpp
new file mode 100644
index 0000000..e1958f5
--- /dev/null
+++ b/kipi-plugins/rawconverter/previewwidget.cpp
@@ -0,0 +1,198 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-22
+ * Description : preview raw file widget used in single convert
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qpainter.h>
+#include <qimage.h>
+#include <qstring.h>
+#include <qevent.h>
+#include <qtimer.h>
+#include <qfile.h>
+
+// KDE includes.
+
+#include <klocale.h>
+
+// Local includes.
+
+#include "previewwidget.h"
+#include "previewwidget.moc"
+
+namespace KIPIRawConverterPlugin
+{
+
+class PreviewWidgetPriv
+{
+public:
+
+ PreviewWidgetPriv()
+ {
+ pix = 0;
+ timer = 0;
+ }
+
+ QPixmap *pix;
+ QPixmap preview;
+
+ QTimer *timer;
+
+ QString text;
+
+ QImage image;
+};
+
+PreviewWidget::PreviewWidget(QWidget *parent)
+ : QFrame(parent, 0, Qt::WRepaintNoErase)
+{
+ d = new PreviewWidgetPriv;
+ setFrameStyle(QFrame::GroupBoxPanel|QFrame::Plain);
+ setMargin(0);
+ setLineWidth(1);
+
+ setMinimumSize(QSize(400, 300));
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ d->pix = new QPixmap(400, 300);
+ d->pix->fill(Qt::black);
+
+ d->timer = new QTimer(this);
+
+ connect(d->timer, SIGNAL(timeout()),
+ this, SLOT(slotResize()));
+}
+
+PreviewWidget::~PreviewWidget()
+{
+ delete d;
+}
+
+void PreviewWidget::load(const QString& file)
+{
+ d->text = "";
+ d->pix->fill(Qt::black);
+ d->image.load(file);
+
+ if (!d->image.isNull())
+ {
+ QImage img = d->image.scale(width(),height(),QImage::ScaleMin);
+ int x = d->pix->width()/2 - img.width()/2;
+ int y = d->pix->height()/2 - img.height()/2;
+
+ QPainter p(d->pix);
+ p.drawImage(x, y, img);
+ p.setPen(QPen(Qt::white));
+ p.drawRect(x,y,img.width(),img.height());
+ p.end();
+ }
+ else
+ {
+ setInfo(i18n( "Failed to load image after processing" ));
+ return;
+ }
+
+ update();
+}
+
+void PreviewWidget::setInfo(const QString& text, const QColor& color, const QPixmap& preview)
+{
+ d->text = text;
+ d->preview = preview;
+ d->pix->fill(Qt::black);
+ QPainter p(d->pix);
+ p.setPen(QPen(color));
+
+ if (!d->preview.isNull())
+ {
+ p.drawPixmap(d->pix->width()/2-d->preview.width()/2, d->pix->height()/4-d->preview.height()/2,
+ d->preview, 0, 0, d->preview.width(), d->preview.height());
+ p.drawText(0, d->pix->height()/2, d->pix->width(), d->pix->height()/2,
+ Qt::AlignCenter|Qt::WordBreak, d->text);
+ }
+ else
+ {
+ p.drawText(0, 0, d->pix->width(), d->pix->height(),
+ Qt::AlignCenter|Qt::WordBreak, d->text);
+ }
+ p.end();
+ update();
+}
+
+void PreviewWidget::paintEvent(QPaintEvent *e)
+{
+ QRect r(e->rect());
+ bitBlt(this, r.topLeft(), d->pix, r, Qt::CopyROP);
+}
+
+void PreviewWidget::resizeEvent(QResizeEvent*)
+{
+ d->timer->start(10,true);
+}
+
+void PreviewWidget::slotResize()
+{
+ if (d->timer->isActive()) return;
+
+ d->pix->resize(width(),height());
+ d->pix->fill(Qt::black);
+ if (!d->text.isEmpty())
+ {
+ QPainter p(d->pix);
+ p.setPen(QPen(Qt::white));
+
+ if (!d->preview.isNull())
+ {
+ p.drawPixmap(d->pix->width()/2-d->preview.width()/2, d->pix->height()/4-d->preview.height()/2,
+ d->preview, 0, 0, d->preview.width(), d->preview.height());
+ p.drawText(0, d->pix->height()/2, d->pix->width(), d->pix->height()/2,
+ Qt::AlignCenter|Qt::WordBreak, d->text);
+ }
+ else
+ {
+ p.drawText(0, 0, d->pix->width(), d->pix->height(),
+ Qt::AlignCenter|Qt::WordBreak, d->text);
+ }
+
+ p.end();
+ }
+ else
+ {
+ if (!d->image.isNull())
+ {
+ QImage img = d->image.scale(width(),height(), QImage::ScaleMin);
+ int x = d->pix->width()/2 - img.width()/2;
+ int y = d->pix->height()/2 - img.height()/2;
+
+ QPainter p(d->pix);
+ p.drawImage(x, y, img);
+ p.setPen(QPen(Qt::white));
+ p.drawRect(x,y,img.width(),img.height());
+ p.end();
+ }
+ }
+
+ update();
+}
+
+} // NameSpace KIPIRawConverterPlugin
+
diff --git a/kipi-plugins/rawconverter/previewwidget.h b/kipi-plugins/rawconverter/previewwidget.h
new file mode 100644
index 0000000..f1e6ca7
--- /dev/null
+++ b/kipi-plugins/rawconverter/previewwidget.h
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-22
+ * Description : preview raw file widget used in single convert
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PREVIEWWIDGET_H
+#define PREVIEWWIDGET_H
+
+// Qt includes.
+
+#include <qcolor.h>
+#include <qframe.h>
+#include <qpixmap.h>
+#include <qstring.h>
+
+class QPaintEvent;
+class QResizeEvent;
+
+namespace KIPIRawConverterPlugin
+{
+class PreviewWidgetPriv;
+
+class PreviewWidget : public QFrame
+{
+ Q_OBJECT
+
+public:
+
+ PreviewWidget(QWidget *parent);
+ ~PreviewWidget();
+
+ void load(const QString& file);
+ void setInfo(const QString& text, const QColor& color=Qt::white,
+ const QPixmap& preview=QPixmap());
+
+protected:
+
+ void paintEvent(QPaintEvent *e);
+ void resizeEvent(QResizeEvent *e);
+
+private slots:
+
+ void slotResize();
+
+private:
+
+ PreviewWidgetPriv* d;
+};
+
+} // NameSpace KIPIRawConverterPlugin
+
+#endif /* PREVIEWWIDGET_H */
diff --git a/kipi-plugins/rawconverter/profiles/Makefile.am b/kipi-plugins/rawconverter/profiles/Makefile.am
new file mode 100644
index 0000000..30d7e5b
--- /dev/null
+++ b/kipi-plugins/rawconverter/profiles/Makefile.am
@@ -0,0 +1,2 @@
+kipirawconverterprofilesdir = $(kde_datadir)/kipiplugin_rawconverter/profiles
+kipirawconverterprofiles_DATA = adobergb.icm srgb.icm widegamut.icm prophoto.icm
diff --git a/kipi-plugins/rawconverter/profiles/adobergb.icm b/kipi-plugins/rawconverter/profiles/adobergb.icm
new file mode 100644
index 0000000..ae368c6
--- /dev/null
+++ b/kipi-plugins/rawconverter/profiles/adobergb.icm
Binary files differ
diff --git a/kipi-plugins/rawconverter/profiles/prophoto.icm b/kipi-plugins/rawconverter/profiles/prophoto.icm
new file mode 100644
index 0000000..a20d29b
--- /dev/null
+++ b/kipi-plugins/rawconverter/profiles/prophoto.icm
Binary files differ
diff --git a/kipi-plugins/rawconverter/profiles/srgb.icm b/kipi-plugins/rawconverter/profiles/srgb.icm
new file mode 100644
index 0000000..878fdf1
--- /dev/null
+++ b/kipi-plugins/rawconverter/profiles/srgb.icm
Binary files differ
diff --git a/kipi-plugins/rawconverter/profiles/widegamut.icm b/kipi-plugins/rawconverter/profiles/widegamut.icm
new file mode 100644
index 0000000..120a99a
--- /dev/null
+++ b/kipi-plugins/rawconverter/profiles/widegamut.icm
Binary files differ
diff --git a/kipi-plugins/rawconverter/rawdecodingiface.cpp b/kipi-plugins/rawconverter/rawdecodingiface.cpp
new file mode 100644
index 0000000..1a86bae
--- /dev/null
+++ b/kipi-plugins/rawconverter/rawdecodingiface.cpp
@@ -0,0 +1,668 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-12-09
+ * Description : RAW decoding interface
+ *
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel.wiesweg@gmx.de>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * NOTE: Do not use kdDebug() in this implementation because
+ * it will be multithreaded. Use qDebug() instead.
+ * See B.K.O #133026 for details.
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <cstdio>
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <jpeglib.h>
+#include <tiffio.h>
+#include <tiffvers.h>
+#include "iccjpeg.h"
+}
+
+// Qt Includes.
+
+#include <qcstring.h>
+#include <qfileinfo.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "pluginsversion.h"
+#include "rawdecodingiface.h"
+#include "rawdecodingiface.moc"
+
+namespace KIPIRawConverterPlugin
+{
+
+RawDecodingIface::RawDecodingIface()
+ : KDcrawIface::KDcraw()
+{
+}
+
+RawDecodingIface::~RawDecodingIface()
+{
+}
+
+QByteArray RawDecodingIface::getICCProfilFromFile(KDcrawIface::RawDecodingSettings::OutputColorSpace colorSpace)
+{
+ QString filePath;
+ KGlobal::dirs()->addResourceType("profiles", KGlobal::dirs()->kde_default("data") +
+ "kipiplugin_rawconverter/profiles");
+
+ switch(colorSpace)
+ {
+ case KDcrawIface::RawDecodingSettings::SRGB:
+ {
+ filePath = KGlobal::dirs()->findResourceDir("profiles", "srgb.icm");
+ filePath.append("srgb.icm");
+ break;
+ }
+ case KDcrawIface::RawDecodingSettings::ADOBERGB:
+ {
+ filePath = KGlobal::dirs()->findResourceDir("profiles", "adobergb.icm");
+ filePath.append("adobergb.icm");
+ break;
+ }
+ case KDcrawIface::RawDecodingSettings::WIDEGAMMUT:
+ {
+ filePath = KGlobal::dirs()->findResourceDir("profiles", "widegamut.icm");
+ filePath.append("widegamut.icm");
+ break;
+ }
+ case KDcrawIface::RawDecodingSettings::PROPHOTO:
+ {
+ filePath = KGlobal::dirs()->findResourceDir("profiles", "prophoto.icm");
+ filePath.append("prophoto.icm");
+ break;
+ }
+ default:
+ break;
+ }
+
+ if ( filePath.isEmpty() )
+ return QByteArray();
+
+ QFile file(filePath);
+ if ( !file.open(IO_ReadOnly) )
+ return QByteArray();
+
+ QByteArray data(file.size());
+ QDataStream stream( &file );
+ stream.readRawBytes(data.data(), data.size());
+ file.close();
+ return data;
+}
+
+bool RawDecodingIface::decodeHalfRAWImage(const QString& filePath,
+ QString& destPath, SaveSettingsWidget::OutputFormat outputFileFormat,
+ KDcrawIface::RawDecodingSettings rawDecodingSettings)
+{
+ int width, height, rgbmax;
+ QByteArray imageData;
+ if (!KDcrawIface::KDcraw::decodeHalfRAWImage(filePath, rawDecodingSettings,
+ imageData, width, height, rgbmax))
+ return false;
+
+ return (loadedFromDcraw(filePath, destPath, outputFileFormat,
+ imageData, width, height));
+}
+
+bool RawDecodingIface::decodeRAWImage(const QString& filePath,
+ QString& destPath, SaveSettingsWidget::OutputFormat outputFileFormat,
+ KDcrawIface::RawDecodingSettings rawDecodingSettings)
+{
+ int width, height, rgbmax;
+ QByteArray imageData;
+ if (!KDcrawIface::KDcraw::decodeRAWImage(filePath, rawDecodingSettings,
+ imageData, width, height, rgbmax))
+ return false;
+
+ return (loadedFromDcraw(filePath, destPath, outputFileFormat,
+ imageData, width, height));
+}
+
+// ----------------------------------------------------------------------------------
+
+bool RawDecodingIface::loadedFromDcraw(const QString& filePath,
+ QString& destPath, SaveSettingsWidget::OutputFormat outputFileFormat,
+ const QByteArray& imageData, int width, int height)
+{
+ // -- Use a QImage instance to write IPTC preview and Exif thumbnail -------
+
+ QImage img(width, height, 32);
+ uchar* dptr = img.bits();
+ uchar* sptr = (uchar*)imageData.data();
+
+ // Set RGB color components.
+ for (int i = 0 ; i < width * height ; i++)
+ {
+ dptr[0] = sptr[2];
+ dptr[1] = sptr[1];
+ dptr[2] = sptr[0];
+ dptr[3] = 0xFF;
+ dptr += 4;
+ sptr += 3;
+ }
+
+ QImage iptcPreview = img.scale(1280, 1024, QImage::ScaleMin);
+ QImage exifThumbnail = iptcPreview.scale(160, 120, QImage::ScaleMin);
+
+ // -- Write image data into destination file -------------------------------
+
+ QByteArray ICCColorProfile = getICCProfilFromFile(m_rawDecodingSettings.outputColorSpace);
+ QString soft = QString("Kipi-plugins v.%1").arg(kipiplugins_version);
+ QFileInfo fi(filePath);
+ destPath = fi.dirPath(true) + QString("/") + ".kipi-rawconverter-tmp-"
+ + QString::number(::time(0));
+
+ // Metadata restoration and update.
+ KExiv2Iface::KExiv2 exiv2Iface;
+ exiv2Iface.load(filePath);
+ exiv2Iface.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+ exiv2Iface.setImageDimensions(QSize(width, height));
+ exiv2Iface.setExifThumbnail(exifThumbnail);
+
+ // Update Iptc preview.
+ // NOTE: see B.K.O #130525. a JPEG segment is limited to 64K. If the IPTC byte array is
+ // bigger than 64K duing of image preview tag size, the target JPEG image will be
+ // broken. Note that IPTC image preview tag is limited to 256K!!!
+ // There is no limitation with TIFF and PNG about IPTC byte array size.
+ if (outputFileFormat != SaveSettingsWidget::OUTPUT_JPEG)
+ exiv2Iface.setImagePreview(iptcPreview);
+
+ exiv2Iface.setExifTagString("Exif.Image.DocumentName", fi.fileName());
+
+ switch(outputFileFormat)
+ {
+ case SaveSettingsWidget::OUTPUT_JPEG:
+ {
+ FILE* f = 0;
+ f = fopen(QFile::encodeName(destPath), "wb");
+
+ if (!f)
+ {
+ qDebug("Failed to open JPEG file for writing");
+ return false;
+ }
+
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ int row_stride;
+ JSAMPROW row_pointer[1];
+
+ // Init JPEG compressor.
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+ jpeg_stdio_dest(&cinfo, f);
+ cinfo.image_width = width;
+ cinfo.image_height = height;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+ jpeg_set_defaults(&cinfo);
+
+ // B.K.O #149578: set encoder horizontal and vertical chroma subsampling
+ // factor to 2x1, 1x1, 1x1 (4:2:2) : Medium subsampling.
+ // See this page for details: http://en.wikipedia.org/wiki/Chroma_subsampling
+ cinfo.comp_info[0].h_samp_factor = 2;
+ cinfo.comp_info[0].v_samp_factor = 1;
+ cinfo.comp_info[1].h_samp_factor = 1;
+ cinfo.comp_info[1].v_samp_factor = 1;
+ cinfo.comp_info[2].h_samp_factor = 1;
+ cinfo.comp_info[2].v_samp_factor = 1;
+
+ // B.K.O #154273: use 99 compresion level instead 100 to reduce output JPEG file size.
+ jpeg_set_quality(&cinfo, 99, true);
+ jpeg_start_compress(&cinfo, true);
+
+ // Write ICC color profil.
+ if (!ICCColorProfile.isEmpty())
+ write_icc_profile (&cinfo, (JOCTET *)ICCColorProfile.data(), ICCColorProfile.size());
+
+ // Write image data
+ row_stride = cinfo.image_width * 3;
+ while (!m_cancel && (cinfo.next_scanline < cinfo.image_height))
+ {
+ row_pointer[0] = (uchar*)imageData.data() + (cinfo.next_scanline * row_stride);
+ jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+ fclose(f);
+
+ exiv2Iface.save(destPath);
+ break;
+ }
+
+ case SaveSettingsWidget::OUTPUT_PNG:
+ {
+ FILE* f = 0;
+ f = fopen(QFile::encodeName(destPath), "wb");
+
+ if (!f)
+ {
+ qDebug("Failed to open PNG file for writing");
+ return false;
+ }
+
+ png_color_8 sig_bit;
+ png_bytep row_ptr;
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ png_init_io(png_ptr, f);
+ png_set_IHDR(png_ptr, info_ptr, width, height, 8,
+ PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+ sig_bit.red = 8;
+ sig_bit.green = 8;
+ sig_bit.blue = 8;
+ sig_bit.alpha = 8;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+ png_set_compression_level(png_ptr, 9);
+
+ // Write ICC profil.
+ if (!ICCColorProfile.isEmpty())
+ {
+ png_set_iCCP(png_ptr, info_ptr, "icc", PNG_COMPRESSION_TYPE_BASE,
+ ICCColorProfile.data(), ICCColorProfile.size());
+ }
+
+ QString libpngver(PNG_HEADER_VERSION_STRING);
+ libpngver.replace('\n', ' ');
+ soft.append(QString(" (%1)").arg(libpngver));
+ png_text text;
+ text.key = "Software";
+ text.text = (char *)soft.ascii();
+ text.compression = PNG_TEXT_COMPRESSION_zTXt;
+ png_set_text(png_ptr, info_ptr, &(text), 1);
+
+ // Store Exif data.
+ QByteArray ba = exiv2Iface.getExif();
+ const uchar ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
+ QByteArray profile = QByteArray(ba.size() + sizeof(ExifHeader));
+ memcpy(profile.data(), ExifHeader, sizeof(ExifHeader));
+ memcpy(profile.data()+sizeof(ExifHeader), ba.data(), ba.size());
+ writeRawProfile(png_ptr, info_ptr, "exif", profile.data(), (png_uint_32) profile.size());
+
+ // Store Iptc data.
+ QByteArray ba2 = exiv2Iface.getIptc();
+ writeRawProfile(png_ptr, info_ptr, "iptc", ba2.data(), (png_uint_32) ba2.size());
+
+ png_write_info(png_ptr, info_ptr);
+ png_set_shift(png_ptr, &sig_bit);
+ png_set_packing(png_ptr);
+ unsigned char* ptr = (unsigned char*)imageData.data();
+
+ for (int y = 0; !m_cancel && (y < height); y++)
+ {
+ row_ptr = (png_bytep) ptr;
+ png_write_rows(png_ptr, &row_ptr, 1);
+ ptr += (width * 3);
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr);
+ png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr);
+ fclose(f);
+ break;
+ }
+
+ case SaveSettingsWidget::OUTPUT_TIFF:
+ {
+ TIFF *tif=0;
+ unsigned char *data=0;
+ int y;
+ int w;
+
+ tif = TIFFOpen(QFile::encodeName(destPath), "wb");
+
+ if (!tif)
+ {
+ qDebug("Failed to open TIFF file for writing");
+ return false;
+ }
+
+ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
+ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
+ TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
+ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+ TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE);
+ TIFFSetField(tif, TIFFTAG_ZIPQUALITY, 9);
+ // NOTE : this tag values aren't defined in libtiff 3.6.1. '2' is PREDICTOR_HORIZONTAL.
+ // Use horizontal differencing for images which are
+ // likely to be continuous tone. The TIFF spec says that this
+ // usually leads to better compression.
+ // See this url for more details:
+ // http://www.awaresystems.be/imaging/tiff/tifftags/predictor.html
+ TIFFSetField(tif, TIFFTAG_PREDICTOR, 2);
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
+ w = TIFFScanlineSize(tif);
+ TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, 0));
+
+ // Store Iptc data.
+ QByteArray ba2 = exiv2Iface.getIptc(true);
+#if defined(TIFFTAG_PHOTOSHOP)
+ TIFFSetField (tif, TIFFTAG_PHOTOSHOP, (uint32)ba2.size(), (uchar *)ba2.data());
+#endif
+
+ QString libtiffver(TIFFLIB_VERSION_STR);
+ libtiffver.replace('\n', ' ');
+ soft.append(QString(" ( %1 )").arg(libtiffver));
+ TIFFSetField(tif, TIFFTAG_SOFTWARE, (const char*)soft.ascii());
+
+ // Write ICC profil.
+ if (!ICCColorProfile.isEmpty())
+ {
+#if defined(TIFFTAG_ICCPROFILE)
+ TIFFSetField(tif, TIFFTAG_ICCPROFILE, (uint32)ICCColorProfile.size(),
+ (uchar *)ICCColorProfile.data());
+#endif
+ }
+
+ // Write full image data in tiff directory IFD0
+
+ for (y = 0; !m_cancel && (y < height); y++)
+ {
+ data = (unsigned char*)imageData.data() + (y * width * 3);
+ TIFFWriteScanline(tif, data, y, 0);
+ }
+
+ TIFFWriteDirectory(tif);
+
+ // Write thumbnail in tiff directory IFD1
+
+ QImage thumb = exiv2Iface.getExifThumbnail(false);
+ if (!thumb.isNull())
+ {
+ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32)thumb.width());
+ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32)thumb.height());
+ TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
+ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+ TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
+ TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE);
+ TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
+ TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, 0));
+
+ int i=0;
+ uint32 x, y;
+ uchar *pixelThumb;
+ uchar *dataThumb = thumb.bits();
+ uint8 *bufThumb = (uint8 *) _TIFFmalloc(TIFFScanlineSize(tif));
+
+ if (!bufThumb)
+ {
+ qDebug("Cannot allocate memory buffer for TIFF thumbnail.");
+ TIFFClose(tif);
+ return false;
+ }
+
+ for (y = 0 ; y < uint32(thumb.height()) ; y++)
+ {
+ i = 0;
+
+ for (x = 0 ; x < uint32(thumb.width()) ; x++)
+ {
+ pixelThumb = &dataThumb[((y * thumb.width()) + x) * 4];
+
+ // This might be endian dependent
+ bufThumb[i++] = (uint8)pixelThumb[2];
+ bufThumb[i++] = (uint8)pixelThumb[1];
+ bufThumb[i++] = (uint8)pixelThumb[0];
+ }
+
+ if (!TIFFWriteScanline(tif, bufThumb, y, 0))
+ {
+ qDebug("Cannot write TIFF thumbnail to target file.");
+ _TIFFfree(bufThumb);
+ TIFFClose(tif);
+ return false;
+ }
+ }
+
+ _TIFFfree(bufThumb);
+ }
+ TIFFClose(tif);
+
+ // Store metadata (Exiv2 0.18 support tiff writting mode)
+ exiv2Iface.save(destPath);
+
+ break;
+ }
+
+ case SaveSettingsWidget::OUTPUT_PPM:
+ {
+ FILE* f = fopen(QFile::encodeName(destPath), "wb");
+ if (!f)
+ {
+ qDebug("Failed to open ppm file for writing");
+ return false;
+ }
+
+ fprintf(f, "P6\n%d %d\n255\n", width, height);
+ fwrite(imageData.data(), 1, width*height*3, f);
+ fclose(f);
+ break;
+ }
+ default:
+ {
+ qDebug("Invalid output file format");
+ return false;
+ }
+ }
+
+ if (m_cancel)
+ {
+ ::remove(QFile::encodeName(destPath));
+ return false;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------
+
+void RawDecodingIface::writeRawProfile(png_struct *ping, png_info *ping_info, char *profile_type,
+ char *profile_data, png_uint_32 length)
+{
+ png_textp text;
+
+ register long i;
+
+ uchar *sp;
+
+ png_charp dp;
+
+ png_uint_32 allocated_length, description_length;
+
+ const uchar hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+
+ qDebug("Writing Raw profile: type=%s, length=%i", profile_type, (int)length);
+
+ text = (png_textp) png_malloc(ping, (png_uint_32) sizeof(png_text));
+ description_length = strlen((const char *) profile_type);
+ allocated_length = (png_uint_32) (length*2 + (length >> 5) + 20 + description_length);
+
+ text[0].text = (png_charp) png_malloc(ping, allocated_length);
+ text[0].key = (png_charp) png_malloc(ping, (png_uint_32) 80);
+ text[0].key[0] = '\0';
+
+ concatenateString(text[0].key, "Raw profile type ", 4096);
+ concatenateString(text[0].key, (const char *) profile_type, 62);
+
+ sp = (uchar*)profile_data;
+ dp = text[0].text;
+ *dp++='\n';
+
+ copyString(dp, (const char *) profile_type, allocated_length);
+
+ dp += description_length;
+ *dp++='\n';
+
+ formatString(dp, allocated_length-strlen(text[0].text), "%8lu ", length);
+
+ dp += 8;
+
+ for (i=0; i < (long) length; i++)
+ {
+ if (i%36 == 0)
+ *dp++='\n';
+
+ *(dp++)=(char) hex[((*sp >> 4) & 0x0f)];
+ *(dp++)=(char) hex[((*sp++ ) & 0x0f)];
+ }
+
+ *dp++='\n';
+ *dp='\0';
+ text[0].text_length = (png_size_t) (dp-text[0].text);
+ text[0].compression = -1;
+
+ if (text[0].text_length <= allocated_length)
+ png_set_text(ping, ping_info,text, 1);
+
+ png_free(ping, text[0].text);
+ png_free(ping, text[0].key);
+ png_free(ping, text);
+}
+
+size_t RawDecodingIface::concatenateString(char *destination, const char *source, const size_t length)
+{
+ register char *q;
+
+ register const char *p;
+
+ register size_t i;
+
+ size_t count;
+
+ if ( !destination || !source || length == 0 )
+ return 0;
+
+ p = source;
+ q = destination;
+ i = length;
+
+ while ((i-- != 0) && (*q != '\0'))
+ q++;
+
+ count = (size_t) (q-destination);
+ i = length-count;
+
+ if (i == 0)
+ return(count+strlen(p));
+
+ while (*p != '\0')
+ {
+ if (i != 1)
+ {
+ *q++=(*p);
+ i--;
+ }
+ p++;
+ }
+
+ *q='\0';
+
+ return(count+(p-source));
+}
+
+size_t RawDecodingIface::copyString(char *destination, const char *source, const size_t length)
+{
+ register char *q;
+
+ register const char *p;
+
+ register size_t i;
+
+ if ( !destination || !source || length == 0 )
+ return 0;
+
+ p = source;
+ q = destination;
+ i = length;
+
+ if ((i != 0) && (--i != 0))
+ {
+ do
+ {
+ if ((*q++=(*p++)) == '\0')
+ break;
+ }
+ while (--i != 0);
+ }
+
+ if (i == 0)
+ {
+ if (length != 0)
+ *q='\0';
+
+ do
+ {
+ }
+ while (*p++ != '\0');
+ }
+
+ return((size_t) (p-source-1));
+}
+
+long RawDecodingIface::formatString(char *string, const size_t length, const char *format,...)
+{
+ long n;
+
+ va_list operands;
+
+ va_start(operands,format);
+ n = (long) formatStringList(string, length, format, operands);
+ va_end(operands);
+ return(n);
+}
+
+long RawDecodingIface::formatStringList(char *string, const size_t length, const char *format, va_list operands)
+{
+ int n = vsnprintf(string, length, format, operands);
+
+ if (n < 0)
+ string[length-1] = '\0';
+
+ return((long) n);
+}
+
+} // namespace KIPIRawConverterPlugin
diff --git a/kipi-plugins/rawconverter/rawdecodingiface.h b/kipi-plugins/rawconverter/rawdecodingiface.h
new file mode 100644
index 0000000..6233447
--- /dev/null
+++ b/kipi-plugins/rawconverter/rawdecodingiface.h
@@ -0,0 +1,101 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-12-09
+ * Description : RAW decoding interface
+ *
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel.wiesweg@gmx.de>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 RAW_DECODING_IFACE_H
+#define RAW_DECODING_IFACE_H
+
+// C++ includes.
+
+#include <cstdarg>
+
+// LibPNG includes.
+
+extern "C"
+{
+#include <png.h>
+}
+
+
+// Qt Includes.
+
+#include <qstring.h>
+#include <qobject.h>
+#include <qimage.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/kdcraw.h>
+#include <libkdcraw/rawdecodingsettings.h>
+
+// Local includes.
+
+#include "savesettingswidget.h"
+
+namespace KIPIRawConverterPlugin
+{
+
+class RawDecodingIface : public KDcrawIface::KDcraw
+{
+ Q_OBJECT
+
+public:
+
+ RawDecodingIface();
+ ~RawDecodingIface();
+
+public:
+
+ /** Extract a small size of decode RAW data in 8 bits/color/pixels
+ using sRGB color space.
+ */
+ bool decodeHalfRAWImage(const QString& filePath,
+ QString& destPath, SaveSettingsWidget::OutputFormat outputFileFormat,
+ KDcrawIface::RawDecodingSettings rawDecodingSettings);
+
+ /** Extract a full size of RAW data in 8 bits/color/pixels using
+ sRGB color space.
+ */
+ bool decodeRAWImage(const QString& filePath,
+ QString& destPath, SaveSettingsWidget::OutputFormat outputFileFormat,
+ KDcrawIface::RawDecodingSettings rawDecodingSettings);
+
+private:
+
+ QByteArray getICCProfilFromFile(KDcrawIface::RawDecodingSettings::OutputColorSpace colorSpace);
+
+ bool loadedFromDcraw(const QString& filePath,
+ QString& destPath, SaveSettingsWidget::OutputFormat outputFileFormat,
+ const QByteArray& imageData, int width, int height);
+
+ void writeRawProfile(png_struct *ping, png_info *ping_info, char *profile_type,
+ char *profile_data, png_uint_32 length);
+
+ size_t concatenateString(char *destination, const char *source, const size_t length);
+ size_t copyString(char *destination, const char *source, const size_t length);
+ long formatString(char *string, const size_t length, const char *format,...);
+ long formatStringList(char *string, const size_t length, const char *format, va_list operands);
+};
+
+} // namespace KIPIRawConverterPlugin
+
+#endif /* RAW_DECODING_IFACE_H */
diff --git a/kipi-plugins/rawconverter/savesettingswidget.cpp b/kipi-plugins/rawconverter/savesettingswidget.cpp
new file mode 100644
index 0000000..8531863
--- /dev/null
+++ b/kipi-plugins/rawconverter/savesettingswidget.cpp
@@ -0,0 +1,153 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-13
+ * Description : save settings widgets
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qcombobox.h>
+#include <qvbuttongroup.h>
+#include <qradiobutton.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qstring.h>
+
+// KDE includes.
+
+#include <kdialog.h>
+#include <klocale.h>
+
+// Local includes.
+
+#include "savesettingswidget.h"
+#include "savesettingswidget.moc"
+
+namespace KIPIRawConverterPlugin
+{
+
+class SaveSettingsWidgetPriv
+{
+public:
+
+ SaveSettingsWidgetPriv()
+ {
+ formatLabel = 0;
+ conflictLabel = 0;
+ conflictButtonGroup = 0;
+ formatComboBox = 0;
+ overwriteButton = 0;
+ promptButton = 0;
+ }
+
+ QLabel *formatLabel;
+ QLabel *conflictLabel;
+
+ QVButtonGroup *conflictButtonGroup;
+
+ QComboBox *formatComboBox;
+
+ QRadioButton *overwriteButton;
+ QRadioButton *promptButton;
+};
+
+SaveSettingsWidget::SaveSettingsWidget(QWidget *parent)
+ : QWidget(parent, 0, Qt::WDestructiveClose)
+{
+ d = new SaveSettingsWidgetPriv;
+ QGridLayout* settingsBoxLayout = new QGridLayout(this, 3, 1, KDialog::spacingHint());
+
+ d->formatLabel = new QLabel(i18n("Output file format:"), this);
+ d->formatComboBox = new QComboBox( false, this );
+ d->formatComboBox->insertItem( "JPEG", OUTPUT_JPEG );
+ d->formatComboBox->insertItem( "TIFF", OUTPUT_TIFF );
+ d->formatComboBox->insertItem( "PPM", OUTPUT_PPM );
+ d->formatComboBox->insertItem( "PNG", OUTPUT_PNG );
+ QWhatsThis::add(d->formatComboBox, i18n("<p>Set here the output file format to use:<p>"
+ "<b>JPEG</b>: output the processed image in JPEG Format. "
+ "this format will give smaller-sized files. Minimum JPEG "
+ "compression level will be used during Raw conversion.<p>"
+ "<b>Warning!!! duing of destructive compression algorithm, "
+ "JPEG is a lossy quality format.</b><p>"
+ "<b>TIFF</b>: output the processed image in TIFF Format. "
+ "This generates larges, without "
+ "losing quality. Adobe Deflate compression "
+ "will be used during conversion.<p>"
+ "<b>PPM</b>: output the processed image in PPM Format. "
+ "This generates the largest files, without "
+ "losing quality.<p>"
+ "<b>PNG</b>: output the processed image in PNG Format. "
+ "This generates larges, without "
+ "losing quality. Maximum PNG compression "
+ "will be used during conversion."));
+
+ d->conflictLabel = new QLabel(i18n("If Target File Exists:"), this);
+ d->conflictButtonGroup = new QVButtonGroup(this);
+ d->overwriteButton = new QRadioButton(i18n("Overwrite automatically"), d->conflictButtonGroup);
+ d->promptButton = new QRadioButton(i18n("Open rename-file dialog"), d->conflictButtonGroup);
+ d->conflictButtonGroup->insert(d->overwriteButton, OVERWRITE);
+ d->conflictButtonGroup->insert(d->promptButton, ASKTOUSER);
+ d->conflictButtonGroup->setRadioButtonExclusive(true);
+ d->overwriteButton->setChecked(true);
+ d->conflictButtonGroup->setFrameStyle(QFrame::NoFrame|QFrame::Plain);
+ d->conflictButtonGroup->setInsideMargin(0);
+
+ settingsBoxLayout->addMultiCellWidget(d->formatLabel, 0, 0, 0, 0);
+ settingsBoxLayout->addMultiCellWidget(d->formatComboBox, 0, 0, 1, 1);
+ settingsBoxLayout->addMultiCellWidget(d->conflictLabel, 1, 1, 0, 1);
+ settingsBoxLayout->addMultiCellWidget(d->conflictButtonGroup, 2, 2, 0, 1);
+ settingsBoxLayout->setRowStretch(3, 10);
+
+ connect(d->formatComboBox, SIGNAL(activated(int)),
+ this, SIGNAL(signalSaveFormatChanged()));
+}
+
+SaveSettingsWidget::~SaveSettingsWidget()
+{
+ delete d;
+}
+
+void SaveSettingsWidget::setDefaultSettings()
+{
+ setFileFormat(OUTPUT_PNG);
+ setConflictRule(OVERWRITE);
+}
+
+SaveSettingsWidget::OutputFormat SaveSettingsWidget::fileFormat()
+{
+ return(OutputFormat)(d->formatComboBox->currentItem());
+}
+
+void SaveSettingsWidget::setFileFormat(SaveSettingsWidget::OutputFormat f)
+{
+ d->formatComboBox->setCurrentItem((int)f);
+}
+
+SaveSettingsWidget::ConflictRule SaveSettingsWidget::conflictRule()
+{
+ return((ConflictRule)(d->conflictButtonGroup->selectedId()));
+}
+
+void SaveSettingsWidget::setConflictRule(SaveSettingsWidget::ConflictRule r)
+{
+ d->conflictButtonGroup->setButton((int)r);
+}
+
+} // NameSpace KIPIRawConverterPlugin
diff --git a/kipi-plugins/rawconverter/savesettingswidget.h b/kipi-plugins/rawconverter/savesettingswidget.h
new file mode 100644
index 0000000..a7b1f14
--- /dev/null
+++ b/kipi-plugins/rawconverter/savesettingswidget.h
@@ -0,0 +1,79 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-13
+ * Description : save settings widgets
+ *
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SAVESETTINGSWIDGET_H
+#define SAVESETTINGSWIDGET_H
+
+// Qt includes.
+
+#include <qwidget.h>
+
+namespace KIPIRawConverterPlugin
+{
+
+class SaveSettingsWidgetPriv;
+
+class SaveSettingsWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ enum OutputFormat
+ {
+ OUTPUT_JPEG = 0,
+ OUTPUT_TIFF,
+ OUTPUT_PPM,
+ OUTPUT_PNG
+ };
+
+ enum ConflictRule
+ {
+ OVERWRITE = 0,
+ ASKTOUSER
+ };
+
+public:
+
+ SaveSettingsWidget(QWidget *parent);
+ ~SaveSettingsWidget();
+
+ SaveSettingsWidget::OutputFormat fileFormat();
+ ConflictRule conflictRule();
+
+ void setFileFormat(SaveSettingsWidget::OutputFormat f);
+ void setConflictRule(ConflictRule r);
+
+ void setDefaultSettings();
+
+signals:
+
+ void signalSaveFormatChanged();
+
+private:
+
+ SaveSettingsWidgetPriv* d;
+};
+
+} // NameSpace KIPIRawConverterPlugin
+
+#endif /* SAVESETTINGSWIDGET_H */
diff --git a/kipi-plugins/rawconverter/singledialog.cpp b/kipi-plugins/rawconverter/singledialog.cpp
new file mode 100644
index 0000000..e7c30b5
--- /dev/null
+++ b/kipi-plugins/rawconverter/singledialog.cpp
@@ -0,0 +1,597 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-22
+ * Description : Raw converter single dialog
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+}
+
+// C++ includes.
+
+#include <cstdio>
+
+// Qt includes.
+
+#include <qtimer.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qfileinfo.h>
+#include <qevent.h>
+#include <qpushbutton.h>
+#include <qfile.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kconfig.h>
+#include <kio/renamedlg.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/dcrawsettingswidget.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "previewwidget.h"
+#include "rawdecodingiface.h"
+#include "savesettingswidget.h"
+#include "actionthread.h"
+#include "singledialog.h"
+#include "singledialog.moc"
+
+namespace KIPIRawConverterPlugin
+{
+
+SingleDialog::SingleDialog(const QString& file, QWidget */*parent*/)
+ : KDialogBase(0, 0, false, i18n("Raw Image Converter"),
+ Help|Default|User1|User2|User3|Close, Close, true,
+ i18n("&Preview"), i18n("Con&vert"), i18n("&Abort"))
+{
+ m_inputFile = file;
+ m_inputFileName = QFileInfo(file).fileName();
+
+ QWidget *page = new QWidget( this );
+ setMainWidget( page );
+ QGridLayout *mainLayout = new QGridLayout(page, 1, 1, 0, spacingHint());
+
+ m_previewWidget = new PreviewWidget(page);
+
+ // ---------------------------------------------------------------
+
+ m_decodingSettingsBox = new KDcrawIface::DcrawSettingsWidget(page, false, true, true);
+ m_saveSettingsBox = new SaveSettingsWidget(m_decodingSettingsBox);
+
+#if KDCRAW_VERSION >= 0x000105
+ m_decodingSettingsBox->addItem(m_saveSettingsBox, i18n("Save settings"));
+ m_decodingSettingsBox->updateMinimumWidth();
+#else
+ m_decodingSettingsBox->insertTab(m_saveSettingsBox, i18n("Save settings"));
+#endif
+
+ mainLayout->addMultiCellWidget(m_previewWidget, 0, 1, 0, 0);
+ mainLayout->addMultiCellWidget(m_decodingSettingsBox, 0, 0, 1, 1);
+ mainLayout->setColStretch(0, 10);
+ mainLayout->setRowStretch(1, 10);
+
+ // ---------------------------------------------------------------
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("RAW Image Converter"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to convert a Raw image"),
+ "(c) 2003-2005, Renchi Raju\n"
+ "(c) 2006-2008, Gilles Caulier");
+
+ m_about->addAuthor("Renchi Raju", I18N_NOOP("Original author"),
+ "renchi at pooh dot tam dot uiuc dot edu");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // ---------------------------------------------------------------
+
+ setButtonTip( User1, i18n("<p>Generate a Preview from current settings. "
+ "Uses a simple bilinear interpolation for "
+ "quick results."));
+
+ setButtonTip( User2, i18n("<p>Convert the Raw Image from current settings. "
+ "This uses a high-quality adaptive algorithm."));
+
+ setButtonTip( User3, i18n("<p>Abort the current Raw file conversion"));
+
+ setButtonTip( Close, i18n("<p>Exit Raw Converter"));
+
+ m_blinkPreviewTimer = new QTimer(this);
+ m_blinkConvertTimer = new QTimer(this);
+ m_thread = new ActionThread(this);
+
+ // ---------------------------------------------------------------
+
+ connect(m_blinkPreviewTimer, SIGNAL(timeout()),
+ this, SLOT(slotPreviewBlinkTimerDone()));
+
+ connect(m_blinkConvertTimer, SIGNAL(timeout()),
+ this, SLOT(slotConvertBlinkTimerDone()));
+
+ // ---------------------------------------------------------------
+
+ busy(false);
+ readSettings();
+ QTimer::singleShot(0, this, SLOT( slotIdentify() ) );
+}
+
+SingleDialog::~SingleDialog()
+{
+ delete m_about;
+ delete m_thread;
+}
+
+void SingleDialog::closeEvent(QCloseEvent *e)
+{
+ if (!e) return;
+ m_blinkPreviewTimer->stop();
+ m_blinkConvertTimer->stop();
+ m_thread->cancel();
+ saveSettings();
+ e->accept();
+}
+
+void SingleDialog::slotClose()
+{
+ m_blinkPreviewTimer->stop();
+ m_blinkConvertTimer->stop();
+ m_thread->cancel();
+ saveSettings();
+ KDialogBase::slotClose();
+}
+
+void SingleDialog::slotDefault()
+{
+ m_decodingSettingsBox->setDefaultSettings();
+ m_saveSettingsBox->setDefaultSettings();
+}
+
+void SingleDialog::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("RawConverter Settings");
+
+ m_decodingSettingsBox->setWhiteBalance((KDcrawIface::RawDecodingSettings::WhiteBalance)
+ config.readNumEntry("White Balance",
+ KDcrawIface::RawDecodingSettings::CAMERA));
+ m_decodingSettingsBox->setCustomWhiteBalance(config.readNumEntry("Custom White Balance", 6500));
+ m_decodingSettingsBox->setCustomWhiteBalanceGreen(config.readDoubleNumEntry("Custom White Balance Green", 1.0));
+ m_decodingSettingsBox->setFourColor(config.readBoolEntry("Four Color RGB", false));
+ m_decodingSettingsBox->setUnclipColor(config.readNumEntry("Unclip Color", 0));
+ m_decodingSettingsBox->setDontStretchPixels(config.readBoolEntry("Dont Stretch Pixels", false));
+ m_decodingSettingsBox->setNoiseReduction(config.readBoolEntry("Use Noise Reduction", false));
+ m_decodingSettingsBox->setBrightness(config.readDoubleNumEntry("Brightness Multiplier", 1.0));
+ m_decodingSettingsBox->setUseBlackPoint(config.readBoolEntry("Use Black Point", false));
+ m_decodingSettingsBox->setBlackPoint(config.readNumEntry("Black Point", 0));
+#if KDCRAW_VERSION >= 0x000105
+ m_decodingSettingsBox->setUseWhitePoint(config.readBoolEntry("Use White Point", false));
+ m_decodingSettingsBox->setWhitePoint(config.readNumEntry("White Point", 0));
+ m_decodingSettingsBox->setMedianFilterPasses(config.readNumEntry("Median Filter Passes", 0));
+#endif
+ m_decodingSettingsBox->setNRThreshold(config.readNumEntry("NR Threshold", 100));
+ m_decodingSettingsBox->setUseCACorrection(config.readBoolEntry("EnableCACorrection", false));
+ m_decodingSettingsBox->setcaRedMultiplier(config.readDoubleNumEntry("caRedMultiplier", 1.0));
+ m_decodingSettingsBox->setcaBlueMultiplier(config.readDoubleNumEntry("caBlueMultiplier", 1.0));
+
+ m_decodingSettingsBox->setQuality(
+ (KDcrawIface::RawDecodingSettings::DecodingQuality)config.readNumEntry("Decoding Quality",
+ (int)(KDcrawIface::RawDecodingSettings::BILINEAR)));
+
+ m_decodingSettingsBox->setOutputColorSpace(
+ (KDcrawIface::RawDecodingSettings::OutputColorSpace)config.readNumEntry("Output Color Space",
+ (int)(KDcrawIface::RawDecodingSettings::SRGB)));
+
+ m_saveSettingsBox->setFileFormat(
+ (SaveSettingsWidget::OutputFormat)config.readNumEntry("Output Format",
+ (int)(SaveSettingsWidget::OUTPUT_PNG)));
+
+ m_saveSettingsBox->setConflictRule(
+ (SaveSettingsWidget::ConflictRule)config.readNumEntry("Conflict",
+ (int)(SaveSettingsWidget::OVERWRITE)));
+
+ resize(configDialogSize(config, QString("Single Raw Converter Dialog")));
+}
+
+void SingleDialog::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("RawConverter Settings");
+
+ config.writeEntry("White Balance", m_decodingSettingsBox->whiteBalance());
+ config.writeEntry("Custom White Balance", m_decodingSettingsBox->customWhiteBalance());
+ config.writeEntry("Custom White Balance Green", m_decodingSettingsBox->customWhiteBalanceGreen());
+ config.writeEntry("Four Color RGB", m_decodingSettingsBox->useFourColor());
+ config.writeEntry("Unclip Color", m_decodingSettingsBox->unclipColor());
+ config.writeEntry("Dont Stretch Pixels", m_decodingSettingsBox->useDontStretchPixels());
+ config.writeEntry("Use Noise Reduction", m_decodingSettingsBox->useNoiseReduction());
+ config.writeEntry("Brightness Multiplier", m_decodingSettingsBox->brightness());
+ config.writeEntry("Use Black Point", m_decodingSettingsBox->useBlackPoint());
+ config.writeEntry("Black Point", m_decodingSettingsBox->blackPoint());
+#if KDCRAW_VERSION >= 0x000105
+ config.writeEntry("Use White Point", m_decodingSettingsBox->useWhitePoint());
+ config.writeEntry("White Point", m_decodingSettingsBox->whitePoint());
+ config.writeEntry("Median Filter Passes", m_decodingSettingsBox->medianFilterPasses());
+#endif
+ config.writeEntry("NR Threshold", m_decodingSettingsBox->NRThreshold());
+ config.writeEntry("EnableCACorrection", m_decodingSettingsBox->useCACorrection());
+ config.writeEntry("caRedMultiplier", m_decodingSettingsBox->caRedMultiplier());
+ config.writeEntry("caBlueMultiplier", m_decodingSettingsBox->caBlueMultiplier());
+ config.writeEntry("Decoding Quality", (int)m_decodingSettingsBox->quality());
+ config.writeEntry("Output Color Space", (int)m_decodingSettingsBox->outputColorSpace());
+
+ config.writeEntry("Output Format", (int)m_saveSettingsBox->fileFormat());
+ config.writeEntry("Conflict", (int)m_saveSettingsBox->conflictRule());
+
+ saveDialogSize(config, QString("Single Raw Converter Dialog"));
+ config.sync();
+}
+
+void SingleDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("rawconverter", "kipi-plugins");
+}
+
+// 'Preview' dialog button.
+void SingleDialog::slotUser1()
+{
+ KDcrawIface::RawDecodingSettings rawDecodingSettings;
+ rawDecodingSettings.whiteBalance = m_decodingSettingsBox->whiteBalance();
+ rawDecodingSettings.customWhiteBalance = m_decodingSettingsBox->customWhiteBalance();
+ rawDecodingSettings.customWhiteBalanceGreen = m_decodingSettingsBox->customWhiteBalanceGreen();
+ rawDecodingSettings.RGBInterpolate4Colors = m_decodingSettingsBox->useFourColor();
+ rawDecodingSettings.unclipColors = m_decodingSettingsBox->unclipColor();
+ rawDecodingSettings.DontStretchPixels = m_decodingSettingsBox->useDontStretchPixels();
+ rawDecodingSettings.enableNoiseReduction = m_decodingSettingsBox->useNoiseReduction();
+ rawDecodingSettings.brightness = m_decodingSettingsBox->brightness();
+ rawDecodingSettings.enableBlackPoint = m_decodingSettingsBox->useBlackPoint();
+ rawDecodingSettings.blackPoint = m_decodingSettingsBox->blackPoint();
+#if KDCRAW_VERSION >= 0x000105
+ rawDecodingSettings.enableWhitePoint = m_decodingSettingsBox->useWhitePoint();
+ rawDecodingSettings.whitePoint = m_decodingSettingsBox->whitePoint();
+ rawDecodingSettings.medianFilterPasses = m_decodingSettingsBox->medianFilterPasses();
+#endif
+ rawDecodingSettings.NRThreshold = m_decodingSettingsBox->NRThreshold();
+ rawDecodingSettings.enableCACorrection = m_decodingSettingsBox->useCACorrection();
+ rawDecodingSettings.caMultiplier[0] = m_decodingSettingsBox->caRedMultiplier();
+ rawDecodingSettings.caMultiplier[1] = m_decodingSettingsBox->caBlueMultiplier();
+ rawDecodingSettings.RAWQuality = m_decodingSettingsBox->quality();
+ rawDecodingSettings.outputColorSpace = m_decodingSettingsBox->outputColorSpace();
+
+ m_thread->setRawDecodingSettings(rawDecodingSettings, SaveSettingsWidget::OUTPUT_PPM);
+ m_thread->processHalfRawFile(KURL(m_inputFile));
+ if (!m_thread->running())
+ m_thread->start();
+}
+
+// 'Convert' dialog button.
+void SingleDialog::slotUser2()
+{
+ KDcrawIface::RawDecodingSettings rawDecodingSettings;
+ rawDecodingSettings.whiteBalance = m_decodingSettingsBox->whiteBalance();
+ rawDecodingSettings.customWhiteBalance = m_decodingSettingsBox->customWhiteBalance();
+ rawDecodingSettings.customWhiteBalanceGreen = m_decodingSettingsBox->customWhiteBalanceGreen();
+ rawDecodingSettings.RGBInterpolate4Colors = m_decodingSettingsBox->useFourColor();
+ rawDecodingSettings.unclipColors = m_decodingSettingsBox->unclipColor();
+ rawDecodingSettings.DontStretchPixels = m_decodingSettingsBox->useDontStretchPixels();
+ rawDecodingSettings.enableNoiseReduction = m_decodingSettingsBox->useNoiseReduction();
+ rawDecodingSettings.brightness = m_decodingSettingsBox->brightness();
+ rawDecodingSettings.enableBlackPoint = m_decodingSettingsBox->useBlackPoint();
+ rawDecodingSettings.blackPoint = m_decodingSettingsBox->blackPoint();
+#if KDCRAW_VERSION >= 0x000105
+ rawDecodingSettings.enableWhitePoint = m_decodingSettingsBox->useWhitePoint();
+ rawDecodingSettings.whitePoint = m_decodingSettingsBox->whitePoint();
+ rawDecodingSettings.medianFilterPasses = m_decodingSettingsBox->medianFilterPasses();
+#endif
+ rawDecodingSettings.NRThreshold = m_decodingSettingsBox->NRThreshold();
+ rawDecodingSettings.enableCACorrection = m_decodingSettingsBox->useCACorrection();
+ rawDecodingSettings.caMultiplier[0] = m_decodingSettingsBox->caRedMultiplier();
+ rawDecodingSettings.caMultiplier[1] = m_decodingSettingsBox->caBlueMultiplier();
+ rawDecodingSettings.RAWQuality = m_decodingSettingsBox->quality();
+ rawDecodingSettings.outputColorSpace = m_decodingSettingsBox->outputColorSpace();
+
+ m_thread->setRawDecodingSettings(rawDecodingSettings, m_saveSettingsBox->fileFormat());
+ m_thread->processRawFile(KURL(m_inputFile));
+ if (!m_thread->running())
+ m_thread->start();
+}
+
+// 'Abort' dialog button.
+void SingleDialog::slotUser3()
+{
+ m_thread->cancel();
+}
+
+void SingleDialog::slotIdentify()
+{
+ m_thread->identifyRawFile(KURL(m_inputFile), true);
+ if (!m_thread->running())
+ m_thread->start();
+}
+
+void SingleDialog::busy(bool val)
+{
+ m_decodingSettingsBox->setEnabled(!val);
+ m_saveSettingsBox->setEnabled(!val);
+ enableButton (User1, !val);
+ enableButton (User2, !val);
+ enableButton (User3, val);
+ enableButton (Close, !val);
+}
+
+void SingleDialog::identified(const QString&, const QString& identity, const QPixmap& preview)
+{
+ m_previewWidget->setInfo(m_inputFileName + QString(" :\n") + identity, Qt::white, preview);
+}
+
+void SingleDialog::previewing(const QString&)
+{
+ m_previewBlink = false;
+ m_previewWidget->setCursor( KCursor::waitCursor() );
+ m_blinkPreviewTimer->start(200);
+}
+
+void SingleDialog::previewed(const QString&, const QString& tmpFile)
+{
+ m_previewWidget->unsetCursor();
+ m_blinkPreviewTimer->stop();
+ m_previewWidget->load(tmpFile);
+ ::remove(QFile::encodeName(tmpFile));
+}
+
+void SingleDialog::previewFailed(const QString&)
+{
+ m_previewWidget->unsetCursor();
+ m_blinkPreviewTimer->stop();
+ m_previewWidget->setInfo(i18n("Failed to generate preview"), Qt::red);
+}
+
+void SingleDialog::processing(const QString&)
+{
+ m_convertBlink = false;
+ m_previewWidget->setCursor( KCursor::waitCursor() );
+ m_blinkConvertTimer->start(200);
+}
+
+void SingleDialog::processed(const QString&, const QString& tmpFile)
+{
+ m_previewWidget->unsetCursor();
+ m_blinkConvertTimer->stop();
+ m_previewWidget->load(tmpFile);
+ QString filter("*.");
+ QString ext;
+
+ switch(m_saveSettingsBox->fileFormat())
+ {
+ case SaveSettingsWidget::OUTPUT_JPEG:
+ ext = "jpg";
+ break;
+ case SaveSettingsWidget::OUTPUT_TIFF:
+ ext = "tif";
+ break;
+ case SaveSettingsWidget::OUTPUT_PPM:
+ ext = "ppm";
+ break;
+ case SaveSettingsWidget::OUTPUT_PNG:
+ ext = "png";
+ break;
+ }
+
+ filter += ext;
+ QFileInfo fi(m_inputFile);
+ QString destFile = fi.dirPath(true) + QString("/") + fi.baseName() + QString(".") + ext;
+
+ if (m_saveSettingsBox->conflictRule() != SaveSettingsWidget::OVERWRITE)
+ {
+ struct stat statBuf;
+ if (::stat(QFile::encodeName(destFile), &statBuf) == 0)
+ {
+ KIO::RenameDlg dlg(this, i18n("Save Raw Image converted from '%1' as").arg(fi.fileName()),
+ tmpFile, destFile,
+ KIO::RenameDlg_Mode(KIO::M_SINGLE | KIO::M_OVERWRITE | KIO::M_SKIP));
+
+ switch (dlg.exec())
+ {
+ case KIO::R_CANCEL:
+ case KIO::R_SKIP:
+ {
+ destFile = QString();
+ break;
+ }
+ case KIO::R_RENAME:
+ {
+ destFile = dlg.newDestURL().path();
+ break;
+ }
+ default: // Overwrite.
+ break;
+ }
+ }
+ }
+
+ if (!destFile.isEmpty())
+ {
+ if (::rename(QFile::encodeName(tmpFile), QFile::encodeName(destFile)) != 0)
+ {
+ KMessageBox::error(this, i18n("Failed to save image %1").arg( destFile ));
+ }
+ }
+}
+
+void SingleDialog::processingFailed(const QString&)
+{
+ m_previewWidget->unsetCursor();
+ m_blinkConvertTimer->stop();
+ m_previewWidget->setInfo(i18n("Failed to convert Raw image"), Qt::red);
+}
+
+void SingleDialog::slotPreviewBlinkTimerDone()
+{
+ QString preview = i18n("Generating Preview...");
+
+ if (m_previewBlink)
+ m_previewWidget->setInfo(preview, Qt::green);
+ else
+ m_previewWidget->setInfo(preview, Qt::darkGreen);
+
+ m_previewBlink = !m_previewBlink;
+ m_blinkPreviewTimer->start(200);
+}
+
+void SingleDialog::slotConvertBlinkTimerDone()
+{
+ QString convert = i18n("Converting Raw Image...");
+
+ if (m_convertBlink)
+ m_previewWidget->setInfo(convert, Qt::green);
+ else
+ m_previewWidget->setInfo(convert, Qt::darkGreen);
+
+ m_convertBlink = !m_convertBlink;
+ m_blinkConvertTimer->start(200);
+}
+
+void SingleDialog::customEvent(QCustomEvent *event)
+{
+ if (!event) return;
+
+ EventData *d = (EventData*) event->data();
+ if (!d) return;
+
+ QString text;
+
+ if (d->starting) // Something have been started...
+ {
+ switch (d->action)
+ {
+ case(IDENTIFY_FULL):
+ break;
+ case(PREVIEW):
+ {
+ busy(true);
+ previewing(d->filePath);
+ break;
+ }
+ case(PROCESS):
+ {
+ busy(true);
+ processing(d->filePath);
+ break;
+ }
+ default:
+ {
+ kdWarning( 51000 ) << "KIPIRawConverterPlugin: Unknown event" << endl;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (!d->success) // Something is failed...
+ {
+ switch (d->action)
+ {
+ case(IDENTIFY_FULL):
+ break;
+ case(PREVIEW):
+ {
+ previewFailed(d->filePath);
+ busy(false);
+ break;
+ }
+ case(PROCESS):
+ {
+ processingFailed(d->filePath);
+ busy(false);
+ break;
+ }
+ default:
+ {
+ kdWarning( 51000 ) << "KIPIRawConverterPlugin: Unknown event" << endl;
+ break;
+ }
+ }
+ }
+ else // Something is done...
+ {
+ switch (d->action)
+ {
+ case(IDENTIFY_FULL):
+ {
+ QPixmap pix = QPixmap(d->image.scale(256, 256, QImage::ScaleMin));
+ identified(d->filePath, d->message, pix);
+ busy(false);
+ break;
+ }
+ case(PREVIEW):
+ {
+ previewed(d->filePath, d->destPath);
+ busy(false);
+ break;
+ }
+ case(PROCESS):
+ {
+ processed(d->filePath, d->destPath);
+ busy(false);
+ break;
+ }
+ default:
+ {
+ kdWarning( 51000 ) << "KIPIRawConverterPlugin: Unknown event" << endl;
+ break;
+ }
+ }
+ }
+ }
+
+ delete d;
+}
+
+} // NameSpace KIPIRawConverterPlugin
diff --git a/kipi-plugins/rawconverter/singledialog.h b/kipi-plugins/rawconverter/singledialog.h
new file mode 100644
index 0000000..2038031
--- /dev/null
+++ b/kipi-plugins/rawconverter/singledialog.h
@@ -0,0 +1,124 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-22
+ * Description : Raw converter single dialog
+ *
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SINGLEDIALOG_H
+#define SINGLEDIALOG_H
+
+// Qt includes.
+
+#include <qstring.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QCloseEvent;
+class QCustomEvent;
+class QTimer;
+
+namespace KDcrawIface
+{
+class DcrawSettingsWidget;
+}
+
+namespace KIPIRawConverterPlugin
+{
+
+class PreviewWidget;
+class ActionThread;
+class SaveSettingsWidget;
+
+class SingleDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ SingleDialog(const QString& file, QWidget *parent);
+ ~SingleDialog();
+
+protected:
+
+ void customEvent(QCustomEvent *event);
+ void closeEvent(QCloseEvent *e);
+
+private:
+
+ void readSettings();
+ void saveSettings();
+
+ void busy(bool busy);
+
+ void identified(const QString&, const QString& identity, const QPixmap& preview);
+
+ void previewing(const QString&);
+ void previewed(const QString&, const QString& tmpFile);
+ void previewFailed(const QString&);
+
+ void processing(const QString&);
+ void processed(const QString&, const QString& tmpFile);
+ void processingFailed(const QString&);
+
+private slots:
+
+ void slotDefault();
+ void slotClose();
+ void slotHelp();
+ void slotUser1();
+ void slotUser2();
+ void slotUser3();
+
+ void slotIdentify();
+
+ void slotPreviewBlinkTimerDone();
+ void slotConvertBlinkTimerDone();
+
+private:
+
+ bool m_previewBlink;
+ bool m_convertBlink;
+
+ QString m_inputFile;
+ QString m_inputFileName;
+
+ QTimer *m_blinkPreviewTimer;
+ QTimer *m_blinkConvertTimer;
+
+ PreviewWidget *m_previewWidget;
+
+ ActionThread *m_thread;
+
+ SaveSettingsWidget *m_saveSettingsBox;
+
+ KDcrawIface::DcrawSettingsWidget *m_decodingSettingsBox;
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // NameSpace KIPIRawConverterPlugin
+
+#endif // SINGLEDIALOG_H
diff --git a/kipi-plugins/sendimages/Makefile.am b/kipi-plugins/sendimages/Makefile.am
new file mode 100644
index 0000000..77c576c
--- /dev/null
+++ b/kipi-plugins/sendimages/Makefile.am
@@ -0,0 +1,29 @@
+INCLUDES = $(LIBKEXIV2_CFLAGS) $(LIBKDCRAW_CFLAGS) $(KIPI_PLUGINS_COMMON_INCLUDE) \
+ $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_sendimages.la
+kipiplugin_sendimages_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+
+# Srcs for the plugin
+kipiplugin_sendimages_la_SOURCES = plugin_sendimages.cpp sendimagesdialog.cpp \
+ listimageserrordialog.cpp sendimages.cpp
+
+# Libs needed by the plugin
+kipiplugin_sendimages_la_LIBADD = $(LIBKEXIV2_LIBS) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIBKDCRAW_LIBS) \
+ $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_sendimages_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) \
+ -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_sendimages.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_sendimages.pot
+
+
diff --git a/kipi-plugins/sendimages/actions.h b/kipi-plugins/sendimages/actions.h
new file mode 100644
index 0000000..6946e19
--- /dev/null
+++ b/kipi-plugins/sendimages/actions.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-02-25
+ * Description : a kipi plugin to e-mailing images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 ACTIONS_H
+#define ACTIONS_H
+
+namespace KIPISendimagesPlugin
+{
+
+enum Action
+{
+ Initialize = 0,
+ Progress,
+ Error,
+ ResizeImages
+};
+
+class EventData
+{
+
+public:
+
+ EventData()
+ {
+ starting = false;
+ success = false;
+ }
+
+ bool starting;
+ bool success;
+
+ int total;
+
+ QString fileName;
+ QString albumName;
+ QString errString;
+
+ Action action;
+};
+
+} // NameSpace KIPISendimagesPlugin
+
+#endif // ACTIONS_H
diff --git a/kipi-plugins/sendimages/kipiplugin_sendimages.desktop b/kipi-plugins/sendimages/kipiplugin_sendimages.desktop
new file mode 100644
index 0000000..8b943a9
--- /dev/null
+++ b/kipi-plugins/sendimages/kipiplugin_sendimages.desktop
@@ -0,0 +1,57 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=SendImages
+Name[br]=Kas ar skeudennoù
+Name[ca]=Enviament d'imatges
+Name[cs]=Odeslání obrázku
+Name[da]=Send billeder
+Name[de]=Bilder senden
+Name[el]=ΑποστολήΕικόνων
+Name[es]=Enviar imágenes
+Name[et]=Piltide saatmine
+Name[fi]=Sähköpostilähetys
+Name[gl]=Envio de Imaxes
+Name[it]=InviaImmagini
+Name[nds]=Biller sennen
+Name[nl]=AfbeeldingenVerzenden
+Name[pl]=Wyślij zdjęcia
+Name[pt]=Envio de Imagens
+Name[sr]=Шаљи слике
+Name[sr@Latn]=Šalji slike
+Name[sv]=Skicka bilder
+Name[tg]=ФиристоданиТасвирҳо
+Name[tr]=ResimGönder
+Name[xx]=xxSendImagesxx
+Name[zh_CN]=发送图像
+Comment=KIPI EMail Images Plugin
+Comment[ca]=Connector del KIPI per enviar imatges per correu-e
+Comment[cs]=KIPI modul odeslání obrázku
+Comment[da]=KIPI-plugin: Send billeder med e-mail
+Comment[de]=Ein KIPI-Modul zum Versenden von Bildern per E-Mail
+Comment[el]=Πρόσθετο του KIPI για αποστολή ηλεκτρονικού μηνύματος εικόνων
+Comment[es]=Complemento de KIPI para enviar imágenes por correo electrónico
+Comment[et]=KIPI piltide e-postiga saatmise plugin
+Comment[fi]=Kipi-liitännäinen sähköpostilähetyksiä varten
+Comment[fr]=Module externe KIPI pour envoyer des images par courrier électronique
+Comment[gl]=Plugin de KIPI para Enviar Imaxes por EMail
+Comment[it]=Plugin di invio immagini di KIPI
+Comment[ja]=Kipi 画像メール送信プラグイン
+Comment[nds]=KIPI-Moduul för't Sennen vun Biller mit Nettpost
+Comment[nl]=KIPI-plugin voor het verzenden van afbeeldingen via e-mail
+Comment[pa]=KIPI ਈ-ਮੇਲ ਚਿੱਤਰ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Wysyłanie zdjęć e-mailem
+Comment[pt]='Plugin' do KIPI de Envio de Imagens por E-Mail
+Comment[pt_BR]=Plugin para Email de Imagens do KIPI
+Comment[sr]=KIPI прикључак за слање слика е-поштом
+Comment[sr@Latn]=KIPI priključak za slanje slika e-poštom
+Comment[sv]=KIPI-insticksprogram: Skicka bilder med e-post
+Comment[tg]=Модули KIPI барои тасвирҳои почтаи электронӣ
+Comment[tr]=KIPI Resim Gönderme Eklentisi
+Comment[xx]=xxKIPI EMail Images Pluginxx
+Comment[zh_CN]=KIPI 电邮图像插件
+Icon=
+ServiceTypes=KIPI/Plugin
+Type=Service
+X-KDE-Library=kipiplugin_sendimages
+author=Gilles Caulier, caulier dot gilles at gmail dot com
+X-KIPI-MergeMenu=true
diff --git a/kipi-plugins/sendimages/listimageserrordialog.cpp b/kipi-plugins/sendimages/listimageserrordialog.cpp
new file mode 100644
index 0000000..307c7fa
--- /dev/null
+++ b/kipi-plugins/sendimages/listimageserrordialog.cpp
@@ -0,0 +1,92 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to e-mailing images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes
+
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qstringlist.h>
+#include <qstring.h>
+#include <qlabel.h>
+#include <qfileinfo.h>
+#include <qframe.h>
+
+// KDElib includes
+
+#include <klocale.h>
+#include <klistview.h>
+#include <kurl.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "listimageserrordialog.h"
+#include "listimageserrordialog.moc"
+
+namespace KIPISendimagesPlugin
+{
+
+listImagesErrorDialog::listImagesErrorDialog(QWidget* parent, QString Caption,
+ const QString &Mess1, const QString &Mess2,
+ KURL::List ListOfiles)
+ : KDialogBase( Caption, Yes|No|Cancel, Yes, Cancel, parent,
+ "listImagesErrorDialog", true, false )
+{
+ QWidget* box = new QWidget( this );
+ setMainWidget(box);
+ QVBoxLayout* ml = new QVBoxLayout(box);
+
+ //---------------------------------------------
+
+ QHBoxLayout* h1 = new QHBoxLayout( ml );
+ QVBoxLayout* v1 = new QVBoxLayout( h1 );
+ h1->addSpacing( 5 );
+ QGridLayout* g1 = new QGridLayout( v1, 1, 3 );
+
+ QLabel *labelMess1 = new QLabel ( Mess1, box);
+ m_listFiles = new KListView( box );
+ m_listFiles->addColumn(i18n("Image File Name"));
+ m_listFiles->addColumn(i18n("From Album"));
+ m_listFiles->setSorting(1);
+ m_listFiles->setItemMargin(3);
+ m_listFiles->setResizeMode(QListView::LastColumn);
+ QLabel *labelMess2 = new QLabel ( Mess2, box);
+
+ g1->addWidget (labelMess1, 1, 1);
+ g1->addWidget (m_listFiles, 2, 1);
+ g1->addWidget (labelMess2, 3, 1);
+
+ for ( KURL::List::Iterator it = ListOfiles.begin() ; it != ListOfiles.end() ; ++it )
+ {
+ new KListViewItem( m_listFiles,
+ (*it).fileName(),
+ (*it).directory().section('/', -1) );
+ }
+
+ resize( 500, 400 );
+}
+
+listImagesErrorDialog::~listImagesErrorDialog()
+{
+}
+
+} // NameSpace KIPISendimagesPlugin
diff --git a/kipi-plugins/sendimages/listimageserrordialog.h b/kipi-plugins/sendimages/listimageserrordialog.h
new file mode 100644
index 0000000..494b4d4
--- /dev/null
+++ b/kipi-plugins/sendimages/listimageserrordialog.h
@@ -0,0 +1,55 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to e-mailing images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 LISTIMAGESERRORDIALOG_included
+#define LISTIMAGESERRORDIALOG_included
+
+// KDElib includes
+
+#include <kdialogbase.h>
+
+class KListView;
+class KURL::List;
+
+namespace KIPISendimagesPlugin
+{
+
+class listImagesErrorDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ listImagesErrorDialog(QWidget* parent, QString Caption,
+ const QString &Mess1, const QString &Mess2,
+ KURL::List ListOfiles);
+
+ ~listImagesErrorDialog();
+
+private:
+
+ KListView *m_listFiles;
+};
+
+} // NameSpace KIPISendimagesPlugin
+
+#endif // LISTIMAGESERRORDIALOG_included
diff --git a/kipi-plugins/sendimages/plugin_sendimages.cpp b/kipi-plugins/sendimages/plugin_sendimages.cpp
new file mode 100644
index 0000000..f6441a0
--- /dev/null
+++ b/kipi-plugins/sendimages/plugin_sendimages.cpp
@@ -0,0 +1,292 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to e-mailing images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes
+
+extern "C"
+{
+#include <unistd.h>
+}
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kimageio.h>
+#include <kdeversion.h>
+
+// LibKipi includes.
+
+#include <libkipi/batchprogressdialog.h>
+
+// Local includes
+
+#include "actions.h"
+#include "sendimages.h"
+#include "plugin_sendimages.h"
+#include "plugin_sendimages.moc"
+
+typedef KGenericFactory<Plugin_SendImages> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_sendimages,
+ Factory("kipiplugin_sendimages"))
+
+// -----------------------------------------------------------
+Plugin_SendImages::Plugin_SendImages(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "SendImages")
+{
+ kdDebug( 51001 ) << "Plugin_SendImages plugin loaded" << endl;
+
+}
+
+void Plugin_SendImages::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_action_sendimages = new KAction (i18n("Email Images..."), // Menu message.
+ "mail_new", // Menu icon.
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "send_images");
+
+ addAction( m_action_sendimages );
+
+ KIPI::Interface* interface = dynamic_cast< KIPI::Interface* >( parent() );
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection selection = interface->currentSelection();
+ m_action_sendimages->setEnabled( selection.isValid() &&
+ !selection.images().isEmpty() );
+
+ connect( interface, SIGNAL(selectionChanged(bool)),
+ m_action_sendimages, SLOT(setEnabled(bool)));
+}
+
+Plugin_SendImages::~Plugin_SendImages()
+{
+}
+
+void Plugin_SendImages::slotActivate()
+{
+ m_progressDlg = 0;
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection images = interface->currentSelection();
+
+ if ( !images.isValid() || images.images().isEmpty() )
+ return;
+
+ KStandardDirs dir;
+ QString Tmp = dir.saveLocation("tmp", "kipi-sendimagesplugin-" + QString::number(getpid()) + "/");
+
+ m_sendImagesOperation = new KIPISendimagesPlugin::SendImages( interface, Tmp, images, this );
+
+ m_sendImagesOperation->showDialog();
+}
+
+void Plugin_SendImages::slotAcceptedConfigDlg()
+{
+ m_sendImagesOperation->prepare();
+ m_sendImagesOperation->start();
+}
+
+void Plugin_SendImages::slotCancel()
+{
+ m_sendImagesOperation->terminate();
+ m_sendImagesOperation->wait();
+ m_sendImagesOperation->removeTmpFiles();
+}
+
+void Plugin_SendImages::customEvent(QCustomEvent *event)
+{
+ if (!event) return;
+
+ if (!m_progressDlg)
+ {
+ m_progressDlg = new KIPI::BatchProgressDialog(kapp->activeWindow(), i18n("Preparing images to send"));
+
+ connect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+
+ m_current = 0;
+ m_progressDlg->show();
+ }
+
+ KIPISendimagesPlugin::EventData *d = (KIPISendimagesPlugin::EventData*) event->data();
+
+ if (!d) return;
+
+ if (d->starting)
+ {
+ QString text;
+
+ switch (d->action)
+ {
+ case(KIPISendimagesPlugin::Initialize):
+ {
+ m_total = d->total;
+ text = i18n("Preparing 1 image to send....", "Preparing %n images to send....", d->total);
+ break;
+ }
+
+ case(KIPISendimagesPlugin::ResizeImages):
+ {
+ text = i18n("Resizing '%1' from Album '%2'...")
+ .arg(d->fileName).arg(d->albumName);
+ break;
+ }
+
+ case(KIPISendimagesPlugin::Progress):
+ {
+ text = i18n("Using '%1' from Album '%2' without resizing...")
+ .arg(d->fileName).arg(d->albumName);
+ break;
+ }
+
+ default:
+ {
+ kdWarning( 51000 ) << "Plugin_SendImages: Unknown 'Starting' event: " << d->action << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::StartingMessage);
+ }
+ else
+ {
+ QString text;
+
+ if (!d->success)
+ {
+ switch (d->action)
+ {
+ case(KIPISendimagesPlugin::ResizeImages):
+ {
+ text = i18n("Failed to resize '%1' from Album '%2'")
+ .arg(d->fileName).arg(d->albumName);
+ break;
+ }
+
+ default:
+ {
+ kdWarning( 51000 ) << "Plugin_SendImages: Unknown 'Failed' event: " << d->action << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::WarningMessage);
+ }
+ else
+ {
+ switch (d->action)
+ {
+ case(KIPISendimagesPlugin::ResizeImages):
+ {
+ text = i18n("Resizing '%1' from Album '%2' completed.")
+ .arg(d->fileName).arg(d->albumName);
+ break;
+ }
+
+ case(KIPISendimagesPlugin::Progress):
+ {
+ text = i18n("All preparatory operations completed.");
+ break;
+ }
+
+ default:
+ {
+ kdWarning( 51000 ) << "Plugin_CDArchiving: Unknown 'Success' event: " << d->action << endl;
+ }
+ }
+
+ m_progressDlg->addedAction(text, KIPI::SuccessMessage);
+ }
+
+ ++m_current;
+ m_progressDlg->setProgress(m_current, m_total);
+
+ if( d->action == KIPISendimagesPlugin::Progress )
+ {
+ // If we have some errors during the resizing images process, show an error dialog.
+
+ if ( m_sendImagesOperation->showErrors() == false )
+ {
+ delete m_progressDlg;
+ return;
+ }
+
+#if KDE_VERSION >= 0x30200
+ m_progressDlg->setButtonCancel( KStdGuiItem::close() );
+#else
+ m_progressDlg->setButtonCancelText( i18n("&Close") );
+#endif
+
+ disconnect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+
+ // Create a text file with images comments if necessary.
+
+ m_sendImagesOperation->makeCommentsFile();
+ m_progressDlg->addedAction(i18n("Creating comments file if necessary..."),
+ KIPI::StartingMessage);
+
+ // Invoke mailer agent call.
+ int type = m_sendImagesOperation->invokeMailAgent() ? KIPI::SuccessMessage : KIPI::ErrorMessage;
+ m_progressDlg->addedAction(i18n("Starting mailer agent..."), type);
+
+ m_progressDlg->setProgress(m_total, m_total);
+ }
+ }
+
+ kapp->processEvents();
+ delete d;
+}
+
+KIPI::Category Plugin_SendImages::category( KAction* action ) const
+{
+ if ( action == m_action_sendimages )
+ return KIPI::IMAGESPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMAGESPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/sendimages/plugin_sendimages.h b/kipi-plugins/sendimages/plugin_sendimages.h
new file mode 100644
index 0000000..dee11c5
--- /dev/null
+++ b/kipi-plugins/sendimages/plugin_sendimages.h
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to e-mailing images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_SENDIMAGES_H
+#define PLUGIN_SENDIMAGES_H
+
+// KIPI includes
+
+#include <libkipi/plugin.h>
+
+class QCustomEvent;
+
+class KAction;
+class KIPISendimagesPlugin::SendImages;
+
+namespace KIPI
+{
+ class BatchProgressDialog;
+}
+
+class Plugin_SendImages : public KIPI::Plugin
+{
+Q_OBJECT
+
+public:
+
+ Plugin_SendImages(QObject *parent, const char* name, const QStringList &args);
+ ~Plugin_SendImages();
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* );
+
+public slots:
+
+ void slotActivate();
+ void slotCancel();
+ void slotAcceptedConfigDlg();
+
+private:
+
+ void customEvent(QCustomEvent *event);
+
+private:
+
+ int m_current;
+ int m_total;
+
+ KAction *m_action_sendimages;
+
+ KIPI::BatchProgressDialog *m_progressDlg;
+
+ KIPISendimagesPlugin::SendImages *m_sendImagesOperation;
+};
+
+#endif // PLUGIN_SENDIMAGES_H
diff --git a/kipi-plugins/sendimages/sendimages.cpp b/kipi-plugins/sendimages/sendimages.cpp
new file mode 100644
index 0000000..abbdf62
--- /dev/null
+++ b/kipi-plugins/sendimages/sendimages.cpp
@@ -0,0 +1,944 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-02-25
+ * Description : a kipi plugin to e-mailing images
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006 by Tom Albers <tomalbers at kde dot nl>
+ * Copyright (C) 2006 by Michael Hoechstetter <michael dot hoechstetter at gmx dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qimage.h>
+#include <qprogressdialog.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qtimer.h>
+#include <qurl.h>
+#include <qdeepcopy.h>
+
+// KDE includes
+
+#include <klocale.h>
+#include <kinstance.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kimageeffect.h>
+#include <kprogress.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kio/netaccess.h>
+#include <kio/global.h>
+#include <kprocess.h>
+#include <kimageio.h>
+#include <knuminput.h>
+#include <kurlrequester.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+// Local includes.
+
+#include "sendimagesdialog.h"
+#include "listimageserrordialog.h"
+#include "actions.h"
+#include "pluginsversion.h"
+#include "sendimages.h"
+#include "sendimages.moc"
+
+namespace KIPISendimagesPlugin
+{
+
+///Constructor: saves system handoff parameters in member variables
+SendImages::SendImages(KIPI::Interface* interface, const QString &tmpFolder,
+ const KIPI::ImageCollection& imagesCollection, QObject *parent)
+ : QObject(parent), QThread()
+{
+ m_invokedBefore = false;
+ m_interface = interface;
+ m_tmp = tmpFolder;
+ m_collection = imagesCollection;
+ m_parent = parent;
+ m_mozillaTimer = new QTimer(this);
+ KImageIO::registerFormats();
+
+ connect(m_mozillaTimer, SIGNAL(timeout()),
+ this, SLOT(slotMozillaTimeout()));
+}
+
+///Destructor
+SendImages::~SendImages()
+{
+ delete m_sendImagesDialog;
+ wait();
+}
+
+///Invokes the User Dialog Window
+void SendImages::showDialog()
+{
+ m_sendImagesDialog = new KIPISendimagesPlugin::SendImagesDialog(kapp->activeWindow(),
+ m_interface, m_collection);
+ m_sendImagesDialog->show();
+
+ connect(m_sendImagesDialog, SIGNAL(signalAccepted()),
+ m_parent, SLOT(slotAcceptedConfigDlg()));
+}
+
+/** Execute the no threadable operations before the real thread.
+ Gets input from the user dialog and store it into member variables */
+void SendImages::prepare(void)
+{
+ m_filesSendList.clear();
+ m_imagesResizedWithError.clear();
+ m_imagesPackage.clear();
+ m_images = m_sendImagesDialog->m_images2send;
+ m_changeProp = m_sendImagesDialog->m_changeImagesProp->isChecked();
+ m_imageFormat = m_sendImagesDialog->m_imagesFormat->currentText();
+ m_sizeFactor = getSize( m_sendImagesDialog->m_imagesResize->currentItem() );
+ m_imageCompression = m_sendImagesDialog->m_imageCompression->value();
+
+ // Base64-encoding needs a lot of space.
+ m_attachmentlimit = m_sendImagesDialog->m_attachmentlimit->value()*770000-2000;
+}
+
+/** List of threaded operations.
+ Prepares the image list. This includes resizing, copying, maintaining an image's exif,
+ and dropping evil characters out of filenames ;-) */
+void SendImages::run()
+{
+ KIPISendimagesPlugin::EventData *d;
+
+ d = new KIPISendimagesPlugin::EventData;
+ d->action = KIPISendimagesPlugin::Initialize;
+ d->starting = true;
+ d->success = false;
+ d->total = m_images.count();
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ for( KURL::List::Iterator it = m_images.begin() ; it != m_images.end() ; ++it )
+ {
+ QString imageName = (*it).path();
+ QString ItemName = imageName.section( '/', -1 );
+
+ d = new KIPISendimagesPlugin::EventData;
+ d->action = KIPISendimagesPlugin::ResizeImages;
+ d->fileName = (*it).fileName();
+ d->albumName = (*it).directory().section('/', -1);
+ d->starting = true;
+ d->success = false;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ // Prepare resized target images to send.
+ QString imageFileName="";
+
+ KIPI::ImageInfo info = m_interface->info( *it );
+
+ ///Generate filename of destination image
+ QString commentItem = info.description();
+
+ if ((m_sendImagesDialog->m_comment2ImageName->isChecked() == true ) &&
+ !commentItem.isEmpty() )
+ {
+ qDebug("commentItem: %s",commentItem.ascii());
+ }
+ else
+ {
+ commentItem = ItemName.left(ItemName.findRev('.'));
+ qDebug("commentItem is empty");
+ }
+
+ //QString TempFileName = (*it).directory().section('/', -1);
+ QString TempFileName=(*it).path().section('/', -2,-2)+"/"+commentItem+
+ +"."+(*it).path().section('.', -1,-1);
+ qDebug("TempFileName: %s",TempFileName.ascii());
+
+
+ // Thunderbird does not like (). Replace them, BUG:131343
+ TempFileName.replace(QChar('('), "_").replace(QChar(')'), "_");
+ // and these characters are better eliminated, too ;-)
+ TempFileName.replace(QChar(','), "_").replace(QChar(' '), "_");
+ TempFileName.replace(QChar(';'), "_").replace(QChar('%'), "_");
+ TempFileName.replace(QChar('/'), "-").replace(QChar('?'), "");
+ TempFileName.replace(QChar('"'), "");
+ //If TempFileName already exists, add a number oder increase number
+ if (entry_already_exists(m_filesSendList,m_tmp + TempFileName))
+ {
+ qDebug ("I entered");
+ QString secondpart=(m_tmp+TempFileName).section(".",-1,-1);
+ QString firstpart=
+ (m_tmp+TempFileName).left((m_tmp+TempFileName).length()-secondpart.length()-1);
+ qDebug("Firstpart: %s \n Secondpart: %s",firstpart.ascii(), secondpart.ascii());
+ //Add _integer value in the end and prove again
+ int int_index=2;
+ QString index=QString::number(int_index,10);
+ while (entry_already_exists(m_filesSendList,firstpart + "_"+index+"."+secondpart))
+ {
+ int_index++;
+ index=QString::number(int_index,10);
+ qDebug("Index: %s",index.ascii());
+ }
+ QString temp=firstpart + "_"+index+"."+secondpart;
+ TempFileName=temp.right(temp.length()-m_tmp.length());
+ // .section("-",-2,-1);
+ // m_tmp=(firstpart + "_"+index+"."+secondpart).section("-",-2);
+ }
+
+ if ( m_changeProp == true )
+ {
+ // Prepare resizing images.
+
+ //QString imageNameFormat = TempFileName.replace(QChar('.'), "_") +
+ // extension(m_imageFormat);
+
+ qDebug( "Resizing %s-> '%s %s ' (%s ; %d )",imageName.ascii(),
+ m_tmp.ascii(),TempFileName.ascii(),m_imageFormat.ascii(),m_sizeFactor);
+
+ // Return value for resizeImageProcess-function, in order to avoid reopening
+ // the image for exiv-writing.
+ QSize newsize;
+
+ if ( resizeImageProcess( imageName, m_tmp, m_imageFormat, TempFileName,
+ m_sizeFactor, m_imageCompression, newsize) == false )
+ {
+ // Resized images failed...
+
+ d = new KIPISendimagesPlugin::EventData;
+ d->action = KIPISendimagesPlugin::ResizeImages;
+ d->fileName = (*it).fileName();
+ d->albumName = (*it).directory().section('/', -1);
+ d->starting = false;
+ d->success = false;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ m_imagesResizedWithError.append(*it);
+ }
+ else // Resized images OK...
+ {
+ // Only try to write Exif if both src and destination are JPEG files.
+
+ if (QString(QImageIO::imageFormat(imageName)).upper() == "JPEG" &&
+ m_imageFormat.upper() == "JPEG")
+ {
+ QString targetFile = m_tmp + TempFileName;
+ KExiv2Iface::KExiv2 exiv2Iface;
+
+ if (exiv2Iface.load(imageName))
+ {
+ exiv2Iface.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+ exiv2Iface.setImageDimensions(newsize);
+ exiv2Iface.save(targetFile);
+ }
+ }
+ else
+ {
+ qWarning( "createThumb::No Exif Data Found") ;
+ }
+
+ d = new KIPISendimagesPlugin::EventData;
+ d->action = KIPISendimagesPlugin::ResizeImages;
+ d->fileName = (*it).fileName();
+ d->albumName = (*it).directory().section('/', -1);
+ d->starting = false;
+ d->success = true;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ m_filesSendList.append(m_tmp + TempFileName);
+ m_imagesPackage.append(*it);
+ m_imagesPackage.append(m_tmp + TempFileName);
+ }
+ }
+ else // No resize images operations...
+ {
+ if ( copyImageProcess( imageName, m_tmp, TempFileName) == true )
+ {
+ d = new KIPISendimagesPlugin::EventData;
+ d->action = KIPISendimagesPlugin::Progress;
+ d->fileName = (*it).fileName();
+ d->albumName = (*it).directory().section('/', -1);
+ d->starting = true;
+ d->success = false;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+
+ m_filesSendList.append(m_tmp + TempFileName);
+ m_imagesPackage.append(*it);
+ m_imagesPackage.append(m_tmp + TempFileName);
+ }
+ }
+ }
+
+ d = new KIPISendimagesPlugin::EventData;
+ d->action = KIPISendimagesPlugin::Progress;
+ d->starting = false;
+ d->success = true;
+ QApplication::postEvent(m_parent, new QCustomEvent(QEvent::User, d));
+}
+
+bool SendImages::entry_already_exists(KURL::List filenamelist,QString entry)
+{
+ KURL::List::Iterator it = filenamelist.begin();
+ while( it != filenamelist.end() )
+ {
+ if ((*it)==entry) return true;
+ it++;
+ }
+ return false;
+}
+
+/// Creates a text file with the images comments.
+void SendImages::makeCommentsFile(void)
+{
+ if ( m_sendImagesDialog->m_addComments->isChecked() == true )
+ {
+ QString ImageCommentsText;
+
+ KURL::List::Iterator it = m_imagesPackage.begin();
+ bool anyCommentsPresent = false;
+
+ while( it != m_imagesPackage.end() )
+ {
+ KIPI::ImageInfo info = m_interface->info( *it );
+
+ QString commentItem = info.description();
+ ++it;
+ QString targetFile = (*it).filename();
+
+ if ( commentItem.isEmpty() )
+ commentItem = i18n("no caption");
+ else
+ anyCommentsPresent = true;
+
+ ImageCommentsText += i18n("Caption for image \"%1\": %2\n")
+ .arg(targetFile).arg(commentItem);
+
+ //Tags from the database
+ if (m_interface->hasFeature(KIPI::HostSupportsTags))
+ {
+ QMap <QString, QVariant> attribs=info.attributes();
+ if (attribs["tags"].asStringList().count() > 0)
+ {
+ ImageCommentsText += i18n("Tags: %2\n").arg(attribs["tags"].asStringList().join(","));
+ anyCommentsPresent = true;
+ }
+ }
+
+ ImageCommentsText += "\n";
+ ++it;
+ }
+
+ if ( anyCommentsPresent )
+ {
+ QFile commentsFile( m_tmp + i18n("comments.txt") );
+ QTextStream stream( &commentsFile );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+ commentsFile.open( IO_WriteOnly );
+ stream << ImageCommentsText << "\n";
+ commentsFile.close();
+ m_filesSendList.append( m_tmp + i18n("comments.txt") );
+ }
+ }
+}
+
+///Shows up an error dialog and the problematic images
+bool SendImages::showErrors()
+{
+ if ( m_imagesResizedWithError.isEmpty() == false )
+ {
+ listImagesErrorDialog *ErrorImagesDialog = new listImagesErrorDialog(kapp->activeWindow(),
+ i18n("Error during resize images process."),
+ i18n("Cannot resize the following image files:"),
+ i18n("Do you want them to be added as attachments "
+ "(without resizing)?"),
+ m_imagesResizedWithError);
+
+ int ValRet = ErrorImagesDialog->exec();
+
+ switch (ValRet)
+ {
+ case KDialogBase::Yes : // Added source image files instead resized images...
+
+ for ( KURL::List::Iterator it = m_imagesResizedWithError.begin();
+ it != m_imagesResizedWithError.end(); ++it )
+ {
+ m_filesSendList.append(*it);
+ m_imagesPackage.append(*it);
+ m_imagesPackage.append(*it);
+ }
+ break;
+
+ case KDialogBase::No : // Do nothing...
+ break;
+
+ case KDialogBase::Cancel : // Stop process...
+ removeTmpFiles();
+ return false;
+ break;
+ }
+ }
+
+ return true;
+}
+
+/** Returns a list of Filenames, whose sum filesize is smaller than the quota
+ The returned images are deleted from the m_filesSendList */
+KURL::List SendImages::divideEmails(void)
+{
+ unsigned long mylistsize=0;
+
+ KURL::List sendnow;
+ KURL::List filesSendList;
+
+ for ( KURL::List::Iterator it = m_filesSendList.begin() ; it != m_filesSendList.end() ; ++it )
+ {
+ qDebug("m_attachmentlimit: %lu ", m_attachmentlimit);
+ QString imageName = (*it).path();
+ qDebug("Imagename: %s", imageName.ascii());
+ QFile file(imageName);
+ qDebug("filesize: %lu", file.size());
+
+ if ((mylistsize + file.size()) <= m_attachmentlimit)
+ {
+ mylistsize+=file.size();
+ sendnow.append(*it);
+ qDebug("mylistsize: %lu; attachmentlimit: %lu",mylistsize, m_attachmentlimit);
+ }
+ else
+ {
+ qDebug("file %s is out of %lu",imageName.ascii(),m_attachmentlimit);
+ filesSendList.append(*it);
+ }
+ }
+ m_filesSendList = filesSendList;
+
+ return sendnow;
+}
+
+/** Invokes mail agent. Depending on which mail agent to be used, we have different
+ proceedings. Easy for every agent except of mozilla derivates */
+bool SendImages::invokeMailAgent(void)
+{
+ bool agentInvoked = false;
+
+ KURL::List filelist;
+ kurllistdeepcopy(m_filesSendList_copy,m_filesSendList);
+
+ qDebug("invokeMailagent1: Number of elements in m_filesSendList=%d, and in m_filesSendList_copy=%d)",(int)m_filesSendList.size(),(int)m_filesSendList_copy.size());
+
+ while (!((filelist=divideEmails()).empty()))
+ {
+ qDebug("invokeMailagent2: Number of elements in m_filesSendList=%d, and in m_filesSendList_copy=%d)",(int) m_filesSendList.size(),(int)m_filesSendList_copy.size());
+ qDebug("number of elements in filelist %d",(int)filelist.size());
+ qDebug("number of elements in m_filelist %d", (int)m_filesSendList.size());
+ if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Default" )
+ {
+ KApplication::kApplication()->invokeMailer(
+ QString::null, // Destination address.
+ QString::null, // Carbon Copy address.
+ QString::null, // Blind Carbon Copy address
+ QString::null, // Message Subject.
+ QString::null, // Message Body.
+ QString::null, // Message Body File.
+ filelist.toStringList()); // Images attachments (+ comments).
+ agentInvoked = true;
+ }
+
+ // KMail mail agent call.
+
+ if ( m_sendImagesDialog->m_mailAgentName->currentText() == "KMail" )
+ {
+ m_mailAgentProc = new KProcess;
+ *m_mailAgentProc << "kmail";
+
+ for ( KURL::List::Iterator it = filelist.begin() ; it != filelist.end() ; ++it )
+ {
+ *m_mailAgentProc << "--attach";
+ *m_mailAgentProc << QFile::encodeName((*it).path());
+ }
+
+ if ( m_mailAgentProc->start() == false )
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot start '%1' program;\nplease "
+ "check your installation.")
+ .arg(m_sendImagesDialog->m_mailAgentName->currentText()));
+ else
+ agentInvoked = true;
+ }
+
+ // Claws Mail and Sylpheed mail agent call.
+
+ if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Claws Mail" ||
+ m_sendImagesDialog->m_mailAgentName->currentText() == "Sylpheed" ||
+ m_sendImagesDialog->m_mailAgentName->currentText() == "Sylpheed-Claws" )
+ {
+ m_mailAgentProc = new KProcess;
+
+ if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Claws Mail")
+ *m_mailAgentProc << "claws-mail";
+ else if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Sylpheed")
+ *m_mailAgentProc << "sylpheed";
+ else
+ *m_mailAgentProc << "sylpheed-claws";
+
+ *m_mailAgentProc << "--compose" << "--attach";
+
+ for ( KURL::List::Iterator it = filelist.begin() ; it != filelist.end() ; ++it )
+ *m_mailAgentProc << QFile::encodeName((*it).path());
+
+ if ( m_mailAgentProc->start() == false )
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot start '%1' program;\nplease "
+ "check your installation.")
+ .arg(m_sendImagesDialog->m_mailAgentName->currentText()));
+ else
+ agentInvoked = true;
+ }
+
+ // Balsa mail agent call.
+
+ if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Balsa" )
+ {
+ m_mailAgentProc = new KProcess;
+ *m_mailAgentProc << "balsa" << "-m" << "mailto:";
+
+ for ( KURL::List::Iterator it = filelist.begin() ; it != filelist.end() ; ++it )
+ {
+ *m_mailAgentProc << "-a";
+ *m_mailAgentProc << QFile::encodeName((*it).path());
+ }
+
+ if ( m_mailAgentProc->start() == false )
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot start '%1' program;\nplease "
+ "check your installation.")
+ .arg(m_sendImagesDialog->m_mailAgentName->currentText()));
+ else
+ agentInvoked = true;
+ }
+
+ // Evolution mail agent call.
+
+ if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Evolution" )
+ {
+ m_mailAgentProc = new KProcess;
+ *m_mailAgentProc << "evolution";
+
+ QString Temp = "mailto:?subject=";
+
+ for ( KURL::List::Iterator it = filelist.begin() ; it != filelist.end() ; ++it )
+ {
+ Temp.append("&attach=");
+ Temp.append( QFile::encodeName((*it).path()) );
+ }
+
+ *m_mailAgentProc << Temp;
+
+ if ( m_mailAgentProc->start() == false )
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot start '%1' program;\nplease "
+ "check your installation.")
+ .arg(m_sendImagesDialog->m_mailAgentName->currentText()));
+ else
+ agentInvoked = true;
+ }
+
+ // Mozilla | Netscape | Thunderbird mail agent call.
+
+ if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Mozilla" ||
+ m_sendImagesDialog->m_mailAgentName->currentText() == "Netscape" ||
+ m_sendImagesDialog->m_mailAgentName->currentText() == "Thunderbird" ||
+ m_sendImagesDialog->m_mailAgentName->currentText() == "GmailAgent")
+ {
+ m_mailAgentProc = new KProcess;
+
+ m_thunderbirdUrl = m_sendImagesDialog->m_ThunderbirdBinPath->url();
+
+ if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Mozilla" )
+ {
+ *m_mailAgentProc << "mozilla" << "-remote";
+ }
+ else if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Thunderbird" )
+ {
+ *m_mailAgentProc << m_thunderbirdUrl << "-remote";
+ qDebug("URL: %s", m_thunderbirdUrl.ascii());
+ }
+ else if ( m_sendImagesDialog->m_mailAgentName->currentText() == "GmailAgent" )
+ {
+ *m_mailAgentProc << "gmailagent" << "-remote";
+ }
+ else
+ {
+ *m_mailAgentProc << "netscape" << "-remote";
+ }
+
+ QString Temp = " xfeDoCommand(composeMessage,attachment='";
+
+ for ( KURL::List::Iterator it = filelist.begin() ; it != filelist.end() ; ++it )
+ {
+ Temp.append( "file://" );
+ QString toencode=(*it).encodedPathAndQuery();
+ Temp.append(toencode);
+ Temp.append( "," );
+ }
+
+ Temp.remove(Temp.length()-1,1);
+ Temp.append("')");
+
+ *m_mailAgentProc << Temp;
+
+ if (!m_invokedBefore)
+ {
+ connect(m_mailAgentProc, SIGNAL(processExited(KProcess *)),
+ this, SLOT(slotMozillaExited(KProcess*)));
+
+ connect(m_mailAgentProc, SIGNAL(receivedStderr(KProcess *, char*, int)),
+ this, SLOT(slotMozillaReadStderr(KProcess*, char*, int)));
+ }
+ qDebug ("%s", Temp.ascii());
+
+ if ( m_mailAgentProc->start(KProcess::NotifyOnExit , KProcess::All) == false )
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot start '%1' program;\nplease "
+ "check your installation.")
+ .arg(m_sendImagesDialog->m_mailAgentName->currentText()));
+ else
+ { agentInvoked = true;
+ m_invokedBefore=true;
+ }
+ }
+ }
+
+ return agentInvoked;
+}
+
+///Cleans up the temp directory
+void SendImages::removeTmpFiles(void)
+{
+ if (DeleteDir(m_tmp) == false)
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot remove temporary folder %1.").arg(m_tmp));
+}
+
+///Checks if directory is empty and invokes its deletion
+bool SendImages::DeleteDir(QString dirname)
+{
+ if ( !dirname.isEmpty() )
+ {
+ QDir dir;
+
+ if (dir.exists ( dirname ) == true)
+ {
+ if (deldir(dirname) == false)
+ return false;
+
+ if (dir.rmdir( dirname ) == false )
+ return false;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+///Deletes a directory and all its contents - Please call it using "DeleteDir"
+bool SendImages::deldir(QString dirname)
+{
+ QDir *dir = new QDir(dirname);
+ dir->setFilter ( QDir::Dirs | QDir::Files | QDir::NoSymLinks );
+
+ const QFileInfoList* fileinfolist = dir->entryInfoList();
+ QFileInfoListIterator it(*fileinfolist);
+ QFileInfo* fi;
+
+ while( (fi = it.current() ) )
+ {
+ if(fi->fileName() == "." || fi->fileName() == ".." )
+ {
+ ++it;
+ continue;
+ }
+
+ if( fi->isDir() )
+ {
+ if (deldir( fi->absFilePath() ) == false)
+ return false;
+ if (dir->rmdir( fi->absFilePath() ) == false)
+ return false;
+ }
+ else
+ if( fi->isFile() )
+ if (dir->remove(fi->absFilePath() ) == false)
+ return false;
+
+ kapp->processEvents();
+ ++it;
+ }
+
+ return true;
+}
+
+///Returns the file-extension of the corresponding fileformat
+QString SendImages::extension(const QString& imageFileFormat)
+{
+ if (imageFileFormat == "PNG")
+ return ".png";
+
+ if (imageFileFormat == "JPEG")
+ return ".jpg";
+
+ Q_ASSERT(false);
+ return "";
+}
+
+/** in sendimagesplugin dialog the user can select a compression of images
+ this function returns the pixel-size of the selected entry */
+int SendImages::getSize ( int choice )
+{
+ switch (choice)
+ {
+ case 0:
+ return (320);
+ break;
+ case 1:
+ return (640);
+ break;
+ case 2:
+ return (800);
+ break;
+ case 3:
+ return (1024);
+ break;
+ case 4:
+ return (1280);
+ break;
+ case 5:
+ return (1600);
+ break;
+ default:
+ return (800); // Default value...
+ break;
+ }
+}
+
+/** This function should copy the images to tempfolder in order to avoid suspicious filenames
+ It is used, when no resizing should take place
+ This function can be replaced with Qt4 QFile.copy */
+bool SendImages::copyImageProcess(const QString &oldFilePath, const QString &DestPath,
+ const QString &ImageName)
+{
+ //same file, no need to copy
+ qDebug("DestPath: %s",(DestPath).ascii());
+ qDebug("ImageName: %s",(ImageName).ascii());
+ if(oldFilePath.compare(DestPath+ImageName) == 0)
+ return true;
+
+ //load both files
+ QFile oldFile(oldFilePath);
+ QFile newFile(DestPath+ImageName);
+ bool openOld = oldFile.open( IO_ReadOnly );
+ bool openNew = newFile.open( IO_WriteOnly );
+
+ //if either file fails to open bail
+ if(!openOld || !openNew) { return false; }
+
+ //copy contents
+ uint BUFFER_SIZE = 16000;
+ char* buffer = new char[BUFFER_SIZE];
+ while(!oldFile.atEnd())
+ {
+ Q_LONG len = oldFile.readBlock( buffer, BUFFER_SIZE );
+ newFile.writeBlock( buffer, len );
+ }
+
+ //deallocate buffer
+ delete[] buffer;
+ buffer = NULL;
+ return true;
+}
+
+///Resizes the Images before Sending...
+bool SendImages::resizeImageProcess(const QString &SourcePath, const QString &DestPath,
+ const QString &ImageFormat, const QString &ImageName,
+ int SizeFactor, int ImageCompression, QSize &newsize)
+{
+ QImage img;
+
+ // Check if RAW file.
+#if KDCRAW_VERSION < 0x000106
+ QString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles());
+#else
+ QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
+#endif
+ QFileInfo fileInfo(SourcePath);
+ if (rawFilesExt.upper().contains( fileInfo.extension(false).upper() ))
+ KDcrawIface::KDcraw::loadDcrawPreview(img, SourcePath);
+ else
+ img.load(SourcePath);
+
+ if ( !img.isNull() )
+ {
+ int w = img.width();
+ int h = img.height();
+
+ if( w > SizeFactor || h > SizeFactor )
+ {
+ if( w > h )
+ {
+ h = (int)( (double)( h * SizeFactor ) / w );
+
+ if ( h == 0 ) h = 1;
+
+ w = SizeFactor;
+ Q_ASSERT( h <= SizeFactor );
+ }
+ else
+ {
+ w = (int)( (double)( w * SizeFactor ) / h );
+
+ if ( w == 0 ) w = 1;
+
+ h = SizeFactor;
+ Q_ASSERT( w <= SizeFactor );
+ }
+
+ const QImage scaleImg(img.smoothScale( w, h ));
+
+ if ( scaleImg.width() != w || scaleImg.height() != h )
+ {
+ qDebug ("Resizing failed. Aborting.");
+ return false;
+ }
+
+ img = scaleImg;
+ newsize=img.size();
+ }
+
+ if ( !img.save(DestPath + ImageName, ImageFormat.latin1(), ImageCompression) )
+ {
+ qDebug("Saving failed with specific compression value. Aborting.");
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/** If mozilla, or thunderbird or any derivate isn't already running, start it now,
+ wait 5 seconds and start SlotMozillaTimeout() */
+void SendImages::slotMozillaExited(KProcess*)
+{
+ qDebug("slotMozillaExited");
+ ///Here would be the right point to clear the sendlist in order to avoid infinite resendings!!
+ m_filesSendList.clear();
+ ///Also disconnect SLOT
+ m_mailAgentProc->disconnect(SIGNAL(processExited(KProcess *)), this, SLOT(slotMozillaExited(KProcess*)));
+
+ qDebug("Number of elements in m_filesSendList=%d, and in m_filesSendList_copy=%d)",(int)m_filesSendList.size(),(int)m_filesSendList_copy.size());
+ if ( m_mozillaStdErr.find("No running window found") != -1 ) // No remote Mozilla | Netscape |
+ { // Thunderbird env. loaded !
+ m_mailAgentProc2 = new KProcess; // Init a new env.
+
+ if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Mozilla" )
+ *m_mailAgentProc2 << "mozilla" << "-mail";
+ else if ( m_sendImagesDialog->m_mailAgentName->currentText() == "Thunderbird" )
+ *m_mailAgentProc2 << m_thunderbirdUrl << "-mail"; ///for new versions of thunderbird, we don't need it anymore
+ //*m_mailAgentProc2 << m_thunderbirdUrl;
+ else
+ *m_mailAgentProc2 << "netscape" << "-mail";
+
+ // Start an instance of mozilla mail agent before a remote call.
+
+ if ( m_mailAgentProc2->start() == false )
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot start '%1' program;\nplease "
+ "check your installation.")
+ .arg(m_sendImagesDialog->m_mailAgentName->currentText()));
+ }
+ else
+ {
+ // Mozilla | Netscape | Thunderbird mail agent started correctly
+ // -> start a remote mail agent with multiple attachments after the env. is loaded !
+
+ m_mozillaTimer->start(5000, true);
+ return;
+ }
+ }
+}
+
+///If Mozilla wasn't started before, now it is and so we can begin with the transmission
+void SendImages::slotMozillaTimeout(void)
+{
+ m_mozillaTimer->disconnect(SIGNAL(timeout()), this, SLOT(slotMozillaTimeout()));
+
+ qDebug("slotMozillaTimeout: Number of elements in m_filesSendList=%d, and in m_filesSendList_copy=%d)",(int)m_filesSendList.size(),(int)m_filesSendList_copy.size());
+ kurllistdeepcopy(m_filesSendList,m_filesSendList_copy);
+ invokeMailAgent();
+
+}
+
+///Handles mozillas errors
+void SendImages::slotMozillaReadStderr(KProcess*, char *buffer, int buflen)
+{
+ m_mozillaStdErr = QString::fromLocal8Bit(buffer, buflen);
+}
+
+///Makes a deep copy of a KURL-list: Real and slow copying instead of only pointer arithmetics
+bool SendImages::kurllistdeepcopy(KURL::List &Destination, KURL::List Source)
+{
+ Destination.clear();
+ qDebug("kurllistdeepcopy started");
+ for ( KURL::List::Iterator it = Source.begin() ; it != Source.end() ; ++it )
+ {
+ //QString Tempstring;
+ QString Getstring=(*it).path();
+ QString Tempstring=Getstring.copy();
+ Destination.append(Tempstring);
+ qDebug("%s",Tempstring.ascii());
+ }
+
+ /*
+ qDebug("deepcopytest");
+ Source.clear();
+ for ( KURL::List::Iterator it = Destination.begin() ; it != Destination.end() ; ++it )
+ {
+ qDebug("%s",(*it).path().ascii());
+ }
+ */
+
+ qDebug("kurllistdeepcopy ended\n");
+ return true;
+}
+
+} // NameSpace KIPISendimagesPlugin
diff --git a/kipi-plugins/sendimages/sendimages.h b/kipi-plugins/sendimages/sendimages.h
new file mode 100644
index 0000000..762300a
--- /dev/null
+++ b/kipi-plugins/sendimages/sendimages.h
@@ -0,0 +1,190 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-02-25
+ * Description : a kipi plugin to e-mailing images
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SENDIMAGES_H
+#define SENDIMAGES_H
+
+// Qt includes.
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qthread.h>
+#include <qstringlist.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// LibKipi includes.
+
+#include <libkipi/imagecollection.h>
+#include <libkipi/interface.h>
+
+class QFile;
+class QTimer;
+class QCustomEvent;
+
+class KProcess;
+
+namespace KIPISendimagesPlugin
+{
+
+class SendImagesDialog;
+
+class SendImages : public QObject, public QThread
+{
+Q_OBJECT
+
+public:
+
+ ///Constructor: saves system handoff parameters in member variables
+ SendImages(KIPI::Interface* interface, const QString &tmpFolder,
+ const KIPI::ImageCollection& imagesCollection, QObject *parent=0);
+ ///Destructor
+ ~SendImages();
+
+ ///Prepares the image list. This includes resizing, copying, maintaining an image's exif,
+ ///and dropping evil characters out of filenames ;-)
+ virtual void run();
+
+ ///Invokes the User Dialog Window
+ void showDialog(void);
+
+ ///Gets input from the user dialog and store it into member variables
+ void prepare(void);
+
+ ///Shows up an error dialog and the problematic images
+ bool showErrors(void);
+
+ /// Creates a text file with the images comments.
+ void makeCommentsFile(void);
+
+ /** Invokes mail agent. Depending on which mail agent to be used, we have different
+ proceedings. Easy for every agent except of mozilla derivates */
+ bool invokeMailAgent(void);
+
+ ///Cleans up the temp directory
+ void removeTmpFiles(void);
+
+ /** Returns a list of Filenames, whose sum filesize is smaller than the quota
+ The returned images are deleted from the m_filesSendList*/
+ KURL::List divideEmails(void);
+
+private slots:
+
+ ///If Mozilla wasn't started before, now it is and so we can begin with the transmission
+ void slotMozillaTimeout(void);
+
+ ///If mozilla, or thunderbird or any derivate isn't already running,
+ ///start it now, wait 5 seconds and start SlotMozillaTimeout()
+ void slotMozillaExited(KProcess* proc);
+
+ ///Handles mozillas errors
+ void slotMozillaReadStderr(KProcess* proc, char *buffer, int buflen);
+
+private:
+
+ ///Returns the file-extension of the corresponding fileformat
+ QString extension(const QString& imageFileFormat);
+
+ ///in sendimagesplugin dialog the user can select a compression of images
+ ///this function returns the pixel-size of the selected entry
+ int getSize( int choice );
+
+ ///Checks if directory is empty and invokes its deletion
+ bool DeleteDir(QString dirname);
+
+ ///Deletes a directory and all its contents - Please call it using "DeleteDir"
+ bool deldir(QString dirname);
+
+ ///Resizes the Images before Sending...
+ bool resizeImageProcess(const QString &SourcePath, const QString &DestPath,
+ const QString &ImageFormat, const QString &ImageName,
+ int SizeFactor, int ImageCompression, QSize &newsize);
+
+ ///This function should copy the images to tempfolder in order to avoid suspicious filenames
+ ///It is used, when no resizing should take place
+ bool copyImageProcess(const QString &oldFilePath, const QString &DestPath,
+ const QString &ImageName);
+
+ ///Tests if an entry already exists in the filename list
+ bool entry_already_exists(KURL::List filenamelist,QString entry);
+
+ ///Makes a deep copy of a KURL-list: Real and slow copying instead of only pointer arithmetics
+ bool kurllistdeepcopy(KURL::List &Destination, KURL::List Source);
+
+private:
+
+ bool m_invokedBefore;
+ /** Change image properties options in setup dialog.*/
+
+ bool m_changeProp;
+
+ /** Image size factor in the setup dialog.*/
+ int m_sizeFactor;
+
+ /** Image compression factor in the setup dialog.*/
+ int m_imageCompression;
+
+ /** Biggest permitted email.*/
+ unsigned long m_attachmentlimit;
+
+ QObject *m_parent;
+
+ QTimer *m_mozillaTimer;
+
+ QString m_mozillaStdErr;
+ QString m_tmp;
+
+ /** Image format option in the setup dialog.*/
+ QString m_imageFormat;
+ QString m_thunderbirdUrl;
+
+ KProcess *m_mailAgentProc;
+ KProcess *m_mailAgentProc2;
+ KProcess *m_mailAgentProc3;
+
+ /** List of images in the setup dialog.*/
+ KURL::List m_images;
+
+ /** URL of resized images.*/
+ KURL::List m_filesSendList;
+ KURL::List m_filesSendList_copy;
+
+ /** URL of original images that cannot be resized.*/
+ KURL::List m_imagesResizedWithError;
+
+ /** URL of original images than have been resized
+ and KURL of resized images (used for to create
+ the comments file).*/
+ KURL::List m_imagesPackage;
+
+ KIPI::ImageCollection m_collection;
+
+ KIPI::Interface *m_interface;
+
+ SendImagesDialog *m_sendImagesDialog;
+};
+
+} // NameSpace KIPISendimagesPlugin
+
+#endif // SENDIMAGES_H
diff --git a/kipi-plugins/sendimages/sendimagesdialog.cpp b/kipi-plugins/sendimages/sendimagesdialog.cpp
new file mode 100644
index 0000000..de502bb
--- /dev/null
+++ b/kipi-plugins/sendimages/sendimagesdialog.cpp
@@ -0,0 +1,689 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to e-mailing images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006 by Tom Albers <tomalbers at kde dot nl>
+ * Copyright (C) 2006 by Michael Hoechstetter <michael dot hoechstetter at gmx dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qdir.h>
+#include <qwidget.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qwhatsthis.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qprogressdialog.h>
+#include <qimage.h>
+#include <qevent.h>
+#include <qdragobject.h>
+#include <qstrlist.h>
+#include <qfileinfo.h>
+#include <qpushbutton.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <klineedit.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kinstance.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <kbuttonbox.h>
+#include <ksqueezedtextlabel.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <kurlrequester.h>
+
+// LibKipi includes.
+
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "listimageserrordialog.h"
+#include "sendimagesdialog.h"
+#include "sendimagesdialog.moc"
+
+namespace KIPISendimagesPlugin
+{
+
+class ImageItem : public QListBoxText
+{
+
+public:
+ ImageItem(QListBox * parent, QString const & comments, KURL const & url)
+ : QListBoxText(parent), _comments(comments), _url(url)
+ {}
+
+ QString comments() { return _comments; }
+ QString name() { return _url.fileName(); }
+ KURL url() { return _url; }
+ QString album() { return _url.directory().section('/', -1); }
+ void setName(const QString &newName) { setText(newName); }
+
+private:
+
+ QString _comments;
+ KURL _url;
+};
+
+ListImageItems::ListImageItems(QWidget *parent, const char *name)
+ : KListBox(parent, name)
+{
+ setSelectionMode (QListBox::Extended);
+ setAcceptDrops(true);
+}
+
+void ListImageItems::dragEnterEvent(QDragEnterEvent *e)
+{
+ e->accept(QUriDrag::canDecode(e));
+}
+
+void ListImageItems::dropEvent(QDropEvent *e)
+{
+ QStrList strList;
+ QStringList FilesPath;
+
+ if ( !QUriDrag::decode(e, strList) ) return;
+
+ QStrList stringList;
+ QStrListIterator it(strList);
+ char *str;
+
+ while ( (str = it.current()) != 0 )
+ {
+ QString filePath = QUriDrag::uriToLocalFile(str);
+ QFileInfo fileInfo(filePath);
+
+ if (fileInfo.isFile() && fileInfo.exists())
+ FilesPath.append(fileInfo.filePath());
+
+ ++it;
+ }
+
+ if (FilesPath.isEmpty() == false)
+ emit addedDropItems(FilesPath);
+}
+
+SendImagesDialog::SendImagesDialog(QWidget *parent, KIPI::Interface* interface,
+ const KIPI::ImageCollection& images )
+ : KDialogBase( IconList, i18n("Email Images Options"), Help|Ok|Cancel,
+ Ok, parent, "SendImagesDialog", false, true )
+{
+ m_interface = interface;
+ m_thumbJob = 0;
+
+ setupImagesList();
+ setupEmailOptions();
+ readSettings();
+ setImagesList( images.images() );
+ page_setupImagesList->setFocus();
+ m_ImagesFilesListBox->setSelected(0, true);
+ slotImageSelected(m_ImagesFilesListBox->item(0));
+ setNbItems();
+ resize( 600, 400 );
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Send Images"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for emailing images"),
+ "(c) 2003-2007, Gilles Caulier");
+
+ m_about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_about->addAuthor("Michael Hoechstetter", I18N_NOOP("Developer"),
+ "michael dot hoechstetter at gmx dot de");
+
+ m_about->addAuthor("Tom Albers", I18N_NOOP("Developer"),
+ "tomalbers at kde dot nl");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ slotMailAgentChanged(m_mailAgentName->currentItem());
+}
+
+SendImagesDialog::~SendImagesDialog()
+{
+ if ( m_thumbJob )
+ delete m_thumbJob;
+
+ delete m_about;
+}
+
+void SendImagesDialog::readSettings(void)
+{
+ // Read all settings from configuration file.
+
+ KConfig config("kipirc");
+ config.setGroup("SendImages Settings");
+
+ QString t = config.readEntry("MailAgentName", "Default");
+
+ // The _old_ Kmail (mind the lowercase 'm') called the default mailer.
+ // this is now renamed to 'Default'. It should not interfere with KMail, which
+ // is now doing what you expect.
+
+ if (t == "Kmail") t = "Default";
+ m_mailAgentName->setCurrentText(t);
+
+ m_ThunderbirdBinPath->setURL( config.readEntry("ThunderbirdBinPath", "/usr/bin/mozilla-thunderbird"));
+
+ if (config.readEntry("ImagesChangeProp", "true") == "true")
+ m_changeImagesProp->setChecked( true );
+ else
+ m_changeImagesProp->setChecked( false );
+
+ m_imagesResize->setCurrentItem(config.readNumEntry("ImageResize", 2)); // Medium size used by default.
+ m_imageCompression->setValue(config.readNumEntry("ImageCompression", 75));
+ m_imagesFormat->setCurrentText(config.readEntry("ImageFormat", "JPEG"));
+ m_attachmentlimit->setValue(config.readNumEntry("AttachmentLimit", 10));
+
+ if (config.readEntry("AddComments", "true") == "true")
+ m_addComments->setChecked( true );
+ else
+ m_addComments->setChecked( false );
+
+ if (config.readEntry("Comment2ImageName", "true") == "true")
+ m_comment2ImageName->setChecked( true );
+ else
+ m_comment2ImageName->setChecked( false );
+}
+
+void SendImagesDialog::writeSettings(void)
+{
+ // Write all settings in configuration file.
+
+ KConfig config("kipirc");
+ config.setGroup("SendImages Settings");
+ config.writeEntry("MailAgentName", m_mailAgentName->currentText());
+ config.writeEntry("ThunderbirdBinPath", m_ThunderbirdBinPath->url());
+ config.writeEntry("AddComments", m_addComments->isChecked());
+ config.writeEntry("ImagesChangeProp", m_changeImagesProp->isChecked());
+ config.writeEntry("ImageResize", m_imagesResize->currentItem());
+ config.writeEntry("ImageCompression", m_imageCompression->value());
+ config.writeEntry("ImageFormat", m_imagesFormat->currentText());
+ config.writeEntry("AttachmentLimit", m_attachmentlimit->value());
+ config.writeEntry("Comment2ImageName", m_comment2ImageName->isChecked());
+ config.sync();
+}
+
+void SendImagesDialog::setupImagesList(void)
+{
+ QString whatsThis;
+
+ page_setupImagesList = addPage(i18n("Images"),
+ i18n("Images to EMail"),
+ BarIcon("image", KIcon::SizeMedium));
+
+ QVBoxLayout *vlay = new QVBoxLayout( page_setupImagesList, 0, spacingHint() );
+
+ //---------------------------------------------
+
+ m_groupBoxImageList = new QGroupBox( page_setupImagesList );
+ m_groupBoxImageList->setFlat(false);
+ QGridLayout* grid = new QGridLayout( m_groupBoxImageList, 2, 2 , 20, 20);
+
+ m_ImagesFilesListBox = new ListImageItems( m_groupBoxImageList, "ListImageItems" );
+ QWhatsThis::add( m_ImagesFilesListBox, i18n( "<p>This is the list of images to email. "
+ "If you want to add some images click on the 'Add Images...' "
+ "button or use the drag-and-drop."));
+ grid->addMultiCellWidget(m_ImagesFilesListBox, 0, 2, 0, 1);
+
+ KButtonBox* imagesListButtonBox = new KButtonBox( m_groupBoxImageList, Vertical );
+ QPushButton* m_addImagesButton = imagesListButtonBox->addButton ( i18n( "&Add ..." ) );
+ QWhatsThis::add( m_addImagesButton, i18n("<p>Add images to the list.") );
+ QPushButton* m_remImagesButton = imagesListButtonBox->addButton ( i18n( "&Remove" ));
+ QWhatsThis::add( m_remImagesButton, i18n("<p>Remove selected images from the list.") );
+ imagesListButtonBox->layout();
+ grid->addMultiCellWidget(imagesListButtonBox, 0, 1, 2, 2);
+
+ m_imageLabel = new QLabel( m_groupBoxImageList );
+ m_imageLabel->setFixedHeight( 120 );
+ m_imageLabel->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
+ m_imageLabel->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
+ QWhatsThis::add( m_imageLabel, i18n( "<p>Preview of the currently selected image on the list." ) );
+ grid->addMultiCellWidget(m_imageLabel, 2, 2, 2, 2);
+
+ vlay->addWidget( m_groupBoxImageList );
+
+ //---------------------------------------------
+
+ QGroupBox * groupBox2 = new QGroupBox( i18n("Image Description"), page_setupImagesList );
+ groupBox2->setColumnLayout(0, Qt::Vertical );
+ groupBox2->layout()->setSpacing( 6 );
+ groupBox2->layout()->setMargin( 11 );
+ QWhatsThis::add( groupBox2, i18n("<p>The description of the currently selected image on the list.") );
+
+ QVBoxLayout * groupBox2Layout = new QVBoxLayout( groupBox2->layout() );
+ groupBox2Layout->setAlignment( Qt::AlignTop );
+
+ m_ImageComments = new KSqueezedTextLabel( groupBox2 );
+ m_ImageComments->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ groupBox2Layout->addWidget( m_ImageComments );
+
+ m_ImageAlbum = new KSqueezedTextLabel( groupBox2 );
+ m_ImageAlbum->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ groupBox2Layout->addWidget( m_ImageAlbum );
+
+ vlay->addWidget( groupBox2 );
+ vlay->addStretch(1);
+
+ //---------------------------------------------
+
+ connect(m_addImagesButton, SIGNAL(clicked()),
+ this, SLOT(slotImagesFilesButtonAdd()));
+
+ connect(m_remImagesButton, SIGNAL(clicked()),
+ this, SLOT(slotImagesFilesButtonRem()));
+
+ connect(m_ImagesFilesListBox, SIGNAL( currentChanged( QListBoxItem * ) ),
+ this, SLOT( slotImageSelected( QListBoxItem * )));
+
+ connect(m_ImagesFilesListBox, SIGNAL( addedDropItems(QStringList) ),
+ this, SLOT( slotAddDropItems(QStringList)));
+}
+
+void SendImagesDialog::setImagesList( const KURL::List& Files )
+{
+ if ( Files.count() == 0 ) return;
+
+ for( KURL::List::ConstIterator it = Files.begin(); it != Files.end(); ++it )
+ {
+ KIPI::ImageInfo imageInfo = m_interface->info( *it );
+ QString comments = imageInfo.description();
+
+ // Check if the new item already exist in the list.
+
+ bool findItem = false;
+
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ {
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(i) );
+
+ if (pitem->url() == (*it))
+ findItem = true;
+ }
+
+ if (findItem == false)
+ {
+ ImageItem *item = new ImageItem(m_ImagesFilesListBox,
+ comments, // Image comments.
+ *it // Complete url (path & file name).
+ );
+
+ item->setName( (*it).fileName() );
+ }
+ }
+
+ m_ImagesFilesListBox->setCurrentItem( m_ImagesFilesListBox->count()-1) ;
+ slotImageSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()));
+ m_ImagesFilesListBox->centerCurrentItem();
+}
+
+void SendImagesDialog::setupEmailOptions(void)
+{
+ QString whatsThis;
+
+ page_setupEmailOptions = addPage(i18n("Mail"),
+ i18n("Mail Options"),
+ BarIcon("mail_generic", KIcon::SizeMedium));
+
+ QVBoxLayout *vlay = new QVBoxLayout( page_setupEmailOptions, 0, spacingHint() );
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay10 = new QHBoxLayout( );
+ vlay->addLayout( hlay10 );
+
+ QLabel *m_mailAgentLabel = new QLabel( i18n("Mail agent:"), page_setupEmailOptions);
+
+ m_mailAgentName = new QComboBox( false, page_setupEmailOptions );
+ m_mailAgentName->insertItem( i18n("Default") );
+ m_mailAgentName->insertItem( "Balsa" );
+ m_mailAgentName->insertItem( "Claws Mail" );
+ m_mailAgentName->insertItem( "Evolution" );
+ m_mailAgentName->insertItem( "GmailAgent" );
+ m_mailAgentName->insertItem( "KMail" );
+ m_mailAgentName->insertItem( "Mozilla" );
+ m_mailAgentName->insertItem( "Netscape" );
+ m_mailAgentName->insertItem( "Sylpheed" );
+ m_mailAgentName->insertItem( "Sylpheed-Claws" );
+ m_mailAgentName->insertItem( "Thunderbird" );
+ m_mailAgentName->setCurrentText( i18n("Default") );
+ QWhatsThis::add( m_mailAgentName, i18n("<p>Select here your preferred external mail agent program."
+ "These mail agent versions are supported:<p>"
+ "<b>Balsa</b>: >= 2.x<p>"
+ "<b>Claws Mail</b>: >= 2.6.1<p>"
+ "<b>Evolution</b>: >= 1.4<p>"
+ "<b>GmailAgent</b>: >= 0.2<p>"
+ "<b>KMail</b>: >= 1.3<p>"
+ "<b>Mozilla</b>: >= 1.4<p>"
+ "<b>Netscape</b>: >= 7.x<p>"
+ "<b>Sylpheed</b>: >= 0.9<p>"
+ "<b>Sylpheed-Claws</b>: >= 0.9<p>"
+ "<b>Thunderbird</b>: >= 0.4<p>") );
+
+ hlay10->addWidget( m_mailAgentLabel );
+ hlay10->addStretch( 1 );
+ hlay10->addWidget( m_mailAgentName );
+
+ connect(m_mailAgentName, SIGNAL(activated(int)),
+ this, SLOT(slotMailAgentChanged(int)));
+
+ //---------------------------------------------
+
+ m_labelThunderbirdBinPath = new QLabel(i18n("&Thunderbird binary path:"), page_setupEmailOptions);
+ vlay->addWidget( m_labelThunderbirdBinPath );
+
+ m_ThunderbirdBinPath = new KURLRequester( "/usr/bin/thunderbird", page_setupEmailOptions);
+ m_labelThunderbirdBinPath->setBuddy( m_ThunderbirdBinPath );
+ vlay->addWidget(m_ThunderbirdBinPath);
+
+ connect(m_ThunderbirdBinPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotThunderbirdBinPathChanged(const QString&)));
+
+ QWhatsThis::add( m_ThunderbirdBinPath, i18n("<p>The path name to the Thunderbird binary program.") );
+
+ //---------------------------------------------
+
+ m_addComments = new QCheckBox( i18n("Attach a file with caption and tags"), page_setupEmailOptions);
+ QWhatsThis::add( m_addComments, i18n("<p>If you enable this option, all image captions and tags "
+ "will be added as an attached file.") );
+ vlay->addWidget( m_addComments );
+ m_comment2ImageName = new QCheckBox( i18n("Generate new filenames from image captions (if available)"), page_setupEmailOptions);
+ vlay->addWidget( m_comment2ImageName );
+
+ //---------------------------------------------
+
+ QGroupBox * groupBox2 = new QGroupBox( i18n("Image Properties"), page_setupEmailOptions );
+ groupBox2->setColumnLayout(0, Qt::Vertical );
+ groupBox2->layout()->setSpacing( 6 );
+ groupBox2->layout()->setMargin( 11 );
+ QWhatsThis::add( groupBox2, i18n("<p>The properties of images to send.") );
+
+ QVBoxLayout * groupBox2Layout = new QVBoxLayout( groupBox2->layout() );
+ groupBox2Layout->setAlignment( Qt::AlignTop );
+
+ m_changeImagesProp = new QCheckBox(i18n("Adjust image properties"), groupBox2);
+ QWhatsThis::add( m_changeImagesProp, i18n("<p>If you enable this option, "
+ "all images to send can be resized and recompressed.") );
+ m_changeImagesProp->setChecked( true );
+ groupBox2Layout->addWidget( m_changeImagesProp );
+
+ QHBoxLayout *hlay12 = new QHBoxLayout();
+ groupBox2Layout->addLayout( hlay12 );
+
+ m_imagesResize = new QComboBox(false, groupBox2);
+ m_imagesResize->insertItem(i18n("Very Small (320 pixels)"));
+ m_imagesResize->insertItem(i18n("Small (640 pixels)"));
+ m_imagesResize->insertItem(i18n("Medium (800 pixels)"));
+ m_imagesResize->insertItem(i18n("Big (1024 pixels)"));
+ m_imagesResize->insertItem(i18n("Very Big (1280 pixels)"));
+ m_imagesResize->insertItem(i18n("Huge - for printing (1600 pixels)"));
+ m_imagesResize->setCurrentText (i18n("Medium (800 pixels)"));
+ whatsThis = i18n("<p>Select here the images size to send:<p>"
+ "<b>%1</b>: use this if you have a very slow internet "
+ "connection or if the target mailbox size is very limited.<p>"
+ "<b>%2</b>: use this if you have a slow internet connection "
+ "and if the target mailbox size is limited.<p>"
+ "<b>%3</b>: this is the default value for a medium internet connection "
+ "and a target mailbox size.<p>"
+ "<b>%4</b>: use this if you have a high-speed internet connection "
+ "and if the target mailbox size is not limited.<p>"
+ "<b>%5</b>: use this if you have no size or speed restrictions.<p>"
+ "<b>%6</b>: use this only for printing purpose.<p>")
+ .arg(i18n("very small (320 pixels)"))
+ .arg(i18n("small (640 pixels)"))
+ .arg(i18n("medium (800 pixels)"))
+ .arg(i18n("big (1024 pixels)"))
+ .arg(i18n("very big (1280 pixels)"))
+ .arg(i18n("huge - for printing (1600 pixels)"));
+ QWhatsThis::add( m_imagesResize, whatsThis );
+
+ m_labelImageSize = new QLabel( i18n("Sent image size:"), groupBox2);
+ hlay12->addWidget( m_labelImageSize );
+ m_labelImageSize->setBuddy( m_imagesResize );
+ hlay12->addStretch( 1 );
+ hlay12->addWidget(m_imagesResize);
+
+ //---------------------------------------------
+
+ m_imageCompression = new KIntNumInput(75, groupBox2);
+ m_imageCompression->setRange(1, 100, 1, true );
+ m_imageCompression->setLabel( i18n("Sent image quality level:") );
+ groupBox2Layout->addWidget( m_imageCompression );
+ whatsThis = i18n("<p>The new compression value of images to send:<p>");
+ whatsThis = whatsThis + i18n("<b>1</b>: very high compression<p>"
+ "<b>25</b>: high compression<p>"
+ "<b>50</b>: medium compression<p>"
+ "<b>75</b>: low compression (default value)<p>"
+ "<b>100</b>: no compression");
+
+ QWhatsThis::add( m_imageCompression, whatsThis);
+
+ //---------------------------------------------
+
+ QHBoxLayout *hlay13 = new QHBoxLayout();
+ groupBox2Layout->addLayout( hlay13 );
+
+ m_imagesFormat = new QComboBox(false, groupBox2);
+ m_imagesFormat->insertItem("JPEG");
+ m_imagesFormat->insertItem("PNG");
+ m_imagesFormat->setCurrentText ("JPEG");
+ whatsThis = i18n("<p>Select here the images files format to send.<p>");
+ whatsThis = whatsThis + i18n("<b>JPEG</b>: The Joint Photographic Experts Group's file format "
+ "is a good Web file format but it uses lossy compression.<p>"
+ "<b>PNG</b>: the Portable Network Graphics format is an extensible file format for "
+ "the lossless, portable, well-compressed storage of raster images. PNG provides a "
+ "patent-free replacement for GIF and can also replace many common uses of TIFF. "
+ "PNG is designed to work well in online viewing applications, such as the World Wide Web, "
+ "so it is fully streamable with a progressive display option. Also, PNG can store gamma "
+ "and chromaticity data for improved color matching on heterogeneous platforms.");
+ QWhatsThis::add( m_imagesFormat, whatsThis );
+
+ m_labelImageFormat = new QLabel(i18n("Image file format:"), groupBox2);
+ hlay13->addWidget(m_labelImageFormat);
+ m_labelImageFormat->setBuddy(m_imagesFormat);
+ hlay13->addStretch(1);
+ hlay13->addWidget(m_imagesFormat);
+
+ vlay->addWidget(groupBox2);
+ vlay->addStretch(1);
+
+ m_attachmentlimit = new KIntNumInput(17, page_setupEmailOptions);
+ m_attachmentlimit->setRange(1, 50, 1, true );
+ m_attachmentlimit->setLabel( i18n("Maximum Email size limit:"));
+ m_attachmentlimit->setSuffix(i18n("MB"));
+ vlay->addWidget( m_attachmentlimit );
+
+ //---------------------------------------------
+
+ connect(m_changeImagesProp, SIGNAL(toggled(bool)),
+ m_labelImageSize, SLOT(setEnabled(bool)));
+
+ connect(m_changeImagesProp, SIGNAL(toggled(bool)),
+ m_imagesResize, SLOT(setEnabled(bool)));
+
+ connect(m_changeImagesProp, SIGNAL(toggled(bool)),
+ m_imageCompression, SLOT(setEnabled(bool)));
+
+ connect(m_changeImagesProp, SIGNAL(toggled(bool)),
+ m_labelImageFormat, SLOT(setEnabled(bool)));
+
+ connect(m_changeImagesProp, SIGNAL(toggled(bool)),
+ m_imagesFormat, SLOT(setEnabled(bool)));
+}
+
+void SendImagesDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("sendimages", "kipi-plugins");
+}
+
+void SendImagesDialog::slotMailAgentChanged(int)
+{
+ if ( m_mailAgentName->currentText() == "Thunderbird" )
+ {
+ m_labelThunderbirdBinPath->setEnabled(true);
+ m_ThunderbirdBinPath->setEnabled(true);
+ }
+ else
+ {
+ m_labelThunderbirdBinPath->setEnabled(false);
+ m_ThunderbirdBinPath->setEnabled(false);
+ }
+}
+
+void SendImagesDialog::slotThunderbirdBinPathChanged(const QString &url )
+{
+ if ( m_mailAgentName->currentText() == "Thunderbird" )
+ enableButtonOK( !url.isEmpty());
+}
+
+void SendImagesDialog::slotAddDropItems(QStringList filesPath)
+{
+ setImagesList( KURL::List( filesPath) );
+}
+
+void SendImagesDialog::slotImagesFilesButtonAdd( void )
+{
+ KURL::List urls = KIPI::ImageDialog::getImageURLs( this, m_interface );
+
+ if ( urls.isEmpty() ) return;
+
+ setImagesList(urls);
+ setNbItems();
+}
+
+void SendImagesDialog::slotImagesFilesButtonRem( void )
+{
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ {
+ if (m_ImagesFilesListBox->isSelected(i))
+ {
+ m_ImagesFilesListBox->removeItem(i);
+ m_ImagesFilesListBox->setCurrentItem(i);
+ --i;
+ }
+ }
+
+ m_ImagesFilesListBox->setSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()), true);
+ slotImageSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()));
+ setNbItems();
+}
+
+void SendImagesDialog::slotImageSelected( QListBoxItem * item )
+{
+ if ( !item || m_ImagesFilesListBox->count() == 0 )
+ {
+ m_imageLabel->clear();
+ return;
+ }
+
+ ImageItem *pitem = static_cast<ImageItem*>( item );
+
+ if ( !pitem ) return;
+
+ m_ImageComments->setText( i18n("Caption: %1").arg(pitem->comments()) );
+ m_ImageAlbum->setText( i18n("Album: %1").arg(pitem->album()) );
+ m_imageLabel->clear();
+
+ if ( m_thumbJob )
+ delete m_thumbJob;
+
+ m_thumbJob = KIO::filePreview( pitem->url(), m_imageLabel->height() );
+
+ connect(m_thumbJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ SLOT(slotGotPreview(const KFileItem*, const QPixmap&)));
+
+ connect(m_thumbJob, SIGNAL(failed(const KFileItem*)),
+ SLOT(slotFailedPreview(const KFileItem*)));
+}
+
+void SendImagesDialog::slotGotPreview(const KFileItem*, const QPixmap &pixmap)
+{
+ m_imageLabel->setPixmap(pixmap);
+ m_thumbJob = 0L;
+}
+
+void SendImagesDialog::slotFailedPreview(const KFileItem*)
+{
+ m_thumbJob = 0L;
+}
+
+void SendImagesDialog::slotOk()
+{
+ if ( m_ImagesFilesListBox->count() == 0 )
+ {
+ KMessageBox::error(this, i18n("You must add some images to send."));
+ return;
+ }
+
+ if ( m_mailAgentName->currentText() == "Thunderbird" )
+ {
+ QFile fileThunderbird(m_ThunderbirdBinPath->url());
+
+ if (fileThunderbird.exists() == false)
+ {
+ KMessageBox::sorry(this, i18n("Thunderbird binary path is not valid. Please check it."));
+ return;
+ }
+ }
+
+ writeSettings();
+
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; i++)
+ {
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(i) );
+ m_images2send << pitem->url();
+ }
+
+ emit signalAccepted();
+ accept();
+}
+
+void SendImagesDialog::setNbItems(void)
+{
+ if ( m_ImagesFilesListBox->count() == 0 ) m_groupBoxImageList->setTitle(i18n("Image List"));
+ else
+ m_groupBoxImageList->setTitle(i18n("Image List (1 item)", "Image List (%n items)",
+ m_ImagesFilesListBox->count() ));
+}
+
+} // NameSpace KIPISendimagesPlugin
diff --git a/kipi-plugins/sendimages/sendimagesdialog.h b/kipi-plugins/sendimages/sendimagesdialog.h
new file mode 100644
index 0000000..3fd4984
--- /dev/null
+++ b/kipi-plugins/sendimages/sendimagesdialog.h
@@ -0,0 +1,173 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-01
+ * Description : a kipi plugin to e-mailing images
+ *
+ * Copyright (C) 2003-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SENDIMAGESDIALOG_H
+#define SENDIMAGESDIALOG_H
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qguardedptr.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <klistbox.h>
+#include <kio/previewjob.h>
+#include <kurl.h>
+
+// LibKipi includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imagecollection.h>
+#include <libkipi/imageinfo.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+
+class QComboBox;
+class QGroupBox;
+class QLabel;
+class QCheckBox;
+class QFrame;
+class QPushButton;
+class QFileInfo;
+
+class KFileItem;
+class KIntNumInput;
+class KListBox;
+class KSqueezedTextLabel;
+class KURLRequester;
+
+namespace KIPISendimagesPlugin
+{
+
+class ListImageItems : public KListBox
+{
+ Q_OBJECT
+
+public:
+
+ ListImageItems(QWidget *parent=0, const char *name=0);
+
+signals:
+
+ void addedDropItems(QStringList filesPath);
+
+protected:
+
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dropEvent(QDropEvent *e);
+};
+
+
+class SendImagesDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ SendImagesDialog(QWidget *parent, KIPI::Interface* interface,
+ const KIPI::ImageCollection& images );
+ ~SendImagesDialog();
+
+ KIntNumInput *m_imageCompression;
+ KIntNumInput *m_attachmentlimit;
+
+ QComboBox *m_imagesFormat;
+ QComboBox *m_imagesResize;
+ QComboBox *m_mailAgentName;
+
+ QCheckBox *m_addComments;
+ QCheckBox *m_comment2ImageName;
+ QCheckBox *m_changeImagesProp;
+
+ KURLRequester *m_ThunderbirdBinPath;
+
+ KURL::List m_images2send;
+
+public slots:
+
+ void slotAddDropItems(QStringList filesPath);
+
+signals:
+
+ void signalAccepted(void);
+
+private slots:
+
+ void slotHelp();
+ void slotOk();
+ void slotImageSelected( QListBoxItem * item );
+ void slotGotPreview(const KFileItem* , const QPixmap &pixmap);
+ void slotFailedPreview(const KFileItem*);
+ void slotImagesFilesButtonAdd(void);
+ void slotImagesFilesButtonRem(void);
+ void slotThunderbirdBinPathChanged(const QString&);
+ void slotMailAgentChanged(int);
+
+private:
+
+ void setupImagesList(void);
+ void setupEmailOptions(void);
+ void setImagesList(const KURL::List& images);
+ void writeSettings(void);
+ void readSettings(void);
+ void setNbItems(void);
+
+private:
+
+ bool m_cancelled;
+
+ QLabel *m_labelImageFormat;
+ QLabel *m_labelImageSize;
+ QLabel *m_mailAgentLabel;
+ QLabel *m_labelThunderbirdBinPath;
+
+ QPushButton *m_addImageButton;
+ QPushButton *m_remImagesButton;
+ QPushButton *m_helpButton;
+
+ QProgressDialog *m_progressDlg;
+
+ QGroupBox *m_groupBoxImageList;
+
+ QLabel *m_imageLabel;
+
+ QFrame *page_setupImagesList;
+ QFrame *page_setupEmailOptions;
+ QFrame *page_about;
+
+ KSqueezedTextLabel *m_ImageComments;
+ KSqueezedTextLabel *m_ImageAlbum;
+
+ KIPI::Interface *m_interface;
+ KIO::PreviewJob *m_thumbJob;
+
+ KIPIPlugins::KPAboutData *m_about;
+ ListImageItems *m_ImagesFilesListBox;
+};
+
+} // NameSpace KIPISendimagesPlugin
+
+#endif // SENDIMAGESDIALOG_H
diff --git a/kipi-plugins/simpleviewerexport/Makefile.am b/kipi-plugins/simpleviewerexport/Makefile.am
new file mode 100644
index 0000000..7acd502
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/Makefile.am
@@ -0,0 +1,25 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) $(LIBKDCRAW_CFLAGS) $(LIBKEXIV2_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = kipiplugin_simpleviewer.la
+
+kipiplugin_simpleviewer_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+
+kipiplugin_simpleviewer_la_SOURCES = plugin_simpleviewer.cpp svedialog.cpp \
+ simpleviewerexport.cpp firstrundlg.cpp
+
+kipiplugin_simpleviewer_la_LIBADD = $(LIBKIPI_LIBS) $(LIBKDCRAW_LIBS) $(LIBKEXIV2_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_simpleviewer_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+kde_services_DATA = kipiplugin_simpleviewer.desktop
+
+kipiplugin_simpleviewer_svdir = $(kde_datadir)/kipiplugin_simpleviewerexport/simpleviewer_html
+kipiplugin_simpleviewer_sv_DATA = space.png
+
+kipiplugin_simpleviewer_svtemplatedir = $(kde_datadir)/kipiplugin_simpleviewerexport
+kipiplugin_simpleviewer_svtemplate_DATA = index.template
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_simpleviewer.pot
diff --git a/kipi-plugins/simpleviewerexport/firstrundlg.cpp b/kipi-plugins/simpleviewerexport/firstrundlg.cpp
new file mode 100644
index 0000000..c2304df
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/firstrundlg.cpp
@@ -0,0 +1,161 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-01-06
+ * Description : a plugin to export image collections using SimpleViewer.
+ *
+ * Copyright (C) 2006 by Joern Ahrens <joern dot ahrens at kdemail dot net>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT include files
+
+#include <qframe.h>
+#include <qlayout.h>
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+
+// KDE include files
+
+#include <klocale.h>
+#include <kapplication.h>
+#include <kurllabel.h>
+#include <kurlrequester.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <kapplication.h>
+
+// KIPI include files
+
+#include <libkipi/version.h>
+#include <libkipi/imagecollectionselector.h>
+
+// Local include files
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "firstrundlg.h"
+#include "firstrundlg.moc"
+
+namespace KIPISimpleViewerExportPlugin
+{
+
+FirstRunDlg::FirstRunDlg(QWidget *parent)
+ : KDialogBase(parent, 0, true, i18n("Flash Export"),
+ Help|Ok|Cancel, Ok, true)
+{
+ enableButtonOK(false);
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Flash Export"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to export images to Flash using Simple Viewer component"),
+ "(c) 2005-2006, Joern Ahrens\n"
+ "(c) 2008, Gilles Caulier");
+
+ m_about->addAuthor("Joern Ahrens",
+ I18N_NOOP("Author and maintainer"),
+ "joern dot ahrens at kdemail dot net");
+
+ m_about->addAuthor("Gilles Caulier",
+ I18N_NOOP("Developer and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_about->addCredit("Felix Turner",
+ "Author of the Simple Viewer Flash component",
+ 0,
+ "http://www.airtightinteractive.com/simpleviewer");
+
+ m_about->addCredit("Mikkel B. Stegmann",
+ "Basis for the index.html template",
+ 0,
+ "http://www.stegmann.dk/mikkel/porta");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"),
+ this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+
+ // ---------------------------------------------------------------
+
+ QFrame *page = new QFrame(this);
+ setMainWidget(page);
+
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ QLabel *info = new QLabel( page );
+ info->setText( i18n( "<p>SimpleViewer is a Flash component which is free to use, "
+ "but uses a license which comes into conflict with several distributions. "
+ "Due to the license it is not possible to ship it with this plugin.</p>"
+ "<p>You can now download SimpleViewer from its homepage and point this tool "
+ "to the downloaded archive. The archive will be stored with the plugin configuration, "
+ "so it is available for further use.</p>"));
+ topLayout->addWidget(info);
+
+ info = new QLabel(page);
+ info->setText(i18n( "<p>1.) Download SimpleViewer Version 1.8.x</p>"));
+ topLayout->addWidget(info);
+
+ KURLLabel *link = new KURLLabel(page);
+ link->setText("http://www.airtightinteractive.com/simpleviewer");
+ link->setURL("http://www.airtightinteractive.com/simpleviewer");
+ topLayout->addWidget(link);
+ connect(link, SIGNAL(leftClickedURL(const QString &)),
+ this, SLOT(slotDownload(const QString &)));
+
+ info = new QLabel(page);
+ info->setText(i18n("<p>2.) Point this tool to the downloaded archive</p>"));
+ topLayout->addWidget( info );
+
+ m_urlRequester = new KURLRequester(page);
+ topLayout->addWidget(m_urlRequester);
+ connect(m_urlRequester, SIGNAL(urlSelected(const QString&)),
+ this, SLOT(slotURLSelected(const QString&)));
+
+ topLayout->addStretch(10);
+}
+
+FirstRunDlg::~FirstRunDlg()
+{
+ delete m_about;
+}
+
+void FirstRunDlg::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("simpleviewerexport", "kipi-plugins");
+}
+
+void FirstRunDlg::slotDownload(const QString &url)
+{
+ KApplication::kApplication()->invokeBrowser(url);
+}
+
+void FirstRunDlg::slotURLSelected(const QString &url)
+{
+ enableButtonOK(true);
+ m_url = url;
+}
+
+QString FirstRunDlg::getURL()
+{
+ return m_url;
+}
+
+} // namespace KIPISimpleViewerExportPlugin
diff --git a/kipi-plugins/simpleviewerexport/firstrundlg.h b/kipi-plugins/simpleviewerexport/firstrundlg.h
new file mode 100644
index 0000000..ea0b16d
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/firstrundlg.h
@@ -0,0 +1,92 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-01-06
+ * Description : a plugin to export image collections using SimpleViewer.
+ *
+ * Copyright (C) 2006 by Joern Ahrens <joern dot ahrens at kdemail dot net>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 FIRSTRUNDLG_H
+#define FIRSTRUNDLG_H
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+// Include files for KIPI
+
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QString;
+
+class KURLRequester;
+
+namespace KIPISimpleViewerExportPlugin
+{
+
+/**
+ * To avoid licensing problems with some distributions, the SimpleViewer
+ * Flash cannot be shipped with the plugin. During the first run of the
+ * plugin, the user has to download SimpleViewer from its homepage and point
+ * the plugin to that archive to install it. This is done by this dialog.
+ */
+
+class FirstRunDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ FirstRunDlg(QWidget *parent=0);
+ ~FirstRunDlg();
+
+ /**
+ * Returns the URL, where the SimpleViewer package is stored
+ */
+ QString getURL();
+
+private slots:
+
+ /**
+ * Opens the browser with the SimpleViewer download page
+ */
+ void slotDownload(const QString &url);
+
+ /**
+ * Starts the installation of SimpleViewer
+ */
+ void slotURLSelected(const QString &url);
+
+ void slotHelp();
+
+private:
+
+ QString m_url;
+
+ KURLRequester *m_urlRequester;
+
+ KIPIPlugins::KPAboutData *m_about;
+};
+
+} // namespace KIPISimpleViewerExportPlugin
+
+#endif /* FIRSTRUNDLG_H */
diff --git a/kipi-plugins/simpleviewerexport/index.template b/kipi-plugins/simpleviewerexport/index.template
new file mode 100644
index 0000000..09a4f0c
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/index.template
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="generator" content="kipiplugin simpleviewerexport">
+ <meta name="description" content="Web photo album generated by Flash Export kipi-plugin - http://www.kipi-plugins.org and displayed by SimpleViewer - http://www.airtightinteractive.com/simpleviewer">
+ <title>{TITLE}</title>
+ <style type="text/css">
+ <!--
+ html, body {
+ height:100%;
+ color: {COLOR};
+ background-color: {BGCOLOR};
+ margin: 0;
+ padding: 0;
+ border: 0;
+ overflow-y: auto;
+ overflow-x: auto;
+ }
+ td {
+ font-size: 70%;
+ color: {COLOR};
+ font-family: Verdana, Arial, Helvetica, Lucida, sans-serif;
+ }
+ a {
+ color: {COLOR};
+ text-decoration: underline;
+ }
+ a:hover {
+ color: #555555;
+ text-decoration: underline;
+ }
+
+ span.title {
+ font-size: 160%;
+ font-weight: bold;
+ padding-bottom: 0em;
+ padding-top: .6em;
+ margin-bottom: 0em;
+ margin-top: 0em;
+ }
+ -->
+ </style>
+
+ </head>
+ <body>
+ <div id="mainlayer" style="visibility: visible; position:absolute; top: 0; left: 0; width: 100%; height: 100%; z-index:1;">
+ <table style="width:100%;height:100%;" border="0" cellpadding="0" cellspacing="0">
+
+ <tr>
+ <td colspan="2">
+ <table style="width:100%;height:100%;" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <img src="space.png" width="1" height="624" alt="">
+ </td>
+ <td valign="middle" align="center">
+ <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="100%" height="100%" align="middle">
+ <param name="movie" value="viewer.swf">
+ <param name="quality" value="high">
+ <param name="scale" value="noscale">
+ <param name="bgcolor" value="{BGCOLOR}">
+ <embed src="viewer.swf" width="100%" height="100%" align="middle" quality="high" scale="noscale" bgcolor="{BGCOLOR}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer">
+ </object>
+ </td>
+ <td>
+ <img src="space.png" width="1" height="624" alt="">
+
+ </td>
+ </tr>
+ <tr style="height:1px;">
+ <td></td>
+ <td align="center">
+ <img src="space.png" width="842" height="1" alt="">
+ </td>
+ <td></td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+ <tr style="height:3ex">
+ <td align="left" valign="top">
+ <img src="space.png" width="31" height="1" alt="">
+ </td>
+ <td align="right" valign="top">
+
+ Created with
+ <a target="_blank" href="{HOSTURL}">{HOSTNAME}</a>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ </body>
+</html>
diff --git a/kipi-plugins/simpleviewerexport/kipiplugin_simpleviewer.desktop b/kipi-plugins/simpleviewerexport/kipiplugin_simpleviewer.desktop
new file mode 100644
index 0000000..2247003
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/kipiplugin_simpleviewer.desktop
@@ -0,0 +1,39 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=SimpleViewer
+Name[br]=Gweller eeun
+Name[ca]=Visualitzador senzill
+Name[cs]=Jednoduchý prohlížeč
+Name[da]=SimpelFremviser
+Name[de]=Einfacher Betrachter
+Name[es]=VisorSencillo
+Name[ga]=AmharcánSimplí
+Name[gl]=Visor Sinxelo
+Name[it]=Visore semplice
+Name[nds]=Eenfach Kieker
+Name[nl]=Eenvoudige viewer
+Name[pa]=ਸਧਾਰਨ ਦਰਸ਼ਕ
+Name[pt]=Visualizador Simples
+Name[sr]=Прост прегледач
+Name[sr@Latn]=Prost pregledač
+Name[sv]=Enkel visning
+Name[xx]=xxSimpleViewerxx
+Name[zh_CN]=简单查看器
+Comment=KIPI Flash Export Plugin
+Comment[ca]=Connector del KIPI d'exportació a Flash
+Comment[de]=KIPI Flash-Exportmodul
+Comment[es]=Complemento de KIPI para exportación a flash
+Comment[et]=KIPI Flashi ekspordiplugin
+Comment[fr]=Un module externe KIPI pour exporter les images en format flash
+Comment[is]=KIPI íforrit til útflutnings á Flash
+Comment[it]=Plugin per l'esportazione a Flash di KIPI
+Comment[ja]=Kipi Flash エクスポートプラグイン
+Comment[nl]=KIPI-plugin voor exporteren naar Flash
+Comment[sr]=KIPI прикључак за извоз у Флеш
+Comment[sr@Latn]=KIPI прикључак за извоз у Флеш
+Comment[sv]=KIPI-insticksprogram för export till Flash
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_simpleviewer
+author=Gilles Caulier, caulier dot gilles at gmail dot com
+
diff --git a/kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp b/kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp
new file mode 100644
index 0000000..42bc873
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/plugin_simpleviewer.cpp
@@ -0,0 +1,93 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-12-19
+ * Description : a plugin to export image collections using SimpleViewer.
+ *
+ * Copyright (C) 2005-2006 by Joern Ahrens <joern dot ahrens at kdemail dot net>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kapplication.h>
+
+// LibKIPI includes.
+
+#include <libkipi/imagecollection.h>
+
+// Local includes.
+
+#include "plugin_simpleviewer.h"
+#include "simpleviewerexport.h"
+#include "plugin_simpleviewer.moc"
+
+typedef KGenericFactory<Plugin_SimpleViewer> Factory;
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_simpleviewer, Factory("kipiplugin_simpleviewer"))
+
+Plugin_SimpleViewer::Plugin_SimpleViewer(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin(Factory::instance(), parent, "SimpleViewer")
+{
+ kdDebug( 51001 ) << "Plugin_SimpleViewer plugin loaded" << endl;
+}
+
+void Plugin_SimpleViewer::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_actionSimpleViewer = new KAction (i18n("Flash Export..."),
+ "www",
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "simpleviewer");
+
+ addAction( m_actionSimpleViewer );
+
+ m_interface = dynamic_cast< KIPI::Interface* >( parent() );
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+}
+
+KIPI::Category Plugin_SimpleViewer::category( KAction* action ) const
+{
+ if ( action == m_actionSimpleViewer )
+ return KIPI::EXPORTPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::EXPORTPLUGIN; // no warning from compiler, please
+}
+
+void Plugin_SimpleViewer::slotActivate()
+{
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPISimpleViewerExportPlugin::SimpleViewerExport::run( m_interface, this );
+}
diff --git a/kipi-plugins/simpleviewerexport/plugin_simpleviewer.h b/kipi-plugins/simpleviewerexport/plugin_simpleviewer.h
new file mode 100644
index 0000000..042ef00
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/plugin_simpleviewer.h
@@ -0,0 +1,55 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-12-19
+ * Description : a plugin to export image collections using SimpleViewer.
+ *
+ * Copyright (C) 2005-2006 by Joern Ahrens <joern dot ahrens at kdemail dot net>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_SIMPLEVIEWER_H
+#define PLUGIN_SIMPLEVIEWER_H
+
+// LibKIPI includes
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+class Plugin_SimpleViewer : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_SimpleViewer(QObject *parent, const char* name, const QStringList &args);
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* widget );
+
+private slots:
+
+ void slotActivate();
+
+private:
+
+ KAction *m_actionSimpleViewer;
+ KIPI::Interface *m_interface;
+};
+
+#endif // PLUGIN_SIMPLEVIEWER_H
+
diff --git a/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp b/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp
new file mode 100644
index 0000000..eab94d9
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/simpleviewerexport.cpp
@@ -0,0 +1,728 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-12-19
+ * Description : a plugin to export image collections using SimpleViewer.
+ *
+ * Copyright (C) 2005-2006 by Joern Ahrens <joern dot ahrens at kdemail dot net>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes
+
+#include <qtimer.h>
+#include <qimage.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qcstring.h>
+#include <qdatastream.h>
+
+// KDE includes
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kio/netaccess.h>
+#include <kfilemetainfo.h>
+#include <kstandarddirs.h>
+#include <kio/job.h>
+#include <kzip.h>
+#include <kmessagebox.h>
+#include <kaboutdata.h>
+#include <ktempdir.h>
+
+// KIPI includes
+
+#include <libkipi/version.h>
+#include <libkipi/batchprogressdialog.h>
+#include <libkipi/imageinfo.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/version.h>
+#include <libkdcraw/kdcraw.h>
+
+#if KDCRAW_VERSION < 0x000106
+#include <libkdcraw/dcrawbinary.h>
+#endif
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes
+
+#include "pluginsversion.h"
+#include "firstrundlg.h"
+#include "svedialog.h"
+#include "simpleviewerexport.h"
+#include "simpleviewerexport.moc"
+
+namespace KIPISimpleViewerExportPlugin
+{
+
+// maxium size of a simpleviewer thumbnail
+// TODO: read from configfile
+const int maxThumbSize = 45;
+const QString viewer("viewer.swf");
+
+void SimpleViewerExport::run(KIPI::Interface* interface, QObject *parent)
+{
+ SimpleViewerExport *plugin = new SimpleViewerExport(interface, parent);
+
+ if(!plugin->checkSimpleViewer())
+ {
+ if(!plugin->installSimpleViewer())
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("SimpleViewer installation failed"));
+ return;
+ }
+ }
+
+ if(plugin->configure())
+ plugin->startExport();
+
+ delete plugin;
+}
+
+SimpleViewerExport::SimpleViewerExport(KIPI::Interface* interface, QObject *parent)
+ : QObject(parent)
+{
+ m_interface = interface;
+ m_configDlg = 0;
+ m_totalActions = 0;
+ m_action = 0;
+ m_canceled = true;
+ m_dataLocal = locateLocal("data", "kipiplugin_simpleviewerexport/simpleviewer/", true);
+ m_tempDir = 0;
+
+ m_simpleViewerFiles.append(viewer);
+ m_simpleViewerFiles.append("swfobject.js");
+
+ const KAboutData *data = KApplication::kApplication()->aboutData();
+ m_hostName = QString::QString( data->appName() );
+ m_hostURL = data->homepage();
+
+ if (m_hostURL.isEmpty())
+ {
+ m_hostName = "Kipi";
+ m_hostURL = "http://www.kipi-plugins.org";
+ }
+}
+
+SimpleViewerExport::~SimpleViewerExport()
+{
+ if(m_tempDir)
+ delete m_tempDir;
+}
+
+bool SimpleViewerExport::configure()
+{
+ m_canceled = false;
+
+ if(!m_configDlg)
+ m_configDlg = new SVEDialog(m_interface, kapp->activeWindow());
+
+ bool configured = false;
+ while(!configured)
+ {
+ if(m_configDlg->exec() == QDialog::Rejected)
+ return false;
+
+ configured = true;
+
+ if(KIO::NetAccess::exists(m_configDlg->exportURL(), false, kapp->activeWindow()))
+ {
+ int ret = KMessageBox::warningYesNoCancel(kapp->activeWindow(),
+ i18n("Target folder %1 already exists.\n"
+ "Do you want to overwrite it (all data in this folder will be lost)")
+ .arg(m_configDlg->exportURL()));
+
+ switch(ret)
+ {
+ case KMessageBox::Yes:
+ if(!KIO::NetAccess::del(m_configDlg->exportURL(), kapp->activeWindow()))
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("Could not delete %1\n"
+ "Please choose another export folder").arg(m_configDlg->exportURL()));
+ configured = false;
+ }
+ break;
+
+ case KMessageBox::No:
+ configured = false;
+ break;
+
+ case KMessageBox::Cancel:
+ return false;
+ break;
+ };
+ }
+ }
+
+ return true;
+}
+
+void SimpleViewerExport::startExport()
+{
+ if(m_canceled)
+ return;
+
+ m_progressDlg = new KIPI::BatchProgressDialog(kapp->activeWindow(), i18n("Flash Export"));
+
+ connect(m_progressDlg, SIGNAL(cancelClicked()),
+ this, SLOT(slotCancel()));
+
+ m_progressDlg->show();
+ kapp->processEvents();
+
+ // Estimate the number of actions for the KIPI progress dialog.
+ m_progressDlg->addedAction(i18n("Estimate the number of actions to do..."), KIPI::StartingMessage);
+ m_albumsList = m_configDlg->getSelectedAlbums();
+ m_totalActions = 0;
+ for( QValueList<KIPI::ImageCollection>::Iterator it = m_albumsList.begin() ;
+ !m_canceled && (it != m_albumsList.end()) ; ++it )
+ {
+ m_totalActions += (*it).images().count();
+ }
+
+ // +copying SimpleViewer, +creating index.html
+ m_totalActions += 2;
+
+ m_progressDlg->setProgress(0, m_totalActions);
+
+ slotProcess();
+
+#if KDE_VERSION >= 0x30200
+ m_progressDlg->setButtonCancel(KStdGuiItem::close());
+#else
+ m_progressDlg->setButtonCancelText(i18n("&Close"));
+#endif
+
+}
+
+void SimpleViewerExport::slotCancel()
+{
+ m_progressDlg->addedAction(i18n("Export canceled"), KIPI::ErrorMessage);
+ m_canceled = true;
+}
+
+void SimpleViewerExport::slotProcess()
+{
+ if(m_canceled)
+ return;
+
+ m_progressDlg->addedAction(i18n("Initialising..."), KIPI::StartingMessage);
+
+ if(!m_canceled && !createExportDirectories())
+ {
+ m_progressDlg->addedAction(i18n("Failed to create export directories"),
+ KIPI::ErrorMessage);
+ return;
+ }
+
+ if(!m_canceled && !exportImages())
+ {
+ m_progressDlg->addedAction(i18n("Failed to export the images"),
+ KIPI::ErrorMessage);
+ return;
+ }
+
+ if(!m_canceled && !createIndex())
+ {
+ m_progressDlg->addedAction(i18n("Failed to create index.html"),
+ KIPI::ErrorMessage);
+ return;
+ }
+
+ if(!m_canceled && !copySimpleViewer())
+ {
+ m_progressDlg->addedAction(i18n("Failed to copy SimpleViewer files"),
+ KIPI::ErrorMessage);
+ return;
+ }
+
+ if(!m_canceled && !upload())
+ {
+ m_progressDlg->addedAction(i18n("Failed to upload the gallery"),
+ KIPI::ErrorMessage);
+ return;
+ }
+
+ if(m_canceled)
+ {
+ int ret = KMessageBox::warningYesNo(kapp->activeWindow(),
+ i18n("Export was canceled.\n"
+ "Do you want to delete the yet created files in %1 ?")
+ .arg(m_configDlg->exportURL()));
+ if(ret == KMessageBox::Yes)
+ {
+ KIO::NetAccess::del(m_configDlg->exportURL(), kapp->activeWindow());
+ }
+ }
+
+ if(!m_canceled)
+ m_progressDlg->addedAction(i18n("Finished..."), KIPI::SuccessMessage);
+}
+
+bool SimpleViewerExport::createExportDirectories()
+{
+ m_tempDir = new KTempDir(locateLocal("tmp", "simpleviewerexport"));
+ m_tempDir->setAutoDelete(true);
+
+ m_progressDlg->addedAction(i18n("Creating directories..."), KIPI::StartingMessage);
+
+ KURL root = m_configDlg->exportURL();
+ if(!KIO::NetAccess::mkdir(root, kapp->activeWindow()))
+ {
+ m_progressDlg->addedAction(i18n("Could not create folder '%1'").arg(root.url()),
+ KIPI::ErrorMessage);
+ return(false);
+ }
+
+ KURL thumbsDir = m_tempDir->name();
+ thumbsDir.addPath("/thumbs");
+ if(!KIO::NetAccess::mkdir(thumbsDir, kapp->activeWindow()))
+ {
+ m_progressDlg->addedAction(i18n("Could not create folder '%1'").arg(thumbsDir.url()),
+ KIPI::ErrorMessage);
+ return(false);
+ }
+
+ KURL imagesDir = m_tempDir->name();
+ imagesDir.addPath("/images");
+ if(!KIO::NetAccess::mkdir(imagesDir, kapp->activeWindow()))
+ {
+ m_progressDlg->addedAction(i18n("Could not create folder '%1'").arg(imagesDir.url()),
+ KIPI::ErrorMessage);
+ return(false);
+ }
+
+ m_progressDlg->setProgress(++m_action, m_totalActions);
+ m_progressDlg->addedAction(i18n("Directories created..."), KIPI::SuccessMessage);
+
+ return true;
+}
+
+bool SimpleViewerExport::exportImages()
+{
+ if(m_canceled)
+ return false;
+
+ m_progressDlg->addedAction(i18n("Creating images and thumbnails..."), KIPI::StartingMessage);
+
+ KURL thumbsDir(m_tempDir->name());
+ thumbsDir.addPath("/thumbs");
+
+ KURL imagesDir(m_tempDir->name());
+ imagesDir.addPath("/images");
+
+ KURL xmlFile(m_tempDir->name());
+ xmlFile.addPath("/gallery.xml");
+ QFile file(xmlFile.path());
+ file.open(IO_WriteOnly);
+
+ QDomDocument xmlDoc;
+ xmlDoc.appendChild(xmlDoc.createProcessingInstruction( QString::fromLatin1("xml"),
+ QString::fromLatin1("version=\"1.0\" encoding=\"UTF-8\"") ) );
+ QDomElement galleryElem = xmlDoc.createElement(QString::fromLatin1("simpleviewerGallery"));
+ xmlDoc.appendChild( galleryElem );
+ galleryElem.setAttribute(QString::fromLatin1("maxImageWidth"), m_configDlg->maxImageDimension());
+ galleryElem.setAttribute(QString::fromLatin1("maxImageHeight"), m_configDlg->maxImageDimension());
+ galleryElem.setAttribute(QString::fromLatin1("textColor"), m_configDlg->textColor().name().replace("#", "0x"));
+ galleryElem.setAttribute(QString::fromLatin1("frameColor"), m_configDlg->frameColor().name().replace("#", "0x"));
+ galleryElem.setAttribute(QString::fromLatin1("bgColor"), m_configDlg->backgroundColor().name().replace("#", "0x"));
+ galleryElem.setAttribute(QString::fromLatin1("frameWidth"), m_configDlg->frameWidth());
+ galleryElem.setAttribute(QString::fromLatin1("stagePadding"), m_configDlg->stagePadding());
+ galleryElem.setAttribute(QString::fromLatin1("thumbnailColumns"), m_configDlg->thumbnailColumns());
+ galleryElem.setAttribute(QString::fromLatin1("thumbnailRows"), m_configDlg->thumbnailRows());
+ galleryElem.setAttribute(QString::fromLatin1("navPosition"), m_configDlg->navPosition());
+ galleryElem.setAttribute(QString::fromLatin1("navDirection"), m_configDlg->navDirection());
+ galleryElem.setAttribute(QString::fromLatin1("title"), m_configDlg->title());
+ galleryElem.setAttribute(QString::fromLatin1("imagePath"), QString());
+ galleryElem.setAttribute(QString::fromLatin1("thumbPath"), QString());
+
+ KExiv2Iface::KExiv2 meta;
+ QImage image;
+ QImage thumbnail;
+ QString tmp;
+ QString newName;
+
+ int index = 1;
+ int maxSize = m_configDlg->imagesExportSize();
+ bool resizeImages = m_configDlg->resizeExportImages();
+
+ for( QValueList<KIPI::ImageCollection>::Iterator it = m_albumsList.begin() ;
+ !m_canceled && (it != m_albumsList.end()) ; ++it )
+ {
+ KURL::List images = (*it).images();
+
+ for(KURL::List::Iterator it = images.begin();
+ !m_canceled && (it != images.end()) ; ++it)
+ {
+ kapp->processEvents();
+ KURL url = *it;
+ QFileInfo fileInfo(url.path());
+
+ m_progressDlg->addedAction(i18n("Processing %1").arg(url.filename()), KIPI::StartingMessage);
+
+ // Check if RAW file.
+#if KDCRAW_VERSION < 0x000106
+ QString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles());
+#else
+ QString rawFilesExt(KDcrawIface::KDcraw::rawFiles());
+#endif
+ if (rawFilesExt.upper().contains( fileInfo.extension(false).upper() ))
+ KDcrawIface::KDcraw::loadDcrawPreview(image, url.path());
+ else
+ image.load(url.path());
+
+ if(image.isNull())
+ {
+ m_progressDlg->addedAction(i18n("Could not open image '%1'").arg(url.filename()),
+ KIPI::WarningMessage);
+ continue;
+ }
+
+ if(!createThumbnail(image, thumbnail))
+ {
+ m_progressDlg->addedAction(i18n("Could not create thumbnail from '%1'").arg(url.filename()),
+ KIPI::WarningMessage);
+ continue;
+ }
+
+ if(resizeImages && !resizeImage(image, maxSize, image))
+ {
+ m_progressDlg->addedAction(i18n("Could not resize image '%1'").arg(url.filename()),
+ KIPI::WarningMessage);
+ continue;
+ }
+
+ meta.load(url.path());
+ newName = QString("%1.%2").arg(tmp.sprintf("%03i", index)).arg(QString("jpg"));
+
+ KURL thumbnailPath(thumbsDir);
+ thumbnailPath.addPath(newName);
+ thumbnail.save(thumbnailPath.path(), "JPEG");
+
+ KURL imagePath(imagesDir);
+ imagePath.addPath(newName);
+ image.save(imagePath.path(), "JPEG");
+
+ // Backup metadata from original image.
+ meta.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version));
+ meta.setImageDimensions(image.size());
+ meta.save(imagePath.path());
+
+ cfgAddImage(xmlDoc, galleryElem, url, newName);
+ m_progressDlg->setProgress(++m_action, m_totalActions);
+ index++;
+ }
+ }
+
+ QCString data(xmlDoc.toCString());
+ QDataStream stream( &file );
+ stream.writeRawBytes(data.data(), data.size());
+ file.close();
+
+ m_progressDlg->addedAction(i18n("Images and thumbnails created..."), KIPI::SuccessMessage);
+
+ return true;
+}
+
+bool SimpleViewerExport::createThumbnail(const QImage &image, QImage &thumbnail)
+{
+ int w = image.width();
+ int h = image.height();
+
+ int maxSize;
+
+ if(w > maxThumbSize || h > maxThumbSize)
+ {
+ if(w > h)
+ {
+ maxSize = (int)(double)(w * maxThumbSize) / h;
+ }
+ else
+ {
+ maxSize = (int)(double)(h * maxThumbSize) / w;
+ }
+ }
+
+ maxSize = (maxSize < maxThumbSize) ? maxThumbSize : maxSize;
+
+ return resizeImage(image, maxSize, thumbnail);
+}
+
+bool SimpleViewerExport::resizeImage(const QImage &image, int maxSize, QImage &resizedImage)
+{
+ int w = image.width();
+ int h = image.height();
+
+ if(w > maxSize || h > maxSize)
+ {
+ if(w > h)
+ {
+ h = (int)(double)(h * maxSize) / w;
+ h = (h == 0) ? 1 : h;
+ w = maxSize;
+ }
+ else
+ {
+ w = (int)(double)(w * maxSize) / h;
+ w = (w == 0) ? 1 : w;
+ h = maxSize;
+ }
+ resizedImage = image.smoothScale(w, h);
+ }
+
+ return true;
+}
+
+void SimpleViewerExport::cfgAddImage(QDomDocument &xmlDoc, QDomElement &galleryElem,
+ const KURL &url, const QString& newName)
+{
+ if(m_canceled)
+ return;
+
+ QString comment;
+
+ if(m_configDlg->showExifComments())
+ {
+ KIPI::ImageInfo info = m_interface->info(url);
+ comment = info.description();
+ }
+ else
+ {
+ comment = QString();
+ }
+
+ QDomElement img = xmlDoc.createElement(QString::fromLatin1("image"));
+ galleryElem.appendChild(img);
+
+ QDomElement name = xmlDoc.createElement(QString::fromLatin1("name"));
+ img.appendChild(name);
+ QDomText nametxt = xmlDoc.createTextNode(newName);
+ name.appendChild(nametxt);
+
+ QDomElement caption = xmlDoc.createElement(QString::fromLatin1("caption"));
+ img.appendChild(caption);
+ QDomText captiontxt = xmlDoc.createTextNode(comment);
+ caption.appendChild(captiontxt);
+}
+
+bool SimpleViewerExport::createIndex()
+{
+ if(m_canceled)
+ return false;
+
+ m_progressDlg->addedAction(i18n("Creating index.html..."), KIPI::StartingMessage);
+
+ QString indexTemplateName = locate("data", "kipiplugin_simpleviewerexport/index.template");
+ if(indexTemplateName.isEmpty())
+ {
+ //TODO: errormsg
+ kdDebug() << "No indexTemplateName" << endl;
+ return false;
+ }
+
+ QFile infile(indexTemplateName);
+ infile.open(IO_ReadOnly);
+ QTextStream in(&infile);
+ QString indexTemplate = in.read();
+ infile.close();
+
+ indexTemplate.replace("{TITLE}", m_configDlg->title());
+ indexTemplate.replace("{COLOR}", m_configDlg->textColor().name());
+ indexTemplate.replace("{BGCOLOR}", m_configDlg->backgroundColor().name());
+ indexTemplate.replace("{HOSTURL}", m_hostURL);
+ indexTemplate.replace("{HOSTNAME}", m_hostName);
+
+ QFile outfile(m_tempDir->name() + "/index.html");
+ outfile.open(IO_WriteOnly);
+ QTextStream out(&outfile);
+ out << indexTemplate;
+ outfile.close();
+
+ m_progressDlg->setProgress(++m_action, m_totalActions);
+ m_progressDlg->addedAction(i18n("index.html created..."), KIPI::SuccessMessage);
+
+ return true;
+}
+
+bool SimpleViewerExport::copySimpleViewer()
+{
+ if(m_canceled)
+ return false;
+
+ m_progressDlg->addedAction(i18n("Copying flash files..."), KIPI::StartingMessage);
+
+ QString dataDir;
+
+ // Due to its license, simpleviewer is installed in $KDEHOME
+ dataDir = locate("data", "kipiplugin_simpleviewerexport/simpleviewer/");
+ if(dataDir.isEmpty())
+ installSimpleViewer();
+ if(dataDir.isEmpty())
+ return false;
+
+ QStringList files;
+ QStringList entries;
+ QDir dir;
+
+ dir.setPath(dataDir);
+ entries = dir.entryList(QDir::Files);
+ for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it)
+ {
+ files.append(dir.absPath() + "/" + *it);
+ }
+
+ // files distributed with the plugin are installed in $KDEDIRS
+ dataDir = locate("data", "kipiplugin_simpleviewerexport/simpleviewer_html/");
+ dir.setPath(dataDir);
+ entries = dir.entryList(QDir::Files);
+ for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it)
+ {
+ files.append(dir.absPath() + "/" + *it);
+ }
+ // TODO: catch errors
+ KIO::CopyJob *copyJob = KIO::copy(files, m_configDlg->exportURL(), true);
+
+ m_progressDlg->addedAction(i18n("flash files copied..."), KIPI::SuccessMessage);
+
+ return true;
+}
+
+bool SimpleViewerExport::upload()
+{
+ if(m_canceled)
+ return false;
+
+ m_progressDlg->addedAction(i18n("Uploading gallery..."), KIPI::StartingMessage);
+
+ if(!KIO::NetAccess::dircopy(m_tempDir->name() + "./", m_configDlg->exportURL(), 0))
+ return false;
+
+ m_progressDlg->addedAction(i18n("Gallery uploaded..."), KIPI::SuccessMessage);
+
+ return true;
+}
+
+bool SimpleViewerExport::checkSimpleViewer() const
+{
+ return ! locate("data", "kipiplugin_simpleviewerexport/simpleviewer/"+viewer).isEmpty();
+}
+
+bool SimpleViewerExport::installSimpleViewer()
+{
+ FirstRunDlg *firstRunDlg = new FirstRunDlg(kapp->activeWindow());
+ if(firstRunDlg->exec() == QDialog::Accepted)
+ {
+ QString url = firstRunDlg->getURL();
+ delete firstRunDlg;
+
+ if(unzip(url))
+ {
+ return true;
+ }
+ else
+ {
+ // ErrorMessage
+ }
+ }
+
+ return false;
+}
+
+bool SimpleViewerExport::unzip(const QString &url)
+{
+ KZip zip(url);
+
+ if(!openArchive(zip))
+ {
+ return false;
+ }
+
+ return extractArchive(zip);
+}
+
+bool SimpleViewerExport::openArchive(KZip &zip)
+{
+ if(!zip.open(IO_ReadOnly))
+ {
+ kdDebug() << "open archive failed\n";
+ return false;
+ }
+ return true;
+}
+
+bool SimpleViewerExport::extractArchive(KZip &zip)
+{
+ // read root directory content
+ QStringList names = zip.directory()->entries();
+ if(names.count() != 1)
+ {
+ kdDebug() << "Wrong SimpleViewer Version or corrupted archive" << endl;
+ kdDebug() << "Content of the archive root folder" << names << endl;
+ return false;
+ }
+
+ // open root directory
+ const KArchiveEntry *root = zip.directory()->entry(names[0]);
+ if(!root || !root->isDirectory())
+ {
+ kdDebug() << "could not open " << names[0] << " of zipname" << endl;
+ return false;
+ }
+
+ const KArchiveDirectory *dir = dynamic_cast<const KArchiveDirectory*>(root);
+
+ // extract the needed files from SimpleViewer archive
+ for(QStringList::Iterator it = m_simpleViewerFiles.begin();
+ it != m_simpleViewerFiles.end(); ++it )
+ {
+ const KArchiveEntry *entry = dir->entry(*it);
+ if(!extractFile(entry))
+ {
+ //TODO error msg
+ kdDebug() << "could not open " << *it << " of zipname" << endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool SimpleViewerExport::extractFile(const KArchiveEntry *entry)
+{
+ if( !entry || !entry->isFile() )
+ return false;
+
+ const KArchiveFile *entryFile = dynamic_cast<const KArchiveFile*>(entry);
+ QByteArray array = entryFile->data();
+
+ QFile file( m_dataLocal + entry->name() );
+ if(file.open( IO_WriteOnly ))
+ {
+ int ret = file.writeBlock(array);
+ file.close();
+ return ret > 0 ? true : false;
+ }
+
+ return false;
+}
+
+} // namespace KIPISimpleViewerExportPlugin
diff --git a/kipi-plugins/simpleviewerexport/simpleviewerexport.h b/kipi-plugins/simpleviewerexport/simpleviewerexport.h
new file mode 100644
index 0000000..d674b52
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/simpleviewerexport.h
@@ -0,0 +1,175 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-12-19
+ * Description : a plugin to export image collections using SimpleViewer.
+ *
+ * Copyright (C) 2005-2006 by Joern Ahrens <joern dot ahrens at kdemail dot net>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SIMPLEVIEWEREXPORT_H
+#define SIMPLEVIEWEREXPORT_H
+
+// QT includes
+
+#include <qobject.h>
+#include <qdom.h>
+
+// KIPI includes
+
+#include <libkipi/interface.h>
+
+class QTimer;
+class QString;
+class QImage;
+
+class KZip;
+class KURL;
+class KArchiveEntry;
+class KTempDir;
+
+namespace KIPI
+{
+ class BatchProgressDialog;
+}
+
+namespace KIPISimpleViewerExportPlugin
+{
+
+ class SVEDialog;
+ class FirstRunDlg;
+
+class SimpleViewerExport : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ static void run( KIPI::Interface* interface, QObject *parent=0 );
+
+private:
+
+ SimpleViewerExport( KIPI::Interface* interface, QObject *parent=0 );
+ ~SimpleViewerExport();
+
+ bool configure();
+ void startExport();
+
+ /**
+ * Creates the standard simpleviewer directories
+ *
+ * @return true=ok
+ */
+ bool createExportDirectories();
+
+ /**
+ * Creates the images and thumbnails
+ *
+ * @return true=ok
+ */
+ bool exportImages();
+
+ /**
+ * Creates a simpleviewer thumbnail from images
+ *
+ * @param image the original images
+ * @param thumbnail the created thumbnail
+ *
+ * @return true=ok
+ */
+ bool createThumbnail(const QImage &image, QImage &thumbnail);
+
+ /**
+ * Resizes the image for the gallery
+ *
+ * @param image the original images
+ * @param thumbnail the created thumbnail
+ *
+ * @return true=ok
+ */
+ bool resizeImage(const QImage &image, int maxSize, QImage &resized);
+
+ /**
+ * Adds an image to the simpleviewer config file
+ *
+ * @param xmlDoc main XML document
+ * @param galleryElem gallery XML element
+ * @param url path to original image
+ * @param newName new image file name used by gallery
+ */
+ void cfgAddImage(QDomDocument &xmlDoc, QDomElement &galleryElem,
+ const KURL &url, const QString& newName);
+
+ /**
+ * Creates the index.html file
+ */
+ bool createIndex();
+
+ /**
+ * Copies simpleviewers files into the export directory
+ */
+ bool copySimpleViewer();
+
+ /**
+ * Is the SimpleViewer flash installed?
+ */
+ bool checkSimpleViewer() const;
+
+ /**
+ * Installs the SimpleViewer files for the later export
+ * on the users machine
+ */
+ bool installSimpleViewer();
+
+ bool upload();
+
+ bool unzip(const QString &url);
+
+ bool openArchive(KZip &zip);
+
+ bool extractArchive(KZip &zip);
+
+ bool extractFile(const KArchiveEntry *entry);
+
+public slots:
+
+ void slotProcess();
+ void slotCancel();
+
+private:
+
+ int m_totalActions;
+ int m_action;
+ bool m_canceled;
+
+ QTimer *m_timer;
+ QString m_dataLocal;
+ QStringList m_simpleViewerFiles;
+ QString m_hostName;
+ QString m_hostURL;
+
+ KTempDir *m_tempDir;
+
+ SVEDialog *m_configDlg;
+ KIPI::Interface *m_interface;
+ KIPI::BatchProgressDialog *m_progressDlg;
+ QValueList<KIPI::ImageCollection> m_albumsList;
+};
+
+} // namespace KIPISimpleViewerExportPlugin
+
+#endif /* SIMPLEVIEWEREXPORT_H */
diff --git a/kipi-plugins/simpleviewerexport/space.png b/kipi-plugins/simpleviewerexport/space.png
new file mode 100644
index 0000000..471adfa
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/space.png
Binary files differ
diff --git a/kipi-plugins/simpleviewerexport/svedialog.cpp b/kipi-plugins/simpleviewerexport/svedialog.cpp
new file mode 100644
index 0000000..9029b99
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/svedialog.cpp
@@ -0,0 +1,517 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-12-19
+ * Description : a plugin to export image collections using SimpleViewer.
+ *
+ * Copyright (C) 2005-2006 by Joern Ahrens <joern dot ahrens at kdemail dot net>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT include files
+
+#include <qframe.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qcheckbox.h>
+#include <qhgroupbox.h>
+#include <qvgroupbox.h>
+#include <qcombobox.h>
+#include <qhbox.h>
+#include <qvbox.h>
+
+// KDE include files
+
+#include <klineedit.h>
+#include <klocale.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kcolorbutton.h>
+#include <kurlrequester.h>
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kapplication.h>
+
+// KIPI include files
+
+#include <libkipi/imagecollectionselector.h>
+
+// Local include files
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "svedialog.h"
+#include "svedialog.moc"
+
+namespace KIPISimpleViewerExportPlugin
+{
+
+SVEDialog::SVEDialog(KIPI::Interface* interface, QWidget *parent)
+ : KDialogBase( IconList, i18n("Flash Export"), Help|Ok|Cancel, Ok,
+ parent, "SimpleViewerExportDialog", true, true ),
+ m_interface( interface )
+{
+ selectionPage();
+ generalPage();
+ lookPage();
+
+ readConfig();
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Flash Export"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to export images to Flash using Simple Viewer component"),
+ "(c) 2005-2006, Joern Ahrens\n"
+ "(c) 2008, Gilles Caulier");
+
+ m_about->addAuthor("Joern Ahrens",
+ I18N_NOOP("Author and maintainer"),
+ "joern dot ahrens at kdemail dot net");
+
+ m_about->addAuthor("Gilles Caulier",
+ I18N_NOOP("Developer and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ m_about->addCredit("Felix Turner",
+ "Author of the Simple Viewer Flash component",
+ 0,
+ "http://www.airtightinteractive.com/simpleviewer");
+
+ m_about->addCredit("Mikkel B. Stegmann",
+ "Basis for the index.html template",
+ 0,
+ "http://www.stegmann.dk/mikkel/porta");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"),
+ this, SLOT(slotHelp()), 0, -1, 0);
+ actionButton(Help)->setPopup( helpMenu->menu() );
+}
+
+SVEDialog::~SVEDialog()
+{
+ delete m_about;
+}
+
+void SVEDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("simpleviewerexport", "kipi-plugins");
+}
+
+void SVEDialog::readConfig()
+{
+ KConfig config("kipirc");
+
+ setThumbnailRows(config.readNumEntry("thumbnailRows", 3));
+ setThumbnailColumns(config.readNumEntry("thumbnailColumns", 3));
+ m_navPosition->setCurrentItem(config.readNumEntry("navPosition", 1));
+ m_navDirection->setCurrentItem(config.readNumEntry("navDirection", 1));
+ setTextColor(QColor(config.readEntry("textColor", "#ffffff")));
+ setBackgroundColor(QColor(config.readEntry("backgroundColor", "#181818")));
+ setFrameColor(QColor(config.readEntry("frameColor", "#ffffff")));
+ setFrameWidth(config.readNumEntry("frameWidth", 1));
+ setStagePadding(config.readNumEntry("stagePadding", 20));
+ setTitle(config.readEntry("title", QString()));
+ m_exportURL->setURL(config.readPathEntry("exporturl", KGlobalSettings::documentPath() + "simpleviewer"));
+ setResizeExportImages(config.readBoolEntry("resizeExportImages", true));
+ setImagesExportSize(config.readNumEntry("imagesExportSize", 640));
+ setMaxImagesDimension(config.readNumEntry("maxImageDimension", 640));
+ setShowExifComments(config.readBoolEntry("showExifComments", true));
+
+ resize(configDialogSize(config, QString("SimpleViewerExport Dialog")));
+}
+
+void SVEDialog::writeConfig()
+{
+ KConfig config("kipirc");
+ config.writeEntry("thumbnailRows", thumbnailRows());
+ config.writeEntry("thumbnailColumns", thumbnailColumns());
+ config.writeEntry("navPosition", m_navPosition->currentItem());
+ config.writeEntry("navDirection", m_navDirection->currentItem());
+ config.writeEntry("textColor", textColor().name());
+ config.writeEntry("backgroundColor", backgroundColor().name());
+ config.writeEntry("frameColor", frameColor().name());
+ config.writeEntry("frameWidth", frameWidth());
+ config.writeEntry("stagePadding", stagePadding());
+ config.writePathEntry("exporturl", exportURL());
+ config.writeEntry("title", title());
+ config.writeEntry("resizeExportImages", resizeExportImages());
+ config.writeEntry("imagesExportSize", imagesExportSize());
+ config.writeEntry("maxImageDimension", maxImageDimension());
+ config.writeEntry("showExifComments", showExifComments());
+
+ saveDialogSize(config, QString("GPS Sync Dialog"));
+ config.sync();
+}
+
+void SVEDialog::selectionPage()
+{
+ m_selectionPage = addPage(i18n("Selection"), i18n("Album Selection"),
+ BarIcon("folder_image", KIcon::SizeMedium));
+
+ QVBoxLayout *layout = new QVBoxLayout( m_selectionPage, 0, spacingHint() );
+ m_imageCollectionSelector = new KIPI::ImageCollectionSelector( m_selectionPage, m_interface );
+ layout->addWidget(m_imageCollectionSelector);
+}
+
+void SVEDialog::lookPage()
+{
+ m_lookPage = addPage(i18n("Look"), i18n("Page Look"),
+ BarIcon("colors", KIcon::SizeMedium));
+
+ QVBoxLayout *mainLayout = new QVBoxLayout(m_lookPage, 0, spacingHint());
+ QVGroupBox *vgroupbox;
+ QHBox *hbox;
+ QLabel *label;
+
+ // ------------------------------------------------------------------------
+
+ vgroupbox = new QVGroupBox(i18n("Navigation"), m_lookPage);
+ mainLayout->addWidget(vgroupbox);
+
+ m_thumbnailRows = new KIntNumInput(3, vgroupbox);
+ m_thumbnailRows->setRange(1, 10, 1, true);
+ m_thumbnailRows->setLabel(i18n("Thumbnail &Rows:"), AlignVCenter);
+ QWhatsThis::add(m_thumbnailRows, i18n("<p>Number of thumbnails rows"));
+
+ // ------------------------------------------------------------------------
+
+ m_thumbnailColumns = new KIntNumInput(3, vgroupbox);
+ m_thumbnailColumns->setRange(1, 10, 1, true);
+ m_thumbnailColumns->setLabel(i18n("Thumbnail &Columns:"), AlignVCenter);
+ QWhatsThis::add(m_thumbnailColumns, i18n("<p>Number of thumbnails columns"));
+
+ // ------------------------------------------------------------------------
+
+ hbox = new QHBox(vgroupbox);
+ label = new QLabel(i18n("Thumbnail &Position:"), hbox);
+ m_navPosition = new QComboBox(false, hbox);
+ m_navPosition->insertItem(i18n("Right"));
+ m_navPosition->insertItem(i18n("Left"));
+ m_navPosition->insertItem(i18n("Top"));
+ m_navPosition->insertItem(i18n("Bottom"));
+ m_navPosition->setCurrentText(i18n("Right"));
+ label->setBuddy(m_navPosition);
+
+ // ------------------------------------------------------------------------
+
+ hbox = new QHBox(vgroupbox);
+ label = new QLabel(i18n("&Direction of Navigation:"), hbox);
+ m_navDirection = new QComboBox(false, hbox);
+ m_navDirection->insertItem(i18n("Left to Right"));
+ m_navDirection->insertItem(i18n("Right to Left"));
+ m_navDirection->setCurrentText(i18n("Left to Right"));
+ label->setBuddy(m_navDirection);
+
+ // ------------------------------------------------------------------------
+
+ vgroupbox = new QVGroupBox(i18n("Colors"), m_lookPage);
+ mainLayout->addWidget(vgroupbox);
+
+ hbox = new QHBox(vgroupbox);
+ label = new QLabel(i18n("&Text Color:"), hbox);
+ m_textColor = new KColorButton(QColor("#ffffff"), hbox);
+ label->setBuddy(m_textColor);
+
+ // ------------------------------------------------------------------------
+
+ hbox = new QHBox(vgroupbox);
+ label = new QLabel(i18n("&Background Color:"), hbox);
+ m_backgroundColor = new KColorButton(QColor("#181818"), hbox);
+ label->setBuddy(m_backgroundColor);
+
+ // ------------------------------------------------------------------------
+
+ hbox = new QHBox(vgroupbox);
+ label = new QLabel(i18n("&Frame Color:"), hbox);
+ m_frameColor = new KColorButton(QColor("#ffffff"), hbox);
+ label->setBuddy(m_frameColor);
+
+ // ------------------------------------------------------------------------
+
+ vgroupbox = new QVGroupBox(i18n("Style"), m_lookPage);
+ mainLayout->addWidget(vgroupbox);
+
+ m_frameWidth = new KIntNumInput(3, vgroupbox);
+ m_frameWidth->setRange(0, 10, 1, true);
+ m_frameWidth->setLabel(i18n("Frame &Width:"), AlignVCenter);
+ QWhatsThis::add(m_frameWidth, i18n("<p>Width of image frame in pixels."));
+
+ // ------------------------------------------------------------------------
+
+ m_stagePadding = new KIntNumInput(20, vgroupbox);
+ m_stagePadding->setRange(1, 100, 1, true);
+ m_stagePadding->setLabel(i18n("Stage &Padding:"), AlignVCenter);
+ QWhatsThis::add(m_stagePadding, i18n("<p>Stage Padding: Distance between image and thumbnails in pixels."));
+
+ mainLayout->addStretch(1);
+}
+
+void SVEDialog::generalPage()
+{
+ m_generalPage = addPage(i18n("General"), i18n("General Setup"),
+ BarIcon("html", KIcon::SizeMedium));
+
+ QVBoxLayout *mainLayout = new QVBoxLayout(m_generalPage, 0, spacingHint());
+
+ QHGroupBox *hgroupbox;
+ QVGroupBox *vgroupbox;
+
+ // ------------------------------------------------------------------------
+
+ hgroupbox = new QHGroupBox(i18n("Gallery &Title"), m_generalPage);
+ mainLayout->addWidget(hgroupbox);
+
+ m_title = new KLineEdit(hgroupbox);
+ QWhatsThis::add(m_title, i18n("<p>Enter here the gallery title"));
+
+ // ------------------------------------------------------------------------
+
+ vgroupbox = new QVGroupBox(i18n("Save Gallery To"), m_generalPage);
+ mainLayout->addWidget(vgroupbox);
+ m_exportURL = new KURLRequester(KGlobalSettings::documentPath() + "simpleviewer", vgroupbox);
+ m_exportURL->setMode(KFile::Directory | KFile::LocalOnly);
+
+ // ------------------------------------------------------------------------
+
+ vgroupbox = new QVGroupBox(i18n("Image Size"), m_generalPage);
+ mainLayout->addWidget(vgroupbox);
+
+ m_resizeExportImages = new QCheckBox(i18n("Resize Target Images"), vgroupbox);
+ m_resizeExportImages->setChecked(true);
+ QWhatsThis::add(m_resizeExportImages, i18n("<p>If you enable this option, "
+ "all target images can be resized.") );
+
+ m_imagesExportSize = new KIntNumInput(640, vgroupbox);
+ m_imagesExportSize->setRange(200, 2000, 1, true );
+ m_imagesExportSize->setLabel(i18n("&Target Images Size:"), AlignVCenter);
+ QWhatsThis::add(m_imagesExportSize, i18n("<p>The new size of the exported images in pixels. "
+ "SimpleViewer resizes the images as well, but this "
+ "resizes your images before they are uploaded to your server"));
+ connect(m_resizeExportImages, SIGNAL(toggled(bool)),
+ m_imagesExportSize, SLOT(setEnabled(bool)));
+
+ // ------------------------------------------------------------------------
+
+ m_maxImageDimension = new KIntNumInput(m_imagesExportSize, 640, vgroupbox);
+ m_maxImageDimension->setRange(200, 2000, 1, true );
+ m_maxImageDimension->setLabel(i18n("&Displayed Images Size:"), AlignVCenter);
+ QWhatsThis::add(m_maxImageDimension, i18n("<p>scales the displayed images to this size. "
+ "Largest height or width of your largest image (in pixels). "
+ "Images will not be scaled up above this size, to ensure best image quality."));
+
+ // ------------------------------------------------------------------------
+
+ vgroupbox = new QVGroupBox(i18n("Misc"), m_generalPage);
+ mainLayout->addWidget(vgroupbox);
+
+ m_showExifComments = new QCheckBox(i18n("Display Captions"), vgroupbox);
+ m_showExifComments->setChecked(true);
+ QWhatsThis::add(m_showExifComments, i18n("<p>If you enable this option, "
+ "the images caption will be shown"));
+
+ mainLayout->addStretch(1);
+}
+
+
+void SVEDialog::slotOk()
+{
+ m_selectedAlbums = m_imageCollectionSelector->selectedImageCollections();
+
+ if (m_selectedAlbums.size() == 0)
+ {
+ KMessageBox::sorry(this, i18n("You must select at least one album."));
+ return;
+ }
+ writeConfig();
+ accept();
+}
+
+QValueList<KIPI::ImageCollection> SVEDialog::getSelectedAlbums() const
+{
+ return m_selectedAlbums;
+}
+
+void SVEDialog::setTitle(const QString &title)
+{
+ m_title->setText(title);
+}
+
+QString SVEDialog::title() const
+{
+ return m_title->text();
+}
+
+bool SVEDialog::resizeExportImages() const
+{
+ return m_resizeExportImages->isChecked();
+}
+
+void SVEDialog::setResizeExportImages(bool resize)
+{
+ m_resizeExportImages->setChecked(resize);
+}
+
+int SVEDialog::imagesExportSize() const
+{
+ return m_imagesExportSize->value();
+}
+
+void SVEDialog::setImagesExportSize(int size)
+{
+ m_imagesExportSize->setValue(size);
+}
+
+int SVEDialog::maxImageDimension() const
+{
+ return m_maxImageDimension->value();
+}
+
+void SVEDialog::setMaxImagesDimension(int size)
+{
+ m_maxImageDimension->setValue(size);
+}
+
+bool SVEDialog::showExifComments() const
+{
+ return m_showExifComments->isChecked();
+}
+
+void SVEDialog::setShowExifComments(bool show)
+{
+ m_showExifComments->setChecked(show);
+}
+
+QString SVEDialog::exportURL() const
+{
+ return m_exportURL->url();
+}
+
+int SVEDialog::thumbnailRows() const
+{
+ return m_thumbnailRows->value();
+}
+
+void SVEDialog::setThumbnailRows(int rows)
+{
+ m_thumbnailRows->setValue(rows);
+}
+
+int SVEDialog::thumbnailColumns() const
+{
+ return m_thumbnailColumns->value();
+}
+
+void SVEDialog::setThumbnailColumns(int columns)
+{
+ m_thumbnailColumns->setValue(columns);
+}
+
+int SVEDialog::frameWidth() const
+{
+ return m_frameWidth->value();
+}
+
+void SVEDialog::setFrameWidth(int width)
+{
+ m_frameWidth->setValue(width);
+}
+
+int SVEDialog::stagePadding() const
+{
+ return m_stagePadding->value();
+}
+
+void SVEDialog::setStagePadding(int stagePadding)
+{
+ m_stagePadding->setValue(stagePadding);
+}
+
+QColor SVEDialog::textColor() const
+{
+ return m_textColor->color();
+}
+
+void SVEDialog::setTextColor(const QColor &color)
+{
+ m_textColor->setColor(color);
+}
+
+QColor SVEDialog::frameColor() const
+{
+ return m_frameColor->color();
+}
+
+void SVEDialog::setFrameColor(const QColor &color)
+{
+ m_frameColor->setColor(color);
+}
+
+QColor SVEDialog::backgroundColor() const
+{
+ return m_backgroundColor->color();
+}
+
+void SVEDialog::setBackgroundColor(const QColor &color)
+{
+ m_backgroundColor->setColor(color);
+}
+
+QString SVEDialog::navDirection() const
+{
+ if(m_navDirection->currentText() == i18n("Left to Right"))
+ return "LTR";
+ else
+ return "RTL";
+}
+
+void SVEDialog::setNavDirection(const QString &direction)
+{
+ if(direction == "LTR")
+ m_navDirection->setCurrentText(i18n("Left to Right"));
+ else
+ m_navDirection->setCurrentText(i18n("Right to Left"));
+}
+
+QString SVEDialog::navPosition() const
+{
+ QString pos = m_navPosition->currentText();
+
+ if(pos == i18n("Top"))
+ return "top";
+ else if(pos == i18n("Bottom"))
+ return "bottom";
+ else if(pos == i18n("Left"))
+ return "left";
+ else
+ return "right";
+}
+
+void SVEDialog::setNavPosition(const QString &pos)
+{
+ m_navPosition->setCurrentText(pos);
+}
+
+} // namespace KIPISimpleViewerExportPlugin
diff --git a/kipi-plugins/simpleviewerexport/svedialog.h b/kipi-plugins/simpleviewerexport/svedialog.h
new file mode 100644
index 0000000..5480d3e
--- /dev/null
+++ b/kipi-plugins/simpleviewerexport/svedialog.h
@@ -0,0 +1,157 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2005-12-19
+ * Description : a plugin to export image collections using SimpleViewer.
+ *
+ * Copyright (C) 2005-2006 by Joern Ahrens <joern dot ahrens at kdemail dot net>
+ * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SVEDIALOG_H
+#define SVEDIALOG_H
+
+// Include files for KDE
+
+#include <kdialogbase.h>
+
+// Include files for KIPI
+
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "kpaboutdata.h"
+
+class QFrame;
+class QCheckBox;
+class QComboBox;
+
+class KLineEdit;
+class KIntNumInput;
+class KColorButton;
+class KURLRequester;
+class KConfig;
+
+namespace KIPI
+{
+ class ImageCollectionSelector;
+}
+
+namespace KIPISimpleViewerExportPlugin
+{
+
+class SVEDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ SVEDialog( KIPI::Interface* interface, QWidget *parent=0);
+ ~SVEDialog();
+
+ void readConfig();
+ void writeConfig();
+
+ void slotOk();
+ QValueList<KIPI::ImageCollection> getSelectedAlbums() const;
+
+ QString title() const;
+ void setTitle(const QString &title);
+
+ bool resizeExportImages() const;
+ void setResizeExportImages(bool resize);
+
+ int imagesExportSize() const;
+ void setImagesExportSize(int size);
+
+ int maxImageDimension() const;
+ void setMaxImagesDimension(int size);
+
+ bool showExifComments() const;
+ void setShowExifComments(bool show);
+
+ int thumbnailRows() const;
+ void setThumbnailRows(int rows);
+
+ int thumbnailColumns() const;
+ void setThumbnailColumns(int columns);
+
+ int frameWidth() const;
+ void setFrameWidth(int width);
+
+ int stagePadding() const;
+ void setStagePadding(int stagePadding);
+
+ QColor textColor() const;
+ void setTextColor(const QColor &color);
+
+ QColor frameColor() const;
+ void setFrameColor(const QColor &color);
+
+ QColor backgroundColor() const;
+ void setBackgroundColor(const QColor &color);
+
+ QString navDirection() const;
+ void setNavDirection(const QString &direction);
+
+ QString navPosition() const;
+ void setNavPosition(const QString &pos);
+
+ QString exportURL() const;
+
+private:
+
+ void selectionPage();
+ void generalPage();
+ void lookPage();
+
+private slots:
+
+ void slotHelp();
+
+private:
+
+ QFrame *m_selectionPage;
+ QFrame *m_generalPage;
+ QFrame *m_lookPage;
+
+ QCheckBox *m_resizeExportImages;
+ QCheckBox *m_showExifComments;
+ QComboBox *m_navPosition;
+ QComboBox *m_navDirection;
+
+ KLineEdit *m_title;
+ KIntNumInput *m_imagesExportSize;
+ KIntNumInput *m_maxImageDimension;
+ KIntNumInput *m_thumbnailRows;
+ KIntNumInput *m_thumbnailColumns;
+ KColorButton *m_textColor;
+ KColorButton *m_backgroundColor;
+ KColorButton *m_frameColor;
+ KIntNumInput *m_frameWidth;
+ KIntNumInput *m_stagePadding;
+ KURLRequester *m_exportURL;
+
+ KIPI::Interface *m_interface;
+ KIPI::ImageCollectionSelector *m_imageCollectionSelector;
+ KIPIPlugins::KPAboutData *m_about;
+ QValueList<KIPI::ImageCollection> m_selectedAlbums;
+};
+
+} // namespace KIPISimpleViewerExportPlugin
+
+#endif /* SVEDIALOG_H */
diff --git a/kipi-plugins/slideshow/Makefile.am b/kipi-plugins/slideshow/Makefile.am
new file mode 100644
index 0000000..9982df4
--- /dev/null
+++ b/kipi-plugins/slideshow/Makefile.am
@@ -0,0 +1,30 @@
+METASOURCES = AUTO
+
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKIPI_CFLAGS) \
+ $(LIBKDCRAW_CFLAGS) $(all_includes)
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_slideshow.la
+
+kipiplugin_slideshow_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKDCRAW_LIBS_DEP)
+
+kipiplugin_slideshow_la_SOURCES = listimageitems.cpp plugin_slideshow.cpp \
+ slideshow.cpp slideshowconfig.cpp slideshowconfigbase.ui slideshowgl.cpp \
+ slideshowloader.cpp toolbar.cpp imageloadthread.cpp kbeffect.cpp screenproperties.cpp \
+ slideshowkb.cpp
+
+#kipiplugin_slideshow_la_LIBADD = -lkdefx $(GL_LIBS) $(LIBKIPI_LIBS) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+kipiplugin_slideshow_la_LIBADD = -lkdefx -lXrandr $(GL_LIBS) $(LIBKIPI_LIBS) $(LIBKDCRAW_LIBS) \
+ $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_KIO) $(LIB_QT)
+
+kipiplugin_slideshow_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+kde_services_DATA = kipiplugin_slideshow.desktop
+
+kipiplugin_slideshowicondir = $(kde_datadir)/kipiplugin_slideshow/icons
+kipiplugin_slideshowicon_ICON = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_slideshow.pot
+
+
diff --git a/kipi-plugins/slideshow/hi22-action-slideshow.png b/kipi-plugins/slideshow/hi22-action-slideshow.png
new file mode 100644
index 0000000..73a0952
--- /dev/null
+++ b/kipi-plugins/slideshow/hi22-action-slideshow.png
Binary files differ
diff --git a/kipi-plugins/slideshow/imageloadthread.cpp b/kipi-plugins/slideshow/imageloadthread.cpp
new file mode 100644
index 0000000..36f40c8
--- /dev/null
+++ b/kipi-plugins/slideshow/imageloadthread.cpp
@@ -0,0 +1,180 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qdir.h>
+#include <qvaluevector.h>
+#include <qdeepcopy.h>
+#include <qwmatrix.h>
+#include <qobject.h>
+
+// KDE includes.
+
+#include <klocale.h>
+
+// Local includes.
+
+#include "slideshowkb.h"
+#include "imageloadthread.h"
+#include "imageloadthread.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+ImageLoadThread::ImageLoadThread(QValueList<QPair<QString, int> >& fileList,
+ int width, int height)
+{
+
+ m_initialized = false;
+ m_needImage = true;
+ m_haveImages = false;
+ m_quitRequested = false;
+
+ m_fileIndex = 0;
+ m_fileList = fileList;
+
+ m_width = width;
+ m_height = height;
+}
+
+void ImageLoadThread::quit() {
+
+ QMutexLocker locker(&m_condLock);
+
+ m_quitRequested = true;
+ m_imageRequest.wakeOne();
+}
+
+void ImageLoadThread::requestNewImage() {
+
+ QMutexLocker locker(&m_condLock);
+
+ if ( !m_needImage) {
+ m_needImage = true;
+ m_imageRequest.wakeOne();
+ }
+}
+
+void ImageLoadThread::run() {
+
+ QMutexLocker locker(&m_condLock);
+
+ // we enter the loop with m_needImage==true, so we will immediatly
+ // try to load an image
+
+ while (true) {
+
+ if (m_quitRequested)
+ break;
+
+ if (m_needImage) {
+
+ if ( m_fileIndex == (int)m_fileList.count() )
+ {
+ m_needImage = false;
+ emit(endOfShow());
+ continue;
+ }
+
+ m_needImage = false;
+ m_condLock.unlock();
+
+ bool ok;
+ do {
+ ok = loadImage();
+ if ( !ok)
+ invalidateCurrentImageName();
+ } while ( !ok && m_fileIndex < (int)m_fileList.count());
+
+ if ( m_fileIndex == (int)m_fileList.count() )
+ {
+
+ emit(endOfShow());
+ m_condLock.lock();
+ continue;
+ }
+
+ if ( !ok) {
+ // generate a black dummy image
+ m_texture = QImage(128, 128, 32);
+ m_texture.fill(Qt::black.rgb());
+ }
+
+ m_condLock.lock();
+
+ m_fileIndex++;
+
+ if ( !m_initialized) {
+ m_haveImages = ok;
+ m_initialized = true;
+ }
+
+ } else {
+ // wait for new requests from the consumer
+ m_imageRequest.wait(&m_condLock);
+ }
+ }
+}
+
+bool ImageLoadThread::loadImage() {
+
+ QPair<QString, int> fileAngle = m_fileList[m_fileIndex];
+ QString path(fileAngle.first);
+ int angle(fileAngle.second);
+ QImage image(path);
+ if (angle != 0)
+ {
+ QWMatrix wm;
+ wm.rotate(angle);
+ image = image.xForm(wm);
+ }
+
+ if (image.isNull()) {
+ return false;
+ }
+
+ float aspect = (float)image.width() / (float)image.height();
+
+ image = image.smoothScale(m_width, m_height, QImage::ScaleMin);
+
+ m_imageLock.lock();
+
+ // this is the critical moment, when we make the new texture and
+ // aspect available to the consumer
+ m_textureAspect = aspect;
+ m_texture = QGLWidget::convertToGLFormat(image);
+
+ m_imageLock.unlock();
+
+ return true;
+}
+
+void ImageLoadThread::invalidateCurrentImageName() {
+ m_fileList.remove(m_fileList[m_fileIndex]);
+ m_fileIndex++;
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/imageloadthread.h b/kipi-plugins/slideshow/imageloadthread.h
new file mode 100644
index 0000000..41c5386
--- /dev/null
+++ b/kipi-plugins/slideshow/imageloadthread.h
@@ -0,0 +1,88 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 IMAGELOADTHREAD_H
+#define IMAGELOADTHREAD_H
+
+// QT includes.
+
+#include <qimage.h>
+#include <qthread.h>
+#include <qwaitcondition.h>
+#include <qmutex.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qstring.h>
+#include <qobject.h>
+
+namespace KIPISlideShowPlugin
+{
+
+class ImageLoadThread : public QObject, public QThread
+{
+
+Q_OBJECT
+
+public:
+
+ ImageLoadThread(QValueList<QPair<QString, int> >& fileList, int width, int height);
+
+ void quit();
+ void requestNewImage();
+ bool grabImage() { m_imageLock.lock(); return m_haveImages; };
+ void ungrabImage() { m_imageLock.unlock(); };
+ bool ready() { return m_initialized; };
+ const QImage &image() { return m_texture; };
+ float imageAspect() { return m_textureAspect; };
+
+signals:
+
+ void endOfShow();
+
+protected:
+
+ void run();
+
+ bool loadImage();
+ void invalidateCurrentImageName();
+
+private:
+
+ int m_fileIndex;
+ QValueList<QPair<QString, int> > m_fileList;
+
+ int m_width, m_height;
+
+ QWaitCondition m_imageRequest;
+ QMutex m_condLock, m_imageLock;
+ bool m_initialized, m_needImage, m_haveImages, m_quitRequested, m_scanSubdirectories;
+
+ float m_textureAspect;
+ QImage m_texture;
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // IMAGELOADTHREAD_H
diff --git a/kipi-plugins/slideshow/kbeffect.cpp b/kipi-plugins/slideshow/kbeffect.cpp
new file mode 100644
index 0000000..891a6fe
--- /dev/null
+++ b/kipi-plugins/slideshow/kbeffect.cpp
@@ -0,0 +1,192 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <assert.h>
+
+// Qt includes.
+
+#include <qdatetime.h>
+
+// KDE includes.
+
+#include "kbeffect.h"
+
+// Local includes.
+
+#include "slideshowkb.h"
+
+namespace KIPISlideShowPlugin
+{
+
+// -------------------------------------------------------------------------
+
+int KBEffect::m_numKBEffectRepeated = 0;
+
+// -------------------------------------------------------------------------
+
+KBEffect::KBEffect(SlideShowKB *parent, bool needFadeIn) {
+
+ this->slideWidget = parent;
+ this->m_needFadeIn = needFadeIn;
+}
+
+
+KBEffect::~KBEffect() {
+
+}
+
+
+void KBEffect::setupNewImage(int img) {
+
+ slideWidget->setupNewImage(img);
+}
+
+
+void KBEffect::swapImages() {
+
+ slideWidget->swapImages();
+}
+
+
+Image *KBEffect::image(int img) {
+
+ assert(img >= 0 && img < 2);
+ return slideWidget->m_image[img];
+}
+
+
+KBEffect::Type KBEffect::chooseKBEffect(KBEffect::Type oldType) {
+
+ KBEffect::Type type;
+
+ do {
+ type = (rand() < RAND_MAX / 2) ? KBEffect::Fade : KBEffect::Blend;
+ } while (type == oldType && m_numKBEffectRepeated >= 1);
+
+ if (type == oldType)
+ m_numKBEffectRepeated++;
+ else
+ m_numKBEffectRepeated = 0;
+
+ return type;
+}
+
+
+
+// -------------------------------------------------------------------------
+
+FadeKBEffect::FadeKBEffect(SlideShowKB *parent, bool needFadeIn):
+ KBEffect(parent, needFadeIn)
+{
+ m_img[0] = image(0);
+}
+
+
+FadeKBEffect::~FadeKBEffect() {
+
+}
+
+
+bool FadeKBEffect::done() {
+
+ if (m_img[0]->m_pos >= 1.0) {
+ setupNewImage(0);
+ return true;
+ }
+
+ return false;
+}
+
+
+void FadeKBEffect::advanceTime(float step) {
+
+ m_img[0]->m_pos += step;
+ if (m_img[0]->m_pos >= 1.0)
+ m_img[0]->m_pos = 1.0;
+
+ if (m_needFadeIn && m_img[0]->m_pos < 0.1)
+ m_img[0]->m_opacity = m_img[0]->m_pos * 10;
+ else if (m_img[0]->m_pos > 0.9)
+ m_img[0]->m_opacity = (1.0 - m_img[0]->m_pos) * 10;
+ else
+ m_img[0]->m_opacity = 1.0;
+}
+
+// -------------------------------------------------------------------------
+
+BlendKBEffect::BlendKBEffect(SlideShowKB *parent, bool needFadeIn):
+ KBEffect(parent, needFadeIn)
+{
+ m_img[0] = image(0);
+ m_img[1] = 0;
+}
+
+
+BlendKBEffect::~BlendKBEffect() {
+
+}
+
+
+bool BlendKBEffect::done() {
+
+ if (m_img[0]->m_pos >= 1.0) {
+ m_img[0]->m_paint = false;
+ swapImages();
+ return true;
+ }
+
+ return false;
+}
+
+
+void BlendKBEffect::advanceTime(float step) {
+
+ m_img[0]->m_pos += step;
+ if (m_img[0]->m_pos >= 1.0)
+ m_img[0]->m_pos = 1.0;
+
+ if (m_img[1])
+ m_img[1]->m_pos += step;
+
+ if (m_needFadeIn && m_img[0]->m_pos < 0.1)
+ m_img[0]->m_opacity = m_img[0]->m_pos * 10;
+
+ else if (m_img[0]->m_pos > 0.9) {
+
+ m_img[0]->m_opacity = (1.0 - m_img[0]->m_pos) * 10;
+
+ if (m_img[1] == 0) {
+ setupNewImage(1);
+ m_img[1] = image(1);
+ m_img[1]->m_opacity = 1.0;
+ }
+
+ } else
+ m_img[0]->m_opacity = 1.0;
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/kbeffect.h b/kipi-plugins/slideshow/kbeffect.h
new file mode 100644
index 0000000..029efb5
--- /dev/null
+++ b/kipi-plugins/slideshow/kbeffect.h
@@ -0,0 +1,101 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 KBEFFECT_H
+#define KBEFFECT_H
+
+namespace KIPISlideShowPlugin
+{
+
+class Image;
+class SlideShowKB;
+
+class KBEffect
+{
+
+public:
+
+ typedef enum { Fade, Blend } Type;
+
+ KBEffect(SlideShowKB *parent, bool m_needFadeIn = true);
+ virtual ~KBEffect();
+
+ virtual void advanceTime(float step) = 0;
+ virtual Type type() = 0;
+ virtual bool done() = 0;
+ virtual bool fadeIn() const { return m_needFadeIn; };
+
+ static Type chooseKBEffect(Type oldType);
+
+protected:
+
+ void setupNewImage(int img);
+ void swapImages();
+ Image *image(int img);
+
+protected:
+
+ static int m_numKBEffectRepeated;
+ bool m_needFadeIn;
+ Image *m_img[2];
+
+private:
+
+ SlideShowKB *slideWidget;
+};
+
+// -------------------------------------------------------------------------
+
+class FadeKBEffect: public KBEffect
+{
+
+public:
+
+ FadeKBEffect(SlideShowKB *parent, bool m_needFadeIn = true);
+ virtual ~FadeKBEffect();
+
+ virtual void advanceTime(float step);
+ virtual Type type() { return Fade; };
+ virtual bool done();
+};
+
+// -------------------------------------------------------------------------
+
+class BlendKBEffect: public KBEffect
+{
+
+public:
+
+ BlendKBEffect(SlideShowKB *parent, bool m_needFadeIn = true);
+ virtual ~BlendKBEffect();
+
+ virtual void advanceTime(float step);
+ virtual Type type() { return Blend; };
+ virtual bool done();
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // KBEFFECT_H
diff --git a/kipi-plugins/slideshow/kipiplugin_slideshow.desktop b/kipi-plugins/slideshow/kipiplugin_slideshow.desktop
new file mode 100644
index 0000000..23a3a8c
--- /dev/null
+++ b/kipi-plugins/slideshow/kipiplugin_slideshow.desktop
@@ -0,0 +1,60 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=SlideShow
+Name[br]=Diskouezadur skeudennoù
+Name[ca]=Passi de dispositives
+Name[cs]=Prezentace
+Name[cy]=Sioe Tryloywderau
+Name[da]=Lysbilledshow
+Name[de]=Diashow
+Name[el]=ΠροβολήΣλάιντ
+Name[es]=Presentación
+Name[et]=Slaidiseanss
+Name[fi]=Kuvasarja
+Name[gl]=Apresentazón
+Name[it]=Presentazione
+Name[nds]=Diaschau
+Name[nl]=Diavoorstelling
+Name[pa]=ਸਲਾਇਡਸ਼ੋ
+Name[pl]=Pokaz slajdów
+Name[pt]=Apresentação
+Name[sr]=Слајд шоу
+Name[sr@Latn]=Slajd šou
+Name[sv]=Bildspel
+Name[tg]=НамоишиСлайд
+Name[th]=นำเสนอภาพ
+Name[tr]=SlaytGösterisi
+Name[xx]=xxSlideShowxx
+Name[zh_CN]=幻灯片
+Comment=KIPI SlideShow Plugin
+Comment[br]=Lugent diskouezadur skeudennoù KIPI
+Comment[ca]=Connector del KIPI de passi de diapositives
+Comment[cs]=KIPI modul prezentace
+Comment[da]=KIPI-plugin: Lysbilledshow
+Comment[de]=Ein KIPI-Modul zur Erstellung von Bildschirmpräsentationen
+Comment[el]=Πρόσθετο του KIPI για προβολή σλάιντ
+Comment[es]=Complemento de KIPI para presentaciones
+Comment[et]=KIPI slaidiseansi plugin
+Comment[fi]=Kipi-liitännäinen kuvasarjojen esityksiä varten
+Comment[fr]=Module externe KIPI pour faire un diaporama
+Comment[gl]=Plugin de KIPI para Apresentazóns
+Comment[it]=Plugin di presentazione di KIPI
+Comment[ja]=Kipi スライドショープラグイン
+Comment[nds]=KIPI-Moduul för Diaschauen
+Comment[nl]=KIPI-plugin voor diavoorstellingen
+Comment[pa]=KIPI ਸਲਾਇਡਸ਼ੋ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Pokaz slajdów
+Comment[pt]='Plugin' do KIPI para Apresentações
+Comment[pt_BR]=Plugin de Show de Slides do KIPI
+Comment[sr]=KIPI прикључак за слајд шоу
+Comment[sr@Latn]=KIPI priključak za slajd šou
+Comment[sv]=KIPI-insticksprogram: Bildspel
+Comment[tg]=Модули KIPI барои НамоишиСлайд
+Comment[tr]=KIPI Slayt Gösterisi Eklentisi
+Comment[xx]=xxKIPI SlideShow Pluginxx
+Comment[zh_CN]=KIPI 幻灯片插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_slideshow
+X-KIPI-MergeMenu=true
+author=Renchi Raju, renchi@pooh.tam.uiuc.edu
diff --git a/kipi-plugins/slideshow/listimageitems.cpp b/kipi-plugins/slideshow/listimageitems.cpp
new file mode 100644
index 0000000..7202b8f
--- /dev/null
+++ b/kipi-plugins/slideshow/listimageitems.cpp
@@ -0,0 +1,87 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-21
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2003-2007 Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes
+
+#include <qstring.h>
+#include <qwidget.h>
+#include <qevent.h>
+#include <qstrlist.h>
+#include <qdragobject.h>
+#include <qfileinfo.h>
+#include <qlistbox.h>
+
+// KDE includes
+
+#include <klistbox.h>
+#include <kurl.h>
+
+// Local includes
+
+#include "listimageitems.h"
+#include "listimageitems.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+ListImageItems::ListImageItems(QWidget *parent, const char *name)
+ : KListBox(parent, name)
+{
+ setSelectionMode (QListBox::Extended);
+ setAcceptDrops(true);
+}
+
+void ListImageItems::dragEnterEvent(QDragEnterEvent *e)
+{
+ e->accept(QUriDrag::canDecode(e));
+}
+
+void ListImageItems::dropEvent(QDropEvent *e)
+{
+ QStrList strList;
+ KURL::List filesUrl;
+
+ if ( !QUriDrag::decode(e, strList) ) return;
+
+ QStrList stringList;
+ QStrListIterator it(strList);
+ char *str;
+
+ while ( (str = it.current()) != 0 )
+ {
+ QString filePath = QUriDrag::uriToLocalFile(str);
+ QFileInfo fileInfo(filePath);
+
+ if (fileInfo.isFile() && fileInfo.exists())
+ {
+ KURL url(fileInfo.filePath());
+ filesUrl.append(url);
+ }
+
+ ++it;
+ }
+
+ if (filesUrl.isEmpty() == false)
+ emit addedDropItems(filesUrl);
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/listimageitems.h b/kipi-plugins/slideshow/listimageitems.h
new file mode 100644
index 0000000..16e575d
--- /dev/null
+++ b/kipi-plugins/slideshow/listimageitems.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-10-21
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2003-2007 Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 LISTIMAGEITEM_H
+#define LISTIMAGEITEM_H
+
+// QT includes
+
+#include <qevent.h>
+#include <qwidget.h>
+#include <qstring.h>
+
+// KDE includes
+
+#include <klistbox.h>
+#include <kurl.h>
+
+namespace KIPISlideShowPlugin
+{
+
+class ImageItem : public QListBoxText
+{
+
+public:
+
+ ImageItem(QListBox * parent, QString const & name, QString const & comments, QString const & path,
+ QString const & album)
+ : QListBoxText(parent), _name(name), _comments(comments), _path(path), _album(album)
+ {}
+
+ QString comments() { return _comments; }
+ QString name() { return _name; }
+ QString path() { return _path; }
+ QString album() { return _album; }
+ void setName(const QString &newName) { setText(newName); }
+
+private:
+
+ QString _name;
+ QString _comments;
+ QString _path;
+ QString _album;
+};
+
+class ListImageItems : public KListBox
+{
+ Q_OBJECT
+
+ public:
+
+ ListImageItems(QWidget *parent=0, const char *name=0);
+
+ signals:
+
+ void addedDropItems(KURL::List filesUrl);
+
+ protected:
+
+ void dragEnterEvent(QDragEnterEvent *e);
+ void dropEvent(QDropEvent *e);
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif /* LISTIMAGEITEM_H */
diff --git a/kipi-plugins/slideshow/plugin_slideshow.cpp b/kipi-plugins/slideshow/plugin_slideshow.cpp
new file mode 100644
index 0000000..3043893
--- /dev/null
+++ b/kipi-plugins/slideshow/plugin_slideshow.cpp
@@ -0,0 +1,267 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-01-31
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/time.h>
+}
+
+// C++ includes.
+
+#include <ctime>
+#include <cstdlib>
+
+// Qt includes.
+
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qstringlist.h>
+
+ // KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+// Lib KIPI includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imagecollection.h>
+
+// Local includes.
+
+#include "slideshow.h"
+#include "slideshowgl.h"
+#include "slideshowkb.h"
+#include "slideshowconfig.h"
+#include "plugin_slideshow.h"
+#include "plugin_slideshow.moc"
+
+typedef KGenericFactory<Plugin_SlideShow> Factory;
+
+K_EXPORT_COMPONENT_FACTORY(kipiplugin_slideshow, Factory("kipiplugin_slideshow"));
+
+Plugin_SlideShow::Plugin_SlideShow(QObject *parent, const char*,
+ const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "SlideShow")
+{
+ kdDebug( 51001 ) << "Plugin_SlideShow plugin loaded"
+ << endl;
+}
+
+void Plugin_SlideShow::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_actionSlideShow = new KAction (i18n("Advanced SlideShow..."),
+ "slideshow",
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "slideshow");
+
+ m_interface = dynamic_cast< KIPI::Interface* >( parent() );
+
+ m_urlList = new KURL::List();
+
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi m_interface is null!" << endl;
+ return;
+ }
+
+ m_actionSlideShow->setEnabled( false );
+
+ connect( m_interface, SIGNAL( currentAlbumChanged( bool ) ),
+ SLOT( slotAlbumChanged( bool ) ) );
+
+ addAction( m_actionSlideShow );
+}
+
+Plugin_SlideShow::~Plugin_SlideShow()
+{
+ if (m_urlList)
+ delete m_urlList;
+}
+
+void Plugin_SlideShow::slotActivate()
+{
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi m_interface is null!" << endl;
+ return;
+ }
+
+ bool allowSelectedOnly = true;
+
+ KIPI::ImageCollection currSel = m_interface->currentSelection();
+ if ( !currSel.isValid() || currSel.images().isEmpty() )
+ {
+ allowSelectedOnly = false;
+ }
+
+ m_imagesHasComments = m_interface->hasFeature(KIPI::ImagesHasComments);
+
+ KIPISlideShowPlugin::SlideShowConfig *slideShowConfig
+ = new KIPISlideShowPlugin::SlideShowConfig( allowSelectedOnly, m_interface,kapp->activeWindow(),
+ i18n("Slide Show").ascii(), m_imagesHasComments,
+ m_urlList);
+
+ connect(slideShowConfig, SIGNAL(buttonStartClicked()),
+ this, SLOT(slotSlideShow()));
+
+ slideShowConfig->show();
+}
+
+void Plugin_SlideShow::slotAlbumChanged(bool anyAlbum)
+{
+ if (!anyAlbum)
+ {
+ m_actionSlideShow->setEnabled( false );
+ return;
+ }
+
+ KIPI::Interface* m_interface = dynamic_cast<KIPI::Interface*>( parent() );
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi m_interface is null!" << endl;
+ m_actionSlideShow->setEnabled( false );
+ return;
+ }
+
+ KIPI::ImageCollection currAlbum = m_interface->currentAlbum();
+ if ( !currAlbum.isValid() )
+ {
+ kdError( 51000 ) << "Current image collection is not valid." << endl;
+ m_actionSlideShow->setEnabled( false );
+ return;
+ }
+
+ m_actionSlideShow->setEnabled(true);
+}
+
+void Plugin_SlideShow::slotSlideShow()
+{
+ if ( !m_interface )
+ {
+ kdError( 51000 ) << "Kipi m_interface is null!" << endl;
+ return;
+ }
+
+ KConfig config("kipirc");
+
+ bool opengl;
+ bool shuffle;
+ bool wantKB;
+
+ config.setGroup("SlideShow Settings");
+ opengl = config.readBoolEntry("OpenGL");
+ shuffle = config.readBoolEntry("Shuffle");
+ wantKB = config.readEntry("Effect Name (OpenGL)") == QString("Ken Burns");
+
+ if ( m_urlList->isEmpty() )
+ {
+ KMessageBox::sorry(kapp->activeWindow(), i18n("There are no images to show."));
+ return;
+ }
+
+ typedef QPair<QString, int> FileAnglePair;
+ typedef QValueList<FileAnglePair > FileList;
+ FileList fileList;
+ QStringList commentsList;
+
+ for( KURL::List::Iterator urlIt = m_urlList->begin(); urlIt != m_urlList->end(); ++urlIt )
+ {
+ KIPI::ImageInfo info = m_interface->info( *urlIt );
+ fileList.append( FileAnglePair((*urlIt).path(), info.angle()) );
+ commentsList.append(info.description());
+ }
+
+ m_urlList->clear();
+
+ if (shuffle)
+ {
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ srand(tv.tv_sec);
+
+ FileList::iterator it = fileList.begin();
+ FileList::iterator it1;
+
+ QStringList::iterator itcom = commentsList.begin();
+ QStringList::iterator itcom1;
+
+ for (uint i=0; i<fileList.size(); i++)
+ {
+ int inc = (int) (float(fileList.count())*rand()/(RAND_MAX+1.0));
+
+ it1 = fileList.begin();
+ it1 += inc;
+
+ itcom1 = commentsList.begin();
+ itcom1 += inc;
+
+ qSwap(*(it++), *(it1));
+ qSwap(*(itcom++), *(itcom1));
+ }
+ }
+
+ if (!opengl) {
+ KIPISlideShowPlugin::SlideShow* slideShow = new KIPISlideShowPlugin::SlideShow(fileList, commentsList, m_imagesHasComments);
+ slideShow->show();
+ }
+ else {
+ if (!QGLFormat::hasOpenGL())
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Sorry. OpenGL support not available on your system"));
+ else {
+ if (wantKB) {
+ KIPISlideShowPlugin::SlideShowKB* slideShow =
+ new KIPISlideShowPlugin::SlideShowKB(fileList, commentsList, m_imagesHasComments);
+ slideShow->show();
+ }
+ else {
+ KIPISlideShowPlugin::SlideShowGL * slideShow =
+ new KIPISlideShowPlugin::SlideShowGL(fileList, commentsList, m_imagesHasComments);
+ slideShow->show();
+ }
+ }
+ }
+}
+
+KIPI::Category Plugin_SlideShow::category( KAction* action ) const
+{
+ if ( action == m_actionSlideShow )
+ return KIPI::TOOLSPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::TOOLSPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/slideshow/plugin_slideshow.h b/kipi-plugins/slideshow/plugin_slideshow.h
new file mode 100644
index 0000000..4195556
--- /dev/null
+++ b/kipi-plugins/slideshow/plugin_slideshow.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-01-31
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_SLIDESHOW_H
+#define PLUGIN_SLIDESHOW_H
+
+// KDE includes
+
+#include <kurl.h>
+
+// libKIPI includes.
+
+#include <libkipi/plugin.h>
+#include <libkipi/interface.h>
+
+class KAction;
+
+class Plugin_SlideShow : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_SlideShow(QObject *parent, const char* name,
+ const QStringList &args);
+ ~Plugin_SlideShow();
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* );
+
+public slots:
+
+ void slotActivate();
+
+private slots:
+
+ void slotAlbumChanged(bool anyAlbum);
+ void slotSlideShow();
+
+private:
+
+ KAction* m_actionSlideShow;
+ KIPI::Interface* m_interface;
+ KURL::List* m_urlList;
+
+ bool m_imagesHasComments;
+};
+
+#endif // PLUGIN_SLIDESHOW_H
diff --git a/kipi-plugins/slideshow/screenproperties.cpp b/kipi-plugins/slideshow/screenproperties.cpp
new file mode 100644
index 0000000..55f1e91
--- /dev/null
+++ b/kipi-plugins/slideshow/screenproperties.cpp
@@ -0,0 +1,105 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qapplication.h>
+
+// X11 includes.
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+
+// Local includes.
+
+#include "screenproperties.h"
+
+namespace KIPISlideShowPlugin
+{
+
+ ScreenProperties::ScreenProperties(QWidget *mainWidget) {
+
+ activeScreen = QApplication::desktop()->screenNumber(mainWidget);
+ }
+
+ unsigned ScreenProperties::suggestFrameRate() {
+
+ int eventBase, errorBase;
+ if ( !XRRQueryExtension(qt_xdisplay(), &eventBase, &errorBase)) {
+ // No information, make a lucky guess on based on that ;)
+ return 25;
+ }
+
+ // ask X11 for the refresh rate of the current screen
+ XRRScreenConfiguration* config;
+ int screenRate;
+
+ config = XRRGetScreenInfo(qt_xdisplay(), RootWindow(qt_xdisplay(),
+ activeScreen));
+ screenRate = XRRConfigCurrentRate(config);
+ XRRFreeScreenConfigInfo(config);
+ //qDebug("monitor refresh rate %d Hz", screenRate);
+
+ // Find the frame rate, that matches the monitor's refresh rate best.
+ // We will choose between 25, 28 and 30 Hz, to get smooth animations.
+ // The following frame rate will be chosen according to the monitor's
+ // refresh rate:
+ //
+ // Frame rate: Monitor refresh rate
+ // 25 Hz (50), 75, 100 Hz (PAL compliant setups)
+ // 28 Hz 85 Hz, 110 Hz (seems to work ok)
+ // 30 Hz 60, 90, 120 Hz (NTSC compliant setups)
+ //
+ // However, this will only work, if the kernel can schedule the
+ // screensaver at the right time (a 2.6.x kernel should work fine,
+ // because of the high HZ value).
+ int candidateRate[3] = { 30, 25, 28 };
+ int bestRate = candidateRate[0];
+ int smallestError = 1000, i = 0;
+ do {
+ int r = candidateRate[i];
+ int error = QMIN(screenRate % r, (screenRate + r) % r);
+
+ if (error < smallestError) {
+ smallestError = error;
+ bestRate = r;
+ }
+ } while (++i < 3);
+
+ //qDebug("using %d Hz as framerate for effects", bestRate);
+ return bestRate;
+ }
+
+ bool ScreenProperties::enableVSync() {
+
+ // currently only supported on NVidia hardware using the
+ // proprietary driver
+
+ // For NVidia graphics cards: always use sync-to-vblank
+ // return (setenv("__GL_SYNC_TO_VBLANK", "1", 1) == 0);
+ return false;
+ }
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/screenproperties.h b/kipi-plugins/slideshow/screenproperties.h
new file mode 100644
index 0000000..3a94237
--- /dev/null
+++ b/kipi-plugins/slideshow/screenproperties.h
@@ -0,0 +1,49 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SCREEN_H
+#define SCREEN_H
+
+namespace KIPISlideShowPlugin
+{
+
+ class ScreenProperties {
+
+ public:
+
+ ScreenProperties(QWidget *mainWidget);
+ virtual ~ScreenProperties() { };
+
+ virtual unsigned suggestFrameRate();
+ virtual bool enableVSync();
+
+ protected:
+
+ unsigned activeScreen;
+ };
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // SCREEN_H
diff --git a/kipi-plugins/slideshow/slideshow.cpp b/kipi-plugins/slideshow/slideshow.cpp
new file mode 100644
index 0000000..8cc87c2
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshow.cpp
@@ -0,0 +1,1214 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-02-16
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdlib>
+#include <cassert>
+#include <cmath>
+#include <ctime>
+
+// Qt includes.
+
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qapplication.h>
+#include <qdesktopwidget.h>
+#include <qevent.h>
+#include <qcursor.h>
+#include <qfont.h>
+#include <qwmatrix.h>
+#include <qtextcodec.h>
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kdeversion.h>
+#include <kglobalsettings.h>
+#include <kdebug.h>
+#include <kurl.h>
+
+// Local includes.
+
+#include "toolbar.h"
+#include "slideshow.h"
+#include "slideshow.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+SlideShow::SlideShow(const FileList& fileList, const QStringList& commentsList, bool ImagesHasComments)
+ : QWidget(0, 0, WStyle_StaysOnTop | WType_Popup | WX11BypassWM | WDestructiveClose)
+{
+#if KDE_IS_VERSION(3,2,0)
+ QRect deskRect = KGlobalSettings::desktopGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+#else
+ QRect deskRect = QApplication::desktop()->screenGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+#endif
+
+ move(m_deskX, m_deskY);
+ resize(m_deskWidth, m_deskHeight);
+ setPaletteBackgroundColor(black);
+
+ m_toolBar = new ToolBar(this);
+ m_toolBar->hide();
+ if (!m_loop)
+ {
+ m_toolBar->setEnabledPrev(false);
+ }
+ connect(m_toolBar, SIGNAL(signalPause()),
+ this, SLOT(slotPause()));
+
+ connect(m_toolBar, SIGNAL(signalPlay()),
+ this, SLOT(slotPlay()));
+
+ connect(m_toolBar, SIGNAL(signalNext()),
+ this, SLOT(slotNext()));
+
+ connect(m_toolBar, SIGNAL(signalPrev()),
+ this, SLOT(slotPrev()));
+
+ connect(m_toolBar, SIGNAL(signalClose()),
+ this, SLOT(slotClose()));
+
+ // ---------------------------------------------------------------
+
+ m_currImage = 0;
+ m_fileIndex = -1; // start with -1
+ m_effect = 0;
+ m_effectRunning = false;
+ m_intArray = 0;
+ m_endOfShow = false;
+
+ m_timer = new QTimer();
+ connect(m_timer, SIGNAL(timeout()),
+ this, SLOT(slotTimeOut()));
+
+ // --------------------------------------------------
+
+ m_fileList = fileList;
+ m_commentsList = commentsList;
+ m_ImagesHasComments = ImagesHasComments;
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("SlideShow Settings");
+
+ readSettings();
+
+ m_imageLoader = new SlideShowLoader(m_fileList, m_cacheSize, width(), height(), m_fileIndex);
+
+ // --------------------------------------------------
+
+ registerEffects();
+
+ if (m_effectName == "Random")
+ m_effect = getRandomEffect();
+ else
+ {
+ m_effect = Effects[m_effectName];
+ if (!m_effect)
+ {
+ m_effect = Effects["None"];
+ }
+ }
+
+ m_timer->start(10, true);
+
+ // -- hide cursor when not moved --------------------
+
+ m_mouseMoveTimer = new QTimer;
+ connect(m_mouseMoveTimer, SIGNAL(timeout()),
+ SLOT(slotMouseMoveTimeOut()));
+
+ setMouseTracking(true);
+ slotMouseMoveTimeOut();
+
+}
+
+SlideShow::~SlideShow()
+{
+ m_timer->stop();
+ delete m_timer;
+ m_mouseMoveTimer->stop();
+ delete m_mouseMoveTimer;
+
+ if (m_painter.isActive())
+ m_painter.end();
+
+ if (m_intArray)
+ delete [] m_intArray;
+
+ if (m_currImage)
+ delete m_currImage;
+
+ if (m_imageLoader)
+ delete m_imageLoader;
+
+ if (m_config)
+ delete m_config;
+}
+
+void SlideShow::readSettings()
+{
+ m_delay = m_config->readNumEntry("Delay", 1500);
+ m_printName = m_config->readBoolEntry("Print Filename", true);
+ m_printProgress = m_config->readBoolEntry("Print Progress Indicator", true);
+ m_printComments = m_config->readBoolEntry("Print Comments", false);
+ m_loop = m_config->readBoolEntry("Loop", false);
+
+ m_effectName = m_config->readEntry("Effect Name", "Random");
+
+ m_enableMouseWheel = m_config->readBoolEntry("Enable Mouse Wheel", true);
+
+ // Comments tab settings
+
+ m_commentsFont = new QFont();
+ m_commentsFont->setFamily(m_config->readEntry("Comments Font Family"));
+ m_commentsFont->setPointSize(m_config->readNumEntry("Comments Font Size", 10 ));
+ m_commentsFont->setBold(m_config->readBoolEntry("Comments Font Bold", false));
+ m_commentsFont->setItalic(m_config->readBoolEntry("Comments Font Italic", false));
+ m_commentsFont->setUnderline(m_config->readBoolEntry("Comments Font Underline", false));
+ m_commentsFont->setOverline(m_config->readBoolEntry("Comments Font Overline", false));
+ m_commentsFont->setStrikeOut(m_config->readBoolEntry("Comments Font StrikeOut", false));
+ m_commentsFont->setFixedPitch(m_config->readBoolEntry("Comments Font FixedPitch", false));
+
+ m_commentsFontColor = m_config->readUnsignedNumEntry("Comments Font Color", 0xffffff);
+ m_commentsBgColor = m_config->readUnsignedNumEntry("Comments Bg Color", 0x000000);
+
+ m_commentsLinesLength = m_config->readNumEntry("Comments Lines Length", 72);
+
+ // Advanced settings
+ bool enableCache = m_config->readBoolEntry("Enable Cache", false);
+ if (enableCache)
+ m_cacheSize = m_config->readNumEntry("Cache Size", 1);
+ else
+ m_cacheSize = 1;
+}
+
+void SlideShow::registerEffects()
+{
+ Effects.insert("None", &SlideShow::effectNone);
+ Effects.insert("Chess Board", &SlideShow::effectChessboard);
+ Effects.insert("Melt Down", &SlideShow::effectMeltdown);
+ Effects.insert("Sweep", &SlideShow::effectSweep);
+ Effects.insert("Noise", &SlideShow::effectRandom);
+ Effects.insert("Growing", &SlideShow::effectGrowing);
+ Effects.insert("Incom_ing Edges", &SlideShow::effectIncom_ingEdges);
+ Effects.insert("Horizontal Lines", &SlideShow::effectHorizLines);
+ Effects.insert("Vertical Lines", &SlideShow::effectVertLines);
+ Effects.insert("Circle Out", &SlideShow::effectCircleOut);
+ Effects.insert("MultiCircle Out", &SlideShow::effectMultiCircleOut);
+ Effects.insert("Spiral In", &SlideShow::effectSpiralIn);
+ Effects.insert("Blobs", &SlideShow::effectBlobs);
+}
+
+QStringList SlideShow::effectNames()
+{
+ QStringList effects;
+
+ effects.append("None");
+ effects.append("Chess Board");
+ effects.append("Melt Down");
+ effects.append("Sweep");
+ effects.append("Noise");
+ effects.append("Growing");
+ effects.append("Incom_ing Edges");
+ effects.append("Horizontal Lines");
+ effects.append("Vertical Lines");
+ effects.append("Circle Out");
+ effects.append("MultiCircle Out");
+ effects.append("Spiral In");
+ effects.append("Blobs");
+ effects.append("Random");
+
+ return effects;
+}
+
+QMap<QString,QString> SlideShow::effectNamesI18N()
+{
+ QMap<QString,QString> effects;
+
+ effects["None"] = i18n("None");
+ effects["Chess Board"] = i18n("Chess Board");
+ effects["Melt Down"] = i18n("Melt Down");
+ effects["Sweep"] = i18n("Sweep");
+ effects["Noise"] = i18n("Noise");
+ effects["Growing"] = i18n("Growing");
+ effects["Incom_ing Edges"] = i18n("Incom_ing Edges");
+ effects["Horizontal Lines"] = i18n("Horizontal Lines");
+ effects["Vertical Lines"] = i18n("Vertical Lines");
+ effects["Circle Out"] = i18n("Circle Out");
+ effects["MultiCircle Out"] = i18n("MultiCircle Out");
+ effects["Spiral In"] = i18n("Spiral In");
+ effects["Blobs"] = i18n("Blobs");
+ effects["Random"] = i18n("Random");
+
+ return effects;
+}
+
+void SlideShow::slotTimeOut()
+{
+ if (!m_effect) return; // No effect -> bye !
+
+ int tmout = -1;
+
+ if (m_effectRunning) // Effect under progress ?
+ {
+ tmout = (this->*m_effect)(false);
+ }
+ else
+ {
+ loadNextImage();
+
+ if (!m_currImage || m_fileList.isEmpty()) // End of slideshow ?
+ {
+ showEndOfShow();
+ return;
+ }
+
+ if (m_effectName == "Random") // Take a random effect.
+ {
+ m_effect = getRandomEffect();
+ if (!m_effect) return;
+ }
+
+ m_effectRunning = true;
+ tmout = (this->*m_effect)(true);
+ }
+
+ if (tmout <= 0) // Effect finished -> delay.
+ {
+ tmout = m_delay;
+ m_effectRunning = false;
+ }
+
+ m_timer->start(tmout, true);
+}
+
+void SlideShow::loadNextImage()
+{
+ if (m_currImage)
+ delete m_currImage;
+ m_currImage = 0;
+
+ m_fileIndex++;
+ m_imageLoader->next();
+ int num = m_fileList.count();
+ if (m_fileIndex >= num)
+ {
+ if (m_loop)
+ {
+ m_fileIndex = 0;
+ }
+ else
+ {
+ m_fileIndex = num-1;
+ return;
+ }
+ }
+
+ if (!m_loop)
+ {
+ m_toolBar->setEnabledPrev(m_fileIndex > 0);
+ m_toolBar->setEnabledNext(m_fileIndex < num-1);
+ }
+
+ QPixmap* oldPixmap = m_currImage;
+ QPixmap* newPixmap = new QPixmap(m_imageLoader->getCurrent());
+
+ QPixmap pixmap(width(),height());
+ pixmap.fill(Qt::black);
+
+ QPainter p(&pixmap);
+ p.drawPixmap((width()-newPixmap->width())/2,
+ (height()-newPixmap->height())/2, *newPixmap,
+ 0, 0, newPixmap->width(), newPixmap->height());
+
+ delete newPixmap;
+ m_currImage = new QPixmap(pixmap);
+ delete oldPixmap;
+
+ if (m_printName)
+ printFilename();
+
+ if (m_printProgress)
+ printProgress();
+
+ if (m_printComments && m_ImagesHasComments)
+ printComments();
+}
+
+void SlideShow::loadPrevImage()
+{
+ if (m_currImage)
+ delete m_currImage;
+ m_currImage = 0;
+
+ m_fileIndex--;
+ m_imageLoader->prev();
+ int num = m_fileList.count();
+ if (m_fileIndex < 0)
+ {
+ if (m_loop)
+ {
+ m_fileIndex = num-1;
+ }
+ else
+ {
+ m_fileIndex = -1; // set this to -1.
+ return;
+ }
+ }
+
+ if (!m_loop)
+ {
+ m_toolBar->setEnabledPrev(m_fileIndex > 0);
+ m_toolBar->setEnabledNext(m_fileIndex < num-1);
+ }
+
+ QPixmap* oldPixmap = m_currImage;
+ QPixmap* newPixmap = new QPixmap(m_imageLoader->getCurrent());
+
+ QPixmap pixmap(width(),height());
+ pixmap.fill(Qt::black);
+
+ QPainter p(&pixmap);
+ p.drawPixmap((width()-newPixmap->width())/2,
+ (height()-newPixmap->height())/2, *newPixmap,
+ 0, 0, newPixmap->width(), newPixmap->height());
+
+ delete newPixmap;
+ m_currImage = new QPixmap(pixmap);
+ delete oldPixmap;
+
+ if (m_printName)
+ printFilename();
+
+ if (m_printProgress)
+ printProgress();
+
+ if (m_printComments)
+ printComments();
+}
+
+void SlideShow::showCurrentImage()
+{
+ if (!m_currImage)
+ return;
+
+ bitBlt(this, 0, 0, m_currImage,
+ 0, 0, m_currImage->width(),
+ m_currImage->height(), Qt::CopyROP, true);
+}
+
+void SlideShow::printFilename()
+{
+ if (!m_currImage) return;
+
+ QPainter p;
+ p.begin(m_currImage);
+
+ p.setPen(QColor("black"));
+ for (int x=9; x<=11; x++)
+ for (int y=31; y>=29; y--)
+ p.drawText(x, height()-y, m_imageLoader->currFileName());
+
+ p.setPen(QColor("white"));
+ p.drawText(10, height()-30, m_imageLoader->currFileName());
+}
+
+void SlideShow::printComments()
+{
+ if (!m_currImage) return;
+
+ QString comments = m_commentsList[m_fileIndex];
+
+ int yPos = 30; // Text Y coordinate
+ if (m_printName) yPos = 50;
+
+ QStringList commentsByLines;
+
+ uint commentsIndex = 0; // Comments QString index
+
+ while (commentsIndex < comments.length())
+ {
+ QString newLine;
+ bool breakLine = FALSE; // End Of Line found
+ uint currIndex; // Comments QString current index
+
+ // Check minimal lines dimension
+
+ uint commentsLinesLengthLocal = m_commentsLinesLength;
+
+ for ( currIndex = commentsIndex; currIndex < comments.length() && !breakLine; currIndex++ )
+ if( comments[currIndex] == QChar('\n') || comments[currIndex].isSpace() ) breakLine = TRUE;
+
+ if (commentsLinesLengthLocal <= (currIndex - commentsIndex))
+ commentsLinesLengthLocal = (currIndex - commentsIndex);
+
+ breakLine = FALSE;
+
+ for ( currIndex = commentsIndex; currIndex <= commentsIndex + commentsLinesLengthLocal &&
+ currIndex < comments.length() &&
+ !breakLine; currIndex++ )
+ {
+ breakLine = (comments[currIndex] == QChar('\n')) ? TRUE : FALSE;
+
+ if (breakLine)
+ newLine.append( ' ' );
+ else
+ newLine.append( comments[currIndex] );
+ }
+
+ commentsIndex = currIndex; // The line is ended
+
+ if ( commentsIndex != comments.length() )
+ while ( !newLine.endsWith(" ") )
+ {
+ newLine.truncate(newLine.length() - 1);
+ commentsIndex--;
+ }
+
+ commentsByLines.prepend(newLine.stripWhiteSpace());
+ }
+
+ QPainter p;
+ p.begin(m_currImage);
+ p.setFont(*m_commentsFont);
+
+ for ( int lineNumber = 0; lineNumber < (int)commentsByLines.count(); lineNumber++ ) {
+
+ p.setPen(QColor(m_commentsBgColor));
+
+ // coefficient 1.5 is used to maintain distance between different lines
+
+ for (int x=9; x<=11; x++)
+ for (int y = (int)(yPos + lineNumber * 1.5 * m_commentsFont->pointSize() + 1);
+ y >= (int)(yPos + lineNumber* 1.5 * m_commentsFont->pointSize() - 1); y--)
+ p.drawText(x, height()-y, commentsByLines[lineNumber]);
+
+ p.setPen(QColor(m_commentsFontColor));
+
+ p.drawText(10, height()-(int)(lineNumber * 1.5 * m_commentsFont->pointSize() + yPos), commentsByLines[lineNumber]);
+ }
+}
+
+void SlideShow::printProgress()
+{
+ if (!m_currImage) return;
+
+ QPainter p;
+ p.begin(m_currImage);
+
+ QString progress(QString::number(m_fileIndex+1) + "/" + QString::number(m_fileList.count()));
+
+ int stringLenght = p.fontMetrics().width(progress) * progress.length();
+
+ p.setPen(QColor("black"));
+ for (int x=9; x<=11; x++)
+ for (int y=21; y>=19; y--)
+ p.drawText(x, height()-y, progress);
+
+ p.setPen(QColor("white"));
+ p.drawText(width() - stringLenght - 10, 20, progress);
+}
+
+EffectMethod SlideShow::getRandomEffect()
+{
+ QStringList effs = Effects.keys();
+ effs.remove("None");
+
+ int count = effs.count();
+
+ int i = rand() % count;
+ QString key = effs[i];
+
+ return Effects[key];
+}
+
+void SlideShow::showEndOfShow()
+{
+ QPainter p;
+ p.begin(this);
+ p.fillRect(0, 0, width(), height(), Qt::black);
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize()+10);
+ fn.setBold(true);
+
+ p.setFont(fn);
+ p.setPen(Qt::white);
+ p.drawText(100, 100, i18n("SlideShow Completed."));
+ p.drawText(100, 150, i18n("Click To Exit..."));
+ p.end();
+
+ m_endOfShow = true;
+ m_toolBar->setEnabledPlay(false);
+ m_toolBar->setEnabledNext(false);
+ m_toolBar->setEnabledPrev(false);
+}
+
+void SlideShow::keyPressEvent(QKeyEvent *event)
+{
+ if (!event)
+ return;
+
+ m_toolBar->keyPressEvent(event);
+}
+
+void SlideShow::mousePressEvent(QMouseEvent *e)
+{
+ if (m_endOfShow)
+ slotClose();
+
+ if (e->button() == Qt::LeftButton)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotNext();
+ }
+ else if (e->button() == Qt::RightButton && m_fileIndex-1 >= 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotPrev();
+ }
+}
+
+void SlideShow::mouseMoveEvent(QMouseEvent *e)
+{
+ setCursor(QCursor(Qt::ArrowCursor));
+ m_mouseMoveTimer->start(1000, true);
+
+ if (!m_toolBar->canHide())
+ return;
+
+ QPoint pos(e->pos());
+
+ if ((pos.y() > (m_deskY+20)) &&
+ (pos.y() < (m_deskY+m_deskHeight-20-1)))
+ {
+ if (m_toolBar->isHidden())
+ return;
+ else
+ m_toolBar->hide();
+ return;
+ }
+
+ int w = m_toolBar->width();
+ int h = m_toolBar->height();
+
+ if (pos.y() < (m_deskY+20))
+ {
+ if (pos.x() <= (m_deskX+m_deskWidth/2))
+ // position top left
+ m_toolBar->move(m_deskX, m_deskY);
+ else
+ // position top right
+ m_toolBar->move(m_deskX+m_deskWidth-w-1, m_deskY);
+ }
+ else
+ {
+ if (pos.x() <= (m_deskX+m_deskWidth/2))
+ // position bot left
+ m_toolBar->move(m_deskX, m_deskY+m_deskHeight-h-1);
+ else
+ // position bot right
+ m_toolBar->move(m_deskX+m_deskWidth-w-1, m_deskY+m_deskHeight-h-1);
+ }
+ m_toolBar->show();
+}
+
+void SlideShow::wheelEvent(QWheelEvent *e)
+{
+ if (!m_enableMouseWheel) return;
+
+ if (m_endOfShow)
+ slotClose();
+
+ int delta = e->delta();
+
+ if (delta < 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotNext();
+ }
+ else if (delta > 0 && m_fileIndex-1 >= 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotPrev();
+ }
+}
+
+void SlideShow::slotMouseMoveTimeOut()
+{
+ QPoint pos(QCursor::pos());
+ if ((pos.y() < (m_deskY+20)) ||
+ (pos.y() > (m_deskY+m_deskHeight-20-1)))
+ return;
+
+ setCursor(QCursor(Qt::BlankCursor));
+}
+
+int SlideShow::effectNone(bool /* aInit */)
+{
+ showCurrentImage();
+ return -1;
+}
+
+
+int SlideShow::effectChessboard(bool aInit)
+{
+ int y;
+
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_dx = 8; // width of one tile
+ m_dy = 8; // height of one tile
+ m_j = (m_w+m_dx-1)/m_dx; // number of tiles
+ m_x = m_j*m_dx; // shrinking x-offset from screen border
+ m_ix = 0; // growing x-offset from screen border
+ m_iy = 0; // 0 or m_dy for growing tiling effect
+ m_y = m_j&1 ? 0 : m_dy; // 0 or m_dy for shrinking tiling effect
+ m_wait = 800 / m_j; // timeout between effects
+ }
+
+ if (m_ix >= m_w)
+ {
+ showCurrentImage();
+ return -1;
+ }
+
+ m_ix += m_dx;
+ m_x -= m_dx;
+ m_iy = m_iy ? 0 : m_dy;
+ m_y = m_y ? 0 : m_dy;
+
+ for (y=0; y<m_w; y+=(m_dy<<1))
+ {
+ bitBlt(this, m_ix, y+m_iy, m_currImage, m_ix, y+m_iy,
+ m_dx, m_dy, CopyROP, true);
+ bitBlt(this, m_x, y+m_y, m_currImage, m_x, y+m_y,
+ m_dx, m_dy, CopyROP, true);
+ }
+
+ return m_wait;
+}
+
+int SlideShow::effectMeltdown(bool aInit)
+{
+ int i, x, y;
+ bool done;
+
+ if (aInit)
+ {
+ delete [] m_intArray;
+ m_w = width();
+ m_h = height();
+ m_dx = 4;
+ m_dy = 16;
+ m_ix = m_w / m_dx;
+ m_intArray = new int[m_ix];
+ for (i=m_ix-1; i>=0; i--)
+ m_intArray[i] = 0;
+ }
+
+ done = true;
+ for (i=0,x=0; i<m_ix; i++,x+=m_dx)
+ {
+ y = m_intArray[i];
+ if (y >= m_h) continue;
+ done = false;
+ if ((rand()&15) < 6) continue;
+ bitBlt(this, x, y+m_dy, this, x, y, m_dx, m_h-y-m_dy, CopyROP, true);
+ bitBlt(this, x, y, m_currImage, x, y, m_dx, m_dy, CopyROP, true);
+ m_intArray[i] += m_dy;
+ }
+
+ if (done)
+ {
+ delete [] m_intArray;
+ m_intArray = NULL;
+ return -1;
+ }
+
+ return 15;
+}
+
+int SlideShow::effectSweep(bool aInit)
+{
+ int w, h, x, y, i;
+
+ if (aInit)
+ {
+ // subtype: 0=sweep right to left, 1=sweep left to right
+ // 2=sweep bottom to top, 3=sweep top to bottom
+ m_subType = rand() % 4;
+ m_w = width();
+ m_h = height();
+ m_dx = (m_subType==1 ? 16 : -16);
+ m_dy = (m_subType==3 ? 16 : -16);
+ m_x = (m_subType==1 ? 0 : m_w);
+ m_y = (m_subType==3 ? 0 : m_h);
+ }
+
+ if (m_subType==0 || m_subType==1)
+ {
+ // horizontal sweep
+ if ((m_subType==0 && m_x < -64) ||
+ (m_subType==1 && m_x > m_w+64))
+ {
+ return -1;
+ }
+ for (w=2,i=4,x=m_x; i>0; i--, w<<=1, x-=m_dx)
+ {
+ bitBlt(this, x, 0, m_currImage, x, 0, w, m_h, CopyROP, true);
+ }
+ m_x += m_dx;
+ }
+ else
+ {
+ // vertical sweep
+ if ((m_subType==2 && m_y < -64) ||
+ (m_subType==3 && m_y > m_h+64))
+ {
+ return -1;
+ }
+ for (h=2,i=4,y=m_y; i>0; i--, h<<=1, y-=m_dy)
+ {
+ bitBlt(this, 0, y, m_currImage, 0, y, m_w, h, CopyROP, true);
+ }
+ m_y += m_dy;
+ }
+
+ return 20;
+}
+
+int SlideShow::effectRandom(bool /*aInit*/)
+{
+ int x, y, i, w, h, fact, sz;
+
+ fact = (rand() % 3) + 1;
+
+ w = width() >> fact;
+ h = height() >> fact;
+ sz = 1 << fact;
+
+ for (i = (w*h)<<1; i > 0; i--)
+ {
+ x = (rand() % w) << fact;
+ y = (rand() % h) << fact;
+ bitBlt(this, x, y, m_currImage, x, y, sz, sz, CopyROP, true);
+ }
+
+ showCurrentImage();
+
+ return -1;
+}
+
+int SlideShow::effectGrowing(bool aInit)
+{
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_x = m_w >> 1;
+ m_y = m_h >> 1;
+ m_i = 0;
+ m_fx = m_x / 100.0;
+ m_fy = m_y / 100.0;
+ }
+
+ m_x = (m_w>>1) - (int)(m_i * m_fx);
+ m_y = (m_h>>1) - (int)(m_i * m_fy);
+ m_i++;
+
+ if (m_x<0 || m_y<0)
+ {
+ showCurrentImage();
+ return -1;
+ }
+
+ bitBlt(this, m_x, m_y, m_currImage, m_x, m_y,
+ m_w - (m_x<<1), m_h - (m_y<<1), CopyROP, true);
+
+ return 20;
+}
+
+int SlideShow::effectIncom_ingEdges(bool aInit)
+{
+ int x1, y1;
+
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_ix = m_w >> 1;
+ m_iy = m_h >> 1;
+ m_fx = m_ix / 100.0;
+ m_fy = m_iy / 100.0;
+ m_i = 0;
+ m_subType = rand() & 1;
+ }
+
+ m_x = (int)(m_fx * m_i);
+ m_y = (int)(m_fy * m_i);
+
+ if (m_x>m_ix || m_y>m_iy)
+ {
+ showCurrentImage();
+ return -1;
+ }
+
+ x1 = m_w - m_x;
+ y1 = m_h - m_y;
+ m_i++;
+
+ if (m_subType)
+ {
+ // moving image edges
+ bitBlt(this, 0, 0, m_currImage, m_ix-m_x, m_iy-m_y, m_x, m_y, CopyROP, true);
+ bitBlt(this, x1, 0, m_currImage, m_ix, m_iy-m_y, m_x, m_y, CopyROP, true);
+ bitBlt(this, 0, y1, m_currImage, m_ix-m_x, m_iy, m_x, m_y, CopyROP, true);
+ bitBlt(this, x1, y1, m_currImage, m_ix, m_iy, m_x, m_y, CopyROP, true);
+ }
+ else
+ {
+ // fixed image edges
+ bitBlt(this, 0, 0, m_currImage, 0, 0, m_x, m_y, CopyROP, true);
+ bitBlt(this, x1, 0, m_currImage, x1, 0, m_x, m_y, CopyROP, true);
+ bitBlt(this, 0, y1, m_currImage, 0, y1, m_x, m_y, CopyROP, true);
+ bitBlt(this, x1, y1, m_currImage, x1, y1, m_x, m_y, CopyROP, true);
+ }
+ return 20;
+}
+
+int SlideShow::effectHorizLines(bool aInit)
+{
+ static int iyPos[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
+ int y;
+
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_i = 0;
+ }
+
+ if (iyPos[m_i] < 0) return -1;
+
+ for (y=iyPos[m_i]; y<m_h; y+=8)
+ {
+ bitBlt(this, 0, y, m_currImage, 0, y, m_w, 1, CopyROP, true);
+ }
+
+ m_i++;
+ if (iyPos[m_i] >= 0) return 160;
+ return -1;
+}
+
+int SlideShow::effectVertLines(bool aInit)
+{
+ static int ixPos[] = { 0, 4, 2, 6, 1, 5, 3, 7, -1 };
+ int x;
+
+ if (aInit)
+ {
+ m_w = width();
+ m_h = height();
+ m_i = 0;
+ }
+
+ if (ixPos[m_i] < 0) return -1;
+
+ for (x=ixPos[m_i]; x<m_w; x+=8)
+ {
+ bitBlt(this, x, 0, m_currImage, x, 0, 1, m_h, CopyROP, true);
+ }
+
+ m_i++;
+ if (ixPos[m_i] >= 0) return 160;
+ return -1;
+}
+
+int SlideShow::effectMultiCircleOut(bool aInit)
+{
+ int x, y, i;
+ double alpha;
+ static QPointArray pa(4);
+
+ if (aInit)
+ {
+ startPainter();
+ m_w = width();
+ m_h = height();
+ m_x = m_w;
+ m_y = m_h>>1;
+ pa.setPoint(0, m_w>>1, m_h>>1);
+ pa.setPoint(3, m_w>>1, m_h>>1);
+ m_fy = sqrt((double)m_w*m_w + m_h*m_h) / 2;
+ m_i = rand()%15 + 2;
+ m_fd = M_PI*2/m_i;
+ m_alpha = m_fd;
+ m_wait = 10 * m_i;
+ m_fx = M_PI/32; // divisor must be powers of 8
+ }
+
+ if (m_alpha < 0)
+ {
+ m_painter.end();
+ showCurrentImage();
+ return -1;
+ }
+
+ for (alpha=m_alpha, i=m_i; i>=0; i--, alpha+=m_fd)
+ {
+ x = (m_w>>1) + (int)(m_fy * cos(-alpha));
+ y = (m_h>>1) + (int)(m_fy * sin(-alpha));
+
+ m_x = (m_w>>1) + (int)(m_fy * cos(-alpha + m_fx));
+ m_y = (m_h>>1) + (int)(m_fy * sin(-alpha + m_fx));
+
+ pa.setPoint(1, x, y);
+ pa.setPoint(2, m_x, m_y);
+
+ m_painter.drawPolygon(pa);
+ }
+
+ m_alpha -= m_fx;
+
+ return m_wait;
+}
+
+int SlideShow::effectSpiralIn(bool aInit)
+{
+ if (aInit)
+ {
+ startPainter();
+ m_w = width();
+ m_h = height();
+ m_ix = m_w / 8;
+ m_iy = m_h / 8;
+ m_x0 = 0;
+ m_x1 = m_w - m_ix;
+ m_y0 = m_iy;
+ m_y1 = m_h - m_iy;
+ m_dx = m_ix;
+ m_dy = 0;
+ m_i = 0;
+ m_j = 16 * 16;
+ m_x = 0;
+ m_y = 0;
+ }
+
+ if (m_i==0 && m_x0>=m_x1)
+ {
+ m_painter.end();
+ showCurrentImage();
+ return -1;
+ }
+
+ if (m_i==0 && m_x>=m_x1) // switch to: down on right side
+ {
+ m_i = 1;
+ m_dx = 0;
+ m_dy = m_iy;
+ m_x1 -= m_ix;
+ }
+ else if (m_i==1 && m_y>=m_y1) // switch to: right to left on bottom side
+ {
+ m_i = 2;
+ m_dx = -m_ix;
+ m_dy = 0;
+ m_y1 -= m_iy;
+ }
+ else if (m_i==2 && m_x<=m_x0) // switch to: up on left side
+ {
+ m_i = 3;
+ m_dx = 0;
+ m_dy = -m_iy;
+ m_x0 += m_ix;
+ }
+ else if (m_i==3 && m_y<=m_y0) // switch to: left to right on top side
+ {
+ m_i = 0;
+ m_dx = m_ix;
+ m_dy = 0;
+ m_y0 += m_iy;
+ }
+
+ bitBlt(this, m_x, m_y, m_currImage, m_x, m_y, m_ix, m_iy, CopyROP, true);
+
+ m_x += m_dx;
+ m_y += m_dy;
+ m_j--;
+
+ return 8;
+}
+
+int SlideShow::effectCircleOut(bool aInit)
+{
+ int x, y;
+ static QPointArray pa(4);
+
+ if (aInit)
+ {
+ startPainter();
+ m_w = width();
+ m_h = height();
+ m_x = m_w;
+ m_y = m_h>>1;
+ m_alpha = 2*M_PI;
+ pa.setPoint(0, m_w>>1, m_h>>1);
+ pa.setPoint(3, m_w>>1, m_h>>1);
+ m_fx = M_PI/16; // divisor must be powers of 8
+ m_fy = sqrt((double)m_w*m_w + m_h*m_h) / 2;
+ }
+
+ if (m_alpha < 0)
+ {
+ m_painter.end();
+ showCurrentImage();
+ return -1;
+ }
+
+ x = m_x;
+ y = m_y;
+ m_x = (m_w>>1) + (int)(m_fy * cos(m_alpha));
+ m_y = (m_h>>1) + (int)(m_fy * sin(m_alpha));
+ m_alpha -= m_fx;
+
+ pa.setPoint(1, x, y);
+ pa.setPoint(2, m_x, m_y);
+
+ m_painter.drawPolygon(pa);
+
+ return 20;
+}
+
+
+int SlideShow::effectBlobs(bool aInit)
+{
+ int r;
+
+ if (aInit)
+ {
+ startPainter();
+ m_alpha = M_PI * 2;
+ m_w = width();
+ m_h = height();
+ m_i = 150;
+ }
+
+ if (m_i <= 0)
+ {
+ m_painter.end();
+ showCurrentImage();
+ return -1;
+ }
+
+ m_x = rand() % m_w;
+ m_y = rand() % m_h;
+ r = (rand() % 200) + 50;
+
+ m_painter.drawEllipse(m_x-r, m_y-r, r, r);
+ m_i--;
+
+ return 10;
+}
+
+void SlideShow::startPainter(Qt::PenStyle aPen)
+{
+ QBrush brush;
+ brush.setPixmap(*(m_currImage));
+
+ if (m_painter.isActive())
+ m_painter.end();
+
+ m_painter.begin(this);
+ m_painter.setBrush(brush);
+ m_painter.setPen(aPen);
+}
+
+void SlideShow::slotPause()
+{
+ m_timer->stop();
+
+ if (m_toolBar->isHidden())
+ {
+ int w = m_toolBar->width();
+ m_toolBar->move(m_deskWidth-w-1,0);
+ m_toolBar->show();
+ }
+}
+
+void SlideShow::slotPlay()
+{
+ m_toolBar->hide();
+ slotTimeOut();
+}
+
+void SlideShow::slotPrev()
+{
+ loadPrevImage();
+ if (!m_currImage || m_fileList.isEmpty())
+ {
+ showEndOfShow();
+ return;
+ }
+ m_effectRunning = false;
+ showCurrentImage();
+}
+
+void SlideShow::slotNext()
+{
+ loadNextImage();
+ if (!m_currImage || m_fileList.isEmpty())
+ {
+ showEndOfShow();
+ return;
+ }
+ m_effectRunning = false;
+ showCurrentImage();
+}
+
+void SlideShow::slotClose()
+{
+ close();
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/slideshow.h b/kipi-plugins/slideshow/slideshow.h
new file mode 100644
index 0000000..4214ce9
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshow.h
@@ -0,0 +1,189 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-02-16
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SLIDESHOW_H
+#define SLIDESHOW_H
+
+// QT includes.
+
+#include <qvaluelist.h>
+#include <qstringlist.h>
+#include <qpair.h>
+#include <qstring.h>
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qmap.h>
+#include <qfont.h>
+#include <qstring.h>
+
+// KDE includes.
+
+#include <kconfig.h>
+#include <kurl.h>
+
+// Libkipi includes.
+
+#include <libkipi/imagecollection.h>
+#include <libkipi/interface.h>
+
+// Local includes.
+
+#include "slideshowloader.h"
+
+class QTimer;
+
+typedef QPair<QString, int> FileAnglePair;
+typedef QValueList<FileAnglePair > FileList;
+
+namespace KIPISlideShowPlugin
+{
+
+class ToolBar;
+
+class SlideShow;
+
+typedef int (SlideShow::*EffectMethod)(bool);
+
+class SlideShow : public QWidget
+{
+
+ Q_OBJECT
+
+public:
+
+ SlideShow(const FileList& fileList, const QStringList& commentsList, bool ImagesHasComments);
+ ~SlideShow();
+
+ void registerEffects();
+
+ static QStringList effectNames();
+ static QMap<QString,QString> effectNamesI18N();
+
+protected:
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *);
+ void wheelEvent(QWheelEvent *);
+ void keyPressEvent(QKeyEvent *event);
+
+ int effectNone(bool);
+ int effectChessboard(bool doInit);
+ int effectMeltdown(bool doInit);
+ int effectSweep(bool doInit);
+ int effectRandom(bool doInit);
+ int effectGrowing(bool doInit);
+ int effectIncom_ingEdges(bool doInit);
+ int effectHorizLines(bool doInit);
+ int effectVertLines(bool doInit);
+ int effectMultiCircleOut(bool doInit);
+ int effectSpiralIn(bool doInit);
+ int effectCircleOut(bool doInit);
+ int effectBlobs(bool doInit);
+
+ void startPainter(Qt::PenStyle penStyle=NoPen);
+
+private slots:
+
+ void slotTimeOut();
+ void slotMouseMoveTimeOut();
+
+ void slotPause();
+ void slotPlay();
+ void slotPrev();
+ void slotNext();
+ void slotClose();
+
+private:
+
+ void loadNextImage();
+ void loadPrevImage();
+ void showCurrentImage();
+ void printFilename();
+ void printComments();
+ void printProgress();
+ EffectMethod getRandomEffect();
+ void showEndOfShow();
+
+ void readSettings();
+
+private:
+
+ // config ------------------
+
+ KConfig* m_config;
+
+ int m_delay;
+ bool m_printName;
+ bool m_printComments;
+ bool m_printProgress;
+ QString m_effectName;
+ bool m_loop;
+
+ bool m_ImagesHasComments;
+
+ QFont* m_commentsFont;
+ uint m_commentsFontColor;
+ uint m_commentsBgColor;
+ int m_commentsLinesLength;
+
+ bool m_enableMouseWheel;
+
+ uint m_cacheSize;
+ // -------------------------
+
+ QMap<QString, EffectMethod> Effects;
+
+ SlideShowLoader* m_imageLoader;
+ QPixmap* m_currImage;
+
+ FileList m_fileList;
+ QStringList m_commentsList;
+ QTimer* m_timer;
+ int m_fileIndex;
+
+ EffectMethod m_effect;
+ bool m_effectRunning;
+
+ int m_commentsLinesLenght;
+
+ // values for state of various effects:
+ int m_x, m_y, m_w, m_h, m_dx, m_dy, m_ix, m_iy, m_i, m_j, m_subType;
+ int m_x0, m_y0, m_x1, m_y1, m_wait;
+ double m_fx, m_fy, m_alpha, m_fd;
+ int* m_intArray;
+ QPainter m_painter;
+
+ ToolBar* m_toolBar;
+ QTimer* m_mouseMoveTimer;
+ bool m_endOfShow;
+
+ int m_deskX;
+ int m_deskY;
+ int m_deskWidth;
+ int m_deskHeight;
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif /* SLIDESHOW_H */
diff --git a/kipi-plugins/slideshow/slideshowconfig.cpp b/kipi-plugins/slideshow/slideshowconfig.cpp
new file mode 100644
index 0000000..033fafa
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowconfig.cpp
@@ -0,0 +1,785 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-02-17
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qmap.h>
+#include <qframe.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+#include <qcolor.h>
+#include <qnamespace.h>
+#include <qlistbox.h>
+#include <qfileinfo.h>
+
+// Kde includes.
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kfontdialog.h>
+#include <kcolorbutton.h>
+#include <kio/previewjob.h>
+#include <kurl.h>
+
+// libkipi includes
+
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "listimageitems.h"
+#include "slideshow.h"
+#include "slideshowgl.h"
+#include "slideshowkb.h"
+#include "slideshowconfig.h"
+#include "slideshowconfig.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+SlideShowConfig::SlideShowConfig(bool allowSelectedOnly, KIPI::Interface * interface,
+ QWidget *parent, const char* name, bool ImagesHasComments,
+ KURL::List *urlList)
+ : SlideShowConfigBase(parent, name)
+{
+ // About data and help button.
+
+ KIPIPlugins::KPAboutData * about = new KIPIPlugins::KPAboutData(I18N_NOOP("Slide Show"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for image slideshow"),
+ "(c) 2003-2004, Renchi Raju\n(c) 2007, Valerio Fuoglio");
+
+ about->addAuthor("Renchi Raju", I18N_NOOP("Author"),
+ "renchi@pooh.tam.uiuc.edu");
+ about->addAuthor("Valerio Fuoglio", I18N_NOOP("Author and maintainer"),
+ "valerio.fuoglio@gmail.com");
+
+ KHelpMenu* helpMenu = new KHelpMenu(this, about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ // Switch to selected files only (it depends on allowSelectedOnly)
+
+ m_selectedFilesButton->setEnabled( allowSelectedOnly );
+
+ m_delayMsMaxValue = 100000;
+ m_delayMsMinValue = 100;
+ m_delayMsLineStep = 10;
+
+ m_delaySpinBox->setMinValue(m_delayMsMinValue);
+ m_delaySpinBox->setMaxValue(m_delayMsMaxValue);
+ m_delaySpinBox->setLineStep(m_delayMsLineStep);
+
+ m_interface = interface;
+
+ // Signal to Slot connections
+
+ connect(m_openglCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotOpenGLToggled()));
+ connect(m_buttonStart, SIGNAL(clicked()), this, SLOT(slotStartClicked()));
+ connect(m_printCommentsCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotPrintCommentsToggled()));
+ connect(m_commentsFontColor, SIGNAL(changed(const QColor &)), this, SLOT(slotCommentsFontColorChanged()));
+ connect(m_commentsBgColor, SIGNAL(changed(const QColor &)), this, SLOT(slotCommentsBgColorChanged()));
+ connect(m_useMillisecondsCheckBox, SIGNAL(toggled(bool)), SLOT(slotUseMillisecondsToggled()));
+ connect(m_delaySpinBox, SIGNAL(valueChanged(int)), this, SLOT(slotDelayChanged()));
+ connect(m_effectsComboBox, SIGNAL(activated(int)), this, SLOT(slotEffectChanged()));
+
+ connect(m_fileSrcButtonGroup, SIGNAL(clicked(int)), this, SLOT(slotSelection()));
+
+ connect( m_ImagesFilesListBox, SIGNAL( currentChanged( QListBoxItem * ) ),
+ this, SLOT( slotImagesFilesSelected(QListBoxItem *) ) );
+ connect(m_ImagesFilesListBox, SIGNAL( addedDropItems(KURL::List) ),
+ this, SLOT( slotAddDropItems(KURL::List)));
+ connect( m_ImagesFilesButtonAdd, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonAdd() ) );
+ connect( m_ImagesFilesButtonDelete, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonDelete() ) );
+ connect( m_ImagesFilesButtonUp, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonUp() ) );
+ connect( m_ImagesFilesButtonDown, SIGNAL( clicked() ),
+ this, SLOT( slotImagesFilesButtonDown() ) );
+
+ connect(m_cacheCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotCacheToggled()));
+
+ m_thumbJob = 0L;
+
+ // Configuration file management
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("SlideShow Settings");
+
+ readSettings();
+
+ slotUseMillisecondsToggled();
+
+ // Comments tab management
+
+ m_commentsFontChooser->setSampleText(
+ i18n("Slideshow is part of KIPI-Plugins (http://www.kipi-plugins.org)"));
+
+ // Host application images has comments
+ if ( ! ImagesHasComments ) {
+ m_printCommentsCheckBox->setEnabled(FALSE);
+ m_tabWidget->setTabEnabled(commentsTab, FALSE);
+ }
+
+ m_urlList = urlList;
+
+ slotSelection();
+ slotEffectChanged();
+}
+
+SlideShowConfig::~SlideShowConfig()
+{
+ if ( m_thumbJob ) delete m_thumbJob;
+ if ( m_config ) delete m_config;
+}
+
+void SlideShowConfig::loadEffectNames()
+{
+ m_effectsComboBox->clear();
+
+ QMap<QString,QString> effectNames = SlideShow::effectNamesI18N();
+ QStringList effects;
+
+ QMap<QString,QString>::Iterator it;
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.append(it.data());
+
+ m_effectsComboBox->insertStringList(effects);
+
+ for (int i=0; i<m_effectsComboBox->count(); i++) {
+ if (effectNames[m_effectName] == m_effectsComboBox->text(i)) {
+ m_effectsComboBox->setCurrentItem(i);
+ break;
+ }
+ }
+}
+
+void SlideShowConfig::loadEffectNamesGL()
+{
+ m_effectsComboBox->clear();
+
+ QStringList effects;
+ QMap<QString,QString> effectNames;
+ QMap<QString,QString>::Iterator it;
+
+ // Load slideshowgl effects
+ effectNames = SlideShowGL::effectNamesI18N();
+
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.append(it.data());
+
+ // Load Ken Burns effect
+ effectNames = SlideShowKB::effectNamesI18N();
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.append(it.data());
+
+ // Update GUI
+
+ effects.sort();
+ m_effectsComboBox->insertStringList(effects);
+
+ for (int i=0; i<m_effectsComboBox->count(); i++) {
+ if (effectNames[m_effectNameGL] == m_effectsComboBox->text(i)) {
+ m_effectsComboBox->setCurrentItem(i);
+ break;
+ }
+ }
+}
+
+
+void SlideShowConfig::readSettings()
+{
+ bool opengl;
+ int delay;
+ bool printFileName;
+ bool printProgress;
+ bool printFileComments;
+ bool loop;
+ bool shuffle;
+ bool showSelectedFilesOnly;
+ bool useMilliseconds;
+ bool enableMouseWheel;
+
+ opengl = m_config->readBoolEntry("OpenGL", false);
+ delay = m_config->readNumEntry("Delay", 1500);
+ printFileName = m_config->readBoolEntry("Print Filename", true);
+ printProgress = m_config->readBoolEntry("Print Progress Inticator", true);
+ printFileComments = m_config->readBoolEntry("Print Comments", false);
+ loop = m_config->readBoolEntry("Loop", false);
+ shuffle = m_config->readBoolEntry("Shuffle", false);
+ showSelectedFilesOnly = m_config->readBoolEntry("Show Selected Files Only", false);
+ m_effectName = m_config->readEntry("Effect Name", "Random");
+ m_effectNameGL = m_config->readEntry("Effect Name (OpenGL)", "Random");
+
+ useMilliseconds = m_config->readBoolEntry("Use Milliseconds", false);
+ enableMouseWheel = m_config->readNumEntry("Enable Mouse Wheel", true);
+
+
+ // Comments tab settings
+ uint commentsFontColor;
+ uint commentsBgColor;
+ int commentsLinesLength;
+
+ QFont *savedFont = new QFont();
+ savedFont->setFamily(m_config->readEntry("Comments Font Family"));
+ savedFont->setPointSize(m_config->readNumEntry("Comments Font Size", 10 ));
+ savedFont->setBold(m_config->readBoolEntry("Comments Font Bold", false));
+ savedFont->setItalic(m_config->readBoolEntry("Comments Font Italic", false));
+ savedFont->setUnderline(m_config->readBoolEntry("Comments Font Underline", false));
+ savedFont->setOverline(m_config->readBoolEntry("Comments Font Overline", false));
+ savedFont->setStrikeOut(m_config->readBoolEntry("Comments Font StrikeOut", false));
+ savedFont->setFixedPitch(m_config->readBoolEntry("Comments Font FixedPitch", false));
+
+ commentsFontColor = m_config->readUnsignedNumEntry("Comments Font Color", 0xffffff);
+ commentsBgColor = m_config->readUnsignedNumEntry("Comments Bg Color", 0x000000);
+
+ commentsLinesLength = m_config->readNumEntry("Comments Lines Length", 72);
+
+ // Advanced tab
+ bool enableCache, kbDisableFadeInOut, kbDisableCrossFade;
+
+ kbDisableFadeInOut = m_config->readBoolEntry("KB Disable FadeInOut", false);
+ kbDisableCrossFade = m_config->readBoolEntry("KB Disable Crossfade", false);
+
+ enableCache = m_config->readBoolEntry("Enable Cache", false);
+ m_cacheSize = m_config->readNumEntry("Cache Size", 5);
+
+
+ // -- Apply Settings to widgets ------------------------------
+
+ m_openglCheckBox->setChecked(opengl);
+
+ m_delaySpinBox->setValue(delay);
+
+ m_printNameCheckBox->setChecked(printFileName);
+
+ m_printProgressCheckBox->setChecked(printProgress);
+
+ m_printCommentsCheckBox->setChecked(printFileComments);
+
+ m_loopCheckBox->setChecked(loop);
+
+ m_shuffleCheckBox->setChecked(shuffle);
+
+ m_enableMouseWheelCheckBox->setChecked(enableMouseWheel);
+ m_useMillisecondsCheckBox->setChecked(useMilliseconds);
+
+ if (showSelectedFilesOnly && m_selectedFilesButton->isEnabled() )
+ m_selectedFilesButton->setChecked(true);
+ else
+ m_allFilesButton->setChecked(true);
+
+ m_commentsLinesLengthSpinBox->setValue(commentsLinesLength);
+ m_commentsFontColor->setColor(QColor(commentsFontColor));
+ m_commentsBgColor->setColor(QColor(commentsBgColor));
+ m_commentsFontChooser->setFont(*savedFont);
+ delete savedFont;
+
+ m_kbDisableFadeCheckBox->setChecked(kbDisableFadeInOut);
+ m_kbDisableCrossfadeCheckBox->setChecked(kbDisableCrossFade);
+
+ m_cacheCheckBox->setChecked(enableCache);
+
+ slotOpenGLToggled();
+ slotCacheToggled();
+}
+
+void SlideShowConfig::saveSettings()
+{
+ if (!m_config) return;
+
+ m_config->writeEntry("OpenGL", m_openglCheckBox->isChecked());
+
+ // Delay will be always saved as millisecond value, to keep compatibility
+ if ( m_useMillisecondsCheckBox->isChecked() )
+ m_config->writeEntry("Delay", m_delaySpinBox->value());
+ else
+ m_config->writeEntry("Delay", m_delaySpinBox->value()*1000);
+
+ m_config->writeEntry("Print Filename", m_printNameCheckBox->isChecked());
+ m_config->writeEntry("Print Progress Indicator", m_printProgressCheckBox->isChecked());
+ m_config->writeEntry("Print Comments", m_printCommentsCheckBox->isChecked());
+ m_config->writeEntry("Loop", m_loopCheckBox->isChecked());
+ m_config->writeEntry("Shuffle", m_shuffleCheckBox->isChecked());
+ m_config->writeEntry("Show Selected Files Only", m_selectedFilesButton->isChecked());
+
+ m_config->writeEntry("Use Milliseconds", m_useMillisecondsCheckBox->isChecked());
+ m_config->writeEntry("Enable Mouse Wheel", m_enableMouseWheelCheckBox->isChecked());
+
+ // Comments tab settings
+ QFont* commentsFont = new QFont(m_commentsFontChooser->font());
+ m_config->writeEntry("Comments Font Family", commentsFont->family());
+ m_config->writeEntry("Comments Font Size", commentsFont->pointSize());
+ m_config->writeEntry("Comments Font Bold", commentsFont->bold());
+ m_config->writeEntry("Comments Font Italic", commentsFont->italic());
+ m_config->writeEntry("Comments Font Underline", commentsFont->underline());
+ m_config->writeEntry("Comments Font Overline", commentsFont->overline());
+ m_config->writeEntry("Comments Font StrikeOut", commentsFont->strikeOut());
+ m_config->writeEntry("Comments Font FixedPitch", commentsFont->fixedPitch());
+ delete commentsFont;
+
+ QColor* fontColor = new QColor(m_commentsFontColor->color());
+ uint commentsFontColorRGB = fontColor->rgb();
+ delete fontColor;
+ m_config->writeEntry("Comments Font Color", commentsFontColorRGB);
+
+ QColor* bgColor = new QColor(m_commentsBgColor->color());
+ uint commentsBgColorRGB = bgColor->rgb();
+ delete bgColor;
+ m_config->writeEntry("Comments Bg Color", commentsBgColorRGB);
+
+ m_config->writeEntry("Comments Lines Length", m_commentsLinesLengthSpinBox->value());
+
+ if (!m_openglCheckBox->isChecked()) {
+
+ QString effect;
+ QMap<QString,QString> effectNames = SlideShow::effectNamesI18N();
+ QMap<QString,QString>::Iterator it;
+
+ for (it = effectNames.begin(); it != effectNames.end(); ++it) {
+ if (it.data() == m_effectsComboBox->currentText()) {
+ effect = it.key();
+ break;
+ }
+ }
+
+ m_config->writeEntry("Effect Name", effect);
+
+ }
+ else
+ {
+ QMap<QString,QString> effects;
+ QMap<QString,QString> effectNames;
+ QMap<QString,QString>::Iterator it;
+
+ // Load slideshowgl effects
+ effectNames = SlideShowGL::effectNamesI18N();
+
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.insert(it.key(),it.data());
+
+ // Load Ken Burns effect
+ effectNames = SlideShowKB::effectNamesI18N();
+ for (it = effectNames.begin(); it != effectNames.end(); ++it)
+ effects.insert(it.key(),it.data());
+
+ QString effect;
+
+ for (it = effects.begin(); it != effects.end(); ++it) {
+ if ( it.data() == m_effectsComboBox->currentText()) {
+ effect = it.key();
+ break;
+ }
+ }
+
+ m_config->writeEntry("Effect Name (OpenGL)", effect);
+ }
+
+ // Advanced settings
+ m_config->writeEntry("KB Disable FadeInOut", m_kbDisableFadeCheckBox->isChecked());
+ m_config->writeEntry("KB Disable Crossfade", m_kbDisableCrossfadeCheckBox->isChecked());
+
+ m_config->writeEntry("Enable Cache", m_cacheCheckBox->isChecked());
+ m_config->writeEntry("Cache Size", m_cacheSizeSpinBox->value());
+
+ m_config->sync();
+}
+
+void SlideShowConfig::addItems(const KURL::List& fileList)
+{
+ if (fileList.isEmpty()) return;
+ KURL::List Files = fileList;
+
+ for ( KURL::List::Iterator it = Files.begin() ; it != Files.end() ; ++it )
+ {
+ KURL currentFile = *it;
+
+ QFileInfo fi(currentFile.path());
+ QString Temp = fi.dirPath();
+ QString albumName = Temp.section('/', -1);
+
+ KIPI::ImageInfo info = m_interface->info(currentFile);
+ QString comments = info.description();
+
+ ImageItem *item = new ImageItem( m_ImagesFilesListBox,
+ currentFile.path().section('/', -1 ), // File name with extension.
+ comments, // Image comments.
+ currentFile.path().section('/', 0, -1), // Complete path with file name.
+ albumName // Album name.
+ );
+
+ item->setName( currentFile.path().section('/', -1) );
+ }
+
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+ m_ImagesFilesListBox->setCurrentItem( m_ImagesFilesListBox->count()-1) ;
+ slotImagesFilesSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()));
+ m_ImagesFilesListBox->centerCurrentItem();
+}
+
+void SlideShowConfig::slotCommentsBgColorChanged()
+{
+ m_commentsFontChooser->setBackgroundColor(m_commentsBgColor->color());
+}
+
+void SlideShowConfig::slotCommentsFontColorChanged()
+{
+ m_commentsFontChooser->setColor(m_commentsFontColor->color());
+}
+
+void SlideShowConfig::slotPrintCommentsToggled()
+{
+ m_tabWidget->setTabEnabled(commentsTab, m_printCommentsCheckBox->isChecked());
+}
+
+void SlideShowConfig::slotUseMillisecondsToggled()
+{
+
+ int delayValue = m_delaySpinBox->value();
+
+ m_delaySpinBox->setValue(0);
+
+ if ( m_useMillisecondsCheckBox -> isChecked() ) {
+ m_delayLabel->setText(QString("Delay between images (ms):"));
+
+ m_delaySpinBox->setMinValue(m_delayMsMinValue);
+ m_delaySpinBox->setMaxValue(m_delayMsMaxValue);
+ m_delaySpinBox->setLineStep(m_delayMsLineStep);
+
+ m_delaySpinBox->setValue(delayValue*1000);
+ }
+ else {
+ m_delayLabel->setText(QString("Delay between images (s):"));
+
+ m_delaySpinBox->setMinValue(m_delayMsMinValue/1000);
+ m_delaySpinBox->setMaxValue(m_delayMsMaxValue/100);
+ m_delaySpinBox->setLineStep(m_delayMsLineStep/10);
+
+ m_delaySpinBox->setValue(delayValue/1000);
+ }
+}
+
+void SlideShowConfig::slotEffectChanged()
+{
+ bool isKB = m_effectsComboBox->currentText() == i18n("Ken Burns");
+
+ m_printNameCheckBox->setEnabled(!isKB);
+ m_printProgressCheckBox->setEnabled(!isKB);
+ m_printCommentsCheckBox->setEnabled(!isKB);
+
+ m_cacheButtonGroup->setEnabled(!isKB);
+}
+
+void SlideShowConfig::slotCacheToggled()
+{
+ bool isEnabled = m_cacheCheckBox->isChecked();
+
+ m_cacheSizeLabel1->setEnabled(isEnabled);
+ m_cacheSizeLabel2->setEnabled(isEnabled);
+ m_cacheSizeSpinBox->setEnabled(isEnabled);
+}
+
+void SlideShowConfig::slotOpenGLToggled()
+{
+ if (m_openglCheckBox->isChecked()) {
+ loadEffectNamesGL();
+ }
+ else {
+ loadEffectNames();
+ }
+
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+
+// slotEffectChanged();
+}
+
+void SlideShowConfig::slotDelayChanged()
+{
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+}
+
+void SlideShowConfig::slotSelection()
+{
+ KURL::List urlList;
+ if (m_selectedFilesButton->isChecked())
+ {
+ urlList = m_interface->currentSelection().images();
+
+ m_ImagesFilesButtonAdd->setEnabled(FALSE);
+ m_ImagesFilesButtonDelete->setEnabled(FALSE);
+ m_ImagesFilesButtonUp->setEnabled(FALSE);
+ m_ImagesFilesButtonDown->setEnabled(FALSE);
+ }
+ else
+ if (m_allFilesButton->isChecked())
+ {
+ KURL currentPath = m_interface->currentAlbum().path();
+ QValueList<KIPI::ImageCollection> albumList;
+ albumList = m_interface->allAlbums();
+ QValueList<KIPI::ImageCollection>::iterator it;
+
+ urlList = m_interface->currentAlbum().images();
+ for ( it = albumList.begin(); it != albumList.end(); ++it )
+ if (currentPath.isParentOf((*it).path()) && !((*it).path() == currentPath))
+ urlList += (*it).images();
+
+ m_ImagesFilesButtonAdd->setEnabled(FALSE);
+ m_ImagesFilesButtonDelete->setEnabled(FALSE);
+ m_ImagesFilesButtonUp->setEnabled(FALSE);
+ m_ImagesFilesButtonDown->setEnabled(FALSE);
+ }
+
+ if ( m_customButton->isChecked() ) // Custom selected
+ {
+ m_ImagesFilesButtonAdd->setEnabled(TRUE);
+ m_ImagesFilesButtonDelete->setEnabled(TRUE);
+ m_ImagesFilesButtonUp->setEnabled(TRUE);
+ m_ImagesFilesButtonDown->setEnabled(TRUE);
+ }
+ else
+ {
+ if (!urlList.isEmpty())
+ {
+ m_ImagesFilesListBox->clear();
+ addItems(urlList);
+ }
+ }
+}
+
+void SlideShowConfig::slotImagesFilesSelected( QListBoxItem *item )
+{
+
+ if ( !item || m_ImagesFilesListBox->count() == 0 )
+ {
+ m_label7->setText("");
+ m_ImageLabel->clear();
+ return;
+ }
+
+ ImageItem *pitem = static_cast<ImageItem*>( item );
+
+ if ( !pitem ) return;
+
+ KURL url;
+ url.setPath(pitem->path());
+
+ m_ImageLabel->clear();
+
+ if ( m_thumbJob ) delete m_thumbJob;
+
+ m_thumbJob = KIO::filePreview( url, m_ImageLabel->width() );
+
+ connect(m_thumbJob, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)),
+ SLOT(slotGotPreview(const KFileItem*, const QPixmap&)));
+ connect(m_thumbJob, SIGNAL(failed(const KFileItem*)),
+ SLOT(slotFailedPreview(const KFileItem*)));
+
+ int index = m_ImagesFilesListBox->index ( item );
+ m_label7->setText(i18n("Image no. %1").arg(index + 1));
+}
+
+void SlideShowConfig::slotAddDropItems(KURL::List filesUrl)
+{
+ addItems(filesUrl);
+}
+
+void SlideShowConfig::slotImagesFilesButtonAdd( void )
+{
+ KURL::List ImageFilesList =
+ KIPI::ImageDialog::getImageURLs( this, m_interface );
+ if ( !ImageFilesList.isEmpty() )
+ addItems( ImageFilesList );
+}
+
+void SlideShowConfig::slotImagesFilesButtonDelete( void )
+{
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ {
+ if (m_ImagesFilesListBox->isSelected(i))
+ {
+ m_ImagesFilesListBox->removeItem(i);
+ m_ImagesFilesListBox->setCurrentItem(i);
+ --i;
+ }
+ }
+
+ m_ImagesFilesListBox->setSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()), true);
+ slotImagesFilesSelected(m_ImagesFilesListBox->item(m_ImagesFilesListBox->currentItem()));
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+}
+
+void SlideShowConfig::slotImagesFilesButtonUp( void )
+{
+ int Cpt = 0;
+
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ if (m_ImagesFilesListBox->isSelected(i))
+ ++Cpt;
+
+ if (Cpt == 0)
+ return;
+
+ if (Cpt > 1)
+ {
+ KMessageBox::error(this, i18n("You can only move up one image file at once."));
+ return;
+ }
+
+ unsigned int Index = m_ImagesFilesListBox->currentItem();
+
+ if (Index == 0)
+ return;
+
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(Index) );
+ QString path(pitem->path());
+ QString comment(pitem->comments());
+ QString name(pitem->name());
+ QString album(pitem->album());
+ m_ImagesFilesListBox->removeItem(Index);
+ ImageItem *item = new ImageItem( 0, name, comment, path, album );
+ item->setName( name );
+ m_ImagesFilesListBox->insertItem(item, Index-1);
+ m_ImagesFilesListBox->setSelected(Index-1, true);
+ m_ImagesFilesListBox->setCurrentItem(Index-1);
+}
+
+void SlideShowConfig::slotImagesFilesButtonDown( void )
+{
+ int Cpt = 0;
+
+ for (uint i = 0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ if (m_ImagesFilesListBox->isSelected(i))
+ ++Cpt;
+
+ if (Cpt == 0)
+ return;
+
+ if (Cpt > 1)
+ {
+ KMessageBox::error(this, i18n("You can only move down one image file at once."));
+ return;
+ }
+
+ unsigned int Index = m_ImagesFilesListBox->currentItem();
+
+ if (Index == m_ImagesFilesListBox->count())
+ return;
+
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(Index) );
+ QString path(pitem->path());
+ QString comment(pitem->comments());
+ QString name(pitem->name());
+ QString album(pitem->name());
+ m_ImagesFilesListBox->removeItem(Index);
+ ImageItem *item = new ImageItem( 0, name, comment, path, album );
+ item->setName( name );
+ m_ImagesFilesListBox->insertItem(item, Index+1);
+ m_ImagesFilesListBox->setSelected(Index+1, true);
+ m_ImagesFilesListBox->setCurrentItem(Index+1);
+}
+
+void SlideShowConfig::ShowNumberImages( int Number )
+{
+ QTime TotalDuration (0, 0, 0);
+
+ int TransitionDuration = 2000;
+
+ if ( m_openglCheckBox->isChecked() )
+ TransitionDuration += 500;
+
+ if ( m_useMillisecondsCheckBox->isChecked() )
+ TotalDuration = TotalDuration.addMSecs(Number * m_delaySpinBox->text().toInt());
+ else
+ TotalDuration = TotalDuration.addSecs(Number * m_delaySpinBox->text().toInt());
+
+ TotalDuration = TotalDuration.addMSecs((Number-1)*TransitionDuration);
+
+ if ( Number < 2)
+ m_label6->setText(i18n("%1 image [%2]").arg(Number).arg(TotalDuration.toString()));
+ else
+ m_label6->setText(i18n("%1 images [%2]").arg(Number).arg(TotalDuration.toString()));
+}
+
+void SlideShowConfig::slotGotPreview(const KFileItem*, const QPixmap &pixmap)
+{
+ m_ImageLabel->setPixmap(pixmap);
+ m_thumbJob = 0L;
+}
+
+void SlideShowConfig::slotFailedPreview(const KFileItem*)
+{
+ m_thumbJob = 0L;
+}
+
+void SlideShowConfig::SlotPortfolioDurationChanged ( int )
+{
+ ShowNumberImages( m_ImagesFilesListBox->count() );
+}
+
+void SlideShowConfig::slotStartClicked()
+{
+ saveSettings();
+
+ for (uint i=0 ; i < m_ImagesFilesListBox->count() ; ++i)
+ {
+ ImageItem *pitem = static_cast<ImageItem*>( m_ImagesFilesListBox->item(i) );
+ if (!QFile::exists(pitem->path()))
+ {
+ KMessageBox::error(this,
+ i18n("Cannot access to file %1, please check the path is right.").arg(pitem->path()));
+ return;
+ }
+ m_urlList->append(pitem->path()); // Input images files.
+ }
+
+ emit buttonStartClicked();
+}
+
+
+void SlideShowConfig::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("slideshow",
+ "kipi-plugins");
+}
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/slideshowconfig.h b/kipi-plugins/slideshow/slideshowconfig.h
new file mode 100644
index 0000000..b3c2ca9
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowconfig.h
@@ -0,0 +1,121 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2003-02-17
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SLIDESHOWCONFIG_H
+#define SLIDESHOWCONFIG_H
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qlistbox.h>
+
+// KDE includes
+
+#include <kconfig.h>
+#include <kio/previewjob.h>
+#include <kurl.h>
+
+// libkipi includes
+
+#include <libkipi/imagedialog.h>
+#include <libkipi/interface.h>
+
+// Local includes
+
+#include "slideshowconfigbase.h"
+
+namespace KIPISlideShowPlugin
+{
+
+class SlideShowConfig : public SlideShowConfigBase
+{
+ Q_OBJECT
+
+public:
+
+ SlideShowConfig(bool allowSelectedOnly, KIPI::Interface* interface,
+ QWidget *parent, const char* name, bool ImagesHasComments,
+ KURL::List* urlList);
+ ~SlideShowConfig();
+
+private slots:
+
+ void slotStartClicked();
+ void slotHelp();
+ void slotOpenGLToggled();
+ void slotEffectChanged();
+ void slotDelayChanged();
+ void slotUseMillisecondsToggled();
+ void slotPrintCommentsToggled();
+ void slotCommentsFontColorChanged();
+ void slotCommentsBgColorChanged();
+
+ void slotSelection();
+ void slotCacheToggled();
+
+ void SlotPortfolioDurationChanged ( int );
+ void slotImagesFilesSelected( QListBoxItem *item );
+ void slotAddDropItems(KURL::List filesUrl);
+ void slotImagesFilesButtonAdd( void );
+ void slotImagesFilesButtonDelete( void );
+ void slotImagesFilesButtonUp( void );
+ void slotImagesFilesButtonDown( void );
+ void slotGotPreview(const KFileItem* , const QPixmap &pixmap);
+ void slotFailedPreview(const KFileItem*);
+
+signals:
+
+ void buttonStartClicked(); // Signal needed by plugin_slideshow class
+
+private:
+
+ void loadEffectNames();
+ void loadEffectNamesGL();
+ void readSettings();
+ void saveSettings();
+
+ void ShowNumberImages( int Number );
+ void addItems(const KURL::List& fileList);
+
+private:
+
+ int m_delayMsMaxValue;
+ int m_delayMsMinValue;
+ int m_delayMsLineStep;
+
+ uint m_cacheSize;
+
+ KConfig* m_config;
+
+ QString m_effectName;
+ QString m_effectNameGL;
+
+ KIO::PreviewJob* m_thumbJob;
+ KURL::List* m_urlList;
+
+ KIPI::Interface* m_interface;
+};
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // SLIDESHOWCONFIG_H
diff --git a/kipi-plugins/slideshow/slideshowconfigbase.ui b/kipi-plugins/slideshow/slideshowconfigbase.ui
new file mode 100644
index 0000000..4c18fb1
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowconfigbase.ui
@@ -0,0 +1,1522 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KIPISlideShowPlugin::SlideShowConfigBase</class>
+<widget class="KDialog">
+ <property name="name">
+ <cstring>SlideShowConfigBase</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>678</width>
+ <height>640</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Slideshow</string>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="modal">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>m_tabWidget</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>mainTab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Main</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>m_fileSrcButtonGroup</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_allFilesButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Show all images in current al&amp;bum</string>
+ </property>
+ <property name="accel">
+ <string>Alt+B</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_selectedFilesButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Show onl&amp;y selected images</string>
+ </property>
+ <property name="accel">
+ <string>Alt+Y</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_customButton</cstring>
+ </property>
+ <property name="text">
+ <string>Custom</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_ImagesFilesGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Image Files in slideshow</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Preview the currently selected image.</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIPISlideShowPlugin::ListImageItems">
+ <property name="name">
+ <cstring>m_ImagesFilesListBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the list of the image files for your portfolio.
+The portfolio's first image is on the top; the last image is on the bottom.
+If you want to add some images, click on the 'Add' button or use the drag-and-drop.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_label6</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>None</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Total number of images in the portfolio and sequence duration.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonAdd</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Add...</string>
+ </property>
+ <property name="accel">
+ <string>Alt+A</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Add some image files to the portfolio list.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonDelete</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Delete</string>
+ </property>
+ <property name="accel">
+ <string>Alt+D</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Remove some image files from the portfolio list.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonUp</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Image &amp;Up</string>
+ </property>
+ <property name="accel">
+ <string>Alt+U</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Moving the current image up on the portfolio list.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>m_ImagesFilesButtonDown</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Image D&amp;own</string>
+ </property>
+ <property name="accel">
+ <string>Alt+O</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Moving the current image down on the portfolio list.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_ImageLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>128</width>
+ <height>128</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Preview the currently selected image.</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_label7</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>None</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Currently selected image in the portfolio list.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout50</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout47</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Video options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_openglCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>238</width>
+ <height>33</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Use Open&amp;GL slideshow transitions</string>
+ </property>
+ <property name="accel">
+ <string>Alt+G</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer59</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>2</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Content options</string>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_printNameCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>P&amp;rint filename</string>
+ </property>
+ <property name="accel">
+ <string>Alt+R</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_printProgressCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Progress indicator</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_printCommentsCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Pr&amp;int captions </string>
+ </property>
+ <property name="accel">
+ <string>Alt+I</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer58</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Playback options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_loopCheckBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Loop</string>
+ </property>
+ <property name="accel">
+ <string>Alt+L</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_shuffleCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>&amp;Shuffle images</string>
+ </property>
+ <property name="accel">
+ <string>Alt+S</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout48</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_delayLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Delay between images (s):</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_delaySpinBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="maxValue">
+ <number>100000</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="lineStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout49</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>label2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Transition effect:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>m_effectsComboBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ <property name="currentItem">
+ <number>0</number>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer57</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>2</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>commentsTab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Comments</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KFontChooser">
+ <property name="name">
+ <cstring>m_commentsFontChooser</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout57</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox7</cstring>
+ </property>
+ <property name="title">
+ <string>Colors</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout52</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Font color :</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer62</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>15</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_commentsFontColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="defaultColor">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout51</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer61</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>15</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_commentsBgColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer66</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>81</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout55</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Line length (in characters) :</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer65</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>15</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_commentsLinesLengthSpinBox</cstring>
+ </property>
+ <property name="buttonSymbols">
+ <enum>UpDownArrows</enum>
+ </property>
+ <property name="maxValue">
+ <number>500</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>72</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer12</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Advanced</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox5</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Interface</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_useMillisecondsCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Use milliseconds instead of seconds</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox8</cstring>
+ </property>
+ <property name="title">
+ <string>Controls</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_enableMouseWheelCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Enable mouse wheel (move between images)</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup3</cstring>
+ </property>
+ <property name="title">
+ <string>Ken Burns effect</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_kbDisableFadeCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Disable fade-in / fade-out</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_kbDisableCrossfadeCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Disable crossfade</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>m_cacheButtonGroup</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="title">
+ <string>Others</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_cacheCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Enable cache</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_cacheSizeLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Cache size:</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer14_4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>31</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_cacheSizeSpinBox</cstring>
+ </property>
+ <property name="maxValue">
+ <number>20</number>
+ </property>
+ <property name="minValue">
+ <number>5</number>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_cacheSizeLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>images</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_KBCacheLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Notice&lt;/b&gt;:
+Ken Burns effect doesn't use this cache mechanism.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer10_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>41</width>
+ <height>90</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>50</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="0" column="3">
+ <property name="name">
+ <cstring>m_buttonExit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Exit</string>
+ </property>
+ <property name="accel">
+ <string>Alt+E</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>m_buttonStart</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Start Slideshow</string>
+ </property>
+ <property name="accel">
+ <string>Alt+S</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="0">
+ <property name="name">
+ <cstring>m_helpButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Help</string>
+ </property>
+ <property name="accel">
+ <string>F1</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KIPISlideShowPlugin::ListImageItems</class>
+ <header location="local">listimageitems.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image1</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="13969">89504e470d0a1a0a0000000d4948445200000080000000800806000000c33e61cb0000200049444154789ced9d77785cc5b9ff3fa7ecaeb4eabd59cd1d775cc102dc30d52114d10288d0434202f64d4808218d7b93c0bd84248484104288136ac0178c31bd1830dd185cb071b7254b966c6955b6ef39677e7f9cddd5566955b0b93ffc7d9ef39c3667e69cf9bef3ce3b33efcc91388a94b162e9b27c4992a6e49665970b43741b86d1e577073aceb8fdd79b8ff4bb0d16d2917e812f33562c5d9667b35baf43e23a9fcb5f4d92fc921559a467a7b5dbd22d9f671566bc5836b6f83fcbeb1ac4617edd41e1a80024c08aa5cb0a54abfaa8e6d7160fe679d5aa88bcf29cf74a47172d1d73e675ef0ff7fb0d278e0a400c56fdf887dfd6fcfaef0cddb0445ecfabaaa478cc18b24af249cbcc40b5d9f0bbba71b61da2f3401b8ec603380f1e421846f8195991c9afc8d99a57967df9e48b6efce0b07f4c0a382a001158f9a39b7fa7f9b41b43e7b2aa3276e10246cf3b094bba1d8440204004370422e258f3ba68dfb98d1d6f7fc0a15dfbc2f12a1685a2eabc753925d9674cacbfa1ed087c5a521c15802056fef0073fd4fcfa6f42e7c563c732fda20b49cfcd352ff4437eecfd80d74dd3c7ebd8fcc2eb189a0e80cd6e350a2a73ff5932b2f0dada53aef61f81cf8cc3510100562c5d361f783d743eeaa4139972f6d9bd01844008237c6c926f441c03c2202c0811421170f7b0fd8d37d9f9eefa6078b0e7a67baa26955d39e1bc1b1e3b3c5f981c5f790158b17499a258941d7a40af012839663cc75f7d359214cc9a21901fa911bcdd5d6c787a156d3bf60220c9124535f91f1755e79f3ceeaceb1d87f9b3c3908f54c25f16c88a7c6d88fcf4bc5c6637340c3bf908812d2b8b59975ec88cf34f435615842168dbd53e7dcffaa6d68f97fff69ac3ffe526bed21a60c5d26559b222371bba910930e78a2b289f3cc9bc398ce487cf837b6f673beb573c4747632b00b2225131bee4d98a634aebcbeb1a0eab6df095d600b2227f2b447ed198d126f942803082e4f71e87c90f911d3c17b1e48b24e487c31ad872f29873f9c51cb3681600862e68dc7ce06b3b3f6adcb7efb507c71fce3cf8ca6a80154b97c98a4569d6037a8924cb2c58b694ecb2328829ad91e4c6113ae0b0bd1ac50c6be0d8bb9b754fbe48c0e30320bb384bab9a5476ced8af7d6bd5e1c887afb20638550fe82500d573669be447a8f894c91703203f2aac799e5b59cd89d75c44de886200badb7ad41d1fec5db9e9893ffce47064c257560054ab720b80a4281c73eaa908c38852dfb1c7890935ab09113a8eaa2e82e71810653bf49e87d2b0666432fb1be7523dc3d4fe5ea74fdaf951e3edeb1ebaebb1e6b5cbbf502dfd951480154b97156a7ebd0ea062ca14ac191908c308d687d11d3c894b768850620cc3e41d4342248837326e4962fca2794c387926007a4067df86e60b9bb7b5bdd5bc76b9ed8bca8bafa40020712ec16faf9d7b7c906448484c42f283a163c927494b80e8f8e204251c06461c7b2c934f9b832449082168dcd852d7b2e3e0a75f94107c250540b5aa5703e4545490575585d075a448f58c11b6d823557b587593a855d047f591e81e912d88882a01289b34892967cc41924d21d8f769f3b8966d6d1f36af5d9e36dc79f1956b05ac58baac006803e469f5f554ce980e4220ab520431906a1bdfdbb985271efc25bb0f2a14955410f0b938d4ba97f6d6dda8aa4a6141018b4f3e9919732f464e2f4ca0058c60d4a1348c703a07b76d65c3eaf73174034992a89c5cf649f9d8e239c3d957a00e5744ff6720712e02d9929646f994c908219024064cbef3c047ac7aea8f94574fe0bc4b6fc0220790f46e64dd89e4cca463c72e9adbbdb47434b27ecd035c7ff31f38767c2e0b4e98c9c5d7fe1e53f9864a3ec4928f10148d1ecb94d3fc7cbafae35075300d78b779edf2e3caeb1a02c3931d5f31acfce1cdef697e6d4ecd9c394cfafa5908c3405165242975f23f597d33ba7d0cb38e9f876c3841eb3137dd055a37b876205a9f8b4ad7ed3378e4352f7f5deda1ba3c9bdffcea2eca6b8f4b4a7eb88a3074f67fbc8ead6f6d35239260e48caa778b6af3eb2ae60eddebe82b6503ac58ba2c5f0b68b3002a674c47e83a2082f57f0409c9ea6dc3cfaa07afa672e242e6d42d44161ed0dca07b4cf27517e86e107a4cca02bb4de2ead3d379edbff350848b53cfbb8a375ff80b10b23112a729215131752a23269487a262efa7fb8f771e74fd6c38f2e42b2500c03908e4ecb232b2cbcac2ea3f69074f5433d0e05ffff335e69c720d2515e37ac9365ca03941f782e63205424416cce8429a9126f18f9bb329cd93f98f5fdc8ba36d6fdfcd4704c80aa3e64e27bb3013309b888d9b5b6e6b7af3a121771b7fa50440b5aad741b0f40b81300c64594a817cc1e637ff884f29a6acb4c4245a0f12afb9c0f080ee3405427783e10ba69858435b15899f5d9a49578fc69dbf5e16df248c7b1f03353d8363164c41b12800741f74ca2ddb0e3edfbc76f990ecb8af8c00ac58baac44f36b332d6969544c9d6a76fcc890acdd1ed501a47bb9f3ee3f70e925df30c936426adf1d3c764554036e44c04132f24397678db32049f0bfaf6d47d3b4089bc388233ff43ef6a23246cea80947b57f6b6b8dbbdb7beb50f265d85b01f5f5f569c02460e230c43f64232784669f7754b92d4daa9a350bc562411802459523323b79efdeba57efa5bd4b909157132ce9bd64a305052174aebb2090c0bf23e64bac168124491886a0b3d341417e3ed1fd01f11d479224513e691c6dbbdae86aebc1d00d9ab7b6feb879edf27bcbeb1a0e0d265f864d00eaebeb47003703d7025f58d7e560e1d4b503b2aa523d6736c230335696a5947af7366dfc98821cb9b7d4c794f8decd83d05de08fe1224e8c051f7eae6118e68d4ec7410af273fb243f742c5bd2187ddc38d63dfb110838d4e8b01654e6dd035c3c987c191601a8afaf3f1d7802c8cccfcda5acb8989cec6c4c0babd7aa0ee543a4c52b42e7e68de86ba11299e89960f86471879e75bbdd34b7b6a2084a2ba64cc16acf4008034595a24a7ec22a20782c2b36d66ded46efda8c925668aa79cd851412022da8fa75a759fa75576fe64491df7bf2e7551e00f273ed5455d7c6373b230521e6fd324b4ac82fcfa5637f270868d9d67661f3dae53f2baf6bd83650ee862c00f5f5f517008fa9aacaf44993185156164598882129d97506183ed5b0465010244932fbfd0d1d21048a62494c7ee479703f79fa3c5cdee778fce1fbf8c6e5df05c3876444ab7da105fb003c8dbd999384fc475ff7b27693d99977d629c7615194b8929e8c7c1048b24af5b1a3e8d8bf0e80ee834ea9a3b9eb6ee0cc81f2372423b0bebebe0ef857467a3aa7ce9b277dd9c80f5d0728a8a9253d373748be045282cc4d40be1082a9732f62dab87c6eb9773b2f3cfe6be85a0fde9660c9ef41f80f82771fb87680d0cccc4942fe9b1b03fcf25fa6865055858b2ebc2e45f27b8d418420bbb484dcd29c70bc1dfbbb4e6d5ebb3c77a01c0e5a03d4d7d7e7032f288aa2cc9d354bb259ad83261f20dd6ec766b361b5d968debfbfcf78422365a90a0a40e9f871849a7e4aba2565f243c70ffc7d35679db5806bfea785d2bf3dc6826956164db372c2642bf6588b2701f95ebfe02fcf79f8ed536e84008b45e19e3b7e1156fffd916f1e87f2cb0049a27ada483a5f580f40c7fe4ec537a1f46ae07f06c2e350aa80ef0399d3274d222b2363c0e4cf98338731e3c79366b361b15aa322bef777bf0b3b68248a67e1e2c54c9e3a95e6fdfbd9b7772f7bf7eca1a9a9092d104898268062b522741dc522234182cc36c2192ca25a05022120b7a09855abdfe2e69b2ee69577b6f3e8eb1e1e7ddd832c49cc1aa7525ea0509a27539a27539227539c2bd3ead0693c68b0eb80ce136b7c61a34f9615eef8f92d9c74d229096c8e50b5440cf9f1f6494e592199f919383b5c189a417b53e7520e8700d4d7d7170337e664658911e5e5d2604a7e56561659595909e3ef2b9ec953a7326dfa74002aabaaa8acaaa2eec413d1759dc67dfbd8bd6b176fbff5569c00844857adca80c90f91929595cb9fffb69add3b3673cfdd3fe5a5b7b7e2f3fb797f6b0008c494fc0490244e9831869b6eba8509e32712f2118c233ff8ce7d910f026485aac9957cb6c61c27686f749407078ade4b95cbc16a809b01fb3163c6843f60306a3f1992c553565ecea2534e49f88ca228d4d4d6b2fee38fe3d2045300144bc8e41938f99142533bf218eebae7091082a6a6263e5df70a9fae7f8f4d5b77a2697af039f3f990119a694f63d9d2db9834694a449d3e78f243c7f95525586c3b08f8345c9d1e1c2d5d3f06ce4a95c8010b407d7d7d19f09ddcec6c515652220d86fcf07112248a27232383b3ce3d174551923eb7e68d37d8b86143620190242c568578f243c7c490df876116713ea2a29c8af2cb3863c9a571cff5868df401ec238db8e7e28f7b05d5dc64d54a6e590e07f7b403d0b1bfebf4e6b5cb73caeb1aba52e173301ae00740da84b1630755f2c3a4f4a10562e3916599b3ce3d97cccccca4cf6cdab89135afbf9ef05d0014e146ef3980303484a183a143f058080d9091240521c948b20c928c242b0842c7b2794f52a2fa3708698d505a41c253263492fc0402d717f92101ceaf2cea1580a64e75c484d22b81bb5321734002505f5f2f031767666488e2c2c2f8d21fcc84d163c7929199c9fa8f3e4a487e7f1a209499a16dd129a7505e5191346ce3be7dac7cfae9c482180cf3ec1f6ee44dfffea8e7168f8402fb4072009024d28f399dac13bf879a5f7dc4c94708724b7a5b7fba66d0d5daf3c50800701c505a515a9ab4e44f9a368d59c71d0740654d0dafbdf4129d0e479c00f485c870e3c68f67cab46949c33a1c0e1e7ff45102a11640024d04a05528f82d6ab0be87cc341871aa8c640873d38080b9179a40d20504005d849f4198b378dcdb9ec7bbfd350acebf0f6be5cc08bbe68b22df88681544930f028bdd863d371d77a7d9bbe8eef18e6d5ebb5c29af6b88754c88c3403b82ce05282b2e4e5cf2c78d0b930f50545ccc79175dc4ece38f27dd6e475155264e999272e9cfccca62f1e9a7270da7691a8ffceb5fb85cae3eab21003907e44205b94046c997a99c28a356c8a865326a898c5a2c612991514b24ac2512d62289b402415a31a495405a29a495817d0414cc16a8693e3a56dc80eeeda4d7713401f92211a149c80f911d477eafed104b7ee8fbf22bf2c3f9e27678ac988371fd62a01ae05c7b7abac8ceca921265762235adaa2ac7ce9cc9b133672284c0300c367cf2499f5a2074eff4254b484b4bee08fbfc73cf71e8e0c1bec98f4a478412c06e939104511b4220456cc92029903d51d0febe0bcfc69564ccb824258b3dec001a476e50cbc46890beaa80a87304b96539346d36ab3897c38da11bc7031b927e4410296b80fafafa69406d59717142f28510bcb7762d1e8f2779c605a75da75205cc9c3d9bea9a9aa461366fdac4c7ebd6f54b7e282d2998c95230699b353a334df28952f77d41b68092a6a0b5ef3ee2e40b21c82ac84292cdfcd535839e7657e2f6720c06a201be0e501a52ff31992d84c0ed72b1e6d557396dc9928411b85c2e5e7be9a50425331a8545459c387f7ed2fb0e87836757ae4c89fc702a91eeaf02fc3e7a89360061762f4bc17329d0b704183ed03d1a96b28983235fe8ec7efd9f6cdbb31f455550550baaaaa02a2a16ab85a9d36721178e0bbe6edfe423049222634bb7e07599834cee2eef9c3e3f20888108c05c4551446e76769f3d7f7b77efe6b38d1b99307972d4c3fbf6ece1e5175e60cef1c7b36bc78e3e0bd892af7f3d697b5fd7759efaf7bff17a3c29911fab01429bd345d479dcd60fbcad8024631b75524c09edbb83470ab8f868f5df59fbc62ba886871cbb8da2aab118c28fcfe360f781831ce83178e4f127e9f149d45414336bda24662f389dcca29a84e48340022c5102e0296f5ebb3cabbcaea1a7afef484900eaebeb2560764e569644e4404c82128810ac5db38611555564e798a355cd4d4dbcf9da6b5c74d965f47477f75b0514141626bdf7daabafd2d4d89832f9bd6989703d8f10b477082423a2156000e1e3bedfcfb517dcfbc03ef56ce4b49c18f2a389e9255fb071e5ef59b1f279ae3bdece4f2e998b54bb10b2cac1d70dfe1e445723e2d3e584245037e0f9cf1dfcf5e957f8d9df5e62e985759cddf03db34f2241b563b3dbe8c11c6974393c12300378a3af6f4955038c0672737372fa253f64e8c9b2695e747775f1e2ead57ced9c73d8b7670fafbcf0422a052c29f6eed93320f24302a06fd6f007b470e93e00ec6f136459217c312c2b12c1d183decb912f2d0419b32e23ebc41b239a677d906ff879e12fb7221fdcc45d3fbc028e39170c0dfc3de0eb01cd8308b8c37184a0c8b064bc9525e3adbcba23c04d8fbfcd932f7fc87fdf7e0b65b5137ac9377484a163b1f56a4d7797075d3366334c02300b20272bab5ff285104c9c3285cce040cf9bafbfce717575b41e38c0cbcf3f9fa064c643d3345435f1ab9d7bde79dc7bcf3df863dafdc9c80fa573d2c233a8ca33e31498f4e6e7d849b75906249002b0148fc33a627a30ddbebb7685b79b7b7e720d8baa7dccbdfea7503d0fe1eb41d23c10f040c08df0bbcde3d8f904112fb668b48567afc8e6d407bab8e9d63bf8e7437f41956584a185ed294b5ad4da96683eadb4bfef49550066430201209e7c4992387696b9f489a3a3834e8783a2e2621ef9c73f52221fe0ed37df64fec28509efe51714b068f162563ff75c4ae487d21a39bf8171636a139214abaa7bdbdc84ebf1e461632cf6c87885e0897b7f4e555a3773affb1be48d848013026ef0bb107e2752c00d0157f0ba076415742de1b7d7e449dcb2209d9fbde4e61ff7fe0f577e7b69d47d6b7a8c0004f4bc3e339ad49b81b32d168b919696169fb911c7aaaab2f88c33c27df69fac5bc7e469d3f8e8fdf7d1753d4e7892e1bd77dee1c0810349ef1f3f772e232a2b53261f4092e17093dfd3f829cfbdf529972c39010ac622026e84cf85a4b920e0420ab81181e06492902024a4a437ee85a3cd32fbc0f31be30a52ac06d0037abf1e42a90ac0949cac2c3936738b4a4a983c6d1af34e3e99b3cf3f9f6b6eb88151c1216280fd4d4d545557f3f9962d09ebeb64d0759d679f79062362dddd484892c4b9e79d8712f4a54b467e5843011252827a3a62ea7714f9a1e3a1f5ee3df8a7df715cb58a3af51208b891348fa9fafd26e12244badf650a80cf097ae49c4f81889c360614d8252409029a4167b7332a5f544b74cb49d7f4ecfe88ed570082ce1f19e931a5df66b371ee051730f7a4933866e244ca627a018510b85c2e7c3e5f7ce9efa70a1040f3fefdbcf7eebb49c3141717b370e1c27ec90fa524857c00c37576ec387f30a3fbea7c49a441e21c4bcd6561843058b7ed00e579e9c1d2ef4204891661f2dd613b00bf1b3c1d043b25c2c4c7e2ddbd5ab8ec74767646ddd302d15587ae89c41e37114845038c048815002589911682d3e9242323c36cf69180a43e9e0d8579ed95577038922fa2397fe142aaaaaa92931f216c1221377048e4e411579a1334b3e28ffbe9dd93243e6e0a80bf0729e03155bedf89140896f8282170219c2d7d1610dd803fbd6b4e3b2bc8b631a2a23ceabee68b36220d5d4f3e7e1e44ea02909e3ea0be1229326c2431293c1b0aef0f0458f9f4d3c9d390242eb9ec32323233a3e34f50d548e156dd61221f83638fa9e1f9cd4e3ab6bf6b121c70236911aa3fe002bf13e1eb41781c084f6782afecc57deff958d764927cf682e958d46895aff9a33580a18b7e07bb531680580330e0f7f7a9caed1919389d4eb212351dfbb10122c36ddfbe9d0fde4ffecf859c9c1c2ebdf4d2684fe104d58d04bdea3a499d1e4bbe08139ec87688a84ee2dcb74cf57dc9d5df0549e294ebee64cfee5d41a32f6803f8dd087fb05af074203a7691ac6808017f79cfc7dd6f790148b32a9c73ee7971e102710260f42b00a934034d0d60b34565aac7e3e1ef7ff90b452525141416925f504071490979f9f94892842ccbd8ed762c160baaaae2f7fbe3b44132c4aaf155cf3e4bc588115424710a19357a34672e59c233cf3c93b4aa31c7a19295e6484d10ef959b3c6c020d1211b6b0bc96fb7efd7daebbe52e4e6af82927d5cd664e6d3693cb542697409e7110e171803bf1b43e21e0bd7d1af7beebe3eddd26b9b99956eefdd50f29298eef2d8dad02148be28a0b14835404a0c6a2aa862ccb71ad0097cb8573e74eb36f3f782d333b9b6baebf1e805163c6b067f76e468e1ecd96cf3e1b9406104210080478f89fffe4bb37de487a7a7ac267e62f58c09e3d7b58bf7e7d9c2d00200735c4e1223fa441a61d379f979f9ac8f2fbef61f90b1fb2e62db3652349509c29519e2d539c29539c2951922993972ed1dc6db0a3dde08d5d017c118d8282ec34eefbef9f50533522611ec4560136bb6567dfd4a6260039aaaac6b97f4102c34e08babbba686b6da5b8a484c953a6f0f8238f70de0517b063c70e7c5e6fd4f3c990c868ece8e8e089c71fa7e1f2cb7b57f38ec1c5dff806cdcdcdb4b4b444910f20741fc2e74408dd5c19c4d041e8611f41499240921192123c36cfcdadd7993465f2858eee73a1fbdda4a9826bbf7d03977cd3cd138f3cccc79fed64fdce43b4f668b4f6e840df8e3bb999362e3b6b1ee79f5f4f7a9a3569b880375a00ecd9e9fdfa03a42200998aa2a42c0002d8ba650bc52525e4e4e652535bcb8eeddb597cca293c1ba9a2fb4830364e4992c8cdcb63f3a64dbcb9660df3920c15abaacac44993686e89b7a61ffd493d697a7754f8f9b5509058a1c423281092a2621bb318fbaccb91338be285c2d0d0bd4ef480274ecb65d8ed5c71f5355c113cdfbbbf8dcf37ae63efbe460cc308ca4e306f8339644f4fe3924b1bb058faa7caddddeb8b61b1a958d32dfdfece2e1501c8521425be051052b1b19b10ecddb327fcf0490b16f08f071fe4f433cf64f4d8b16cfbfcf338f20dc3a0a3a30387c381a3a323981966fc16ab9599336670f0d0215c4e27cfad5a45555515b52347026677f3e6cd9bd9b46913dbb66f376d8d182105708f90d164353c2268b749542c964c6f20a3d70750d240e8024913a011e11328001d43d3f16c7d0edf8ed7c85972274ac9044020f400bab707ddef0de550bfa8ae28a6ba22b9cbdb40e0f704a234802dd306b0a3bfe752d300b21c572ac30290400be4e7f7faa7a5a5a5f18d4b2f65f9430f71d6d96733a2b292375e7b8d0f3ff8800fde7f1f87c34177708838762b2e2961d6ac596cdcb081abafbd96a6c646fefca73ff1c0030fb060c1023efef863f647ce238c789f58c8c5b2e963101cfaadaa014bad8ca499644b41875034732f0540f625ee89b457083a3778e85efd63722e5e8ea16be87e770a59f9c5c1d519ed89959669851404209566a05d0e75b946929f6403386eeedca808b2b2b3b9e4b2cb58bd6a155e8f87ebaebf1e5996d9b7776f42f2b373723873c912468f1ecda64d9bf8e6955762b55a19396a14a79f79266eb79b55ab56a54c3e10525bc16341469a34789f40157226090c5f0fee0d2b8e38f940d823388434bb2d0034f7f75c9f1aa0bebe3e1d5062350009323db4cd9c3327a143476e5e1e575e730defbef30e0ffeed6f4c9a3c9925679d85c7e361f7ae5d288a426e6e2e1e8f87d6d656d6ac59435d5d1dd77ffbdb51f12c5cb8105992a8a9ade5d1471ea1b9b9b97ff20139d80b18ed1348541fc0807c02ada0d8648caea6be031e26b83aa385d092ae1e48e5efa5fd55019900722201209efcc2c242e62d589034328bc5c249f3e631e7b8e3d8ba650b2fbff4121d1d1d6163c962b5525850c0e4a9533973c992a4d6fefc601a575e751577dc71073e9fafdf964514a302fc7e7a891e8c4fa01f74af8e9a57dd4fba8707b15540469e3da53f96a62400093500f102b060f1e2a48e1cefbdf30ec74c98404e6e2e369b8da9d3a631b58f091fa9a0a4a48433cf3c93a79e7a2ab507224ab7cb197d3ea07e6ec0db0648126ac5f4c1bcfab042f3ebf85cbdcb07dbec5632f3ec2b537936350d10d10a8088763ad179b6f1d34f19396a5454045d5d5d3cfaf0c3b43437b37af56a66cc9cc949f3e6919797dc57211008b079d326b66fdfcefbefbf4f4e6e2e8b162d62ce9c3971cea27b225a1c8910d20c9230a27c023b1c83f70974379a7e816af55ca4b49c3ec31e0e74b644376fb38b3221e23f887d61c05540940148b416d8b47123e9763ba79c761a604ed85cb572259e90072f84adfffa0b2ee0d8638f8d4bd0300c6ebbf55673aa5730fef6438778fcb1c778fbadb768b8fc724a8353d31e7bec31d6ad5b97ca7712586ffacd858cc166a0a50332ad44947a296a1f6a9147ee10207403cb9845d8a65f96343d49d7d8f0bf66215454054555515515c562eef3f2b2c9983c2dd4473d247434474f04ceccb7b796d735a4649cf427003e206a3cbf2f011042f0febbefe2743a5114257aae7e4cd8d5ab563175ead4b0f36808870e1e8c223f726b6c6ce457bffa15679c71068d8d8dac5fbf3ed53ce2e4f98bb1abf4722c203dcf4e7a9a6a9a20a15f05ea7ab013c7e8bd08114449c879d5a8e589ab2fbdb989971ffe37ef7df239858585548c1a4b5e5131c2e741eb6963e307efd2e63368f30bac8acc98f2428e9d389aa9c7cfa060f2149007365bcfd00dba5aa335405661c6aba93edf9f006c050cb7db2da72a000212ced18f0ddbd3d3c3eeddbb19155365b4b6b626ed5f1080a1ebac5c9952f516858967dd44a63d9da45db78646c0e540f73949be0241727876efe499fb97a33adab978511d975ff00d28ab018f0bdcdde6ded383e1fa0c34b3be16c09af66efef9dabbdcf2efb7985992c92d4bbfc9885933534eb7abcd89aef5f657a465dab0e7a43f9beaf37d8adb934f3ee9063e7074760abfdfdf3ff9c9b624611b1b1be3d26c89e8c64d16c76010fa1f5022f2356f0fbecefde83e67df912441e38b2ff0b75fdec5158b4ee486fb1f23ffd2ff40aa1c0b3e2ff8dce00fee7d1eb0f4f6e54bc0fc0295bf4dc9e09313b3a9c0c7f9b7fc913fffe897783b3a524adb11a3feb3cc05a5df48f5dd53d137ff650821ed899c8c3140a293856ddebf3f2eb18402c0d0c88790434834f986e6c7d7d542c0790891c4ffb0cf38758d37eefe03ef3cf33cb7df731f39177e0f6c7624af1bbc2ef07b4cd2839bf0ba4149ac74b35589bb27d8f96e8d8dbf7fb88babaeb915771fde50000870b4c4084081bda9bcae21b9476d0cfa1580279f7c7215f04c6757178da14e1712b702a208ebefba10ecdcb913b7db8dd7ebc5ebf5e276bbd9bd7b777cf821901f6e059827e6b961107075e0ebdc8f11f00e2a5e8057eebe87773fdac88dbffd338c9c84f079103e37047c089f07bcee0801f09afb24378f76a20000164c494441540210c28d35699c536a615ba7873b6ebbabcfb0dd879c51fdff8a2a93579ef3e040be21d579011703efb71e3c38d9edf1505d5969f60d90bcae4ee57a576727b7dd7a6b4ae1870ad3234c60047cf8bb5b11fad0feb8d2f3d926fef1d626567def62a89988e47182df6b0a419078e1f32005054184aa8014705d958d1507023cbfa5896fed69a4aca63261b8d69dd18e247915b9c2625307240029999c4f3ef9a407980b3cd1e374f2d9d6ada2a9b9196fb0076e30e43380f0c3014902cddd89af73ff90c94708fe78d75f39bfd48275ded9617243c4874abe14ac0244443580b75f271dc6d895b04fe5aead89c773fc9e001dfba3d57f7e45cefaf2ba86bd03f9949467073ff9e4934ee0c2f3ebeb1fc954d5c7da1d8eb47687839cec6cac562b1655c562b1600d2efa986ca14723746e1883223f1581880c139a5b10e86e450effc86168300eece799bd5d9c373d074a6b903c3d08af1bc9ef41f83da6d1e7f7823796fca041d80fb6b9f470b783e3506263b075e7a1a8efb46558c92bcbfec340bf65c0ab845d5c59e505d20ef97c6cf37ad8e774269dc0f1658211f0202bc3f37f8c832d6de8029c86045e67b8b40b8f0bbc1ed3e20fd7ffeea031e846b43787c73dfac2b36dbd1aca921ddfd368e806adbbdaa3ae1556e5f925497a72a0df32600150adcacf35bf4ea1cdc6ac050b183173061ddd0eda1ded1c686be3406b1bba6eba5849f4ae0a2249a66fbe149c781b3a0ede25ec85150c2c91f89c88ebbdf782bf7e233a9ce137bd7025091479f87e9056386a24aa044f36ba387dd3bb4895634df51f6aee79dd26e191ad008f0bbadafb8dfba32e8dbfec3335559eddc6fcd3e6c58539b4cf11e7ff975f91fb6c795d43fff54b0c0624002b962e9ba4f9f5f02a50c563c7a2aa2a35b523a8a9ade8ed5409b5b763dbdca1e388fb51e789c246dc37c3c6afa8191bd6d0fcf8bb5a31b4e151f9b1507272f9fa84113cb5b9893ffffe6eaeffc18fc16a3389f67bcd5680df1bb4fcbde0ee4134ed483ae93384169fc1351bdd68c14f3b77e14c6c564b5cb8033ba28dbfeca24c3272d3ff38a86f1948e06f9c74c26f84218e05c82a2ea66ad64c2c36c55c82f54b42bee6e9c6d7652e08f94562ca8c49ac79f94d56edeb66cf076b48777752ac68a83e0f04fcd0e300471be2d07e68de65ae07d0079e6e0d70d506375d41f6a7d694f2c39fde8835c617d0d1dcc5811d07a3ae554c2c6d1a73e675370ee63b52d68b2b962e9314556ed735230f60e409275039fd58d2b36d31ffde192cb982212dba280c7cdd6de8de3e57441956b437b7b0ec0777f2d901b3c3460246d965e6e6a99c90af52619329b2c9145b1367f3019fc1eab600ffdb1a60634faf67f0dc63aab9e3ae5b49b3457b000b43f0e9cb5bf1f6f46a367b4e1a93178dbbb8e2c4cb1f1bcc370ca40a981e221fcc7a5008611a567d1213128cfe17478e132212909f409b0843c3d7d932a44e9dc1a0a0bc8c7f3c7c372faf58cdfd8f3dcf9ef61e76b80d76b8fd2cdfdf3b3e2f01f91689629b4c8145a2d56fb0db6d84557d088a2273f9e973b9f6c62b51120c0ab5ee3a14453e40d998e22649969e18ec37a42c00b2229f67e82689b2aa62cbca4256a4debf6ef6477eb079174f7e02c20740be11f0e1eb6a197adb7e08587cee192c3ef70c3edfba93ed9f6c62db961d6cd9d3c296d64e7c010d01b40704ed81c4feff19360bf50b6771d1951752989fd8bf400be8347dd61a75cd9e93466155decde5750d836e86a52c008a2a2f0a09405a561618c2fcf152927ada1c4f8f243f816d9080dca48210577d18e83e17beaed6b07639d218377e14e3c6478f6eeededd445bf301821912d678e1bd21987de22cd43e564107d8bfa535cef20f96fec787f2ce290b80a11be12f4bcbcec6fcf3964cbf46da17447ec0e520e0ecbf5975a4515b3b82dadac453b95285d7e58b33fc86a3f4438a02b062e9b20c5d33c2cefeb6ac2cf3cf9bc111b678f2fb217128e40b1d7f771bda301a7b02c18b6deff1abbf3f8ee3800b599150541959955014194595c9ceb2b368f654ce9fb1801a5bd9b0a59d0a76ad6b0cfeebb017c351fa21750d504b448bc19a918130823f5e3e8ce40b2330ecc6decbad1ff0fb179fe2a0a7938a53f2b974e23728cdae20dd6aa753ebe0e56dcfb06bf74edc87ba7972c31aeefbfdcb648fb632ffb8c9fce2f42bc8563386ed5d12a16d773bdd6dd17e0a9979760aabf36f1c6ae987d40520aa82d2037e7ad7d58927374e1806d2c687601cd16d7c43f3e173ec37fdfa86015ee1e382bfff9c565f07b32e9fc0b7aabecb31b9c7e2d1dcb835276edd49a69e415e7936d999bdd9547a968db697fdac7c741d2bffb58e0baf389e5f9d76edb0bc53dc3b3a7decfd34da674292252aa794bf517142c38ae14823550188d23f7e971ba11b18ba8ea2ca29901b2294a87abcaf367e645cbadf83bfb339287443c721ad934bfefe9fa4cd94b8fdb4ff645afe5c5c811ebcba3b6e93a5e8e698629728fbba8dd2afd9d8f367378ffce91d366dd9c7d337de6efe897c98208460c707fba2dcbd004a4717fa728a32937ba30e10a90a40d45bf8dd2e843030340359918695fcc79fd670743ab059156c5605ab1c40357a484fb371fc342f8a2c180a1a7dad5cfc87ffa2ec3c3bb79f7c1f85b6125c5a0f3edd835b77e2d1dd780d375edd834773232719319764a8fdb61dc3e762c3eb4d7ca7f877fcf992a509c30e06fbb7b4e2ec88eeda4fcbb45131bee487a97afca682540520cadc0eb83d08c340f30750ad664b20be8307c2e447d6eb4904e58db53adfffd9d3ec6bfa08f3ff3d3624ac8005dd3880aeef44c24a7eee2cc68f1cc99d3f984455c5c0dafe02c1657ffc35b6591ab7ccff6f8a6ca5b834a759da83a4fb740f5edd13d600823e044e82ea6bec6cfe410fcf3ff1291f9df83933abc60de89d12c1d9e166ff96d6b8ebd553ca37a956f59e212710819404e0dcbb7fdbf2f4f7bfef34742313c0ef72210c81cfed272dd33a24f2b76c177cf7476fb06d672e1919cbf8e63773a8aa92282a0287c3e0edb70d3efcc0acf70da39340e07ddefde437d45dbc9cda11a7f2e06f1630ba2a35bbe0895dafd2d1e9e4a245a75393390e8feec26798847b747790fc5ef5ef333c7d0b00a06649e4cdb170e8753f77af7c8a876ff8714aef920c7a4067fbfb7b7a9bd24114d5e4eb79e539170c87e117895407c8559fa185d54ec0ebc579e810018f1f43d763c88f50fbb1d67d0cf92fbeeee794fa076969bd9c73ce69e09e7bf239e71c85f1e325ac564156a6447ec4042259cec5663b9582fc57c8cafc257b9b3f66e1653fe6fe27dafafd001d9ddf3ffc0cc5a7d898577a265edd8d477385c9f6682e73d3cd6b1edd1d3608fb435a85998d4d4da979f22683a10bb6aedd1535cd0bcc1540474c28bdb3bcae61cb901248805404200398d7e2706c8dbc7870c7760cc3c0dde52125f263ba7657bee0e59a9b9e62e2c4dff0d707f2b9ea2a858c0c81db656e1e37b893ceba56484b3b9fbcdc6790e591dcfec7dff3b77ff7dd29b4b66d03cd1ff590556ba336737c9878b7e6c21d26dd8527782d74ee0c74f7192f80ee364babab7b68cdd39d1feda3e75074bd2f4912b5d347ecb4d9ad3f1f52e449d09f006401f300fb4beb3f7d39f28663ef5e74bf1f57a71b438ffed191e8a35d2f84e085d75c5cf71f7f62e1c29f72efbd99646682cb257039cdbdd32970b9c0e90a5527495e5ece2337e721c0ca6feeff174e7772edb861df6ef38372324c834f73e18e29f1bd75bf69007a74174ead7f0170ed30ab209f6bf043d08d9b5a686f8c77031f31a1b43bbf3ce7a4f2ba067f82c7868cbe04c0069c085801567ff2c91e5d16e16a400f68b4efd98311d0e939e48c57f351e7bd1a41d3e03b37ff9551236fe3c7b766e0f1083c1ecc92ef3670b983e7c1bdd64f9eca720119f6ebf17a5bf8fe1d9b9286b32b361070706b37dd0147c2269f272c082e3cba932e7f07817efc08dd7b757a369b2f396e7c799f6193e1e09e0ef66f8d37fa0a2a738d8a634a4e2baf6be877a187c1229900c8985ec0514b287db863e7a391e72d9b36e3f7b87139dc78ba3dfd74f098d7eefb7b1b2eb795af9f3d8a40c024dae534707b4c95ef719b5ac0ed36efe929983c56eb7c005e7a2bf994b1136ba682042dabdd7cea782faeb967967e531b9855828783de96be1316b0efef9ef032ff0d0b17f7ffb231e839e462d7baf8195219b9e9d44cadb8b1bcae21f982c9c38064023001288abdf8bbe756bf8e2a853be175bf9fa68fd7230c03474b17016f80687b20fa9fb9866ef0bbbf3c4e76f6059c78a28cdb0d2e17b8dce00aaafd48f25d2e70f6f4dfee5714d36f3ea039e97626361cc6e48d60f4ac623ad705f8c743cb69f53406897747d5ff1ecd85577373c0d388bf9fd2bfef210fee5d26fb59d9699c392ba5ff3485d1d9dac396b776c659fcaa5565e48cca47aa175d352837af81209100a403c7240aecd734e3950d1b7f1d79ada7b5958ebd7b317483f6c60e0ccd88273f58fa77ed95e970bc4a5ddd3854d524d9ed1678dc02b7877075e0f19842e0f1081c7d2f9f0b80ae076b2601073b9293f6a7ebbe8b2d5b65d7f24e7ebdecb7bcf9c69b3439f6d215e8c0abb9e9f277d0e66d66b7f3735c5af2c126c327d8f50737875e37ab658b45e18f3ffc7642278e64e8d8dfc5e76b7761c4a83849921839a37273469efd8a248f0e2b12f5034c0e5e4fd8b8fed38b2f7d78dcf8b1ef64cad6f04a5007366fc69699812d2b8bf646070555b9718e2220f8ecf37640273fdf86cb65e072054bba1b530882eadfd40ae6beabb37f0d10d0826b0448e0f525371ac61655f2d0ed4bb9fae7bfa7fd432f4f7df82ac890395a21e7580bf61a85ac096a524739df4183f637fcb4bfe927d065be972c4bfcd74d0dcc9b3ca5dff70ce1d03e073b3fdc1757f20146ceac74e657e42cfea28cbe58c40a800cd4f4f7d0cf1f7de2d7775ddef084d08c7430a76ceffde0432a674cc7d0b2d0760628aace0b77138704a1acc4fc0b6867e7263ceef9410d40781f52ff2e97c01dac0ebabafa160021bcb8dd0f00909d59c884d1c9ff3806707ced445ebfe74e7ef08ffb79ebb52d18bac0b94dc7b92d28ef12a4572ac836506c12729a84bfddc077d04077c6a86a55e127dfb9900b4e9cd75f9685d1b6ab9d5deb1b49d4bf5435b9bcbda83a7f46795d433fc6c7f021d60da5141883f97a493787cbe5cbcdcad830a6a4f4544468216e03675b1b19f97920645c9d6ed2336da61004b5405181c4effffa3a9d9dbba93be19c20c944b402a285e0e041414f3fc3fe6ecf9ff0fb5e0160f109f358b2a0a6df8fceb0a571ce9c3abebef07802197e1c9e1e9c9dde30275a9720d021f0b519789b0d029d0211511e154566f1a2a93c72db8fa89b90d22f7a01736877d7c7f1061f40e5a4b28e8af12533063ab56ba8885576d3804998eabfdfed17179fbf687259e54f23a559b158289b3c095b4606920cc535f9a465da10868eaf733f57defc212fbef908679f7d1bb3e75c69aafb50bb3f62dfd525686a12f435e92810f888ceae2b40f8902478ee81654c1e5b3ca88ce876ba59bf7b071fefddce9e03ad18c20877690b41b84b5842e2a7f5975252d0efff98c21002f66dd84fcbf68309ef574e2eeba8185732a3bcae61cfa05e7e08881580e330ff1198920000fa3dd75e79494546eef551914a12f935356497962284813d5b253bc70742c3e7379875de3fe9eafe9c69c79ecc8ce9e7601813f07a47e00c76041d386096febec8f7781fc3e9fc05081d24b8b1e15cbe7ff5ec61ca96e183a1196cff606fdc420e21544e2a73548c2f997e24c88778013809a862000200e8f77de7dacb8b6d99df8aadd7ec7979a4e7e6d0b1672f695936464eaf24ab3083e6362f5fbffe090eb47d06405a9a8d8ccc52a09e406034aa321e4589ff3780aeefc1ef5f83dbb31c436f0c7fc1e9279dc4fdff79c6b064c87022e00db075ed6e5c8ec44dd3ca89658e8a634a6694d735ec3eccaf1646ac00cc06c632400100f4df5e75f9d76af30a6f15bae8b32d543cb280aa49e5c8aacccffef0190faf7c8a40203e8324c98e24e7997bc986a67d46acf7af2cc379a79dc65d3f9a977451c92385ce03ddecfca831d837120d5996a83976444b716dc19cf2ba86c446c16142ac11980594d38f1198687b71fda75b6aca8a3faa2e2c3a5d1822a98fb3cbe1e1e09e0e1455e66ba755f3cdf3e6a0c8151cea9470badb22d47e00217a10460786d14694d92c41cd88513cf89b4bb8e2bc295f2af2f580ceeef54decdbd08ca1c5d761d6740ba36657bf54589957575ed770c4dd9a6373ae00389d416880d076d6ec9945d79cb2e8c1802b9078598b0858d32c948f2fa6b8b6005991d1749dcf77b5f0e6875d341de821e4082b823e06a1767355b9cc0d971ed747cc4706dd6d4eb67fb03761a907c82cc81023a78ff82f7b4efa4f5359c7f7702051d15982a909062d048a2c1bfffcfef796d90de54a4317fd16cf5841f8bf0697c34de3a6163a5b93b7598b6b0b7c5593caceab5a78e57387f1d5fa4522552d03650ca21a086d4208e3a9b5efbdad29e2d13993c7cd0b7802f9f1c9f442d70c3a0ff4d0b6bb1dcdaf61cbb4a25a07bc74c16187a7dbcbee8f9bd8fbe97ebcaec41d77922c513db97c7fd5e4f2d923e67d33a5059c0f2712954e05b31ab033042d10b93df4fd1bce294acffca9cfe9eff75fb621e41467513cb280fcf21ca461f4b61d320474b6f5d0baf350d2a65d08b60c2bd5532b1ecc2fcfb9aebcaee18b9daf3e4824cbd952cc26e1b00800a05b54d578f4969bae4bd395fff07b02fdfecf2e04599129aec927af2297eca28c2366f0f9dd01daf6b473704f073e77dfddf492245132aad0593eaef8b29a93af4afee7cb2f01facacd69c02886510800bd223f9ffb6fbaee36ddad5fa3f9b4e4bfc04a00c5a2905392455e5936b9a5d9586c5f5c352184c0d9e1a6abb587ced61e5c1dee848337b148cf4aa37272d973f9e5399796d735a430967964d1970048983d83250cb31000faec31a3955f5c76c103de2edfd784d177df413264e4a563cfe9dd32f2d2e3fea09d12843901d3d3ed3537a78f43fb1c71f3f1fa82244914d5e6f7544e2c5b52bdf0ca3707fe124706fde95319a80372f9028400d0e74f9a28df76f9f9cb3477e07a57a7a764a81f644db760cf49475165148b62ee5505c5aa606806baa6a30774f48041c0af11f06ae6efd606d928535499c2ea7c47514dfeed9979f67b0fd730ee7021950a55068ee50bd204115b60cd6f6fafd3fcda9dce0ed7717ac0f852b70755ab42514d415b5175fe4fec39690f96d735e847fa9d06838158541381117c8102104ae8b53b7e9e25abf2afdc9d9e06afd3973d84ef1b76641566889ce2ac8d65638bef5354f9be2f4b87ce60315093ba08d35d4ce10b148048bcf3c75fd56901fd3b5e977f81bbd35362e8c6616d06489244666186915d98b131b724fbfeacc28c7f95d735f4ef2bfe7f0483c94c0ba6100cb75dd0ef44bf0ffe7aa73de0d3bee5f7042ef47b0213dc9d9ecce15a4b38045991c9c84d17b64ceb81b44cdba6d25145ffab5a9507caeb1a8edc22445f2086529af231ddc7ac1c26018845f3dae56acbf683c707bc81f99a5f9b11f0e9e302de4099a18b74433714c33064a10b49d78cb0f3a56a5351ad0aaa450928aae29355d9ad58e4ceb44cdbcef4acb4d7f3ca7356cbb2b465b8e7e07d593154752a01c5982388128759005241cbdae592806c2043d78c4c45950f95d7350c6d12dfff4718aefa54c6d408f90c5e23fc7fa962bfec18ccff911241006ecc75049c988265616083485f0995fb65c317d197ea0e6e0a41d5cbf0699aa318660c970648040178816e4cf52e05d33baa01be4438dc2553c2d43a2abdd3d28eda004710475a354b440bc2511cc5511cc5511cc5511cc5511cc5517cd1f87fdfa54b2570e59fed0000000049454e44ae426082</data>
+ </image>
+ <image name="image1">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>m_buttonExit</sender>
+ <signal>clicked()</signal>
+ <receiver>SlideShowConfigBase</receiver>
+ <slot>close()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>m_buttonExit</tabstop>
+ <tabstop>m_buttonStart</tabstop>
+ <tabstop>m_helpButton</tabstop>
+ <tabstop>m_delaySpinBox</tabstop>
+ <tabstop>m_shuffleCheckBox</tabstop>
+ <tabstop>m_loopCheckBox</tabstop>
+ <tabstop>m_openglCheckBox</tabstop>
+ <tabstop>m_printNameCheckBox</tabstop>
+ <tabstop>m_effectsComboBox</tabstop>
+ <tabstop>m_allFilesButton</tabstop>
+ <tabstop>m_selectedFilesButton</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">klineedit.h</include>
+ <include location="global" impldecl="in declaration">libkipi/interface.h</include>
+ <include location="global" impldecl="in declaration">kprocess.h</include>
+ <include location="global" impldecl="in declaration">kio/previewjob.h</include>
+ <include location="global" impldecl="in declaration">klistbox.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">libkipi/interface.h</include>
+ <include location="global" impldecl="in implementation">kprocess.h</include>
+ <include location="global" impldecl="in implementation">kio/previewjob.h</include>
+ <include location="global" impldecl="in implementation">klistbox.h</include>
+</includes>
+<slots>
+ <slot access="protected">slotOpenGLToggled()</slot>
+ <slot access="protected">slotStartClicked()</slot>
+ <slot access="protected">slotHelp()</slot>
+ <slot access="protected">slotUseMillisecondsToggled()</slot>
+ <slot specifier="non virtual">SlotPortfolioDurationChanged( int )</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonUp( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonAdd( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonDown()</slot>
+ <slot specifier="non virtual">slotImagesFilesButtonDelete( void )</slot>
+ <slot specifier="non virtual">slotImagesFilesSelected( QListBoxItem * item )</slot>
+ <slot specifier="non virtual">slotGotPreview( const KFileItem *, const QPixmap &amp; pixmap )</slot>
+ <slot specifier="non virtual">slotFailedPreview( const KFileItem * )</slot>
+ <slot specifier="non virtual">slotAddDropItems( KURL::List filesUrl )</slot>
+ <slot access="protected">slotCacheToggled()</slot>
+</slots>
+<functions>
+ <function access="protected">loadEffectNames()</function>
+ <function access="protected">loadEffectNamesGL()</function>
+ <function access="protected">readSettings()</function>
+ <function access="protected">saveSettings()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kdialog.h</includehint>
+ <includehint>listimageitems.h</includehint>
+ <includehint>kfontdialog.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kipi-plugins/slideshow/slideshowgl.cpp b/kipi-plugins/slideshow/slideshowgl.cpp
new file mode 100644
index 0000000..ba49931
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowgl.cpp
@@ -0,0 +1,1508 @@
+/* ============================================================
+ * File : slideshowgl.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-01-19
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2007 by Valerio Fuoglio <valerio.fuoglio@gmail.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <kglobalsettings.h>
+#include <kimageeffect.h>
+
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qapplication.h>
+#include <qevent.h>
+#include <qcursor.h>
+#include <qimage.h>
+#include <qpainter.h>
+#include <qfileinfo.h>
+#include <qfontmetrics.h>
+#include <qwmatrix.h>
+
+#include <math.h>
+#include <cstdlib>
+
+#include "slideshowgl.h"
+#include "toolbar.h"
+
+namespace KIPISlideShowPlugin
+{
+
+SlideShowGL::SlideShowGL(const QValueList<QPair<QString, int> >& fileList,
+ const QStringList& commentsList, bool ImagesHasComments)
+ : QGLWidget(0, 0, 0, WStyle_StaysOnTop | WType_Popup |
+ WX11BypassWM | WDestructiveClose)
+{
+#if KDE_IS_VERSION(3,2,0)
+ QRect deskRect = KGlobalSettings::desktopGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+#else
+ QRect deskRect = QApplication::desktop()->screenGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+#endif
+
+ move(m_deskX, m_deskY);
+ resize(m_deskWidth, m_deskHeight);
+
+ m_toolBar = new ToolBar(this);
+ m_toolBar->hide();
+ if (!m_loop)
+ {
+ m_toolBar->setEnabledPrev(false);
+ }
+ connect(m_toolBar, SIGNAL(signalPause()),
+ SLOT(slotPause()));
+ connect(m_toolBar, SIGNAL(signalPlay()),
+ SLOT(slotPlay()));
+ connect(m_toolBar, SIGNAL(signalNext()),
+ SLOT(slotNext()));
+ connect(m_toolBar, SIGNAL(signalPrev()),
+ SLOT(slotPrev()));
+ connect(m_toolBar, SIGNAL(signalClose()),
+ SLOT(slotClose()));
+
+ // -- Minimal texture size (opengl specs) --------------
+
+ m_width = 64;
+ m_height = 64;
+
+ // --------------------------------------------------
+
+ m_fileList = fileList;
+ m_commentsList = commentsList;
+
+ m_imagesHasComments = ImagesHasComments;
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("SlideShow Settings");
+
+ readSettings();
+
+ // ------------------------------------------------------------------
+
+ m_fileIndex = 0;
+
+ m_texture[0] = 0;
+ m_texture[1] = 0;
+ m_curr = 0;
+ m_tex1First = true;
+ m_timeout = m_delay;
+ m_effectRunning = false;
+ m_endOfShow = false;
+
+ m_imageLoader = new SlideShowLoader(m_fileList, m_cacheSize, width(), height());
+
+ // --------------------------------------------------
+
+ registerEffects();
+
+ if (m_effectName == "Random") {
+ m_effect = getRandomEffect();
+ m_random = true;
+ }
+ else {
+ m_effect = m_effects[m_effectName];
+ if (!m_effect)
+ m_effect = m_effects["None"];
+ m_random = false;
+ }
+
+ // --------------------------------------------------
+
+ m_timer = new QTimer();
+ connect(m_timer, SIGNAL(timeout()),
+ SLOT(slotTimeOut()));
+ m_timer->start(m_timeout, true);
+
+ // -- hide cursor when not moved --------------------
+
+ m_mouseMoveTimer = new QTimer;
+ connect(m_mouseMoveTimer, SIGNAL(timeout()),
+ SLOT(slotMouseMoveTimeOut()));
+
+ setMouseTracking(true);
+ slotMouseMoveTimeOut();
+}
+
+SlideShowGL::~SlideShowGL()
+{
+ delete m_timer;
+ delete m_mouseMoveTimer;
+
+ if (m_texture[0])
+ glDeleteTextures(1, &m_texture[0]);
+ if (m_texture[1])
+ glDeleteTextures(1, &m_texture[1]);
+
+ if (m_imageLoader)
+ delete m_imageLoader;
+
+ if (m_config)
+ delete m_config;
+}
+
+void SlideShowGL::readSettings()
+{
+ m_delay = m_config->readNumEntry("Delay", 1500);
+ m_printName = m_config->readBoolEntry("Print Filename", true);
+ m_printProgress = m_config->readBoolEntry("Print Progress Indicator", true);
+ m_printComments = m_config->readBoolEntry("Print Comments", false);
+ m_loop = m_config->readBoolEntry("Loop", false);
+
+ m_effectName = m_config->readEntry("Effect Name (OpenGL)", "Random");
+
+ m_enableMouseWheel = m_config->readBoolEntry("Enable Mouse Wheel", true);
+
+ // Comments tab settings
+
+ m_commentsFont = new QFont();
+ m_commentsFont->setFamily(m_config->readEntry("Comments Font Family"));
+ m_commentsFont->setPointSize(m_config->readNumEntry("Comments Font Size", 10 ));
+ m_commentsFont->setBold(m_config->readBoolEntry("Comments Font Bold", false));
+ m_commentsFont->setItalic(m_config->readBoolEntry("Comments Font Italic", false));
+ m_commentsFont->setUnderline(m_config->readBoolEntry("Comments Font Underline", false));
+ m_commentsFont->setOverline(m_config->readBoolEntry("Comments Font Overline", false));
+ m_commentsFont->setStrikeOut(m_config->readBoolEntry("Comments Font StrikeOut", false));
+ m_commentsFont->setFixedPitch(m_config->readBoolEntry("Comments Font FixedPitch", false));
+
+ m_commentsFontColor = m_config->readUnsignedNumEntry("Comments Font Color", 0xffffff);
+ m_commentsBgColor = m_config->readUnsignedNumEntry("Comments Bg Color", 0x000000);
+
+ m_commentsLinesLength = m_config->readNumEntry("Comments Lines Length", 72);
+
+ // Advanced settings
+ bool enableCache = m_config->readBoolEntry("Enable Cache", false);
+ if (enableCache)
+ m_cacheSize = m_config->readNumEntry("Cache Size", 1);
+ else
+ m_cacheSize = 1;
+}
+
+void SlideShowGL::initializeGL()
+{
+ // Enable Texture Mapping
+ glEnable(GL_TEXTURE_2D);
+ // Clear The Background Color
+ glClearColor(0.0, 0.0, 0.0, 1.0f);
+
+ // Turn Blending On
+ glEnable(GL_BLEND);
+ // Blending Function For Translucency Based On Source Alpha Value
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+
+ // Enable perspective vision
+ glClearDepth(1.0f);
+
+ // get the maximum texture value.
+ GLint maxTexVal;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexVal);
+
+ // allow only maximum texture value of 1024. anything bigger and things slow down
+ maxTexVal = QMIN(1024, maxTexVal);
+
+ m_width = QApplication::desktop()->width();
+ m_height = QApplication::desktop()->height();
+
+ m_width = 1 << (int)ceil(log((float)m_width)/log((float)2)) ;
+ m_height = 1 << (int)ceil(log((float)m_height)/log((float)2));
+
+ m_width = QMIN( maxTexVal, m_width );
+ m_height = QMIN( maxTexVal, m_height );
+
+ // load the first image
+
+ loadImage();
+}
+
+void SlideShowGL::paintGL()
+{
+ glDisable(GL_DEPTH_TEST);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ if (m_endOfShow)
+ showEndOfShow();
+ else {
+ if (m_effectRunning && m_effect)
+ (this->*m_effect)();
+ else
+ paintTexture();
+ }
+}
+
+void SlideShowGL::resizeGL(int w, int h)
+{
+ // Reset The Current Viewport And Perspective Transformation
+ glViewport(0, 0, (GLint)w, (GLint)h);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+}
+
+void SlideShowGL::keyPressEvent(QKeyEvent *event)
+{
+ if(!event)
+ return;
+
+ m_toolBar->keyPressEvent(event);
+}
+
+void SlideShowGL::mousePressEvent(QMouseEvent *e)
+{
+ if (m_endOfShow)
+ slotClose();
+
+ if (e->button() == Qt::LeftButton)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotNext();
+ }
+ else if (e->button() == Qt::RightButton && m_fileIndex-1 >= 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotPrev();
+ }
+}
+
+void SlideShowGL::mouseMoveEvent(QMouseEvent *e)
+{
+ setCursor(QCursor(Qt::ArrowCursor));
+ m_mouseMoveTimer->start(1000, true);
+
+ if (!m_toolBar->canHide())
+ return;
+
+ QPoint pos(e->pos());
+
+ if ((pos.y() > (m_deskY+20)) &&
+ (pos.y() < (m_deskY+m_deskHeight-20-1)))
+ {
+ if (m_toolBar->isHidden())
+ return;
+ else
+ m_toolBar->hide();
+ return;
+ }
+
+ int w = m_toolBar->width();
+ int h = m_toolBar->height();
+
+ if (pos.y() < (m_deskY+20))
+ {
+ if (pos.x() <= (m_deskX+m_deskWidth/2))
+ // position top left
+ m_toolBar->move(m_deskX, m_deskY);
+ else
+ // position top right
+ m_toolBar->move(m_deskX+m_deskWidth-w-1, m_deskY);
+ }
+ else
+ {
+ if (pos.x() <= (m_deskX+m_deskWidth/2))
+ // position bot left
+ m_toolBar->move(m_deskX, m_deskY+m_deskHeight-h-1);
+ else
+ // position bot right
+ m_toolBar->move(m_deskX+m_deskWidth-w-1, m_deskY+m_deskHeight-h-1);
+ }
+ m_toolBar->show();
+}
+
+void SlideShowGL::wheelEvent(QWheelEvent *e)
+{
+ if (!m_enableMouseWheel) return;
+
+ if (m_endOfShow)
+ slotClose();
+
+ int delta = e->delta();
+
+ if (delta < 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotNext();
+ }
+ else if (delta > 0 && m_fileIndex-1 >= 0)
+ {
+ m_timer->stop();
+ m_toolBar->setPaused(true);
+ slotPrev();
+ }
+}
+
+void SlideShowGL::registerEffects()
+{
+ m_effects.insert("None", &SlideShowGL::effectNone);
+ m_effects.insert("Blend", &SlideShowGL::effectBlend);
+ m_effects.insert("Fade", &SlideShowGL::effectFade);
+ m_effects.insert("Rotate", &SlideShowGL::effectRotate);
+ m_effects.insert("Bend", &SlideShowGL::effectBend);
+ m_effects.insert("In Out", &SlideShowGL::effectInOut);
+ m_effects.insert("Slide", &SlideShowGL::effectSlide);
+ m_effects.insert("Flutter", &SlideShowGL::effectFlutter);
+ m_effects.insert("Cube", &SlideShowGL::effectCube);
+}
+
+QStringList SlideShowGL::effectNames()
+{
+ QStringList effects;
+
+ effects.append("None");
+ effects.append("Bend");
+ effects.append("Blend");
+ effects.append("Cube");
+ effects.append("Fade");
+ effects.append("Flutter");
+ effects.append("In Out");
+ effects.append("Rotate");
+ effects.append("Slide");
+ effects.append("Random");
+
+ return effects;
+}
+
+QMap<QString,QString> SlideShowGL::effectNamesI18N()
+{
+ QMap<QString,QString> effects;
+
+ effects["None"] = i18n("None");
+ effects["Bend"] = i18n("Bend");
+ effects["Blend"] = i18n("Blend");
+ effects["Cube"] = i18n("Cube");
+ effects["Fade"] = i18n("Fade");
+ effects["Flutter"] = i18n("Flutter");
+ effects["In Out"] = i18n("In Out");
+ effects["Rotate"] = i18n("Rotate");
+ effects["Slide"] = i18n("Slide");
+ effects["Random"] = i18n("Random");
+
+ return effects;
+}
+
+SlideShowGL::EffectMethod SlideShowGL::getRandomEffect()
+{
+ QMap<QString,EffectMethod> tmpMap(m_effects);
+
+ tmpMap.remove("None");
+ QStringList t = tmpMap.keys();
+
+ int count = t.count();
+
+ int i = (int)((float)(count)*rand()/(RAND_MAX+1.0));
+ QString key = t[i];
+
+ return tmpMap[key];
+}
+
+void SlideShowGL::advanceFrame()
+{
+ m_fileIndex++;
+ m_imageLoader->next();
+ int num = m_fileList.count();
+ if (m_fileIndex >= num) {
+ if (m_loop)
+ {
+ m_fileIndex = 0;
+ }
+ else
+ {
+ m_fileIndex = num-1;
+ m_endOfShow = true;
+ m_toolBar->setEnabledPlay(false);
+ m_toolBar->setEnabledNext(false);
+ m_toolBar->setEnabledPrev(false);
+ }
+ }
+
+ if (!m_loop && !m_endOfShow)
+ {
+ m_toolBar->setEnabledPrev(m_fileIndex > 0);
+ m_toolBar->setEnabledNext(m_fileIndex < num-1);
+ }
+
+ m_tex1First = !m_tex1First;
+ m_curr = (m_curr == 0) ? 1 : 0;
+}
+
+void SlideShowGL::previousFrame()
+{
+ m_fileIndex--;
+ m_imageLoader->prev();
+ int num = m_fileList.count();
+ if (m_fileIndex < 0) {
+ if (m_loop)
+ {
+ m_fileIndex = num-1;
+ }
+ else
+ {
+ m_fileIndex = 0;
+ m_endOfShow = true;
+ m_toolBar->setEnabledPlay(false);
+ m_toolBar->setEnabledNext(false);
+ m_toolBar->setEnabledPrev(false);
+ }
+ }
+
+ if (!m_loop && !m_endOfShow)
+ {
+ m_toolBar->setEnabledPrev(m_fileIndex > 0);
+ m_toolBar->setEnabledNext(m_fileIndex < num-1);
+ }
+
+ m_tex1First = !m_tex1First;
+ m_curr = (m_curr == 0) ? 1 : 0;
+}
+
+void SlideShowGL::loadImage()
+{
+
+ QImage image = m_imageLoader->getCurrent();
+
+ if (!image.isNull()) {
+
+ int a = m_tex1First ? 0 : 1;
+ GLuint& tex = m_texture[a];
+
+ if (tex)
+ glDeleteTextures(1, &tex);
+
+ QImage black(width(), height(), 32);
+ black.fill(Qt::black.rgb());
+
+/* image = image.smoothScale(width(), height(),
+ QImage::ScaleMin);*/
+ montage(image, black);
+
+ black = black.smoothScale(m_width, m_height);
+
+ if (m_printName)
+ printFilename(black);
+
+ if (m_printProgress)
+ printProgress(black);
+
+ if (m_printComments && m_imagesHasComments)
+ printComments(black);
+
+ QImage t = convertToGLFormat(black);
+
+ /* create the texture */
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ /* actually generate the texture */
+ glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
+ /* enable linear filtering */
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+
+ }
+
+}
+
+void SlideShowGL::montage(QImage& top, QImage& bot)
+{
+ int tw = top.width(); int th = top.height();
+ int bw = bot.width(); int bh = bot.height();
+
+ if (tw > bw || th > bh)
+ qFatal("Top Image should be smaller or same size as Bottom Image");
+
+ if (top.depth() != 32) top = top.convertDepth(32);
+ if (bot.depth() != 32) bot = bot.convertDepth(32);
+
+ int sw = bw/2 - tw/2; //int ew = bw/2 + tw/2;
+ int sh = bh/2 - th/2; int eh = bh/2 + th/2;
+
+
+ unsigned int *tdata = (unsigned int*) top.scanLine(0);
+ unsigned int *bdata = 0;
+
+ for (int y = sh; y < eh; y++) {
+
+ bdata = (unsigned int*) bot.scanLine(y) + sw;
+ for (int x = 0; x < tw; x++) {
+ *(bdata++) = *(tdata++);
+ }
+
+ }
+}
+
+void SlideShowGL::printFilename(QImage& layer)
+{
+ QFileInfo fileinfo(m_fileList[m_fileIndex].first);
+ QString filename = fileinfo.fileName();
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize());
+ fn.setBold(true);
+
+ QFontMetrics fm(fn);
+ QRect rect=fm.boundingRect(filename);
+ rect.addCoords( 0, 0, 2, 2 );
+
+ QPixmap pix(rect.width(),rect.height());
+ pix.fill(Qt::black);
+
+ QPainter p(&pix);
+ p.setPen(Qt::white);
+ p.setFont(fn);
+ p.drawText(1,fn.pointSize()+1 , filename);
+ p.end();
+
+ QImage textimage(pix.convertToImage());
+ KImageEffect::blendOnLower(0,m_height-rect.height(),textimage,layer);
+}
+
+void SlideShowGL::printProgress(QImage& layer)
+{
+ QString progress(QString::number(m_fileIndex + 1) + "/" + QString::number(m_fileList.count()));
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize());
+ fn.setBold(true);
+
+ QFontMetrics fm(fn);
+ QRect rect=fm.boundingRect(progress);
+ rect.addCoords( 0, 0, 2, 2 );
+
+ QPixmap pix(rect.width(),rect.height());
+ pix.fill(Qt::black);
+
+ QPainter p(&pix);
+
+ int stringLenght = p.fontMetrics().width(progress) * progress.length();
+
+ p.setPen(Qt::white);
+ p.setFont(fn);
+ p.drawText(1,fn.pointSize()+1 , progress);
+ p.end();
+
+ QImage textimage(pix.convertToImage());
+ KImageEffect::blendOnLower(m_width - stringLenght - 10,
+ 20,textimage,layer);
+}
+
+void SlideShowGL::printComments(QImage& layer)
+{
+ QString comments = m_commentsList[m_fileIndex];
+
+ int yPos = 5; // Text Y coordinate
+ if (m_printName) yPos += 20;
+
+ QStringList commentsByLines;
+
+ uint commentsIndex = 0; // Comments QString index
+
+ while (commentsIndex < comments.length())
+ {
+ QString newLine;
+ bool breakLine = FALSE; // End Of Line found
+ uint currIndex; // Comments QString current index
+
+ // Check miminal lines dimension
+
+ int commentsLinesLengthLocal = m_commentsLinesLength;
+
+ for ( currIndex = commentsIndex; currIndex < comments.length() && !breakLine; currIndex++ )
+ if( comments[currIndex] == QChar('\n') || comments[currIndex].isSpace() ) breakLine = TRUE;
+
+ if (commentsLinesLengthLocal <= (int)((currIndex - commentsIndex)))
+ commentsLinesLengthLocal = (currIndex - commentsIndex);
+
+ breakLine = FALSE;
+
+ for ( currIndex = commentsIndex; currIndex <= commentsIndex + commentsLinesLengthLocal &&
+ currIndex < comments.length() &&
+ !breakLine; currIndex++ )
+ {
+ breakLine = (comments[currIndex] == QChar('\n')) ? TRUE : FALSE;
+
+ if (breakLine)
+ newLine.append( ' ' );
+ else
+ newLine.append( comments[currIndex] );
+ }
+
+ commentsIndex = currIndex; // The line is ended
+
+ if ( commentsIndex != comments.length() )
+ while ( !newLine.endsWith(" ") )
+ {
+ newLine.truncate(newLine.length() - 1);
+ commentsIndex--;
+ }
+
+ commentsByLines.prepend(newLine.stripWhiteSpace());
+ }
+
+ QFontMetrics fm(*m_commentsFont);
+
+ for ( int lineNumber = 0; lineNumber < (int)commentsByLines.count(); lineNumber++ ) {
+
+ yPos += int(1.5 * m_commentsFont->pointSize());
+
+ QRect rect=fm.boundingRect(commentsByLines[lineNumber]);
+ rect.addCoords( 0, 0, 2, 2 );
+
+ QPixmap pix(rect.width(),rect.height());
+ pix.fill(QColor(m_commentsBgColor));
+
+ QPainter p(&pix);
+ p.setPen(QColor(m_commentsFontColor));
+ p.setFont(*m_commentsFont);
+ p.drawText(1,m_commentsFont->pointSize()+0 , commentsByLines[lineNumber]);
+ p.end();
+
+ QImage textimage(pix.convertToImage());
+ KImageEffect::blendOnLower(0,m_height-rect.height()-yPos,textimage,layer);
+ }
+}
+
+void SlideShowGL::showEndOfShow()
+{
+ QPixmap pix(512,512);
+ pix.fill(Qt::black);
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize()+10);
+ fn.setBold(true);
+
+ QPainter p(&pix);
+ p.setPen(Qt::white);
+ p.setFont(fn);
+ p.drawText(20, 50, i18n("SlideShow Completed."));
+ p.drawText(20, 100, i18n("Click To Exit..."));
+ p.end();
+
+ QImage image(pix.convertToImage());
+ QImage t = convertToGLFormat(image);
+
+ GLuint tex;
+
+ /* create the texture */
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ /* actually generate the texture */
+ glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
+ /* enable linear filtering */
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ /* paint the texture */
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0, -1.0, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0, -1.0, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0, 1.0, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0, 1.0, 0);
+ }
+ glEnd();
+
+}
+
+void SlideShowGL::slotTimeOut()
+{
+ if (!m_effect) {
+ kdWarning( 51000 ) << "SlideShowGL: No transition method"
+ << endl;
+ m_effect = &SlideShowGL::effectNone;
+ }
+
+ if (m_effectRunning) {
+ m_timeout = 10;
+ }
+ else {
+ if (m_timeout == -1) {
+ // effect was running and is complete now
+ // run timer while showing current image
+ m_timeout = m_delay;
+ m_i = 0;
+ }
+ else {
+
+ // timed out after showing current image
+ // load next image and start effect
+ if (m_random)
+ m_effect = getRandomEffect();
+
+ advanceFrame();
+ if (m_endOfShow) {
+ updateGL();
+ return;
+ }
+
+ loadImage();
+ m_timeout = 10;
+ m_effectRunning = true;
+ m_i = 0;
+
+ }
+ }
+
+ updateGL();
+ m_timer->start(m_timeout, true);
+}
+
+void SlideShowGL::slotMouseMoveTimeOut()
+{
+ QPoint pos(QCursor::pos());
+ if ((pos.y() < (m_deskY+20)) ||
+ (pos.y() > (m_deskY+m_deskHeight-20-1)))
+ return;
+
+ setCursor(QCursor(Qt::BlankCursor));
+}
+
+void SlideShowGL::paintTexture()
+{
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ GLuint& tex = m_texture[m_curr];
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0, -1.0, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0, -1.0, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0, 1.0, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0, 1.0, 0);
+ }
+ glEnd();
+}
+
+void SlideShowGL::effectNone()
+{
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+}
+
+void SlideShowGL::effectBlend()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0/(100.0)*(float)m_i);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ m_i++;
+}
+
+void SlideShowGL::effectFade()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ int a;
+ float opacity;
+ if (m_i <= 50) {
+ a = (m_curr == 0) ? 1 : 0;
+ opacity = 1.0 - 1.0/50.0*(float)(m_i);
+ }
+ else {
+ opacity = 1.0/50.0*(float)(m_i-50.0);
+ a = m_curr;
+ }
+
+ GLuint& ta = m_texture[a];
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, opacity);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+
+ m_i++;
+}
+
+void SlideShowGL::effectRotate()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ if (m_i == 0)
+ m_dir = (int)((2.0*rand()/(RAND_MAX+1.0)));
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ float rotate = 360.0/100.0*(float)m_i;
+ glRotatef( ((m_dir == 0) ? -1 : 1) * rotate,
+ 0.0, 0.0, 1.0);
+ float scale = 1.0/100.0*(100.0-(float)(m_i));
+ glScalef(scale,scale,1.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ m_i++;
+}
+
+void SlideShowGL::effectBend()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ if (m_i == 0)
+ m_dir = (int)((2.0*rand()/(RAND_MAX+1.0)));
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glRotatef(90.0/100.0*(float)m_i,
+ (m_dir == 0) ? 1.0 : 0.0,
+ (m_dir == 1) ? 1.0 : 0.0,
+ 0.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ m_i++;
+}
+
+void SlideShowGL::effectInOut()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ if (m_i == 0) {
+ m_dir = 1 + (int)((4.0*rand()/(RAND_MAX+1.0)));
+ }
+
+ int a;
+ bool out;
+ if (m_i <= 50) {
+ a = (m_curr == 0) ? 1 : 0;
+ out = 1;
+ }
+ else {
+ a = m_curr;
+ out = 0;
+ }
+
+ GLuint& ta = m_texture[a];
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ float t = out ? 1.0/50.0*(50.0-m_i) : 1.0/50.0*(m_i-50.0);
+ glScalef(t, t, 1.0);
+ t = 1.0 - t;
+ glTranslatef((m_dir % 2 == 0) ? ((m_dir == 2)? 1 : -1) * t : 0.0,
+ (m_dir % 2 == 1) ? ((m_dir == 1)? 1 : -1) * t : 0.0,
+ 0.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+
+ m_i++;
+}
+
+void SlideShowGL::effectSlide()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ if (m_i == 0)
+ m_dir = 1 + (int)((4.0*rand()/(RAND_MAX+1.0)));
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ float trans = 2.0/100.0*(float)m_i;
+ glTranslatef((m_dir % 2 == 0) ? ((m_dir == 2)? 1 : -1) * trans : 0.0,
+ (m_dir % 2 == 1) ? ((m_dir == 1)? 1 : -1) * trans : 0.0,
+ 0.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ m_i++;
+}
+
+void SlideShowGL::effectFlutter()
+{
+ if (m_i > 100) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ if (m_i == 0) {
+ for (int x = 0; x<40; x++) {
+ for (int y = 0; y < 40; y++) {
+ m_points[x][y][0] = (float) (x / 20.0f - 1.0f);
+ m_points[x][y][1] = (float) (y / 20.0f - 1.0f);
+ m_points[x][y][2] = (float) sin((x / 20.0f - 1.0f) *
+ 3.141592654*2.0f)/5.0;
+ }
+ }
+ }
+
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0f, -1.0f, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0f, 1.0f, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0f, 1.0f, 0);
+ }
+ glEnd();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ float rotate = 60.0/100.0*(float)m_i;
+ glRotatef(rotate, 1.0f, 0.0f, 0.0f);
+ float scale = 1.0/100.0*(100.0-(float)m_i);
+ glScalef(scale, scale, scale);
+ glTranslatef(1.0/100.0*(float)m_i, 1.0/100.0*(float)m_i, 0.0);
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ float float_x, float_y, float_xb, float_yb;
+ int x, y;
+
+ for (x = 0; x < 39; x++)
+ {
+ for (y = 0; y < 39; y++)
+ {
+ float_x = (float) x / 40.0f;
+ float_y = (float) y / 40.0f;
+ float_xb = (float) (x + 1) / 40.0f;
+ float_yb = (float) (y + 1) / 40.0f;
+ glTexCoord2f(float_x, float_y);
+ glVertex3f(m_points[x][y][0], m_points[x][y][1], m_points[x][y][2]);
+ glTexCoord2f(float_x, float_yb);
+ glVertex3f(m_points[x][y + 1][0], m_points[x][y + 1][1],
+ m_points[x][y + 1][2]);
+ glTexCoord2f(float_xb, float_yb);
+ glVertex3f(m_points[x + 1][y + 1][0], m_points[x + 1][y + 1][1],
+ m_points[x + 1][y + 1][2]);
+ glTexCoord2f(float_xb, float_y);
+ glVertex3f(m_points[x + 1][y][0], m_points[x + 1][y][1],
+ m_points[x + 1][y][2]);
+ }
+ }
+ }
+ glEnd();
+
+ // wave every two iterations
+ if (m_i%2 == 0) {
+
+ float hold;
+ int x, y;
+ for (y = 0; y < 40; y++)
+ {
+ hold = m_points[0][y][2];
+ for (x = 0; x < 39; x++)
+ {
+ m_points[x][y][2] = m_points[x + 1][y][2];
+ }
+ m_points[39][y][2] = hold;
+ }
+ }
+ m_i++;
+}
+
+void SlideShowGL::effectCube()
+{
+ int tot = 200;
+ int rotStart = 50;
+
+ if (m_i > tot) {
+ paintTexture();
+ m_effectRunning = false;
+ m_timeout = -1;
+ return;
+ }
+
+ // Enable perspective vision
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+ int a = (m_curr == 0) ? 1 : 0;
+ int b = m_curr;
+
+ GLuint& ta = m_texture[a];
+ GLuint& tb = m_texture[b];
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ float PI = 4.0 * atan(1.0);
+ float znear = 3.0;
+ float theta = 2.0 * atan2((float)2.0/(float)2.0, (float)znear);
+ theta = theta * 180.0/PI;
+
+ glFrustum(-1.0,1.0,-1.0,1.0, znear-0.01,10.0);
+
+
+ static float xrot;
+ static float yrot;
+ static float zrot;
+
+ if (m_i == 0) {
+ xrot = 0.0;
+ yrot = 0.0;
+ zrot = 0.0;
+ }
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ float trans = 5.0 * (float)((m_i <= tot/2) ? m_i : tot-m_i)/(float)tot;
+ glTranslatef(0.0,0.0, -znear - 1.0 - trans);
+
+ glRotatef(xrot, 1.0f, 0.0f, 0.0f);
+ glRotatef(yrot, 0.0f, 1.0f, 0.0f);
+
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+
+ /* Front Face */
+ glVertex3f( -1.00f, -1.00f, 0.99f );
+ glVertex3f( 1.00f, -1.00f, 0.99f );
+ glVertex3f( 1.00f, 1.00f, 0.99f );
+ glVertex3f( -1.00f, 1.00f, 0.99f );
+
+ /* Back Face */
+ glVertex3f( -1.00f, -1.00f, -0.99f );
+ glVertex3f( -1.00f, 1.00f, -0.99f );
+ glVertex3f( 1.00f, 1.00f, -0.99f );
+ glVertex3f( 1.00f, -1.00f, -0.99f );
+
+ /* Top Face */
+ glVertex3f( -1.00f, 0.99f, -1.00f );
+ glVertex3f( -1.00f, 0.99f, 1.00f );
+ glVertex3f( 1.00f, 0.99f, 1.00f );
+ glVertex3f( 1.00f, 0.99f, -1.00f );
+
+ /* Bottom Face */
+ glVertex3f( -1.00f, -0.99f, -1.00f );
+ glVertex3f( 1.00f, -0.99f, -1.00f );
+ glVertex3f( 1.00f, -0.99f, 1.00f );
+ glVertex3f( -1.00f, -0.99f, 1.00f );
+
+ /* Right face */
+ glVertex3f( 0.99f, -1.00f, -1.00f );
+ glVertex3f( 0.99f, 1.00f, -1.00f );
+ glVertex3f( 0.99f, 1.00f, 1.00f );
+ glVertex3f( 0.99f, -1.00f, 1.00f );
+
+ /* Left Face */
+ glVertex3f( -0.99f, -1.00f, -1.00f );
+ glVertex3f( -0.99f, -1.00f, 1.00f );
+ glVertex3f( -0.99f, 1.00f, 1.00f );
+ glVertex3f( -0.99f, 1.00f, -1.00f );
+
+ }
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, ta);
+ glBegin(GL_QUADS);
+ {
+ glColor4d(1.0, 1.0, 1.0, 1.0);
+
+ // Front Face
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, 1.00f );
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, 1.00f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, 1.00f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, 1.00f );
+
+
+ // Top Face
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.0f, 1.00f, -1.0f );
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.0f, 1.00f, 1.0f );
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f, 1.00f, 1.0f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f, 1.00f, -1.0f );
+
+ // Bottom Face
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, -1.00f, -1.0f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, -1.00f, -1.0f );
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, -1.00f, 1.0f );
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.00f, 1.0f );
+
+ // Right face
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.00f, -1.0f, -1.0f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.00f, -1.0f, 1.0f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.00f, 1.0f, 1.0f );
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.00f, 1.0f, -1.0f );
+
+ // Left Face
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.00f, -1.0f, -1.0f );
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.00f, 1.0f, -1.0f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.00f, 1.0f, 1.0f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.00f, -1.0f, 1.0f );
+
+ }
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, tb);
+ glBegin(GL_QUADS);
+ {
+ glColor4d(1.0, 1.0, 1.0, 1.0);
+
+ // Back Face
+ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, -1.00f );
+ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, -1.00f );
+ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, -1.00f );
+ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, -1.00f );
+ }
+ glEnd();
+
+ if (m_i >= rotStart && m_i < (tot-rotStart)) {
+ xrot += 360.0f/(float)(tot-2*rotStart);
+ yrot += 180.0f/(float)(tot-2*rotStart);
+ }
+
+ m_i++;
+}
+
+void SlideShowGL::slotPause()
+{
+ m_timer->stop();
+
+ if (m_toolBar->isHidden())
+ {
+ int w = m_toolBar->width();
+ m_toolBar->move(m_deskWidth-w-1,0);
+ m_toolBar->show();
+ }
+}
+
+void SlideShowGL::slotPlay()
+{
+ m_toolBar->hide();
+ slotTimeOut();
+}
+
+void SlideShowGL::slotPrev()
+{
+ previousFrame();
+ if (m_endOfShow) {
+ updateGL();
+ return;
+ }
+
+ m_effectRunning = false;
+ loadImage();
+ updateGL();
+}
+
+void SlideShowGL::slotNext()
+{
+ advanceFrame();
+ if (m_endOfShow) {
+ updateGL();
+ return;
+ }
+
+ m_effectRunning = false;
+ loadImage();
+ updateGL();
+}
+
+void SlideShowGL::slotClose()
+{
+ close();
+}
+
+} // NameSpace KIPISlideShowPlugin
+
+#include "slideshowgl.moc"
diff --git a/kipi-plugins/slideshow/slideshowgl.h b/kipi-plugins/slideshow/slideshowgl.h
new file mode 100644
index 0000000..bb1bc8e
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowgl.h
@@ -0,0 +1,172 @@
+/* ============================================================
+ * File : slideshowgl.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-01-19
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright 2007 by Valerio Fuoglio <valerio.fuoglio@gmail.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SLIDESHOWGL_H
+#define SLIDESHOWGL_H
+
+// KDE includes
+#include <kconfig.h>
+
+// QT includes
+#include <qvaluelist.h>
+#include <qstringlist.h>
+#include <qpair.h>
+#include <qstring.h>
+#include <qmap.h>
+#include <qgl.h>
+
+// Local includes
+#include "slideshowloader.h"
+
+class QTimer;
+
+namespace KIPISlideShowPlugin
+{
+ class SlideShowGL;
+ class ToolBar;
+
+ class SlideShowGL : public QGLWidget
+ {
+ Q_OBJECT
+
+ public:
+
+ SlideShowGL(const QValueList<QPair<QString, int> >& fileList,
+ const QStringList& commentsList, bool ImagesHasComments);
+ ~SlideShowGL();
+
+ void registerEffects();
+
+ static QStringList effectNames();
+ static QMap<QString,QString> effectNamesI18N();
+
+ protected:
+
+ void initializeGL();
+ void paintGL();
+ void resizeGL(int w, int h);
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *);
+ void wheelEvent(QWheelEvent *e);
+ void keyPressEvent(QKeyEvent *event);
+
+ private:
+
+ // config ------------------
+
+ KConfig* m_config;
+
+ int m_delay;
+ QString m_effectName;
+ bool m_loop;
+ bool m_printName;
+ bool m_printProgress;
+ bool m_printComments;
+
+ bool m_imagesHasComments;
+
+ QFont* m_commentsFont;
+ uint m_commentsFontColor;
+ uint m_commentsBgColor;
+ int m_commentsLinesLength;
+
+ bool m_enableMouseWheel;
+
+ uint m_cacheSize;
+ // -------------------------
+
+ typedef void (SlideShowGL::*EffectMethod)();
+ QMap<QString, EffectMethod> m_effects;
+
+ QValueList<QPair<QString, int> > m_fileList;
+ QStringList m_commentsList;
+ QTimer* m_timer;
+ int m_fileIndex;
+
+ SlideShowLoader* m_imageLoader;
+ GLuint m_texture[2];
+ bool m_tex1First;
+ int m_curr;
+
+ int m_width;
+ int m_height;
+
+ EffectMethod m_effect;
+ bool m_effectRunning;
+ int m_timeout;
+ bool m_random;
+ bool m_endOfShow;
+
+ int m_i;
+ int m_dir;
+ float m_points[40][40][3];
+
+ ToolBar* m_toolBar;
+ QTimer* m_mouseMoveTimer;
+
+ int m_deskX;
+ int m_deskY;
+ int m_deskWidth;
+ int m_deskHeight;
+
+ private:
+
+ void paintTexture();
+ void advanceFrame();
+ void previousFrame();
+ void loadImage();
+ void montage(QImage& top, QImage& bot);
+ EffectMethod getRandomEffect();
+ void showEndOfShow();
+ void printFilename(QImage& layer);
+ void printProgress(QImage& layer);
+ void printComments(QImage& layer);
+
+ void readSettings();
+
+ void effectNone();
+ void effectBlend();
+ void effectFade();
+ void effectRotate();
+ void effectBend();
+ void effectInOut();
+ void effectSlide();
+ void effectFlutter();
+ void effectCube();
+
+
+ private slots:
+
+ void slotTimeOut();
+ void slotMouseMoveTimeOut();
+
+ void slotPause();
+ void slotPlay();
+ void slotPrev();
+ void slotNext();
+ void slotClose();
+ };
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif /* SLIDESHOWGL_H */
diff --git a/kipi-plugins/slideshow/slideshowkb.cpp b/kipi-plugins/slideshow/slideshowkb.cpp
new file mode 100644
index 0000000..2f08205
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowkb.cpp
@@ -0,0 +1,578 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de> and slideshowgl.{cpp|h} by Renchi Raju
+ * <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cassert>
+#include <cmath>
+
+// Qt includes.
+
+#include <qapplication.h>
+#include <qimage.h>
+#include <qdatetime.h>
+#include <qpainter.h>
+#include <qobject.h>
+#include <qfont.h>
+#include <qcursor.h>
+
+// KDE includes.
+
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdeversion.h>
+#include <kglobalsettings.h>
+
+// Local includes.
+
+#include "slideshowkb.h"
+#include "imageloadthread.h"
+#include "slideshowkb.moc"
+
+namespace KIPISlideShowPlugin
+{
+ // -------------------------------------------------------------------------
+
+ ViewTrans::ViewTrans(bool zoomIn, float relAspect) {
+
+ int i;
+
+ // randomly select sizes of start end end viewport
+ double s[2];
+ i = 0;
+ do {
+ s[0] = 0.3 * rnd() + 1.0;
+ s[1] = 0.3 * rnd() + 1.0;
+ } while (fabs(s[0] - s[1]) < 0.15 && ++i < 10);
+
+ if (zoomIn xor s[0] > s[1]) {
+ double tmp = s[0];
+ s[0] = s[1];
+ s[1] = tmp;
+ }
+
+ m_deltaScale = s[1] / s[0] - 1.0;
+ m_baseScale = s[0];
+
+ // additional scale factors to ensure proper m_aspect of the displayed image
+ double x[2], y[2], xMargin[2], yMargin[2], bestDist;
+ double sx, sy;
+ if (relAspect > 1.0) {
+ sx = 1.0;
+ sy = relAspect;
+ } else {
+ sx = 1.0 / relAspect;
+ sy = 1.0;
+ }
+ m_xScale = sx;
+ m_yScale = sy;
+
+ // calculate path
+ xMargin[0] = (s[0] * sx - 1.0) / 2.0;
+ yMargin[0] = (s[0] * sy - 1.0) / 2.0;
+ xMargin[1] = (s[1] * sx - 1.0) / 2.0;
+ yMargin[1] = (s[1] * sy - 1.0) / 2.0;
+
+ i = 0;
+ bestDist = 0.0;
+ do {
+ double sign = rndSign();
+ x[0] = xMargin[0] * (0.2 * rnd() + 0.8) * sign;
+ y[0] = yMargin[0] * (0.2 * rnd() + 0.8) * -sign;
+ x[1] = xMargin[1] * (0.2 * rnd() + 0.8) * -sign;
+ y[1] = yMargin[1] * (0.2 * rnd() + 0.8) * sign;
+
+ if (fabs(x[1] - x[0]) + fabs(y[1] - y[0]) > bestDist) {
+ m_baseX = x[0];
+ m_baseY = y[0];
+ m_deltaX = x[1] - x[0];
+ m_deltaY = y[1] - y[0];
+ bestDist = fabs(m_deltaX) + fabs(m_deltaY);
+ }
+
+ } while (bestDist < 0.3 && ++i < 10);
+ }
+
+ // -------------------------------------------------------------------------
+
+ Image::Image(ViewTrans *viewTrans, float aspect) {
+
+ this->m_viewTrans = viewTrans;
+ this->m_aspect = aspect;
+ this->m_pos = 0.0;
+ this->m_opacity = 0.0;
+ this->m_paint = (m_viewTrans) ? true : false;
+ this->m_texture = 0;
+ }
+
+ Image::~Image() {
+
+ delete m_viewTrans;
+ if (glIsTexture(m_texture))
+ glDeleteTextures(1, &m_texture);
+ }
+
+ // -------------------------------------------------------------------------
+ SlideShowKB::SlideShowKB(const QValueList<QPair<QString, int> >& fileList,
+ const QStringList& commentsList, bool ImagesHasComments)
+ : QGLWidget(0, 0, 0, WStyle_StaysOnTop | WType_Popup |
+ WX11BypassWM | WDestructiveClose)
+ {
+ #if KDE_IS_VERSION(3,2,0)
+ QRect deskRect = KGlobalSettings::desktopGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+ #else
+ QRect deskRect = QApplication::desktop()->screenGeometry(this);
+ m_deskX = deskRect.x();
+ m_deskY = deskRect.y();
+ m_deskWidth = deskRect.width();
+ m_deskHeight = deskRect.height();
+ #endif
+
+ move(m_deskX, m_deskY);
+ resize(m_deskWidth, m_deskHeight);
+
+ // =======================================================
+ // Avoid boring compile time "unused parameter" warning :P
+ // These parameters could be useful for future implementations
+ m_commentsList = commentsList;
+ m_imagesHasComments = ImagesHasComments;
+ // =======================================================
+
+ srand(QTime::currentTime().msec());
+
+ m_config = new KConfig("kipirc");
+ m_config->setGroup("SlideShow Settings");
+ readSettings();
+
+ m_screen = new ScreenProperties(this);
+ m_screen->enableVSync();
+
+ unsigned frameRate;
+ if (m_forceFrameRate == 0)
+ frameRate = m_screen->suggestFrameRate() * 2;
+ else
+ frameRate = m_forceFrameRate;
+
+ m_image[0] = new Image(0);
+ m_image[1] = new Image(0);
+ m_effect = 0;
+ m_step = 1.0 / ((float) (m_delay * frameRate));
+ m_zoomIn = rand() < RAND_MAX / 2;
+ m_initialized = false;
+ m_haveImages = true;
+
+ QValueList<QPair<QString, int> > m_fileList = fileList;
+
+ m_imageLoadThread = new ImageLoadThread(m_fileList, width(), height());
+ m_timer = new QTimer(this);
+
+ m_endOfShow = false;
+ m_showingEnd = false;
+
+ connect(m_timer, SIGNAL(timeout(void)), this, SLOT(moveSlot()));
+ connect(m_imageLoadThread, SIGNAL(endOfShow(void)), this, SLOT(slotEndOfShow()));
+
+ // -- hide cursor when not moved --------------------
+
+ m_mouseMoveTimer = new QTimer;
+ connect(m_mouseMoveTimer, SIGNAL(timeout()),
+ SLOT(slotMouseMoveTimeOut()));
+
+ setMouseTracking(true);
+ slotMouseMoveTimeOut();
+
+ m_imageLoadThread->start();
+ m_timer->start(1000 / frameRate);
+ }
+
+ SlideShowKB::~SlideShowKB() {
+
+ delete m_effect;
+ delete m_image[0];
+ delete m_image[1];
+
+ m_imageLoadThread->quit();
+ bool terminated = m_imageLoadThread->wait(10000);
+
+ if ( !terminated) {
+ m_imageLoadThread->terminate();
+ terminated = m_imageLoadThread->wait(3000);
+ }
+
+ if (terminated)
+ delete m_imageLoadThread;
+
+ delete m_mouseMoveTimer;
+ delete m_timer;
+ delete m_screen;
+ }
+
+
+ void SlideShowKB::setNewKBEffect() {
+
+ KBEffect::Type type;
+ bool needFadeIn = (m_effect == 0 || m_effect->type() == KBEffect::Fade);
+
+ // we currently only have two effects
+ if (m_disableFadeInOut)
+ type = KBEffect::Blend;
+ else if (m_disableCrossFade)
+ type = KBEffect::Fade;
+ else
+ type = KBEffect::chooseKBEffect((m_effect) ? m_effect->type() : KBEffect::Fade);
+
+ delete m_effect;
+ switch (type) {
+ case KBEffect::Fade:
+ m_effect = new FadeKBEffect(this, needFadeIn);
+ break;
+ case KBEffect::Blend:
+ m_effect = new BlendKBEffect(this, needFadeIn);
+ break;
+ default:
+ qDebug("Unknown transition effect, falling back to crossfade");
+ m_effect = new BlendKBEffect(this, needFadeIn);
+ }
+ }
+
+
+ void SlideShowKB::moveSlot() {
+
+ if (m_initialized) {
+
+ if (m_effect->done()) {
+ setNewKBEffect();
+ m_imageLoadThread->requestNewImage();
+ }
+ m_effect->advanceTime(m_step);
+ }
+
+ updateGL();
+ }
+
+
+ bool SlideShowKB::setupNewImage(int idx) {
+
+ assert(idx >= 0 && idx < 2);
+
+ if ( !m_haveImages)
+ return false;
+
+ bool ok = false;
+ m_zoomIn = !m_zoomIn;
+
+ if (m_imageLoadThread->grabImage()) {
+
+ delete m_image[idx];
+
+ // we have the image lock and there is an image
+ float imageAspect = m_imageLoadThread->imageAspect();
+ ViewTrans *viewTrans = new ViewTrans(m_zoomIn, aspect() / imageAspect);
+ m_image[idx] = new Image(viewTrans, imageAspect);
+
+ applyTexture(m_image[idx], m_imageLoadThread->image());
+ ok = true;
+
+ }
+ else {
+ m_haveImages = false;
+ }
+
+ // don't forget to release the lock on the copy of the image
+ // owned by the image loader thread
+ m_imageLoadThread->ungrabImage();
+
+ return ok;
+ }
+
+ void SlideShowKB::startSlideShowOnce() {
+ // when the image loader thread is ready, it will already have loaded
+ // the first image
+ if (m_initialized == false && m_imageLoadThread->ready()) {
+
+ setupNewImage(0); // setup the first image and
+ m_imageLoadThread->requestNewImage(); // load the next one in background
+ setNewKBEffect(); // set the initial effect
+
+ m_initialized = true;
+ }
+ }
+
+
+ void SlideShowKB::swapImages() {
+
+ Image *tmp = m_image[0];
+ m_image[0] = m_image[1];
+ m_image[1] = tmp;
+ }
+
+
+ void SlideShowKB::initializeGL() {
+
+ // Enable Texture Mapping
+ glEnable(GL_TEXTURE_2D);
+
+ // Clear The Background Color
+ glClearColor(0.0, 0.0, 0.0, 1.0f);
+
+ glEnable (GL_TEXTURE_2D);
+ glShadeModel (GL_SMOOTH);
+
+ // Turn Blending On
+ glEnable(GL_BLEND);
+ // Blending Function For Translucency Based On Source Alpha Value
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ // Enable perspective vision
+ glClearDepth(1.0f);
+ }
+
+
+ void SlideShowKB::paintGL() {
+
+ startSlideShowOnce();
+
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+
+ // only clear the color buffer, if none of the active images is fully opaque
+ if ( !((m_image[0]->m_paint && m_image[0]->m_opacity == 1.0) ||
+ (m_image[1]->m_paint && m_image[1]->m_opacity == 1.0)) )
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ if (m_endOfShow && m_image[0]->m_paint && m_image[1]->m_paint)
+ {
+ endOfShow();
+ m_timer->stop();
+ }
+ else
+ {
+ if (m_image[1]->m_paint)
+ paintTexture(m_image[1]);
+ if (m_image[0]->m_paint)
+ paintTexture(m_image[0]);
+ }
+ glFlush();
+ }
+
+
+ void SlideShowKB::resizeGL(int w, int h) {
+ glViewport(0, 0, (GLint) w, (GLint) h);
+ }
+
+
+
+ void SlideShowKB::applyTexture(Image *img, const QImage &texture) {
+
+ /* create the texture */
+ glGenTextures(1, &img->m_texture);
+ glBindTexture(GL_TEXTURE_2D, img->m_texture);
+
+ /* actually generate the texture */
+ glTexImage2D(GL_TEXTURE_2D, 0, 3, texture.width(), texture.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture.bits());
+ /* enable linear filtering */
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ }
+
+
+ void SlideShowKB::paintTexture(Image *img) {
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ float sx = img->m_viewTrans->m_xScaleCorrect();
+ float sy = img->m_viewTrans->m_yScaleCorrect();
+
+ glTranslatef(img->m_viewTrans->transX(img->m_pos) * 2.0,
+ img->m_viewTrans->transY(img->m_pos) * 2.0, 0.0);
+ glScalef(img->m_viewTrans->scale(img->m_pos),
+ img->m_viewTrans->scale(img->m_pos), 0.0);
+
+ GLuint& tex = img->m_texture;
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, img->m_opacity);
+ glTexCoord2f(0, 0);
+ glVertex3f(-sx, -sy, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(sx, -sy, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(sx, sy, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-sx, sy, 0);
+ }
+ glEnd();
+
+ }
+
+
+ void SlideShowKB::readSettings() {
+ m_delay = m_config->readUnsignedNumEntry("Delay", 8000)/1000;
+ m_disableFadeInOut = m_config->readBoolEntry("KB Disable FadeInOut", false);
+ m_disableCrossFade = m_config->readBoolEntry("KB Disable Crossfade", false);
+ m_forceFrameRate = m_config->readUnsignedNumEntry("KB Force Framerate", 0);
+
+ if (m_delay < 5) m_delay = 5;
+// if (m_delay > 20) m_delay = 20;
+ if (m_forceFrameRate > 120) m_forceFrameRate = 120;
+ }
+
+ void SlideShowKB::endOfShow()
+ {
+ QPixmap pix(512,512);
+ pix.fill(Qt::black);
+
+ QFont fn(font());
+ fn.setPointSize(fn.pointSize()+10);
+ fn.setBold(true);
+
+ QPainter p(&pix);
+ p.setPen(Qt::white);
+ p.setFont(fn);
+ p.drawText(20, 50, i18n("SlideShow Completed."));
+ p.drawText(20, 100, i18n("Click To Exit..."));
+ p.end();
+
+ QImage image(pix.convertToImage());
+ QImage t = convertToGLFormat(image);
+
+ GLuint tex;
+
+ /* create the texture */
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ /* actually generate the texture */
+ glTexImage2D( GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, t.bits() );
+ /* enable linear filtering */
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+
+ /* paint the texture */
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glBegin(GL_QUADS);
+ {
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+ glTexCoord2f(0, 0);
+ glVertex3f(-1.0, -1.0, 0);
+
+ glTexCoord2f(1, 0);
+ glVertex3f(1.0, -1.0, 0);
+
+ glTexCoord2f(1, 1);
+ glVertex3f(1.0, 1.0, 0);
+
+ glTexCoord2f(0, 1);
+ glVertex3f(-1.0, 1.0, 0);
+ }
+ glEnd();
+
+ m_showingEnd = true;
+ }
+
+ QStringList SlideShowKB::effectNames()
+ {
+ QStringList effects;
+
+ effects.append("Ken Burns");
+ return effects;
+ }
+
+ QMap<QString,QString> SlideShowKB::effectNamesI18N()
+ {
+ QMap<QString,QString> effects;
+
+ effects["Ken Burns"] = i18n("Ken Burns");
+
+ return effects;
+ }
+
+ void SlideShowKB::mousePressEvent(QMouseEvent *e)
+ {
+ // =======================================================
+ // Avoid boring compile time "unused parameter" warning :P
+ // This parameter could be useful for future implementations
+ if ( !e ) { /* TODO */ }
+ // =======================================================
+
+ if (m_endOfShow && m_showingEnd)
+ slotClose();
+ }
+
+ void SlideShowKB::mouseMoveEvent(QMouseEvent *e)
+ {
+ setCursor(QCursor(Qt::ArrowCursor));
+ m_mouseMoveTimer->start(1000, true);
+
+ QPoint pos(e->pos());
+ }
+
+ void SlideShowKB::slotEndOfShow()
+ {
+ m_endOfShow = true;
+ }
+
+ void SlideShowKB::slotMouseMoveTimeOut()
+ {
+ QPoint pos(QCursor::pos());
+ if ((pos.y() < (m_deskY+20)) ||
+ (pos.y() > (m_deskY+m_deskHeight-20-1)))
+ return;
+
+ setCursor(QCursor(Qt::BlankCursor));
+ }
+
+ void SlideShowKB::slotClose()
+ {
+ close();
+ }
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/slideshowkb.h b/kipi-plugins/slideshow/slideshowkb.h
new file mode 100644
index 0000000..58c2ce8
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowkb.h
@@ -0,0 +1,190 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-14
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ *
+ * Parts of this code are based on smoothslidesaver by Carsten Weinhold
+ * <carsten dot weinhold at gmx dot de> and slideshowgl.{cpp|h} by Renchi Raju
+ * <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SLIDESHOWKB_H
+#define SLIDESHOWKB_H
+
+// C++ includes.
+
+#include <cstdlib>
+
+// Qt includes.
+
+#include <qgl.h>
+#include <qtimer.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qevent.h>
+#include <qmap.h>
+
+// KDE includes.
+
+#include <kconfig.h>
+
+// Local includes.
+
+#include "kbeffect.h"
+#include "screenproperties.h"
+
+namespace KIPISlideShowPlugin
+{
+ class SmoothSlideSaver;
+ class ImageLoadThread;
+
+ // -------------------------------------------------------------------------
+
+ class ViewTrans
+ {
+
+ public:
+
+ ViewTrans(bool m_zoomIn, float relAspect);
+
+ float transX(float pos) const { return m_baseX + m_deltaX * pos; };
+ float transY(float pos) const { return m_baseY + m_deltaY * pos; };
+ float scale (float pos) const { return m_baseScale * (1.0 + m_deltaScale * pos); };
+ float m_xScaleCorrect() { return m_xScale; };
+ float m_yScaleCorrect() { return m_yScale; };
+
+ private:
+
+ double rnd() const { return (double)rand() / (double)RAND_MAX; };
+ double rndSign() const { return (rand() < RAND_MAX / 2) ? 1.0 : -1.0; };
+
+ private:
+
+ // delta and scale values (begin to end) and the needed offsets
+ double m_deltaX, m_deltaY, m_deltaScale;
+ double m_baseScale, m_baseX, m_baseY;
+ float m_xScale, m_yScale;
+ };
+
+ // -------------------------------------------------------------------------
+
+ class Image
+ {
+
+ public:
+
+ Image(ViewTrans *viewTrans, float aspect = 1.0);
+ ~Image();
+
+ ViewTrans* m_viewTrans;
+ float m_aspect;
+ float m_pos;
+ float m_opacity;
+ bool m_paint;
+ GLuint m_texture;
+ };
+
+ // -------------------------------------------------------------------------
+
+ class SlideShowKB : public QGLWidget
+ {
+
+ Q_OBJECT
+
+ public:
+
+ SlideShowKB(const QValueList<QPair<QString, int> >& fileList,
+ const QStringList& commentsList, bool ImagesHasComments);
+
+ ~SlideShowKB();
+
+ static QStringList effectNames();
+ static QMap<QString,QString> effectNamesI18N();
+
+ private:
+
+ float aspect() { return (float)width() / (float)height(); };
+ bool setupNewImage(int imageIndex);
+ void startSlideShowOnce();
+ void swapImages();
+ void setNewKBEffect();
+ void endOfShow();
+
+ void initializeGL();
+ void paintGL();
+ void resizeGL(int w, int h);
+ void applyTexture(Image *img, const QImage &image);
+ void paintTexture(Image *img);
+ unsigned suggestFrameRate(unsigned forceRate);
+
+ void readSettings();
+
+ protected:
+
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *);
+
+ private slots:
+
+ void moveSlot();
+ void slotEndOfShow();
+ void slotMouseMoveTimeOut();
+ void slotClose();
+
+ private:
+
+ int m_deskX;
+ int m_deskY;
+ int m_deskWidth;
+ int m_deskHeight;
+
+ KConfig* m_config;
+
+ bool m_imagesHasComments;
+ QStringList m_commentsList;
+
+ ScreenProperties* m_screen;
+ QTimer *m_timer;
+ QTimer *m_mouseMoveTimer;
+ ImageLoadThread *m_imageLoadThread;
+ bool m_haveImages;
+
+ Image *m_image[2];
+ KBEffect *m_effect;
+ int m_numKBEffectRepeated;
+ bool m_zoomIn, m_initialized;
+ float m_step;
+
+ bool m_endOfShow;
+ bool m_showingEnd;
+
+ // settings from config file
+ int m_delay;
+ bool m_disableFadeInOut;
+ bool m_disableCrossFade;
+ unsigned m_forceFrameRate;
+
+ friend class KBEffect;
+ };
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // SLIDESHOWKB_H
diff --git a/kipi-plugins/slideshow/slideshowloader.cpp b/kipi-plugins/slideshow/slideshowloader.cpp
new file mode 100644
index 0000000..b208783
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowloader.cpp
@@ -0,0 +1,219 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-11
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// QT includes
+
+#include <qimage.h>
+#include <qwmatrix.h>
+#include <qpainter.h>
+#include <qvaluelist.h>
+
+// KDE includes
+
+#include <kdebug.h>
+
+// Local includes
+
+#include "slideshowloader.h"
+
+namespace KIPISlideShowPlugin
+{
+
+ LoadThread::LoadThread(LoadedImages* loadedImages, QMutex* imageLock, const KURL path,
+ const int angle, int width, int height) {
+
+ m_path = path;
+ m_angle = angle;
+ m_swidth = width;
+ m_sheight = height;
+ m_imageLock = imageLock;
+ m_loadedImages = loadedImages;
+ }
+
+ LoadThread::~LoadThread() {
+ }
+
+ void LoadThread::run() {
+
+ QImage newImage(m_path.path());
+ // Rotate according to angle
+ if ( m_angle != 0 )
+ {
+ QWMatrix matrix;
+ matrix.rotate((double)m_angle);
+ newImage.xForm( matrix );
+ }
+
+
+ newImage = QImage(newImage.smoothScale(m_swidth, m_sheight, QImage::ScaleMin));
+
+ m_imageLock->lock();
+ m_loadedImages->insert(m_path, newImage);
+ m_imageLock->unlock();
+ }
+
+ // -----------------------------------------------------------------------------------------
+
+ SlideShowLoader::SlideShowLoader(FileList &pathList, uint cacheSize, int width, int height, int beginAtIndex) {
+
+ m_currIndex = beginAtIndex;
+ m_cacheSize = cacheSize;
+ m_pathList = pathList;
+ m_swidth = width;
+ m_sheight = height;
+ m_loadingThreads = new LoadingThreads();
+ m_loadedImages = new LoadedImages();
+ m_imageLock = new QMutex();
+ m_threadLock = new QMutex();
+
+ for ( uint i = 0; i < uint(m_cacheSize/2) && i < uint(m_pathList.count()); i++ ) {
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[i].first),
+ m_pathList[i].second, m_swidth, m_sheight);
+ m_threadLock->lock();
+ m_loadingThreads->insert(m_pathList[i].first, newThread);
+ newThread->start();
+ m_threadLock->unlock();
+ }
+ for ( uint i = 0; i < ( m_cacheSize%2 == 0? (m_cacheSize%2) : uint(m_cacheSize/2)+1); i++ ) {
+ int toLoad = (m_currIndex - i)%m_pathList.count();
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[toLoad].first),
+ m_pathList[toLoad].second, m_swidth, m_sheight);
+ m_threadLock->lock();
+ m_loadingThreads->insert(m_pathList[toLoad].first, newThread);
+ newThread->start();
+ m_threadLock->unlock();
+ }
+
+ }
+
+ SlideShowLoader::~SlideShowLoader() {
+
+ m_threadLock->lock();
+ LoadingThreads::Iterator it;
+ for ( it = m_loadingThreads->begin(); it != m_loadingThreads->end(); ++it ) {
+ it.data()->wait();
+ delete it.data();
+ m_loadingThreads->remove(it);
+ }
+ m_threadLock->unlock();
+
+
+ delete(m_loadingThreads);
+ delete(m_loadedImages);
+
+ delete(m_imageLock);
+ delete(m_threadLock);
+ }
+
+ void SlideShowLoader::next() {
+ int victim = (m_currIndex - ( m_cacheSize%2 == 0 ? (m_cacheSize/2)-1 : int(m_cacheSize/2))) % m_pathList.count();
+ int newBorn = (m_currIndex + int(m_cacheSize/2) + 1) % m_pathList.count();
+
+ if ( victim == newBorn ) return;
+
+ m_threadLock->lock();
+ m_imageLock->lock();
+ m_loadingThreads->remove(m_pathList[victim].first);
+ m_loadedImages->remove(m_pathList[victim].first);
+ m_imageLock->unlock();
+ m_threadLock->unlock();
+
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[newBorn].first),
+ m_pathList[newBorn].second, m_swidth, m_sheight);
+
+ m_threadLock->lock();
+ m_loadingThreads->insert(m_pathList[newBorn].first, newThread);
+ newThread->start();
+ m_threadLock->unlock();
+
+ m_currIndex = (m_currIndex + 1) % m_pathList.count();
+ }
+
+ void SlideShowLoader::prev() {
+ int victim = (m_currIndex + int(m_currIndex/2)) % m_pathList.count();
+ int newBorn = (m_currIndex - ( m_cacheSize&2 == 0 ? (m_cacheSize/2) : int(m_cacheSize/2)+1)) % m_pathList.count();
+
+ if ( victim == newBorn ) return;
+
+ m_threadLock->lock();
+ m_imageLock->lock();
+ m_loadingThreads->remove(m_pathList[victim].first);
+ m_loadedImages->remove(m_pathList[victim].first);
+ m_imageLock->unlock();
+ m_threadLock->unlock();
+
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[newBorn].first),
+ m_pathList[newBorn].second, m_swidth, m_sheight);
+
+
+ m_threadLock->lock();
+ m_loadingThreads->insert(m_pathList[newBorn].first, newThread);
+ newThread->start();
+ m_threadLock->unlock();
+
+ m_currIndex = (m_currIndex - 1) % m_pathList.count();
+
+ }
+
+ QImage SlideShowLoader::getCurrent() {
+ checkIsIn(m_currIndex);
+
+ m_imageLock->lock();
+ QImage returned = (*m_loadedImages)[m_pathList[m_currIndex].first];
+ m_imageLock->unlock();
+
+
+ return returned;
+ }
+
+ QString SlideShowLoader::currFileName()
+ {
+ return KURL(m_pathList[m_currIndex].first).fileName();
+ }
+
+ KURL SlideShowLoader::currPath()
+ {
+ return m_pathList[m_currIndex].first;
+ }
+
+ void SlideShowLoader::checkIsIn(int index)
+ {
+ m_threadLock->lock();
+ if (m_loadingThreads->contains(m_pathList[index].first))
+ {
+ if ( (*m_loadingThreads)[m_pathList[index].first]->running() )
+ (*m_loadingThreads)[m_pathList[index].first]->wait();
+ m_threadLock->unlock();
+ }
+ else
+ {
+ LoadThread* newThread = new LoadThread(m_loadedImages, m_imageLock, KURL(m_pathList[index].first),
+ m_pathList[index].second, m_swidth, m_sheight);
+
+ m_loadingThreads->insert(m_pathList[index].first,newThread);
+ newThread->start();
+ (*m_loadingThreads)[m_pathList[index].first]->wait();
+ m_threadLock->unlock();
+ }
+ }
+
+} // NameSpace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/slideshowloader.h b/kipi-plugins/slideshow/slideshowloader.h
new file mode 100644
index 0000000..165fe60
--- /dev/null
+++ b/kipi-plugins/slideshow/slideshowloader.h
@@ -0,0 +1,109 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2007-11-11
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 SLIDESHOWLOADER_H
+#define SLIDESHOWLOADER_H
+
+// QT includes
+
+#include <qmap.h>
+#include <qmutex.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qthread.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+
+// KDE includes
+
+#include <kurl.h>
+
+typedef QPair<QString, int> FileAnglePair;
+typedef QValueList<FileAnglePair> FileList;
+
+namespace KIPISlideShowPlugin
+{
+
+ typedef QMap<KURL, QImage> LoadedImages;
+
+ class LoadThread : public QThread
+ {
+
+ public:
+
+ LoadThread(LoadedImages* loadedImages, QMutex* imageLock, const KURL path,
+ const int angle, int width, int height);
+ ~LoadThread();
+
+ protected:
+
+ void run();
+
+ private:
+
+ QMutex* m_imageLock;
+ LoadedImages* m_loadedImages;
+
+ KURL m_path;
+ QString m_filename;
+ int m_angle;
+ int m_swidth;
+ int m_sheight;
+ };
+
+ typedef QMap<KURL, LoadThread*> LoadingThreads;
+
+ class SlideShowLoader
+ {
+
+ public:
+
+ SlideShowLoader(FileList &pathList, uint cacheSize, int width, int height, int beginAtIndex=0);
+ ~SlideShowLoader();
+
+ void next();
+ void prev();
+
+ QImage getCurrent();
+ QString currFileName();
+ KURL currPath();
+
+ private:
+
+ void checkIsIn(int index);
+
+ LoadingThreads* m_loadingThreads;
+ LoadedImages* m_loadedImages;
+ FileList m_pathList;
+
+ QMutex* m_imageLock;
+ QMutex* m_threadLock;
+
+ uint m_cacheSize;
+ int m_currIndex;
+ int m_swidth;
+ int m_sheight;
+ };
+
+} // NameSpace KIPISlideShowPlugin
+
+#endif // SLIDESHOWLOADER_H
diff --git a/kipi-plugins/slideshow/toolbar.cpp b/kipi-plugins/slideshow/toolbar.cpp
new file mode 100644
index 0000000..35d0896
--- /dev/null
+++ b/kipi-plugins/slideshow/toolbar.cpp
@@ -0,0 +1,192 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-05
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Qt includes.
+
+#include <qtoolbutton.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+
+// KDE includes.
+
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+// Local includes.
+
+#include "toolbar.h"
+#include "toolbar.moc"
+
+namespace KIPISlideShowPlugin
+{
+
+ToolBar::ToolBar(QWidget* parent)
+ : QWidget(parent)
+{
+ QHBoxLayout* lay = new QHBoxLayout(this);
+ m_playBtn = new QToolButton(this);
+ m_prevBtn = new QToolButton(this);
+ m_nextBtn = new QToolButton(this);
+ m_stopBtn = new QToolButton(this);
+ m_playBtn->setToggleButton(true);
+
+ KIconLoader* loader = kapp->iconLoader();
+ m_playBtn->setIconSet(loader->loadIcon("player_pause", KIcon::NoGroup, 22));
+ m_prevBtn->setIconSet(loader->loadIcon("back", KIcon::NoGroup, 22));
+ m_nextBtn->setIconSet(loader->loadIcon("forward", KIcon::NoGroup, 22));
+ m_stopBtn->setIconSet(loader->loadIcon("stop", KIcon::NoGroup, 22));
+
+ lay->addWidget(m_playBtn);
+ lay->addWidget(m_prevBtn);
+ lay->addWidget(m_nextBtn);
+ lay->addWidget(m_stopBtn);
+
+ adjustSize();
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ m_canHide = true;
+
+ connect(m_playBtn, SIGNAL(toggled(bool)),
+ this, SLOT(slotPlayBtnToggled()));
+
+ connect(m_nextBtn, SIGNAL(clicked()),
+ this, SLOT(slotNexPrevClicked()));
+
+ connect(m_prevBtn, SIGNAL(clicked()),
+ this, SLOT(slotNexPrevClicked()));
+
+ connect(m_nextBtn, SIGNAL(clicked()),
+ this, SIGNAL(signalNext()));
+
+ connect(m_prevBtn, SIGNAL(clicked()),
+ this, SIGNAL(signalPrev()));
+
+ connect(m_stopBtn, SIGNAL(clicked()),
+ this, SIGNAL(signalClose()));
+}
+
+ToolBar::~ToolBar()
+{
+}
+
+bool ToolBar::canHide() const
+{
+ return m_canHide;
+}
+
+bool ToolBar::isPaused() const
+{
+ return m_playBtn->isOn();
+}
+
+void ToolBar::setPaused(bool val)
+{
+ if (val == isPaused())
+ return;
+
+ m_playBtn->setOn(val);
+ slotPlayBtnToggled();
+}
+
+void ToolBar::setEnabledPlay(bool val)
+{
+ m_playBtn->setEnabled(val);
+}
+
+void ToolBar::setEnabledNext(bool val)
+{
+ m_nextBtn->setEnabled(val);
+}
+
+void ToolBar::setEnabledPrev(bool val)
+{
+ m_prevBtn->setEnabled(val);
+}
+
+void ToolBar::slotPlayBtnToggled()
+{
+ if (m_playBtn->isOn())
+ {
+ m_canHide = false;
+ KIconLoader* loader = kapp->iconLoader();
+ m_playBtn->setIconSet(loader->loadIcon("player_play", KIcon::NoGroup, 22));
+ emit signalPause();
+ }
+ else
+ {
+ m_canHide = true;
+ KIconLoader* loader = kapp->iconLoader();
+ m_playBtn->setIconSet(loader->loadIcon("player_pause", KIcon::NoGroup, 22));
+ emit signalPlay();
+ }
+}
+
+void ToolBar::slotNexPrevClicked()
+{
+ if (!m_playBtn->isOn())
+ {
+ m_playBtn->setOn(true);
+ m_canHide = false;
+ KIconLoader* loader = kapp->iconLoader();
+ m_playBtn->setIconSet(loader->loadIcon("player_play", KIcon::NoGroup, 22));
+ emit signalPause();
+ }
+}
+
+void ToolBar::keyPressEvent(QKeyEvent *event)
+{
+ switch(event->key())
+ {
+ case(Qt::Key_Space):
+ {
+ if (m_playBtn->isEnabled())
+ m_playBtn->animateClick();
+ break;
+ }
+ case(Qt::Key_Prior):
+ {
+ if (m_prevBtn->isEnabled())
+ m_prevBtn->animateClick();
+ break;
+ }
+ case(Qt::Key_Next):
+ {
+ if (m_nextBtn->isEnabled())
+ m_nextBtn->animateClick();
+ break;
+ }
+ case(Qt::Key_Escape):
+ {
+ if (m_stopBtn->isEnabled())
+ m_stopBtn->animateClick();
+ break;
+ }
+ default:
+ break;
+ }
+
+ event->accept();
+}
+
+} // namespace KIPISlideShowPlugin
diff --git a/kipi-plugins/slideshow/toolbar.h b/kipi-plugins/slideshow/toolbar.h
new file mode 100644
index 0000000..776a249
--- /dev/null
+++ b/kipi-plugins/slideshow/toolbar.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-10-05
+ * Description : a kipi plugin to slide images.
+ *
+ * Copyright (C) 2006-2007 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 TOOLBAR_H
+#define TOOLBAR_H
+
+// Qt includes.
+
+#include <qwidget.h>
+
+class QToolButton;
+
+namespace KIPISlideShowPlugin
+{
+
+class ToolBar : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ ToolBar(QWidget* parent);
+ ~ToolBar();
+
+ bool canHide() const;
+ bool isPaused() const;
+ void setPaused(bool val);
+
+ void setEnabledPlay(bool val);
+ void setEnabledNext(bool val);
+ void setEnabledPrev(bool val);
+
+signals:
+
+ void signalNext();
+ void signalPrev();
+ void signalClose();
+ void signalPlay();
+ void signalPause();
+
+protected:
+
+ void keyPressEvent(QKeyEvent *event);
+
+private slots:
+
+ void slotPlayBtnToggled();
+ void slotNexPrevClicked();
+
+private:
+
+ QToolButton* m_playBtn;
+ QToolButton* m_stopBtn;
+ QToolButton* m_nextBtn;
+ QToolButton* m_prevBtn;
+ bool m_canHide;
+
+ friend class SlideShow;
+ friend class SlideShowGL;
+};
+
+} // namespace KIPISlideShowPlugin
+
+#endif /* TOOLBAR_H */
diff --git a/kipi-plugins/sync/Makefile.am b/kipi-plugins/sync/Makefile.am
new file mode 100644
index 0000000..7a6d257
--- /dev/null
+++ b/kipi-plugins/sync/Makefile.am
@@ -0,0 +1,33 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKEXIV2_CFLAGS) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_sync.la
+
+kipiplugin_sync_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP)
+
+kipiplugin_sync_la_SOURCES = plugin_sync.cpp \
+ libkipi2/interface.cpp \
+ libkipi2/collection.cpp libkipi2/item.cpp \
+ sink.cpp sinkfactory.cpp sinks.cpp \
+ sinklist.cpp sinklistbase.ui \
+ sinks/gallery/galleryform.cpp sinks/gallery/gallerysink.cpp \
+ sinks/gallery/gallerycollection.cpp sinks/gallery/galleryitem.cpp
+
+kipiplugin_sync_la_LIBADD = $(LIBKEXIV2_LIBS) \
+ -lkwalletclient $(LIB_KHTML) $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_sync_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+kde_services_DATA = kipiplugin_sync.desktop
+
+#kipiplugin_syncpicsdir = $(kde_datadir)/kipiplugin_sync/pics
+#kipiplugin_syncpics_DATA = gallery.png
+
+#kipiplugin_syncicondir = $(kde_datadir)/kipiplugin_sync/icons
+#kipiplugin_syncicon_ICON = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_sync.pot
+
diff --git a/kipi-plugins/sync/TODO b/kipi-plugins/sync/TODO
new file mode 100644
index 0000000..fcff8e0
--- /dev/null
+++ b/kipi-plugins/sync/TODO
@@ -0,0 +1,13 @@
+Somewhat immediate implementation needed:
+
+* Implement *.ui files for all dialogs that don't want to be kdialog[base] based
+* Return more sensible error strings
+* Implement logging to backtrace problems
+* Abstract the communications layer 100%
+* Rename to websync
+* Add support for other web backends
+
+For the lazy times:
+
+* Polish the html code used to render the thumbnails, better
+ fonts sizes and layout
diff --git a/kipi-plugins/sync/gallery.png b/kipi-plugins/sync/gallery.png
new file mode 100644
index 0000000..849eea9
--- /dev/null
+++ b/kipi-plugins/sync/gallery.png
Binary files differ
diff --git a/kipi-plugins/sync/galleryalbumdialog.ui b/kipi-plugins/sync/galleryalbumdialog.ui
new file mode 100644
index 0000000..2dfbf6a
--- /dev/null
+++ b/kipi-plugins/sync/galleryalbumdialog.ui
@@ -0,0 +1,197 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>KIPIGalleryExportPlugin::GalleryAlbumDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>GalleryAlbumDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>342</width>
+ <height>180</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>MyDialog</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>10</number>
+ </property>
+ <property name="spacing">
+ <number>5</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>header</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;h3&gt;Enter New Album Name&lt;/h3&gt;</string>
+ </property>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>hline1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>titleLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Title (optional):</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>nameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Name (optional):</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>captionLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Caption (optional):</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>titleEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>nameEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>captionEdit</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>hline2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>GalleryAlbumDialog</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>GalleryAlbumDialog</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kipi-plugins/sync/galleryconfig.cpp b/kipi-plugins/sync/galleryconfig.cpp
new file mode 100644
index 0000000..65fd7f4
--- /dev/null
+++ b/kipi-plugins/sync/galleryconfig.cpp
@@ -0,0 +1,161 @@
+/* ============================================================
+ * File : galleryconfig.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qlineedit.h>
+#include <qprogressdialog.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+#include <krun.h>
+#include <kdebug.h>
+#include <kconfig.h>
+
+// KIPI include files
+
+#include <libkipi/version.h>
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "galleryconfig.h"
+#include "galleries.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+GalleryEdit::GalleryEdit(QWidget* pParent,
+ Gallery* pGallery,
+ QString title)
+ : KDialogBase(pParent, 0, true, title, Ok|Cancel, Ok, false),
+ mpGallery(pGallery)
+{
+ setButtonGuiItem( Ok, KStdGuiItem::save() );
+
+ QFrame *page = new QFrame (this);
+ QHBoxLayout *tll = new QHBoxLayout(page);
+ page->setMinimumSize (500, 200);
+ setMainWidget(page);
+
+ QVBoxLayout* vbox = new QVBoxLayout();
+ vbox->setSpacing (KDialog::spacingHint());
+ tll->addItem(vbox);
+
+ mpHeaderLabel = new QLabel(page);
+ mpHeaderLabel->setSizePolicy(QSizePolicy(QSizePolicy::Minimum,
+ QSizePolicy::Fixed));
+ mpHeaderLabel->setText(title);
+ vbox->addWidget(mpHeaderLabel);
+
+ QFrame* hline = new QFrame(page, "hline");
+ hline->setFrameShape(QFrame::HLine);
+ hline->setFrameShadow(QFrame::Sunken);
+ hline->setFrameShape(QFrame::HLine);
+ vbox->addWidget(hline);
+
+ QGridLayout* centerLayout = new QGridLayout(0, 1, 1, 5, 5);
+
+ mpNameEdit = new QLineEdit( this );
+ centerLayout->addWidget(mpNameEdit, 0, 1);
+
+ mpUrlEdit = new QLineEdit( this );
+ centerLayout->addWidget(mpUrlEdit, 1, 1);
+
+ mpUsernameEdit = new QLineEdit( this );
+ centerLayout->addWidget(mpUsernameEdit, 2, 1);
+
+ mpPasswordEdit = new QLineEdit( this );
+ mpPasswordEdit->setEchoMode(QLineEdit::Password);
+ centerLayout->addWidget(mpPasswordEdit, 3, 1);
+
+ QLabel* name_label = new QLabel(this);
+ name_label->setText(i18n( "Name:" ));
+ centerLayout->addWidget(name_label, 0, 0);
+
+ QLabel* urlLabel = new QLabel(this);
+ urlLabel->setText(i18n( "URL:" ));
+ centerLayout->addWidget(urlLabel, 1, 0);
+
+ QLabel* nameLabel = new QLabel(this);
+ nameLabel->setText(i18n( "Username:" ));
+ centerLayout->addWidget(nameLabel, 2, 0);
+
+ QLabel* passwdLabel = new QLabel(this);
+ passwdLabel->setText(i18n( "Password:" ));
+ centerLayout->addWidget(passwdLabel, 3, 0);
+
+ //---------------------------------------------
+ mpGalleryVersion = new QCheckBox( i18n("Use &Gallery 2"), this);
+ mpGalleryVersion->setChecked( 2 == pGallery->version() );
+ centerLayout->addWidget( mpGalleryVersion, 4, 1 );
+ //---------------------------------------------
+
+ vbox->addLayout( centerLayout );
+
+ resize( QSize(300, 150).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+
+ mpNameEdit->setText(pGallery->name());
+ mpUrlEdit->setText(pGallery->url());
+ mpUsernameEdit->setText(pGallery->username());
+ mpPasswordEdit->setText(pGallery->password());
+}
+
+GalleryEdit::~GalleryEdit()
+{
+
+}
+
+void GalleryEdit::slotOk(void)
+{
+ if (mpNameEdit->isModified())
+ mpGallery->setName(mpNameEdit->text());
+ if (mpUrlEdit->isModified())
+ mpGallery->setUrl(mpUrlEdit->text());
+ if (mpUsernameEdit->isModified())
+ mpGallery->setUsername(mpUsernameEdit->text());
+ if (mpPasswordEdit->isModified())
+ mpGallery->setPassword(mpPasswordEdit->text());
+ if (mpGalleryVersion->isChecked())
+ mpGallery->setVersion(2);
+ else
+ mpGallery->setVersion(1);
+ accept();
+}
+
+}
+
+#include "galleryconfig.moc"
+
diff --git a/kipi-plugins/sync/galleryconfig.h b/kipi-plugins/sync/galleryconfig.h
new file mode 100644
index 0000000..0aaedcc
--- /dev/null
+++ b/kipi-plugins/sync/galleryconfig.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ * File : galleryconfig.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 GALLERYCONFIG_H
+#define GALLERYCONFIG_H
+
+#include <kdialogbase.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qintdict.h>
+
+namespace KIPIGalleryExportPlugin
+{
+
+class Gallery;
+
+class GalleryEdit : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ GalleryEdit(QWidget* pParent,
+ Gallery* pGallery,
+ QString title);
+ ~GalleryEdit();
+
+private:
+
+ Gallery* mpGallery;
+ QLabel* mpHeaderLabel;
+ QLineEdit* mpNameEdit;
+ QLineEdit* mpUrlEdit;
+ QLineEdit* mpUsernameEdit;
+ QLineEdit* mpPasswordEdit;
+ QCheckBox* mpGalleryVersion;
+
+private slots:
+ void slotOk(void);
+};
+
+}
+
+#endif /* GALLERYCONFIG_H */
diff --git a/kipi-plugins/sync/galleryitem.h b/kipi-plugins/sync/galleryitem.h
new file mode 100644
index 0000000..89661ec
--- /dev/null
+++ b/kipi-plugins/sync/galleryitem.h
@@ -0,0 +1,88 @@
+/* ============================================================
+ * File : galleryitem.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-04
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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 bythe 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 GALLERYITEM_H
+#define GALLERYITEM_H
+
+#include <qstring.h>
+
+namespace KIPIGalleryExportPlugin
+{
+
+class GPhoto
+{
+public:
+
+ GPhoto()
+ {
+ ref_num = -1;
+ }
+
+ int ref_num;
+ int album_num;
+ QString name;
+ QString caption;
+ QString thumbName;
+ QString albumURL;
+};
+
+class GAlbum
+{
+public:
+
+ GAlbum()
+ {
+ ref_num = -1;
+ parent_ref_num = -1;
+
+ add = false;
+ write = false;
+ del_item = false;
+ del_alb = false;
+ create_sub = false;
+ }
+
+ bool operator<(const GAlbum& rhs) const
+ {
+ if (parent_ref_num == rhs.parent_ref_num)
+ return ref_num < rhs.ref_num;
+
+ return parent_ref_num < rhs.parent_ref_num;
+ }
+
+ int ref_num;
+ int parent_ref_num;
+ QString name;
+ QString parentName;
+ QString title;
+ QString summary;
+ QString baseurl;
+
+ bool add;
+ bool write;
+ bool del_item;
+ bool del_alb;
+ bool create_sub;
+};
+
+}
+
+#endif /* GALLERYITEM_H */
diff --git a/kipi-plugins/sync/galleryviewitem.cpp b/kipi-plugins/sync/galleryviewitem.cpp
new file mode 100644
index 0000000..4a847ca
--- /dev/null
+++ b/kipi-plugins/sync/galleryviewitem.cpp
@@ -0,0 +1,93 @@
+/* ============================================================
+ * File : galleryviewitem.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-03
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <qpainter.h>
+#include <qpixmap.h>
+
+#include "galleryviewitem.h"
+#include "gallerytalker.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+void GAlbumViewItem::paintCell(QPainter * p, const QColorGroup & cg,
+ int column, int width, int )
+{
+ if (!p)
+ return;
+
+ QListView *lv = listView();
+ if (!lv)
+ return;
+ QFontMetrics fm(p->fontMetrics());
+
+ if (isSelected())
+ p->fillRect(0, 0, width, height(), cg.highlight());
+ else
+ p->fillRect(0, 0, width, height(), cg.base());
+
+ const QPixmap * icon = pixmap( column );
+
+ int iconWidth = 0;
+ if (icon)
+ {
+ iconWidth = icon->width() + lv->itemMargin();
+ int xo = lv->itemMargin();
+ int yo = (height() - icon->height())/2;
+ p->drawPixmap( xo, yo, *icon );
+ }
+
+ if (isSelected())
+ p->setPen( cg.highlightedText() );
+ else
+ p->setPen( cg.text() );
+
+ int r = lv->itemMargin() + iconWidth;
+ int h = lv->fontMetrics().height() + 2;
+
+ // Gallery2 does not return the "name" of the album, instead it
+ // returns a reference number than means nothing to the user.
+ // We display things slightly differently depending on version.
+ if (GalleryTalker::isGallery2())
+ {
+ p->drawText(r, h/2, width-r, h, Qt::AlignVCenter, album.title);
+ }
+ else
+ {
+ p->drawText(r, 0, width-r, h, Qt::AlignVCenter, album.title);
+
+ QFont fn(lv->font());
+ fn.setPointSize(fn.pointSize()-2);
+ fn.setItalic(true);
+ p->setFont(fn);
+ p->setPen(isSelected() ? cg.highlightedText() : Qt::gray);
+ p->drawText(r, h, width-r, h, Qt::AlignVCenter, album.name);
+ }
+}
+
+void GAlbumViewItem::setup()
+{
+ int h = listView()->fontMetrics().height();
+ int margin = 4;
+ setHeight( QMAX(2*h + margin, 32) );
+}
+
+}
diff --git a/kipi-plugins/sync/galleryviewitem.h b/kipi-plugins/sync/galleryviewitem.h
new file mode 100644
index 0000000..6c5077a
--- /dev/null
+++ b/kipi-plugins/sync/galleryviewitem.h
@@ -0,0 +1,55 @@
+/* ============================================================
+ * File : galleryviewitem.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-01
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GALLERYVIEWITEM_H
+#define GALLERYVIEWITEM_H
+
+#include <qlistview.h>
+
+#include "galleryitem.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+class GAlbumViewItem : public QListViewItem
+{
+public:
+
+ GAlbumViewItem(QListView* parent, const QString& name,
+ const GAlbum& _album)
+ : QListViewItem(parent, name), album(_album) {}
+ GAlbumViewItem(QListViewItem* parent, const QString& name,
+ const GAlbum& _album)
+ : QListViewItem(parent, name), album(_album) {}
+
+ GAlbum album;
+
+ void paintCell(QPainter * p, const QColorGroup & cg,
+ int column, int width, int );
+ void paintFocus (QPainter*, const QColorGroup&,
+ const QRect&) {}
+
+protected:
+
+ void setup();
+
+};
+
+}
+
+#endif /* GALLERYVIEWITEM_H */
diff --git a/kipi-plugins/sync/gallerywidget.cpp b/kipi-plugins/sync/gallerywidget.cpp
new file mode 100644
index 0000000..ed6e6fb
--- /dev/null
+++ b/kipi-plugins/sync/gallerywidget.cpp
@@ -0,0 +1,157 @@
+/* ============================================================
+ * File : gallerywidget.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-01
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <klocale.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qframe.h>
+#include <qheader.h>
+#include <qlistview.h>
+#include <qbuttongroup.h>
+#include <qgroupbox.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qsplitter.h>
+#include <qwhatsthis.h>
+
+#include "gallerywidget.h"
+
+namespace KIPIGalleryExportPlugin
+{
+
+GalleryWidget::GalleryWidget( QWidget* parent, const char* name, WFlags fl )
+ : QWidget( parent, name, fl )
+{
+ if ( !name )
+ setName( "GalleryWidget" );
+ QVBoxLayout* galleryWidgetLayout
+ = new QVBoxLayout( this, 5, 5, "GalleryWidgetLayout");
+
+ // ------------------------------------------------------------------------
+
+ QLabel* headerLabel;
+ QFrame* headerLine;
+
+ headerLabel = new QLabel( this, "headerLabel" );
+ galleryWidgetLayout->addWidget( headerLabel, 0 );
+ headerLine = new QFrame( this, "headerLine" );
+ headerLine->setFrameShape( QFrame::HLine );
+ headerLine->setFrameShadow( QFrame::Sunken );
+ galleryWidgetLayout->addWidget( headerLine, 0 );
+
+ // ------------------------------------------------------------------------
+
+ QSplitter* splitter = new QSplitter(this);
+ galleryWidgetLayout->addWidget( splitter, 5 );
+
+ m_albumView = new QListView( splitter, "m_albumView" );
+ m_albumView->addColumn( i18n( "Albums" ) );
+ m_albumView->setResizeMode( QListView::AllColumns );
+
+ // ------------------------------------------------------------------------
+
+ m_photoView = new KHTMLPart( splitter, "m_photoView" );
+
+ // ------------------------------------------------------------------------
+
+ QVBoxLayout* rightButtonGroupLayout;
+ QSpacerItem* spacer;
+ QButtonGroup* rightButtonGroup;
+
+ rightButtonGroup = new QButtonGroup( splitter, "rightButtonGroup" );
+ rightButtonGroupLayout = new QVBoxLayout( rightButtonGroup );
+ rightButtonGroupLayout->setSpacing( 5 );
+ rightButtonGroupLayout->setMargin( 5 );
+
+ m_newAlbumBtn = new QPushButton( rightButtonGroup, "m_newAlbumBtn" );
+ m_newAlbumBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ rightButtonGroupLayout->addWidget( m_newAlbumBtn, 0, Qt::AlignHCenter );
+
+ m_addPhotoBtn = new QPushButton( rightButtonGroup, "m_addPhotoBtn" );
+ m_addPhotoBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ rightButtonGroupLayout->addWidget( m_addPhotoBtn, 0, Qt::AlignHCenter );
+
+ // ------------------------------------------------------------------------
+
+ QGroupBox* optionsBox = new QGroupBox(i18n("Override Default Options"),
+ rightButtonGroup);
+ optionsBox->setColumnLayout(0, Qt::Vertical);
+ optionsBox->layout()->setSpacing(5);
+ optionsBox->layout()->setMargin(5);
+ QGridLayout* optionsBoxLayout = new QGridLayout(optionsBox->layout());
+
+ // ------------------------------------------------------------------------
+
+ m_resizeCheckBox = new QCheckBox(optionsBox);
+ m_resizeCheckBox->setText(i18n("Resize photos before uploading"));
+ optionsBoxLayout->addMultiCellWidget(m_resizeCheckBox, 0, 0, 0, 1);
+
+ m_dimensionSpinBox = new QSpinBox(0, 5000, 10, optionsBox);
+ m_dimensionSpinBox->setValue(600);
+ m_dimensionSpinBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ optionsBoxLayout->addWidget(m_dimensionSpinBox, 1, 1);
+
+ QLabel* resizeLabel = new QLabel(i18n("Maximum dimension:"), optionsBox);
+ optionsBoxLayout->addWidget(resizeLabel, 1, 0);
+
+ m_resizeCheckBox->setChecked(false);
+ m_dimensionSpinBox->setEnabled(false);
+ connect(m_resizeCheckBox, SIGNAL(clicked()), SLOT(slotResizeChecked()));
+
+ // ------------------------------------------------------------------------
+
+ rightButtonGroupLayout->addWidget(optionsBox);
+
+ // ------------------------------------------------------------------------
+
+ spacer = new QSpacerItem( 20, 100, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ rightButtonGroupLayout->addItem( spacer );
+
+ // ------------------------------------------------------------------------
+
+ headerLabel->setText( i18n( "<h2>Gallery Export</h2>" ) );
+ m_albumView->header()->setLabel( 0, i18n( "Albums" ) );
+ m_newAlbumBtn->setText( i18n( "&New Album" ) );
+ m_addPhotoBtn->setText( i18n( "&Add Photos" ) );
+
+ // ------------------------------------------------------------------------
+
+ resize( QSize(600, 400).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+}
+
+GalleryWidget::~GalleryWidget()
+{
+}
+
+void GalleryWidget::slotResizeChecked()
+{
+ m_dimensionSpinBox->setEnabled(m_resizeCheckBox->isChecked());
+}
+
+}
+
+#include "gallerywidget.moc"
diff --git a/kipi-plugins/sync/gallerywidget.h b/kipi-plugins/sync/gallerywidget.h
new file mode 100644
index 0000000..9389ce1
--- /dev/null
+++ b/kipi-plugins/sync/gallerywidget.h
@@ -0,0 +1,60 @@
+/* ============================================================
+ * File : gallerywidget.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-01
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GALLERYWIDGET_H
+#define GALLERYWIDGET_H
+
+#include <qwidget.h>
+
+class QListView;
+class QPushButton;
+class QSpinBox;
+class QCheckBox;
+class KHTMLPart;
+
+namespace KIPIGalleryExportPlugin
+{
+
+class GalleryWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ GalleryWidget( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+ ~GalleryWidget();
+
+private slots:
+
+ void slotResizeChecked();
+
+private:
+
+ QListView* m_albumView;
+ KHTMLPart* m_photoView;
+ QPushButton* m_newAlbumBtn;
+ QPushButton* m_addPhotoBtn;
+ QCheckBox* m_resizeCheckBox;
+ QSpinBox* m_dimensionSpinBox;
+
+ friend class GalleryWindow;
+};
+
+}
+
+#endif // GALLERYWIDGET_H
diff --git a/kipi-plugins/sync/gallerywindow.cpp b/kipi-plugins/sync/gallerywindow.cpp
new file mode 100644
index 0000000..0b5960f
--- /dev/null
+++ b/kipi-plugins/sync/gallerywindow.cpp
@@ -0,0 +1,637 @@
+/* ============================================================
+ * File : gallerywindow.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-30
+ * Description :
+ *
+ * Copyright 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Include files for Qt
+
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qlineedit.h>
+#include <qprogressdialog.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+
+// Include files for KDE
+
+#include <kaboutdata.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <khtml_part.h>
+#include <khtmlview.h>
+#include <krun.h>
+#include <kdebug.h>
+#include <kconfig.h>
+
+// KIPI include files
+
+#include <libkipi/interface.h>
+#include <libkipi/imagedialog.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "galleries.h"
+#include "gallerylist.h"
+#include "gallerytalker.h"
+#include "galleryitem.h"
+#include "galleryviewitem.h"
+#include "gallerywidget.h"
+#include "galleryalbumdialog.h"
+#include "gallerywindow.h"
+#include "gallerywindow.moc"
+
+namespace KIPIGalleryExportPlugin
+{
+
+GalleryWindow::GalleryWindow(KIPI::Interface* interface, QWidget *parent, Galleries* pGalleries)
+ : KDialogBase(parent, 0, true, i18n("Gallery Export"), Help|Close, Close, false),
+ m_interface(interface),
+ mpGalleries(pGalleries)
+{
+ m_uploadCount = 0;
+ m_uploadTotal = 0;
+
+ // About data and help button.
+
+ m_about = new KIPIPlugins::KPAboutData(I18N_NOOP("Gallery Export"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin to export image collection to remote Gallery server."),
+ "(c) 2003-2005, Renchi Raju");
+
+ m_about->addAuthor("Renchi Raju", I18N_NOOP("Author"),
+ "renchi at pooh dot tam dot uiuc dot edu");
+
+ m_about->addAuthor("Colin Guthrie", I18N_NOOP("Maintainer"),
+ "kde at colin dot guthr dot ie");
+
+ m_helpButton = actionButton( Help );
+ KHelpMenu* helpMenu = new KHelpMenu(this, m_about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ m_helpButton->setPopup( helpMenu->menu() );
+
+ GalleryWidget* widget = new GalleryWidget(this);
+ setMainWidget(widget);
+ widget->setMinimumSize(600, 400);
+
+ m_albumView = widget->m_albumView;
+ m_photoView = widget->m_photoView;
+ m_newAlbumBtn = widget->m_newAlbumBtn;
+ m_addPhotoBtn = widget->m_addPhotoBtn;
+ m_resizeCheckBox = widget->m_resizeCheckBox;
+ m_dimensionSpinBox = widget->m_dimensionSpinBox;
+
+ m_albumView->setRootIsDecorated( true );
+
+ m_newAlbumBtn->setEnabled( false );
+ m_addPhotoBtn->setEnabled( false );
+
+ m_progressDlg = new QProgressDialog( this, 0, true );
+ m_progressDlg->setAutoReset( true );
+ m_progressDlg->setAutoClose( true );
+
+ connect(m_progressDlg, SIGNAL(canceled()), SLOT(slotAddPhotoCancel()));
+
+ connect(m_albumView, SIGNAL(selectionChanged()), SLOT(slotAlbumSelected()));
+ connect(m_photoView->browserExtension(),
+ SIGNAL(openURLRequest(const KURL&,
+ const KParts::URLArgs&)),
+ SLOT(slotOpenPhoto(const KURL&)));
+
+ connect(m_newAlbumBtn, SIGNAL(clicked()), SLOT(slotNewAlbum()));
+ connect(m_addPhotoBtn, SIGNAL(clicked()), SLOT( slotAddPhotos()));
+
+ // read config
+ KConfig config("kipirc");
+ config.setGroup("GallerySync Settings");
+
+ m_talker = new GalleryTalker( this );
+ connect( m_talker, SIGNAL( signalError( const QString& ) ),
+ SLOT( slotError( const QString& ) ) );
+ connect( m_talker, SIGNAL( signalBusy( bool ) ),
+ SLOT( slotBusy( bool ) ) );
+ connect( m_talker, SIGNAL( signalLoginFailed( const QString& ) ),
+ SLOT( slotLoginFailed( const QString& ) ) );
+ connect( m_talker, SIGNAL( signalAlbums( const QValueList<GAlbum>& ) ),
+ SLOT( slotAlbums( const QValueList<GAlbum>& ) ) );
+ connect( m_talker, SIGNAL( signalPhotos( const QValueList<GPhoto>& ) ),
+ SLOT( slotPhotos( const QValueList<GPhoto>& ) ) );
+ connect( m_talker, SIGNAL( signalAddPhotoSucceeded() ),
+ SLOT( slotAddPhotoSucceeded() ) );
+ connect( m_talker, SIGNAL( signalAddPhotoFailed( const QString& ) ),
+ SLOT( slotAddPhotoFailed( const QString& ) ) );
+
+ if (config.readBoolEntry("Resize", false))
+ {
+ m_resizeCheckBox->setChecked(true);
+ m_dimensionSpinBox->setEnabled(true);
+ }
+ else
+ {
+ m_resizeCheckBox->setChecked(false);
+ m_dimensionSpinBox->setEnabled(false);
+ }
+ m_dimensionSpinBox->setValue(config.readNumEntry("Maximum Width", 1600));
+
+ QTimer::singleShot( 0, this, SLOT( slotDoLogin() ) );
+}
+
+GalleryWindow::~GalleryWindow()
+{
+ // write config
+ KConfig config("kipirc");
+ config.setGroup("GallerySync Settings");
+ config.writeEntry("Resize", m_resizeCheckBox->isChecked());
+ config.writeEntry("Maximum Width", m_dimensionSpinBox->value());
+
+ delete m_progressDlg;
+ delete m_talker;
+ delete m_about;
+}
+
+void GalleryWindow::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("galleryexport", "kipi-plugins");
+}
+
+void GalleryWindow::slotDoLogin()
+{
+ GalleryList dlg(this, mpGalleries);
+
+ if (QDialog::Accepted != dlg.exec())
+ {
+ close();
+ return;
+ }
+
+ Gallery* p_gallery = dlg.GetGallery();
+ if (!p_gallery)
+ {
+ close();
+ return;
+ }
+
+ GalleryTalker::setGallery2((2 == p_gallery->version()));
+
+ KURL url(p_gallery->url());
+ if (url.protocol().isEmpty())
+ {
+ url.setProtocol("http");
+ url.setHost(p_gallery->url());
+ }
+ if (!url.url().endsWith(".php"))
+ {
+ if (GalleryTalker::isGallery2())
+ url.addPath("main.php");
+ else
+ url.addPath("gallery_remote2.php");
+ }
+ // If we've done something clever, save it back to the gallery.
+ if (p_gallery->url() != url.url())
+ {
+ p_gallery->setUrl(url.url());
+ mpGalleries->Save();
+ }
+
+ m_talker->login(url.url(), p_gallery->username(), p_gallery->password());
+}
+
+void GalleryWindow::slotLoginFailed( const QString& msg )
+{
+ if ( KMessageBox::warningYesNo( this,
+ i18n( "Failed to login into remote gallery. " )
+ + msg
+ + i18n("\nDo you want to try again?" ) )
+ != KMessageBox::Yes )
+ {
+ close();
+ return;
+ }
+
+ slotDoLogin();
+}
+
+void GalleryWindow::slotBusy( bool val )
+{
+ if ( val )
+ {
+ setCursor(QCursor::WaitCursor);
+ m_newAlbumBtn->setEnabled( false );
+ m_addPhotoBtn->setEnabled( false );
+ }
+ else
+ {
+ setCursor(QCursor::ArrowCursor);
+ bool loggedIn = m_talker->loggedIn();
+ m_newAlbumBtn->setEnabled( loggedIn );
+ m_addPhotoBtn->setEnabled( loggedIn && m_albumView->selectedItem() );
+ }
+}
+
+void GalleryWindow::slotError( const QString& msg )
+{
+ KMessageBox::error( this, msg );
+}
+
+void GalleryWindow::slotAlbums( const QValueList<GAlbum>& albumList )
+{
+ m_albumDict.clear();
+ m_albumView->clear();
+ m_photoView->begin();
+ m_photoView->write( "<html></html>" );
+ m_photoView->end();
+
+ KIconLoader* iconLoader = KApplication::kApplication()->iconLoader();
+ QPixmap pix = iconLoader->loadIcon( "folder", KIcon::NoGroup, 32 );
+
+ typedef QValueList<GAlbum> GAlbumList;
+ GAlbumList::const_iterator iter;
+ for ( iter = albumList.begin(); iter != albumList.end(); ++iter )
+ {
+ const GAlbum& album = *iter;
+
+ if ( album.parent_ref_num == 0 )
+ {
+ GAlbumViewItem* item = new GAlbumViewItem( m_albumView, album.title,
+ album );
+ item->setPixmap( 0, pix );
+ m_albumDict.insert( album.ref_num, item );
+ }
+ else
+ {
+ QListViewItem* parent = m_albumDict.find( album.parent_ref_num );
+ if ( parent )
+ {
+ GAlbumViewItem* item = new GAlbumViewItem( parent, album.title,
+ album);
+ item->setPixmap( 0, pix );
+ m_albumDict.insert( album.ref_num, item );
+ }
+ else
+ {
+ kdWarning() << "Failed to find parent for album "
+ << album.name
+ << " with id " << album.ref_num << "\n";
+ }
+ }
+ }
+
+
+ // find and select the last selected album
+ int lastSelectedID = 0;
+ for ( iter = albumList.begin(); iter != albumList.end(); ++iter )
+ {
+ if ((*iter).name == m_lastSelectedAlbum)
+ {
+ lastSelectedID = (*iter).ref_num;
+ break;
+ }
+ }
+
+ if (lastSelectedID > 0)
+ {
+ GAlbumViewItem* lastSelectedItem = m_albumDict.find( lastSelectedID );
+ if (lastSelectedItem)
+ {
+ m_albumView->setSelected( lastSelectedItem, true );
+ m_albumView->ensureItemVisible( lastSelectedItem );
+ }
+ }
+}
+
+void GalleryWindow::slotPhotos( const QValueList<GPhoto>& photoList)
+{
+ int pxSize = fontMetrics().height() - 2;
+ QString styleSheet =
+ QString( "body { margin: 8px; font-size: %1px; "
+ " color: %2; background-color: %3;}" )
+ .arg( pxSize )
+ .arg( colorGroup().text().name() )
+ .arg( colorGroup().base().name() );
+
+ styleSheet += QString( "a { font-size: %1px; color: %2; "
+ "text-decoration: none;}" )
+ .arg( pxSize )
+ .arg( colorGroup().text().name() );
+ styleSheet += QString( "i { font-size: %1px; color: %2; "
+ "text-decoration: none;}" )
+ .arg( pxSize-2 )
+ .arg( QColor("steelblue").name() );
+
+ m_photoView->begin();
+ m_photoView->setUserStyleSheet( styleSheet );
+ m_photoView->write( "<html>" );
+
+
+ m_photoView->write("<table class='box-body' width='100%' "
+ "border='0' cellspacing='1' cellpadding='1'>" );
+
+
+ typedef QValueList<GPhoto> GPhotoList;
+ GPhotoList::const_iterator iter;
+ for ( iter = photoList.begin(); iter != photoList.end(); ++iter )
+ {
+ const GPhoto& photo = *iter;
+ KURL imageurl(photo.albumURL + photo.name);
+ KURL thumburl(photo.albumURL + photo.thumbName);
+
+ m_photoView->write( "<tr><td class='photo'>"
+ + QString("<a href='%1'>")
+ .arg(imageurl.url())
+ + QString("<img border=1 src=\"%1\"><br>")
+ .arg(thumburl.url())
+ + photo.name
+ + ( photo.caption.isEmpty() ? QString() :
+ QString("<br><i>%1</i>")
+ .arg(photo.caption) )
+ + "</a></td></tr>" );
+ }
+
+ m_photoView->write("</table>");
+
+ m_photoView->write( "</html>" );
+ m_photoView->end( );
+}
+
+void GalleryWindow::slotAlbumSelected()
+{
+ QListViewItem* item = m_albumView->selectedItem();
+ if ( !item )
+ {
+ m_addPhotoBtn->setEnabled( false );
+ }
+ else
+ {
+ if ( m_talker->loggedIn() )
+ {
+ m_addPhotoBtn->setEnabled( true );
+
+ m_photoView->begin();
+ m_photoView->write( "<html></html>" );
+ m_photoView->end();
+
+ GAlbumViewItem* viewItem = static_cast<GAlbumViewItem*>(item);
+ m_talker->listPhotos(viewItem->album.name);
+ m_lastSelectedAlbum = viewItem->album.name;
+ }
+ }
+}
+
+void GalleryWindow::slotOpenPhoto( const KURL& url )
+{
+ new KRun(url);
+}
+
+void GalleryWindow::slotNewAlbum()
+{
+ GalleryAlbumDialog dlg;
+ dlg.titleEdit->setFocus( );
+ if ( dlg.exec() != QDialog::Accepted )
+ {
+ return;
+ }
+
+ QString name = dlg.nameEdit->text();
+ QString title = dlg.titleEdit->text();
+ QString caption = dlg.captionEdit->text();
+
+ // check for prohibited chars in the album name
+ // \ / * ? " ' & < > | . + # ( ) or spaces
+ // Todo: Change this to a QRegExp check.
+ QChar ch;
+ bool clean = true;
+ for (uint i=0; i<name.length(); i++)
+ {
+ ch = name[i];
+ if (ch == '\\')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '/')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '*')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '?')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '"')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '\'')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '&')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '<')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '>')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '|')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '.')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '+')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '#')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == '(')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == ')')
+ {
+ clean = false;
+ break;
+ }
+ else if (ch == ' ')
+ {
+ clean = false;
+ break;
+ }
+ }
+
+ if (!clean)
+ {
+ KMessageBox::error( this, i18n("Sorry, these characters are not allowed in album name: %1")
+ .arg("\\ / * ? \" \' & < > | . + # ( ) or spaces") );
+ return;
+ }
+
+ QString parentAlbumName;
+
+ QListViewItem* item = m_albumView->selectedItem();
+ if (item)
+ {
+ GAlbumViewItem* viewItem = static_cast<GAlbumViewItem*>(item);
+ parentAlbumName = viewItem->album.name;
+ }
+ else
+ {
+ parentAlbumName = "0";
+ }
+
+ m_talker->createAlbum(parentAlbumName, name, title, caption);
+}
+
+void GalleryWindow::slotAddPhotos()
+{
+ QListViewItem* item = m_albumView->selectedItem();
+ if (!item)
+ return;
+
+ KURL::List urls = KIPI::ImageDialog::getImageURLs( this, m_interface );
+ if (urls.isEmpty())
+ return;
+
+ typedef QPair<QString,QString> Pair;
+
+ m_uploadQueue.clear();
+ for (KURL::List::iterator it = urls.begin(); it != urls.end(); ++it)
+ {
+ KIPI::ImageInfo info = m_interface->info( *it );
+ m_uploadQueue.append( Pair( (*it).path(), info.description() ) );
+ }
+
+ m_uploadTotal = m_uploadQueue.count();
+ m_uploadCount = 0;
+ m_progressDlg->reset();
+ slotAddPhotoNext();
+}
+
+void GalleryWindow::slotAddPhotoNext()
+{
+ if ( m_uploadQueue.isEmpty() )
+ {
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+ slotAlbumSelected();
+ return;
+ }
+
+ typedef QPair<QString,QString> Pair;
+ Pair pathComments = m_uploadQueue.first();
+ m_uploadQueue.pop_front();
+
+ bool res = m_talker->addPhoto( m_lastSelectedAlbum, pathComments.first,
+ pathComments.second,
+ m_resizeCheckBox->isChecked(),
+ m_dimensionSpinBox->value() );
+ if (!res)
+ {
+ slotAddPhotoFailed( "" );
+ return;
+ }
+
+ m_progressDlg->setLabelText( i18n("Uploading file %1 ")
+ .arg( KURL(pathComments.first).filename() ) );
+
+ if (m_progressDlg->isHidden())
+ m_progressDlg->show();
+}
+
+void GalleryWindow::slotAddPhotoSucceeded()
+{
+ m_uploadCount++;
+ m_progressDlg->setProgress( m_uploadCount, m_uploadTotal );
+ slotAddPhotoNext();
+}
+
+void GalleryWindow::slotAddPhotoFailed( const QString& msg )
+{
+ if ( KMessageBox::warningContinueCancel( this,
+ i18n( "Failed to upload photo into "
+ "remote gallery. " )
+ + msg
+ + i18n("\nDo you want to continue?" ) )
+ != KMessageBox::Continue )
+ {
+ m_uploadQueue.clear();
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+
+ // refresh the thumbnails
+ slotAlbumSelected();
+ }
+ else
+ {
+ m_uploadTotal--;
+ m_progressDlg->setProgress( m_uploadCount, m_uploadTotal );
+ slotAddPhotoNext();
+ }
+}
+
+void GalleryWindow::slotAddPhotoCancel()
+{
+ m_uploadQueue.clear();
+ m_progressDlg->reset();
+ m_progressDlg->hide();
+
+ m_talker->cancel();
+
+ // refresh the thumbnails
+ slotAlbumSelected();
+}
+
+}
+
diff --git a/kipi-plugins/sync/gallerywindow.h b/kipi-plugins/sync/gallerywindow.h
new file mode 100644
index 0000000..7e4aa0e
--- /dev/null
+++ b/kipi-plugins/sync/gallerywindow.h
@@ -0,0 +1,106 @@
+/* ============================================================
+ * File : gallerywindow.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-30
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GALLERYWINDOW_H
+#define GALLERYWINDOW_H
+
+#include <kdialogbase.h>
+#include <qvaluelist.h>
+#include <qpair.h>
+#include <qintdict.h>
+
+class QListView;
+class QPushButton;
+class QSpinBox;
+class QCheckBox;
+class QProgressDialog;
+class KHTMLPart;
+class KURL;
+
+namespace KIPI
+{
+class Interface;
+}
+namespace KIPIPlugins
+{
+class KPAboutData;
+}
+
+namespace KIPIGalleryExportPlugin
+{
+
+class Galleries;
+class GalleryTalker;
+class GAlbum;
+class GPhoto;
+class GAlbumViewItem;
+
+class GalleryWindow : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ GalleryWindow(KIPI::Interface *interface, QWidget *parent, Galleries* pGalleries);
+ ~GalleryWindow();
+
+private:
+
+ QListView *m_albumView;
+ KHTMLPart *m_photoView;
+ QPushButton *m_newAlbumBtn;
+ QPushButton *m_addPhotoBtn;
+ QPushButton *m_helpButton;
+ QCheckBox *m_resizeCheckBox;
+ QSpinBox *m_dimensionSpinBox;
+ GalleryTalker *m_talker;
+ QIntDict<GAlbumViewItem> m_albumDict;
+ QString m_lastSelectedAlbum;
+ KIPI::Interface *m_interface;
+ KIPIPlugins::KPAboutData *m_about;
+
+ QProgressDialog *m_progressDlg;
+ unsigned int m_uploadCount;
+ unsigned int m_uploadTotal;
+ QValueList< QPair<QString,QString> > m_uploadQueue;
+
+ Galleries* mpGalleries;
+ Gallery* mpGallery;
+
+private slots:
+
+ void slotDoLogin();
+ void slotLoginFailed( const QString& msg );
+ void slotBusy( bool val );
+ void slotError( const QString& msg );
+ void slotAlbums( const QValueList<GAlbum>& albumList );
+ void slotPhotos( const QValueList<GPhoto>& photoList );
+ void slotAlbumSelected();
+ void slotOpenPhoto( const KURL& url );
+ void slotNewAlbum();
+ void slotAddPhotos();
+ void slotAddPhotoNext();
+ void slotAddPhotoSucceeded();
+ void slotAddPhotoFailed( const QString& msg );
+ void slotAddPhotoCancel();
+ void slotHelp();
+};
+
+}
+
+#endif /* GALLERYWINDOW_H */
diff --git a/kipi-plugins/sync/kipiplugin_sync.desktop b/kipi-plugins/sync/kipiplugin_sync.desktop
new file mode 100644
index 0000000..f248c05
--- /dev/null
+++ b/kipi-plugins/sync/kipiplugin_sync.desktop
@@ -0,0 +1,41 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Sync
+Name[ca]=Sincronització
+Name[de]=Abgleich
+Name[el]=Συγχρονισμός
+Name[et]=Sünkroniseerimine
+Name[fi]=Synkronointi
+Name[nds]=Synkroniseren
+Name[pl]=Synchronizacja
+Name[pt]=Sincronização
+Name[sr]=Синхро
+Name[sr@Latn]=Sinhro
+Name[sv]=Synkronisering
+Name[xx]=xxSyncxx
+Name[zh_CN]=同步
+Comment=KIPI Synchronization Plugin
+Comment[ca]=Connector del KIPI de sincronització
+Comment[da]=KIPI Synkroniserings-plugin
+Comment[de]=Ein KIPI-Modul zum Abgleichen
+Comment[el]=Πρόσθετο συγχρονισμού του KIPI
+Comment[es]=Complemento de sincronización de KIPI
+Comment[et]=KIPI sünkroniseerimisplugin
+Comment[fr]=Module externe KIPI pour synchroniser les images
+Comment[it]=Plugin di sincronizzazione di KIPI
+Comment[ja]=Kipi 同期プラグイン
+Comment[nds]=KIPI-Moduul för't Synkroniseren
+Comment[nl]=KIPI-plugin voor het synchroniseren van afbeeldingen
+Comment[pa]=KIPI ਸਮਕਾਲੀ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Synchronizacja
+Comment[pt]='Plugin' de Sincronização do KIPI
+Comment[pt_BR]=Plugin de Sincronização do KIPI
+Comment[sr]=KIPI прикључак за синхронизацију
+Comment[sr@Latn]=KIPI priključak za sinhronizaciju
+Comment[sv]=KIPI-insticksprogram: Synkronisering
+Comment[xx]=xxKIPI Synchronization Pluginxx
+Comment[zh_CN]=KIPI 同步插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_sync
+author=Colin Guthrie, kde@colin.guthr.ie
diff --git a/kipi-plugins/sync/libkipi2/collection.cpp b/kipi-plugins/sync/libkipi2/collection.cpp
new file mode 100644
index 0000000..9709810
--- /dev/null
+++ b/kipi-plugins/sync/libkipi2/collection.cpp
@@ -0,0 +1,78 @@
+/* ============================================================
+ * File : collection.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-26
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include "collection.h"
+
+namespace KIPI2
+{
+
+template <class T> void DestroyCollectionList(CollectionList& collections)
+{
+ for (CollectionList::iterator it = collections.begin();
+ it != collections.end();
+ ++it)
+ {
+ delete dynamic_cast<T*>(*it);
+ }
+ collections.empty();
+}
+
+template <class T> void DestroyItemList(ItemList& items)
+{
+ for (ItemList::iterator it = items.begin();
+ it != items.end();
+ ++it)
+ {
+ delete dynamic_cast<T*>(*it);
+ }
+ items.empty();
+}
+
+
+Collection::Collection(Collection* pParent, unsigned int features)
+ : mpParent(pParent),
+ mFeatures(features),
+ mpSubCollections(NULL),
+ mpItems(NULL)
+{
+}
+
+bool Collection::Supports(enum Features feature)
+{
+ return (mFeatures & feature);
+}
+
+const Collection* Collection::getParentCollection()
+{
+ return mpParent;
+}
+
+// Default, basic implementation of getSubCollections
+const CollectionList* Collection::getSubCollections()
+{
+ return mpSubCollections;
+}
+
+
+// Default, basic implementation of getItems
+const ItemList* Collection::getItems()
+{
+ return mpItems;
+}
+
+}
diff --git a/kipi-plugins/sync/libkipi2/collection.h b/kipi-plugins/sync/libkipi2/collection.h
new file mode 100644
index 0000000..f7953aa
--- /dev/null
+++ b/kipi-plugins/sync/libkipi2/collection.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ * File : collection.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-26
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 KIPI2_COLLECTION_H
+#define KIPI2_COLLECTION_H
+
+#include <qvaluelist.h>
+
+namespace KIPI2
+{
+ enum Features
+ {
+ None = 0,
+ Comments = 1,
+ SubCollections = 2,
+ ItemComments = 4,
+ NewSubCollections = 8,
+ NewItems = 16
+ };
+
+ // Forward declarations
+ class Collection;
+ class Item;
+
+ // Some list definitions
+ typedef QValueList<Collection*> CollectionList;
+ typedef QValueList<Item*> ItemList;
+
+ // And some templated functions for cleaning up in Collection derived destructors
+ template <class T> void DestroyCollectionList(CollectionList& collections);
+ template <class T> void DestroyItemList(ItemList& items);
+
+ // Main (abstract) Collection definition
+ class Collection
+ {
+ public:
+ // ctor/dtor
+ Collection(Collection* pParent = NULL, unsigned int mFeatures = 0);
+
+ // State whether a given Feature is supported.
+ bool Supports(enum Features feature);
+
+ const Collection* getParentCollection();
+
+ // Get the list of Sub-Collections (assuming this is supported)
+ virtual const CollectionList* getSubCollections();
+ // Create a new sub collection
+ virtual const Collection* createSubCollection() = 0;
+
+ // Get the list of items.
+ virtual const ItemList* getItems();
+ // Add a new item
+ virtual const Item* addItem() = 0;
+
+ private:
+ // Store for parent
+ Collection* mpParent;
+
+ // Store the features that this collection supports
+ unsigned int mFeatures;
+
+ // Store for the Sub-Collections
+ CollectionList* mpSubCollections;
+
+ // Store for the Items
+ ItemList* mpItems;
+ };
+}
+#endif /* KIPI2_COLLECTION_H */
diff --git a/kipi-plugins/sync/libkipi2/interface.cpp b/kipi-plugins/sync/libkipi2/interface.cpp
new file mode 100644
index 0000000..1aa4e66
--- /dev/null
+++ b/kipi-plugins/sync/libkipi2/interface.cpp
@@ -0,0 +1,3 @@
+#include "interface.h"
+
+#include "interface.moc"
diff --git a/kipi-plugins/sync/libkipi2/interface.h b/kipi-plugins/sync/libkipi2/interface.h
new file mode 100644
index 0000000..e4d0e31
--- /dev/null
+++ b/kipi-plugins/sync/libkipi2/interface.h
@@ -0,0 +1,35 @@
+/* ============================================================
+ * File : interface.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-26
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 KIPI2_INTERFACE_H
+#define KIPI2_INTERFACE_H
+
+#include <qobject.h>
+#include "collection.h"
+
+namespace KIPI2
+{
+class Interface : public QObject
+{
+ Q_OBJECT
+
+public:
+ virtual const CollectionList* getCollections() = 0;
+};
+}
+#endif /* KIPI2_INTERFACE_H */
diff --git a/kipi-plugins/sync/libkipi2/item.cpp b/kipi-plugins/sync/libkipi2/item.cpp
new file mode 100644
index 0000000..3a3de98
--- /dev/null
+++ b/kipi-plugins/sync/libkipi2/item.cpp
@@ -0,0 +1,25 @@
+/* ============================================================
+ * File : item.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-26
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include "item.h"
+
+namespace KIPI2
+{
+
+
+}
diff --git a/kipi-plugins/sync/libkipi2/item.h b/kipi-plugins/sync/libkipi2/item.h
new file mode 100644
index 0000000..6b42830
--- /dev/null
+++ b/kipi-plugins/sync/libkipi2/item.h
@@ -0,0 +1,34 @@
+/* ============================================================
+ * File : item.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-26
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 KIPI2_ITEM_H
+#define KIPI2_ITEM_H
+
+#include <qvaluelist.h>
+
+namespace KIPI2
+{
+ class Item
+ {
+ public:
+
+ private:
+
+ };
+}
+#endif /* KIPI2_ITEM_H */
diff --git a/kipi-plugins/sync/plugin_sync.cpp b/kipi-plugins/sync/plugin_sync.cpp
new file mode 100644
index 0000000..c29f587
--- /dev/null
+++ b/kipi-plugins/sync/plugin_sync.cpp
@@ -0,0 +1,195 @@
+/* ============================================================
+ * File : plugin_sync.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-14
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published bythe 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.
+ *
+ * ============================================================ */
+
+// KDE includes.
+#include <klocale.h>
+#include <kaction.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+
+// libkipi includes.
+#include <libkipi/interface.h>
+
+// Local includes.
+#include "plugin_sync.h"
+#include "sinks.h"
+//#include "sinklist.h"
+//#include "gallerywindow.h"
+//#include "galleryconfig.h"
+
+typedef KGenericFactory<Plugin_Sync> Factory;
+
+K_EXPORT_COMPONENT_FACTORY(kipiplugin_sync,
+ Factory("kipiplugin_sync"))
+
+
+Plugin_Sync::Plugin_Sync(QObject *parent,
+ const char*,
+ const QStringList&)
+ : KIPI::Plugin(Factory::instance(), parent, "Sync"),
+ mpSinks(NULL)
+{
+ kdDebug(51001) << "Plugin_Sync plugin loaded"
+ << endl;
+}
+
+
+void Plugin_Sync::setup(QWidget* widget)
+{
+ // Create a collection to store the various Sinks a user can
+ // define.
+ mpSinks = new KIPISyncPlugin::Sinks();
+
+ // Standard initialisation for Kipi Plugins
+ KIPI::Plugin::setup(widget);
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+
+ if (!interface)
+ {
+ kdError(51000) << "KIPI interface is null!" << endl;
+ return;
+ }
+
+ // Add our directory in to the icon loader dirs.
+ KGlobal::iconLoader()->addAppDir("kipiplugin_sync");
+
+ mpActionSync = new KAction(i18n("Synchronize..."),
+ 0,
+ this,
+ SLOT(slotSync()),
+ actionCollection(),
+ "sync");
+ mpActionSync->setEnabled(true);
+ addAction(mpActionSync);
+
+ mpActionConfigure = new KAction(i18n("Configure Synchronization..."),
+ 0,
+ this,
+ SLOT(slotConfigure()),
+ actionCollection(),
+ "sync");
+ mpActionConfigure->setEnabled(true);
+ addAction(mpActionConfigure);
+
+ mpActionSettingsCollection = new KAction(i18n("Synchronization Settings..."),
+ 0,
+ this,
+ SLOT(slotSettingsCollection()),
+ actionCollection(),
+ "sync");
+ mpActionSettingsCollection->setEnabled(true);
+ addAction(mpActionSettingsCollection);
+
+ mpActionSettingsImage = new KAction(i18n("Synchronization Settings..."),
+ 0,
+ this,
+ SLOT(slotSettingsImage()),
+ actionCollection(),
+ "sync");
+ mpActionSettingsImage->setEnabled(true);
+ addAction(mpActionSettingsImage);
+}
+
+
+Plugin_Sync::~Plugin_Sync()
+{
+ // Tidy up.
+ if (mpSinks)
+ delete mpSinks;
+}
+
+
+void Plugin_Sync::slotSync()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+/*
+ KIPISyncPlugin::GalleryWindow dlg(interface, kapp->activeWindow(), mpSinks);
+ dlg.exec();
+*/
+}
+
+
+void Plugin_Sync::slotConfigure()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError(51000) << "Kipi interface is null!" << endl;
+ return;
+ }
+/*
+ KIPISyncPlugin::SinkList dlg(kapp->activeWindow(), mpSinks, false);
+ dlg.exec();
+*/
+}
+
+
+void Plugin_Sync::slotSettingsCollection()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError(51000) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KMessageBox::error(kapp->activeWindow(), "Not Implemented Yet!");
+}
+
+
+void Plugin_Sync::slotSettingsImage()
+{
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>(parent());
+ if (!interface)
+ {
+ kdError(51000) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KMessageBox::error(kapp->activeWindow(), "Not Implemented Yet!");
+}
+
+
+KIPI::Category Plugin_Sync::category(KAction* pAction) const
+{
+ if (pAction == mpActionSync)
+ return KIPI::EXPORTPLUGIN;
+ if (pAction == mpActionConfigure)
+ return KIPI::TOOLSPLUGIN;
+ if (pAction == mpActionSettingsCollection)
+ return KIPI::COLLECTIONSPLUGIN;
+ if (pAction == mpActionSettingsImage)
+ return KIPI::IMAGESPLUGIN;
+
+ kdWarning(51000) << "Unrecognized action for plugin category identification"
+ << endl;
+ return KIPI::EXPORTPLUGIN;
+}
+
+#include "plugin_sync.moc"
diff --git a/kipi-plugins/sync/plugin_sync.h b/kipi-plugins/sync/plugin_sync.h
new file mode 100644
index 0000000..2d04997
--- /dev/null
+++ b/kipi-plugins/sync/plugin_sync.h
@@ -0,0 +1,68 @@
+/* ============================================================
+ * File : plugin_sync.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-14
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published bythe 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 PLUGIN_SYNC_H
+#define PLUGIN_SYNC_H
+
+// libKIPI includes.
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+// Let this header know this exists (no need to load full definition)
+namespace KIPISyncPlugin
+{
+class Sinks;
+}
+
+class Plugin_Sync : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_Sync(QObject* pParent,
+ const char* pName,
+ const QStringList &rArgs);
+ ~Plugin_Sync();
+
+ virtual KIPI::Category category(KAction* pAction) const;
+ virtual void setup(QWidget* pWidget);
+
+public slots:
+
+ void slotSync();
+ void slotConfigure();
+
+ void slotSettingsCollection();
+ void slotSettingsImage();
+
+private:
+
+ KIPISyncPlugin::Sinks* mpSinks;
+
+ KAction* mpActionSync;
+ KAction* mpActionConfigure;
+
+ KAction* mpActionSettingsCollection;
+ KAction* mpActionSettingsImage;
+};
+
+#endif
diff --git a/kipi-plugins/sync/sink.cpp b/kipi-plugins/sync/sink.cpp
new file mode 100644
index 0000000..7d27f91
--- /dev/null
+++ b/kipi-plugins/sync/sink.cpp
@@ -0,0 +1,112 @@
+/* ============================================================
+ * File : sink.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-22
+ *
+ * Copyright 2007 Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include "sink.h"
+#include "sinkfactory.h"
+#include "libkipi2/collection.h"
+
+namespace KIPISyncPlugin
+{
+
+Sink::Sink(unsigned int sinkId, QString name, KConfig*, KWallet::Wallet*)
+ : mSinkId(sinkId),
+ mName(name)
+{
+}
+
+unsigned int Sink::SinkId()
+{
+ return mSinkId;
+}
+
+QString Sink::Name()
+{
+ return mName;
+}
+/*
+Sink::Sink(const QString& name, const QString& url,
+ const QString& username, const QString& password,
+ const unsigned int version,
+ const unsigned int sinkId)
+ : mName(name),
+ mUrl(url),
+ mUsername(username),
+ mPassword(password),
+ mVersion(version),
+ mSinkId(sinkId)
+{
+
+}
+
+Sink::~Sink()
+{
+
+}
+
+QString Sink::name() const { return mName; }
+QString Sink::url() const { return mUrl; }
+QString Sink::username() const { return mUsername; }
+QString Sink::password() const { return mPassword; }
+unsigned int Sink::version() const { return mVersion; }
+unsigned int Sink::sinkId() const { return mSinkId; }
+
+void Sink::setName(QString name) { mName = name; }
+void Sink::setUrl(QString url) { mUrl = url; }
+void Sink::setUsername(QString username) { mUsername = username; }
+void Sink::setPassword(QString password) { mPassword = password; }
+void Sink::setVersion(unsigned int version) { mVersion = version; }
+void Sink::setSinkId(unsigned int sinkId) { mSinkId = sinkId; }
+
+
+void Sink::asQListViewItem(QListView* pParent)
+{
+ new SinkQListViewItem(this, pParent);
+}
+*/
+
+// Pretend sink (just for testin the structure - will be removed!)
+Sink2::Sink2(unsigned int sinkId, QString name, KConfig* pConfig, KWallet::Wallet* pWallet)
+ : Sink(sinkId, name, pConfig, pWallet)
+{
+ mName = "Sink2";
+}
+
+QString Sink2::Type() { return "Sink2"; }
+QString Sink2::TypeDescription() { return "Sink2"; }
+
+KIPI2::CollectionList* Sink2::getCollections()
+{
+ //KIPI2::Collection* tmp = new KIPI2::Collection;
+ return (KIPI2::CollectionList*) NULL;
+}
+
+void Sink2::Save(KConfig*, KWallet::Wallet*)
+{
+
+}
+
+void test()
+{
+ SinkFactory::Register("Sink2", SinkCreator<Sink2>);
+
+ Sink* p_tmp = SinkFactory::Create("Sink2", 1, "Something", NULL, NULL);
+ p_tmp = p_tmp;
+}
+}
+
+//#include "sink.moc"
diff --git a/kipi-plugins/sync/sink.h b/kipi-plugins/sync/sink.h
new file mode 100644
index 0000000..feabf3d
--- /dev/null
+++ b/kipi-plugins/sync/sink.h
@@ -0,0 +1,89 @@
+/* ============================================================
+ * File : sink.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-22
+ *
+ * Copyright 2007 Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 SINK_H
+#define SINK_H
+
+#include <qstring.h>
+#include "libkipi2/interface.h"
+
+#include <kconfig.h>
+#include <kdeversion.h>
+#if KDE_IS_VERSION(3,2,0)
+#include <kwallet.h>
+#endif
+
+namespace KIPI2
+{
+class Collection;
+}
+
+namespace KIPISyncPlugin
+{
+
+// Foreard definition
+/// @todo Convert this to an Interface/Factory type setup.
+class Sink : public KIPI2::Interface
+{
+public:
+ Sink(unsigned int sinkId, QString name, KConfig* pConfig, KWallet::Wallet* pWallet);
+
+ unsigned int SinkId();
+
+ /// The Name of the Sink as chosen by the user.
+ QString Name();
+
+ /// An internal, unique type as specified by the sink.
+ virtual QString Type() = 0;
+
+ /// Some information about the sink type for the benefit of the user.
+ virtual QString TypeDescription() = 0;
+
+ virtual const KIPI2::CollectionList* getCollections() = 0;
+
+ virtual void Save(KConfig* pConfig, KWallet::Wallet* pWallet) = 0;
+
+ // As some Sinks are remote, we have the concept of connect/disconnect
+ virtual bool Connect() { return true; };
+
+ virtual void Disconnect() { };
+
+ //virtual void asQListViewItem(QListView* pParent) = 0;
+
+protected:
+
+ unsigned int mSinkId;
+ QString mName;
+
+
+};
+
+// Play at creating a sink (this will be removed)
+class Sink2 : Sink
+{
+public:
+ Sink2(unsigned int sinkId, QString name, KConfig* pConfig, KWallet::Wallet* pWallet);
+ QString Type();
+ QString TypeDescription();
+ KIPI2::CollectionList* getCollections();
+ void Save(KConfig* pConfig, KWallet::Wallet* pWallet);
+};
+
+
+}
+#endif /* SINK_H */
diff --git a/kipi-plugins/sync/sinkfactory.cpp b/kipi-plugins/sync/sinkfactory.cpp
new file mode 100644
index 0000000..bd34bcc
--- /dev/null
+++ b/kipi-plugins/sync/sinkfactory.cpp
@@ -0,0 +1,46 @@
+/* ============================================================
+ * File : sinkfactory.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-22
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include "sinkfactory.h"
+
+namespace KIPISyncPlugin
+{
+
+// Define the static stack variables
+SinkMap SinkFactory::mSinkProxies;
+
+// Define the register method
+bool SinkFactory::Register(QString type, SinkProxy* pSinkProxy)
+{
+ if (mSinkProxies.contains(type))
+ return false;
+
+ mSinkProxies[type] = pSinkProxy;
+ return true;
+}
+
+// The main creation method
+Sink* SinkFactory::Create(QString type, unsigned int sinkId, QString name, KConfig* pConfig, KWallet::Wallet* pWallet)
+{
+ if (!mSinkProxies.contains(type))
+ return NULL;
+
+ return (*(mSinkProxies[type]))(sinkId, name, pConfig, pWallet);
+}
+
+}
diff --git a/kipi-plugins/sync/sinkfactory.h b/kipi-plugins/sync/sinkfactory.h
new file mode 100644
index 0000000..19f9cd9
--- /dev/null
+++ b/kipi-plugins/sync/sinkfactory.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ * File : sinkfactory.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-22
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 SINKFACTORY_H
+#define SINKFACTORY_H
+
+#include <qmap.h>
+class QListView;
+class KConfig;
+namespace KWallet
+{
+class Wallet;
+}
+
+
+namespace KIPISyncPlugin
+{
+class Sink;
+
+// Create a templated creator function to allow our "sinks" to
+// register themselves with the factory.
+template <class T>
+Sink* SinkCreator(unsigned int sinkId, QString name, KConfig* pConfig, KWallet::Wallet* pWallet)
+{
+ return (Sink*) new T(sinkId, name, pConfig, pWallet);
+}
+
+// Define a type that is a pointer to the templated function above.
+typedef Sink* SinkProxy(unsigned int sinkId, QString name, KConfig* pConfig, KWallet::Wallet* pWallet);
+
+// And define a type that is a Map of names to creator functions.
+typedef QMap<QString, SinkProxy*> SinkMap;
+
+// The factory to register and create the sinks
+class SinkFactory
+{
+public:
+ static bool Register(QString name, SinkProxy* pSinkProxy);
+ static Sink* Create(QString name, unsigned int sinkId, QString name, KConfig* pConfig, KWallet::Wallet* pWallet);
+
+private:
+ static SinkMap mSinkProxies;
+};
+
+}
+
+#endif /* SINKFACTORY_H */
diff --git a/kipi-plugins/sync/sinklist.cpp b/kipi-plugins/sync/sinklist.cpp
new file mode 100644
index 0000000..5e290ad
--- /dev/null
+++ b/kipi-plugins/sync/sinklist.cpp
@@ -0,0 +1,169 @@
+/* ============================================================
+ * File : sinklist.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ *
+ * ============================================================ */
+
+
+// Include files for KDE
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kpushbutton.h>
+
+
+// Local includes.
+
+#include "sinks.h"
+#include "sinklist.h"
+//#include "sinkconfig.h"
+
+namespace KIPISyncPlugin
+{
+
+SinkList::SinkList(QWidget *pParent, Sinks* pSinks, bool blnShowOpen)
+ : SinkListBase(pParent),
+ mpSinks(pSinks),
+ mpCurrentSink(0)
+{
+ buttonOpen->setEnabled(blnShowOpen);
+ buttonRemove->setEnabled(false);
+ buttonConfigure->setEnabled(false);
+
+ listSinks->addColumn(i18n("Name"));
+ listSinks->addColumn(i18n("Type"));
+ mpSinks->asQListView(listSinks);
+}
+
+SinkList::~SinkList()
+{
+
+}
+
+Sink* SinkList::GetSink()
+{
+ return mpCurrentSink;
+}
+
+void SinkList::selectionChanged()
+{
+ QListViewItem* p_lvi = listSinks->selectedItem();
+ bool bln_selected = (p_lvi ? true : false);
+ buttonRemove->setEnabled(bln_selected);
+ buttonConfigure->setEnabled(bln_selected);
+ buttonOpen->setEnabled(bln_selected);
+
+ if (bln_selected)
+ {
+ SinkQListViewItem* p_glvi = dynamic_cast<SinkQListViewItem*>(p_lvi);
+ mpCurrentSink = p_glvi->GetSink();
+ }
+ else
+ {
+ mpCurrentSink = 0;
+ }
+}
+
+void SinkList::doubleClicked(QListViewItem* pCurrent, const QPoint&, int)
+{
+ if (!pCurrent)
+ return;
+
+ if (buttonOpen->isEnabled())
+ {
+ accept();
+ }
+ else
+ {
+ buttonConfigure_clicked();
+ }
+}
+
+//================== Add =====
+void SinkList::buttonAdd_clicked(void)
+{
+/*
+ Sink* p_sink = new Sink();
+ SinkEdit dlg(this, p_sink, i18n("New Sink"));
+ if (QDialog::Accepted == dlg.exec())
+ {
+ mpSinks->Add(p_sink);
+ mpSinks->Save();
+ p_sink->asQListViewItem(mpSinkList);
+ }
+ else
+ {
+ delete p_sink;
+ }
+*/
+}
+
+
+//================== Edit ======
+void SinkList::buttonConfigure_clicked(void)
+{
+ QListViewItem* p_lvi = listSinks->selectedItem();
+ if (!p_lvi)
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("No sink selected!"));
+ }
+ else
+ {
+ /*
+ SinkQListViewItem* p_glvi = dynamic_cast<SinkQListViewItem*>(p_lvi);
+ SinkEdit dlg(this, p_glvi->GetSink(), i18n("Edit Sink"));
+ if (QDialog::Accepted == dlg.exec())
+ {
+ p_glvi->Refresh();
+ mpSinks->Save();
+ }
+ */
+ }
+}
+
+
+//================== Remove ======
+void SinkList::buttonRemove_clicked(void)
+{
+ QListViewItem* p_lvi = listSinks->selectedItem();
+ if (!p_lvi)
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("No sink selected!"));
+ }
+ else
+ {
+ if (KMessageBox::Yes ==
+ KMessageBox::warningYesNo(kapp->activeWindow(),
+ i18n("Are you sure you want to remove this sink? "
+ "All synchronisaton settings will be lost. "
+ "You cannot undo this action."),
+ i18n("Remove Sink?"),
+ KStdGuiItem::yes(), KStdGuiItem::no(),
+ QString::null, KMessageBox::Dangerous))
+ {
+ SinkQListViewItem* p_glvi = dynamic_cast<SinkQListViewItem*>(p_lvi);
+ Sink* p_sink = p_glvi->GetSink();
+ delete p_glvi;
+ mpSinks->Remove(p_sink);
+ mpSinks->Save();
+ }
+ }
+}
+
+}
+
+#include "sinklist.moc"
+
diff --git a/kipi-plugins/sync/sinklist.h b/kipi-plugins/sync/sinklist.h
new file mode 100644
index 0000000..850b3f4
--- /dev/null
+++ b/kipi-plugins/sync/sinklist.h
@@ -0,0 +1,60 @@
+/* ============================================================
+ * File : sinklist.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2006-09-04
+ * Copyright 2006 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 SINKLIST_H
+#define SINKLIST_H
+
+#include "sinklistbase.h"
+
+class QWidget;
+
+namespace KIPISyncPlugin
+{
+
+class Sink;
+class Sinks;
+
+class SinkList : public SinkListBase
+{
+ Q_OBJECT
+
+public:
+
+ SinkList(QWidget* pParent, Sinks* pSinks, bool blnShowOpen = true);
+ ~SinkList();
+
+ Sink* GetSink(void);
+
+private:
+
+ Sinks* mpSinks;
+ Sink* mpCurrentSink;
+ QListView* mpSinkList;
+
+private slots:
+
+ void buttonRemove_clicked();
+ void buttonConfigure_clicked();
+ void buttonAdd_clicked();
+
+ void selectionChanged();
+ void doubleClicked(QListViewItem*, const QPoint&, int);
+};
+
+}
+
+#endif /* SINKLIST_H */
diff --git a/kipi-plugins/sync/sinklistbase.ui b/kipi-plugins/sync/sinklistbase.ui
new file mode 100644
index 0000000..804ab72
--- /dev/null
+++ b/kipi-plugins/sync/sinklistbase.ui
@@ -0,0 +1,180 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KIPISyncPlugin::SinkListBase</class>
+<widget class="KDialog">
+ <property name="name">
+ <cstring>SinkListBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>570</width>
+ <height>315</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Sinks</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>pixmapEyeCandy</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>100</width>
+ <height>250</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ </widget>
+ <widget class="QListView">
+ <property name="name">
+ <cstring>listSinks</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>120</x>
+ <y>10</y>
+ <width>440</width>
+ <height>250</height>
+ </rect>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layoutButtons</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>270</y>
+ <width>550</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonAdd</cstring>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="stdItem" stdset="0">
+ <number>27</number>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonConfigure</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Find</string>
+ </property>
+ <property name="accel">
+ <string>Alt+F</string>
+ </property>
+ <property name="stdItem" stdset="0">
+ <number>25</number>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonRemove</cstring>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="stdItem" stdset="0">
+ <number>28</number>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonOpen</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Open...</string>
+ </property>
+ <property name="accel">
+ <string>Alt+O</string>
+ </property>
+ <property name="stdItem" stdset="0">
+ <number>18</number>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonClose</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Close</string>
+ </property>
+ <property name="accel">
+ <string>Alt+C</string>
+ </property>
+ <property name="stdItem" stdset="0">
+ <number>13</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+</widget>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="159624">789c4cddc772eb4ab7aee9febe8a3f367a3b2a7848c237aa21ef2843caeb443560258af25e3a375f498e777cf32cb5e6b34098cc91064066e27ffdcf7fae4e0efff33fffebbfde3faa8f79f39fe6ae7afbcfffb49f8f8fbffffbfffb7fffcf7ffdf76838fccf381dfe272947d97fe2fffe7ffeebbf0751fd9fe63fd170f5df0a46074b1835a36254aee06cbe84713ceac7b6c5cd60058960fab4826c3c1edb4ecf6e81789cace0f110087f2bb8fe59413e4ec6e912a2ee6d0555d8225f6d71d100f9b8586d7177be825a30ef57d0380cceee8062bc3af5a89f01e5b85a6df1f96c102771b7daa2f95e41178e53db4f4e57d00bba17a01e37ab7d9caece231e86ddb6b6c5eb0a46e3766c3bbdb52de2711f5b025d662b48e2613cb26b39138ced5ad68091c1e06c950d71fa0f262bc8e2714c221f0271bc4ae4a85d9d699c07b0346d5f81c4607076bf82c221babd1058be7c6e1824c3a4b1045a65545c85bd58223f8e0d9271d2afb688ecb0b5b6f89c1a8483d8e53f1e01696aa77eb0cadbb889cbd8f2e57a950d71178e53db3e9e0cc279ac526cf03500f2d44ebdf95d411ff662f972be0aba6418a0b59dce81d6327b70b98ab164148ed35b566eae60ec10f5ab6b49e2b84fecd4afef0cfe9dc71bd0a6161fd12a9193445b1cac4a54928604b2abbda85690091e7f0dd2616ae7f1b5e99091620fc008b8b09de6e1389695a7ab084a8a701ccbb9473b4a19fe4d22472ba8c281ad447dcd0cd234b37d5cafd234a9c35eaca83f8c0dd22cb39da6ab6c489aa44cc828db691b766bf07062909699eda3bc5e4117b620820aa04e2c6fcb0b81e5dccbc4206d732b1e951da5d716a30fa001a6ab6b4987e14c2cb31fb60dd23ab32dbe5f8126b32df2d561d35138b06576bb6f90c6a925d0c317d066962fbb7f2b08919e5ade9eae1984dd1a3c2c803eb78cfa599d7a1a67c3dccaedc78fc0eac2746b0549388e95fd2603c606838781c1bf7dcc80716e393759d53069eafb182c6e0cb2516eb9bf3802c6c0c71c8873f27615742116e2d44e6cb161a0a3fc8c811898ad6adc340fe76a3fd95d13d8160b4bf55c3fb99f09ecb0510324b9a5fa895d4ba17d8cde8170b2565beeaea00ce7ca4f2c2bab70606b0aa237a03018bc5b7a54599e53a14440915b65305dd552691d7e62815b2440995a68bf0059c94f3e4e812ab7f8c82cc51aed63f717280da2790c54565d0c3eee0db48f64d524a5adb6d85d076ae0e5d020ab0b8bb1770bdc2eabd9c7fb10680a42ca7ed287035bf07fbe18646d4138fc025d61f5e9609584d9301cd876fa716690f585e5dc4b6a900f0bcb86e355d9cf4669975ac337f810d83e8e8f819e7aec6595b721c286ecf46321b09dbe1f00a3c2b272d6ad2014a0cccadcde89c082ffd5f611877e8065c3e726101795d5eb762d4936621fa7eb02db477e29b0047a1f19f83e062f47405258be8c5749988522c64f8ea7026b91efee80d8ebe4a1c00ad0fb9341388a5dedcb079016568f25b645a67d8cd704b68fc34b2001266702f2d6523d7718bcde1b846bb154ff3807f28258ff13106313a0282d2b9f760496842776ea45b83ccbdb9b08c8323bcaeb8f81f671665b94dae2e3c1202fd9e9530a54fce4f54160e9f1b9aa614279aa8178558d6775083bcbb98367a0c82895eb409991b7b1419e911e4f7740535a9abe64024bc2e77da02dad966af21584929d597cbc7e1be41569fa3e061afbc9e0f9136839ca732fb02d5e2dd5db0076714f5f02fbc9d329d09524e105d09716526f99c08ac7869597d0445b0f7690597a840a85c6f3c54eacd34f0eaf56d067de9a2605d0667671af96847d31e43c5e3a81a5c7fb33303288ead561f3a1ef23aa37808e9d9ebc0b2c0adf52837062960d4fdf0661a774f14f0564c3afc02eee2903c6c0e12ac5f251e68df8576450c4a55d6dbcca863cdc9c589334d8bf02fc27fb3706e1d40c86c702ab72deee0dc261ed4c9ff949388a5dedd31c484abbdac718484bfaa776a671085cbbfcc36b837cc4518647c098bec3f39741d82947d905d8e9e03d76a8ecd433bbda24545376d8eed02044b21de5730034548ecfb7064556d9162fb9804a9a7d1439b0b7ea2a84ae43cddd5a6b679a668937c00706794701fadc3208fbb0a33c9d096ca76f7f4001bc1c0bac009ddb4eb390445680ce274062107537024be4cf132003367e81a6a0dcb2531de5e947605bbc2d80d22117d84e333b6c101acfad7da021b35f2c8172fde4fd45c04dc0315001cfdf406d10f556a2c231124bd36c26b0c316160ec5f27aadfabc125039daa91761a7068f09d000cf1ca54c6a7a4a16b8653af49b5587da6f684a031d65ff1a08676f87b5332d8b9c92fd7602549efb53a0a9f8c99ec0eab1d70468810d2b9555466773b0f10764f4e9867694cacf236a07005db8a86b81cec36168a0a33cdd0b2cb43f2e810ef83c13d8c55dd816a13b6ab7a25137022a6e34b373836c48ceed5902d521cd6ca757db40955b118b52a0b62e6d142540431ff71dd0893dfe09e8c1ae013df07c27b0faf4d9d2a32ef38633b57c09376ff67027ea2c9243b798fbeccc4a549395747a6756a134e15a0cf6d8c732dd57f0fd0e34544a4f961e8dcee3a5302887c0db1da013b3546fb398fbb9ec546021357c012a4ae51e5b2c137105e52510cec4d234037afadacf16c96d8853bbda67ab72da7062d6bebc9c0023e0f11fd01f7b14d8793cbf01855f8bd5415da83eed28bf77404737f0ceda97cecf74301a0bb84d2881cec3c12ae94ee7f1560063cee33105623fb11da06aecf2ffac10f659cdcdc8ae9d7a1f5a5c2b73e515d07262935f018fd49e0d0abf6f78b18aad2fc735ddd1028881c74720a9898f77a06aa82e8e0476a637ab242c86a144598c8d4e0d941ed36707eec53e2b8370588eb20ff8615f5301875d0352e06921a0f588013fd3a72d015b8c81dab6886adbe92834519640872706a1b360f5693a053aee1a4733a0e75a5e5a8350807850c54e97b5b4e56d03d49cc7dbad80666d0c34c0647557508cb35162d567730be4dccd1fdc1be83c766c1fe390d996848f76eae332e33c9e2e80501dda899d030d27f6fe20b09f6cac8a6911a7456c878ded5ac26da43dfd8aea33a0e0c44a4bf5389c0905796ea0c37e6d09e8af1f0105f0580b683c5ba0e5c4d65637ab4592c53c854bb681dc1e9746cd2750f174e3f219e021e4a0dc310879c7036687314dd2e90610dbb544510ce4dcce3efd1ae84cdfdf8012782b0534af0dd0712d8f7b027a4a960d69d2f2aee0caae36dc23fb13c54260e7b13f01628368fe01246c919640c1f3e4d8422a0d6d03cfb60606cab92403b8fc41fa20b0533f7814d8a9ef5c0109f0f864a0cb7ffd032ae0715d6059f9fc23a04bdb03355bbca702dbe2ed1bf0347ddf1570f33e047a4ff56f01fd42cbfdd09f6f2c3d32ab94b234f6b71a8f409fd036580265a134d83eaec600d930187f0bac92debf003c5fa6960da1e34cbd7ed01928094f0b817547e71c2524b3fde4eb15c88027761a5a201e0070a64ad3a707c093f07924a0a3b80e340e3de029f6786310520c980bec4c236b1bf2508f59ceddd4c03821822e81d49e49478da57a1e5a312b401bb6d33c5cbefd643411d8610fde004f8f9f1320e34eebc1ca6dae6b799c092c5f5e8f81167829053c2ccf0dfe5dedae806aeb0b1801c7965145ea6f574e4f808eeee8e8c520c40337120d50d297ca1740456febcf12a808753f1d9233c09fc3243b022b62e53d90db16517300146cf1b90e54f6042dea7ba0e151d687352745e8c3d8793cb353a5d86323a063742eb08ec0f321d0799a5aee174ab1d77d815dcbaf45f2b295e70ec7d2a30c0586f70d16c965ce03c4c1de0be08ff62ead78944aa0e31f20e7f24fce004f8fc3738105ee8bc55859267e2bca6175b58f19d071b51f57400f3c6e08ecd49faca897bafc777e528d81a71301edcba5c0ce746c3badbc4445956543b8f5e291da490c543c0f8af78186c71d13ab942a5dfeef1cf0a7702f9662954efdf9d7a1b11ae6c1e223f4d61d5e013ff5c71d2006debe04d6cba92ce8ea50d5d9619305d0f0ce626e7d87daaf259adbe5d7caa85d8792b27fdc02156df623f0ef4c13014f6ab681115b3c9e0a78857500f8b5bc2f043c40fc0112e0d2b2a109d5b6a5fa86a57a930f792b5a65c09807eeeb3d90f0c0fdd052ac0917c7cbfa57815dede10d50f9e5cf0576f9f9abc0caedde02a8816c00348585f6b3c569130ec2dd2b3f517a3c5d0aec4c1f9f81b1432eb0cec4cb1488bd5b3c1358117b58031212f96122a0eff029b0dc7fdc075260c34a549b74233bf5cccea30d35ae55e3e7a74049137d1e033d8fd4b6ad690cf7a6d6538a5a3b8f3654c15417958054df006a523d6b057694dd1fc013f9e70bf007770fd6cb6995620f3b80a7d8c34c40a7a613d0a9390412b6787a14d8161f4702bb96e75d20051e3a8105ddc0f2b64b2beae4a1256117ea644bf56dabb6ba3ce3a5ce3c15d861d31a68a9838613a0e779e189758bbb506bdb16bb1de029f66b157d570e4b8bc28d3ba0f007aad67a74bafc8753013723ef02ab711fbe81d49bf917016fdf6e0574472f800c5824024aa5edb4cf860cd5381c036346556cac01296179fd0794d485f1b5419ef05065ba0bd419f58735e27d91f8138119907393b87b0f9084d1600f6849d3fd27813d44a80aa0a323f09d023d2f977eacecf7ca86074e4c29f63d115090396c4820ba4ebdc0b658fcdb82067807c8818f6381bdaf8c567749e5304dadbf3e381f1b8454b78b3b8c809441255703a0a2f759b54063bdad687e0fb4dc369ded1ae4fe0e67ef10e87936be561b14feb23ee127214d79c3fb07789a1e3e029ea6f9b980bbf985c1f2cfd2744b600f33a21c88799774b10e64bc90b9d80072e0e31ba879f4fbba66a09c7b7a023c5f5eee04d40e2f02cb97b79180cef70390fb4f7e0494974f81fd64311558563e902fa1cdb2586f2c4d47e18ed7d2233e305066ffb145c6609fa8f90372a09a033e50e7af175801ba6e809a4278b52bb09c3bab1dec016234bf015aefc3bc1984bb114bc2895dfe48b97f337520b3af12c0c3e1d1027714fec87d0bbad1bf347d14f03aff554036fc0285a7fa4c40aaef0a78ba7105946cf1590b6c8b2dcbfd71685e7933726d90263cbbd83e36c846b1b51e770b2026a3be674096d01dcd818ae664b40978aa8f62a021d50743a0a573b5f50af494dbe99741e816db16e71c76f9fcdc0ae1be4131a2dc1e35c0d820aab700af2d0fb8da65ce5865702cb0a37c25c018f83d03625ec65eac0105af16bf2a03e5cbd33fa007cbc5856c202b4702fb493417d84fa2078185b63516012adfe24e605b6cadaae032ce52af3e074041f5b915015e3c2edf818e549f6440cfb8add6b2320ea5c1b638028a98bed47a0724c0e9a9414853fbc9d731e0491859251dffbbda5b815d4bb40074b5bdc0b6580c05f4c7d6811a98ac9e0894892e7f5200250f3366c780bf9f9ba406e16aad3969addc26c588210147ec43977f60d990e86a0f5f8131b0ff0cc48c66b8d8042aba3defdb06badafb03815dedc79780bbd76ba0f6f4d814d8168b378165f6a2071a60dbca6d1aaa60eec5b68092d194a595a834dcbed9a9175f404f6b7ac816a1ccd9b59cdc031e0e7fb740cafb97e34380516ad11d5b840462acf502482cc5a27e2ab08c2acf8194342d46023a8a6b40c62893bf07819dd83dfb5012de9702422a063cc5a24e6065ffdc6a872c24210fff16003116cd9f0596b7450ed49ec8438165c3fa2de00341d31d837cc4e8c1f581802757a740cc0bdd9f63a0ce78b4b701b416c9d19c7d143e9a72ef09f0518cbfec2364a5c12401526adca96565169a3ede68fe09782e752cb0349d3e0209f932bb069473a498726e7a0ee48ceeb8f0a3b4bcc3d9b0263aabfc5de3072716328af1301f02b6288016885a879636cab6c8435b69a17d64a19da73e0560d7e26339ce82be8395dbdcb3216a8740c25b8d7c04d4d4a79335a06198d68d65651e1299116667024bf59b7320a388dd5c0079ce63db1ba0e0cee286f3284a0ae1690ef86897f308f001983719e06fcdcb39d0f1d8b6dc007a1e5356d6ddc8d5ed397a043cb34fb780940165ddb38046fc05f0dc3f7a16d8169fe4cbf2cf02e6092819c8f560fda05c997dbf003cb3175f02bbb8af07a003b6acafbd7cbd4268db518ae59032cb5bbbb8221f3250f8a8021a6acba34cc00b088b8fe5b360dbe2e612c8791071331390735740c1abf89b6b816d91ef02a5ff6424a0926e818adcbf190be8d2c6808fb6bd4980c621055a06840cb61d78cd717b0f7838dc9e0a18e54a0285fb24cba809875d368e966224b232fbfa17f0cc7ee0e2967f9673eb80e7fef4c5c15ea6443d19157a5f762d0babfa0a85c39cf308b90ffc081850b609f456f347f7b6d3d27bc151d50135ef80fb0868122e7f62106a6d2b73bb5702ee091f001f1e956f013e3cea681d6881d36d815dfe3910ba2cd6bcde27800f9cbe4f8116680f001f05bd7e641032ca62fdfe091853d11f72b5a1dc3279e30cc8c997b37da0205fbe4e00cfa8bf0381dd24de71eaa15e67a75c7e3562ccd5612fe0a9c21da0a109a4ba72ee7301f4c07c22e0f9baf5d8aa3c4fad00c52f40e1f00c948cee98ec038d57e37b022bd9e523d051af9fe4404f466d5be7bb0a05d91a8bfb0c504615027b9f7dcf3e3ce706370e3e5463eb1fd8794c4ba0a7ccddb0d365136cb9ff067889baae04f693e335809c8baa52c038a50550316ced7b1ba8d9e2f7556069fac999865269693a9b03deaa3f59fb52fdcbb944603937b728acea21f074ec608df8e0dcaa8b3aed78ee905aa554670c391bc476f9f5bfcc7e022a1bf13f98ec025ee6bed947c84aebe50cac44d5212b292f3140364473ebd3d54ab109fb508afd7c039e40eb874043b7e7ef1168819329d0f392ebd4aae03af4830c5e6f004fb17b8e12528c34fd0724e1ab03fda0caeac210d836092daa7e016e34a3ea0fc8794d7a5c029ec81b2740cda39b8995fd26a4294368d8226720d760f606f49985e5d4c2b2298640be06240c479ede00395da7ad19e00ddf8ca3148cb91a9cbd033d53449a070153432db49b6570db995e0aa80b6bc063fdbc13588ad5910315db94f358fe59f138075adaa8cf63a003bedf1c1818fb6a4fe19aaae67de58bc57a538fc8cabb2b074ac3472ee071a965659b8d635ee9ed001d772767761e6dce54c8c1e408f0d23039043ce7263b02ee1bb680de615d40de5a56b6cadb9f0530e646739df3089d5eabfad23f40b5a5756adad267c8e4cf02cb97e2118879a973bc09e476ef11dd7f022575e1790f905151ff2cb0e0afcf819601baf937d0333e79cb6adcb64ab83bf9990aa86138f5aa60b4dccb0de0e33f5e7b013d14ebf3b7ff327be24066df3f08ac54deb5c0982dee7e05945bbbfc2e6d99907b6cd9d085726bc534cf818e4ecd9a95ca2edce1d84fe27780ea336a8f009fa7153f3a30612a7e10d879c40b013bbd075a87b98006780228e83681de9fe35a73d229c60e778151c60caa1ba0a445aeb601efc11e5921ec96cf142d604ac067501dff025e6bcfd601afb57fade6ef4225cd28826ba060c4ddc744c050f33d016f5738b15005311e866b09f141bd6e71da29b36d1af40a18b3790bc4c099555bbde77e545924f77e7f1b0dd6809e8719132b95fdbf44b613eb9783342d81be002fb77bcf800f7ade38077cbcf6fd29d0b0c57902f8bd07ed7e1ffa3076719b0e399d9a4105787dfac099868cb0043abd10d0a33f037a2ae92d6ba3fad0d9b4e0ff5b00639fce90082c5f2e7e8194d1d88f2301e3725a20631cec87efa3f4bc7d011ab2f2f51ae8787b7f672d72ffaf201f02b167f6bdc07e327f123055650f4880f5559c56c3d0aa5b69a81640ed7738f740c303d5f50ce869d5673f0639b3e223eb6e0460c46e64536503f84cd02df6116a077ae31f0ed40ec5af41e103a77f1aa0a78f7bfe6050a6bc04edf94999f16e7e6d1728b98ddc8980863eee650e78ee1f5d0a18d27c6da04afa7d2eb0f3f8f81430a9e60ef0417a9f7f404335fe9c0bec4c6fb70c942f778dc052fd8e13ab5360777533528dd28e65258a23832c8ee9c2bd00a575d0a2660fa87c14d233a0cc7e12d8bd47f50034bec5a3c0cee397c386ae825ddcfa09e0d36df7ce0dca118f08062550f33c6830011a3a579705e0f972550aec5a7ace342422eb19f4020bfe724fc01b09d263f9b7da473406120af25a0378417edf000aca6d1e012563f1df3e808adc7fda067cd0e2f38581f2f6611d4881dbb9c08e3227c5eaac65988565f6381b7243534c819ad73ee7962fe3dc8756dfae095811631df019dced06c0e0ebe8d6c1a7334c388aeaf5db5b20663ae51f5b2c5fa45b31dd10d8a96f6e0123b6d8da10f05cbb058a823a79e460157d648f6e0294f6062f1acc81aa64da8d834f953db670182b1c2e2201e19001638afaef33e0e1f056032579fb66f131ae7d74e9db27e04301fb21e079dbef09b8bf3d0232e0dc323bce9231b3e30640469d7c3f052a2f84af40cdadd7d0a230ce331e320ddf058cdc7903727b6e19dd6e020d37bcf127d0796fcbeab138e43e8fb2f68084f762071c3664a55dfe0e3b0d3d25fbc906e7112a69aba5b6de0496c8313b0d3967f1b133035a1e11a45f06caa8835b015949022dff56f0bd23b09d9e5c0129bdf157dfa2a1b7658f5daa38e40ba5f24ec09c912b81ed747e09e4c0dfaa43522521f359cec1823fc9462cd333dc07bc2f35b4629ae43e4960b80ec434afc33f015bfc02096f8a863f02bbb8e13790f2ca77f825b0181b7e3ad066dffa5132e6586dbf09acccd14625a1f3cded2c870d5d386660727145479b3d03427c502ab938e55cca7928e72e538115b1070ebb24cbdb0701cf3fae043c97ca80942d62df22a35ebfd8066a9fca74256042ff07d03003e2333108659f41030b60e4a3d4c680074c370172e0765b608530b2045a2e7762f9727200e4bc6d3a3c36081d34daec2f800638baff015a46a90d2db4d37ce801b3098c3ca476056cb101f8dc95f529400445b7fe939697e4b77e14aa8b888b5bbe25b604dab48a2d0dbd290bcbad4e603b9dbf015e4c7fb896f0c724812b20e359f0ef0590db68a86830004a4af6df04a869a27fde043c1ff3f3e8e8a06d588592d643e0f914183188f3eb17f0a1c4fd03e065bfcb8002b8bb10587c6cadee4eaa6cb9789895971668786036b344ce42ced96187db80726e4f40ce6d01e45c34c8002fc86502145ef3fb3ebcf3fd6d3116fa89d4c93f0f40496b5a7e00be14c39615e42cf4c81852140109e5f62a063c2bf739cabfac3c01724ae5df135050907f2e80b2220aaf00afb55fac7b9e859c6346c896c0c2e1ed00481975d3a5806754f729a0033f074aafe85b816d71f728b08bb345de02542d4f14ad78843b2086589d5821cc4353c033943d80721b556f404ff7bcb680c943de323f7b1dc8bdd63e10d0c9db072a9e6bcfacab90872a9870f8041a7f13700a743cfd2a8f0196d9881696b77928b7ccbe4e01cfdbd11a9001bbb7029e28fe096c1f790f78319d6d0a6880ad79cd950ddd81806ce804cc9d254d3d1b06f6167005cc17b39d16693ce279f22950b1f85e6737bccb29650ca28880cc17ac7b040ad6963bdf12d803a2be061a8746c0cd6a05f8026dd527c0bcb5c1baf53f8a501950c14e009f063db506a750dece0e809c479db32950da1bbc68c0d52e6f8aadf5180a2c5fb62e80848ef3e63a90faa3ce37206340ea85ef3477f8017aef385b58162a952fcf80cf4db8e8011fd07e710bf8a0d6af43819de917a75ee70cf7f824e7140e0f5c8bc2e1a110d8166fa4695d7bc0cc053cbbb05aaacc8674cfcf87c098356666e740cbd0c8620fe83d6fdf1d7c50abd5a765c85b5ea3ff02a90f18ba020afa74b33383a2f5d53d2c6fcb5090599ecfaacf72392168053b3702debdde0165c5ebfc06a82884df63a0af99d37c2c60ad1bf6a11af7ed4a6067face99d623ffc9ba809f54021e765d0263662ebd9384a1bd253efcb01e0e6f5c5c5df04eeb23033cb3bfe702c281ab556677b5c0b6987f010df0bc2db0c3ae5965502d17a7b4623a035a660dfc58142edf233382c802b72a63de597467804fdbdbb6acac422164d5b709e06bff6c7f0089af64d300e46d143d0325d37f267f02a6aa7c0215e1705d0a3875dfa2e371c7b7e55c880e1e535eec00239f39fd0e8c3d2bb71d9896f5ea5b2464e56b2b6092d115903101e47953c028f93950503b2c480fe55cb70f349eb71f02dbe27653603bb57139cb772b2daf8e2c2ceb9471d2516fed4b380d56f3dc4a8116886f809e8a7e60995d870e1af7ea6b023bb1bd0301cbb0bc020de3fab6edcea25ed6b99651f74049ce7dbf0015ad69920bac889d0d80ba6298c505d0317f7f7d02f4748bbfb89690d9a4fa2ee099fd7d2bb06cf8f800c614f58f46c0d3af0c48c9ec0baea5f611eeef0e358fb19f490fe5dcd39b80a06b81d673bf1270fb3612d899f67e711db06349d8847a9d51bfc780afa1ba67ad7a136eabed4cf73680d4614d60d9b0b70964bc281b1e08ac722c2e819c8afee748c0c82e8bb1460df0ee00c8fc21f539e0b97f7c0b90d98333761a32dbf236db06a8d7075f96ea4dc86cdadb7d60447c5cec0918827728e096f857c074861818fb4ebf058cdc391070a735037c92d1c502f061f3775cadf2f63315d851ba77a0638bc73b816d312709ebbe65608a5d4b1b1a714ba0ed57a0e209ebc63ad03125a2b322b67c27ce13d64301e1b00bf87a177bdb8022e80f48898fbd75816d31b3f468436f9cfebab5516de5cb8ded2602ab1d620e1ba2819bb377a0a1ec37f7028bb1af0da0e5a6f9381130dad632aa0d19c584ba58c0e29d9b80d7da170f80e79c2d631dc073aee328caa8fb7d01336432a0075e0602dbe9a9f52dbb701f65d7b23300c663e68a5e00051db4b335a0e381eadc8ed2e5232fea7b80726e5f40c9de013c2b67d6e9ed420784996d9c58e5eba01d8e04ac0a18039e2ff5a180710643a0e5b9d4d109d0912f7b8f40efc5d4ba2c5d9d7abe3c01b9379efca4aee8383f3f0bb869e66a4322db4fe69f02b26128b0cbef2de8ba6608f06a600976943969da8c5a32ca7ed2879c63f4f10048e94bfded002565eefe17a8b8f59a599af6a1ccf10eb807625e72b56b40e2c5f407f0f5a48fad8dea972f18ac593b03bc73b5e190f2a6a8e5b015abad45835740e5a505c8a8a8f972a06bfd700ff4fce42b15f012d41a9cd01e535beec440ee45ac037c0ad11b0954fb24928b27a0668bef3ba0a1797db11e6c1f328aea732cb0c3dedf0b6c1ff75c4bc84af276576081dbadba70f530e42ddd8da980d0be069a981af7c020242173ded9c732b85730f972f0bb931cf0143be81d7c8b5d83e59f35afd70246996c0b78edf3068c80ef04f06cf8de04523a353fa702266d4e80cc47665c002585f03905bc105e3c039e51172f40e3c57443405faa3450ceddef09682b6b6004d80a432b202b3b60dcdaa99fd8a98fd2d188e10d8706d9c89f496f38f8a3ac570143356e80943af9fc09a8ecb30083ef29d033eb28b39c1be53ecb779ba378a98ceed969c5928751bd002873519b035e39c63b06cb80b0a23e73b070889a89c04eece7171879041d086c8b9b89c0e2e3e751c094994b606cb74d910d595d01b35a6320b60722d17c0824be24d529507851ff044a6e9bde6f053c547913f0302312d04ff613ab7ce992470173897d1fb5cfe0be14d09c902f8ac20b72bf6ed9e27d13e8fd399d95db91a2b08b0516853d5919a2d0e0ee49c0d49d0110b776941d2b51e32ca6f52867005fde8806be45ed2fc91f80962779b747807f0461db4ac3b8ca18e8d7ed025dc540bf6301558e5dfe5811547402de7b348087d4ceb580268913f38019fc3d0b2c09cf7c8bcc1faaac0125f1f1ba05d464e5cb23e0f35fdee680cf6f789e0aacbc7c6f003d2fa8ded9a932eaa906c6deeeef08a8507201d3184942e5dc89d5b871c828a63358eec795cf793f4f81962757eb0dc05a9d51530b58f1600a50f347d1b7c1b2b958ed636dcb816cd8bd0328c8d1ed2310930dc79d80b10a5f404241ae8e0476a6c5265050f37fbc039e51bb0740c503918f7d816df139017ca9c10bdf8717b18b3701c5230194b70e3ee6fbb972e07df63349a8ac7ceb047694c529107b31bd17d816f377819d87ad72162001b6ada827a1374edb700994f40ce6db404fa91c580425f998ef9dec58e5982ccb8395ca77016baaf8169e733b2301a97e2ee0fb0d2590f093f31d802520a3ea4ec044fa31e0f9523c012d65ee9da38424645d961720762804749d1a01a9be23b0cbbffb0612b6b06feaac8039ab9f404a237eef5b64c05d2960daefea96a74ef5fa693b1530332501c6ac5a5ded02f598d1d8a740c3e7803aab94d2d0d7b6d0de9b00850f4db0629a2a5fca0590902fc5b180703817f0ac2f0732b6e807024bd39d7b20f78ef31c60e86c1415023bb1933780b1b4d1dd4cc064eb1fa0e299f4f7c88116f96b22604cde2550fb1881b98092fd017434d13f4f021675b7f6256d7c6ac6cb85833f1f5b17b0c81bfb687ccc77c799fe8ba053815d7eb707a4c022165866db325ff5f22333ccce7f145802d1a34f9bbc65de9a9d4796b66306e75bde661afeb2710d8c473c0edb70f02d1e8164c42b8ad620f7a5293abbfcacf6656847c70296e63c15f040b500bca8377702db62fc03106383877720270a7716808fc6fe3e17b058361757fb68ecef35071f45e05bf822b3df3de08bbbe6f7406b10d57eea8a0fab3f3285c30be9a1dc7f3e11f07cfd018881074efd5f7c7c021e0eb7ff609551d38f01a070b81158566e5e02b9d752b1c0b6d8b6fa7439268d598bd7804fb73dbf02682c067bd63d5f8e6a64b975abf9f3700bc8dab6d600e7ffb2721df0ac3cbe1358999bad09a861388fe59f9de94cc0cdc807d07acedd0b18fb35077a32eacd0a721e0a3243cece05762dafa447e393379e6320f65758ff80eae25d40fb1201095b3c6f09ac445523c0f3d65e3daf80c622073c6f9bb98069f2438185f67d2b60a4fd1fe0b9df9c0aac27bd6804b68f4deb902cdfabb3d8ed10e8b86b3cb196b0c84b5fcbf512a898a894583b57a86da83604b6c5de03e005f96700f83c8b873b01c32cb6044c2d3f143078e108f05958a7bf021a8b0fa0f55b2f4ba042e1f0b62760c2f62d30e201c07b2fe0271702267f9d0389bfaf5c0352874701ab348f04961ef5afc08ed2de031e0ed55840651009ec3c1aff89e77e7b2860a7230153551c0ab6e84e056c7125e0cdbb15f5322dbcf5b0725be6be96c9d13b90faa7f3ac2e2c55b2cb070193d04e01cffdf9ab80757b0e00e66a44ed18e8a80c4ebe04b6d39833ad7d21e377ab50ca7f5999003e9be3f918f09cfbe8809c4aba590848d37fd059be5480d2745360696a03535660697ac4d536253f79db103073e943603fb14f4e2d1f417676eaf6ed9615b0faad75f1978f4f5956d3a2b0ca1206c6fef640c7a7266fada85779c680f6295b84469cb14effc08eb23f044a4ae53747a97dfedc6e2fe021c20350d3c92b5e1de8d3eddc013e35637106b434f3fd08e828d93f3380cc8eaa5b014b64588512fa8dbeb2cf9e8085496a60ec8dc50190f8c4ad4d20a56d787d1130f8690164dce03d73b5cb8f2ead60bd10b0d62f1717c281fbb94a60e751c502fb49fd27b07068fd28a5d70eb580dae1df1634167e949280b9f513abd8e26ee0e031b621b09fd8bcf9e5736f20b1ccaed37444dbd00139df7b4d5ac03f009b344039e2366121e01b763550f193d872bfce182e36282e006e67073f56f5d5e17696a1802740411fe6c4ca7ef80df7b7f7d780af47bf601fb52ffcfdbd27b0488e5b011df81f80759ca3ce2239043671fa150b785d7b0b8c3d2cc702168766a74d0cbc90628dcf6f783d037c50fcb3ef23a7fff1b2061444e1d350c043a64301bdcf1f0143579e0596841549f82fc6ce0444d09b0311143d019587f68680eab311d83e6ccacc12d8c77a05d41cf6ae10f0133f0f0fcb5ba2b0693a4bb1c4f6d1a4b5476104340e03a0f5a02b81dec10edb6423871c881d3220193152650c146346a97194705b404fe90d68798a9f5a0dd3e43981bb63ddaf26349ed6f015db8087e5372756fbeca787238155f4dc46867fb2c5ef95c0d2f4e7d5a161b64f02f877022e2c609a10a73ca9391010b82320b6d08ee673c003f78dcb0f71ca8736fe812561f10c14fe12f41e283d706f0414c2b1803e4c2db024ec860e84d4ed0950f98d772ab09f348f0efcc4be8812c0a3b0db12d84f7e3f1dfc281b02567f79071a7ef2b1eec04fe69180f94076626d96b24a739c082cd52fef1cf818f6e52de05fc7be9c0bf856490ce4d4b8971150f94f0640cd27965a6b81dadc3fed7c710d308975f0c35172663e0e622b84adc272ef4cc0da500f80af14bf3817b010c70bd0d1c52fa70e3ced9959c0b4a147cffd3ee9e1513858af81845bc0b75dc0a7116c7c0385b7ea67025e0b1e011e744feb80576c4f7f02aacf5ac0721f070e64f6d304a8d9c7f39fc0f6d14602c2f2dc817ddced0b2cd517c7024ba0c813a8f158df14f45605b70eb6d329bde025509ff6028689fb4f5ae0d2b2b20b31c610ef63206740c8650f1444e16507940e15a028ac054c85f49dd6bccfbe2881c6bff35e08180d950b184d99012d4fbf2e52a0a30abe48809e53bfb0f2d2e5431eca5e8c81116fbd4efe0183173a8125d0c508183b0c81d8afe5064862a6ec7e023e27b1be004affc0b8c57a17da063b8fc53ae0256a772ea06b4d22d77c8c217208d538cb7a0f04f461ae8098a72c5f070286361d0169c39287ef0ed4fc19e9111a3ae6f09e035e085fc96c75595e9f8112783915d05f77a87c8b3f01a5b2143042e44840a95c03bc103ebd085890ec59c0bdd8d4c1db867501abab93eaa188b1d36b01adc7998092fde4c04eab4cc0c2022f023e1ce0fb68bd32f81030a3dd4fbdebf87091b50d7d9a30f0e0d23adf7d28a6cccebf070a0ad06503a898b68097ca7b4bf5de8b4754df015e3cd6e7401e33086b1b60f2c66027015a060cad59c5d61743de6aec586fbc0fbd1ee68c14807f33e52415f070e74960897ccde5d7fe6d8e6d2b62e19f747beeaf80310f11beb9b8d07ad8a9b731e05322664301e3e87f019fdbf4760c943e52f60ba81c4a01c1cfa92f3b64069580bb023f8a87d46321b0f3b0efdf2ec1e3e34bc0fded00683db4bf1df8892dbdb802a2702860b235f11162cc7ed23c0bec27752ce027db020bcbb5d5e537c334b3b08ca22d836ccca8f0e6d220549f0cd2bb022abfc1cb0c1aff78c9d98f80a16fbe857f8a231b01fa8ec42d1073b7f63d0412327b7713f019cbf6f82780cf6c7bfe003cb3df5e808a2eedcf19a0bc8d04646529e0a9f506e015cacb4c40bdfeee40367ce50216ca3f075a3fca85c08e12f999b6de11e805b68fb614d011f053f7dcaf720187bd15f013f6d10e3b4bb14d83e548269af96b83bca12b79f66d1042865e8e9de9c8333bb24ecd0a18633402fc4b35d34ec003b343c08bfafa01e0d3a1befe808277381fbb02be75b40378b97df7a3d45e900bc073eef511f0546ffc5abcccf53f02be76b32960358b33819d58f40a749e73b702db475508681b8e044cb5df027abf7fa904b68fe64260fb68ff04b68f26135802dd5b588e4266db16f7db02966e5df5829b71eadff42bde0c721fc558b345e829d9614bdbc75859b9e800ffa6cea210d82b3d1b3abbecd2f045a57e5bc00783b600ff2c405e02a5afe93612f01afd1ba8888fcf5e407c9c01b5dfbd7e020df0f60cb4fedac78fd29240af33a023601e371d3ca3be04d4b8ffb6b0f4b0b96f2b882d3eee047694e61520b3a71f7301997d24b0ab7d3d31085969878dde0464c39680dc67a7ed08b83b11d879dc9e0b2c916d6ddb00e38ee9b676ea7136e4a1cad421665ec18e5d4b5cfbfcb964cf40f1b17b21604d846381ed63f10bf049a12872e0f337918dca0ae0dff778d8000a3a029ffb009369a3fb4ba022a43ebf05cc07ba15f09da21fa0f11a660ab444d0f1bd80b7d539e001f3ba0ea864e702eaf5278125907dd06105348d6ca1ccae6e05f693ee5c603fb1b54b574065e03f21f7239b2fb602dbe2787513d024693f26c52ce812dd576eef0b783e56022d778d9b7694a4f0b53b0ead8825aa0ce69b807f2eca16340ce0b3e3be9f049cfaa1c08e621dc5f04fff1ad2d607e0f3e7c8ec441dc5af1fc033fb732860350b2e2e541784c323e0d3b23ede009f3ff73a1750a16c033dcdfc7020a0fef013f370787c1330abf55dc063a8630165dfa2305138743f02fb093db644e1d0bc09ece26cecd7f2658bd71f1f029e5dbc0ba8b6ee055417338125a1bdf60930f69f2c04f693682ca0205b12a669e35f66b1a32c876931017500f8abb4ed17a061225b65f191867b75966fb49a3f551bb5ff0a7848edbf08ecd47f6f80d4bfc9b529a05bbc0e781bb57d0af04594a8df14d89d789b00957f9c62e1401df4c7d586ea82e5e82a0103ca22c06772bd5bb595b64362ec6dcb81907a7b14d0dd781050a1ec0bf844db36e0e150ff03fb493d10d0bc72b5212be95b7e0b08ba2b81fda4bd103067f559c07252a4691b03f73d90747ce5ce822e4b2b9ef36fae19841688d5a31e80946aab2c017f06bbb601d43c754a2cd6b3e5270dac7761f99215bea0902d4915aa13af720ee6023bd3c504f0897d37870296d5e4c41a3e8f1445be055343a3fb67c03f80b2fd25a042a9009f3cbad817f098e15560a93eac019f10f3dd09b8da5d010f988f80d65708c9808eaaefb31358367c0c058c926f0d3c4ea33bb221441071fa24a00e8a0563ab3f1e048cd71e08085c724e51b8b815d03dff14d0bbd816d0cc4740ec81fb2eb09fd43b023a460d90789cee08986c4d9cb629b06d699ae72c7b16d1735c0ef56260fd2150da32c583cc769a178947a11d36578c6df5400ecccf040c3c780798491e0d460296d869010fa9dd54c0e26a7e582228eac702c66ddd001e303fcf021e0e9f001d31f6c9e5ab627b61a72160588cf0444004dd031e41ef8d8087e5b5c0b2f2a71258565efb16637ef2100968b41e058c65c9043c533a05626f6faf05d4745381fdc496a25c815d7ee13b4dbc45de16588343073e578cb56381a56944128618b32dea27012b1c5a121669cfdba6b337079f05ce16a1fae4c1ff13d0312471cb5ab122f721abfbec4351989e08ecc40e5e0085e58e800f269f08ac42892aa0f081c27f02aea513d889fdbd023effd6664f2e039b0698040a3ff0ead3f7e1b13eec01ffd6d1f0d6c1b7b803fc8b39dc242e818118fb025e731c038af51bc0637dc23e4268dbd5da08b315f07ab2047c36e9c7ab801787da8248fe2091db313d83f72f07b678af05ac92f82cb0ee79fb21b0b0bcf29dc6be8f4f010bc45602ba0abb027a7d8980bed4bb80b52aa600a561faf124a0ab702fa0abd00af86010a91e829f9f6c0bf84927b09fb4fe93cc20b285af9a327473980e652d50990f99cb73f803f8271e2fae005f0f65d7aae0e55aea2c945f011e635ba50331f6f322a0c69d03adb7d91780426a0fe8696fbfacfb5586086291b71ef0994b2faf023e58b8e14056fece80980ad64641af8017cbbdc002c606e9ad801bab4640d5f721a077c1b5849c230a67029af97701e1f02ce0e37aa9c0761af9e5a79c87ad8ebc02fb49bd27b09f34fb02d611b0a354d96844f37aee40e5b865a15de5be16d2fa1910f30e676303c87dd1bb1fa0e5f3590b6b5f9673e02d5f467f40edb39f6602debf5440e3155b09b484d4e1bd83575bffc0726e7203747cdba74d1df8c9ec1df0d971e796b7e16685a7e75fbd80559bb838d552f137e0f31a3f8f04966225e7a1fae3e305f070783f16100e1f025ae42381e5edcd09e0b95fef0bc8fd4840c064022a03723f5406a905dd8b8006f844c0fa0e770226287f089809ea579bfb4f2e04dc9d58ded6594713bd67695a878e228b9a5947a02e4ad6411bd979d48aa0c505e01134fe13d873dc2601fc53603b8f021abe8503017338073c60062f0e1e630f027ee2fbe83de8ac63145a5b5ed94c130143462e019f81f9b527a01e9b0918dd710328c65a019fbeca8098a0fbfc14d0bc6e038ab112481d7201af4a3605acc6570918f25e082cb31b3fd3cca3f040603fb98b04f6933a1550e67ca7b9efa3126416a7af02fa853f82c2b678030a767af72e60a127bb8b6e424dc7039109d030f8a97c073a063f9563019fce3b1250c3d8a93739d56764b3b0028c81fa44c058a75e60673ab2536f1aff5ce5c307e0f3b3d30d019303398fc63f7c16af0becc49a14e8fce3586b0e8476fc07f40ebf025ac21f01a1cd51fec57a2de0eb1d57c08867d2ddad80d51a49b110c9960df7130103635b019fddbd0752daeccf350177386f026adc67016bda3f01195b3c5f097845f12960ddc0998025a91602bab4e48b02b7bb14d0007f095864764b60b9dffe0aac3e6d5f80c2abf15f0105a816b016d29b8035226e80d24bc38bc0b6b06f702fdf13b1d3c42afa36cd196bbd69ed7eabf272b6032406d1e007f0c5d51aeb18b51edad1fd1a907263f5c351f28e9119a7567db645c2c88c433bd356c16f9fac5b46ba07ff9f809be64260b13eb52735a1a3c0e791a22b80288cfa1888a9713f398f36a1fafcea1cbca3780378481d73d8e5f55b319d092cc69e7a016ff03e047c69e24960899c46025ae47f3bb57c39ce819c9d7e6c09e8194c04549fef023a02b1c0e2c3962a0de031664bc8ae80383d17104184430829fb49fa23a0ab702ae00e989c53d06d5951ef32bff738b772db859e01537772c0970b4aad59eb3c1ca2e808f079f336f47e0596b7fb99803544be00affa0ead99ef54b19d1f035e6de56340d5d623e0132ee313c0c361f12de0c15d04e43e78e140c01a1195802f086d0a78ccf0ef27f4b6e6029670f3132bfccdfb50c0dba61f0147b916506d7d0b0887570115cab1807038033c1c167702d6ebfb13b0bed41a50752c746d91dca73d15cadc4eecdffa52874740e96ff00e05cc16b4f2d2e73e23f58f9fa8fe1839784b686b8705f086efcc8a69f827b03511d82dcf622e60a2e3061053c34497026bf723aea5f5599cdf0e3e4befeb0bc87c90cd05e001f3b52bb090fafc07ac8b3f053cf73fdf0596d92f9580f62517d0be340242ea0128bd42f910d00dfc113005f150c032812740e58f2a7a01cf93ff04b68f2617b016d22b50d3a75b5ff50cda61ee131ed6370c1a5f5563f40978d9df4f01cfecef6783d6675fff1d03fe71bd8e9d86b26fa9bef529e03672574041de0362ef076d0209379af93a90120e650c78667f5f09784d3a13f01ef912283c1cae04148f37012b2d3a909583a7a920b7bcfd1450f327027a1724a1b2f276574075f126201c5a018bce5c0aecf26df6c2f2b6db0f9b0a7875f42ae04bacab906a47594eebb1796750142cf1b7a80d54904743010b7ff700791bd938d81590b7be0f9f6abff30ff8f8730924b40da7538155068b3b015f11d9057ca6dfafff84f9b7d1fd05e013fbbe3e01afc6bf7604ac1a790a94c4c7d7b9809fb402de7aed08ec3caa5d01b5f618f0bc7de805dc7a7d092c6f9b5f8165437d0478ded69d804e6f266049ff2ba0610bfbfaf10a78396de7314e6b66a49ece0d961f4e5841f10934f6e58d686005681cfaa754f42740cfe4e2936b83a24d79d768e130f6aee4603f073c827ed600af1dec15e70a580aea4dc008a20620a4a2c5bdc0f265fb0c48f8c9d6a1808f316c095811e35cc017d86bc0a7971ee50216cf8a005f1420df0398a01cdd0e044ceaad006693467d29e05bbebf80a2d0afb6f2a0bb14f0a4f742407c1c0be839160246226c00b53f66581370a7b52f20926f05a505eeb780a0f333f5a0ab4f042c9f742eb05e5ff700b4fc643117b03ad0bec07ed216025628b39d2e879cb10266018cb817cbad78c4f9686471bab10914dc5895769478b9c8bf65942572acb04c1f05bc38bc01bc62b3bbb565b546a36513fa57c028a423c0abade33d0115db1cc8d8e2684360fda0664bc0dcfb6d0129760cf834f9d9b78028ac019fd3bcbe2d60e11a3f6c415feafb17f0b08ccf808acaf1e453c07829dfa9c7d8572d20a4d6042c7f7228e059df07d0b08ff52d01fdc2a980e0ef05d4a77f02db69b426b004b2913bcb67815e27ff0888e45b41655bfc0a98e779246016e717d071d8cd2b010b5dd702be9f6df558122a585e1d5968278ab1624bc0f71be680d774e739e0d5d6fc1ff008e94fc0c0830780a08bea5cc0cbd858c0ca93730113e9f781dc5713ff07c46926b0f438fc04e87e457d02787b3b1d01b507ddb980c9819580956b1bc003c6d6b75c012bf9be0ab88ffa1558d9b7795a2bb06abc4f81d62bc77501f1910888b10d016fdf4a010b4e5d031e1f36316705ac97130b78cb3315f021383ff59e2dca5d8115f5c6fa1fcb35ccac01de780362bea755fc0129cdbc7dc829807f716b7d6190578cea2c26807f1f39b3044acb210bf6df58bea40acbd34b200516ff802702c702eed54f008fc224155866ef1f02045d14fd092c4da7df0013e9231bfdb302eac206f0796bb19f183116d95ce2008ddf245e0878e53b14d8a97fd702660b1e0888d34f8145d0d719e031665f765a01b5e59380fbb9a9809b800f010ba4f8613dc69aa1a0b67aec4fc0d2365f024b8f5bdfa267a73b1b0216cbae05f693ccaacf2c2d4754d2d6ce6521a46c88c4dd968065beac35cdca111134b2b29f293e164f80378d936f01897c07f87cf5ed09e0b316e343018babd502a6bab580cf255edf11b06a530ff8c4f1c19f8061f3d700f111d938831550056f092cb30f3f80d647ffcc05bce539053aeff3e7029aa4358165543d15b0065105f4de34ae09f8c95c603fa9c70256262591bb215b3c4e043c93b68a3e4f7beb6d45f68aa2cdb39a3b8bd2622ccf635e0cad599ce6a1fe60de89dd6ae4cbbf15cc5a01df9178047ce981ad63815dcbd47fc26cd228ba007ce2d62e671ab281baf044c0038077c0e77b1cfe030af20fd09195b30d01935932019359fe043416a5c01a1c1b6bbd02aa2dbf96de779a0b2c2b0fdf04ac72f620a0a8af0b580a6a2ee066c4c2210f5949f7fc51406928053c2dbe13f041ba2760dc5b8393dbcd6a91e73efc761d287983f763f15114639f4a5d0b68c5ec3c8a503b301bcc6ebd0ac5c7d19980b1b453812550ba0054f67d0b8fa0f99f80813a7e948aca6032047c9ee7762560c2c31be033fda60dc06cb068d109580be918e8bcbad811d0ac7d023d3196c702bbdab35f0135ff4860a7fe6d652ef4e7890f9b3eb802cafebda0b180d910d8d536e45c37f208ba17d8161b038195ec5d52bd1b77bc592d81b8b7bec38db50d65da30bce1d02ae9f2df92983740c69ca27c07f0418b7f563ccadc1f74e7562acb324e59cae50248f992f3b6e56dd9fab212f71ca5f519eddbdf02e2a310b0f8ef14a880f55d011f3ff2a3d4bec59e80f50ca60206607e023e27717eeb40486d732dadcf493cb904bc6dc862a0f72a675dc0bb82b1c04eecd632aa0c99cd324e2f02f651087802ff2d208266023a13cf02965f3b0246de65f914d0e09c0a48c25860219556c018d8880454f4be8fa4e7dbe86f40d1f3ccc00f5bf6ac9c7f0e54802d4bb302bec16d095485668d58b7467cf9354abe4cfb0bd40c8c3db044aeca2ca5eb740a541983e3ac0aae1463dffb4005fc9d082c810ea702be395d011e6359296009ea1f018d7801346c31bb11f028eb05603e72648b8a04f0598bbb39d0d30bceaf053c20da14d0ac59255d291cf22f60e4117426a0cad910b0f8de3d30f65a6a4bc04fc602fbc9d185c0b272e110fb4f36058ca34f052ce6710e643de3503e81bcb732776cad589d0d79c8540c818c4aa938077c2ad33a90fb0a54df96d975e10ba3cdec6aeb1041769403cba85a55cefd0be0b93f5f13d8c5fd5e039ed99b1740ebb95f0bc8ec3301af7c6307aa9cc33bc0a7b9ee7400938ba3888bf3fa6330bb13f0c8a402bcec774f0256c379043c6fab818045783853cfcaa98ddb5a015b7c09f8f6e48943cfac7812b94bf8497d2eb09fd4da820a259a09980cb709a49c696927d6f8b2cd832d6bb49a3c26f7772d5f9603942d3d8e2d929b72cc27ea53ab3e1be5adad18bb1acbc1fdfe89c00efbf70ef88ce5b32f01e3fa9e0026a0465def4056ee1640efcfd82c929b902f2c11cac579211cd0656954a2da6f01697a216095c41f07cf863d20f1cc7e11b0a4dd9680532f1d6c1f11cf611acfa841b40da4f44f6d2af5127c0bdf69c651620bcb36cd463c2cb746abf5f52e06b32b20212bcf37005ff76b7aefc016747a5be5cbc140c0e0b84d878e7be41cf08cb279c04b20a39207c0e78a4eb7047671dbd624855d7287b35b0a786ddc03237f41750d9073539b35b002962eb9043c5faa48c06284fb40eafbd815f09ac38f929273b668c4f2fe977cb9b19f840d48c2991da553057bb3e3e05bfc0223b2e1ac14d899de6c3bf0206270038cfdc9440ff8bde96907144c88b93f003adafd2dab1cbbdcb7b0b5c2c31de2d047ddd8fd5cd7faea2fc729e0b97f740a74c07e226054d6b6832f47770790fb914d1e5dfe7f9e4cd8028f01982e17f142770976ea7b0360ccadc6e0576089bcfb0ec4de44fb51542a6301ebd45c3978a93c02520f986f01cb6ca40e1e0efb40e65b240e5417df0381dd1326d697ead39a899fe51dd08d781d3717507d5aa9ec1552d389c022e8660bf0f8e80f00afc66f3601af0c6617404aab7eb301f897cf6ffcb0b9c31a50f80d4de940dfe1b4054a8706a8819b1fc0efa3d6ad76e873564a8b06960dbd7a1753ab0bfbb2a07f9a5b66f78ac2c533e0d3d34fff1c3c0ad70516fcf66585e5ffa70e3a9d0918ff7102f84cf2bb1b013de93d019f888d00e274b0c39986a063a1fc238175f1a31b01f71e2461083a96f63d14b0d69e1f565178226091956dc0c3b27a75f09f1c09685f76809cc0cd130157bb0aba6e18ba0a76a66beb80b71ea73d90fb40ae03a0f438fd13d889ddfc0295c337d03a7c19e443874fc0dbb99b0f2001a631e04de3fd06c0a3bdc8ee91bb61e15f839eed0029b39fb607069d4f4fb7ef892fc1d794cd0576b56badc0763a2f018fa07c0ef834b5fb7381d50e7b3590f8e37492d0c361fae1e0354c752e6045ae3b2027f73b3f53cfdbfa4a60a561f12ab0045af8510a7e327b11d07aac6ef0ba51a88318aab1097893f4b705f814f7a965f628e48b25f2cd3b50f0938d1ba0f6f5c63b80599c51cb1645cd67226db9d36e14ee3dac104e2f808a67283f962fa3aa2d581d283550cee577804fc85d5c0958b26c2ee0b07f80cfcfbe1b0ac8ca0a88793261f70d017caed75e23e0d9f83ee0053977c8fcddeb19e0796b834a96e0e1f0246091955ac072a71f40e1eddc42c0225ebb0e3d4b414d04ec9444ee4a8fa03701ef3cbf809a5b519b19db8db3ce1fb8dbc58d735f84e7a4000aef3abd01a5b751af803fa3bf79017ce5969b67a06364e8cc77daf3b8e3c6ae761c8aba15b19b7ba0f0ef5859e08eab2c67651fab94c60a87fb21c08cc3e86e0ff0c9a3f7af022b51fd898081f53b804ffe3adf1330da655dc003d50320f5a7e79503f9b2d702195becf402bbb38806029ad70d20f726694d404ffadac15b8f6d811d769a021e418d5f9cd71ff58d8080f9b705eb4bf9c5951e633f0296513814b03ad02550f93e1a81a5ba2d72dfc5ba29ca1dfc71c78d959738c40741f76850f8ca9337fc448dc5610c242cb3713307aa8438bd037c29cad4d2342edbcc76ba6f555f5c953923a9ad42893d82a2c1aec08eb2f303f8f4c19d5f0111d4086ca7534ebd4b7d32fe3fe083c91de033fdf28980914c1b40e1cfa504e4ed221590b733010b0b1480e76dfd2060b1a8a180f52ef680cac36122201c8e04fc641fa8fd71c701d0b0c5c42a9424f46188758be424f79bb3d35ac04804dfa2f68f636d028d47d0ad41396299d11b2b844935caac86d9628b90d97c6b807d5415b9fffb2de06d5302d4c0c127d0e43c1cb6cb4f3a9f159f7394ce2739ef17020b295be9790516410723c0a70f7e970262ec4f6031f6f701f8f4c1f9bd806a6b43c034023f8acf6eb9dd1358ab6edf905901cf82c9865007d1e727c54214b22af1a103f1d1f9d596d4413b7ea62571fa762860f2c68980efbef9997ad075af026a985f01cb6c1c0b580083180b51c8abb47701df39fb1030102312b0baba41eaf3f70733abb553dd8bcd2ca3d2d0cef142d73a7969a8a558ce720f48594e2ab5da212d63e6dfdef440c293bc9b0e68e83a6d5acd9f5645cee4d16da0cc098799804577e7404d68ef4f058ccae25a1463b9834fbaa2bf9e2ac676d6009f3035df1050d3ed08f894e00140de461d67da55fe58eed881f868d704d4522301ebd34502d6887806bccae9be05e4fe07d090fbb15d6da6f92ff635e82e7436fcd1cd2e9038ec00a9574a4f80df89cf0e81da77bae540c01c5a410ef7eeb473d36ba0b78f740d12ab6097b36eaccc6dce8124e53194d51f995706913dd70ee01965230096d944464d8f050c6c9b013eb7e96e53c080a15b81f561d67ac0a721edfd031eff1c015eb2f302f0acdc3d16d07a9c082c2b3bf24559d9ec0a6c8bb7a1800f26bf000d3fb16f0cad8007991f02d6ed590db3e8f2d4c718d967bc021464d4e809202b07632bea79b8d3020ac09f178ed9a96ebdc629903a2440e6f7c87b028ba0710ce46c717208f0d5aea8b57cc9d55f9ff440c516b630eb12b8964907f8bba4490bb43c959c34404f3d36b19a3f4436fdf5937520665c5f6e699a2b8236370434387740e9af8d6f04b42f7f020695ec395019d802c2cb18f4189b08ec3c36b8b8ae067e1f1dbc53f30fe8b05e0918b5770234fee8e65040149602db47bb2ee05efd5340f3ba03b4fce4f952c04fbe808e9bb3c6aea548fd49ded89a934221b53f17f08ced16f09ef4780c941e742380f8188c8740ed21e53bf5bed4f806f0856b5acbca4241b77e0128a4ec1ea82812968eb7c9d60158fa39bab39c2bca3e63f28615f5a2f3b96fd958401de45011417bb702be447227e023088f404d48d9673496d0b3facb54c0101a07cffddd130115caa680eec64cc007933f055605b77e719efbb6aee40aec273fe702ee0aae80ceb7f810d065e128fdb0e76bd0564b957ac0fc57002530be067c24c2d88e52e6fede631a01fef2717c09f80baac93de04f8cc61740ce238209fb28727a396b16c965e713a6b24d01b5c316e03397768e047c56752eb0a3646b400d1cf94f1abf8bf6a378cecdbe04960ddb5c5c487556e02e0574265e0414d35d01737853a0f35b9e898085043f04e4edb7805903a740cf4f6cf9c61530ebc86a982af5ac9c582fb8f2e7b8917d6a7209de14bc005ed46ff61d28d99367a0f1bcb5e730551e034711e0e170943af879dc02b587c3b9c0f2657c06f851f26d0195d20cf0f762e329c07ac183b115c2aaf04f6e8f8f01ff36faf808600dc4c1f810c8631e0f5a79a9c23d213341ff80716235cc8fd58595a270be10f01ec8c183eed67fd2f0e0ee765fc0adf913e031d671628a8fea4fc062b75c8bc2a13a16b046155b84b26f5bcc3e05cc7cfc11f0e6dd3adfb5f77206d3b9c0c2e17808788c5dfd0396a3db14d0815f00debbb82a0456d1dbc8ae15d8e51fed030dfb88accb526763727f9f2dbc1e8be63f0206517440e25d9627c0178c396a1d3cd6ad29a8434d47f7fc08488109e911ba4e1652933b40917c0a745e9f5a51af8b8ae7966312b96858916bccb594c38448de0362a6caaeb18fb24ce97f7071aa2d371ac0e701dbe4e2d5b77e18b9b329603ae54c6065ced6dd58fe7fa2b0208142d03176632aa0593b1310962740ef8de7b98029eebb02a29013539cf677021e551c09ecee64e753c09243c7c0887d4c3301c3f72d6f1b05eee991803ecca780f7eab980e73009e081db2f04bc299a0204ee60e487f5c1a4237b82d664fe5e6cc43e32822e8a6e1d08dccd2fc0276eadaf01dea7db1f03dc790e0ece052cace847f15edfd629907bdbb00bf8a94f38d350f479e57b0978176e6b1bf0ef37fc5ac02c97f334c8f6808aafc9db4a9c5d13629d3102ecb42a335e0a7371cb3f4b8f6301435639f5e5e8056bf7b70554b023019f897c7420920b52acebd862ffc1c11f21fd0aec4c6f7d8b9e2d0e67027a7d8980dbc87f5b50495f0b282fad8039de449007fff4e3424079990023f6d11c09b879cf0556e59c5812b6a93e4659031eeb97230115ca11e0b5f67502f89080eb1468fc96f807f070d8fa1550d17f035e395ec702d600b01eca723414c5e30ef0dec5fe9983cf13e73c342262740b708f1cd9bca425f093b535013fe901ff2ce259e2c0c5d95a6a2be04c3ba0f0a35c3bb0c5be9f3a6fcd437504b4346bf6c27fb5088dfde4a8047a6ff8ac54b67ad07db803f813813fae25a7200fb62cb4dbc2d7865a7f04bc54ce32a062658ec90068788dfe7300f409ad18e711faf800e751d63e069ecb2f3b1e428eb9b82aceec3cc65b4095f33ace6afef65f418e057c55967008c5d4aef6bc14b05ce1dcc11f003c015e2a236b925ab52fd5bb804278236009954b016b6690732a73b602c40a5823e241c0422d3930f672fb27b007aa8b5f81b5d9bf0b81b5fba7565ebab4f6286c052c7f7209789dbcf12ae0c6fb17e880ed3bc087be5d5bc02c47bad94e6d01f21558eb517f0123ffc948603f999f033e13f4e85640119b03345a51fde9c04e8f7a01d5c507e03712d74301abe0d540ca5885eb1b077f067b0f645e4bf9c5f903b3eb6b071fa4d700fe686fab16d0b7241b32f50c7c8bca1fbbdc0aa8c7fc27fe7870dfafd6ef70f63ba0f513bb70f0478c7e145fd3cd96805c01b75e5b80afaf6d0b3c769d86e16cec00fe93032b735d55e72c306de5a55399db59173054f419f09670f42aa0254c057ce6cd2a83504879176d1f0b5b013f9908ec27fdb3807ee18b80a5285f05d6c95bf84fbc98d699806502770594ec4d80623ad8be12d84efb5b014ba6dafd4beffdc2c1c90be00fedd713012365e78017d3624d605b5c39a8f16c006f1b8a4a602976f5077841befa15d03f9d08181c7726602aa475d07a1fe51a0dae04bcb33806bc54ced9874ae57a2ab0a36c7e02a9575b2381edb4e4d4f55eeca813b05e5f2260a886ffc4dbdbfa0df0e79667b1802f06ff3a78fde117577965f00a78a9bcbe74f0324736a8cc0d7c8bcef741ee67bd17642bea7dee0ffef7d9473ef2723b00d4cb216f35166ebf06781310d9a7f356c04f22c03bf0b785807df84e7d18dfc80feb4f7bfe1a0117b72ea0cf6fb5655f78381c12a745c24395b329d033eef380330d5d7c1622251cc2cd2b9f571b0a98ca940319afe20f32a0624a666e0f447aef1944363e3940ef936a220183c0ad45eebdca19dc1e081819ba0046c0edb3803a2813f0658546c0aaa29d80d51b08a9505df01c662aa0777125b09fecdc0aac86e948c290a4546ca702db627375b5fd50154a990b28fb87024a6505b47e0bf82760bdad57c0bbe76926b02d36260035cc607d2420b3f705dcbdfe1aa84259ff11307eec19f0f9956b998053ff06fc0ef8ea47c04f5240b5d48580bb79dfc2dfceda30adfeff1a07fb29608b16f0a1d557df02b65803bc1e3bfd10701ea780f71dee3c3dbc96da3c72f0aa2f062aaffafc6a197c1dd9678996e03bf513f3e1b76763c09bf9d33740bdbe7303dd59fc25023b8fcd7f60e75193511ac27b7d06f85338fb024880d45f2d768027e135e991fb9dd6f50ca881bc7560a7b784b69e05ef13fcb90fb328c9dbdc1787de1f005e2767c70ebe5362acf0cb3fd901fc53829b2f00eb8f4503f6518ea8d80e0a204eb807ba01bcdafab905ba94e140a98025ecd962592d593d4689524fe9fe45c033d8230177f38443a8837890f929a0621b0b180b772ae0936497c0d81f77bc08e87e1d0aa8fa8e052c87fb6f1f74aeb6040c8b262b433d4607ad10b0c2e1b580bba43d81dd25ed528ff5093b6d5b816db16915db4875a1ad7abf02eab117c0ebc2cd81c0b618bf0b5851f840c0070b6f003dbbf815b08f0f016bdd8c01af3e379e05f693b55cc04fac3218fdeb8f1d0a38ca9b803756b70246104d00af60679702f6f12ae0b0df8056e3db16f064e24ec06306d2c3abe0c1c681c08e72fa05e8d1cd9680a6e04960e751ae015e49af25022680fc0392f007f0a73d9bc7026e89af81dc4fcc13d99f8f5df999965eb165021eeeec01fe7c6ced5bc0891141ea4a6657029ed29e09682bc97dbd6cbbfa74f016792ce0be8118d34de2951fd62bfa742420d501dd13a643c0c3e18ff4c8356f8df4c8fd89f3a66fe1eded1d67faefb9d43ae01d781b5511a0f607550b078e72df023ec9a83805fc95cdfa8780cf469480bfadbe9e0a1851d5087862c44fbce68f6e53c08bc7b010587aec3978240f7301b3061c12ff90356159f065ebc13013b0aac685c09e8ddf92a645c650afa19f58ee7ded73a0e049de369541d1d146d9e29dfda81cd3466d52c39409c3c57629c8559a71ea846595677c3e2b11b078e70ec02382414931adda9cfa949c531b35a764ab49badb11d823936a2060482211141a0bdbe9fe9180a99053014dd29bc05aa0dd5301eb9e531a42ebc1e7089f047c49e0df16ace9762cb07dd8aad52b6041f6a1800573fd5a126f09af043c0d2c05ac9ffcef272c0842a514eecd0d0a2b40e3b4f1dae114f046eb341530493101bc49ba1c0a182c1803aa0cac251cab7db9bc16d84f8ef7012f1ec7ef02cba8e34a60677a7925a02ff5037873b23e14d002bd086881be006f4e4eef04045d097873721c09d8e9b380e7741b803727eb9f021aad7d01fb7812f0288b24fcf736e157c07d54266070cb18f0a71b6b7f028ef228b0a39c1e02fe36e17820e0270f02fbc9d50da0366a17f0366a7f24e03c1cd4249d0a68803bc01b9cfd1dc06f35d63c2bbd05dadf06fc36f26026b0532f5bc07be3cd9580f3980a68a24942ddae5c5d0b38b12dc01f525fbd01de8a459cba164938e3d4f550e5ead5c11b4fd254f72f57c469eeb76f67be853f425abf12f0509652a966ed8ab0cc3d09ff0807ddbffcd580dfbf9c5d0bb805640b355abf078017b1eb13c0dba8b34b806f840cae8f016fa3324e2cb4408cd8cd04d6025d1f01de245d13a745c9989a61e2401b35a4bc1435f370365f0576d86b3ff58e2112c3b1c09a465b7635401fb31e1be9510e81c34c608de73505b91cf15cea880a458fa1cea860cb9a71f4f744905aa0b55b819dfa412b609e0549189a02d6a47e14f099ea898017ba3702bbdac33320f126e948c053eb1301cdc99b807569df0596628b7f3b65ddd13520e527bb5f02d671a6ecf7053f19ac9e8df771683dec5a2e6f0434279651b1eaf5cb4b818d639b5f01ac081acd2f053696e58ea3a81abfbc10b036f62ee095f4590178a9dc9c09d8c7b9c0f6717906f87af447db80d7a7232eceabcfc8be59bf029ab5530105e803f0fa74bc10d0fd3a1170f97ea67e57b0f625a09d9b00dee71ffd08787aeea02af8d3c1071ddd0b388f43c0ebe4b51b01a73e17f0133f0fbf9158fb1070a6566e63d5c9a36b013bbd137067910a684ddf017f93d855803f1b3fdd77f0676c23018dc589809e2321e5b72b914d0009e0a3088a3307dfc7b180616b7e71de145c5d09ec4c071b80dff29cfaa9fbbb469b9b10408fe43704d4fc6307ff895f2d73aba33a15d8b5d84bf225f89ba20701cfa58e001fddb1bf0ef8ebc9b517406d949fa93f63dbd813f058ffd08114cb7c1f1e855b049deeb43628b77ac676f504e845c88780d6f4cac1fb631475356bebff3f6f5fd69d38b073fb63fcbe570620f0c83c0f861092bcd90633cf33bffe4a55aac22424dd7dbe73ee6a2f967b87c1de9654924aa5da08600cca482428699edc441e030d6bda6c251a16d0f6349b10c06ec9deb380eca329ac2793128ba5df2c20976eae232580e4d89eed48d859194096768d45a3929e8c841f06f06545ea8388368d62b263f0830031a90dfc285b403e228a9c7a91b9939348502a25db76c7e4f653812cb54f6a3fe8d98e73c9910564557c4c0033ac496cfa6c87b5f8c402524431b0806c9de70a6087b5a4056458bb5840927f0f1690c04ae483c628c9280e2ca07fc5695b40e2a84f0b48134031f461c2845e2d0b4846d1b7807c2414c0b45ff33a1690ae09690b48e3092deb313b5616ca0298a9d642d1023234eacc44cce4e99c60238004560e3e047832df51b0800cc08f02983c4c3811c00c9eb10701ecacc6c002526d2b176607cfd450001359c43e053063542ab480d48fb52d203fab153966bdf15ed302b2c65b7ed6daf558d602e2c16e0530fefa63c50232be0c2d201e9b50686acf9d514b0063c61fdf2d20a3983c28ebe23f5e01f995d002f25c660218331ecb18c0e40b5d01cc4abff4da00a660d9bcc30412ef3d014cb4f634b080be8e8b3c6c6bb5e363014c095e3f2580a92149ee2c2046c9318099384c58405837149a1cdbfb9b01cc85f52d20a1575a0063f9d33a9088251fcca0f5248031f4f9bc014c9058b3804c4fcacd258d23e05e0c20ef68a52c20198117018c3854ab02988cc0fbdc02d23a1e02c44570df6716d099bc893046218fa4c3d616d0c6e07d2a806cf8e1e8de3f0498a1e05db432699adcc73f0c2051524e58a7a140d4746d0111edae00812c56f08716904cde5180feb35898aa05243fb6b680e4c7441b28d2d2c0ebab056411fca705a484579490bc62195f44c65209e99a501239a521499bcf0f318ea9a44cf83fc8eddbd0eb438c018d51d2ea47384d0df4a0e5c87c54cc8b27f4d3ff14f3e9f909a90b9667cbff14506c594036706c584036c792074583856c7cd6b4806ce1e75a40d6e13c5a40df5c2f2640c28c511f169001c7b1800c27690b68092ac9bdd80127f02c20ef385a402f33f1f4cfc66dc2acb913c0087fd211c04ca6bcb42c20bbaa340430bb3378cf0224cc167e2301644f3f5c5e0430e622f62180b10e3dd70212359a9f3523614c5bbab8b5ebb1b4007d63b59b0298bd7c31358099add6c35adc5818f4aa0630771b08604c4e236d00e38e7605b065384703989067610131c19f029811a8f16c01617d6b0159aa7211402c8ca3fb2a1060d383ef169054382c205bf97c584056e79f057891c98371c3025a60ce29018c511a3d5840d6899b2b4dc96ef2dd9505a41d6e52004f80fa8b01c46c95e302f8026463169009aab100c64a75960288517246e66707e205bf8bd025c3676987ab079c38b9c5fad2cf05011e0588f72ca0aff47d2880b152e7bc00cf7a7929ca0701623255127fb380b4e3979b4bc5c5d76ecf05f0c4b53e3b16904ebef228537e4cd26102780f71a9502d584016f49b773cc7e523722f5e2c213524330192093106721d5e4a66685e8520cfd3b6d019e81441dc1f240578b6802cb7955ff14301429d4488070f297126e43b82c794ac6e917758032b91569cff296054b28018581107b27462605316907aa9bd05643a7f6801e9f4fc6401d95bb023c08bf948d10292ca7ab58078f4e6c292c6810f2c201dcab4d9e224be1482e62da07f257311c024545fda02883d7586064888ee374616d0baef3d0990948f788f0278067810c0f4caca990b33ab2874b93a01c6c036c6029855037a99890264ed9b56f58449aa387a45bbaaae14cbdf13c00c16bd8605c48cd705305bf8c5de04303e6eaf268099b18a750510efd3d1bbee10607ccbba16878435d22e0c600cfd59003358a43f2c208ee2c80232bd70b4806cf2673e62dcc0d8c50292d8ad081037ad069b02244c9aa1610189c4d716901d2e7716d0127431d7f12240ec6c012dfcefaf1690a0f9600169c95d162029efa8272d207be81e2c20b9f19c05b4718c9d04481987b56301a9b72c5940166f04027802543a16906497f988190a9a22527628685c2c204381a8070d05325374b2804c62bc58404adf3e2d206b237d01fae623250b48142d6269879373c2029ac273d1029ac2b4790ca10067b97d1a70f4f01a8824db01a7b9b1802488e6023cc93bcacf16d0ef888f2c20dd81e216902d95e5e652cff28efcbb01641dcebb28108d51a20d330b4884135a4076daac0a90902ab582b952b3136b2bb080ac9b9f08202924476f114b8027ef288b41a1714ede51b28056e4d24a80beb8f8ef030b888326da60063e07a101a4dbdaeb528098001f6293290810a757ee85063e195e45f8292a90220a1107af9f90e1551ea54fcea4fe4846804152175184620b83a794a670acc7ec841dc58a470b883f36b78014e80a63340249778fb505a416ceb1806c9f254fdf8e51fece02d2d34d24284c0950ea5b409a33eaa1e0c5ce3738fad9bebc98d560b9b80026a7d49a0a1037a3c79b002f666ce80a6096bbe8fdc4c3179b0bae1704b01398da3378499afc7aecd50232137012c0a4a12e8e0564bfa4b6006634ed552c200e5ac60262603b02188b9b590b60cc67af2c80d91fa85712c0135bd82b0a60ac5475660149a79b0b333bd4bdbb16d03f5b35df616c50e3c902fa1d95a305a4ea666a01b930e1948c92ac9ff32ca03f52922f252ba53ff2b1b2808c1e050b68917aec09f028efb8bc5b405c6b910f6bc79a3d0b688262470b68df52f7db22c098ad6ade02e26c060688c984ffab0524ebb4142026d3b58f250388a5cb552d2089bb850564dc8705242162088acb47ce310b48a946ce02e208182021dff1deb48044272f161047d15cc74b4cda6bf90224a58bc4396701195f3c0be8e712db5b40bba33858406b7620a24d3659fab1952da0bfb4f16001fda09a461c8cd5be88665b237d3604050294cda30c649d675554cc9af1332c20d16b4300c9d4205d1720344b43e5c2bc47a9827eef5b405fbabb13c0c440f1810031011a9f0248fac719889c525024f3d92230141449164e48f60652a55612adf442698bd714f5f09f5fa49a212b4042c686923c5b9f7e467f443b132f762818c9755c0d7dc3023289d1b2807ed83d792e64d765b7bd4f0bc89e6d5d0bc8f66acf1690672b4a48965f468fc002d24a7f6f0119b32702783258381a48da2c7e577f69f2c506235ae892b61232d616c0b892315700f1fa1cdda48900e3a035ce028412efeb5dffc2241925d95eed24c093a962ac08f02c26a797b3804c60ca8591b9902e3447038885192d2d2005546b018cee371e2d20e1cac1021204940530c6a0d5b7807efabdac002fa6778763017d73f99e0056f79f2d201bd23d086014f9d2b38026b91db380b892430b88c535d721aaee606801f1e86101c9902404f0e54b1f8b1690bd7db216109fce5ca935173b0388b9c82d2c2015664d0106e2f5bd3704088db9985a409aee562da0296ccaa3f4cc06b08f290be804916e53ac00596791b68018c7bd008f260f3310e059f230ef750b486fb9a3056414fb10201697ad5a661690b268115cb252523fb6b180e6a3f46901298b7e1720a9cb6f1d99154d5ac3f61e08e08b8f1b1729342ead23c5a449b274323f2714928f2b93c27a444e5e933b9e00e4f56b3b26b2cefff473195940b6328e0b90325996370b88d9ea5940ccd6f523d2063f6601d937411e141925315b070b48cf2e91a0d0978f7ce80138652b775e0de099fca916edd48bc9d4744f0298ea9faefe9554d254a8d6f30298b54df5ac00c6d9cc2c04e88b5f782e5b407cdc9600e2b1397ae7af3045964e4c5fd5025ab47b790bc8d6f08f02182b156b5a402a32d716900d4f1d0112f291b32fc08b00e9b605c431da0b2016c619c9cd917590598d8c05a4add58300be694ad43280e8feab306635fb9cb180ec4c3bb680ec482f576a353b1e5a403a1c7a16d06e8fccf2a48c33e18c8f169086fdf2f4491a44d5e5e6acaa3f162c206b673f2d20de67520051754737535780b84ef2a0bcb80045f3a546f79b250b68f9288a9c7a09f31d6903988f2c2c20654917015ec45c0cb702a412fa415544926d047c361ff11392e72f5b40b23d670102e9b9931809d01720deb5802cb6d61637e53f888589cbb325d7495f474728b426e75d9e2df9527a481ac993f349ebf43be4d9fafda4bef48a1e4e52c1a35829099a5364a5f43b86da9ea66c483c92876d8dd2c7c102fa2383d002fa236fb080ec2f26ea412647b2c50f1690ad150f1690a47dd202b22bb5dc0b5929a9b7ac5b4082f7b20564bf829a05f4773c988f04b24da4af1fa5673bc804a1014cedd7c902524d1917401200785c0a606a375a730b6835ad6837d0b37517ddb30026b359d7768c1be7e99fedee0530c6b1acedba6723cfb42b802f53bebdb40026fd939c0a100ad0d21ae591aa4bcda6dcbed15b677c10c00cc0a7940071017a72e974ed526225774b972af15ccd02fa571e5f0448c9001c1e2ca02d8cace6f08cce397d47002f21867e650171e1ba0258257cb2806c8b5810a02fd3d7ad8b0544092b16d0e6a2e509309077a4561610b395102014a0244f9ff4566623f716907469568047098aaa2252fe9374028faf05308a2c4ac89dc1259a6f0b903440c6029221917b091e92327326bf62541d6991c2e0498053dc02623e5f2d20b1ba3ca8e059f2745df915abeae9a2009e5807299bf7acaa0f9b1690b46dc302b267ecd102d223d3bcc337dfb1b580ec8fdcb780b83d090b4893d99e0081fc4abf6201d942386301d933563b9bbed5dbc45180be54aae88d8b429f9450f62a690960d31d1d0112925449d52d20d6212d80e8ad332e091088229fb41df38dce397e5100338ac5e44b49c564235a4700a31ea7a400463d3a0f020402a46a16108bdb136020fae26e2da045aaf9660119b4cc47441b9c911ec47d127e69c0b5b48016a9f35900a30da7170b68d64f72b7a41eda654999ef302361b32b404c3ae78fde0588bf688169be0a9094b1f26366012918aa1a40346a70b68068434280946c8ff418b7805430c704f0e41da78200be24333eb409f6492ba543485e804751d3c7370b48c1b24850f02440eed300a2b7b9a205e44ae5c282784adc40ad84be55c2c78c05a4f1b7dcdc55a30616108d7ab180ec095ab580be7431e3be55b141c60232a795b280ece63a16a02fef085c0be87714fa16906e057a7c096c9f1a2c04489a82b2ac00a61abbd3b480a4a11e2da0f5d6195b40fce49900a684a6abef25b896ab0702241fc50bae099092d65879b9305b3dd8d5de56904c49b2fcc517c093a9c5cc4a80be4cfae51f2d20657c5a6f83d4a3e4b5b3cf16900de82b16d0daa0370c22e0595c85d44680c4b3cc031d0d204629a7c786801c01a97790bb25fba17fb6f16101c99e9f0430c36bb328c0400c4a4eeec56a764f7ed66a76bc2c404c34bb75162021f9c2d6830564e6ac64016de803619d9450eafaea16d0e250ec0ae027f5b33d3f58404c4e42804080aab9d24152dfed50bbb4c155d68716d0b7ef9f2c201b6bb60530b2eebc5b40f61a6858403fec81487238303a57b380a8c78305c48e6992fbd61d6d5405f045e8badaede9bf98e2fc4b4e0053f69a9f5b40a6f3b30298ef4869a3d4b73345ad910081a429334b0106a633a97e2e7d124ba9cca809f024b1fa7027c02026d31c810524e2d3a3589f224f29c4908f50e4291b069504e88bd035b522f769c0915a5ab95b1a1bb4aa77e6169075c0290bc874ad23404280f6b305648ff6a10524f1ff2a8091a05cc90292c83c0830484a02403b8a7d322092fe919b3322e5eee4c28c04b9bba40564f4a85b401a5d7705301224014ddf4a50b16e01e9c12cac87a1001ffac20656a49e0e16d02eaddf11c04c4fc6f2169084485200d3dda3a2c57260971055df043029a484f6a506b60e25a5457b40de85246535a703d25b315b0f02f48575575bba41e0a7f4bd38da6c0dac123e372ca0f9701c010c41c1c802622d7d01427947b76f01a9cbd1b14768752e5e17c0f0114f0a109ac4bf1eb34353ad8f4a57005353139b08602aed839d05f43b127b01cceada5c4200a3a689830564584b5b407c5cf3a5660555622b80e9fa96d80860763391383b347d261cc73780dc7e622d8029573feb312ab4e6a22bbf42e39c6c002bbf927a9091b0bb36801894d6d002b272e941802763726602c4a496a5155a40f6b3980b109705425979723434ea0bcb3e0af02209c4c2d20232240d04488a8bffda1620255b6fc215c06c7b97980ad09729ce7a4c8081f8fc25e13415ca5c4141eb7e48a64f9cbca205f4a517e5c2c816cab25fb9390adea54442f8f0529296cbc97578be34477a5d08d097d01c727334884b302214fa7d894d039120b263d2cc439bbe907c5c59777214e049c6dba4087ff02c69a8cecc023a061a192091944ddb452cc9dd92e01d06102f38fe6a017d1d27b9f4209592da2f47004fca2b3fd216900bab5840aa90e4c991fd905d329f2c2063c3c9029aa0b6701a04627212090378928593671bf4c53dffe85b4066249e2ca05db8c1d102e2187d1ac0936044cc453090bb7d8c5940c617a1b01fd3d7e14ce5e6ae964e34ca1a36071608f5800377e7b83b4f1dbebb0bdc5ddfdd0ddc5de8ee86ee6ee4eec6ee6ee2eea6ee6ee6eee6ee6ee1ee96ee6ee5eed6ee6ee3eeb6ee6ee7eef6eeeee0ee8eeeeee4eeceeeeee2eed2ee2ee3eeb2ee2ee7eef2eeaee0ee8aeeaee4eecaeeaee2eeaaeeaee6eeeaeeaee1ee9aeeaee5ee5c77d776771d77f7eaeebaeeeecdddf5dcddbbbbfb70779feeeec1dd3dbabb27753cbbbb98bb8bbbbb843a5e68cca47194ee8c0c7de4d583e3c309e0f4e10ce0847086704670c6ea64a2cee964aa5e43f33a33f89d734de03cca179c059ca53a5670d67036ead8c22152e670f6700e708e9a2f3827386738174516e169381938d9bb7cc1c9c1c9c3a193221dc4179c129c329c0a9caae60b0e8175380d384d382d38aee28b8e0738f4d70e9c57385d386f707a86af0479a93468fe055fd1631ae1e86f0fcdd7279c879fe40bcea3962f384f709e156531387138092b5f705eb47cc1a1e77cd27cc14945f98247525c84470fa60c8f7ea80a8f7eab0e2fb82b5ff0fa56bee00dfe1bf2a54569ac0e2b35e3081d23838c7e3a577c79e16ff2e50df920f9f2463fca9737fea37cc19bdc912f6ffaff51bec6916312790d233cfee1f837f9d2f6eb17f9d2f64be4cb9b29be3286afb9952f6dbfe02dfed27efd97e42b54044dcdab3dac7a4e2327f7cfff205f8aafff93fd82b7347cadaef2e591d8ae6fec97b7b9235fdef67f60bfb4a45816c6c6de0f0d32f9e5fc97f1b12ff2e5ed7e191f992f6fff657c24bee01dbec897a28c7ea504ef68c74778349836e09da3f205ef72777c64bebcf4ff41bef4c83883978958ae71c47269f33f33ffbd732efa78235f1edd6d8e0f255f8aacb1b25f74cf33962faf70c317db2f52b492e68be42bea4fdcc8974796bea25c8aaac8974727f47ad6f2058fcc3fd14792d58247ffdd1a7d6c1bbeac7cf522f2f5f2eff2a5e5258ce8a31d2b47bf9cdf912fcdd777f9d27c45e54b91a5f97ab5f2a5f5f1bb7c91fd529491ea1de1758dbd7f83d7d37cc17b87f7a1f952e323f1f569f87a88f2a5e42bfe45befe8eaf883d12299bfc80df3fd7f6eb111e09b907ef195e0c1e5d471f5e02de8be22bc9f2e5a5e0e3c6defb14e27bf089df3d7c52e11dfc3efc01fc10fe103e0da669f863f8132562c69ff0a7ca9fe8aa63017fa6c83ac39fb3f1f20959c25f2993df83bf16befc0dfcad32f96cefe1d36fd18f1ee01fd978f9f4ccde15657f275f51166efc89bfb4f7fe59f8f22fcc979f66befc0cfc2cfb137e0e7e9e5d0abfc0cae8d33d97e097e157e057e1d7982fef157e1d7e037e133e3901694596cbfae8130b1df8f4862efc37f83d6dece1bfc327223ee13fc07f844f2c3cc3a75fa72741f69b5c7f7a333d307a5b127e0a0158be02078187c047103065419ff90a060842e62b182218fd697c1c1a8e66dff8fa4b7f3518239820982298315fc19c8d57b040b044b042a05cfc808748b65f01bdd29f762c5f015df101c191f90a4e2c5cc199852bb8f09d07ca7e0519e62bc822a0efcc335f414119af2a82228212cb6050e68fb302ba082a08e84f35047504f400124259d054acb5983232610149749cf85264d1a7da7f962f16ab993a2611a626113a669168e9feb9e68bee6722fa18bc923e22e8b23efa59d6c7e04df145c695087d47f071d5c7e093f922f922cafc3efb13fe80c747e22b7860110b1e992f8f787fe27888f80ae82788ca384b169f9074bc2048b2c10a524c5f1fe83bacda7d8f05adefa31f30657d12f92dfa03f443f487e88f0c5ff44e32afa9ab7cd1eb1fe2a1d13fc9d477f9eaa03f417f8afeec86affe5c99b031fa24503dd147c517d97bf497ac8ffd15f3d55fa3bf417fab280b99affe4e192ffa2cfd75cff6ab7f40ffa8282ba07f42ff8c3ebd2d8d7e8699f2576a702499e2288a7f91a4b59f453fa7c8ca2bad24be0aac95fd22fa251e22fb65f42be8d365d4fece5fb526dc9e8c7ee0f1feb9d1c77e3d6aeff909070b353ed2f726d127bda0c7de44bf85becb64b17c55d8def7e9ea3b5abed4d1d4f2a5842b4d43240b1799b03e691059a81e1bfb7e17fd37356ebeb1400525162ebfa34695ba92b29412e71d53ef7148843e51f3ce7c31591fac8f64f2fb9fe83fb0fdea8fff4a1f45b386e285898f3a361ec3d058b4d92fe7c6def74971a6ca99888c8f143f062b255f4fac77fd67254a4f44d9d5de33be66fbd58fa14f4427d8de9309ebbf305f6cc2b262ef49b2fa447d8abd8d01d88f67b2521838fc84061e063e7f0ffbf735359e26310830e8633060e1f2da7cd040492ac9f68bf4748441c8fa3818fe1d5f539614122b96ac51c46b8fcad11f0ed147f2bfb43e2ae73e10bec8def3458f98a6c15829dd9a091a4c8c7c5531985ef5519bb0c14cdb2f564692afc11c03522ebab7250be640e91d31e55d30505f38d860b0c5608701fdca813d8cc191456f70e2dfa23177705656aca74c3ebdf9c222462a495eeb20adf8ca6090fd3b7f62668ed1edeb3fe9a3f7c4266c9063f922fb35c8abc191c747b6f783c2952c3e9e492bc55fd5f2c58323dde13ee27fc5982fa66cc29245ea4c23e0a0a88c7a89e8c0a0c4ef1c9459a688237ead6040ecd758780775a692cdd9334beb80286bf24152366829ca5c113192af419b9dfbc1f0eff4d166bbac96fd07f92fb6f774891de54fd083222d7865bec8ff227f62d01565d46491a91abc5dedfda0c788b65f24628377562292afc1079bedc127060f1436b2de59db4423e3e01183270c9ed56b4c09171d71455c02831763c52e3cc8b08811532911b110cc1719fed0e1a8bb5f562efe5fc68f23e3558c22f16354e3c2dfcf155fa1a754d243a8e48be221228bf4310c54fc3844d86746facf1c308603f6276eec5787a90c4384c3a87cb100d230178eb451e7a89075ad8b70cc92154e104ebff215ce10cef9e1d19b99d9471e70e83b43fa9e25c21542faa10dc22dc21dc23d9b7c1a25c9050b0f7fe74fcc2201e3f866b8b47a171d37bf9d1bbee81223f6def075447862ff9e6e92e244365b7b1d6f2324bfd461fa94ffc5635978e10194d4274c23d4299d2c423a724ab9e80ec9debf212c289a88afa23a4ab7f2b5475866c5245df6346b69457a056155f1450a1b20ac236c2024596bb188f947a58f2945d35fc897d8fb9961e18b28fd85bdd77c697d64bec8bf0f49e6e7eaf1aa78880778c517d917ed7f91b31ab63959c8c2d561c10cc95475d89ff043959c20e2baca7123a921a67aecb286ef083f94704d982f2d5fe1e70d5fe1032b6cf8c8b1a4e7f23590f71f3e217c46486f2631a467f982308930c52246268c446c88bf8b1f4d487823596144eeee2611a3f1a3f2bf687c147b1ff527860e861ebb14c186f91afa143feafc84d8af618061df0406cf2c3e7ecca458957f3fa43b0955d83897f891481c0e992f6dbf3862253b9853e3e31ec31186630c272a42aaf3e04074b3c7dfc2708ae10cc339860b0c9718ae98b2e11ac30d865b0c771111fb253f117e63eacb20f8db28a94b3cf6e2afeaf891bd2165ef491fbd170c0f8aaf1e86474e4ee8f851c743619b05677812b258c4c8601372c6f082619ae91b92b3de657f8ae26df6efe31c6c0fb3ac95fc84c85aad594899fa9ce12b8f6181c74aeda30d8b6c3dc9680ee9bc8c61455146c4d1476a18d6316c60d86411fb833ece4c72c2bc5eedfdec161ffd746ee3c78ee8e3b065f3f71c0f91fdd2fe3d7943ce96472bd2c7a12bfe17a9e4b0cda2414c116b9a32fa148584c38e643be818923bfec49405799d5fc5b0cbbf159cb43a8b52d343229a44be88f49eb20c2a89c801a61a4c86ef187e6048bffb802109ef1386cf18d24fc4314ca82832f5b37ce9487b1299bf189a8cc5c41cc3c854c89d73c917b20b46b7adee90fd099d9fd0f67ef8c2f69e4d1845240595955e44f239555637ab8fc3241bf5614a48bcea6947a5550b3c2c8c40c2c5e23c72ac5bc7948d08f199af51c0fa38ea6334602de688b2cbfe0a594f32fca310a32146f4b63146f4b6a9d1caa63261bfeba375b8a259ad7ff5bf9ccf6bfcc892d262fb457c19f9627d1ccd78b01bcd315a887f4ff68b9339073661242c44d06889d18afdfbd11aa38d30a5be932de38818d971e035da8b3f313a18be3acab33b60748cf075c2e8ac4c84b2625e832f694474a731ca60441743bf98c7a8805111a31246a4aad022667cb15ff80a23c3629491e1efe78aaffe44e4cbf075f52774fe6b444fb58a510da33a1b9751438998c3ce2ac543a326462d951a1d88ff3572316a5f458c5492a8275d66fd7a66be461dc5d7ab1a37b43e12175d8cde145f3dc5571da377fa513509a04328878720fa89d107469f183d6044ec3f6144df19c3288e51c252f6a7fcc4d4448e936f4234f9e55cf1357ab9c94f8c92ec4c28f962ab314af10327b2e81ec8acd0c918261e727814232bee9d4cfc7854c1a3ca178e1d8c3df5551fc64e8d19b9f2e563ecb3968d03e5d9c731eedff0351ef0c938e46c8f0ecefd123f2432fce321c6238ce90be90d538c6718cf958809653fda7b3966c67e8d23e2667315d39fceadbd572e851e1fb57cf91999ef20e11a2fd4752f1565134519ddc0a74a373fb247dacf306b9a2f9fee64cdf3b563356b4963a804ea47c5ef2bff16f135def21039de614c7c1daefed70d5f478c4f7ceeecd50c489dc75612550ab9c6678ce927d2186730ce629cc3388f71418958427cb171f19b7c8daea3de4d16ffae63f1933f4137a0f531f445be68a8f233e2af3a1b8c4b6c7d3559ccda1bc6659eddd1a93eba8d3ed49c454cf4715c61d79fe48b3ddbedd5a28fab2c4d1c66976ff862e1fa89af9aa28ce850e1e7b8a1e28a25e78ec64d8c5b18bb8ab236c61dd1caa1a28cf97abdc3973dae9efd77b27e7cbde6bfacff25f1b6caaf4afc48fec4b8ab6e8098ea61fcaec6c737c988da63fcc19a38fec4f8415b43fe2ac59462adc3af246ee347255f4f123f8a7c557ee6eb19e398f22756ecf193534641083f15a22c81f10bc6498c5398001307138fb572e2f31039097eadcf89d630fd95b1bf191fd9ffd21e931e1f753eda8e8f933e6be564a0a6884a6cef394d7816f9923c720b93d00409c693980cd56cdb5665383a988c30196b63cf7c4d264abe76bfc9d784c43086c94cf21c1427794b71c726734ce8aa9698ac305963b2896825eef165edd7f7fc97c94388dcdd3f8fc48f3a1ed2f99c6bfc385493db1bf6bf265b36b7e485697f8242ee20c32ac911f551a5e71398ec22c3e2b364d3c86c1153aca405367303bac93df345f1d0e4a042489f592307f527f922ca2647153fd585328a37e8814d4e989c31b96092c624834916931c268a3252c9af7c8d239419fb753f36faa3ff154c245fa8f4f1ea7fa9f9478987b47fafe787882c722fd95f7d6035e499b4939aec20112b5cc9d2b327ac92594ee17b60bec8124d8a989424de9e94393ca46f9b547e962fa2accaae0c07462a4ed2f97efe397a037d61039326262dd14a1e2b892f97f99ab4bff95f3f7912d33f9e47ec7d7fca83bdbe43b25f245f7e5629e3d0ce6fcbfc909ef2a03be42172a75ccdd375fe71d2610f5ebb263cae5595c2aea4c470c0254d7c4c5ec98d6059a6efd1a38137e464e15dbef8e83265c4699064df6242d673a8024fd2ca1e26ef987c60f289c9036be5e4910dffe4c9f035f851be6ef285c3c81bee9f2bbe26cf32ff68e36de5aff2e078cd4ff4f47cadaa9f509978ae07a86a437e9d1f9ac4547295acf28ea739ae39d519cf0ff58f6a16b28009dd4c42a97960468335bbbe93174c92c6bfffc2578af99aaa67465fcb53e22b7e2ae45b4c1d4c3d1e0da73ea6f4dfbed24a0fd3c195af6968ee398cc4cf76ae28ea9dda58f2cef9adbd8f8e8f1c3f062af7b45629e91ecbd774c81985683d809eac9d8e543e3acef500d3318b98ff19991c4bb199e3396d35bfdd6fc199b3c9e7290295cbb69303a4ef2c62e3fb7cd1151365e103a613f9da70a81e0cd131c57486e91cd305a64ba5958f98ae98afe95af1b589c84b949df16da98475fdef9f1b7bcf531e365f9895f171bad5252757fbc5fab815fb45f24501330905cb97365e7dce4c70f666cb33439c8dd1de598673320387bdd9f08d834472f155be50496b2445410f60bafb99af10d33da607654054c29ae3ca248716537a66274ccf6ab8fcc4f482691ad38ce22bcbc235cddd9215d5c77ff457393f11cd7f0d333a3fa19c558afb49b023f9d5408d923adee6f9da165f6e50c194b4ac73552e16bac955c4d8841d99717e2a631e1ca72a1fcda19871d0c80e905f7a8db7efc9d7b48469993d9ba0aa1cb18b9a425fb01198d23510dd35d14a12b1695df1d560e122bee8b3519514c98af2759b17bb771e191f6d7ed5fa5f5c3f11ea7a39555f68f2d13c449af94772d9a74d35543d2b595b5fefdf490b53533d83ab92fd3414869e72be26e2dceb6203f62a7ef6bfae7cb9ccd7b48d69c7ce8daba2d117369d537a0c5d4cdf30ed61fa8ee987e2eb53092669f1e36d4de14fa3e41ffd092e9ea84b3c347d127b4ff190b3227f55f4914dd8bb1aef54fdd7a0a0f285074c9f558557931d05169fa3e54b1df4b64954e3d4c0aa42228ab129de1e1d95335cf983bffa952f1a7943b600ba44651a57633a597ab2212f982679ac64c39f62be6610d34e7c0965e3ab40dd891f7ff32a6c3d5387fd09d247cd97d8fb93ce47ab095765bf668ead37e13b27633ff3582fd8e7aeb3d34f22161c8c312af0f7e8a4204fe81a559df94a1927ca2c1e942fb2c02cf82bbe667de66b36604346668ef571a97e7acb0f72166236c46cc45a391b6336517c4d319b3153b3b952c92859ff205911f9a2f851f9ab268851f38fe47f8547191f670bb15f862fb2f7aa7e754542c7a1b5aaae5125bc435598b960bd9b2d39c00ad657732ea2b7549183a18fa735b74a1fab7fc5d76cc57ccdd66cf875c29aa52cc93f4403e56c83d996c7cad90eb3bde2eb80d911b313b3363b1bcaac62ded5c71f454cf135bbe878e8c6ffb2f65ee7ef49bebcbcad6752f572ca7e91f870f8fda9e656f5c818339e7d4c79ad7132768c93aa92b1a3b182dfd0bbc95bf4d5af8cfbdff25fbff09566ca66191536a8994a1e763e28eac22ccb5a39cb6196577c15302b6256c2acccacb156b66f0dff172b368e0c8b5fcfafe3a3f035f6aff69eeba38d7c71300499ef9092b9235336ab705ad92ff2731eac954f5414e7de4491fc25c4c8c853a98e479e5b241326beaea961617ff5e96b7ef537beaa9891d255d5189592a2287ec63b76ca6675cc1a9835155f2dcc5cccda98759462b6bf197eebb80e0d77d39fce6fec971d1fa5de44e757757e42d563aa6a8602bb14441991457ec6ec55954c6ed99bd70e57a8e6163565a48fb3a50a4b93928c26be665d36f641571b35f5bae407367bfb177dd47cf5307b57139dca6b997da8843531f589d903668f8aaf27cc9e318b6116575236bfc7d7f85ff45192abd3487eb5cb2266e61f5564a75cfc01c9f3508d924bcebb7268e2aa1ae7ba52559bdb19ab89b5e94d6247bf8a7c7538f461513db078ce12cadeefff9daf17759ec44c0d94fcd31f4a727798037387f99a7b98d36b80791ff301e6a1b262ed48623aea91fea1ea24e2df47e63b243f417ccdcd7a05aefadd897c910da2889a93132b95f66a73943388f300cf91dd8a7d8bf988478c2859377c29ff6ba4b23ae24cfc9d3ff15dbee6630ec5a309ebb94a8dcd27984f155f33cce7982f14654bcc576cc5e6eb5bc31f25e58f7c9193ade2a16bbd09272732cadedb12c3051ff30de65b55f9448cec44a0481369689fef39f5caf5ce4b65f843e6c2d27487afe2b57ee2b7fcfd9fe46b7ec0fcc8b9339db00e472a11a00aaee727c5d719f30be669cc339867d9f6b388cdbf197eab7de35fce6fe687cce28eb8ccd7fa59ad926cc5e639ccf39817e0859c1714c747cd03d11d9237342ff280c5e979953c20db3f29cb2819bcdee14be7bfbed7e7fc135ff3923aca9857f8d1ea69372ee72451aa624e6fa863dec0bc89790b7317f336e61de55ecc222a694dd85faee733f5d15fedfdfc552d815c61dec5fc0df39e9a97ce4854c8aba248cade31ff503eb77223e9f6c81552568cbd336df87fe1eb6bbddc7fc0d741f1f5c9ee188918a75e53f05fd5337ec0fc11f327cc9f318f611e575a99c0fc4519fe53c41dfb62ec673f9d9bfc97b5f7d3273549e1f0417ccd9386ac1416e004a9ae01e12551cac35e382a33d5c5c253c9833d4f6768ab1fe6b0f0791cd486ff7fc7d722c0a28fc54055fb34f8f2b8160a6c34162116432c4658d0a54eb098623163f76231c762a17c8bf6bdf1f177ff5e8f8fba7ec2ca17f1b558325f8b151f349ce90921364f6f3c4a726d085dc15aa6bce8f14eaaecaa8c631c51d243e6fcc10c8bcd8de1ff5fc957198b2d163b2ea66583b05215d6caf02ff65810a7c4dd89b5727116c3cf22b65256ec8be19f44dcd7afe7b7f598b6de647161b9a0e86f91c622c389048a69b57567eb30e4d8252cb37ce949dcd13b16592c728ab52e07d23a05cad56ebeb817ff53be58c4f2fc1a8e556c94e28475a0c3af3316052c8a5894b0a07756d8f06b0f960cbf765f6f0cff2c42dfd7f3487ec2c6438b2a4fea5054bca829e1aa73783c78112d2343ced3f7eaf6c8782d1a1c945ce7bde93136396becf78d30569994ff4f7cd1d16277474f59792aa947eeeb8214b08d45070b9200321d6f2c628b9e1231d28077a39551c37ffffcba7ec8cca719f9e2e3038b4f2c1eb078244bc413da7ae10a17843f71d1fc74a782e438df24b3969709703efabc2841a672874ae5a7ff7bbe9eb078e6aa0bd68692545873584294911cc4b14860f182455219fe2c1b7eb26264f56f788906925fcfadfdb2f31d59b53e4d2d8959a498af25b074b0f4b0f4d5b485f2a449e6f5d434afcbd8b1874dc45dabdd98383571595322097e270740d3ff2d5fcb00cb3e8343e5be92d51fa8fc1aa7cb77580eb00cb11c6239c2728ce504cbe975a0fc07be94ff75939fa083f571a5f89a6139c77281e512cb95480dbbf56a768bee995ec99b5fae79da55c780a4a75ce61ce71c34a7c69a2a9c56e997ffad7c3d63b9c172cba3f620e0a7c54e755ac5242d2c89b23d96072c8f2c62cb1396678e90b4885d55f24b4479731ec94747e78796972b5fa48fcb3496192cb358e6b0ccb3a72a597922b1a02a77d5343585812c6e9e11b7110fb53cb7aa281bedd55351f1f6ff90af2296f4cd73353e2a6b4094f194e08e73e2cb3296152cab58d678a05cd65584144a9ee74fc2059b8f56eb87ea917a5f6def535836145f4d2ce9f9b858b6b1ec60f96a26ca4a1c2a729ddb51e21b9d92e79070cb12371cf1ccb672bbf906385bffbf90af23f3b5ecb2b15f2a5f872e6cd9136bcb33950ee78ac9ea2fdfb1fcc09294e68123a4e5a3b2fa9d085fd1d50c77ce6fd7f30533f1bf281e22be48cad89fa06f7fc2921e5d0ccb3896092c5fd8c9e81b734eded650c5eae4a32d934c04f913cb1456c0ca513ea49a52a3d7854ade73e6bef35ff557fb7c4eefa1006e5c97554a6c072e3c4cb33bb9c5cac3cac72ac0aa8fd54059fd0a56213b16ab2156a3afbeeb0fe7d6bf37fa28fe6a97ed3db1b61ab357b19a6035c56a86d51cab05564bac5612af490227add450b95a3a1dc85c1825f5ab62f883183348e692e4f1bfc217e7737aecbe90447babeb2a259da818e9e1e8893d8cd51aab0d5644dc0eab3d5607ac8e3c4aae4ecc9738627fc917174f3caaba1a3b3ee698320ab6c9655d9db1ba609566ad5c65b0ca62453ce6b152b99d415d4f76b041257523cad8959f2a526452968b9668806787e8930372a66ccfc2f81ff03575aff9fb5591278ac81a5064b65202a5b3ace42a4e0b4a8adfb02a635561095855b1a2075fc7aac18ed88aee45fbfa09ac5c498a91236639fae13c52cfc489e3c87a2b0a62062a7e5cb51565f41bc45d172bba881e56ef587d60f5c99913afc5eac6769daee981dd5d1bfdf03318b36e72aed1acd2231ba7f35fff997c4d55368262afd5a35af095e4c184466d9eeeaef32c11cfd1f96af96457e5487aec7fad9eb07ac68a043c8e1571f48255921dd7554a85df9daf199e1fce4d3ca4a73c8cbd977e0afd39d6902e4d6b076b0f6b9fa56c1db0215bf7b11e60ad72f3a2054dceebd325f28c8972e839c052531e5cb47434d3dd17e588fca77c5160bf1eb2847ab5484637c56938923572fde61f3c0b41567f3d521217aa59d10dd663ac27584fb19e716c44269fc2efd933e75dbfa7f67f38bf596ff5753d32e9a3b41c5a73fe6b4df42db05e62bdc29a18a42bd862bdc37aafdce89a720ebbeccd93ae4573d0fa64ec192b966285d5f3db7fc397d4cb75a5d09082333fc6e1a1766b3853a20a75b8823bcf610605b3247adcac41b1497aca4b4e346507ac8f589fb03eb3c92713b6bea824621bebf44d9efa87f3c8fa5a93cff936dff1c2c968e62ba328cbb294ad732c65eb3cd605ac8b5897e0bb32dfc1af5db6fab3a590a50f36674313b1e759168832d2dfbf91aff18963ac4142adca3df2c027d9fa949a7b4f70393231b52e73428986cb7585bd1926b4640a12b2aa548dd4a28a758d4dd8bace5ed8ba81759393885ff2d43f9cdfc643a43e3affa5e7b7557da16a41b1e663ddc2dac5baad28a3df7bc5ba8bf51bd63dacdfb1fee0424b72325805ded47ab3f24da6d0535936f6861e593a46ba12f367f9e250f4c802b5fee468949badd4241d28ebd6faaaf869a2c2af374ee6ac1f9423a60ef2c5d68ff27ea6b5c6dfc04d1f12583f61fdcc2ab9a62f27061366c2ad7c75c47e38bfcd7fe9dc7164be43eaa3075d4ede93a20d5f1465f49ac43a850d98b28d838d878d8f4da09a0a2952583d73bcf24d97b3ea836d565b0c3f3df94d9f3db5ef7c493dd389edd430afea69e76a224addbc0e7136039629f24e892c923ef22d36219345be3e91b51962336257831c171bf60705e5276d7828df8cb19960331511dbcc8ca33f978cd80fe7dabfaf0b5f744b5abeb43e46fb59f10047d4ccd5b160dddc2cb159b1946dd6d86cb0d962b3c366cf8d71fa901a39b2e8d189358e1c0edc234dc687bd5ac3f78dafb55a32ba68a8787e2e3aaebd16f215c80ed29f14956caae87e36079928da1c55a2b5cf811187df7d6c4edc4d49dcd73aa73c596fd43af3cd199b0b4f856c88fd8c38ae92747dfce9dcd82fdd6f68a38aa323f64be61ffdbcd4e790c345e3ce2607e7199b3c36056c8ad8d01597156515256555d51b475531f37d96ae22c65e5e993d156bf8a71d76c736b52b5f831ae739161b55f2b91285a2f76fd4dc224b9f5240122e5240122b8a1649f5e8987f32654c16c9574349999a88e19f2e99a9ac4fa52e3d2e7eda34b1214173557a27c38eeb269241fce1fc767d87f657297854fd4dd8c4105fd1fa68f236754926b3d6614163ca48c448f4deb0e96143cfed039b4f6c1eb403c94a3452c3ae96620ab607cf92b0e61ac10795298ba9f9da2aa73778a56857156f76f5082865191ca5be4b6e92335cf4901e597cbef2a572f94c16851603e999a28fa9ae00a56ba3874d7cc5b14960f3824d129b143baed18ceb0fe7263f1159ffa8fa4f74edfa0e5bcfc4f5395bb0ebbc55553a5b0f5b1fdb00db3eb603a66c1b623bc47684ed18db49f4a9b2c3a5a325bdd28a6d3f5489ca1bcb350b97c764d15fd9ca44c31ab084b29d5262458ec2b5102cc6c7762a13b7cc5ac0b1f776c627f41ebf74f5ce283ce215051b1e61b7736c17ec556c97d8aeb05d63bb517ca98201e1e8fef94dfdea75be56cf3f8a3fb1d3f265ea313f543f2be26b8bed0edb3db6076ce92ae9e7cfd85eb04d639bc1368bad5a8765ed0e5146868ce7b45fd830f14a23b5be85ec1de9e336cf88f7a16d8d92a92a8f6832fce555b29bd829085fce4cf155e64092dc7dcdd7b6a8f82af13402071eda8f5df1a25eae70d8b11a6ecbd856b0ad625b132fcceae3b67e95a91fceaffdbfcc7cedd55f65cf58af479e2afb65eac955bddc82f9f2e9871bd836156574b9aea2ac8d6d07db5725655d8e96542a5dad545029308aecf8756faba7d91de350a9c9efd44998d18cf59438d20a489ac82ed84939ae6a164a4fdf6ddf785e9de46bdb53b5272fd8beb37fcb8b01569214e9efc5f92235dcd263fec4f6015b62e1095b42944bb18db3bdff5bbe385f38bef697b3febdb6f7816a596bf5719bb8aedfded2f525b96bda36851db07338e6a0ef21de49ca68e8a0efd90da496992e9d1ec07cc4f2c5ed128acab834af35c1cb1ecf5390459bbd894ce97584a3b39ab53b99c0a8aa0af1db6cc2882fd2001e1f954ad2098d034e36a2d14b4e1fe885acbb11e817e92e7653ec662c5c64bce8f1eb19363dfdc1891de543fc701ea9978bced7ea785bafb78ada2fa38fb25e816ca76e0943e246c86e85dd1abb8d5046469a9eea6ecfe90d1597b0091fb99c4a24ca2866a271803b0694d4444e970581b5f55da64e882c325b1c2a6a475fad85d40b637607e56dcf54616659395fcaf00f55d34433fdce511a194dee1248641db13b71bcbd3b6377e194cee215f4e6795a6670c5a8efaf3ed7bdf36ff9426dbf78d29ffbc144ea7336323eda7e1dba9e7ca45625efb2d8e5406ab52b6057549495b02b6357019921f2ade71b33315ee7ab5f3d480b9dc55275c3aca962f2917855daf9a2573de1247cc5787e93e46b57572a3993e9f45d8359db351559f9eb40c10b7f175cd1ba6b61e762d7c6ae831d71d405851fcb21763d4e19d2c8b87b37d3b7a76ba8f8c3f9b7fe265cef9b15ff8bfc09aebf8ff85f9ceafd503556b2be431560eef9d87da8a2ee13769f9c9cdb3d60f788dd9392b267ec625cfbba8b2bdb5f97cc0fc7986fca47213154914d58e6a495cefd0b5ff40c5e58cb389024194932657aa107f35562b2883bee9a76bca62bf4dae7213db314f66035dc3b4216f91064b61613ec3de54604aa02a523b31e7bdf7074fffc5bfca8e66b251ed2fdac82b72fe323f68159af50bdf62fd45d1f571e17c6cc36d8f7b11f601f623f14caf623b674e446a81923d50b6c2b53bf3a2ada8f99b8fd842dfdfcdd34ee182bb2962c627b1578939b2a26acc45e059d904de41e9275f16cf9c2f2d8cfb09f63bfc07e89fd8a0744ad863c9ff6c06491d9e2e4978ab449e3f6eb7fc9e7a814eb4dbe50d7fbb27f2feb3bb88243fb5fc37bfde5b8c54dc822b627b2b6d8d39defb13f604ff77962c5dcd353baa865332671ece89991a7dba9cc20329599372ad93743644d95b7a4648824ee484e83a25432f57985135b0cf2b3f669ecd57a987d16fb1c1b78226b9f17c9d264ed0b5278c2e1b412a56b61c0fdf35bfbf5657c64f7c731fd1e37aa72f5fdc6de6bbe648dc25efacb7163a027ec8bd897146565ec89ac2af635eceb3c57c2dd035626b113aa5938c5178989e58b0b7fc7124bea38519768e8f48e3661f45f727d7d93b1e04e6c5df52c49ae1bd837b16f29be5cecdbd8ab1cf4fe95bd0752c37d9725eb4a96b2ebd12a8a1fcebfadb7d2f2c50bff33577f42d793ebf58f6a3db2922fb5decae823f3d5572599341eeddfd46b0ffb77ec497f3fb1271578c49e7824c58ca9beac2919c528f6dac7d52a6ebb30b9ca2a39498a09a38172a47c31d247e248f345e69fddc69230c5c75aad026b619fc09ec43c89bd5adf71000e0e4f706857cbda2c52434dd6c13312348bcc72df3fb7ebf91e6fea734cfe4bfa59917c393b191fbff4f7d5fdd2943eeafd157862995b800d71a06b0d70e8e330c021c48190110e631c26384c653a473caf0b4b19458864d178ae7727890ae28bab80de8ccbaa5c8ac38ccd1967871e23642df84a68343ccc7158e0b0c46185c35af1b551a9d416e721b82433e03280c3f62a595f54efd7c2939b7a806bbd89e66b74d0f9afabbd1f1ed9de47fa3d9af151fa6d73368ed54db5980b338ab21d0e7b1c0e381c713845283bf3f41a39a8da4ef38c64454c985ee8412a498e5858be3561479574f6af8b0583244be84ead893e5c7048e390516465a53efa90e3cac2435e919550ae831a0dd9c06b357c8c4c62ff580910e18bfb29d4efd4476b7f55fa21f7aeeb916fd6f399feabbcf231aee46ba6faaf9e545718973b2a1d0a38147128e150c6a1824315879aa2acce8d514c665935cfc95d5592f8627d1cf3f23e51c977f66039535293d9755e951a57ae560287060e4d1c5a38b84cd6b4cae7cc575b79f0ed1bb248b216efc66645552f340b47ef9fdfac4766f91afbdffc2f4ff7bf67f952fe97b1f7aa5fadeeb76dd72373ffd550fa896abe0e1dee3e7878c5a18bc31b0e3d451991f881c3270e0f46a152383c723a4c9b7cd24ae2ebf0c42246864ceacbde6431b204d21cc6b1e2d3687878c62166c88af392ab590e8784acefe03a898e38a551037f23417f2ece4174bda8c857343f7178b9aedfe6965605497ed9f5b587242fb652fe84f413a5ab9f8eb95fda218523707470f470f4d511287376c0b18fe380293b86380e711c71cb5a555dc08ebe762c8e6a1683bc0a6df2592b0baab389aa52e2e175ae1250aa1be45195da1fe9983159c7398e0b1c9738aaf5c8c735d79093c1d265d1b3b948d68d4c8d4d91c4d4f4fcba7f7e133f7ef1bf88afa8fd62beb4ffa5fa6dab7e439eb5f77a7c14fba5f73b396e70dce2b8c3718f23d174c4f184e3f94ad991de93c631836356d61e69caac151bf7c4e40faa6a30a9095983b95a2130409fbe3f87631ec7028e451c4b389679311f9355c1b12aebf98e84d4af338c37d5845f44e96fea57953e4a7ef58bfd22f98ae627bec543dcf5522f581f5daefdef8f0dc55713473a77716ce3d8c1f115c72e8e6f38f67024e1fac0f113c7071c1f717cc2f15952fe816e40a70c1979f96cf5dfae2e1ba7ccf48a8a21873bc7188e712559091c5f704c4a9700262b851398af9373f518beaaa13d89b6d3194756767c3dbfe6efd9ff227d8ccea7913eb2fff5a6d70f493ee7e45de321ee8ddc13fbc553552a7be90f71f299af5380531fa7014e214e048e701ae334c1698ad30ca7394e0b9c9638ad705ae3b4c169cb299dd38e6780fc57aebe63d67c96263de1c8b1ce46f5831df28078dae374c0e988d309a7334bd6897e34cdbd61a617ee4241f4e9f5c8a70c1f379215adeeb592f577fb77e87e5651ff5ef2d14a1f391eb2feaaf627a4df76a4ffbdf473577c912c68f93a6571cae194c7a9805311a7124e744b159caa38d570aae3d4c0a989530b2717a7364e1d9c5ed9ea7b679cbadcaf229cf3ca243debc185f5aaf324395914d59fde70ea29b2de71fa10c93a7df2326496ac076ea47352ebd34e4f383dabf5eeb6cce68b7c8d6efa86463bc47c3bffd67f62fac4f9fbc552b5ec78d1feead5ff52f9c2eb7e2762bfd6d77ec8dade5ff98ae114c72981d30b4e499c5238036707670f671fe700e73ece039c439c87388f701ef334d77982f314e719d7f39ce76aa385945afe3c64037f5ee0bcc47985f39ac93a6f78a9e379cb92c56d01b2d7fe26d3f36dff892f347ddf0fccdaa91fcf4dfcc8269f2e7127f275de9bfa89b5aa6237f65e2d7957ebdd27ac8f3cf9da8bd8fb8db4d0391f787f18e2eb7cc4f9c47c9d89850bce699c3338139ec3398f7301e722ce259ccb385770aee25cc3b98e33dd7f1367fa1e57cd96b755fadb6383756ee3dcc1f915e72ece6f38f7707e67359c10831f4216491677b5a21ffdbcf6372111fbea1c448dfdd074cfb43df2ef9fdfe4efaff190ee5f68d68baa7a00359fa6ed3df14526ccc68fd65fd5f69e9dd533975368f922bece0f86af47c5d713cecf38d39fe8c1d05dbde09cc439850b707170f170f1710970e9e332c025c46588cb0897312e135ca6b8cc7099e3b2c06589cb0a97352e1b5cb6b8ecb847c765affa5971ef471e28eff41bb221e12cd27b28fcf6d7fbe7dffa4fdcce0f49ff68b65f9b6bfe4bfcafcab53f399bb08df85f7e4befd774a38f7fe4eb72c0e588cb0997332e175ce8ce33b86471c9e192c7a5804b1197122e655c2ab85471a9e152c7a5814b1397167731643534cdbf263eb730bcdfcf6a74ab6bdffa29fcd97e29ffebebfc90a99f90fd4ef4f868fb0368ff6b97957c8e1f6863af7a42187b7f717169e3d2c1e595f9ba74451f2f6fb8f498afcbfb2d5f245f1fb87ce2f280cb232e4fb83ce3426f8be392c0e505177a5b0a6920ed20ed21ed231d20dd477a807488f4906d567af46b3fbeb1e99136fc59be7e3b74bcbdbf938f36fdd2787c94fd6126b21fd8d77c61471d117fc2dafbf418e909f345f65edbaff454c917dded0ce9f91dbed20ba49748af905e23bd417a8bf40ee93dd207a48f489f903e237d419abe2a8334fd440ee93cd2056ec19a2e46bafcdedd8fc234f795fe2e51f7ddb6961e0b89f7ce6dff89cef7fa09e98f191d1fed7c2ddbaf8acd47abd2aa187bdb9a2f27cbf62b4d375046ba827415e91ad275a41b4837916e214d7f6d23dd41fa15e92ed26f48f7907e577c7d887c5df9fa44fa41f145e013d2cf48c79026514a20fd827412e9143240c6619b35e0e6f7bff6ab0d239b9d84b7fb51fca57c71323a929fc878d7f9b46065fb6d5fed9757607f959c2f365e26ff65f63b51fddc63bc61c72244c6472640a68fcc0019faef10991132636426c84c91992133476681cc129915326b6436c86c91d9ddca97e5eba824eb82cc1e99033247644ec89c9121248d4c0619d20cdb08ff6eff7b3b147ef154ff892f9e1f7abcee3fe4a7affda33339d5346261e36dae65277f55c7dbda5fb5fdd2ecfe43fe90e701fb3b64f2c8149029225342a68c4c05992a323564eac834906922d342c645a68d4c07197a545d64de90e921f3fe235f990fc5d727320fc83c22f384cc33323164e2c8249079f98bfd9a6cfffbd16dffc23f34138dca173df0a4ae2fbcd69ba87e433c3eeaf90ed3ff4bf60323ff4b4f3edafdd3ac7faff3399914b240d6e19653598f73d3e44f657d6eca9b0d90ed233b4036447688ec08590227c84e919d213b4776f1b77c6597ea7585ec1ad90db25beef01e843fec0776bbefeab563d5d49c4fcd060cf7cfcdfe7cb61fb29ddff633d23f47e7a3bfcf77e8f9349bffb2fed720607d24e122cac2056f44743c72794c7687ec1ed903b247644fc89e91bd209b4636836c16d91cb279640bc816912d215bfe8daf6c05d92af395ad315fd9bae2ab816c13d916b2bc9dda9ffa215b177f6c6cd950ca58ae3df8ee9cdff4eb607f82eb7d3391fcfdf04b3ca4f77fbcc9474b373deddc0f743e87f70bc8b6398f9aed20fb8a6c17d937647bc8be234b37fc892cdd2dc9c513b2cfc8c6908d239b40f605d9e4b7f1f19efdcaa622fa78420ec839c879c8f9c805c8f5eff743becacbc4f47ab1b9d330824c7f3abfcad7d5decffceb7e14de0bfbf7c317d51f53c997aa07907e43bc7f87eec61e994fb3f9afdc00b910b9217223e4c6c84d909b2237436e8edc02b925722be4d6c86d90dbb23f91db893f41e3e37dbe0e3c3ee6f6c8d19b8fc89d44be7267c5d745bda691cb2097bde77fd986bed14e6977fbdfffd8e837323e46d7f3e97848cf6f933eaa78e89affd2f343b99cd9ef44e22199ef6063affcfb5c1eb9027245e44aec7fe5e82315f6bfc85fa5f83157fde6df1b7ff58b7ce56ac8d599ac5c03b926722de45ce4da6a7c7c54c6fea424aba3f87a45ae8bdcdb3dbebeeba38d1f67e6afa3df5f155fb99ed4afdafd61d8f91ad87e3037f92f671fd5c76b7e82fdd5b8e863ee5dfcfbdc07729fc83d20f788dc9389b77f8a876ef922ff3ef78c5c0cb9387209e488f1247229e481bc83bc87bc8f7cc0c62bca57be8ffc80fb70135ff9f0de7e27935bf9b2febddd31c63aa877ce7f9edfb6fd7db5ff3538b13eea2d4f6cfe3ebaffa31e1c397e8cc8577ec8f1e397789be5ebf95e3c74447e84fc18f909f253e467c8cf915f20bf447e85fc1af90df25be477c8ef913f204fef3f217f6611cb5f0c5f69e433dc84fb0e5f63b3b995ddc5239a7b9845181cfe746efc2fe741fa6dab78c8ae1f8ad8fb8d2473beccd7f22e4cb7fe97cd7fe5b3c2d7dfc4dbf99c8ab73f9027960bc817912f215f46be827c15f91af275455303f926f22de45de4dbc877907f35f64bf3d545feed07be86a65fc9f86a98eef85fb35fce6febc923fa78cde768fba5ed3de757b7bc799c962fdf93f95a8ab7c390339f51f9b27c7dcfe7e47bc8bf234fec7c22ff80fc23f2049298c4908f239f40fe057922318502507098a9828782cffb5b1502771743a18fc200851085210a2314c6e698a0304561f6833e7e37e1ff60ec71cd4f68f9fa36df217cf517b7f1e3d2eecf67bae9ed6ffc099dbfff51beb228cc5158a0b0e4c8b1b042618dc206852d0a3b14889a034b53e188c20985330a17de98d5a737f066e5f0d2bc856d2183027d4f0e853c0a05148a28945028a35041a18a42ed0e5fe2497c3b6e761e1adfbceddbf9b7fd7ed57c9af0a5ea014c7f39c5d7c9b3f96899dfd6f92f991feadbfc3dc7db3ff145f6ab4074345068a2d042c145a18d428785a2f08a4217853716a5428ff3d105b59f74ff1d850f143e797364e795f7af2d3ca0f088c2130acf2890b8c55148a8d7171492ccf56ff2154646c62f9235fbfdfccbfaa1e72b5fdc1f3388ce7768f9627bafe787c87e8d1cf1276cfd84d247e66bf37ccfdeabf1b1904211283a287a28fa28066c6e8a7d140728863c39346ea8bafc37e6ab9f4371c83b230b5f0ecb57e8f0e6dbe93e9bb3e208c5318a13754c519ca1384771713fffa5fdd56be468e3c7bf4d5144f6e7eb5ffbf1ddd95f81fd8929e70b753d93dddf2ae24f88ffa5ecfd0ff2a5f82a2e515ca1b8e6d4687183e216c59daa76cbe8a230b5c69958d8b31a16ccfedbfe96f922b248b8fc1defbf5d3ca07844f184e2591d17cedf4f2f28a651ccdcf3efa34efc2fa4fcb95fedd77e7cd17c0e9365fb47abf9b46ffe97ad3751f3433a1e2ad241a291bfe1ab58507c15512ca15846b1c20d53e82856d55ad3b6b48be022f30fb528901e8ccbfac83bd7a6441f892fa7cb9b95176b28d65124116baafd9ae228b6382bedc01cdff21312724777aefdce5d94d0afe7a6df90da8ff5cad72e13a92797fc2a93a5ebe5a41f72f5ba5fb9ec5f3b60f9a278bbe8724ea2d846b183e22b8add6ff2f586628fd33b411183356ffc619790f152ac865adfa1f8e2fda43f947c6db43eb2c9ef7f2af95246bdf88ee2078a9f283ea0f888e2d36f7c899b1ef1efefec47f137fd906ff67f34fe97aac7bcc917eafa09af70677f513ddfc17ccd787064be9e518ca1488fddcad78be22b89620a25a04466e803d316f3e52fa5168ce46ba0caf179eb1ca38f258ff92af928056cc2481f4b7dde499a48290d500a511aa23442698cd2e44f7cd93d9a6c2474bb93e19ff7170d6ef7df0ee6117b1f4a3f51f2bf48be74fcf8653f695bcfa4eb31753e878ed214a5194a739416282dd57c871a1f4b2b94d6286dd8d094b6aa759183d28ef92a91f0aa66bdab1282064fd90e522c5fc457e920fa583ab23ef2feee9aaf134a67942e28d1b7d197677fe52bea52fddb4ebfb7e3e375bf80efebad92120f39db6b3ec7cca75df3390bf71a3feafdc0822a4a44411ea5024a45944ac6ff2276ca285550a237d4787175a9ce26bfd440a9c9b3d9a516f7532db928b5e1b464dbda4113a50eef8fdc1fb088697bcf7cbda2d4e5a9ecd21b97314d1efeb4bf68184954fcc3c8f88b3f71f5ef4dbdef225a2f67f2d115f1efaff19032615abed47ed29c952ef5507a478964e453ec57e901a547949e507a4689c4308e5202a5179448ef5228036507650f651fe500e53eca0376c7caa13a86288f501ea33c11f92a4f519ef12edc7acef1cffbb17ee1e83fe14b8d8f99e4cdfeb55ffc7bcedf43e757aff136e9a3def49de2215e12d6e7fd61c8fff247cc57798ef202e525ca2b94d7286f50de723ea7bc43798ff201e523ca2794cf285f504ea39c41398b724e1d79f5df02ca45944b289751aea8a38a720de5ba62aaa15e9b28b75076516ea3dc41f9f5677d346efa356b38ba994ffbe29ddd3b8fec2f3a7efc5a0fa0fd7bbbbe56ed7762fbdf47e63b543ca4ea31d57e732df1bfca5d94df50eea1fc8ef207ca9f283fb07c951f39de2e3fa14caf3194e32827507e413989720a15a0e2a0e2a1e2a312a0d24765804a88ca1095112a635426a84c5199a13267522a0b5496a8ac5059a3b2f9551f87919cc4f7fdf9867f737cdfefc4ecd7a4eb4dd4fe43aae464c2f1b6ce4fe8f57c2a1e8afaf7525f48f2a5f35fa72c2a5b5476ecdf57f6a81cbee673ce71548ea89c38bf5a39a372e1e4579e1849a39241853e9e43258f4a0195222a2554caa85450a9a25243a58e8a92af4a1395166f2e3af1233b19fea48f4313095aa6be74720f236cde398feeef9ebb912f9bffd2cd27a2f38f517d8cf8ab120fe97a13f257992f57e6b7753d80f627bee4732a6d543aa67e22520f70677efb11955754baa8bc29be7acade93e8bda3f281caa73a1e7e1d1fa35bd246735b5fbcad1fb794167bcffdd2bec4db225fcade0f5f643d9fa98fbee5eb76be43c78f9a2f5d9ff3b7f5263fe4a36dfebe427c3d19be9e794b6987988aa112e7d2920a51ff824af24ff6de18f83b9eea6f9db623fb95abfa9caffb19eafed1b27fc742ea7378495fe16bbdaff1bf6c3e87e5cb3b70fc783eb27c7dcf4fdccfaffe2b5f749e4215a83aa87aa8faa8065c46fe07ffeb8b34fd07fbfdeaf51da12ff539d2ffcbf63751c5e4667f18e1eb4bfd17c9d7b024fba745eb31bfd6cb7db35f7f556ff2035f553569561da01aa23a447584ea18d55ffc7ba580124286b75e7ee4f8733d931a1f23f9d5ec8dfd8aae5788d82f96af43f2d6bfd7f5396a7cd4f585bafe4be7736c3d53541fab535467c2979e4fbb2f5ffb9ff99aa3ba407589ea0ad535aabfc6dbff25ff6bfcad9fa8a99f50fd3a581fab91cd2822f1906c64a2e71f23f5be6cbfaa3b54f7a81e503da27a42f58cea05d534aa1954e9af3954f3a816502df210592da15a46b5826a15d51aaa75541ba836516da1eaa2da46b583ea2baa5d54df50ed893e0e32bceb6ff51dd50f543f517d40f5f157fb35badd29f327ee463f9d47fa9373f1aa8a1fb9a75e2e3a3fa4ecbdd91fc6d82f535f38d5f5d191fad5d0e86380ea13aa24083154499412a8bea09a4435851a507350f350f3510b50eba336402d446d88da08b5316a13d4a6a8cd509ba3b6406d89da0ab5356a1bd4b6a8ed38b751a360f38d4d58ed80da11b5136a678cca3fd7e7dc65e73f902fbdff90ae0718fb5fe787f47a2b0ab96dfdaa96af5ceeeb7e86ba8f0fc9d721c59150ed821abd6650cba296432daf5e0bea28a25642ad8c5ae5f6a8a25643ad8e5a439d34d5a1919a3a5aa8b9a8b5d54491cba4d43aa8bda2d6e54445ed0db5decffa381203ff1fed2c1ae14be7bfec7e0137fde5d6323eeaf95ab33f9f5d6f159ddf967c21c9d7f02c21914fb7fd8eda076a9fa83da0f688da136acfa8c5508ba39640ed05b5246a29d481ba83bac76faefba807a8f7511fa01ea23e447d84fa18f509ea5375cc78866da8f25ff539bb11f505ea4bd457a8af7fe66b2801d097aa1b67740d7a9cf0264ffdeddccc0fdde6276ee68774fdaaf65723f1a39e1f92f8d1e40b953e0e1166481f59c4ea1bd4b7a8ef50dfa37e40fd88fa09f533ea17d4e9af19d4b3a8e750cfa35e40bd887a09f532ea15d4aba8d750afa3de40bd897a0b7517f536c204ea1d96acfa2ba7f099af2eea6fa8f7507f479db8fefc537e35eaaf46f7228f78f957d1fb7a6efa7fd9f57cd1fdf9a2f69e8bbfb652bf6ae3c7e87af77e4cf2abb29eafca29433aea0fa83fa2fe84fa33ea31d4e3a82738d2ae935024794ccc93eca4d0001a0e1a1e1a3e1a011a7d34066884680cd118a131466382c694931381a3e63b76c2576386c61c8d051a4b34562a67ff135fd3db78c8b0f0d57b187fddad35721e59dfd158dfecaf10ed2f67f313b6fe5efc55932fd4f9098a1fc9ff52eb4599af91cbf55f8d0d1a5b347668ecd138a07144e384c6198d8bf810c45723cd055fcc57068d2c1a3934f26814d028a2514283fe5441a38a460d0dbace06935526fa9a8aaf161a2e1a6d343a68bca2d1fd0bf99adc569784dfc6cae14fe7d7fe13d17e3062ef49be8295a9cfd944e5ebc69fb0f9896bfe4b95fc36ded0e8a1f18ec6071a9f9cc9693ca0f1c86989c693f0453e6ae399f96ac4d088a39140e3058d241a2934c1755e4d47d5793d736949d343d34753a5a4fb25c97f35fb680ed00cd11ca2394273fc335fd1fa9c59e43534eec52c52a873ffdcf6c734fbf3d9f131ba1ed9ce0f718bb9e2b53f80cde7907cf17ced80d7236bb2c8d83727684ed19ca139477381e612cd159a6b3437bff145031fcb5784afe696f9e23a42faf80e4d020f681e0d5f2734cf685ed04ca39941f3e77cf44ff3db9aac7f9bdffe929f88ac77b7f3dbe24ff01059b6f539d7f191eba337522fb77986ff84660ecd3c9a05348b6896982f2d5fbff3d52c7fe3aba22a2e6b5cb4d4aca25943b38e66c3e4a343b6f7cd269a2d345d34db7f9aefb0363e5aab148d2227111bfff55cfc5577e7dcef6765f717b5f91cde7cdbaedffee67f493de60b9f343b68bea2d945f3ed96af1ef3d57c67be9a1fdff4317b47be345fcd4f34496ce91be8e3cf18844abe624ab8e26826b8fefeb77cf4d018a32ff5f7d6f6cf22c8fdf348feebfb7e4d6a7f6433ffb8912d0db5fdb2fe44b49e5c521464475ed04ca299420b68396879cc57cb472b40ab8fd600ad10ad215a23b6f75ff86a8dd19aa035456b86d61cad055a4be18bf4b1b5e2ba92d61aad0dd741eb7c0eb9acad2d5a3b4e844ddc5fe5cbeebff465d6f69ffc55b3deea6bfc38ddeafe85d77cf41656bebeacdf56fe4483fd55b2f7ad3d5a07b48e689dd03aa37561bec8deb7d26865d0caa295432b8f5601ade22d5ff457a2a38c5605ad2a5a35b4ea6835c47ee5a0286ba2d542cb45abcd7cb53abc98aff58a5617ad37ce4affe24f7c3552a6a2f79aa1373ed70fe75abe266cc24cfe5ef213b6fe4bcf0f69ff5ed9fb2b5fd67ed9f95a9eef68a0d5438beee403ad4fb41e145f24268f683da1f58c560cad385a244a2f6825d14ac105f3e53a703db83edc006e1fee006e08770877c443248d8fba28ce1dc39dc09dc255455eee1cee02ee12935684a91fd67758cf3eba57f435a8b6ded6eca7f3c8fe433c9966fae7f05e2ea6ff84a9ff927a000e1e75bd891a1ff57ee5d24f41f9ab44dc916e7b05770d77c37cb93c6d09770ff7c0955914cd14ba708f704f70cf702f11bed2703370b3707370f3700b708b704b70cb702b2c5ccc57156e0d6e9d8b70dc069750b84db82db82edc36dcce9fe2c7db9dcaefd4e7fc989c30fe2ae70b1f6ffacbd1f828fbfd0ea5de44cfd71a7b2feb3bc87e493064eabf060113e7bec22546de0c5f3db8ef703fe07ec2a5ff3e22c8735b4cf709eef32d5f44349dc4e126e0bef08cb79b849b421bbcb4caf2d576d0f6d0f6d10ed0eef314647b807688f6903b29fcc1de0faf8efe57fb35fce3eb9df9215e3f4464a97ec8d17e8fd7f5ee361ee27e1ddb9b7e1da48ffd2dda23b4c7684fd09e8a7cb56768cfd15ea0bde44545fd13da2bb4d75ff96a6fd0a637efb898a94dc701ed23da274e13ea452fc2d719ed0bf345a4b4d36867306edf6ae22ff99ce81cda6d3c741d227f3cbfd9ffd1ee4721fe2ab7045fdb7e56b2fe51ad1f12fb357244be687c24f992f57c0db4b368e7d0ce0b5fed82b25f240e45b44b6897d1aea04db75d43bbcef69ef8a278a84d1f6ca2dd42db45bb8d7607ed57b4bb68bfa1dd13ff4bdbaff63bda1f68531867668346258ce77c4cfc9ff99a5dd73fde78f95aca46664672f6cbb9b15fbade376aef753d93ead721f5d1da9930f6febbff65d62bb4b821539b687a44fb09ed67191fc9ff6ac7d08ea39d40fb05ed24da29748cbfda71d0f1d0f1d109d0e9a33340274467c80b443b23b528e1918bc6f5f8d819a333e1398e42068374c4605911fb49beec7aab897074e3afda1160f2d37964bee34b3f519d9f88f8ab663ddf47247ef4441f39ff7532f54c1f6ad745179d293a3374e6e27f69be3a0b6e0bd059a2b342672dfe6a3e2f7c55e86483ce9697727476e8ecd139b07fcffe448dc7c7ce91fdaf0e9178e6860064ec3b177488ee0c3a597472e8e4ff3d7eb413ddb3c81cf8fdf36ff5bedfd72bd87e56bc95fbfc66bd82edc7371d31417abdc2742c3de63bc44b91fd7bb25f9a2f891f957fdf29497ee2ca57199d0a3a55746a3cb5d1a9cbba2a5e275417fbd5211e49bee8cbe979289bd5e9a0f3caf31d9d2e3a6fe8f47ed6c7c9377db4ffb51d85a2d9b13be7dfd60ff17a85f855be78b19577edff75536ff22d1e32fdaca45eaef38ece073a9fe83c48bcfd537ee2ca17d1f464f87afe7fb57dc7722b49ace57e7e03fb1364d1c7ac2843794b16ddaebca33c6523e6df07c82c93455194bafbbd8e0c46b62e45a98e002480040e306e57f110e3c5f66bdcc1b88b714f4a84e358e1d5c77880093021450ed0f9ad1ea0b4f7665464ae5febef553c64fa1335bea1fcbeb6f0ef85816b54e3132deb3157a14ab17e884a7a0d4c1c4c5c4c3c4c7ca95cdd1a6fd7f4711b5e2c5fb93e3e88fdba5a631220e34f0e11bee6f9d54984498c4982498a49f65b3c54f4e76d46da66cb7bf8d3fedbbc93d2ff52fcabbabfb68a870a7fa286579e9f78aeee87a45e2e16b6e8c90a933b4cee317990f3f16c7f7b7ee257f99a3c62f224904d9e31e1ff65d418ac99f8ab93374cde31f990fc7df6285def7fac07f8f7fc13694ba9a4eadf4edc2a1f5dab0730ecbd962f7d9f66f2cba9fcaac897ee471611fbc4e40b9321267b98ec0b5e93839a3eee96af611b93434c46e24f1cf0471d61722ce5f5931344f77293c6a04c4e3139c3e41c930bb162e9c14e7f75c32a65dfea4d32e39fb6eccb7cb4e40bf37a8068cf881fc3bc9f4fd9fb9caf438a014ec4ff0a66aadfaae8e72bf9f8724a85440693784d4c580aae30b9c6e406935b4cc6984c30613d9a6232c3648ec9029325268c2fbfd9c2a4850923d5c1a48b490f933e2603d8804db01dd82e6c4fd593bfc1f6b15ac30e24596887b0a39df9d50d1f35fde6afeeaa8c36fcd59cdfb7e41b2ae2edd0c3de41793e6a7fd5e84756cae8ba72386ab2c7d0e625c526cf2dd831ec04762a63a77c7eb00cf60af61dec7bd80fb01f613fc17e86fd029b1ff81536bfe71df607ec4fd85fb0f9f9f760efc33e807d087b04fb08f6b19879fb44ba16a404ff4dca30fd13d8a7883ad2b36d9fc13eff0dafcc58ffae9e5cdf6f17f33bf2fcaabb57ceefc8fbdd4dbea1f2be432c7d57c0b22f042969731f0a1dadab907218dcd1cdfa48c8b0ed4bd857b0af61dfc0e6671bc39ec0b6614f61cf60cf612f602f61376037615bb019f4366cfee42e560c3d23d5873d10a4a6c0b19fd7df4f0953472d17530f53ff0f78a5df62c3bf2e83ef91e5eb79bf9aff282ebea7f93aaafb477d5feb8cc4bf6797c25b621a601a621a611a639a609a629a61bac2f40ed37b4c1f307dc4f409d367b579c1748de92ba66f98be63fa81e927a65f980e31ddc3741fd3034c0f311d617a84e931a627989e627a86e939a617985e627a85e935a637723fc4fae8f10fbdc5742c6eea7482a9bdd3bfffee7965456e272d2e6ea3e20e69fbde983ff49deff17b7f9acee7a8963e1976329d623ac3748ee90253c6ae81a94a724d79b5306dabd551abab560fd33ea603cc8019a9e560e662e661e6abd700b310b3a858b15a0966296619662bccee30bbc7ec413213be8a1f678f983d61f6acd6939033fd885799e42a6fb6932a9f63e6057fb97f54f3caabfb21b37f48c543557f9ae637718f1581992b933b662f98ad317bc5ec0db377cc3e30fbc4ec0bb321667b98ed637680d9216623cc8e303bc6ec04b353e1f99a9d61768ed905669798f1e75c637683d92d6663cc2698d9984d319b6136c76ca1d6123346a7899985594b9cd5595b40997530eb62d6c3ac2f07e5d5de6ffa583eff4fac30b1a1a49bfb1a9fc266fe5ef359e9fa2fed4f147c5682d76c2078cd813961ee60ee62ee4991fddcc73c908ed079887984798c7982798a7986f90af33bf11ee6f7983f60fe88f913e6cf98bf60bec6fc15f337091be7ef12390e3b987f881b31e7f525bdb3f321e67b98ef637e80f9615eff75ba907a260dd07cf49bbd8feb0163e9eb9b8efe46d1746d5ff1f16de6270a7f42ecbde69f607b1fb9123f462a65383f92793af363cc4f303fc5fc4cf236f373cc2f30bf94d07ace685e0b49e1fc06f35bccc7984f140913636a633ec57c86f95c7caef9421813d8ed9a2fc5ed3ab81206137d532b371d8af18583ed2bfec606e6fc7e4bea99a24785514b22c7ab2fccdbb29977fe94bfd79176ed7f0dde04b33abfbeafcfb7d2fd1dee50fad3b4bd57f34e2affbea82f54f6eb4dc9d70f78cdbb98f772bcd83bfdef784930c4dfd8cff13a6595cce44a8db5723ec0025810164e4166b5bbbf632b5fc79f0eca6df5399a6fa8d447962ff71069548bb7792d5c91af8587855fc36b11fc0fc857999990cc97555cd61af2c578e9faaf4528254da9e27824cdffb5235fb8aa677256752b6676ac6ddf97f539498dcfbde01b32f9c9cbfeed5c1f7f922f8d17873ea57cfd477ddcb3b6e823e3757a29fefd22c222c622c12295cbc75ffaad32e3288c0d8cfe89ff55ebe733fb6b8bfb8eaa1ea0eaaf6dabf351c917e3b5c8b058c9bdc6e20e8bfb3c54bce68779c0e2b186d7e249181d19afc5b3e0c531e3e245725ec2f8f28ac55ad25e43ab922f9d9c90fcc4a3e035bec4e2b5d247f627166f72ffb878c7e243cec7c5e74e7b5f127494b7d6dfeb317ff5ef757e559f8f667e35f727928a4fb4e0eb28e48bf1fac26288c51e16fb581c607188c5088b232c8eb1602c4eb1e06760a1bbc0821ff50a8b6b69125adc60718bc5180b4690b19b62c158cfb15860b1c4a221955f8b261616162d6130e1b5600bd0c1a28b450f8bbea18f032c812561e92085a4f077c957d93f647aade5e1981a31f9f6bdc22b7a35e5abec1fd2f3d3aa7c34e3a5fc8942be943e2e5d2c3d2c7d2c032c432c232c632c132c532c332c5758de61798fe503968f583e61f98ce58b5a6b2c5fb17cc3f21dcb0f2c3fb1fcc27288e51e96fb581ea875a8d608cb232c8fd53ac1f214cbb3aa7f68798ea56a575b5efea17fa8345b65d589a98f6504befa696fc48fdffbadf4706493dfb7acbf5f5ec9bcb9e535963758de6239c67282a58de514cb995a732c17582eb16ca8d52c9665ac567db57f581d6375b1ec61d9c77220f5e41c72fba7e2e247ad7fd86f951a567c03afb09ee7a9edb7f30d99fa58ce1faae2215dffe53f483ea70134080d070d170dafbe7c3402b5c2dab21d217a6944f96b2396c5fb7235927c4981af5a8d726568ac841ea67187c6bda40c8f2efe7c3f6426ec1343bea2ba62263bf6dfe6cd95fc3955bdef539e2fccf90b0b3ed1c683d8afc6231a4f683ca3f18206ff2f3fc91b1aef687ca8f5a9d657b186ea754fadfd621da8c59b43f53a32d6111ac7689c18eb148d3334ced1b810b0189415c37d89c6151ad792c26feca8cf312d57645c479ac6abd4c1edfb2d7c6966fd57d15f7ba98a998afe0ec94fa8f8b1718bc6188d091a361a533458dce6682cd058a2d140a3898685460b8d361a1d34ba68f4d0e88bb16f0cd0049a84a6234da14d174d7ef5a529b419a019a2c99b18cd04cd14cd0ccd159a776adda3f980e6239a4f08af241f9d3ea1f92cd41fcd1734d768befe215f587679983af80ffc89b1f4f309644abeb43f51cc77cffd5555ef6be40bdb79bc6dfa5fd7ce16ffcbf4279a6fca9f58a2f9bee97f0df98b1fb9ff35fcacfc2fb9d9be90c5fe57f3b3e67f9dbf8a3f115da2f925fc00cd219a7b7febdfce0c4fe2bb3ff1537751c527daacec97c9d7a1fd55931fb3e857107bdfdc17bc9a07e2df370f856442e3d51c095ecd23f1bf9ac78297190f315ec345e5af364fd03ccdfd2f9db6bfc236bc1e0a7fb59ffb5f1c3f96fe44f34c34b1792efddb1fcddfe46bc37ea5dbb0dbdd3fc4fed7c6fd90ce177a0f797de1d3f5b77999f7957cfdf778686cfd1bff9ecfc7e6051216ab4bb1624dfee35d23ddfb4dbecab6c7b48e51547fc30e7f55dbafeff5981bf5bebadf4a9f8fe24f7cd3c7ffa578a8166fd7f53160b06ed0bc952b6e5ecdb1baafdd5d3f61de0c7dbf1f0a8b82a7edfbe27c64f9926474c98f69177cb551d9325ad4e72c8af8f135cfe76cc897ce4f085eff59be74258054929f6fc14bebe37b262da35a019b1395a2d8513fb1328ebcc4c8e194a1f82ffb6ade5c394f5af062e355ce4736e36dc56f92d703b07fbf7e14fbd5b4d19cfe68bf9ab39df66b2ef6ab59c85773b9cd7e3d54f6cb8c1ff3feb44f341b88dbb29a4d3477f00d95734dcc7accefb7b67fab0728e75b99fd1d397f4e795f5bb35f4abe9a2d34db421adaeca0d945b387661fcd012cc0222199f89ac37260b9b0bc1a0980e5c30a6085b0225831ac04560a2b83b5827507eb1ed603ac47584fb09ed57a81b586f50aeb0dd67b9e9f6050ac0f589fb0bea439cd1ac2da9d8f369213ba31f93bdfe39ff88674fe4bf3936b3e7719f01de6f391cbf90ab578e84dfc2f6b1fd601ac4358235847b08e619dc03a857506eb1cd605ac4b5857b0ae61ddc0e2f78f614d60d9b0a6b066b018cd052c86af01ab09cb82d582d586d581d585d583d5873590d5025a849683968b9627e7639ce5fda22d5ffcd58b055aa2983fe70b37325fe5abc9e35156e76fdf97f3ad928a9fa9baaf7d977a13933f5a8998085730422b9492805684568c56a2568a5656ac95b1ee8a758fd6035a8fdfd6d31fd6335a2f68add17a45eb4de2edab4bf1bf3c95c50fd86d5cff5e8f69d647ffd835fa777e39ed7fdd7fd5fa870a3e3e33bf5af2630a6aad77b43ed0faacafaf620dd1da139ec2d63e5a07681da235928efeabdb7fb05a47681da3758216ff85f8879ea37591e7a3397eb47db42eebc54c3bfc89ad354cffc8bf57f539baff518cbd3b2cf3d1e2dfebfaafd655cddebb2779bddcc1818cf66d5dcb78c7d60d5afc6c63248cd7042d1bad295a33b5e668b1be2cd16aa0d544cb42ab85561bad0e5a5db47a68f5d11aa00db4096d076d176d0f6d1fed40ad10ed08ed18ed04ed14ed0ced15da77d2727534947ee49b2bb4efd17e40fbf10ffed7f7ccc4867c453fed0d7e93e2bea33e7f28acf15915f7b59bf3c0b2d8e0cf51f526d28c7c23f526ed27b49fd17e417b8df62bda6f68bfe7fd8fed0fb43fd1fe92fad536af3db4f7e5ac140285b7fca0e453721cab92b9078987da07681fa23d127b1f2a7bdf3e922b225eed63b44f76f2f1d579986afd30a513bbd130b3b9afe557cbf351fb13ba7f5b5c56255f79ffa3ce4f78eb5aff50166bbe6de167ca12ddcf27fdc8ed53b4cfd03e47fb02ed4b190bd3be927ed1f635da3768dfa23d467b22fdb56d1bed29da33b4e7682fd05e8a6f71c06f68a0dd44db429b11698b3fa1f16a77102aea977617ed1eda7db407a2b91decf4bfc2222711d7f33966b4981a31d0e6becce714fe979e2f6ac44362bc5c9dffca44be5eba159f28e3d5a1bc7fc8bd502599d7395f1a43d671d071d1f1d0f1d109d009d18944be3af196faaf4e22f2a57dd7e16bad5e4ed77fb18bcffe97295f9d5492859d4c8a7d3b2b74eed0b9476747bf4258afc14ceb5a597633a4c6ff6eeecbf3716c9c8fdbfaf9343fb9ae07d0fe84e2bfaff16d17f32854b3fb9ef03d761ed179122698ceb33865978d4dbccafac21d7869af750b5e2f086e15646b745ed1e14f7eff83bddf2828fc37f99cdcff32e247bb9c3f54dd0fe9fb5a962fb31e3398a1f3b1856fa8c38b611aa2b327f5d1ff052f8e8ab6e2159d0b2b728705f9405a624e59b8f87346bfd5af9aaaf72fcfc7e696fcfd46fcf86d5e93eeef28e7492b7d947e3e014b4f77ee1ca1738cce093aa78257e7ec6f789dd5f0d2733a3ae7793d39fbf79d8b42be94bde760bb739503d4b9466777ff6358943195f9fbecdbeb2e2facacbf2ff83ac47eb129bd11c834dfa3c96755f2dfd7e69d287b2ffd0a9779b37be716776cdac6e84ca4bfa36357f2d599a2c322394767b159efdb59a2c36f68a263a1c3dfd546a793df42325e9dae84dc9d1e3a7d7406ea7c54f6becb8bd075d075d1f5d0dd5d2f1719c5abe5fd769989fe7d6ff8ab89c3f190122ee33e4de155ca97385fc5bc934abe2a3e3ed53f94b6a51fa61ba01b4abf6837423716bcba09ba29ba19ba2b74efd0bd47f741fc09dd0fd37d44f7095d7edb0bba6b74f913ded07d17fe89bd3795055b4add4ef743a67f753fd1fd127d64ffbecbdfbb27cd7cdd7da9f7edeea8f7dde848d8b84fcb0c347fdc1bf769d2d2e7e6fe97ae270f3deddc97f64be7a3a53e3aef777f35fa61caf94373740fd11da17b24fda2dd63c1ebea5ee4ab7b82ee29ba67e89ea37b21c5abdd4bc1ab7b85ee35bafcccb7e88ed19da06ba33b457726cc4c7bef92cfe9f2c72ed0e50f648c9a52cbaafdafc987dc6f772d414a27bfbc78e77d5a5ce8d70e7ff5c77de17f95f315caf97c8a1fd3e8e77baefc55c5e79efb5fae93b7a8957c0aec8875198236ba1d74bb82d7f597f4f39db0d4f4d0eda33b400fe8117a0e7aaea42b7a1e7a3e7a017a217a117ab134cbf612f452f432f4566ae204bff90ebd7bf41e8473a1f728f5850c4aef09bd67640fe8bda0b746eff567f93225cb942fb5a92e25931dfb6ffdee66bf82b65f3a7e547c30d5fc34f7a4983ff452f1c1687e1396b2de1b7aefe87d5478f53ed1e3d7a18493bd3df4f6d13b40ef10bd51d5bfdd3b42ef18bd13f44ed13b43ef1cbd0bf4f8d3aed0bb96aab9de0d7ab7e88dd19be0e82de79fe8d9e84dd19ba9962bfee4f94e7f75a3c1ca2c874b0ade93d2a86dd99778a59bfd69159fd5b49aef6eded7ba3fcc3b59b18c2c44be7acb3a5e0df49ae859e8b5d0e3539811e9a0d795fe6df6eff74fa49ca2d793dbd95e5fc8c9bd4be1bcef0dd007fa84be2322d677254eea7be8ab4a7252fcd1fd00fd10fd08fd5826b1fe123f6e9445fff3fa68753eaa7ccee7ba56effb7d9ea1ee1f52fc85853e9e2be3a5fd55c5cfc4f6ab9fe02d455ff5d76abc8e46e867e8afd0bf43ff1efd07f41fd17f42ff19fd1721e0ebafc59fe8bfa2ff863e7fe09ef42cf7198b4ff4bf54fca84ac0fa43f4f96dfbe81fe4fc13d617fa8792f9eaf38f382a9cd59feeb7a3ba7c99f6dee8dbcbdbdcb7ec4b7e0083bfb0bcef70f7359f427effa8f91eeb7c1d798b6dcea750ccef68dda27f8cfe09faa7d5f9c8fe579fd739fa17e85fa27f85fe35fa37e8f39bc7e24f7c59e84fd0b7d19fa23f439f715fa0bf1497b5a3e77e15fdb5fd06fa4df42df157933d494bf45b52c8da6fa3bfbb3fadd4c7741b6a7fec7f14fe89f1e67c64cd7feff4f3f9c84a1ff3f3b1dfcdfb61a45f619ccb97d7cbedfdc15c323c6cf5fb3df4fbe80f727f55fb5f036040183818b888430c3c49e7f3f9a8e58bfdd5818f418001ff5324cd4332b7f02df757f550a69b330c620c129942c4a00c520c32046a4ce66025571ebff8f769bd1ef3fbfd50565c0b6dd917f3c0cafafbd2bfd7f1b6e253d0fdc8553e5af50fe9feda9c4fa1ec1f626514be6d5fa46c7087c13d060f183ce67871bc3d78c2e01983170cd6327870f08ac11b06ef62bf4aff7ef081c12706fc09c3dcbfd7f15085d71e06fb1828576b70286302344083110647bff9ab658ad9e47a29bf1e16d98bed7b239f53ce1735fb1fcbfcaad90f53f53f16fc26e53c0addff38389666abc10906a718f0e39dd7e2c7c1050697185c61708d0143768bc158cec7cdf8f142cd791ce4f1a3be52d3fa389860604bbffbe9409cafc114831906730c165235c748d9fe0ff526a58ac5758d338dbaf995cd7d61bf36fab74b7e4cb6f7e67d5a79df51c4db95bfaae7cd69be5acd7f3f5862c0afcdbc5fb486972578257d0c5a18b431e860d0fd3d3fc1780d7a18f0770d94009124ef678fe2ac8ea76c47f1d18094fbba7fe8e7dba8670a0d2b961a766d735fe35fcdfdaf959bcf63d5f30cd97ea9fe0e9dcf11fb55f27fb9061f9fea77977ca1c64bfaf9d8860bb319c9bc89109d5006181bf24588f179474808292123ac7ec94f88fef1fbef090f8447f17b059627c233ac4fc20b618df7de2e7dccaf1dcd9ae8ef8ec5cac85e6cee2b7eb9c2deef57f9afb23f4df3afea7c0efb5f7abe82e213adf8b6957f9fe7579327958f66d77785ab03c2ab347d0c1911068b1fef9df021f275cc62c0cff94532807c8fb02ff9e80dbc2a7d14be349229a2878411128e0f8ee47c3ce26f3c269ce08aff1ea7726bfb4b7d749905ccea3085f56ccff67d150f55fda2de9dc844c50f3015f9d2f9423922efaafb21cd875cf1e7f8126cebfc97e4a3f98465d93923e1a6bd20e1276469b92645644218b33e1226701b249da053912f2b22cca43166a8ecd7b0a5ecfd92c0be8543d292c07b7e7f53ba460f6f64c442f42489d6c9290b9a94e0ebc9eebbeaefbffb5f26139fe95b6cd957fd0a9bf3f9ca78a8a82fccf3d17a3e321f91a5bd2ffd553defa4baefe0a880d5c722b9686d93a4aebb1c3462ca5f61a406225ffc54ce278277512bf9cf2172893c229f28200a8922a29828214a8932a215d11d0e5f89ee75ff23d1033a07448f44fc09cfc262f8277fa2bc2532335ff1af7b831f53df7798f5e4457d8e393f0dee1149ada1c95f589c8f25bf9ce25f15e1a2b578eafeebcd7a44c40fc9d1d20bd13bd107d127d117d150e65b65d7789811ed11ed13f1c31f12f1fb8f307f2662504f884e89ce88ce892e44b258fffc451e421e5da3d920ba24ba22badec9a7600e6b5ad53dd552f5ca7b90edfb6f7c0a3a1e32cfc78d7a5f937f22e7732ff957d9de3328372c5c2253744b34562cac2c2613e94d76ee886ca22911a333275a48641e1cc1cde030284b227ef2269145c4dfde26ea1075897ac46e7083256ba05ea78c03fc58a89b1894d12b3af72297ac8fc968a73e9676fddf30471bf163c1875cd533315eaa7fbb8ab7cdfe5a83dfa4f0273ed8dedfacd7b02fc871f06e93e392e391e3931390139213c1677118c16b911393939093929391b3220651163ff3835a8fe43c91f34cce0b396b725ec97923e79d9c0f723ec9f92267487cccdd7a395fed317f7d9ff817eefa02d6ef78153efdbfe78f967c61f33b9f5579df91f3d59afddbf9f998f3470b521e3fcc213923728ec839269617e7949c3372cec961102fc9b922e7fa66cdff7443ce2d39637226e430b22c2f3372e6e42cd45a92d350ab498ea51643dc628b47fcbb1df2b774c8e9121b5695ff22a74fce40f857c71c3f8cc8c51ff08abebdfe23bcf4f9b871df91f3dff76bfeaaa2d0a9cdfb0d0fe58a88a580cdb4eb90eb92ebe1e8815c9fdc805813dd88dc18872fc4e6cc65957c2737237745ee1db9f7e4f23b1f71caef7c22f799dc1734f9fd6b72f903df78611493fbaed607f62fc9fd24f78bf82f9a5c2bbe470847edf50bda7d72f7c8dd2777c73c8aa2f8ab4a0486463adf5cc94ffb7abf02e325cdeedbf94445beeafc3932ac3cbc657d24f790d8dbe8f0631fe16c48ee31f1813066384ec93d23f79cdc0b8d17b9fccc57e45e8b83eade48bd9c5903707a2c2586c356ad12a02cf965ffcbbd257683dd89dc6f5f4c544ac74c10eeee57289d2cb31233a90b5d588fc037f7757fc2ec4f2bfa150abc9ea539adea47d67cdb0ecb17b936b9537267e4cec95d90bbc4a7456e43e1d524d75278b5145eed3a5e1dc1abac27577891db15ce2f8dd7fe9922f7fd28f97d4bbcc8ed49e5aadf90fbda7f8057b42d3f91fde5665bef0d3eabb27fbb88b795fd32f84d0afe420469a98fe4f2c9c50a3290df8add26c64b46e835345e68bfd7f152f2e5b9e47935bcc4a7afe3757055e175f0a9eaef3fc9f3c90bc80bc98b441f192f625fba415e8ce3297909f1535ceca8cfa9f771d4badeff91fd2af0caebbfca7aa6325fc8f69e21738b79d22a7e24b1774bf256e4dd91774fde03798f1b786dca97f7f41fe4eb82bc67f25ec85b93f72a7885522047de1b79efc407f4d8268ef667fd3fdc6f9bf1d0f77ed11f9bad8a7e3e2fa9eae5f47d87aecfd17815f9fb7c7e6dd5cff78a17fe5dbfc81b92b747defe76bcbc831c2f8f353795f391e56b032f2d5fd2af50da2f150989fd3a15f93ae49f3222ef883cfe76fe539d8a3e2a3e05f2ce609f91774edec5dfecd7464e35ae23f58b975ff4232bfe9cfc7e3bba26ef525492e3ed7a3e470e471d0f315e6ce6bd2bf2f8cd37e4dde2f4b5869737266f421effcd595366357dfc265fc4c7c8018b0f7f2f0b6c030bfef6a630f1edbde578ed9f63d821cf42833f96a16f93d711175ffb5f5e97bc1e797da108d8c5ef5bdaa38db5e155fc5a1fadfb3b36eae58a7c74ad7ea2e0eb40c4180de4d7e038cf7704afe3421fb5bdf75df23df27d9cbc931f6cda7b3fdcc46bf1427e447e4c7e427e4aec3ceb64b42627d72dc9ec2af82bf2efc8bf278e5ef5fdd0e503f98f426635b920fe13fa3be60f99fdeef10ff15064bc61cbbed2c7aaff71c58ffaa2f94dccf9db85fd127d247f4dfe2bf96fe4331c1f527c5fe085f925f99fe47f913f247f8ffc7df20fc83f247ff40d2ff127c83f22ff98fc13f24fc93f23ff9c7c7e72fe107edb3586c3c27e9d63d023ff86fc5be288357a927e3eff5ce60f6581cc173d7d245f92f73bf91422a35fc13cfbca8ab81f3d89cade0bdf9071df91f70fb1fd527cdb793d4031bf43e70b155e36f9532c1894993477b03efafcf00bf297c46796df249fa5ac457e9bfc0e260c4737b7f73e3f769ffc813c4240143814b8147814f81404c42ed5de11051105310509f159bc68c865ed9e25f2156414ac28b8a3e05ecfcba440981e2978a4e08982670a5e7e96afb4ea54a8f16d87753a9da4f6cefadeb0f7ac0226bf4991cfd1f11005eb2a1e92f3f19882570ade2878a7e083824fc12bf8c282df39a4608f827d6205eff1eb210523e2a03ab8843b85d7a180bff704fd3505a7149c15789d537041c1250557145c537043c12d05630a26c4a198f5c4f245c1943896189d5030a7608170908f0c28d7c582829df361aacec7d5b7fcaaa9953fee8df8b1a85fadee3b34bfaff8139766fd44ae8f418382260516052d0adaa28f0163d1a5a047411f2d3e5bf72465c846dab324d2669f3618483c243f9d2874287429f4d4f2290c280ca50ce2f34e464a2797b8e95118511853985098b288315eb85a529851b8a2f00e714b4049bf28bca7f041bd3e52f8abbddfc8e498f6eb7b5cb9f9fa7d3ef27e553fb1d19f56e6a3a59efc98c2670a5f285c53f89aeb63f84621c3f141eccdee8d24ab13f2c30c853bcd7f85c7081e0a6ae11e85fb141e10c706e148ad230ad95168cb300a760bd61da907e013233ca1f094c2330acf45bec20b29f9bde28fbda4f08a42b97fa4f086c25b0ac7a292e164673d932932713d836aaec410abcd7dbd3e87f551f3af16f5be793db9f2ef0b7f6251e0655338c54748e14cec7de94f84730af99505811fac49a145618bc236851d0abb14b2d4f431f9a470a00c2e51e450e40aaff6914f9147912f2743145014521451148b1726c3151e2abca284a2544a7446d22d445146d18aa23b64fe4effab2806a8e65b95889479ea55513abe7d6fcc8731ea57cbfc44353f4d9f8f2adecef531baa7e881a2478a9e287a167d8c5eb43f4111ffeb2b456f14bd53f441d127455f140d29daa3689fa2038a0e291aa97544d1314527149d527446d1394517145d527445ec06b2d712dde6f190215f18f0e78c299ae8fa558a6c4c528aa698f0b7ef989f562a5d5918b155be7e8d870afee8925fce9c0796e7bf349f55c5cfc4d2c740cc295ae0d6aafcd56829fe2afb5f114b013b56b6f85f11ff6f8ba2361a3d8a3a14b130f2efccfb3e45036582896207a721c52ec51ec53efbf71407d2a2763b539769c2b79de3356f50ccef8c042f52fd7c57579259bdea521c539cfc8c57490b5a567599b90aa38fd4fcd7fabeaacfa9f8ac0cfe9c6dfc85aa1e40f5a7519c529c51bca2f82ef7274aff3ebea7f80127fcd88f143f51fc8ce10cdd4b8a5f285e0b45c06449f12b7108316952fc4ef107c59f147f513ca4788fe27d8a0ff27848fb5f8c5769efe3438a47c254cb6a171f517c4cf109c5a75295d9eefe66efc36ff9898de071d7be8ab737f23937eba09ad744cf793f4cf49ee70bd92d7a71707040f119c5e7145fe0f333972ff6efcbfcc4d9a1343f7e1ecbf49cc303b419914b2930e9b1105d61c8385e577c43cd8fcdfc97c4db0aaf7cfe906299637f22bea1f856ee6b47fc8719533c11cf2bb6c5d1ffa53ec78cb1373c89f8dbe6277f82ed97b424d7fbb755bdafd92f5ac5437afeb67b22f989784af18ce239c58beff1b6948e5b0ec54b9c74286e28bc9af8e2efb2c4bf678760fe433e47e325f190cae768fefb7d16d536c5fc5132a688e29e92afbe5050585f58add9b3dfc90793d5d666bf68566dcc2fd6f705df63398f55e773f43c0a959fa8c58f1f0eb291e6abd5f54c140fd4c142943868f636f3131cbdff6bbcd44d6d9ecfd1f2c5f150e251e25312201d42992af1279290928838308afe929f30fbb14323ff15175f2f6bc8b7ec4bfed5e6e67dadeeb7f2079b7ca2b97f7f925f3ebae7942494a4946494acd01c5172f78ff1d2fc001b78e5f1f64b1e6c4f58d78694f0673ee07245c923c24bb97f8cf9273e0933b91d91d7a76477bcbd71ffb83274d3fcd7e8a7bdd1df61cc17cdfdafa27e22ef1f2ae6f3e5f361f2fad55b91b2e485923525af94bc51f28e93b5cedfff037dace1d5aae44b2ae53ed4b228f920e9ac3c92e1a2fc991c0c71e0957ca1cbaf0c25bfee53b2e3be233260fa2ffebde29fa8eac9d922e8fcaae6ebc8ef1f55fd5731dfaaea4f63110bbfa48a957da5e49012fe6b1fe18c7fef634a4e2839a584d16419bc200e7118afe44af8e5d8de27d794dc98f69e925bc12b19cbf9984c28b129995232a364ced851b2a06449498392a634d786ebdc594d18c7967411fd9ebf4f8a18bbbcf8f97e3efe989930ee3b36f239063f79deef6ed603e8f9c8c148f7a7e5fd43bafe8b3db2a44d4987922e256c6bfa42bebadfa264c03f0bf3b19440a40ea52ea51ea53ea581e69713a6df34c4f01da74d4a234a63b97f4c134a534a334a5794de517a4fe9838035e2bfcd83dc6fbb4abed247a1d0f1627559fb17beb4adac8fa5692b1ddaed7bb37fa8b959efabf451844bf8609ecd7ebecd79bfd26fc5cfff44e933a52f94ae297da5f48dd2774a3f28fd248e8ad321a5fc78fb941e507a48e988d2234a8f293da1f494d2334acf29bda0f492d22b4aaf29bda1f496524679a20a727a18f3576c0457325fd4f3727e721904d9cb65ca8b04387edd317fa846f6b82141f1afcbe0db66e7ab94af22deaef7bb8f441f753f5f69bf5813cbfad530927ee4fb1bf413a99348a794b2e0cc295d50baa4944586c5c7a2b445699bd20ea55d4a7b947238c9100fd4294f528a12ec217388577828c3c3d225cb14652e824f78d742e6ce781dfb8a2c4d440c2edbd6f9cdbaff1b5ee90ff63e36fe29ae7f7d739fd79b50e619f6becea750d533a555ff90aec7d4fda21bfd30eeb52e31bc590f25c0ce7cca02ca42ca2209a4b318472e6589d8eccdf54a592af31fd93c4d789f51b6a2ec8eb27bca589c394475a55ef1d853e4f7afb284fffe145ec060d53571777ee2a77cce2fceaae94f147c8f657ea2e0db2ee6491bfd7c253f40398f95f551e325fd8f1f55fd97cae4105af0df2419ed3d51f6885e9b32de3cc3f1287ba16c4d19a3f346d93b651f3236eda647d927655f37eb39fc0379756e291b62c43fce11c8727d7cc589722958bebcdb3fe0a5d2d0796622aacb8ea98c49e1706dd96fe6bf54718eceafda55bcbdc17fafeb7dcbfec77c24d8879aefee214b28db53f33b864211e0bfc279b8591f4aca70b580f308e71dced3cdfa8c30a18c7f565feabf02c03b863780fb0862ede33f18db9a25e305b7cf78c1e3e7bf156564c84afb7572c9f225f64bf02af471977cc5867f60eeff517e6263de9ce9af6a7dd47cdb6cbf54be90b2c34a1f8dfa4235bc56d5474b49269bc295e457192f772c595627957cb4cbb89ff0823ba78cd5f308c193d403bb8c29c37141d9319cab9bb52d2943f6c5462c6287949de0f82dc72b1f46f1aac8314f441ffdb3bfe96364d43b6f74706cbd61dbb2afcfef909114c57d5a7e3f14cafd101bfb0dfe9cb2fe5eea4dc605ff849e37770d622938133e0567952757dd493e98c29d51c612714219bfe11c5927c72b80c64be4cbb962e112bc3ef991f8d79855f265ea23db7bcf177d0c2219ded1bafcc3f9181a95e43fd59bec72c1b6de7754f387547e756ad633e5f190d6c7bcbeb0eaefa8e60f297d947a4c970380b164a2a55eee48c9d7b134a765e9065ea28c8cd7dd9a17cb1765e7088e45be581f7d5fec178b181b7b514997fdaf9b7587b20b0559af86d7eff55fa609ffa68fbfce1faaecbdf6ef4bbe47b35f54f3e794fc263adeceeba3ebfd0ac10ad167ce6fc2265feba33b117d14fbc510b31a5eb27c31648297f309b7c9fa48d9158e5f3558783c16f94aa762ec19af63273f1f355eac8fec4f046c1fdfe588649722d8ff035e1b41626278f961ada3bb2ad3dfdc7f9f07a6e36d5ba5281e72be5a9d8f56f358cb7e05357f2813bc349f82ee4fabec173f4c920f8a29ecbd922ffe16c688658a23d365255fee834c13f5f921cfe17c0964be2bf2a5edbd3b10e1e2f3b1942f7d3e2a7d54feea1cb4f883fd0aebfe7d997bd8f0577fdc17f5d139056b69efed62de5caf9a5fcbf2a5ebef557f5a8d1f408e483d0c2cd0fe4485d7fb7b2e5f5a1fe57c6467e25af0a263391cebf65ef431b810bc9c1b6dbf58c46ed68b12af9bb525f6abf4bf947ce93b6dca6e8acea1ddfa68d49057443a59fd5fb7ef6bfd3055bd6fd1afb065be7bce2ff790f7c3b0bfaacfc772be15bb147a7e1aeb23db7b8f45ec56db2f0516c9956d7609870f10f61b6e2bf972e662c244be2e73bcb4fdf2678297fba2fc2fcafd8963962c3e734ec4defb67cabfff8bff556a6266dc12154538d50dc88f7b032f552fa7fcaf8ed44f287e005dcfa4fa3becfc7e48df3fe6f5d14e35cf50cfcbd4f255da2fc68bed975c3e5a8297b25f7c3e8a3eba73b1f7baf85ee3e5b39830b263ed4fc8952de345ecbe8c155ecf944d441f355e225c5e7e3efa49ee7ffdc99f28c924be9f8fe6d7b7efb7df77d4e7654eabfa7b35ef44f2398c57359fefa9e8ef502ac9f225fd43675a25f5f9a82e6b47d262cc8bc15278c15d98f69ef112fba5fd09c717bcd8ff62fbe55de5f65ecb971f61e41978f570cab1a70d2fccf5f1477f2232ea7dcdaec68d1333312cd7e6de98d7a4eb31052cfe010f66bcade321d53f049d2f2cf9e5aa79e56adeaf3261d7b93f91db7bc18bb269ae8f1eff49460ab2fb9a3eb23fa1f152fa28ce7daafc55b15f0bb1f7ac8fb9ffe5e4e7a3d4e7b01f37932e4801cbfe4dbecafb34d360a57553b52b798f5a3d80799f26f955bbac37d9928fdee083c9f94d3ab9bfaae34773909a2ea190b1dbec648eb47f2fe763a98f1a2f6def59beb43fa1e58b9d55912f8d17033129fd2ff1efbd40cd3899ff2d1e8a8a48302ab8bd2283446e57e6dee8e713f94acbfc44d5dfa1eb315d35a2afeaafcdef876a7c30857faf42a22fe5df6bf91a9afeaab6f7ca7ed9b2b43fa1f591f1627bcfcf95cd953e2eb6e355c68f857ce5fe9717fe393f91d62bbfcc7adf3fe4a3ffdffffd3fff1ff6920cb5</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>buttonClose</sender>
+ <signal>clicked()</signal>
+ <receiver>SinkListBase</receiver>
+ <slot>reject()</slot>
+ </connection>
+ <connection>
+ <sender>buttonOpen</sender>
+ <signal>clicked()</signal>
+ <receiver>SinkListBase</receiver>
+ <slot>accept()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot access="protected">buttonRemove_clicked()</slot>
+ <slot access="protected">buttonConfigure_clicked()</slot>
+ <slot access="protected">buttonAdd_clicked()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kdialog.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kipi-plugins/sync/sinks.cpp b/kipi-plugins/sync/sinks.cpp
new file mode 100644
index 0000000..9dc9f14
--- /dev/null
+++ b/kipi-plugins/sync/sinks.cpp
@@ -0,0 +1,191 @@
+/* ============================================================
+ * File : sinks.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-14
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include <qstring.h>
+
+#include <qwidget.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kdeversion.h>
+#if KDE_IS_VERSION(3,2,0)
+#include <kwallet.h>
+#endif
+
+#include "sinks.h"
+#include "sink.h"
+#include "sinkfactory.h"
+
+namespace KIPISyncPlugin
+{
+
+SinkQListViewItem::SinkQListViewItem(Sink* pSink, QListView* pParent)
+ : QListViewItem(pParent, pSink->Name(), pSink->Type()),
+ mpSink(pSink)
+{
+}
+
+Sink* SinkQListViewItem::GetSink()
+{
+ return mpSink;
+}
+
+void SinkQListViewItem::Refresh()
+{
+ setText(0, mpSink->Name());
+ setText(1, mpSink->Type());
+}
+
+
+
+Sinks::Sinks()
+ : mpWallet(NULL),
+ mMaxSinkId(0)
+{
+ KWallet::Wallet* p_wallet = NULL;
+#if KDE_IS_VERSION(3,2,0)
+ mpWallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(),
+ kapp->activeWindow()->winId(),
+ KWallet::Wallet::Synchronous);
+ if (!mpWallet)
+ {
+ kdWarning() << "Failed to open kwallet" << endl;
+ }
+ else
+ {
+ if (!mpWallet->hasFolder("KIPISyncPlugin"))
+ {
+ if (!mpWallet->createFolder("KIPISyncPlugin"))
+ kdWarning() << "Failed to create kwallet folder" << endl;
+ }
+
+ if (!mpWallet->setFolder("KIPISyncPlugin"))
+ kdWarning() << "Failed to set kwallet folder" << endl;
+ else
+ p_wallet = mpWallet;
+ }
+#endif
+
+ // Read config
+ KConfig config("kipirc");
+ config.setGroup("Sync Settings");
+ QValueList<int> sink_ids = config.readIntListEntry("Sinks");
+
+ config.setGroup("Sync Sinks");
+ QString name, type;
+ for (QValueList<int>::Iterator it = sink_ids.begin(); it != sink_ids.end(); ++it)
+ {
+ unsigned int sink_id = (*it);
+
+ if (sink_id > mMaxSinkId)
+ mMaxSinkId = sink_id;
+
+ type = config.readEntry(QString("Type%1").arg(sink_id));
+ name = config.readEntry(QString("Name%1").arg(sink_id));
+ Sink* p_sink = SinkFactory::Create(type, sink_id, name, &config, p_wallet);
+ if (p_sink)
+ mSinks.append(p_sink);
+ }
+}
+
+
+Sinks::~Sinks()
+{
+ if (mpWallet)
+ delete mpWallet;
+
+ // Todo: clear up mSinks
+}
+
+
+/// @todo Abstract this to per-sink-type load
+void Sinks::Load()
+{
+ static bool bln_loaded = false;
+ if (bln_loaded) return;
+ bln_loaded = true;
+}
+
+
+Sink* Sinks::Add(QString type, QString name)
+{
+ Sink* p_sink = SinkFactory::Create(type, ++mMaxSinkId, name, NULL, NULL);
+ // This actually needs to be a call to sync factory creation... pass in the new SinkId
+ mSinks.append(p_sink);
+ return p_sink;
+}
+
+void Sinks::Remove(Sink* pSink)
+{
+ mSinks.remove(pSink);
+
+ // Slight cosmetic thing for sink numbering.
+ if (mSinks.isEmpty())
+ mMaxSinkId = 0;
+}
+
+
+/// @todo Abstract this to per-sink-type save
+void Sinks::Save()
+{
+ QValueList<int> sink_ids;
+ KConfig config("kipirc");
+ config.deleteGroup("Sync Sinks");
+ config.setGroup("Sync Sinks");
+
+ KWallet::Wallet* p_wallet = NULL;
+ if (mpWallet)
+ {
+ if (mpWallet->hasFolder("KIPISyncPlugin"))
+ {
+ if (!mpWallet->removeFolder("KIPISyncPlugin"))
+ kdWarning() << "Failed to clear kwallet folder" << endl;
+ }
+ if (!mpWallet->createFolder("KIPISyncPlugin"))
+ kdWarning() << "Failed to create kwallet folder" << endl;
+
+ if (!mpWallet->setFolder("KIPISyncPlugin"))
+ kdWarning() << "Failed to set kwallet folder" << endl;
+ else
+ p_wallet = mpWallet;
+ }
+
+ for (SinkPtrList::iterator it = mSinks.begin(); it != mSinks.end(); ++it)
+ {
+ Sink* p_sink = (*it);
+ p_sink->Save(&config, p_wallet);
+ sink_ids.append(p_sink->SinkId());
+ }
+
+ config.setGroup("Sync Settings");
+ config.writeEntry("Sinks", sink_ids);
+}
+
+void Sinks::asQListView(QListView* pListView)
+{
+ Load();
+
+ pListView->clear();
+ for (SinkPtrList::iterator it = mSinks.begin(); it != mSinks.end(); ++it)
+ {
+ //(*it)->asQListViewItem(pListView);
+ }
+}
+
+}
diff --git a/kipi-plugins/sync/sinks.h b/kipi-plugins/sync/sinks.h
new file mode 100644
index 0000000..21d70fa
--- /dev/null
+++ b/kipi-plugins/sync/sinks.h
@@ -0,0 +1,81 @@
+/* ============================================================
+ * File : sinks.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-01-14
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 SINKS_H
+#define SINKS_H
+
+#include <qptrlist.h>
+#include <qlistview.h>
+
+// Some sinks may wish to make use of the Wallet to store sensitive
+// information so we manage it here.
+namespace KWallet
+{
+class Wallet;
+}
+
+namespace KIPISyncPlugin
+{
+
+// Forward Declarations
+class Sink;
+
+/* Simple Stub Class to allow easy access to Sinks from GUI elements */
+class SinkQListViewItem : public QListViewItem
+{
+
+public:
+ SinkQListViewItem(Sink* pSink, QListView* pParent);
+
+ Sink* GetSink();
+ void Refresh();
+
+private:
+ Sink* mpSink;
+
+};
+
+
+typedef QPtrList<Sink> SinkPtrList;
+
+/* Container class for all Sinks */
+class Sinks
+{
+
+public:
+ Sinks();
+ ~Sinks();
+
+ Sink* Add(QString type, QString name);
+ void Remove(Sink* pSink);
+ void Save();
+ void asQListView(QListView* pListView);
+
+private:
+ void Load();
+
+ KWallet::Wallet* mpWallet;
+
+ SinkPtrList mSinks;
+ unsigned int mMaxSinkId;
+};
+
+
+}
+
+#endif /* SINKS_H */
diff --git a/kipi-plugins/sync/sinks/gallery/gallerycollection.cpp b/kipi-plugins/sync/sinks/gallery/gallerycollection.cpp
new file mode 100644
index 0000000..4351e7c
--- /dev/null
+++ b/kipi-plugins/sync/sinks/gallery/gallerycollection.cpp
@@ -0,0 +1,20 @@
+/* ============================================================
+ * File : gallerycollection.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-02-02
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include "gallerycollection.h"
+
diff --git a/kipi-plugins/sync/sinks/gallery/gallerycollection.h b/kipi-plugins/sync/sinks/gallery/gallerycollection.h
new file mode 100644
index 0000000..5c41c71
--- /dev/null
+++ b/kipi-plugins/sync/sinks/gallery/gallerycollection.h
@@ -0,0 +1,29 @@
+/* ============================================================
+ * File : gallerycollection.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-02-02
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include "../../libkipi2/collection.h"
+
+namespace KipiSyncPlugin
+{
+
+class GalleryCollection : KIPI2::Collection
+{
+
+};
+
+}
diff --git a/kipi-plugins/sync/sinks/gallery/galleryform.cpp b/kipi-plugins/sync/sinks/gallery/galleryform.cpp
new file mode 100644
index 0000000..44a15ce
--- /dev/null
+++ b/kipi-plugins/sync/sinks/gallery/galleryform.cpp
@@ -0,0 +1,135 @@
+/* ============================================================
+ * File : gallerympform.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-02
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kurl.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+
+//#include <cstring>
+//#include <cstdio>
+
+#include "galleryform.h"
+
+namespace KIPISyncPlugin
+{
+
+GalleryForm::GalleryForm(GalleryVersion version, QString authToken)
+ : mVersion(version)
+{
+ mBoundary = "----------";
+ mBoundary += KApplication::randomString( 42 + 13 ).ascii();
+
+ if (Gallery2 == mVersion)
+ {
+ addPairRaw("g2_controller", "remote:GalleryRemote");
+ if (!authToken.isEmpty())
+ addPairRaw("g2_authToken", authToken);
+ }
+}
+
+
+GalleryForm::~GalleryForm()
+{
+}
+
+
+void GalleryForm::addPair(const QString& name, const QString& value)
+{
+ if (Gallery2 == mVersion)
+ return addPairRaw(QString("g2_form[%1]").arg(name), value);
+
+ return addPairRaw(name, value);
+}
+
+
+void GalleryForm::addPairRaw(const QString& name, const QString& value)
+{
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << "--" << mBoundary << "\r\n";
+ ts << "Content-Disposition: form-data; name=\"" << name.ascii() << "\"\r\n\r\n";
+ ts << value.ascii() << "\r\n";
+}
+
+bool GalleryForm::addFile(const QString& path, const QString& displayFilename)
+{
+ QString filename = "userfile_name";
+ if (Gallery2 == mVersion)
+ filename = "g2_userfile_name";
+
+ addPairRaw(filename, displayFilename);
+ KMimeType::Ptr ptr = KMimeType::findByURL(path);
+ QString mime = ptr->name();
+ if (mime.isEmpty())
+ {
+ // if we ourselves can't determine the mime of the local file,
+ // very unlikely the remote gallery will be able to identify it
+ return false;
+ }
+
+ QFile imageFile(path);
+ if ( !imageFile.open( IO_ReadOnly ) )
+ return false;
+ QByteArray imageData = imageFile.readAll();
+ imageFile.close();
+
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << "--" << mBoundary << "\r\n";
+ ts << "Content-Disposition: form-data; name=\"";
+ if (Gallery2 == mVersion)
+ ts << "g2_userfile";
+ else
+ ts << "userfile";
+ ts << "\"; filename=\"" << QFile::encodeName(KURL(path).filename()) << "\"\r\n";
+ ts << "Content-Type: " << mime.ascii() << "\r\n\r\n";
+
+ int oldSize = m_buffer.size();
+ m_buffer.resize(oldSize + imageData.size() + 3);
+ memcpy(m_buffer.data()+oldSize, imageData.data(), imageData.size());
+ m_buffer[m_buffer.size()-3] = '\r';
+ m_buffer[m_buffer.size()-2] = '\n';
+ m_buffer[m_buffer.size()-1] = '\0';
+
+ return true;
+}
+
+
+QString GalleryForm::contentType() const
+{
+ return QString("Content-Type: multipart/form-data; boundary=" + mBoundary);
+}
+
+
+QByteArray GalleryForm::formData()
+{
+ QTextStream ts(m_buffer, IO_Append|IO_WriteOnly);
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ ts << "--" << mBoundary << "--" << "\r\n";
+
+ return m_buffer;
+}
+
+}
diff --git a/kipi-plugins/sync/sinks/gallery/galleryform.h b/kipi-plugins/sync/sinks/gallery/galleryform.h
new file mode 100644
index 0000000..e8f39a2
--- /dev/null
+++ b/kipi-plugins/sync/sinks/gallery/galleryform.h
@@ -0,0 +1,61 @@
+/* ============================================================
+ * File : galleryform.h
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-12-02
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 GALLERYFORM_H
+#define GALLERYFORM_H
+
+#include <qcstring.h>
+#include <qstring.h>
+
+class KURL;
+
+namespace KIPISyncPlugin
+{
+
+typedef enum
+{
+ Gallery1,
+ Gallery2
+} GalleryVersion;
+
+
+class GalleryForm
+{
+public:
+
+ GalleryForm(GalleryVersion version, QString authToken = "");
+ ~GalleryForm();
+
+ void addPair(const QString& name, const QString& value);
+ bool addFile(const QString& path, const QString& displayFilename);
+
+ QString contentType() const;
+ QByteArray formData();
+
+private:
+
+ void addPairRaw(const QString& name, const QString& value);
+
+ GalleryVersion mVersion;
+ QByteArray m_buffer;
+ QCString mBoundary;
+};
+
+}
+
+#endif /* GALLERYMPFORM_H */
diff --git a/kipi-plugins/sync/sinks/gallery/galleryitem.cpp b/kipi-plugins/sync/sinks/gallery/galleryitem.cpp
new file mode 100644
index 0000000..5c07d5b
--- /dev/null
+++ b/kipi-plugins/sync/sinks/gallery/galleryitem.cpp
@@ -0,0 +1,19 @@
+/* ============================================================
+ * File : galleryitem.cpp
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-02-02
+ *
+ * Copyright 2007 Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include "galleryitem.h"
diff --git a/kipi-plugins/sync/sinks/gallery/galleryitem.h b/kipi-plugins/sync/sinks/gallery/galleryitem.h
new file mode 100644
index 0000000..88fc7e8
--- /dev/null
+++ b/kipi-plugins/sync/sinks/gallery/galleryitem.h
@@ -0,0 +1,29 @@
+/* ============================================================
+ * File : galleryitem.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Date : 2007-02-02
+ *
+ * Copyright 2007 Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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.
+ * ============================================================ */
+
+#include "../../libkipi2/item.h"
+
+namespace KipiSyncPlugin
+{
+
+class GalleryItem : KIPI2::Item
+{
+
+};
+
+}
diff --git a/kipi-plugins/sync/sinks/gallery/gallerysink.cpp b/kipi-plugins/sync/sinks/gallery/gallerysink.cpp
new file mode 100644
index 0000000..8578b9c
--- /dev/null
+++ b/kipi-plugins/sync/sinks/gallery/gallerysink.cpp
@@ -0,0 +1,686 @@
+/* ============================================================
+ * File : gallerysink.cpp
+ * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2004-11-30
+ * Description :
+ *
+ * Copyright 2004 by Renchi Raju <renchi@pooh.tam.uiuc.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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <qcstring.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qimage.h>
+#include <qregexp.h>
+
+#include <klocale.h>
+#include <kio/job.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kstandarddirs.h>
+
+#include <cstring>
+#include <cstdio>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/libkexiv2.h>
+
+#include "gallerysink.h"
+#include "gallerycollection.h"
+#include "galleryitem.h"
+
+namespace KIPISyncPlugin
+{
+
+GallerySink::GallerySink(unsigned int sinkId, QString name, KConfig* pConfig, KWallet::Wallet* pWallet, GalleryVersion version)
+ : Sink(sinkId, name, pConfig, pWallet),
+ mVersion(version),
+ mAuthToken(""),
+ mpJob(0),
+ m_loggedIn(false)
+{
+ QString tmp = pConfig->readEntry(QString("URL%1").arg(sinkId));
+ mURL = KURL(tmp);
+ mUsername = pConfig->readEntry(QString("Username%1").arg(sinkId));
+ if (pWallet)
+ pWallet->readPassword(QString("Password%1").arg(sinkId), mPassword);
+}
+
+GallerySink::~GallerySink()
+{
+ if (mpJob)
+ mpJob->kill();
+}
+
+
+const KIPI2::CollectionList* GallerySink::getCollections()
+{
+ return NULL;
+}
+
+void GallerySink::Save(KConfig* pConfig, KWallet::Wallet* pWallet)
+{
+ pConfig->writeEntry(QString("Name%1").arg(mSinkId), mName);
+ pConfig->writeEntry(QString("Type%1").arg(mSinkId), Type());
+ pConfig->writeEntry(QString("URL%1").arg(mSinkId), QString(mURL.url()));
+ pConfig->writeEntry(QString("Username%1").arg(mSinkId), mUsername);
+ if (pWallet)
+ pWallet->writePassword(QString("Password%1").arg(mSinkId), mPassword);
+}
+
+
+/*
+bool GallerySink::loggedIn() const
+{
+ return m_loggedIn;
+}
+*/
+
+bool GallerySink::Connect()
+{
+ GalleryForm form(mVersion, mAuthToken);
+
+ form.addPair("cmd", "login");
+ form.addPair("protocol_version", "2.3");
+ form.addPair("uname", mUsername);
+ form.addPair("password", mPassword);
+
+ KIO::TransferJob* job = KIO::http_post(mURL, form.formData(), false);
+ job->addMetaData("content-type", form.contentType() );
+ job->addMetaData("cookies", "manual");
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ mState = GE_LOGIN;
+ mpJob = job;
+ mBuffer.resize(0);
+ //emit signalBusy( true );
+}
+/*
+void GallerySink::listAlbums()
+{
+ GalleryForm form(mVersion, mAuthToken);
+
+ QString task = "fetch-albums";
+ if (Gallery2 == mVersion)
+ task = "fetch-albums-prune";
+
+ form.addPair("cmd", task);
+ form.addPair("protocol_version", "2.3");
+
+ KIO::TransferJob* job = KIO::http_post(m_url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType() );
+ job->addMetaData("cookies", "manual");
+ job->addMetaData("setcookies", m_cookie);
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ mState = GE_LISTALBUMS;
+ mpJob = job;
+ mBuffer.resize(0);
+ emit signalBusy( true );
+}
+
+void GallerySink::listPhotos( const QString& albumName )
+{
+ if (mpJob)
+ {
+ mpJob->kill();
+ mpJob = 0;
+ }
+
+ GalleryForm form(mVersion, mAuthToken);
+
+ form.addPair("cmd", "fetch-album-images");
+ form.addPair("protocol_version", "2.3");
+ form.addPair("set_albumName", albumName);
+
+ KIO::TransferJob* job = KIO::http_post(m_url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType() );
+ job->addMetaData("cookies", "manual");
+ job->addMetaData("setcookies", m_cookie);
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ mState = GE_LISTPHOTOS;
+ mpJob = job;
+ mBuffer.resize(0);
+ emit signalBusy( true );
+}
+
+void GallerySink::createAlbum( const QString& parentAlbumName,
+ const QString& albumName,
+ const QString& albumTitle,
+ const QString& albumCaption )
+{
+ if (mpJob)
+ {
+ mpJob->kill();
+ mpJob = 0;
+ }
+
+ GalleryForm form(mVersion, mAuthToken);
+
+ form.addPair("cmd", "new-album");
+ form.addPair("protocol_version", "2.3");
+ form.addPair("set_albumName", parentAlbumName);
+ if (!albumName.isEmpty())
+ form.addPair("newAlbumName", albumName);
+ if (!albumTitle.isEmpty())
+ form.addPair("newAlbumTitle", albumTitle);
+ if (!albumCaption.isEmpty())
+ form.addPair("newAlbumDesc", albumCaption);
+
+ KIO::TransferJob* job = KIO::http_post(m_url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType() );
+ job->addMetaData("cookies", "manual");
+ job->addMetaData("setcookies", m_cookie);
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ mState = GE_CREATEALBUM;
+ mpJob = job;
+ mBuffer.resize(0);
+ emit signalBusy( true );
+}
+
+bool GallerySink::addPhoto( const QString& albumName,
+ const QString& photoPath,
+ const QString& caption,
+ bool rescale, int maxDim )
+{
+ if (mpJob)
+ {
+ mpJob->kill();
+ mpJob = 0;
+ }
+
+ QString path = photoPath;
+ QString display_filename = QFile::encodeName(KURL(path).filename());
+
+ GalleryForm form(mVersion, mAuthToken);
+
+ form.addPair("cmd", "add-item");
+ form.addPair("protocol_version", "2.3");
+ form.addPair("set_albumName", albumName);
+
+ if (!caption.isEmpty())
+ form.addPair("caption", caption);
+ QImage image(photoPath);
+
+ if (!image.isNull())
+ {
+ // image file - see if we need to rescale it
+ if (rescale && (image.width() > maxDim || image.height() > maxDim))
+ {
+ image = image.smoothScale(maxDim, maxDim, QImage::ScaleMin);
+ path = locateLocal("tmp", KURL(photoPath).filename());
+ image.save(path, QImageIO::imageFormat(photoPath));
+
+ if ("JPEG" == QString(QImageIO::imageFormat(photoPath)).upper())
+ {
+ KExiv2Library::LibKExiv2 exiv2;
+ if (exiv2.load(photoPath))
+ {
+ exiv2.save(path);
+ }
+ }
+ kdDebug() << "Resizing and saving to temp file: "
+ << path << endl;
+ }
+ }
+
+ // The filename bit can perhaps be calculated in addFile()
+ // but not sure of the temporary filename that could be
+ // used for resizing... so I've added it explicitly for now.
+ if (!form.addFile(path, display_filename))
+ return false;
+
+ KIO::TransferJob* job = KIO::http_post(m_url, form.formData(), false);
+ job->addMetaData("content-type", form.contentType());
+ job->addMetaData("cookies", "manual");
+ job->addMetaData("setcookies", m_cookie);
+ connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
+ SLOT(data(KIO::Job*, const QByteArray&)));
+ connect(job, SIGNAL(result(KIO::Job *)),
+ SLOT(slotResult(KIO::Job *)));
+
+ mState = GE_ADDPHOTO;
+ mpJob = job;
+ mBuffer.resize(0);
+ emit signalBusy( true );
+
+ return true;
+}
+
+void GallerySink::cancel()
+{
+ if (mpJob)
+ {
+ mpJob->kill();
+ mpJob = 0;
+ }
+}
+
+void GallerySink::data(KIO::Job*, const QByteArray& data)
+{
+ if (data.isEmpty())
+ return;
+
+ int oldSize = mBuffer.size();
+ mBuffer.resize(mBuffer.size() + data.size());
+ memcpy(mBuffer.data()+oldSize, data.data(), data.size());
+}
+
+void GallerySink::slotResult(KIO::Job *job)
+{
+ mpJob = 0;
+ emit signalBusy( false );
+
+ if ( job->error() )
+ {
+ if ( mState == GE_LOGIN )
+ emit signalLoginFailed( job->errorString() );
+ else if ( mState == GE_ADDPHOTO )
+ emit signalAddPhotoFailed( job->errorString() );
+ else
+ job->showErrorDialog( ); //m_parent
+ return;
+ }
+
+ switch(mState)
+ {
+ case(GE_LOGIN):
+ parseResponseLogin(mBuffer);
+ break;
+ case(GE_LISTALBUMS):
+ parseResponseListAlbums(mBuffer);
+ break;
+ case(GE_LISTPHOTOS):
+ parseResponseListPhotos(mBuffer);
+ break;
+ case(GE_CREATEALBUM):
+ parseResponseCreateAlbum(mBuffer);
+ break;
+ case(GE_ADDPHOTO):
+ parseResponseAddPhoto(mBuffer);
+ break;
+ }
+
+ if (mState == GE_LOGIN && m_loggedIn)
+ {
+ QStringList cookielist = QStringList::split("\n", job->queryMetaData("setcookies"));
+ m_cookie = "Cookie:";
+ for (QStringList::Iterator it = cookielist.begin(); it != cookielist.end(); ++it)
+ {
+ QRegExp rx("^Set-Cookie: ([^;]+)");
+ if (rx.search(*it) > -1)
+ m_cookie += " " + rx.cap(1) + ";";
+ }
+ listAlbums();
+ }
+}
+
+void GallerySink::parseResponseLogin(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+
+ m_loggedIn = false;
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+
+ if (!foundResponse)
+ {
+ foundResponse = line.startsWith("#__GR2PROTO__");
+ }
+ else
+ {
+ QStringList strlist = QStringList::split("=", line);
+ if (strlist.count() == 2)
+ {
+ if (("status" == strlist[0]) && ("0" == strlist[1]))
+ {
+ m_loggedIn = true;
+ }
+ else if ("auth_token" == strlist[0])
+ {
+ mAuthToken = strlist[1];
+ }
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalLoginFailed( i18n("Gallery URL probably incorrect"));
+ return;
+ }
+
+ if (!m_loggedIn)
+ {
+ emit signalLoginFailed(i18n("Incorrect username or password specified"));
+ }
+}
+
+void GallerySink::parseResponseListAlbums(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+ bool success = false;
+
+ typedef QValueList<GAlbum> GAlbumList;
+ GAlbumList albumList;
+ GAlbumList::iterator iter = albumList.begin();
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+ if (!foundResponse)
+ {
+ foundResponse = line.startsWith("#__GR2PROTO__");
+ }
+ else
+ {
+ QStringList strlist = QStringList::split("=", line);
+ if (strlist.count() == 2)
+ {
+ QString key = strlist[0];
+ QString value = strlist[1];
+
+ if (key == "status")
+ {
+ success = (value == "0");
+ }
+ else if (key.startsWith("album.name"))
+ {
+ GAlbum album;
+ album.name = value;
+ if (Gallery2 == mVersion)
+ album.ref_num = value.toInt();
+ else
+ album.ref_num = key.section(".", 2, 2).toInt();
+ iter = albumList.append(album);
+ }
+ else if (key.startsWith("album.title"))
+ {
+ if (iter != albumList.end())
+ (*iter).title = value;
+ }
+ else if (key.startsWith("album.summary"))
+ {
+ if (iter != albumList.end())
+ (*iter).summary = value;
+ }
+ else if (key.startsWith("album.parent"))
+ {
+ if (iter != albumList.end())
+ (*iter).parent_ref_num = value.toInt();
+ }
+ else if (key.startsWith("album.perms.add"))
+ {
+ if (iter != albumList.end())
+ (*iter).add = (value == "true");
+ }
+ else if (key.startsWith("album.perms.write"))
+ {
+ if (iter != albumList.end())
+ (*iter).write = (value == "true");
+ }
+ else if (key.startsWith("album.perms.del_item"))
+ {
+ if (iter != albumList.end())
+ (*iter).del_item = (value == "true");
+ }
+ else if (key.startsWith("album.perms.del_alb"))
+ {
+ if (iter != albumList.end())
+ (*iter).del_alb = (value == "true");
+ }
+ else if (key.startsWith("album.perms.create_sub"))
+ {
+ if (iter != albumList.end())
+ (*iter).create_sub = (value == "true");
+ }
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalError(i18n("Invalid response received from remote Gallery"));
+ return;
+ }
+
+ if (!success)
+ {
+ emit signalError(i18n("Failed to list albums"));
+ return;
+ }
+
+ // We need parent albums to come first for rest of the code to work
+ qHeapSort(albumList);
+
+ emit signalAlbums( albumList );
+}
+
+void GallerySink::parseResponseListPhotos(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+ bool success = false;
+
+ typedef QValueList<GPhoto> GPhotoList;
+ GPhotoList photoList;
+ GPhotoList::iterator iter = photoList.begin();
+
+ QString albumURL;
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+
+ if (!foundResponse)
+ {
+ foundResponse = line.startsWith("#__GR2PROTO__");
+ }
+ else
+ {
+ // Boris the Gallery default URL contains "=" char. So we will split the string only from the first "=" char
+ QStringList strlist = QStringList();
+ strlist << line.left(line.find('=')) << line.mid(line.find('=')+1);
+ if (strlist.count() >= 2)
+ {
+ QString key = strlist[0];
+ QString value = strlist[1];
+
+ if (key == "status")
+ {
+ success = (value == "0");
+ }
+ else if (key.startsWith("image.name"))
+ {
+ GPhoto photo;
+ photo.name = value;
+ photo.ref_num = key.section(".", 2, 2).toInt();
+ iter = photoList.append(photo);
+ }
+ else if (key.startsWith("image.caption"))
+ {
+ if (iter != photoList.end())
+ (*iter).caption = value;
+ }
+ else if (key.startsWith("image.thumbName"))
+ {
+ if (iter != photoList.end())
+ (*iter).thumbName = value;
+ }
+ else if (key.startsWith("baseurl"))
+ {
+ albumURL = value.replace("\\","");
+ }
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalError(i18n("Invalid response received from remote Gallery"));
+ return;
+ }
+
+ if (!success)
+ {
+ emit signalError(i18n("Failed to list photos"));
+ return;
+ }
+
+ for ( iter = photoList.begin(); iter != photoList.end(); ++iter )
+ {
+ (*iter).albumURL = albumURL;
+ }
+
+ emit signalPhotos( photoList );
+}
+
+void GallerySink::parseResponseCreateAlbum(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+ bool success = false;
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+
+ if (!foundResponse)
+ {
+ foundResponse = line.startsWith("#__GR2PROTO__");
+ }
+ else
+ {
+ QStringList strlist = QStringList::split("=", line);
+ if (strlist.count() == 2)
+ {
+ QString key = strlist[0];
+ QString value = strlist[1];
+
+ if (key == "status")
+ {
+ success = (value == "0");
+ }
+ else if (key.startsWith("status_text"))
+ {
+ kdDebug() << "STATUS: Create Album: " << value << endl;
+ }
+
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalError(i18n("Invalid response received from remote Gallery"));
+ return;
+ }
+
+ if (!success)
+ {
+ emit signalError(i18n("Failed to create new album"));
+ return;
+ }
+
+ listAlbums();
+}
+
+void GallerySink::parseResponseAddPhoto(const QByteArray &data)
+{
+ QTextStream ts(data, IO_ReadOnly );
+ ts.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ bool foundResponse = false;
+ bool success = false;
+
+ while (!ts.atEnd())
+ {
+ line = ts.readLine();
+
+ if (!foundResponse)
+ {
+ // Gallery1 sends resizing debug code sometimes so we
+ // have to detect things slightly differently
+ foundResponse = (line.startsWith("#__GR2PROTO__")
+ || (line.startsWith("<br>- Resizing")
+ && line.endsWith("#__GR2PROTO__")));
+ }
+ else
+ {
+ QStringList strlist = QStringList::split("=", line);
+ if (strlist.count() == 2)
+ {
+ QString key = strlist[0];
+ QString value = strlist[1];
+
+ if (key == "status")
+ {
+ success = (value == "0");
+ }
+ else if (key.startsWith("status_text"))
+ {
+ kdDebug() << "STATUS: Add Photo: " << value << endl;
+ }
+
+ }
+ }
+ }
+
+ if (!foundResponse)
+ {
+ emit signalAddPhotoFailed(i18n("Invalid response received from remote Gallery"));
+ return;
+ }
+
+ if (!success)
+ {
+ emit signalAddPhotoFailed(i18n("Failed to upload photo"));
+ }
+ else
+ {
+ emit signalAddPhotoSucceeded();
+ }
+}
+*/
+}
+
+
+//#include "gallerysink.moc"
diff --git a/kipi-plugins/sync/sinks/gallery/gallerysink.h b/kipi-plugins/sync/sinks/gallery/gallerysink.h
new file mode 100644
index 0000000..1e76968
--- /dev/null
+++ b/kipi-plugins/sync/sinks/gallery/gallerysink.h
@@ -0,0 +1,120 @@
+/* ============================================================
+ * File : gallerysink.h
+ * Author: Colin Guthrie <kde@colin.guthr.ie>
+ * Based On Work By: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Date : 2007-01-27
+ *
+ * Copyright 2007 by Colin Guthrie <kde@colin.guthr.ie>
+ *
+ * This program is free software; you can redistribute 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 GALLERYSINK_H
+#define GALLERYSINK_H
+
+#include <qobject.h>
+#include <kurl.h>
+
+#include "../../sink.h"
+#include "galleryform.h"
+
+namespace KIO
+{
+ class Job;
+}
+
+class KURL;
+template <class T> class QValueList;
+
+namespace KIPISyncPlugin
+{
+
+class GalleryCollection;
+class GalleryItem;
+
+class GallerySink : public Sink
+{
+public:
+ enum State {
+ GE_LOGIN = 0,
+ GE_LISTALBUMS,
+ GE_LISTPHOTOS,
+ GE_CREATEALBUM,
+ GE_ADDPHOTO
+ };
+
+ GallerySink(unsigned int sinkId, QString name, KConfig* pConfig, KWallet::Wallet* pWallet, GalleryVersion version);
+ ~GallerySink();
+
+ const KIPI2::CollectionList* getCollections();
+
+ void Save(KConfig* pConfig, KWallet::Wallet* pWallet);
+
+ bool Connect();
+
+ /*
+ bool loggedIn() const;
+
+ void login( const KURL& url, const QString& name,
+ const QString& passwd );
+ void listAlbums();
+ void listPhotos( const QString& albumName );
+ void createAlbum( const QString& parentAlbumName,
+ const QString& albumName,
+ const QString& albumTitle,
+ const QString& albumCaption );
+ bool addPhoto( const QString& albumName,
+ const QString& photoPath,
+ const QString& caption=QString(),
+ bool rescale=false, int maxDim=600);
+
+ void cancel();
+ */
+private:
+ GalleryVersion mVersion;
+ QString mAuthToken;
+
+ QString mName;
+ KURL mURL;
+ QString mUsername;
+ QString mPassword;
+
+ State mState;
+ QString m_cookie;
+ KURL m_url;
+ KIO::Job* mpJob;
+ bool m_loggedIn;
+ QByteArray mBuffer;
+ /*
+ void parseResponseLogin(const QByteArray &data);
+ void parseResponseListAlbums(const QByteArray &data);
+ void parseResponseListPhotos(const QByteArray &data);
+ void parseResponseCreateAlbum(const QByteArray &data);
+ void parseResponseAddPhoto(const QByteArray &data);
+
+signals:
+ void signalError( const QString& msg );
+ void signalLoginFailed( const QString& msg );
+ void signalBusy( bool val );
+ void signalAlbums( const QValueList<GAlbum>& albumList );
+ void signalPhotos( const QValueList<GPhoto>& photoList );
+ void signalAddPhotoSucceeded( );
+ void signalAddPhotoFailed( const QString& msg );
+
+private slots:
+ void data(KIO::Job *job, const QByteArray &data);
+ void slotResult (KIO::Job *job);
+ */
+};
+
+}
+
+#endif /* GALLERYTALKER_H */
diff --git a/kipi-plugins/timeadjust/Makefile.am b/kipi-plugins/timeadjust/Makefile.am
new file mode 100644
index 0000000..66e9ade
--- /dev/null
+++ b/kipi-plugins/timeadjust/Makefile.am
@@ -0,0 +1,25 @@
+INCLUDES = $(KIPI_PLUGINS_COMMON_INCLUDE) $(LIBKEXIV2_CFLAGS) $(LIBKIPI_CFLAGS) $(all_includes)
+
+METASOURCES = AUTO
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kipiplugin_timeadjust.la
+
+kipiplugin_timeadjust_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP) $(LIBKEXIV2_LIBS_DEP)
+
+# Srcs for the plugin
+kipiplugin_timeadjust_la_SOURCES = plugin_timeadjust.cpp timeadjustdialog.cpp
+
+# Libs needed by the plugin
+kipiplugin_timeadjust_la_LIBADD = $(LIBKEXIV2_LIBS) $(LIBKIPI_LIBS) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+# LD flags for the plugin
+kipiplugin_timeadjust_la_LDFLAGS = $(KIPI_PLUGINS_COMMON_LDFLAGS) -module $(KDE_PLUGIN) $(all_libraries) -lkipiplugins
+
+# Install the desktop file needed to detect the plugin
+kde_services_DATA = kipiplugin_timeadjust.desktop
+
+# i18n translation messages
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_timeadjust.pot
+
diff --git a/kipi-plugins/timeadjust/kipiplugin_timeadjust.desktop b/kipi-plugins/timeadjust/kipiplugin_timeadjust.desktop
new file mode 100644
index 0000000..5d4c9bd
--- /dev/null
+++ b/kipi-plugins/timeadjust/kipiplugin_timeadjust.desktop
@@ -0,0 +1,55 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=TimeDateAdjust
+Name[ca]=Ajust de data i hora
+Name[cs]=Nastavení data
+Name[da]=Justér dato og tid
+Name[de]=Zeit und Datum anpassen
+Name[el]=ΡύθμισηΏραςΗμερομηνίας
+Name[es]=Ajustar fecha y hora
+Name[et]=Aja kohendamine
+Name[fi]=Päiväyksen tarkistus
+Name[gl]=Axuste de Data e Hora
+Name[it]=RegolazioneDataOra
+Name[nds]=Tiet topassen
+Name[nl]=Tijd/DatumAanpassen
+Name[pl]=Zmiana daty i godziny
+Name[pt]=Ajuste de Data e Hora
+Name[sr]=Подеси време/датум
+Name[sr@Latn]=Podesi vreme/datum
+Name[sv]=Justera datum och tid
+Name[tg]=ТанзимдиҳииТаърих/Вақт
+Name[tr]=ZamanTarihAyarla
+Name[xx]=xxTimeDateAdjustxx
+Name[zh_CN]=日期时间调整
+Comment=KIPI Time and Date Adjust
+Comment[ca]=Connector del KIPI per ajustar la data i l'hora
+Comment[cs]=KIPI nastavení času a data
+Comment[da]=KIPI-plugin: Justér dato og tid
+Comment[de]=Ein KIPI-Modul zum Setzen von Zeit und Datum
+Comment[el]=Ρύθμιση ώρας και ημερομηνίας του KIPI
+Comment[es]=Ajuste de fecha y hora para KIPI
+Comment[et]=KIPI kuupäeva ja kellaaja kohendamine
+Comment[fi]=Kipi-liitännäinen kuvatiedostojen päiväyksen ja ajan asetusta varten
+Comment[fr]=Module externe KIPI pour ajuster la date et l'heure
+Comment[gl]=Axuste de Data e Hora de KIPI
+Comment[it]=Regolazione di data e ora di KIPI
+Comment[ja]=Kipi 日付と時刻の調整
+Comment[nds]=KIPI-Moduul för't Topassen vun Datum un Tiet
+Comment[nl]=KIPI-plugin voor het aanpassen van de datum/tijd
+Comment[pa]=KIPI ਸਮਾਂ ਅਤੇ ਮਿਤੀ ਅਨੁਕੂਲਣ
+Comment[pl]=Wtyczka KIPI - Zmiana daty i godziny
+Comment[pt]=Ajuste de Data e Hora do KIPI
+Comment[pt_BR]=Ajuste de Hora e Data do KIPI
+Comment[sr]=KIPI-јево подешавање времена и датума
+Comment[sr@Latn]=KIPI-jevo podešavanje vremena i datuma
+Comment[sv]=KIPI-insticksprogram: Justera datum och tid
+Comment[tg]=Модули KIPI барои танзимдиҳии таърих ва вақт
+Comment[tr]=KIPI Zaman ve Tarih Ayarlama
+Comment[xx]=xxKIPI Time and Date Adjustxx
+Comment[zh_CN]=KIPI 时间和日期调整
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_timeadjust
+author=Gilles Caulier, caulier dot gilles at gmail dot com
+X-KIPI-ReqFeatures=ImagesHasTime
diff --git a/kipi-plugins/timeadjust/plugin_timeadjust.cpp b/kipi-plugins/timeadjust/plugin_timeadjust.cpp
new file mode 100644
index 0000000..de4f5f6
--- /dev/null
+++ b/kipi-plugins/timeadjust/plugin_timeadjust.cpp
@@ -0,0 +1,106 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-05-16
+ * Description : a plugin to set time stamp of picture files.
+ *
+ * Copyright (C) 2003-2005 by Jesper Pedersen <blackie@kde.org>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+// LibKIPI includes.
+
+#include <libkipi/imagecollection.h>
+
+// Local includes.
+
+#include "timeadjustdialog.h"
+#include "plugin_timeadjust.h"
+#include "plugin_timeadjust.moc"
+
+typedef KGenericFactory<Plugin_TimeAdjust> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_timeadjust,
+ Factory("kipiplugin_timeadjust"))
+
+Plugin_TimeAdjust::Plugin_TimeAdjust(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "TimeAdjust")
+{
+ kdDebug( 51001 ) << "Plugin_TimeAdjust plugin loaded" << endl;
+}
+
+void Plugin_TimeAdjust::setup(QWidget* widget)
+{
+ KIPI::Plugin::setup(widget);
+
+ // this is our action shown in the menubar/toolbar of the mainwindow
+
+ m_actionTimeAjust = new KAction (i18n("Adjust Time && Date..."),
+ "clock",
+ 0,
+ this,
+ SLOT(slotActivate()),
+ actionCollection(),
+ "timeadjust");
+
+ addAction(m_actionTimeAjust);
+
+ m_interface = dynamic_cast< KIPI::Interface* >(parent());
+
+ if (!m_interface)
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection selection = m_interface->currentSelection();
+ m_actionTimeAjust->setEnabled(selection.isValid() &&
+ !selection.images().isEmpty());
+
+ connect(m_interface, SIGNAL(selectionChanged(bool)),
+ m_actionTimeAjust, SLOT(setEnabled(bool)));
+}
+
+void Plugin_TimeAdjust::slotActivate()
+{
+ KIPI::ImageCollection images = m_interface->currentSelection();
+
+ if (!images.isValid() || images.images().isEmpty())
+ return;
+
+ KIPITimeAdjustPlugin::TimeAdjustDialog dlg(m_interface, kapp->activeWindow());
+ dlg.setImages(images.images());
+ dlg.exec();
+}
+
+KIPI::Category Plugin_TimeAdjust::category( KAction* action ) const
+{
+ if ( action == m_actionTimeAjust )
+ return KIPI::IMAGESPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMAGESPLUGIN; // no warning from compiler, please
+}
diff --git a/kipi-plugins/timeadjust/plugin_timeadjust.h b/kipi-plugins/timeadjust/plugin_timeadjust.h
new file mode 100644
index 0000000..366472f
--- /dev/null
+++ b/kipi-plugins/timeadjust/plugin_timeadjust.h
@@ -0,0 +1,55 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-05-16
+ * Description : a plugin to set time stamp of picture files.
+ *
+ * Copyright (C) 2003-2005 by Jesper Pedersen <blackie@kde.org>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_TIMEADJUST_H
+#define PLUGIN_TIMEADJUST_H
+
+// LibKIPI includes.
+
+#include <libkipi/plugin.h>
+
+class KAction;
+
+class Plugin_TimeAdjust : public KIPI::Plugin
+{
+ Q_OBJECT
+
+public:
+
+ Plugin_TimeAdjust(QObject *parent, const char* name, const QStringList &args);
+
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* );
+
+protected slots:
+
+ void slotActivate();
+
+private:
+
+ KAction *m_actionTimeAjust;
+
+ KIPI::Interface *m_interface;
+};
+
+#endif // PLUGIN_TIMEADJUST_H
diff --git a/kipi-plugins/timeadjust/timeadjustdialog.cpp b/kipi-plugins/timeadjust/timeadjustdialog.cpp
new file mode 100644
index 0000000..394c110
--- /dev/null
+++ b/kipi-plugins/timeadjust/timeadjustdialog.cpp
@@ -0,0 +1,550 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-05-16
+ * Description : a plugin to set time stamp of picture files.
+ *
+ * Copyright (C) 2003-2005 by Jesper Pedersen <blackie@kde.org>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C Ansi includes.
+
+extern "C"
+{
+#include <sys/types.h>
+#include <utime.h>
+}
+
+// Qt includes.
+
+#include <qtooltip.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qvbuttongroup.h>
+#include <qvgroupbox.h>
+#include <qgroupbox.h>
+#include <qhbox.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qfile.h>
+#include <qspinbox.h>
+#include <qgrid.h>
+#include <qpushbutton.h>
+#include <qframe.h>
+#include <qtoolbutton.h>
+
+// KDE includes.
+
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kdatetimewidget.h>
+#include <kconfig.h>
+#include <kmessagebox.h>
+
+// LibKipi includes.
+
+#include <libkipi/interface.h>
+#include <libkipi/imageinfo.h>
+
+// LibKExiv2 includes.
+
+#include <libkexiv2/kexiv2.h>
+
+// Local includes.
+
+#include "kpaboutdata.h"
+#include "pluginsversion.h"
+#include "timeadjustdialog.h"
+#include "timeadjustdialog.moc"
+
+namespace KIPITimeAdjustPlugin
+{
+
+class TimeAdjustDialogPrivate
+{
+
+public:
+
+ TimeAdjustDialogPrivate()
+ {
+ add = 0;
+ subtract = 0;
+ exif = 0;
+ custom = 0;
+ syncEXIFDateCheck = 0;
+ syncIPTCDateCheck = 0;
+ exampleBox = 0;
+ adjustValGrp = 0;
+ adjustTypeGrp = 0;
+ infoLabel = 0;
+ exampleAdj = 0;
+ secs = 0;
+ minutes = 0;
+ hours = 0;
+ days = 0;
+ months = 0;
+ years = 0;
+ dateCreatedSel = 0;
+ interface = 0;
+ about = 0;
+ todayBtn = 0;
+ }
+
+ QRadioButton *add;
+ QRadioButton *subtract;
+ QRadioButton *exif;
+ QRadioButton *custom;
+
+ QToolButton *todayBtn;
+
+ QCheckBox *syncEXIFDateCheck;
+ QCheckBox *syncIPTCDateCheck;
+
+ QVGroupBox *exampleBox;
+ QVButtonGroup *adjustValGrp;
+ QButtonGroup *adjustTypeGrp;
+
+ QLabel *infoLabel;
+ QLabel *exampleAdj;
+
+ QSpinBox *secs;
+ QSpinBox *minutes;
+ QSpinBox *hours;
+ QSpinBox *days;
+ QSpinBox *months;
+ QSpinBox *years;
+
+ QDateTime exampleDate;
+
+ KDateTimeWidget *dateCreatedSel;
+
+ KURL::List images;
+
+ KIPI::Interface *interface;
+
+ KIPIPlugins::KPAboutData *about;
+};
+
+TimeAdjustDialog::TimeAdjustDialog(KIPI::Interface* interface, QWidget* parent)
+ : KDialogBase(Plain, i18n("Adjust Time & Date"), Help|Ok|Cancel,
+ Ok, parent, 0, true, true)
+{
+ d = new TimeAdjustDialogPrivate;
+ d->interface = interface;
+
+ QVBoxLayout *vlay = new QVBoxLayout(plainPage());
+
+ // -- About data and help button ----------------------------------------
+
+ d->about = new KIPIPlugins::KPAboutData(I18N_NOOP("Time Adjust"),
+ 0,
+ KAboutData::License_GPL,
+ I18N_NOOP("A Kipi plugin for adjusting time stamp of picture files"),
+ "(c) 2003-2005, Jesper K. Pedersen\n"
+ "(c) 2006-2008, Gilles Caulier");
+
+ d->about->addAuthor("Jesper K. Pedersen", I18N_NOOP("Author"),
+ "blackie@kde.org");
+
+ d->about->addAuthor("Gilles Caulier", I18N_NOOP("Developper and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ QPushButton *helpButton = actionButton(Help);
+ KHelpMenu* helpMenu = new KHelpMenu(this, d->about, false);
+ helpMenu->menu()->removeItemAt(0);
+ helpMenu->menu()->insertItem(i18n("Plugin Handbook"), this, SLOT(slotHelp()), 0, -1, 0);
+ helpButton->setPopup(helpMenu->menu());
+
+ // -- Adjustment type ------------------------------------------------------------
+
+ QVGroupBox *adjGB = new QVGroupBox(i18n("Adjustment Type"), plainPage());
+ d->adjustTypeGrp = new QButtonGroup(1, Qt::Horizontal, adjGB);
+ d->add = new QRadioButton(i18n("Add"), d->adjustTypeGrp);
+ d->subtract = new QRadioButton(i18n("Subtract"), d->adjustTypeGrp);
+ d->exif = new QRadioButton(i18n("Set file date to EXIF/IPTC creation date"), d->adjustTypeGrp);
+ d->custom = new QRadioButton(i18n("Custom date"), d->adjustTypeGrp);
+
+ d->adjustTypeGrp->setFrameStyle(QFrame::NoFrame);
+ d->adjustTypeGrp->setInsideMargin(0);
+ d->adjustTypeGrp->setRadioButtonExclusive(true);
+
+ QHBox *hbox = new QHBox(d->adjustTypeGrp);
+ QLabel *space1 = new QLabel(hbox);
+ space1->setFixedWidth(15);
+ d->dateCreatedSel = new KDateTimeWidget(hbox);
+ QLabel *space2 = new QLabel(hbox);
+ space2->setFixedWidth(15);
+ d->todayBtn = new QToolButton(hbox);
+ d->todayBtn->setIconSet(SmallIcon("today"));
+ QToolTip::add(d->todayBtn, i18n("Reset to current date"));
+ new QLabel(hbox);
+
+ d->syncEXIFDateCheck = new QCheckBox(i18n("Update EXIF creation date"), d->adjustTypeGrp);
+ d->syncIPTCDateCheck = new QCheckBox(i18n("Update IPTC creation date"), d->adjustTypeGrp);
+
+ vlay->addWidget(adjGB);
+
+ // -- Adjustments ------------------------------------------------------------
+
+ d->adjustValGrp = new QVButtonGroup(i18n("Adjustments"), plainPage());
+ vlay->addWidget(d->adjustValGrp);
+
+ QWidget* grid = new QWidget(d->adjustValGrp);
+ QGridLayout* gridLay = new QGridLayout(grid, 1, 7, spacingHint());
+ gridLay->setColStretch( 2, 1 );
+ gridLay->setColStretch( 5, 1 );
+
+ QLabel* label = new QLabel( i18n("Hours:"), grid );
+ d->hours = new QSpinBox( 0, 1000, 1, grid );
+ gridLay->addWidget( label, 0, 0 );
+ gridLay->addWidget( d->hours, 0, 1 );
+
+ label = new QLabel( i18n("Minutes:"), grid );
+ d->minutes = new QSpinBox( 0, 1000, 1, grid );
+ gridLay->addWidget( label, 0, 3 );
+ gridLay->addWidget( d->minutes, 0, 4 );
+
+ label = new QLabel( i18n("Seconds:"), grid );
+ d->secs = new QSpinBox( 0, 1000, 1, grid );
+ gridLay->addWidget( label, 0, 6 );
+ gridLay->addWidget( d->secs, 0, 7 );
+
+ label = new QLabel( i18n("Days:"), grid );
+ d->days = new QSpinBox( 0, 1000, 1, grid );
+ gridLay->addWidget( label, 1, 0 );
+ gridLay->addWidget( d->days, 1, 1 );
+
+ label = new QLabel( i18n("Months:"), grid );
+ d->months = new QSpinBox( 0, 1000, 1, grid );
+ gridLay->addWidget( label, 1, 3 );
+ gridLay->addWidget( d->months, 1, 4 );
+
+ label = new QLabel( i18n("Years:"), grid );
+ d->years = new QSpinBox( 0, 1000, 1, grid );
+ gridLay->addWidget( label, 1, 6 );
+ gridLay->addWidget( d->years, 1, 7 );
+
+ // -- Example ------------------------------------------------------------
+
+ d->exampleBox = new QVGroupBox(i18n("Example"), plainPage());
+ vlay->addWidget(d->exampleBox);
+
+ d->infoLabel = new QLabel(d->exampleBox);
+ d->exampleAdj = new QLabel(d->exampleBox);
+ d->exampleAdj->setAlignment(Qt::AlignCenter);
+
+ vlay->addStretch();
+
+ // -- Slots/Signals ------------------------------------------------------
+
+ connect(d->adjustTypeGrp, SIGNAL( clicked(int) ),
+ this, SLOT( slotAdjustmentTypeChanged() ));
+
+ connect(d->secs, SIGNAL( valueChanged( int ) ),
+ this, SLOT( slotUpdateExample() ));
+
+ connect(d->minutes, SIGNAL( valueChanged( int ) ),
+ this, SLOT( slotUpdateExample() ));
+
+ connect(d->hours, SIGNAL( valueChanged( int ) ),
+ this, SLOT( slotUpdateExample() ));
+
+ connect(d->days, SIGNAL( valueChanged( int ) ),
+ this, SLOT( slotUpdateExample() ));
+
+ connect(d->months, SIGNAL( valueChanged( int ) ),
+ this, SLOT( slotUpdateExample() ));
+
+ connect(d->years, SIGNAL( valueChanged( int ) ),
+ this, SLOT( slotUpdateExample() ));
+
+ connect(d->todayBtn, SIGNAL(clicked()),
+ this, SLOT(slotResetDateToCurrent()));
+
+ // -----------------------------------------------------------------------
+
+ readSettings();
+ slotAdjustmentTypeChanged();
+}
+
+TimeAdjustDialog::~TimeAdjustDialog()
+{
+ delete d->about;
+ delete d;
+}
+
+void TimeAdjustDialog::slotHelp()
+{
+ KApplication::kApplication()->invokeHelp("timeadjust", "kipi-plugins");
+}
+
+void TimeAdjustDialog::slotResetDateToCurrent()
+{
+ d->dateCreatedSel->setDateTime(QDateTime::currentDateTime());
+}
+
+void TimeAdjustDialog::closeEvent(QCloseEvent *e)
+{
+ if (!e) return;
+ saveSettings();
+ e->accept();
+}
+
+void TimeAdjustDialog::slotCancel()
+{
+ saveSettings();
+ KDialogBase::slotCancel();
+}
+
+void TimeAdjustDialog::readSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Time Adjust Settings");
+
+ int adjType = config.readNumEntry("Adjustment Type", 0); // add by default.
+ if (adjType == 0) d->add->setChecked(true);
+ if (adjType == 1) d->subtract->setChecked(true);
+ if (adjType == 2) d->exif->setChecked(true);
+ if (adjType == 3) d->custom->setChecked(true);
+
+ QDateTime current = QDateTime::currentDateTime();
+ d->dateCreatedSel->setDateTime(config.readDateTimeEntry("Custom Date", &current));
+
+ d->syncEXIFDateCheck->setChecked(config.readBoolEntry("Sync EXIF Date", true));
+ d->syncIPTCDateCheck->setChecked(config.readBoolEntry("Sync IPTC Date", true));
+ resize(configDialogSize(config, QString("Time Adjust Dialog")));
+}
+
+void TimeAdjustDialog::saveSettings()
+{
+ KConfig config("kipirc");
+ config.setGroup("Time Adjust Settings");
+
+ int adjType = 0; // add
+ if (d->subtract->isChecked()) adjType = 1;
+ if (d->exif->isChecked()) adjType = 2;
+ if (d->custom->isChecked()) adjType = 3;
+ config.writeEntry("Adjustment Type", adjType);
+
+ config.writeEntry("Custom Date", d->dateCreatedSel->dateTime());
+
+ config.writeEntry("Sync EXIF Date", d->syncEXIFDateCheck->isChecked());
+ config.writeEntry("Sync IPTC Date", d->syncIPTCDateCheck->isChecked());
+ saveDialogSize(config, QString("Time Adjust Dialog"));
+ config.sync();
+}
+
+void TimeAdjustDialog::setImages(const KURL::List& images)
+{
+ d->images.clear();
+ int exactCount = 0;
+ int inexactCount = 0;
+
+ for( KURL::List::ConstIterator it = images.begin(); it != images.end(); ++it )
+ {
+ KIPI::ImageInfo info = d->interface->info( *it );
+ if (info.isTimeExact())
+ {
+ exactCount++;
+ d->exampleDate = info.time();
+ d->images.append(*it);
+ }
+ else
+ inexactCount++;
+ }
+
+ if ( inexactCount > 0 )
+ {
+ QString tmpLabel = i18n("1 image will be changed; ",
+ "%n images will be changed; ",
+ exactCount)
+ + i18n("1 image will be skipped due to an inexact date.",
+ "%n images will be skipped due to inexact dates.",
+ inexactCount );
+
+ d->infoLabel->setText(tmpLabel);
+ }
+ else
+ {
+ d->infoLabel->setText(i18n("1 image will be changed",
+ "%n images will be changed",
+ d->images.count()));
+ }
+ // PENDING(blackie) handle all images being inexact.
+
+ slotUpdateExample();
+}
+
+void TimeAdjustDialog::slotUpdateExample()
+{
+ QString oldDate = d->exampleDate.toString(Qt::LocalDate);
+ QDateTime date = updateTime(KURL(), d->exampleDate);
+ QString newDate = date.toString(Qt::LocalDate);
+ d->exampleAdj->setText(i18n("<b>%1</b><br>would, for example, "
+ "change into<br><b>%2</b>")
+ .arg(oldDate).arg(newDate));
+}
+
+void TimeAdjustDialog::slotAdjustmentTypeChanged()
+{
+ d->exampleBox->setEnabled(false);
+ d->adjustValGrp->setEnabled(false);
+ d->dateCreatedSel->setEnabled(false);
+ d->todayBtn->setEnabled(false);
+ d->syncEXIFDateCheck->setEnabled(false);
+ d->syncIPTCDateCheck->setEnabled(false);
+
+ if (d->add->isChecked() || d->subtract->isChecked())
+ {
+ d->exampleBox->setEnabled(true);
+ d->adjustValGrp->setEnabled(true);
+ d->syncEXIFDateCheck->setEnabled(true);
+ d->syncIPTCDateCheck->setEnabled(true);
+ }
+ else if (d->custom->isChecked())
+ {
+ d->dateCreatedSel->setEnabled(true);
+ d->todayBtn->setEnabled(true);
+ d->syncEXIFDateCheck->setEnabled(true);
+ d->syncIPTCDateCheck->setEnabled(true);
+ }
+}
+
+void TimeAdjustDialog::slotOk()
+{
+ KURL::List updatedURLs;
+ QStringList errorFiles;
+
+ for( KURL::List::ConstIterator it = d->images.begin(); it != d->images.end(); ++it )
+ {
+ KURL url = *it;
+ KIPI::ImageInfo info = d->interface->info(url);
+ QDateTime dateTime = info.time();
+ dateTime = updateTime(info.path(), info.time());
+ info.setTime(dateTime);
+
+ if (d->syncEXIFDateCheck->isChecked() || d->syncIPTCDateCheck->isChecked())
+ {
+ bool ret = true;
+ if (!KExiv2Iface::KExiv2::isReadOnly(url.path()))
+ {
+ KExiv2Iface::KExiv2 exiv2Iface;
+
+ ret &= exiv2Iface.load(url.path());
+ if (ret)
+ {
+ if (d->syncEXIFDateCheck->isChecked())
+ {
+ ret &= exiv2Iface.setExifTagString("Exif.Image.DateTime",
+ dateTime.toString(QString("yyyy:MM:dd hh:mm:ss")).ascii());
+ ret &= exiv2Iface.setExifTagString("Exif.Photo.DateTimeOriginal",
+ dateTime.toString(QString("yyyy:MM:dd hh:mm:ss")).ascii());
+ }
+
+ if (d->syncIPTCDateCheck->isChecked())
+ {
+ ret &= exiv2Iface.setIptcTagString("Iptc.Application2.DateCreated",
+ dateTime.date().toString(Qt::ISODate));
+ ret &= exiv2Iface.setIptcTagString("Iptc.Application2.TimeCreated",
+ dateTime.time().toString(Qt::ISODate));
+ }
+
+ ret &= exiv2Iface.save(url.path());
+
+ if (!ret)
+ {
+ kdDebug() << "Failed to save metadata to file " << url.fileName() << endl;
+ }
+ }
+ else
+ {
+ kdDebug() << "Failed to load metadata from file " << url.fileName() << endl;
+ }
+ }
+
+ if (!ret)
+ errorFiles.append(url.fileName());
+ else
+ updatedURLs.append(url);
+ }
+
+ // See B.K.O #138880: set the file acess and modification time (after than Exiv2 play with metadata).
+ struct utimbuf ut;
+ ut.modtime = dateTime.toTime_t();
+ ut.actime = dateTime.toTime_t();
+ ::utime(QFile::encodeName(url.path()), &ut);
+ }
+
+ // We use kipi interface refreshImages() method to tell to host than
+ // metadata from pictures have changed and need to be re-read.
+ d->interface->refreshImages(d->images);
+
+ if (!errorFiles.isEmpty() && (d->syncEXIFDateCheck->isChecked() || d->syncIPTCDateCheck->isChecked()))
+ {
+ KMessageBox::informationList(
+ kapp->activeWindow(),
+ i18n("Unable to set date and time like picture metadata from:"),
+ errorFiles,
+ i18n("Adjust Time & Date"));
+ }
+
+ saveSettings();
+ accept();
+}
+
+QDateTime TimeAdjustDialog::updateTime(const KURL& url, const QDateTime& time) const
+{
+ if (d->custom->isChecked())
+ {
+ return d->dateCreatedSel->dateTime();
+ }
+ else if (d->exif->isChecked())
+ {
+ KExiv2Iface::KExiv2 exiv2Iface;
+ if ( !exiv2Iface.load(url.path()) )
+ return time;
+
+ QDateTime newTime = exiv2Iface.getImageDateTime();
+ if (newTime.isValid())
+ return newTime;
+ else
+ return time;
+ }
+ else
+ {
+ int sign = -1;
+ if (d->add->isChecked())
+ sign = 1;
+
+ QDateTime newTime = time.addSecs( sign * ( d->secs->value()
+ + 60*d->minutes->value()
+ + 60*60*d->hours->value()
+ + 24*60*60*d->days->value() ) );
+ newTime = newTime.addMonths( sign * d->months->value() );
+ newTime = newTime.addYears( sign * d->years->value() );
+ return newTime;
+ }
+}
+
+} // NameSpace KIPITimeAdjustPlugin
diff --git a/kipi-plugins/timeadjust/timeadjustdialog.h b/kipi-plugins/timeadjust/timeadjustdialog.h
new file mode 100644
index 0000000..d8d8196
--- /dev/null
+++ b/kipi-plugins/timeadjust/timeadjustdialog.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2004-05-16
+ * Description : a plugin to set time stamp of picture files.
+ *
+ * Copyright (C) 2003-2005 by Jesper Pedersen <blackie@kde.org>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 TIMEADJUSTDIALOG_H
+#define TIMEADJUSTDIALOG_H
+
+// Qt includes.
+
+#include <qdatetime.h>
+
+// KDE includes.
+
+#include <kdialogbase.h>
+#include <kurl.h>
+
+namespace KIPI
+{
+ class Interface;
+}
+
+namespace KIPITimeAdjustPlugin
+{
+
+class TimeAdjustDialogPrivate;
+
+class TimeAdjustDialog :public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ TimeAdjustDialog(KIPI::Interface* interface, QWidget* parent);
+ ~TimeAdjustDialog();
+
+ void setImages(const KURL::List& images);
+
+protected:
+
+ void closeEvent(QCloseEvent *);
+
+private slots:
+
+ void slotUpdateExample();
+ void slotAdjustmentTypeChanged();
+ void slotOk();
+ void slotCancel();
+ void slotHelp();
+ void slotResetDateToCurrent();
+
+private:
+
+ void readSettings();
+ void saveSettings();
+ QDateTime updateTime(const KURL& url, const QDateTime& time) const;
+
+private:
+
+ TimeAdjustDialogPrivate *d;
+};
+
+} // NameSpace KIPITimeAdjustPlugin
+
+#endif /* TIMEADJUSTDIALOG_H */
+
diff --git a/kipi-plugins/tips b/kipi-plugins/tips
new file mode 100644
index 0000000..e729a53
--- /dev/null
+++ b/kipi-plugins/tips
@@ -0,0 +1,238 @@
+<tip category="Kipi|BatchProcessImages">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that you could brighten up your images using Batch Color Images plugin for increased contrast?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|Slideshow">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that you could abort a slideshow using <b>ESC</b>?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|Scanner">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that Kipi library provide a scanner plugin that gives you direct access to your scanner?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|Screenshot">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that you can take a screenshot with the Kipi library and save the result to an Album with some comments?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|ConvertImages">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that you can use the <b>LZW</b> compression to reduce the size of the <b>TIFF</b> image files in the Convert Images plugin?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|BatchProcessImages">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that all image operations in the batch processing images plugins run without losing the <b>Exif</b> information in the <b>JPEG</b> files?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|FilterImages">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that the <b>Noise Reduction</b> option in the <b>Filter Images</b> plugin can be used to improve the rendering of images taken with an analog camera?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|SendImages">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that you can use the drag and drop feature in e-mail images to add some items to the list?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|RecompressImages">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that if you want to reduce the space disk used by your images in the Albums database, you could try using the Recompress Images plugin?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|ResizeImages">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that if you want to resize images to prepare them for printing on photographic paper sizes, you could use the Resize Images plugin?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|BatchProcessImages">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that you could use image files from different Albums in the 'batch-process images'
+plugin? The processed results will then be merged in the selected target Album.
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|BatchRenameImages">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that you can change the time stamp of the target images files in the batch-rename images plugin?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|SlideShow">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that you can navigate on the slideshow with the left and right mouse buttons?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
+
+<tip category="Kipi|General">
+<html>
+<p>
+<table border="0" cellpadding="0" cellspacing="10" align="center">
+<tr>
+<td>
+<img src="hicolor/32x32/apps/kipi.png">
+</td>
+<td>
+Did you know that Kipi plugins can be used also in Digikam, KPhotoalbum, Showimg, and Gwenview programs?
+</td>
+</tr>
+</table>
+</p>
+</html>
+</tip>
diff --git a/kipi-plugins/wallpaper/Makefile.am b/kipi-plugins/wallpaper/Makefile.am
new file mode 100644
index 0000000..8d980d0
--- /dev/null
+++ b/kipi-plugins/wallpaper/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES = $(LIBKIPI_CFLAGS) $(all_includes)
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = kipiplugin_wallpaper.la
+kipiplugin_wallpaper_la_DEPENDENCIES = $(LIBKIPI_LIBS_DEP)
+kipiplugin_wallpaper_la_SOURCES = plugin_wallpaper.cpp
+
+kipiplugin_wallpaper_la_LIBADD = $(LIBKIPI_LIBS) $(LIB_KIO) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT)
+
+kipiplugin_wallpaper_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+pluginsdir = $(kde_datadir)/kipi/plugins
+
+kde_services_DATA = kipiplugin_wallpaper.desktop
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kipiplugin_wallpaper.pot
+
diff --git a/kipi-plugins/wallpaper/kipiplugin_wallpaper.desktop b/kipi-plugins/wallpaper/kipiplugin_wallpaper.desktop
new file mode 100644
index 0000000..1f52612
--- /dev/null
+++ b/kipi-plugins/wallpaper/kipiplugin_wallpaper.desktop
@@ -0,0 +1,62 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=WallPaper
+Name[br]=paper-moger
+Name[ca]=Paper pintat
+Name[cs]=Tapeta
+Name[da]=Tapet
+Name[de]=Hintergrundbild
+Name[el]=Ταπετσαρία
+Name[es]=Fondo de escritorio
+Name[et]=Taustapilt
+Name[fi]=Taustakuva
+Name[gl]=Fondo de Escritório
+Name[is]=VeggFóður
+Name[it]=Sfondo
+Name[ms]=Kertas Dinding
+Name[nds]=Achtergrundbild
+Name[nl]=Bureaubladachtergrond
+Name[pa]=ਕੰਧ-ਚਿੱਤਰ
+Name[pl]=Tapeta
+Name[pt]=Papel de Parede
+Name[sr]=Позадина
+Name[sr@Latn]=Pozadina
+Name[sv]=Skrivbordsunderlägg
+Name[tg]=Сурати экран
+Name[tr]=DuvarKağıdı
+Name[uk]=Шпалери
+Name[xx]=xxWallPaperxx
+Name[zh_CN]=壁纸
+Comment=KIPI Set Wall Paper Plugin
+Comment[ca]=Connector del KIPI per a fixar un paper pintat
+Comment[cs]=KIPI modul nastavení tapety
+Comment[da]=KIPI-plugin: Angiv tapet
+Comment[de]=Ein KIPI-Modul zum Setzen des Hintergrundbildes
+Comment[el]=Πρόσθετο ορισμού ταπετσαρίας του KIPI
+Comment[es]=Complemento de KIPI para establecer el fondo del escritorio
+Comment[et]=KIPI taustapildi seadmise plugin
+Comment[fi]=Kipi-liitännäinen työpöydän taustakuvan asetusta varten
+Comment[fr]=Module externe KIPI pour modifier le fond d'écran
+Comment[gl]=Plugin de KIPI para Cambiar o Fondo do Escritório
+Comment[is]=KIPI íforrit til að skipta um bakgrunnsmynd
+Comment[it]=Plugin di impostazione dello sfondo di KIPI
+Comment[ja]=Kipi 壁紙設定プラグイン
+Comment[ms]=Plugin Tetap Kertas Dinding KIPI
+Comment[nds]=KIPI-Moduul för't Fastleggen vun den Achtergrund
+Comment[nl]=KIPI-plugin voor het instellen van de bureaubladachtergrond
+Comment[pa]=KIPI ਕੰਧ-ਚਿੱਤਰ ਲਗਾਉਣ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka KIPI - Ustawianie tapety
+Comment[pt]='Plugin' de Mudança do Papel de Parede do KIPI
+Comment[pt_BR]=Plugin para Configuração de Papel de Parede do KIPI
+Comment[sr]=KIPI прикључак за постављање позадине
+Comment[sr@Latn]=KIPI priključak za postavljanje pozadine
+Comment[sv]=KIPI-insticksprogram: Ange skrivbordsunderlägg
+Comment[tg]=Модули KIPI барои тайини сурати экран
+Comment[tr]=KIPI Duvar Kağıdı Yapma Eklentisi
+Comment[uk]=Втулок KIPI для встановлення шпалерів
+Comment[xx]=xxKIPI Set Wall Paper Pluginxx
+Comment[zh_CN]=KIPI 设定壁纸插件
+Type=Service
+ServiceTypes=KIPI/Plugin
+X-KDE-Library=kipiplugin_wallpaper
+author=Gregory KOKANOSKY, gregory.kokanosky@free.fr
diff --git a/kipi-plugins/wallpaper/plugin_wallpaper.cpp b/kipi-plugins/wallpaper/plugin_wallpaper.cpp
new file mode 100644
index 0000000..e4e5074
--- /dev/null
+++ b/kipi-plugins/wallpaper/plugin_wallpaper.cpp
@@ -0,0 +1,274 @@
+/* ============================================================
+ * File : plugin_wallpaper.cpp
+ *
+ * Authors: Gregory KOKANOSKY <gregory dot kokanosky at free.fr>
+ * Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Date : 01/2004
+ *
+ * Description : Set Wall paper plugin for KIPI
+ *
+ * Copyright 2004 by Gregory KOKANOSKY <gregory dot kokanosky at free.fr>
+ * Copyright 2004 by Gilles CAULIER <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * ============================================================ */
+
+// Include files for KDE
+
+ #include <klocale.h>
+ #include <kaction.h>
+ #include <kgenericfactory.h>
+ #include <klibloader.h>
+ #include <kconfig.h>
+ #include <kdebug.h>
+ #include <kdeversion.h>
+ #include <krun.h>
+ #include <kapplication.h>
+ #include <kmessagebox.h>
+ #include <ktextbrowser.h>
+ #include <kdeversion.h>
+ #include <kfiledialog.h>
+ #include <kio/netaccess.h>
+
+// KIPI includes
+
+ #include <libkipi/interface.h>
+ #include <libkipi/imagecollection.h>
+
+// Local includes
+
+ #include "plugin_wallpaper.h"
+
+typedef KGenericFactory<Plugin_WallPaper> Factory;
+
+K_EXPORT_COMPONENT_FACTORY( kipiplugin_wallpaper,
+ Factory("kipiplugin_wallpaper"))
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ Plugin_WallPaper::Plugin_WallPaper(QObject *parent, const char*, const QStringList&)
+ : KIPI::Plugin( Factory::instance(), parent, "WallPaper")
+ {
+ kdDebug( 51001 ) << "Plugin_WallPaper plugin loaded" << endl;
+ }
+
+void Plugin_WallPaper::setup( QWidget* widget )
+{
+ KIPI::Plugin::setup( widget );
+
+ m_action_Background = new KActionMenu(i18n("&Set as Background"),
+ actionCollection(),
+ "images2desktop");
+
+ m_action_Background->insert(new KAction (i18n("Centered"),
+ 0,
+ this,
+ SLOT(slotSetCenter()),
+ actionCollection(),
+ "images2desktop_center"));
+
+ m_action_Background->insert(new KAction (i18n("Tiled"),
+ 0,
+ this,
+ SLOT(slotSetTiled()),
+ actionCollection(),
+ "images2desktop_tiled"));
+
+ m_action_Background->insert(new KAction (i18n("Centered Tiled"),
+ 0,
+ this,
+ SLOT(slotSetCenterTiled()),
+ actionCollection(),
+ "images2desktop_center_tiled"));
+
+ m_action_Background->insert(new KAction (i18n("Centered Max-Aspect"),
+ 0,
+ this,
+ SLOT(slotSetCenteredMaxpect()),
+ actionCollection(),
+ "images2desktop_center_maxpect"));
+
+ m_action_Background->insert(new KAction (i18n("Tiled Max-Aspect"),
+ 0,
+ this,
+ SLOT(slotSetTiledMaxpect()),
+ actionCollection(),
+ "images2desktop_tiled_maxpect"));
+
+ m_action_Background->insert(new KAction (i18n("Scaled"),
+ 0,
+ this,
+ SLOT(slotSetScaled()),
+ actionCollection(),
+ "images2desktop_scaled"));
+
+ m_action_Background->insert(new KAction (i18n("Centered Auto Fit"),
+ 0,
+ this,
+ SLOT(slotSetCenteredAutoFit()),
+ actionCollection(),
+ "images2desktop_centered_auto_fit"));
+
+ //The Scale & crop code was available from Beta1 on
+ #if KDE_IS_VERSION(3,3,91)
+ m_action_Background->insert(new KAction (i18n("Scale && Crop"),
+ 0,
+ this,
+ SLOT(slotSetScaleAndCrop()),
+ actionCollection(),
+ "images2desktop_scale_and_crop"));
+
+ #endif
+
+ addAction( m_action_Background );
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection selection = interface->currentSelection();
+ m_action_Background->setEnabled( selection.isValid() );
+
+ connect( interface, SIGNAL(selectionChanged(bool)),
+ m_action_Background, SLOT(setEnabled(bool)));
+ }
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_WallPaper::slotSetCenter()
+{
+ return setWallpaper(CENTER);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_WallPaper::slotSetTiled()
+{
+ return setWallpaper(TILED);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_WallPaper::slotSetCenterTiled()
+{
+ return setWallpaper(CENTER_TILED);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_WallPaper::slotSetCenteredMaxpect()
+{
+ return setWallpaper(CENTER_MAXPECT);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_WallPaper::slotSetTiledMaxpect()
+{
+ return setWallpaper(TILED_MAXPECT);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_WallPaper::slotSetScaled()
+{
+ return setWallpaper(SCALED);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_WallPaper::slotSetCenteredAutoFit()
+{
+ return setWallpaper(CENTERED_AUTOFIT);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_WallPaper::slotSetScaleAndCrop()
+{
+ return setWallpaper(SCALE_AND_CROP);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Plugin_WallPaper::setWallpaper(int layout)
+{
+ if (layout>SCALE_AND_CROP || layout < CENTER)
+ return;
+
+ KIPI::Interface* interface = dynamic_cast<KIPI::Interface*>( parent() );
+
+ if ( !interface )
+ {
+ kdError( 51000 ) << "Kipi interface is null!" << endl;
+ return;
+ }
+
+ KIPI::ImageCollection images = interface->currentSelection();
+
+ if (!images.isValid() ) return;
+
+ KURL url=images.images()[0];
+ QString path;
+ if (url.isLocalFile())
+ {
+ path=url.path();
+ }
+ else
+ {
+ // PENDING We need a way to get a parent widget
+ // Sun, 06 Jun 2004 - Aur�ien
+
+ KMessageBox::information( kapp->activeWindow(), i18n(
+ "<qt><p>You selected a remote image. It needs to be saved to your local disk to be used as a wallpaper."
+ "</p><p>You will now be asked where to save the image.</p></qt>"));
+ path = KFileDialog::getSaveFileName(url.fileName(), QString::null, kapp->activeWindow());
+
+ if (path.isNull()) return;
+#if KDE_VERSION > 0x30200
+ KIO::NetAccess::download(url, path, 0L);
+#else
+ KIO::NetAccess::download(url, path);
+#endif
+ }
+
+ QString cmd = QString("dcop kdesktop KBackgroundIface setWallpaper '%1' %2")
+ .arg(path).arg(layout);
+
+ KRun::runCommand(cmd);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+KIPI::Category Plugin_WallPaper::category( KAction* action ) const
+{
+ if ( action == m_action_Background )
+ return KIPI::IMAGESPLUGIN;
+
+ kdWarning( 51000 ) << "Unrecognized action for plugin category identification" << endl;
+ return KIPI::IMAGESPLUGIN; // no warning from compiler, please
+}
+
+#include "plugin_wallpaper.moc"
diff --git a/kipi-plugins/wallpaper/plugin_wallpaper.h b/kipi-plugins/wallpaper/plugin_wallpaper.h
new file mode 100644
index 0000000..9953ad7
--- /dev/null
+++ b/kipi-plugins/wallpaper/plugin_wallpaper.h
@@ -0,0 +1,81 @@
+/* ============================================================
+ * File : plugin_wallpaper.h
+ *
+ * Authors: Gregory KOKANOSKY <gregory dot kokanosky at free.fr>
+ * Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Date : 01/2004
+ *
+ * Description : Wall Paper plugin parts for KII
+ *
+ * Copyright 2004 by Gregory KOKANOSKY <gregory dot kokanosky at free.fr>
+ * Copyright 2004 by Gilles CAULIER <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 PLUGIN_IMAGES2DESKTOP_H
+ #define PLUGIN_IMAGES2DESKTOP_H
+
+ // Include files for KDE
+
+ #include <kprocess.h>
+
+ // KIPI includes
+
+ #include <libkipi/plugin.h>
+
+ class KActionMenu;
+ class KAction;
+
+ class Plugin_WallPaper : public KIPI::Plugin
+ {
+ Q_OBJECT
+
+ public:
+
+ Plugin_WallPaper(QObject *parent,
+ const char* name,
+ const QStringList &args);
+ virtual KIPI::Category category( KAction* action ) const;
+ virtual void setup( QWidget* );
+
+ private slots:
+
+ void slotSetCenter();
+ void slotSetTiled();
+ void slotSetCenterTiled();
+ void slotSetCenteredMaxpect();
+ void slotSetTiledMaxpect();
+ void slotSetScaled();
+ void slotSetCenteredAutoFit();
+ void slotSetScaleAndCrop();
+
+ private:
+
+ enum {
+ CENTER = 1,
+ TILED = 2,
+ CENTER_TILED = 3,
+ CENTER_MAXPECT = 4,
+ TILED_MAXPECT = 5,
+ SCALED = 6,
+ CENTERED_AUTOFIT = 7,
+ SCALE_AND_CROP = 8
+ };
+
+ KActionMenu *m_action_Background;
+ void setWallpaper( int layout );
+ };
+
+ #endif // PLUGIN_IMAGES2DESKTOP_H