diff -Nur gpssync.orig/gpsdataparser.cpp gpssync/gpsdataparser.cpp --- gpssync.orig/gpsdataparser.cpp 2006-10-28 12:58:45.000000000 +0200 +++ gpssync/gpsdataparser.cpp 2007-03-28 09:32:45.000000000 +0200 @@ -267,5 +267,15 @@ return true; } +QString GPSDataParser::lineString() { + QString line = ""; + for (GPSDataMap::Iterator it = m_GPSDataMap.begin(); + it != m_GPSDataMap.end(); ++it ) + { + line += QString("%1,%2,%3 ").arg(it.data().longitude()).arg(it.data().latitude()).arg(it.data().altitude()); + } + return line; +} + } // NameSpace KIPIGPSSyncPlugin diff -Nur gpssync.orig/gpsdataparser.h gpssync/gpsdataparser.h --- gpssync.orig/gpsdataparser.h 2006-10-28 12:58:45.000000000 +0200 +++ gpssync/gpsdataparser.h 2007-03-28 08:59:15.000000000 +0200 @@ -26,6 +26,7 @@ #include #include +#include // KDE includes. @@ -53,6 +54,7 @@ bool matchDate(QDateTime photoDateTime, int maxGapTime, int timeZone, bool interpolate, int interpolationDstTime, GPSDataContainer& gpsData); + QString lineString(); private: diff -Nur gpssync.orig/kmlexportconfig.cpp gpssync/kmlexportconfig.cpp --- gpssync.orig/kmlexportconfig.cpp 1970-01-01 01:00:00.000000000 +0100 +++ gpssync/kmlexportconfig.cpp 2007-03-28 00:20:01.000000000 +0200 @@ -0,0 +1,355 @@ +/*************************************************************************** + * Copyright (C) 2007 by Shadow Walker * + * shadow.walker@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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +// Qt includes. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// KDE includes. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Local includes. + +#include "kmlexportconfig.h" + +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, true ) +{ + if ( !name ) + setName( "KMLExportConfig" ); + setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, + (QSizePolicy::SizeType)0, 0, 0, sizePolicy().hasHeightForWidth() ) ); + KMLExportConfigLayout = new QGridLayout ( plainPage(), 1, 4, 0, spacingHint()); + + //--------------------------------------------- + + QFrame *headerFrame = new QFrame( plainPage() ); + headerFrame->setFrameStyle(QFrame::Panel|QFrame::Sunken); + QHBoxLayout* layout = new QHBoxLayout( headerFrame ); + layout->setMargin( 2 ); // to make sure the frame gets displayed + layout->setSpacing( 0 ); + QLabel *pixmapLabelLeft = new QLabel( headerFrame, "pixmapLabelLeft" ); + pixmapLabelLeft->setScaledContents( false ); + layout->addWidget( pixmapLabelLeft ); + QLabel *labelTitle = new QLabel( i18n("KML Export"), + headerFrame, "labelTitle" ); + layout->addWidget( labelTitle ); + layout->setStretchFactor( labelTitle, 1 ); + + QString directory; + KGlobal::dirs()->addResourceType("kipi_banner_left", KGlobal::dirs()->kde_default("data") + "kipi/data"); + directory = KGlobal::dirs()->findResourceDir("kipi_banner_left", "banner_left.png"); + + pixmapLabelLeft->setPaletteBackgroundColor( QColor(201, 208, 255) ); + pixmapLabelLeft->setPixmap( QPixmap( directory + "banner_left.png" ) ); + labelTitle->setPaletteBackgroundColor( QColor(201, 208, 255) ); + headerFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + KMLExportConfigLayout->addWidget( headerFrame, 0, 0 ); + + // -------------------------------------------------------------- + // Target preferences + TargetPreferenceGroupBox = new QGroupBox(0, Qt::Vertical, i18n( "Target Preferences" ), plainPage()); + TargetPreferenceGroupBoxLayout = new QGridLayout( TargetPreferenceGroupBox->layout(), 5, 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, and icons are sqarred ones" ) ); + + + // target preference, suite + TargetPreferenceGroupBoxLayout->addMultiCellWidget( buttonGroupTargetType, 0, 1, 0, 4 ); + + destinationDirectoryLabel_ = new QLabel( i18n( "Destination Directory" ), + TargetPreferenceGroupBox, "destinationDirectoryLabel_" ); + TargetPreferenceGroupBoxLayout->addMultiCellWidget( destinationDirectoryLabel_, 2, 2, 0, 2 ); + + DestinationDirectory_ = new QLineEdit( TargetPreferenceGroupBox, "DestinationDirectory_" ); + TargetPreferenceGroupBoxLayout->addMultiCellWidget( DestinationDirectory_, 2, 2, 3, 4 ); + + FileNameLabel_ = new QLabel( i18n( "File Name" ), + TargetPreferenceGroupBox, "FileNameLabel_" ); + TargetPreferenceGroupBoxLayout->addWidget( FileNameLabel_, 4, 0 ); + + FileName_ = new QLineEdit( TargetPreferenceGroupBox, "FileName_" ); + TargetPreferenceGroupBoxLayout->addMultiCellWidget( FileName_, 4, 4, 1, 4 ); + + DestinationUrlLabel_ = new QLabel( i18n( "Destination URL" ), + TargetPreferenceGroupBox, "DestinationUrlLabel_" ); + TargetPreferenceGroupBoxLayout->addMultiCellWidget( DestinationUrlLabel_, 3, 3, 0, 1 ); + + DestinationURL_ = new QLineEdit( TargetPreferenceGroupBox, "DestinationURL_" ); + TargetPreferenceGroupBoxLayout->addMultiCellWidget( DestinationURL_, 3, 3, 2, 4 ); + + KMLExportConfigLayout->addWidget( TargetPreferenceGroupBox, 1, 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( "Icons 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( "Images 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, 2, 0 ); + + + // -------------------------------------------------------------- + // GPX Tracks + QGroupBox *GPXTracksGroupBox = new QGroupBox(0, Qt::Vertical, i18n( "GPX Tracks" ), plainPage()); + QGridLayout *GPXTracksGroupBoxLayout = new QGridLayout( GPXTracksGroupBox->layout(), 1, 2, 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 , 1); + + // file selector + GPXFileLabel_ = new QLabel( i18n( "GPX File" ), + GPXTracksGroupBox, "GPXFileLabel_" ); + GPXTracksGroupBoxLayout->addWidget( GPXFileLabel_, 1, 0 ); + + GPXFileKURLRequester_ = new KURLRequester( GPXTracksGroupBox, "GPXFileKURLRequester" ); + GPXFileKURLRequester_->setFilter(i18n("%1|GPS Exchange Format").arg("*.gpx")); + GPXFileKURLRequester_->setCaption(i18n("Select GPX File to Load")); + + GPXTracksGroupBoxLayout->addWidget( GPXFileKURLRequester_, 1, 1 ); + // TODO GMT Adjust + // color + // elevation? + + KMLExportConfigLayout->addWidget( GPXTracksGroupBox, 3, 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"), + NULL, + 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("KMLExport 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); + } else { + GPXFileKURLRequester_->setEnabled(false); + GPXFileLabel_->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_->text(); + 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("UseGPXTracks", GPXTracksCheckBox_->isChecked()); + + config_->writeEntry("GPXFile", GPXFileKURLRequester_->lineEdit()->originalText()); + + config_->sync(); +} + +void KMLExportConfig::readSettings() +{ + bool localTarget; + bool optimize_googlemap; + int iconSize; + // int googlemapSize; + int size; + QString UrlDestDir; + QString baseDestDir; + QString KMLFileName; + bool GPXtracks; + QString GPXFile; + + localTarget = config_->readBoolEntry("localTarget", true); + optimize_googlemap = config_->readBoolEntry("optimize_googlemap", false); + iconSize = config_->readNumEntry("iconSize", 33); + // 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"); + GPXtracks = config_->readBoolEntry("UseGPXTracks", false); + GPXFile = config_->readEntry("GPXFile", ""); + + // -- Apply Settings to widgets ------------------------------ + + LocalTargetRadioButton_->setChecked(localTarget); + GoogleMapTargetRadioButton_->setChecked(optimize_googlemap); + + IconSizeInput_->setValue(iconSize); + ImageSizeInput_->setValue(size); + + DestinationDirectory_->setText(baseDestDir); + DestinationURL_->setText(UrlDestDir); + FileName_->setText(KMLFileName); + +} + +} //namespace + +#include "kmlexportconfig.moc" diff -Nur gpssync.orig/kmlexportconfig.h gpssync/kmlexportconfig.h --- gpssync.orig/kmlexportconfig.h 1970-01-01 01:00:00.000000000 +0100 +++ gpssync/kmlexportconfig.h 2007-03-27 22:20:21.000000000 +0200 @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 2007 by Shadow Walker * + * shadow.walker@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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef KMLEXPORTCONFIG_H +#define KMLEXPORTCONFIG_H + +#include +#include "kpaboutdata.h" +#include +#include "kurlrequester.h" +#include "qcheckbox.h" + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QSpacerItem; +class QGroupBox; +class QLabel; +class KIntNumInput; +class QPushButton; +class QButtonGroup; +class QRadioButton; +class QLineEdit; + +namespace KIPIGPSSyncPlugin { +class KMLExportConfig : public KDialogBase +{ + Q_OBJECT + +public: + KMLExportConfig( QWidget* parent = 0, const char* name = 0); + ~KMLExportConfig(); + + QLabel* ImageSizeLabel; + KIntNumInput* ImageSizeInput_; + QLabel* IconSizeLabel; + KIntNumInput* IconSizeInput_; + QGroupBox* TargetPreferenceGroupBox; + QButtonGroup* buttonGroupTargetType; + QRadioButton* LocalTargetRadioButton_; + QRadioButton* GoogleMapTargetRadioButton_; + QLabel* destinationDirectoryLabel_; + QLineEdit* DestinationDirectory_; + QLineEdit* DestinationURL_; + QLabel* FileNameLabel_; + QLineEdit* FileName_; + QLabel* DestinationUrlLabel_; + + KURLRequester *GPXFileKURLRequester_; + QCheckBox *GPXTracksCheckBox_; + QLabel* GPXFileLabel_; + + +public slots: + void GoogleMapTargetRadioButton__toggled(bool); + void KMLTracksCheckButton__toggled(bool); + +protected: + KConfig* config_; + + void saveSettings(); + void readSettings(); + + QGridLayout* KMLExportConfigLayout; + QGridLayout* SizeGroupBoxLayout; + QSpacerItem* spacer3; + QSpacerItem* spacer4; + QGridLayout* TargetPreferenceGroupBoxLayout; + QGridLayout* buttonGroupTargetTypeLayout; + + KIPIPlugins::KPAboutData * m_about; + +protected slots: + void slotOk(); + // void slotOkClicked(); + void slotHelp(); + + +signals: + void okButtonClicked(); // Signal needed by plugin_kmlexport class +}; + +} // namespace + +#endif // KMLEXPORTCONFIG_H diff -Nur gpssync.orig/kmlexport.cpp gpssync/kmlexport.cpp --- gpssync.orig/kmlexport.cpp 1970-01-01 01:00:00.000000000 +0100 +++ gpssync/kmlexport.cpp 2007-03-28 23:53:15.000000000 +0200 @@ -0,0 +1,408 @@ +/*************************************************************************** + * Copyright (C) 2006 by Shadow Walker * + * shadow.walker@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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +#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(QString fileName) + */ +QString kmlExport::webifyFileName(QString fileName) { + fileName=fileName.lower(); + + // Remove potentially troublesome chars + fileName=fileName.replace(QRegExp("[^-0-9a-z]+"), "_"); + + return fileName; +} + + +/*! + \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); + + 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 extention of the file + * it's appear with digikam but not with gwenview + * which already seems to strip the extention + */ + 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); + 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)); + } + // we try to load exif value if any otherwise, try the application db + /** FIXME 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 wich 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 = ""; + } else { + my_description = ""; + } + if ( m_interface->hasFeature( KIPI::ImagesHasComments ) ) { + my_description += "
" + 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() ) + 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; + } + + QDomElement kmlPlacemark = addKmlElement(kmlAlbum, "Placemark"); + addKmlTextElement(kmlPlacemark, "name", i18n("Track")); + QDomElement kmlMultiGeometry = addKmlElement(kmlPlacemark, "MultiGeometry"); + QDomElement kmlLineString = addKmlElement(kmlMultiGeometry, "LineString"); + addKmlTextElement(kmlLineString, "coordinates", m_gpxParser.lineString()); + + QDomElement kmlStyle = addKmlElement(kmlPlacemark, "Style"); + QDomElement kmlLineStyle = addKmlElement(kmlStyle, "LineStyle"); + addKmlTextElement(kmlLineStyle, "color", "64eeee17"); + addKmlTextElement(kmlLineStyle, "width", "4"); +} + +/*! + \fn kmlExport::generate() + */ +/** + * + */ +void kmlExport::generate() +{ + //! @todo faire un test ici avant d'aller plus loin + 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 kipi-plugin"); + + + KURL::List images = selection.images(); + int pos = 1; + int count = images.count(); + for( KURL::List::Iterator selIt = images.begin(); selIt != images.end(); ++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 info for:'%1'").arg(info.title())); + } + m_progressDialog->setProgress(pos, count); + qApp->processEvents(); + } + + if (m_GPXtracks) { + addTrack(kmlAlbum); + } + + /** @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; + + + /** @todo handle copy problems */ + 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_KMLFileName = config.readEntry("KMLFileName"); + m_GPXtracks = config.readBoolEntry("UseGPXTracks"); + m_GPXFile = config.readEntry("GPXFile"); + + 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 diff -Nur gpssync.orig/kmlexport.h gpssync/kmlexport.h --- gpssync.orig/kmlexport.h 1970-01-01 01:00:00.000000000 +0100 +++ gpssync/kmlexport.h 2007-03-28 21:25:10.000000000 +0200 @@ -0,0 +1,145 @@ +/*************************************************************************** + * Copyright (C) 2006 by Shadow Walker * + * shadow.walker@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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef KIPIKMLEXPORTKMLEXPORT_H +#define KIPIKMLEXPORTKMLEXPORT_H + +// LibKIPI includes +#include + +// KIPI +#include +#include +#include + +// Qt +#include +#include +#include +#include +#include +#include +#include +#include + +// locale include +#include "gpsdataparser.h" + + +namespace KIPIGPSSyncPlugin { + +/** +Exporter to KML + + @author KIPI dev. team +*/ +class kmlExport{ +public: + kmlExport(KIPI::Interface* interface); + + ~kmlExport(); + + bool createDir(QDir dir); + 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 + */ + QString webifyFileName(QString fileName); + /** + * Generate a square thumbnail from @fullImage of @size x @size pixels + */ + QImage generateSquareThumbnail(const QImage& fullImage, int size); + QImage generateBorderedThumbnail(const QImage& fullImage, int size); + void addTrack(QDomElement &kmlAlbum); + void generate(); + int getConfig(); + + /** temporary directory where everything will be created */ + QString m_tempDestDir; + /** directory selected by user*/ + QString m_baseDestDir; + QString m_imgdir; + QString m_KMLFileName; + KIPI::Interface* m_interface; + + /** directory used in kmldocument structure */ + QString m_imageDir; + + bool m_localTarget; + int m_iconSize; + int m_googlemapSize; + bool m_optimize_googlemap; + int m_size; + QString m_UrlDestDir; + bool m_GPXtracks; + QString m_GPXFile; + +private: + KIPI::BatchProgressDialog* m_progressDialog; + void logInfo(const QString& msg); + void logError(const QString& msg); + void logWarning(const QString& msg); + + QDomDocument *kmlDocument; +private: + + GPSDataParser m_gpxParser; + + /*! + \fn KIPIKMLExport::kmlExport::addKmlElement(QDomElement target, QString tag) + */ + 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) + */ + 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) + */ + 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; + } +}; + +} + +#endif diff -Nur gpssync.orig/Makefile.am gpssync/Makefile.am --- gpssync.orig/Makefile.am 2007-02-01 20:46:58.000000000 +0100 +++ gpssync/Makefile.am 2007-03-26 20:36:41.000000000 +0200 @@ -10,11 +10,13 @@ # Srcs for the plugin kipiplugin_gpssync_la_SOURCES = plugin_gpssync.cpp gpssyncdialog.cpp gpslistviewitem.cpp \ gpsbabelbinary.cpp gpsdataparser.cpp gpseditdialog.cpp \ - gpsmapwidget.cpp + gpsmapwidget.cpp \ + kmlexport.cpp kmlexportconfig.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_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) diff -Nur gpssync.orig/plugin_gpssync.cpp gpssync/plugin_gpssync.cpp --- gpssync.orig/plugin_gpssync.cpp 2007-02-01 20:46:58.000000000 +0100 +++ gpssync/plugin_gpssync.cpp 2007-03-26 23:29:59.000000000 +0200 @@ -50,6 +50,9 @@ #include "gpssyncdialog.h" #include "plugin_gpssync.h" #include "plugin_gpssync.moc" +#include "kmlexport.h" +#include "kmlexportconfig.h" + typedef KGenericFactory Factory; @@ -96,6 +99,17 @@ addAction( m_action_geolocalization ); + // this is our action shown in the menubar/toolbar of the mainwindow + m_actionKMLExport = new KAction (i18n("Export kml..."), + "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 ) @@ -305,10 +319,38 @@ } } + +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_geolocalization ) 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 -Nur gpssync.orig/plugin_gpssync.h gpssync/plugin_gpssync.h --- gpssync.orig/plugin_gpssync.h 2007-02-01 20:46:58.000000000 +0100 +++ gpssync/plugin_gpssync.h 2007-03-26 23:00:36.000000000 +0200 @@ -27,6 +27,7 @@ #include class KActionMenu; +class KAction; class Plugin_GPSSync : public KIPI::Plugin { @@ -44,6 +45,8 @@ void slotGPSSync(); void slotGPSEdit(); void slotGPSRemove(); + void slotKMLGenerate(); + void slotKMLExport(); private: @@ -52,6 +55,7 @@ private: KActionMenu *m_action_geolocalization; + KAction *m_actionKMLExport; KIPI::Interface *m_interface; };