diff options
Diffstat (limited to 'src/libs/imageproperties')
23 files changed, 6506 insertions, 0 deletions
diff --git a/src/libs/imageproperties/Makefile.am b/src/libs/imageproperties/Makefile.am new file mode 100644 index 00000000..2c4f021a --- /dev/null +++ b/src/libs/imageproperties/Makefile.am @@ -0,0 +1,51 @@ +METASOURCES = AUTO + +noinst_LTLIBRARIES = libimagepropertiesshowfoto.la libimagepropertiesdigikam.la \ + libimagepropertiescamgui.la + +# Image Properties SideBar for Camera GUI. + +libimagepropertiescamgui_la_SOURCES = imagepropertiessidebarcamgui.cpp cameraitempropertiestab.cpp + +libimagepropertiescamgui_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor + +# Image Properties SideBar for Showfoto (without digiKam database support). + +libimagepropertiesshowfoto_la_SOURCES = imagepropertiessidebar.cpp navigatebarwidget.cpp \ + imagepropertiesmetadatatab.cpp imagepropertiescolorstab.cpp \ + imagepropertiestab.cpp navigatebartab.cpp + +libimagepropertiesshowfoto_la_LIBADD = $(top_builddir)/src/libs/widgets/libwidgets.la \ + $(top_builddir)/src/libs/dmetadata/libdmetadata.la \ + $(top_builddir)/src/libs/dimg/libdimg.la \ + $(top_builddir)/src/libs/threadimageio/libthreadimageio.la \ + $(top_builddir)/src/libs/histogram/libhistogram.la + +libimagepropertiesshowfoto_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor + +# Image Properties SideBar for digiKam Main interface and Image Editor (digiKam database support). + +libimagepropertiesdigikam_la_SOURCES = imagedescedittab.cpp imagepropertiessidebar.cpp \ + imagepropertiessidebardb.cpp \ + talbumlistview.cpp imagepropertiesmetadatatab.cpp \ + imagepropertiescolorstab.cpp \ + navigatebarwidget.cpp imagepropertiestab.cpp navigatebartab.cpp + +libimagepropertiesdigikam_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_TQT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor + +INCLUDES = -I$(top_srcdir)/src/libs/histogram \ + -I$(top_srcdir)/src/libs/themeengine \ + -I$(top_srcdir)/src/libs/dmetadata \ + -I$(top_srcdir)/src/libs/widgets/common \ + -I$(top_srcdir)/src/libs/widgets/iccprofiles \ + -I$(top_srcdir)/src/libs/widgets/metadata \ + -I$(top_srcdir)/src/libs/dialogs \ + -I$(top_srcdir)/src/libs/dimg \ + -I$(top_srcdir)/src/libs/threadimageio \ + -I$(top_srcdir)/src/utilities/cameragui \ + -I$(top_srcdir)/src/utilities/batch \ + -I$(top_srcdir)/src/digikam \ + $(LIBKEXIV2_CFLAGS) \ + $(LIBKDCRAW_CFLAGS) \ + $(all_includes) + diff --git a/src/libs/imageproperties/cameraitempropertiestab.cpp b/src/libs/imageproperties/cameraitempropertiestab.cpp new file mode 100644 index 00000000..8593e9c7 --- /dev/null +++ b/src/libs/imageproperties/cameraitempropertiestab.cpp @@ -0,0 +1,555 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2006-02-08 + * Description : A tab to display camera item information + * + * 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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqlayout.h> +#include <tqstyle.h> +#include <tqfile.h> +#include <tqlabel.h> +#include <tqpixmap.h> +#include <tqcombobox.h> +#include <tqwhatsthis.h> +#include <tqframe.h> +#include <tqscrollview.h> + +// KDE includes. + +#include <tdelocale.h> +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kdialogbase.h> +#include <tdefileitem.h> +#include <kmimetype.h> +#include <kseparator.h> +#include <ksqueezedtextlabel.h> + +// Local includes. + +#include "ddebug.h" +#include "dmetadata.h" +#include "gpiteminfo.h" +#include "navigatebarwidget.h" +#include "cameraitempropertiestab.h" +#include "cameraitempropertiestab.moc" + +namespace Digikam +{ + +class CameraItemPropertiesTabPriv +{ +public: + + CameraItemPropertiesTabPriv() + { + title = 0; + file = 0; + folder = 0; + date = 0; + size = 0; + isReadable = 0; + isWritable = 0; + mime = 0; + dimensions = 0; + newFileName = 0; + downloaded = 0; + settingsArea = 0; + title2 = 0; + make = 0; + model = 0; + photoDate = 0; + aperture = 0; + focalLength = 0; + exposureTime = 0; + sensitivity = 0; + exposureMode = 0; + flash = 0; + whiteBalance = 0; + labelFile = 0; + labelFolder = 0; + labelFileIsReadable = 0; + labelFileIsWritable = 0; + labelFileDate = 0; + labelFileSize = 0; + labelImageMime = 0; + labelImageDimensions = 0; + labelNewFileName = 0; + labelAlreadyDownloaded = 0; + labelPhotoMake = 0; + labelPhotoModel = 0; + labelPhotoDateTime = 0; + labelPhotoAperture = 0; + labelPhotoFocalLength = 0; + labelPhotoExposureTime = 0; + labelPhotoSensitivity = 0; + labelPhotoExposureMode = 0; + labelPhotoFlash = 0; + labelPhotoWhiteBalance = 0; + } + + TQLabel *title; + TQLabel *file; + TQLabel *folder; + TQLabel *date; + TQLabel *size; + TQLabel *isReadable; + TQLabel *isWritable; + TQLabel *mime; + TQLabel *dimensions; + TQLabel *newFileName; + TQLabel *downloaded; + + TQLabel *title2; + TQLabel *make; + TQLabel *model; + TQLabel *photoDate; + TQLabel *aperture; + TQLabel *focalLength; + TQLabel *exposureTime; + TQLabel *sensitivity; + TQLabel *exposureMode; + TQLabel *flash; + TQLabel *whiteBalance; + + TQFrame *settingsArea; + + KSqueezedTextLabel *labelFile; + KSqueezedTextLabel *labelFolder; + KSqueezedTextLabel *labelFileIsReadable; + KSqueezedTextLabel *labelFileIsWritable; + KSqueezedTextLabel *labelFileDate; + KSqueezedTextLabel *labelFileSize; + KSqueezedTextLabel *labelImageMime; + KSqueezedTextLabel *labelImageDimensions; + KSqueezedTextLabel *labelNewFileName; + KSqueezedTextLabel *labelAlreadyDownloaded; + + KSqueezedTextLabel *labelPhotoMake; + KSqueezedTextLabel *labelPhotoModel; + KSqueezedTextLabel *labelPhotoDateTime; + KSqueezedTextLabel *labelPhotoAperture; + KSqueezedTextLabel *labelPhotoFocalLength; + KSqueezedTextLabel *labelPhotoExposureTime; + KSqueezedTextLabel *labelPhotoSensitivity; + KSqueezedTextLabel *labelPhotoExposureMode; + KSqueezedTextLabel *labelPhotoFlash; + KSqueezedTextLabel *labelPhotoWhiteBalance; +}; + +CameraItemPropertiesTab::CameraItemPropertiesTab(TQWidget* parent, bool navBar) + : NavigateBarTab(parent) +{ + d = new CameraItemPropertiesTabPriv; + + setupNavigateBar(navBar); + + TQScrollView *sv = new TQScrollView(this); + sv->viewport()->setBackgroundMode(TQt::PaletteBackground); + sv->setResizePolicy(TQScrollView::AutoOneFit); + sv->setFrameStyle(TQFrame::NoFrame); + + d->settingsArea = new TQFrame(sv->viewport()); + d->settingsArea->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken ); + d->settingsArea->setLineWidth( style().pixelMetric(TQStyle::PM_DefaultFrameWidth, this) ); + + sv->addChild(d->settingsArea); + m_navigateBarLayout->addWidget(sv); + + // -------------------------------------------------- + + TQGridLayout *settingsLayout = new TQGridLayout(d->settingsArea, 27, 1, KDialog::spacingHint(), 0); + + d->title = new TQLabel(i18n("<big><b>Camera File Properties</b></big>"), d->settingsArea); + d->file = new TQLabel(i18n("<b>File</b>:"), d->settingsArea); + d->folder = new TQLabel(i18n("<b>Folder</b>:"), d->settingsArea); + d->date = new TQLabel(i18n("<b>Date</b>:"), d->settingsArea); + d->size = new TQLabel(i18n("<b>Size</b>:"), d->settingsArea); + d->isReadable = new TQLabel(i18n("<b>Readable</b>:"), d->settingsArea); + d->isWritable = new TQLabel(i18n("<b>Writable</b>:"), d->settingsArea); + d->mime = new TQLabel(i18n("<b>Type</b>:"), d->settingsArea); + d->dimensions = new TQLabel(i18n("<b>Dimensions</b>:"), d->settingsArea); + d->newFileName = new TQLabel(i18n("<nobr><b>New Name</b></nobr>:"), d->settingsArea); + d->downloaded = new TQLabel(i18n("<b>Downloaded</b>:"), d->settingsArea); + + KSeparator *line = new KSeparator(TQt::Horizontal, d->settingsArea); + d->title2 = new TQLabel(i18n("<big><b>Photograph Properties</b></big>"), d->settingsArea); + d->make = new TQLabel(i18n("<b>Make</b>:"), d->settingsArea); + d->model = new TQLabel(i18n("<b>Model</b>:"), d->settingsArea); + d->photoDate = new TQLabel(i18n("<b>Created</b>:"), d->settingsArea); + d->aperture = new TQLabel(i18n("<b>Aperture</b>:"), d->settingsArea); + d->focalLength = new TQLabel(i18n("<b>Focal</b>:"), d->settingsArea); + d->exposureTime = new TQLabel(i18n("<b>Exposure</b>:"), d->settingsArea); + d->sensitivity = new TQLabel(i18n("<b>Sensitivity</b>:"), d->settingsArea); + d->exposureMode = new TQLabel(i18n("<nobr><b>Mode/Program</b></nobr>:"), d->settingsArea); + d->flash = new TQLabel(i18n("<b>Flash</b>:"), d->settingsArea); + d->whiteBalance = new TQLabel(i18n("<nobr><b>White balance</b></nobr>:"), d->settingsArea); + + d->labelFile = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFolder = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFileDate = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFileSize = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFileIsReadable = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFileIsWritable = new KSqueezedTextLabel(0, d->settingsArea); + d->labelImageMime = new KSqueezedTextLabel(0, d->settingsArea); + d->labelImageDimensions = new KSqueezedTextLabel(0, d->settingsArea); + d->labelNewFileName = new KSqueezedTextLabel(0, d->settingsArea); + d->labelAlreadyDownloaded = new KSqueezedTextLabel(0, d->settingsArea); + + d->labelPhotoMake = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoModel = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoDateTime = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoAperture = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoFocalLength = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoExposureTime = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoSensitivity = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoExposureMode = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoFlash = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoWhiteBalance = new KSqueezedTextLabel(0, d->settingsArea); + + int hgt = fontMetrics().height()-2; + d->title->setAlignment(TQt::AlignCenter); + d->file->setMaximumHeight(hgt); + d->folder->setMaximumHeight(hgt); + d->date->setMaximumHeight(hgt); + d->size->setMaximumHeight(hgt); + d->isReadable->setMaximumHeight(hgt); + d->isWritable->setMaximumHeight(hgt); + d->mime->setMaximumHeight(hgt); + d->dimensions->setMaximumHeight(hgt); + d->newFileName->setMaximumHeight(hgt); + d->downloaded->setMaximumHeight(hgt); + d->labelFile->setMaximumHeight(hgt); + d->labelFolder->setMaximumHeight(hgt); + d->labelFileDate->setMaximumHeight(hgt); + d->labelFileSize->setMaximumHeight(hgt); + d->labelFileIsReadable->setMaximumHeight(hgt); + d->labelFileIsWritable->setMaximumHeight(hgt); + d->labelImageMime->setMaximumHeight(hgt); + d->labelImageDimensions->setMaximumHeight(hgt); + d->labelNewFileName->setMaximumHeight(hgt); + d->labelAlreadyDownloaded->setMaximumHeight(hgt); + + d->title2->setAlignment(TQt::AlignCenter); + d->make->setMaximumHeight(hgt); + d->model->setMaximumHeight(hgt); + d->photoDate->setMaximumHeight(hgt); + d->aperture->setMaximumHeight(hgt); + d->focalLength->setMaximumHeight(hgt); + d->exposureTime->setMaximumHeight(hgt); + d->sensitivity->setMaximumHeight(hgt); + d->exposureMode->setMaximumHeight(hgt); + d->flash->setMaximumHeight(hgt); + d->whiteBalance->setMaximumHeight(hgt); + d->labelPhotoMake->setMaximumHeight(hgt); + d->labelPhotoModel->setMaximumHeight(hgt); + d->labelPhotoDateTime->setMaximumHeight(hgt); + d->labelPhotoAperture->setMaximumHeight(hgt); + d->labelPhotoFocalLength->setMaximumHeight(hgt); + d->labelPhotoExposureTime->setMaximumHeight(hgt); + d->labelPhotoSensitivity->setMaximumHeight(hgt); + d->labelPhotoExposureMode->setMaximumHeight(hgt); + d->labelPhotoFlash->setMaximumHeight(hgt); + d->labelPhotoWhiteBalance->setMaximumHeight(hgt); + + // -------------------------------------------------- + + settingsLayout->addMultiCellWidget(d->title, 0, 0, 0, 1); + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 1, 1, 0, 1); + settingsLayout->addMultiCellWidget(d->file, 2, 2, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFile, 2, 2, 1, 1); + settingsLayout->addMultiCellWidget(d->folder, 3, 3, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFolder, 3, 3, 1, 1); + settingsLayout->addMultiCellWidget(d->date, 4, 4, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFileDate, 4, 4, 1, 1); + settingsLayout->addMultiCellWidget(d->size, 5, 5, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFileSize, 5, 5, 1, 1); + settingsLayout->addMultiCellWidget(d->isReadable, 6, 6, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFileIsReadable, 6, 6, 1, 1); + settingsLayout->addMultiCellWidget(d->isWritable, 7, 7, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFileIsWritable, 7, 7, 1, 1); + settingsLayout->addMultiCellWidget(d->mime, 8, 8, 0, 0); + settingsLayout->addMultiCellWidget(d->labelImageMime, 8, 8, 1, 1); + settingsLayout->addMultiCellWidget(d->dimensions, 9, 9, 0, 0); + settingsLayout->addMultiCellWidget(d->labelImageDimensions, 9, 9, 1, 1); + settingsLayout->addMultiCellWidget(d->newFileName, 10, 10, 0, 0); + settingsLayout->addMultiCellWidget(d->labelNewFileName, 10, 10, 1, 1); + settingsLayout->addMultiCellWidget(d->downloaded, 11, 11, 0, 0); + settingsLayout->addMultiCellWidget(d->labelAlreadyDownloaded, 11, 11, 1, 1); + + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 12, 12, 0, 1); + settingsLayout->addMultiCellWidget(line, 13, 13, 0, 1); + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 14, 14, 0, 1); + + settingsLayout->addMultiCellWidget(d->title2, 15, 15, 0, 1); + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 16, 16, 0, 1); + settingsLayout->addMultiCellWidget(d->make, 17, 17, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoMake, 17, 17, 1, 1); + settingsLayout->addMultiCellWidget(d->model, 18, 18, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoModel, 18, 18, 1, 1); + settingsLayout->addMultiCellWidget(d->photoDate, 19, 19, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoDateTime, 19, 19, 1, 1); + settingsLayout->addMultiCellWidget(d->aperture, 20, 20, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoAperture, 20, 20, 1, 1); + settingsLayout->addMultiCellWidget(d->focalLength, 21, 21, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoFocalLength, 21, 21, 1, 1); + settingsLayout->addMultiCellWidget(d->exposureTime, 22, 22, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoExposureTime, 22, 22, 1, 1); + settingsLayout->addMultiCellWidget(d->sensitivity, 23, 23, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoSensitivity, 23, 23, 1, 1); + settingsLayout->addMultiCellWidget(d->exposureMode, 24, 24, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoExposureMode, 24, 24, 1, 1); + settingsLayout->addMultiCellWidget(d->flash, 25, 25, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoFlash, 25, 25, 1, 1); + settingsLayout->addMultiCellWidget(d->whiteBalance, 26, 26, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoWhiteBalance, 26, 26, 1, 1); + settingsLayout->setRowStretch(27, 10); + settingsLayout->setColStretch(1, 10); +} + +CameraItemPropertiesTab::~CameraItemPropertiesTab() +{ + delete d; +} + +void CameraItemPropertiesTab::setCurrentItem(const GPItemInfo* itemInfo, + const TQString &newFileName, const TQByteArray& exifData, + const KURL ¤tURL) +{ + if (!itemInfo) + { + d->labelFile->setText(TQString()); + d->labelFolder->setText(TQString()); + d->labelFileIsReadable->setText(TQString()); + d->labelFileIsWritable->setText(TQString()); + d->labelFileDate->setText(TQString()); + d->labelFileSize->setText(TQString()); + d->labelImageMime->setText(TQString()); + d->labelImageDimensions->setText(TQString()); + d->labelNewFileName->setText(TQString()); + d->labelAlreadyDownloaded->setText(TQString()); + + d->labelPhotoMake->setText(TQString()); + d->labelPhotoModel->setText(TQString()); + d->labelPhotoDateTime->setText(TQString()); + d->labelPhotoAperture->setText(TQString()); + d->labelPhotoFocalLength->setText(TQString()); + d->labelPhotoExposureTime->setText(TQString()); + d->labelPhotoSensitivity->setText(TQString()); + d->labelPhotoExposureMode->setText(TQString()); + d->labelPhotoFlash->setText(TQString()); + d->labelPhotoWhiteBalance->setText(TQString()); + + setEnabled(false); + return; + } + + setEnabled(true); + + TQString str; + TQString unknown(i18n("<i>unknown</i>")); + + // -- Camera file system information ------------------------------------------ + + d->labelFile->setText(itemInfo->name); + d->labelFolder->setText(itemInfo->folder); + + if (itemInfo->readPermissions < 0) + str = unknown; + else if (itemInfo->readPermissions == 0) + str = i18n("No"); + else + str = i18n("Yes"); + + d->labelFileIsReadable->setText(str); + + if (itemInfo->writePermissions < 0) + str = unknown; + else if (itemInfo->writePermissions == 0) + str = i18n("No"); + else + str = i18n("Yes"); + + d->labelFileIsWritable->setText(str); + + TQDateTime date; + date.setTime_t(itemInfo->mtime); + d->labelFileDate->setText(TDEGlobal::locale()->formatDateTime(date, true, true)); + + str = i18n("%1 (%2)").arg(TDEIO::convertSize(itemInfo->size)) + .arg(TDEGlobal::locale()->formatNumber(itemInfo->size, 0)); + d->labelFileSize->setText(str); + + // -- Image Properties -------------------------------------------------- + + d->labelImageMime->setText( (itemInfo->mime == TQString("image/x-raw")) ? + i18n("RAW Image") : KMimeType::mimeType(itemInfo->mime)->comment() ); + + TQString mpixels; + TQSize dims; + if (itemInfo->width == -1 && itemInfo->height == -1 && !currentURL.isEmpty()) + { + // delayed loading to list faster from UMSCamera + if (itemInfo->mime == TQString("image/x-raw")) + { + DMetadata metaData(currentURL.path()); + dims = metaData.getImageDimensions(); + } + else + { + KFileMetaInfo meta(currentURL.path()); + if (meta.isValid()) + { + if (meta.containsGroup("Jpeg EXIF Data")) + dims = meta.group("Jpeg EXIF Data").item("Dimensions").value().toSize(); + else if (meta.containsGroup("General")) + dims = meta.group("General").item("Dimensions").value().toSize(); + else if (meta.containsGroup("Technical")) + dims = meta.group("Technical").item("Dimensions").value().toSize(); + } + } + } + else + { + // if available (GPCamera), take dimensions directly from itemInfo + dims = TQSize(itemInfo->width, itemInfo->height); + } + mpixels.setNum(dims.width()*dims.height()/1000000.0, 'f', 2); + str = (!dims.isValid()) ? unknown : i18n("%1x%2 (%3Mpx)") + .arg(dims.width()).arg(dims.height()).arg(mpixels); + d->labelImageDimensions->setText(str); + + // -- Download information ------------------------------------------ + + d->labelNewFileName->setText(newFileName.isEmpty() ? i18n("<i>unchanged</i>") : newFileName); + + if (itemInfo->downloaded == GPItemInfo::DownloadUnknow) + str = unknown; + else if (itemInfo->downloaded == GPItemInfo::DownloadedYes) + str = i18n("Yes"); + else + str = i18n("No"); + + d->labelAlreadyDownloaded->setText(str); + + // -- Photograph information ------------------------------------------ + // NOTA: If something is changed here, please updated albumfiletip section too. + + TQString unavailable(i18n("<i>unavailable</i>")); + DMetadata metaData; + metaData.setExif(exifData); + PhotoInfoContainer photoInfo = metaData.getPhotographInformations(); + + if (photoInfo.isEmpty()) + { + d->title2->hide(); + d->make->hide(); + d->model->hide(); + d->photoDate->hide(); + d->aperture->hide(); + d->focalLength->hide(); + d->exposureTime->hide(); + d->sensitivity->hide(); + d->exposureMode->hide(); + d->flash->hide(); + d->whiteBalance->hide(); + d->labelPhotoMake->hide(); + d->labelPhotoModel->hide(); + d->labelPhotoDateTime->hide(); + d->labelPhotoAperture->hide(); + d->labelPhotoFocalLength->hide(); + d->labelPhotoExposureTime->hide(); + d->labelPhotoSensitivity->hide(); + d->labelPhotoExposureMode->hide(); + d->labelPhotoFlash->hide(); + d->labelPhotoWhiteBalance->hide(); + } + else + { + d->title2->show(); + d->make->show(); + d->model->show(); + d->photoDate->show(); + d->aperture->show(); + d->focalLength->show(); + d->exposureTime->show(); + d->sensitivity->show(); + d->exposureMode->show(); + d->flash->show(); + d->whiteBalance->show(); + d->labelPhotoMake->show(); + d->labelPhotoModel->show(); + d->labelPhotoDateTime->show(); + d->labelPhotoAperture->show(); + d->labelPhotoFocalLength->show(); + d->labelPhotoExposureTime->show(); + d->labelPhotoSensitivity->show(); + d->labelPhotoExposureMode->show(); + d->labelPhotoFlash->show(); + d->labelPhotoWhiteBalance->show(); + } + + d->labelPhotoMake->setText(photoInfo.make.isEmpty() ? unavailable : photoInfo.make); + d->labelPhotoModel->setText(photoInfo.model.isEmpty() ? unavailable : photoInfo.model); + + if (photoInfo.dateTime.isValid()) + { + str = TDEGlobal::locale()->formatDateTime(photoInfo.dateTime, true, true); + d->labelPhotoDateTime->setText(str); + } + else + d->labelPhotoDateTime->setText(unavailable); + + d->labelPhotoAperture->setText(photoInfo.aperture.isEmpty() ? unavailable : photoInfo.aperture); + + if (photoInfo.focalLength35mm.isEmpty()) + d->labelPhotoFocalLength->setText(photoInfo.focalLength.isEmpty() ? unavailable : photoInfo.focalLength); + else + { + str = i18n("%1 (35mm: %2)").arg(photoInfo.focalLength).arg(photoInfo.focalLength35mm); + d->labelPhotoFocalLength->setText(str); + } + + d->labelPhotoExposureTime->setText(photoInfo.exposureTime.isEmpty() ? unavailable : photoInfo.exposureTime); + d->labelPhotoSensitivity->setText(photoInfo.sensitivity.isEmpty() ? unavailable : i18n("%1 ISO").arg(photoInfo.sensitivity)); + + if (photoInfo.exposureMode.isEmpty() && photoInfo.exposureProgram.isEmpty()) + d->labelPhotoExposureMode->setText(unavailable); + else if (!photoInfo.exposureMode.isEmpty() && photoInfo.exposureProgram.isEmpty()) + d->labelPhotoExposureMode->setText(photoInfo.exposureMode); + else if (photoInfo.exposureMode.isEmpty() && !photoInfo.exposureProgram.isEmpty()) + d->labelPhotoExposureMode->setText(photoInfo.exposureProgram); + else + { + str = TQString("%1 / %2").arg(photoInfo.exposureMode).arg(photoInfo.exposureProgram); + d->labelPhotoExposureMode->setText(str); + } + + d->labelPhotoFlash->setText(photoInfo.flash.isEmpty() ? unavailable : photoInfo.flash); + d->labelPhotoWhiteBalance->setText(photoInfo.whiteBalance.isEmpty() ? unavailable : photoInfo.whiteBalance); +} + +} // NameSpace Digikam diff --git a/src/libs/imageproperties/cameraitempropertiestab.h b/src/libs/imageproperties/cameraitempropertiestab.h new file mode 100644 index 00000000..badf4a70 --- /dev/null +++ b/src/libs/imageproperties/cameraitempropertiestab.h @@ -0,0 +1,69 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2006-02-08 + * Description : A tab to display camera item information + * + * 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 CAMERAITEMPROPERTIESTAB_H +#define CAMERAITEMPROPERTIESTAB_H + +// TQt includes. + +#include <tqwidget.h> +#include <tqstring.h> + +// KDE includes. + +#include <kurl.h> + +// Local includes. + +#include "digikam_export.h" +#include "navigatebartab.h" + +namespace Digikam +{ + +class GPItemInfo; +class CameraItemPropertiesTabPriv; + +class DIGIKAM_EXPORT CameraItemPropertiesTab : public NavigateBarTab +{ + TQ_OBJECT + + +public: + + CameraItemPropertiesTab(TQWidget* parent, bool navBar=true); + ~CameraItemPropertiesTab(); + + void setCurrentItem(const GPItemInfo* itemInfo=0, + const TQString &newFileName=TQString(), + const TQByteArray& exifData=TQByteArray(), + const KURL ¤tURL = KURL()); + +private: + + CameraItemPropertiesTabPriv* d; +}; + +} // NameSpace Digikam + +#endif /* CAMERAITEMPROPERTIESTAB_H */ diff --git a/src/libs/imageproperties/imagedescedittab.cpp b/src/libs/imageproperties/imagedescedittab.cpp new file mode 100644 index 00000000..f79b1d7c --- /dev/null +++ b/src/libs/imageproperties/imagedescedittab.cpp @@ -0,0 +1,1763 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2003-03-09 + * Description : Captions, Tags, and Rating properties editor + * + * Copyright (C) 2003-2005 by Renchi Raju <[email protected]> + * Copyright (C) 2003-2009 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2006-2009 by Marcel Wiesweg <[email protected]> + * Copyright (C) 2009 by Andi Clemens <andi dot clemens at gmx 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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqhbox.h> +#include <tqvbox.h> +#include <tqlabel.h> +#include <tqlayout.h> +#include <tqtoolbutton.h> +#include <tqpushbutton.h> +#include <tqiconset.h> +#include <tqwhatsthis.h> +#include <tqtooltip.h> +#include <tqscrollview.h> + +// KDE includes. + +#include <tdeabc/stdaddressbook.h> +#include <tdepopupmenu.h> +#include <tdelocale.h> +#include <kurl.h> +#include <kcursor.h> +#include <tdeapplication.h> +#include <kiconloader.h> +#include <tdemessagebox.h> +#include <ktextedit.h> +#include <tdeconfig.h> +#include <klineedit.h> +#include <kdialogbase.h> + +// Local includes. + +#include "ddebug.h" +#include "dmetadata.h" +#include "kdatetimeedit.h" +#include "albumiconitem.h" +#include "albumdb.h" +#include "album.h" +#include "albumsettings.h" +#include "albumlister.h" +#include "albumthumbnailloader.h" +#include "tageditdlg.h" +#include "navigatebarwidget.h" +#include "ratingwidget.h" +#include "talbumlistview.h" +#include "tagfilterview.h" +#include "imageinfo.h" +#include "imageattributeswatch.h" +#include "metadatahub.h" +#include "statusprogressbar.h" +#include "searchtextbar.h" +#include "imagedescedittab.h" +#include "imagedescedittab.moc" + +namespace Digikam +{ + +class ImageDescEditTabPriv +{ + +public: + + ImageDescEditTabPriv() + { + modified = false; + ignoreImageAttributesWatch = false; + recentTagsBtn = 0; + commentsEdit = 0; + tagsSearchBar = 0; + dateTimeEdit = 0; + tagsView = 0; + ratingWidget = 0; + ABCMenu = 0; + assignedTagsBtn = 0; + applyBtn = 0; + revertBtn = 0; + newTagEdit = 0; + toggleAutoTags = TagFilterView::NoToggleAuto; + } + + bool modified; + bool ignoreImageAttributesWatch; + + TQToolButton *recentTagsBtn; + TQToolButton *assignedTagsBtn; + TQToolButton *revertBtn; + + TQPopupMenu *ABCMenu; + + TQPushButton *applyBtn; + + TQPushButton *moreButton; + TQPopupMenu *moreMenu; + + KTextEdit *commentsEdit; + + KDateTimeEdit *dateTimeEdit; + + SearchTextBar *tagsSearchBar; + SearchTextBar *newTagEdit; + + TQPtrList<ImageInfo> currInfos; + + TAlbumListView *tagsView; + + RatingWidget *ratingWidget; + + TagFilterView::ToggleAutoTags toggleAutoTags; + + MetadataHub hub; +}; + +ImageDescEditTab::ImageDescEditTab(TQWidget *parent, bool navBar) + : NavigateBarTab(parent) +{ + d = new ImageDescEditTabPriv; + + setupNavigateBar(navBar); + + TQScrollView *sv = new TQScrollView(this); + sv->viewport()->setBackgroundMode(TQt::PaletteBackground); + sv->setResizePolicy(TQScrollView::AutoOneFit); + sv->setFrameStyle(TQFrame::NoFrame); + + TQWidget *settingsArea = new TQWidget(sv->viewport()); + sv->addChild(settingsArea); + m_navigateBarLayout->addWidget(sv); + + TQGridLayout *settingsLayout = new TQGridLayout(settingsArea, 6, 1, + KDialog::spacingHint(), KDialog::spacingHint()); + + // Captions/Date/Rating view ----------------------------------- + + TQVBox *commentsBox = new TQVBox(settingsArea); + new TQLabel(i18n("Caption:"), commentsBox); + d->commentsEdit = new KTextEdit(commentsBox); + d->commentsEdit->setTextFormat(TQTextEdit::PlainText); + d->commentsEdit->setCheckSpellingEnabled(true); + d->commentsEdit->setFixedHeight(100); + + TQHBox *dateBox = new TQHBox(settingsArea); + new TQLabel(i18n("Date:"), dateBox); + d->dateTimeEdit = new KDateTimeEdit(dateBox, "datepicker"); + + TQHBox *ratingBox = new TQHBox(settingsArea); + new TQLabel(i18n("Rating:"), ratingBox); + d->ratingWidget = new RatingWidget(ratingBox); + + // Tags view --------------------------------------------------- + + d->newTagEdit = new SearchTextBar(settingsArea, "ImageDescEditTabNewTagEdit", i18n("Enter new tag here...")); + TQWhatsThis::add(d->newTagEdit, i18n("Enter here the text used to create new tags. " + "'/' can be used here to create a hierarchy of tags. " + "',' can be used here to create more than one hierarchy at the same time.")); + + d->tagsView = new TAlbumListView(settingsArea); + + TQHBox *tagsSearch = new TQHBox(settingsArea); + tagsSearch->setSpacing(KDialog::spacingHint()); + + d->tagsSearchBar = new SearchTextBar(tagsSearch, "ImageDescEditTabTagsSearchBar"); + + d->assignedTagsBtn = new TQToolButton(tagsSearch); + TQToolTip::add(d->assignedTagsBtn, i18n("Tags already assigned")); + d->assignedTagsBtn->setIconSet(kapp->iconLoader()->loadIcon("tag-assigned", + TDEIcon::NoGroup, TDEIcon::SizeSmall, + TDEIcon::DefaultState, 0, true)); + d->assignedTagsBtn->setToggleButton(true); + + d->recentTagsBtn = new TQToolButton(tagsSearch); + TQPopupMenu *popupMenu = new TQPopupMenu(d->recentTagsBtn); + TQToolTip::add(d->recentTagsBtn, i18n("Recent Tags")); + d->recentTagsBtn->setIconSet(kapp->iconLoader()->loadIcon("tag-recents", + TDEIcon::NoGroup, TDEIcon::SizeSmall, + TDEIcon::DefaultState, 0, true)); + d->recentTagsBtn->setUsesBigPixmap(false); + d->recentTagsBtn->setPopup(popupMenu); + d->recentTagsBtn->setPopupDelay(1); + + // Buttons ----------------------------------------- + + TQHBox *buttonsBox = new TQHBox(settingsArea); + buttonsBox->setSpacing(KDialog::spacingHint()); + + d->revertBtn = new TQToolButton(buttonsBox); + d->revertBtn->setIconSet(SmallIcon("reload_page")); + TQToolTip::add(d->revertBtn, i18n("Revert all changes")); + d->revertBtn->setEnabled(false); + + d->applyBtn = new TQPushButton(i18n("Apply"), buttonsBox); + d->applyBtn->setIconSet(SmallIcon("button_ok")); + d->applyBtn->setEnabled(false); + TQToolTip::add(d->applyBtn, i18n("Apply all changes to images")); + buttonsBox->setStretchFactor(d->applyBtn, 10); + + d->moreButton = new TQPushButton(i18n("More"), buttonsBox); + d->moreMenu = new TQPopupMenu(this); + d->moreButton->setPopup(d->moreMenu); + + // -------------------------------------------------- + + settingsLayout->addMultiCellWidget(commentsBox, 0, 0, 0, 1); + settingsLayout->addMultiCellWidget(dateBox, 1, 1, 0, 1); + settingsLayout->addMultiCellWidget(ratingBox, 2, 2, 0, 1); + settingsLayout->addMultiCellWidget(d->newTagEdit, 3, 3, 0, 1); + settingsLayout->addMultiCellWidget(d->tagsView, 4, 4, 0, 1); + settingsLayout->addMultiCellWidget(tagsSearch, 5, 5, 0, 1); + settingsLayout->addMultiCellWidget(buttonsBox, 6, 6, 0, 1); + settingsLayout->setRowStretch(4, 10); + + // -------------------------------------------------- + + connect(d->tagsView, TQ_SIGNAL(signalProgressBarMode(int, const TQString&)), + this, TQ_SIGNAL(signalProgressBarMode(int, const TQString&))); + + connect(d->tagsView, TQ_SIGNAL(signalProgressValue(int)), + this, TQ_SIGNAL(signalProgressValue(int))); + + connect(popupMenu, TQ_SIGNAL(activated(int)), + this, TQ_SLOT(slotRecentTagsMenuActivated(int))); + + connect(d->tagsView, TQ_SIGNAL(signalItemStateChanged(TAlbumCheckListItem *)), + this, TQ_SLOT(slotItemStateChanged(TAlbumCheckListItem *))); + + connect(d->commentsEdit, TQ_SIGNAL(textChanged()), + this, TQ_SLOT(slotCommentChanged())); + + connect(d->dateTimeEdit, TQ_SIGNAL(dateTimeChanged(const TQDateTime& )), + this, TQ_SLOT(slotDateTimeChanged(const TQDateTime&))); + + connect(d->ratingWidget, TQ_SIGNAL(signalRatingChanged(int)), + this, TQ_SLOT(slotRatingChanged(int))); + + connect(d->tagsView, TQ_SIGNAL(rightButtonClicked(TQListViewItem*, const TQPoint &, int)), + this, TQ_SLOT(slotRightButtonClicked(TQListViewItem*, const TQPoint&, int))); + + connect(d->tagsSearchBar, TQ_SIGNAL(signalTextChanged(const TQString&)), + this, TQ_SLOT(slotTagsSearchChanged(const TQString&))); + + connect(this, TQ_SIGNAL(signalTagFilterMatch(bool)), + d->tagsSearchBar, TQ_SLOT(slotSearchResult(bool))); + + connect(d->assignedTagsBtn, TQ_SIGNAL(toggled(bool)), + this, TQ_SLOT(slotAssignedTagsToggled(bool))); + + connect(d->newTagEdit->lineEdit(), TQ_SIGNAL(returnPressed(const TQString&)), + this, TQ_SLOT(slotCreateNewTag())); + + connect(d->applyBtn, TQ_SIGNAL(clicked()), + this, TQ_SLOT(slotApplyAllChanges())); + + connect(d->revertBtn, TQ_SIGNAL(clicked()), + this, TQ_SLOT(slotRevertAllChanges())); + + connect(d->moreMenu, TQ_SIGNAL(aboutToShow()), + this, TQ_SLOT(slotMoreMenu())); + + // Initialize --------------------------------------------- + + d->commentsEdit->installEventFilter(this); + d->dateTimeEdit->installEventFilter(this); + d->ratingWidget->installEventFilter(this); + d->tagsView->installEventFilter(this); + updateRecentTags(); + + // Connect to album manager ----------------------------- + + AlbumManager* man = AlbumManager::instance(); + + connect(man, TQ_SIGNAL(signalAlbumAdded(Album*)), + this, TQ_SLOT(slotAlbumAdded(Album*))); + + connect(man, TQ_SIGNAL(signalAlbumDeleted(Album*)), + this, TQ_SLOT(slotAlbumDeleted(Album*))); + + connect(man, TQ_SIGNAL(signalAlbumRenamed(Album*)), + this, TQ_SLOT(slotAlbumRenamed(Album*))); + + connect(man, TQ_SIGNAL(signalAlbumsCleared()), + this, TQ_SLOT(slotAlbumsCleared())); + + connect(man, TQ_SIGNAL(signalAlbumIconChanged(Album*)), + this, TQ_SLOT(slotAlbumIconChanged(Album*))); + + connect(man, TQ_SIGNAL(signalTAlbumMoved(TAlbum*, TAlbum*)), + this, TQ_SLOT(slotAlbumMoved(TAlbum*, TAlbum*))); + + // Connect to thumbnail loader ----------------------------- + + AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance(); + + connect(loader, TQ_SIGNAL(signalThumbnail(Album *, const TQPixmap&)), + this, TQ_SLOT(slotGotThumbnailFromIcon(Album *, const TQPixmap&))); + + connect(loader, TQ_SIGNAL(signalFailed(Album *)), + this, TQ_SLOT(slotThumbnailLost(Album *))); + + connect(loader, TQ_SIGNAL(signalReloadThumbnails()), + this, TQ_SLOT(slotReloadThumbnails())); + + // Connect to attribute watch ------------------------------ + + ImageAttributesWatch *watch = ImageAttributesWatch::instance(); + + connect(watch, TQ_SIGNAL(signalImageTagsChanged(TQ_LLONG)), + this, TQ_SLOT(slotImageTagsChanged(TQ_LLONG))); + + connect(watch, TQ_SIGNAL(signalImagesChanged(int)), + this, TQ_SLOT(slotImagesChanged(int))); + + connect(watch, TQ_SIGNAL(signalImageRatingChanged(TQ_LLONG)), + this, TQ_SLOT(slotImageRatingChanged(TQ_LLONG))); + + connect(watch, TQ_SIGNAL(signalImageDateChanged(TQ_LLONG)), + this, TQ_SLOT(slotImageDateChanged(TQ_LLONG))); + + connect(watch, TQ_SIGNAL(signalImageCaptionChanged(TQ_LLONG)), + this, TQ_SLOT(slotImageCaptionChanged(TQ_LLONG))); + + // -- read config --------------------------------------------------------- + + TDEConfig* config = kapp->config(); + config->setGroup("Tag List View"); + d->toggleAutoTags = (TagFilterView::ToggleAutoTags)(config->readNumEntry("Toggle Auto Tags", + TagFilterView::NoToggleAuto)); +} + +ImageDescEditTab::~ImageDescEditTab() +{ + slotChangingItems(); + + /* + AlbumList tList = AlbumManager::instance()->allTAlbums(); + for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it) + { + (*it)->removeExtraData(this); + } + */ + + TDEConfig* config = kapp->config(); + config->setGroup("Tag List View"); + config->writeEntry("Toggle Auto Tags", (int)(d->toggleAutoTags)); + config->sync(); + + delete d; +} + +bool ImageDescEditTab::singleSelection() const +{ + return (d->currInfos.count() == 1); +} + +void ImageDescEditTab::slotChangingItems() +{ + if (!d->modified) + return; + + if (d->currInfos.isEmpty()) + return; + + if (!AlbumSettings::instance()->getApplySidebarChangesDirectly()) + { + KDialogBase *dialog = new KDialogBase(i18n("Apply changes?"), + KDialogBase::Yes | KDialogBase::No, + KDialogBase::Yes, KDialogBase::No, + this, "applyChanges", + true, true, + KStdGuiItem::yes(), KStdGuiItem::discard()); + + int changedFields = 0; + if (d->hub.commentChanged()) + changedFields++; + if (d->hub.dateTimeChanged()) + changedFields++; + if (d->hub.ratingChanged()) + changedFields++; + if (d->hub.tagsChanged()) + changedFields++; + + TQString text; + if (changedFields == 1) + { + if (d->hub.commentChanged()) + text = i18n("<qt><p>You have edited the comment of the image. ", + "<qt><p>You have edited the comment of %n images. ", + d->currInfos.count()); + else if (d->hub.dateTimeChanged()) + text = i18n("<qt><p>You have edited the date of the image. ", + "<qt><p>You have edited the date of %n images. ", + d->currInfos.count()); + else if (d->hub.ratingChanged()) + text = i18n("<qt><p>You have edited the rating of the image. ", + "<qt><p>You have edited the rating of %n images. ", + d->currInfos.count()); + else if (d->hub.tagsChanged()) + text = i18n("<qt><p>You have edited the tags of the image. ", + "<qt><p>You have edited the tags of %n images. ", + d->currInfos.count()); + + text += i18n("Do you want to apply your changes?</p></qt>"); + } + else + { + text = i18n("<qt><p>You have edited the metadata of the image: </p><ul>", + "<qt><p>You have edited the metadata of %n images: </p><ul>", + d->currInfos.count()); + + if (d->hub.commentChanged()) + text += i18n("<li>comment</li>"); + if (d->hub.dateTimeChanged()) + text += i18n("<li>date</li>"); + if (d->hub.ratingChanged()) + text += i18n("<li>rating</li>"); + if (d->hub.tagsChanged()) + text += i18n("<li>tags</li>"); + + text += "</ul><p>"; + + text += i18n("Do you want to apply your changes?</p></qt>"); + } + + bool alwaysApply = false; + int returnCode = KMessageBox::createKMessageBox + (dialog, TQMessageBox::Information, + text, TQStringList(), + i18n("Always apply changes without confirmation"), + &alwaysApply, KMessageBox::Notify); + + if (alwaysApply) + AlbumSettings::instance()->setApplySidebarChangesDirectly(true); + + if (returnCode == KDialogBase::User1) + return; + // otherwise apply + } + + slotApplyAllChanges(); +} + +void ImageDescEditTab::slotApplyAllChanges() +{ + if (!d->modified) + return; + + if (d->currInfos.isEmpty()) + return; + + bool progressInfo = (d->currInfos.count() > 1); + emit signalProgressBarMode(StatusProgressBar::ProgressBarMode, + i18n("Applying changes to images. Please wait...")); + MetadataWriteSettings writeSettings = MetadataHub::defaultWriteSettings(); + + // debugging - use this to indicate reentry from event loop (kapp->processEvents) + // remove before final release + if (d->ignoreImageAttributesWatch) + { + DWarning() << "ImageDescEditTab::slotApplyAllChanges(): re-entering from event loop!" << endl; + } + + // we are now changing attributes ourselves + d->ignoreImageAttributesWatch = true; + AlbumLister::instance()->blockSignals(true); + AlbumManager::instance()->albumDB()->beginTransaction(); + int i=0; + for (ImageInfo *info = d->currInfos.first(); info; info = d->currInfos.next()) + { + // apply to database + d->hub.write(info); + // apply to file metadata + d->hub.write(info->filePath(), MetadataHub::FullWrite, writeSettings); + + emit signalProgressValue((int)((i++/(float)d->currInfos.count())*100.0)); + if (progressInfo) + kapp->processEvents(); + } + AlbumLister::instance()->blockSignals(false); + AlbumManager::instance()->albumDB()->commitTransaction(); + + d->ignoreImageAttributesWatch = false; + + emit signalProgressBarMode(StatusProgressBar::TextMode, TQString()); + + d->modified = false; + d->hub.resetChanged(); + d->applyBtn->setEnabled(false); + d->revertBtn->setEnabled(false); + + updateRecentTags(); + updateTagsView(); +} + +void ImageDescEditTab::slotRevertAllChanges() +{ + if (!d->modified) + return; + + if (d->currInfos.isEmpty()) + return; + + setInfos(d->currInfos); +} + +void ImageDescEditTab::setItem(ImageInfo *info) +{ + slotChangingItems(); + TQPtrList<ImageInfo> list; + if (info) + list.append(info); + setInfos(list); +} + +void ImageDescEditTab::setItems(TQPtrList<ImageInfo> infos) +{ + slotChangingItems(); + setInfos(infos); +} + +void ImageDescEditTab::setInfos(TQPtrList<ImageInfo> infos) +{ + if (infos.isEmpty()) + { + d->hub = MetadataHub(); + d->commentsEdit->blockSignals(true); + d->commentsEdit->clear(); + d->commentsEdit->blockSignals(false); + d->currInfos.clear(); + setEnabled(false); + return; + } + + setEnabled(true); + d->currInfos = infos; + d->modified = false; + d->hub = MetadataHub(); + d->applyBtn->setEnabled(false); + d->revertBtn->setEnabled(false); + + for (ImageInfo *info = d->currInfos.first(); info; info = d->currInfos.next()) + { + d->hub.load(info); + } + + updateComments(); + updateRating(); + updateDate(); + updateTagsView(); +} + +void ImageDescEditTab::slotReadFromFileMetadataToDatabase() +{ + emit signalProgressBarMode(StatusProgressBar::ProgressBarMode, + i18n("Reading metadata from files. Please wait...")); + + d->ignoreImageAttributesWatch = true; + AlbumManager::instance()->albumDB()->beginTransaction(); + int i=0; + for (ImageInfo *info = d->currInfos.first(); info; info = d->currInfos.next()) + { + // A batch operation: a hub for each single file, not the common hub + MetadataHub fileHub(MetadataHub::NewTagsImport); + // read in from DMetadata + fileHub.load(info->filePath()); + // write out to database + fileHub.write(info); + + emit signalProgressValue((int)((i++/(float)d->currInfos.count())*100.0)); + kapp->processEvents(); + } + AlbumManager::instance()->albumDB()->commitTransaction(); + d->ignoreImageAttributesWatch = false; + + emit signalProgressBarMode(StatusProgressBar::TextMode, TQString()); + + // reload everything + setInfos(d->currInfos); +} + +void ImageDescEditTab::slotWriteToFileMetadataFromDatabase() +{ + emit signalProgressBarMode(StatusProgressBar::ProgressBarMode, + i18n("Writing metadata to files. Please wait...")); + MetadataWriteSettings writeSettings = MetadataHub::defaultWriteSettings(); + + int i=0; + for (ImageInfo *info = d->currInfos.first(); info; info = d->currInfos.next()) + { + MetadataHub fileHub; + // read in from database + fileHub.load(info); + // write out to file DMetadata + fileHub.write(info->filePath()); + + emit signalProgressValue((int)((i++/(float)d->currInfos.count())*100.0)); + kapp->processEvents(); + } + + emit signalProgressBarMode(StatusProgressBar::TextMode, TQString()); +} + +bool ImageDescEditTab::eventFilter(TQObject *, TQEvent *e) +{ + if ( e->type() == TQEvent::KeyPress ) + { + TQKeyEvent *k = (TQKeyEvent *)e; + if (k->state() == TQt::ControlButton && + (k->key() == TQt::Key_Enter || k->key() == TQt::Key_Return)) + { + emit signalNextItem(); + return true; + } + else if (k->state() == TQt::ShiftButton && + (k->key() == TQt::Key_Enter || k->key() == TQt::Key_Return)) + { + emit signalPrevItem(); + return true; + } + + return false; + } + + return false; +} + +void ImageDescEditTab::populateTags() +{ + d->tagsView->clear(); + + AlbumList tList = AlbumManager::instance()->allTAlbums(); + for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it) + { + TAlbum *tag = (TAlbum*)(*it); + slotAlbumAdded(tag); + } + + d->tagsView->loadViewState(); +} + +void ImageDescEditTab::slotItemStateChanged(TAlbumCheckListItem *item) +{ + TagFilterView::ToggleAutoTags oldAutoTags = d->toggleAutoTags; + + switch(d->toggleAutoTags) + { + case TagFilterView::Children: + d->toggleAutoTags = TagFilterView::NoToggleAuto; + toggleChildTags(item->album(), item->isOn()); + d->toggleAutoTags = oldAutoTags; + break; + case TagFilterView::Parents: + d->toggleAutoTags = TagFilterView::NoToggleAuto; + toggleParentTags(item->album(), item->isOn()); + d->toggleAutoTags = oldAutoTags; + break; + case TagFilterView::ChildrenAndParents: + d->toggleAutoTags = TagFilterView::NoToggleAuto; + toggleChildTags(item->album(), item->isOn()); + toggleParentTags(item->album(), item->isOn()); + d->toggleAutoTags = oldAutoTags; + break; + default: + break; + } + + d->hub.setTag(item->album(), item->isOn()); + + d->tagsView->blockSignals(true); + item->setStatus(d->hub.tagStatus(item->album())); + d->tagsView->blockSignals(false); + + slotModified(); +} + +void ImageDescEditTab::slotCommentChanged() +{ + // we cannot trust that the text actually changed + // (there are bogus signals caused by spell checking, see bug 141663) + // so we have to check before marking the metadata as modified + if (d->hub.comment() == d->commentsEdit->text()) + return; + + d->hub.setComment(d->commentsEdit->text()); + setMetadataWidgetStatus(d->hub.commentStatus(), d->commentsEdit); + slotModified(); +} + +void ImageDescEditTab::slotDateTimeChanged(const TQDateTime& dateTime) +{ + d->hub.setDateTime(dateTime); + setMetadataWidgetStatus(d->hub.dateTimeStatus(), d->dateTimeEdit); + slotModified(); +} + +void ImageDescEditTab::slotRatingChanged(int rating) +{ + d->hub.setRating(rating); + // no handling for MetadataDisjoint needed for rating, + // we set it to 0 when disjoint, see below + slotModified(); +} + +void ImageDescEditTab::slotModified() +{ + d->modified = true; + d->applyBtn->setEnabled(true); + d->revertBtn->setEnabled(true); +} + +void ImageDescEditTab::assignRating(int rating) +{ + d->ratingWidget->setRating(rating); +} + +void ImageDescEditTab::updateTagsView() +{ + d->tagsView->blockSignals(true); + + TQListViewItemIterator it( d->tagsView); + while (it.current()) + { + TAlbumCheckListItem* tItem = dynamic_cast<TAlbumCheckListItem*>(it.current()); + if (tItem) + tItem->setStatus(d->hub.tagStatus(tItem->album())); + ++it; + } + + // The condition is a temporary fix not to destroy name filtering on image change. + // See comments in these methods. + if (d->assignedTagsBtn->isOn()) + slotAssignedTagsToggled(d->assignedTagsBtn->isOn()); + + d->tagsView->blockSignals(false); +} + +void ImageDescEditTab::updateComments() +{ + d->commentsEdit->blockSignals(true); + d->commentsEdit->setText(d->hub.comment()); + setMetadataWidgetStatus(d->hub.commentStatus(), d->commentsEdit); + d->commentsEdit->blockSignals(false); +} + +void ImageDescEditTab::updateRating() +{ + d->ratingWidget->blockSignals(true); + if (d->hub.ratingStatus() == MetadataHub::MetadataDisjoint) + d->ratingWidget->setRating(0); + else + d->ratingWidget->setRating(d->hub.rating()); + d->ratingWidget->blockSignals(false); +} + +void ImageDescEditTab::updateDate() +{ + d->dateTimeEdit->blockSignals(true); + d->dateTimeEdit->setDateTime(d->hub.dateTime()); + setMetadataWidgetStatus(d->hub.dateTimeStatus(), d->dateTimeEdit); + d->dateTimeEdit->blockSignals(false); +} + +void ImageDescEditTab::setMetadataWidgetStatus(int status, TQWidget *widget) +{ + if (status == MetadataHub::MetadataDisjoint) + { + // For text widgets: Set text color to color of disabled text + TQPalette palette = widget->palette(); + palette.setColor(TQColorGroup::Text, palette.color(TQPalette::Disabled, TQColorGroup::Text)); + widget->setPalette(palette); + } + else + { + widget->unsetPalette(); + } +} + +void ImageDescEditTab::slotRightButtonClicked(TQListViewItem *item, const TQPoint &, int ) +{ + TAlbum *album; + + if (!item) + { + album = AlbumManager::instance()->findTAlbum(0); + } + else + { + TAlbumCheckListItem* viewItem = dynamic_cast<TAlbumCheckListItem*>(item); + + if(!viewItem) + album = AlbumManager::instance()->findTAlbum(0); + else + album = viewItem->album(); + } + + if(!album) + return; + + d->ABCMenu = new TQPopupMenu; + + connect(d->ABCMenu, TQ_SIGNAL( aboutToShow() ), + this, TQ_SLOT( slotABCContextMenu() )); + + TDEPopupMenu popmenu(this); + popmenu.insertTitle(SmallIcon("digikam"), i18n("Tags")); + popmenu.insertItem(SmallIcon("tag-new"), i18n("New Tag..."), 10); + popmenu.insertItem(SmallIcon("tag-addressbook"), i18n("Create Tag From AddressBook"), d->ABCMenu); + + if (!album->isRoot()) + { + popmenu.insertItem(SmallIcon("tag-properties"), i18n("Edit Tag Properties..."), 11); + popmenu.insertItem(SmallIcon("tag-reset"), i18n("Reset Tag Icon"), 13); + popmenu.insertSeparator(-1); + popmenu.insertItem(SmallIcon("tag-delete"), i18n("Delete Tag"), 12); + } + + popmenu.insertSeparator(-1); + + TQPopupMenu selectTagsMenu; + selectTagsMenu.insertItem(i18n("All Tags"), 14); + if (!album->isRoot()) + { + selectTagsMenu.insertSeparator(-1); + selectTagsMenu.insertItem(i18n("Children"), 17); + selectTagsMenu.insertItem(i18n("Parents"), 19); + } + popmenu.insertItem(i18n("Select"), &selectTagsMenu); + + TQPopupMenu deselectTagsMenu; + deselectTagsMenu.insertItem(i18n("All Tags"), 15); + if (!album->isRoot()) + { + deselectTagsMenu.insertSeparator(-1); + deselectTagsMenu.insertItem(i18n("Children"), 18); + deselectTagsMenu.insertItem(i18n("Parents"), 20); + } + popmenu.insertItem(i18n("Deselect"), &deselectTagsMenu); + + popmenu.insertItem(i18n("Invert Selection"), 16); + popmenu.insertSeparator(-1); + + TQPopupMenu toggleAutoMenu; + toggleAutoMenu.setCheckable(true); + toggleAutoMenu.insertItem(i18n("None"), 21); + toggleAutoMenu.insertSeparator(-1); + toggleAutoMenu.insertItem(i18n("Children"), 22); + toggleAutoMenu.insertItem(i18n("Parents"), 23); + toggleAutoMenu.insertItem(i18n("Both"), 24); + toggleAutoMenu.setItemChecked(21 + d->toggleAutoTags, true); + popmenu.insertItem(i18n("Toggle Auto"), &toggleAutoMenu); + + TagFilterView::ToggleAutoTags oldAutoTags = d->toggleAutoTags; + + int choice = popmenu.exec((TQCursor::pos())); + switch( choice ) + { + case 10: // New Tag. + { + tagNew(album); + break; + } + case 11: // Edit Tag Properties. + { + if (!album->isRoot()) + tagEdit(album); + break; + } + case 12: // Delete Tag. + { + if (!album->isRoot()) + tagDelete(album); + break; + } + case 13: // Reset Tag Icon. + { + TQString errMsg; + AlbumManager::instance()->updateTAlbumIcon(album, TQString("tag"), 0, errMsg); + break; + } + case 14: // Select All Tags. + { + d->toggleAutoTags = TagFilterView::NoToggleAuto; + TQListViewItemIterator it(d->tagsView, TQListViewItemIterator::NotChecked); + while (it.current()) + { + TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(it.current()); + if (item->isVisible()) + item->setOn(true); + ++it; + } + d->toggleAutoTags = oldAutoTags; + break; + } + case 15: // Deselect All Tags. + { + d->toggleAutoTags = TagFilterView::NoToggleAuto; + TQListViewItemIterator it(d->tagsView, TQListViewItemIterator::Checked); + while (it.current()) + { + TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(it.current()); + if (item->isVisible()) + item->setOn(false); + ++it; + } + d->toggleAutoTags = oldAutoTags; + break; + } + case 16: // Invert All Tags Selection. + { + d->toggleAutoTags = TagFilterView::NoToggleAuto; + TQListViewItemIterator it(d->tagsView); + while (it.current()) + { + TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(it.current()); + if (item->isVisible()) + item->setOn(!item->isOn()); + ++it; + } + d->toggleAutoTags = oldAutoTags; + break; + } + case 17: // Select Child Tags. + { + d->toggleAutoTags = TagFilterView::NoToggleAuto; + toggleChildTags(album, true); + TAlbumCheckListItem *item = (TAlbumCheckListItem*)album->extraData(d->tagsView); + item->setOn(true); + d->toggleAutoTags = oldAutoTags; + break; + } + case 18: // Deselect Child Tags. + { + d->toggleAutoTags = TagFilterView::NoToggleAuto; + toggleChildTags(album, false); + TAlbumCheckListItem *item = (TAlbumCheckListItem*)album->extraData(d->tagsView); + item->setOn(false); + d->toggleAutoTags = oldAutoTags; + break; + } + case 19: // Select Parent Tags. + { + d->toggleAutoTags = TagFilterView::NoToggleAuto; + toggleParentTags(album, true); + TAlbumCheckListItem *item = (TAlbumCheckListItem*)album->extraData(d->tagsView); + item->setOn(true); + d->toggleAutoTags = oldAutoTags; + break; + } + case 20: // Deselect Parent Tags. + { + d->toggleAutoTags = TagFilterView::NoToggleAuto; + toggleParentTags(album, false); + TAlbumCheckListItem *item = (TAlbumCheckListItem*)album->extraData(d->tagsView); + item->setOn(false); + d->toggleAutoTags = oldAutoTags; + break; + } + case 21: // No toggle auto tags. + { + d->toggleAutoTags = TagFilterView::NoToggleAuto; + break; + } + case 22: // Toggle auto Children tags. + { + d->toggleAutoTags = TagFilterView::Children; + break; + } + case 23: // Toggle auto Parents tags. + { + d->toggleAutoTags = TagFilterView::Parents; + break; + } + case 24: // Toggle auto Children and Parents tags. + { + d->toggleAutoTags = TagFilterView::ChildrenAndParents; + break; + } + default: + break; + } + + if ( choice > 100 ) + { + tagNew(album, d->ABCMenu->text( choice ), "tag-people" ); + } + + delete d->ABCMenu; + d->ABCMenu = 0; +} + +void ImageDescEditTab::slotABCContextMenu() +{ + d->ABCMenu->clear(); + + int counter = 100; + TDEABC::AddressBook* ab = TDEABC::StdAddressBook::self(); + TQStringList names; + for ( TDEABC::AddressBook::Iterator it = ab->begin(); it != ab->end(); ++it ) + { + names.push_back(it->formattedName()); + } + + qHeapSort(names); + + for ( TQStringList::Iterator it = names.begin(); it != names.end(); ++it ) + { + TQString name = *it; + if ( !name.isNull() ) + d->ABCMenu->insertItem( name, ++counter ); + } + + if (counter == 100) + { + d->ABCMenu->insertItem( i18n("No AddressBook Entries Found"), ++counter ); + d->ABCMenu->setItemEnabled( counter, false ); + } +} + +void ImageDescEditTab::slotMoreMenu() +{ + d->moreMenu->clear(); + + if (singleSelection()) + { + d->moreMenu->insertItem(i18n("Read metadata from file to database"), this, TQ_SLOT(slotReadFromFileMetadataToDatabase())); + int writeActionId = d->moreMenu->insertItem(i18n("Write metadata to each file"), this, TQ_SLOT(slotWriteToFileMetadataFromDatabase())); + // we do not need a "Write to file" action here because the apply button will do just that + // if selection is a single file. + // Adding the option will confuse users: Does the apply button not write to file? + // Removing the option will confuse users: There is not option to write to file! (not visible in single selection) + // Disabling will confuse users: Why is it disabled? + d->moreMenu->setItemEnabled(writeActionId, false); + } + else + { + // We need to make clear that this action is different from the Apply button, + // which saves the same changes to all files. These batch operations operate on each single file. + d->moreMenu->insertItem(i18n("Read metadata from each file to database"), this, TQ_SLOT(slotReadFromFileMetadataToDatabase())); + d->moreMenu->insertItem(i18n("Write metadata to each file"), this, TQ_SLOT(slotWriteToFileMetadataFromDatabase())); + } +} + +void ImageDescEditTab::tagNew(TAlbum* parAlbum, const TQString& _title, const TQString& _icon) const +{ + if (!parAlbum) + return; + + TQString title = _title; + TQString icon = _icon; + + if (title.isNull()) + { + if (!TagEditDlg::tagCreate(kapp->activeWindow(), parAlbum, title, icon)) + return; + } + + TQMap<TQString, TQString> errMap; + AlbumList tList = TagEditDlg::createTAlbum(parAlbum, title, icon, errMap); + TagEditDlg::showtagsListCreationError(kapp->activeWindow(), errMap); + + for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it) + { + TAlbumCheckListItem* item = (TAlbumCheckListItem*)(*it)->extraData(d->tagsView); + if (item) + { + item->setOn(true); + d->tagsView->setSelected(item, true); + d->tagsView->ensureItemVisible(item); + } + } +} + +void ImageDescEditTab::tagDelete(TAlbum *album) +{ + if (!album || album->isRoot()) + return; + + AlbumManager *albumMan = AlbumManager::instance(); + + if (album == albumMan->currentAlbum() || + album->isAncestorOf(albumMan->currentAlbum())) + { + KMessageBox::error(this, i18n("You are currently viewing items in the " + "tag '%1' that you are about to delete. " + "You will need to apply change first " + "if you want to delete the tag." ) + .arg(album->title())); + return; + } + + // find number of subtags + int children = 0; + AlbumIterator iter(album); + while(iter.current()) + { + children++; + ++iter; + } + + if(children) + { + int result = KMessageBox::warningContinueCancel(this, + i18n("Tag '%1' has one subtag. " + "Deleting this will also delete " + "the subtag. " + "Do you want to continue?", + "Tag '%1' has %n subtags. " + "Deleting this will also delete " + "the subtags. " + "Do you want to continue?", + children).arg(album->title())); + + if(result != KMessageBox::Continue) + return; + } + + TQString message; + LLongList assignedItems = albumMan->albumDB()->getItemIDsInTag(album->id()); + if (!assignedItems.isEmpty()) + { + message = i18n("Tag '%1' is assigned to one item. " + "Do you want to continue?", + "Tag '%1' is assigned to %n items. " + "Do you want to continue?", + assignedItems.count()).arg(album->title()); + } + else + { + message = i18n("Delete '%1' tag?").arg(album->title()); + } + + int result = KMessageBox::warningContinueCancel(this, message, + i18n("Delete Tag"), + KGuiItem(i18n("Delete"), + "edit-delete")); + + if (result == KMessageBox::Continue) + { + TQString errMsg; + if (!albumMan->deleteTAlbum(album, errMsg)) + KMessageBox::error(this, errMsg); + } +} + +void ImageDescEditTab::tagEdit(TAlbum* album) +{ + if (!album || album->isRoot()) + return; + + TQString title; + TQString icon; + + if (!TagEditDlg::tagEdit(kapp->activeWindow(), album, title, icon)) + return; + + AlbumManager *albumMan = AlbumManager::instance(); + if (album->title() != title) + { + TQString errMsg; + if (!albumMan->renameTAlbum(album, title, errMsg)) + { + KMessageBox::error(this, errMsg); + return; + } + } + + if (album->icon() != icon) + { + TQString errMsg; + if (!albumMan->updateTAlbumIcon(album, icon, 0, errMsg)) + { + KMessageBox::error(this, errMsg); + } + } +} + +void ImageDescEditTab::slotAlbumAdded(Album* a) +{ + if (!a || a->type() != Album::TAG) + return; + + TAlbumCheckListItem* viewItem = 0; + + TAlbum* tag = dynamic_cast<TAlbum*>(a); + if (!tag) + return; + + if (tag->isRoot()) + { + viewItem = new TAlbumCheckListItem(d->tagsView, tag); + } + else + { + TAlbumCheckListItem* parent = (TAlbumCheckListItem*)(tag->parent()->extraData(d->tagsView)); + if (!parent) + { + DWarning() << k_funcinfo << "Failed to find parent for Tag " << tag->title() + << endl; + return; + } + + viewItem = new TAlbumCheckListItem(parent, tag); + d->tagsSearchBar->lineEdit()->completionObject()->addItem(tag->title()); + d->newTagEdit->lineEdit()->completionObject()->addItem(tag->tagPath()); + d->newTagEdit->lineEdit()->completionObject()->addItem(tag->tagPath().remove(0, 1)); // without root "/" + } + + if (viewItem) + { + // commenting this out due to the issues described in bug 148166. + // viewItem->setOpen(true); + setTagThumbnail(tag); + } +} + +void ImageDescEditTab::slotAlbumDeleted(Album* a) +{ + if (!a || a->isRoot() || a->type() != Album::TAG) + return; + + TAlbum* album = (TAlbum*)a; + + d->tagsSearchBar->lineEdit()->completionObject()->removeItem(album->title()); + d->newTagEdit->lineEdit()->completionObject()->removeItem(album->tagPath()); + d->newTagEdit->lineEdit()->completionObject()->removeItem(album->tagPath().remove(0, 1)); // without root "/" + TAlbumCheckListItem* viewItem = (TAlbumCheckListItem*)album->extraData(d->tagsView); + delete viewItem; + album->removeExtraData(this); + d->hub.setTag(album, false, MetadataHub::MetadataDisjoint); +} + +void ImageDescEditTab::slotAlbumsCleared() +{ + d->tagsView->clear(); + d->tagsSearchBar->lineEdit()->completionObject()->clear(); + d->newTagEdit->lineEdit()->completionObject()->clear(); +} + +void ImageDescEditTab::slotAlbumIconChanged(Album* a) +{ + if (!a || a->isRoot() || a->type() != Album::TAG) + return; + + setTagThumbnail((TAlbum *)a); +} + +void ImageDescEditTab::slotAlbumMoved(TAlbum* tag, TAlbum* newParent) +{ + if (!tag || !newParent) + return; + + TAlbumCheckListItem* item = (TAlbumCheckListItem*)tag->extraData(d->tagsView); + if (!item) + return; + + if (item->parent()) + { + TQListViewItem* oldPItem = item->parent(); + oldPItem->takeItem(item); + } + else + { + d->tagsView->takeItem(item); + } + + TAlbumCheckListItem* newPItem = (TAlbumCheckListItem*)newParent->extraData(d->tagsView); + if (newPItem) + newPItem->insertItem(item); + else + d->tagsView->insertItem(item); +} + +void ImageDescEditTab::slotAlbumRenamed(Album* album) +{ + if (!album || album->isRoot() || album->type() != Album::TAG) + return; + + TAlbum* tag = (TAlbum*)album; + d->tagsSearchBar->lineEdit()->completionObject()->addItem(tag->title()); + d->newTagEdit->lineEdit()->completionObject()->addItem(tag->tagPath()); + d->newTagEdit->lineEdit()->completionObject()->addItem(tag->tagPath().remove(0, 1)); // without root "/" + slotTagsSearchChanged(d->tagsSearchBar->lineEdit()->text()); + TAlbumCheckListItem* item = (TAlbumCheckListItem*)(tag->extraData(d->tagsView)); + if (item) + item->refresh(); +} + +void ImageDescEditTab::toggleChildTags(TAlbum *album, bool b) +{ + if (!album) + return; + + AlbumIterator it(album); + while ( it.current() ) + { + TAlbum *ta = (TAlbum*)it.current(); + TAlbumCheckListItem *item = (TAlbumCheckListItem*)(ta->extraData(d->tagsView)); + if (item) + if (item->isVisible()) + item->setOn(b); + ++it; + } +} + +void ImageDescEditTab::toggleParentTags(TAlbum *album, bool b) +{ + if (!album) + return; + + TQListViewItemIterator it(d->tagsView); + while (it.current()) + { + TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(it.current()); + if (item->isVisible()) + { + if (!item->album()) + continue; + if (item->album() == album->parent()) + { + item->setOn(b); + toggleParentTags(item->album() , b); + } + } + ++it; + } +} + +void ImageDescEditTab::setTagThumbnail(TAlbum *album) +{ + if(!album) + return; + + TAlbumCheckListItem* item = (TAlbumCheckListItem*)album->extraData(d->tagsView); + + if(!item) + return; + + AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance(); + TQPixmap icon; + if (!loader->getTagThumbnail(album, icon)) + { + if (icon.isNull()) + { + item->setPixmap(0, loader->getStandardTagIcon(album)); + } + else + { + TQPixmap blendedIcon = loader->blendIcons(loader->getStandardTagIcon(), icon); + item->setPixmap(0, blendedIcon); + } + } +} + +void ImageDescEditTab::slotGotThumbnailFromIcon(Album *album, const TQPixmap& thumbnail) +{ + if(!album || album->type() != Album::TAG) + return; + + // update item in tags tree + TAlbumCheckListItem* item = (TAlbumCheckListItem*)album->extraData(d->tagsView); + if(!item) + return; + + AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance(); + TQPixmap blendedIcon = loader->blendIcons(loader->getStandardTagIcon(), thumbnail); + item->setPixmap(0, blendedIcon); + + // update item in recent tags popup menu, if found there in + TQPopupMenu *menu = d->recentTagsBtn->popup(); + if (menu->indexOf(album->id()) != -1) + { + menu->changeItem(album->id(), thumbnail, menu->text(album->id())); + } +} + +void ImageDescEditTab::slotThumbnailLost(Album *) +{ + // we already set the standard icon before loading +} + +void ImageDescEditTab::slotReloadThumbnails() +{ + AlbumList tList = AlbumManager::instance()->allTAlbums(); + for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it) + { + TAlbum* tag = (TAlbum*)(*it); + setTagThumbnail(tag); + } +} + +void ImageDescEditTab::slotImageTagsChanged(TQ_LLONG imageId) +{ + // don't lose modifications + if (d->ignoreImageAttributesWatch || d->modified) + return; + + reloadForMetadataChange(imageId); +} + +void ImageDescEditTab::slotImagesChanged(int albumId) +{ + if (d->ignoreImageAttributesWatch || d->modified) + return; + + Album *a = AlbumManager::instance()->findAlbum(albumId); + if (d->currInfos.isEmpty() || !a || a->isRoot() || a->type() != Album::TAG) + return; + + setInfos(d->currInfos); +} + +void ImageDescEditTab::slotImageRatingChanged(TQ_LLONG imageId) +{ + if (d->ignoreImageAttributesWatch || d->modified) + return; + + reloadForMetadataChange(imageId); +} + +void ImageDescEditTab::slotImageCaptionChanged(TQ_LLONG imageId) +{ + if (d->ignoreImageAttributesWatch || d->modified) + return; + + reloadForMetadataChange(imageId); +} + +void ImageDescEditTab::slotImageDateChanged(TQ_LLONG imageId) +{ + if (d->ignoreImageAttributesWatch || d->modified) + return; + + reloadForMetadataChange(imageId); +} + +// private common code for above methods +void ImageDescEditTab::reloadForMetadataChange(TQ_LLONG imageId) +{ + if (d->currInfos.isEmpty()) + return; + + if (singleSelection()) + { + if (d->currInfos.first()->id() == imageId) + setInfos(d->currInfos); + } + else + { + // if image id is in our list, update + for (ImageInfo *info = d->currInfos.first(); info; info = d->currInfos.next()) + { + if (info->id() == imageId) + { + setInfos(d->currInfos); + return; + } + } + } +} + +void ImageDescEditTab::updateRecentTags() +{ + TQPopupMenu *menu = d->recentTagsBtn->popup(); + menu->clear(); + + AlbumManager* albumMan = AlbumManager::instance(); + IntList recentTags = albumMan->albumDB()->getRecentlyAssignedTags(); + + if (recentTags.isEmpty()) + { + menu->insertItem(i18n("No Recently Assigned Tags"), 0); + menu->setItemEnabled(0, false); + } + else + { + for (IntList::const_iterator it = recentTags.begin(); + it != recentTags.end(); ++it) + { + TAlbum* album = albumMan->findTAlbum(*it); + if (album) + { + AlbumThumbnailLoader *loader = AlbumThumbnailLoader::instance(); + TQPixmap icon; + if (!loader->getTagThumbnail(album, icon)) + { + if (icon.isNull()) + { + icon = loader->getStandardTagIcon(album, AlbumThumbnailLoader::SmallerSize); + } + } + TQString text = album->title() + " (" + ((TAlbum*)album->parent())->prettyURL() + ')'; + menu->insertItem(icon, text, album->id()); + } + } + } +} + +void ImageDescEditTab::slotRecentTagsMenuActivated(int id) +{ + AlbumManager* albumMan = AlbumManager::instance(); + + if (id > 0) + { + TAlbum* album = albumMan->findTAlbum(id); + if (album) + { + TAlbumCheckListItem* viewItem = (TAlbumCheckListItem*)album->extraData(d->tagsView); + if (viewItem) + { + viewItem->setOn(true); + d->tagsView->setSelected(viewItem, true); + d->tagsView->ensureItemVisible(viewItem); + } + } + } +} + +void ImageDescEditTab::slotTagsSearchChanged(const TQString& filter) +{ + if (filter.isEmpty()) + { + d->tagsView->collapseView(FolderView::OmitRoot); + return; + } + + //TODO: this will destroy assigned-tags filtering. Unify in one method. + TQString search = filter.lower(); + + bool atleastOneMatch = false; + + AlbumList tList = AlbumManager::instance()->allTAlbums(); + for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it) + { + TAlbum* tag = (TAlbum*)(*it); + + // don't touch the root Tag + if (tag->isRoot()) + continue; + + bool match = tag->title().lower().contains(search); + bool doesExpand = false; + if (!match) + { + // check if any of the parents match the search + Album* parent = tag->parent(); + while (parent && !parent->isRoot()) + { + if (parent->title().lower().contains(search)) + { + match = true; + break; + } + + parent = parent->parent(); + } + } + + if (!match) + { + // check if any of the children match the search + AlbumIterator it(tag); + while (it.current()) + { + if ((*it)->title().lower().contains(search)) + { + match = true; + doesExpand = true; + break; + } + ++it; + } + } + + TAlbumCheckListItem* viewItem = (TAlbumCheckListItem*)(tag->extraData(d->tagsView)); + + if (match) + { + atleastOneMatch = true; + + if (viewItem) + { + viewItem->setVisible(true); + viewItem->setOpen(doesExpand); + } + } + else + { + if (viewItem) + { + viewItem->setVisible(false); + viewItem->setOpen(false); + } + } + } + + if (search.isEmpty()) + { + TAlbum* root = AlbumManager::instance()->findTAlbum(0); + TAlbumCheckListItem* rootItem = (TAlbumCheckListItem*)(root->extraData(d->tagsView)); + if (rootItem) + rootItem->setText(0, root->title()); + } + else + { + TAlbum* root = AlbumManager::instance()->findTAlbum(0); + TAlbumCheckListItem* rootItem = (TAlbumCheckListItem*)(root->extraData(d->tagsView)); + if (rootItem) + rootItem->setText(0, i18n("Found Tags")); + } + + emit signalTagFilterMatch(atleastOneMatch); +} + +void ImageDescEditTab::slotAssignedTagsToggled(bool t) +{ + //TODO: this will destroy name filtering. Unify in one method. + TQListViewItemIterator it(d->tagsView); + while (it.current()) + { + TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(it.current()); + TAlbum *tag = item->album(); + if (tag) + { + if (!tag->isRoot()) + { + if (t) + { + MetadataHub::TagStatus status = d->hub.tagStatus(item->album()); + bool tagAssigned = (status == MetadataHub::MetadataAvailable && status.hasTag) + || status == MetadataHub::MetadataDisjoint; + item->setVisible(tagAssigned); + + if (tagAssigned) + { + Album* parent = tag->parent(); + while (parent && !parent->isRoot()) + { + TAlbumCheckListItem *pitem = (TAlbumCheckListItem*)parent->extraData(d->tagsView); + pitem->setVisible(true); + parent = parent->parent(); + } + } + } + else + { + item->setVisible(true); + } + } + } + ++it; + } + + // correct visibilities afterwards: + // As TQListViewItem::setVisible works recursively on all it's children + // we have to correct this + if (t) + { + it = d->tagsView; + while (it.current()) + { + TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(it.current()); + TAlbum *tag = item->album(); + if (tag) + { + if (!tag->isRoot()) + { + // only if the current item is not marked as tagged, check all children + MetadataHub::TagStatus status = d->hub.tagStatus(item->album()); + bool tagAssigned = (status == MetadataHub::MetadataAvailable && status.hasTag) + || status == MetadataHub::MetadataDisjoint; + if (!tagAssigned) + { + bool somethingIsSet = false; + TQListViewItem* nextSibling = (*it)->nextSibling(); + TQListViewItemIterator tmpIt = it; + ++tmpIt; + while (*tmpIt != nextSibling ) + { + TAlbumCheckListItem* tmpItem = dynamic_cast<TAlbumCheckListItem*>(tmpIt.current()); + MetadataHub::TagStatus tmpStatus = d->hub.tagStatus(tmpItem->album()); + bool tmpTagAssigned = (tmpStatus == MetadataHub::MetadataAvailable && tmpStatus.hasTag) + || tmpStatus == MetadataHub::MetadataDisjoint; + if(tmpTagAssigned) + { + somethingIsSet = true; + } + ++tmpIt; + } + if (!somethingIsSet) + { + item->setVisible(false); + } + } + } + } + ++it; + } + } + + TAlbum *root = AlbumManager::instance()->findTAlbum(0); + TAlbumCheckListItem *rootItem = (TAlbumCheckListItem*)(root->extraData(d->tagsView)); + if (rootItem) + { + if (t) + rootItem->setText(0, i18n("Assigned Tags")); + else + rootItem->setText(0, root->title()); + } +} + +void ImageDescEditTab::refreshTagsView() +{ + d->tagsView->refresh(); +} + +void ImageDescEditTab::slotCreateNewTag() +{ + TQString tagStr = d->newTagEdit->text(); + if (tagStr.isEmpty()) return; + + TAlbum *mainRootAlbum = 0; + TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(d->tagsView->selectedItem()); + if (item) + mainRootAlbum = item->album(); + + TQMap<TQString, TQString> errMap; + AlbumList tList = TagEditDlg::createTAlbum(mainRootAlbum, tagStr, TQString("tag"), errMap); + + for (AlbumList::iterator it = tList.begin(); it != tList.end(); ++it) + { + TAlbumCheckListItem* item = (TAlbumCheckListItem*)(*it)->extraData(d->tagsView); + if (item) + { + item->setOn(true); + d->tagsView->ensureItemVisible(item); + } + } + + d->newTagEdit->lineEdit()->clear(); +} + +} // NameSpace Digikam diff --git a/src/libs/imageproperties/imagedescedittab.h b/src/libs/imageproperties/imagedescedittab.h new file mode 100644 index 00000000..617bd59b --- /dev/null +++ b/src/libs/imageproperties/imagedescedittab.h @@ -0,0 +1,145 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2003-03-09 + * Description : Captions, Tags, and Rating properties editor + * + * Copyright (C) 2003-2005 by Renchi Raju <[email protected]> + * Copyright (C) 2003-2009 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2006-2009 by Marcel Wiesweg <[email protected]> + * Copyright (C) 2009 by Andi Clemens <andi dot clemens at gmx 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 IMAGEDESCEDITTAB_H +#define IMAGEDESCEDITTAB_H + +// TQt includes. + +#include <tqwidget.h> +#include <tqpixmap.h> +#include <tqptrlist.h> + +// Local includes. + +#include "digikam_export.h" +#include "navigatebartab.h" +#include "albummanager.h" + +class TQListViewItem; + +namespace Digikam +{ +class TAlbumCheckListItem; +class ImageInfo; +class ImageDescEditTabPriv; + +class DIGIKAM_EXPORT ImageDescEditTab : public NavigateBarTab +{ + TQ_OBJECT + + +public: + + ImageDescEditTab(TQWidget *parent, bool navBar=true); + ~ImageDescEditTab(); + + void assignRating(int rating); + void setItem(ImageInfo *info=0); + void setItems(TQPtrList<ImageInfo> infos); + void populateTags(); + void refreshTagsView(); + +signals: + + void signalProgressBarMode(int, const TQString&); + void signalProgressValue(int); + void signalTagFilterMatch(bool); + +protected: + + bool eventFilter(TQObject *o, TQEvent *e); + +private: + + void setInfos(TQPtrList<ImageInfo> infos); + + void updateTagsView(); + void updateComments(); + void updateRating(); + void updateDate(); + void updateRecentTags(); + + void tagNew(TAlbum* parAlbum, const TQString& _title=TQString(), const TQString& _icon=TQString()) const; + void tagEdit(TAlbum* album); + void tagDelete(TAlbum *album); + + void toggleChildTags(TAlbum *album, bool b); + void toggleParentTags(TAlbum *album, bool b); + + void setTagThumbnail(TAlbum *album); + + bool singleSelection() const; + void setMetadataWidgetStatus(int status, TQWidget *widget); + void reloadForMetadataChange(TQ_LLONG imageId); + +private slots: + + void slotApplyAllChanges(); + void slotCreateNewTag(); + void slotRevertAllChanges(); + void slotChangingItems(); + void slotItemStateChanged(TAlbumCheckListItem *); + void slotCommentChanged(); + void slotDateTimeChanged(const TQDateTime& dateTime); + void slotRatingChanged(int rating); + void slotModified(); + void slotRightButtonClicked(TQListViewItem *, const TQPoint &, int); + void slotTagsSearchChanged(const TQString&); + + void slotAlbumAdded(Album* a); + void slotAlbumDeleted(Album* a); + void slotAlbumIconChanged(Album* a); + void slotAlbumRenamed(Album* a); + void slotAlbumsCleared(); + void slotAlbumMoved(TAlbum* tag, TAlbum* newParent); + + void slotABCContextMenu(); + void slotGotThumbnailFromIcon(Album *album, const TQPixmap& thumbnail); + void slotThumbnailLost(Album *album); + void slotReloadThumbnails(); + + void slotImageTagsChanged(TQ_LLONG imageId); + void slotImagesChanged(int albumId); + void slotImageRatingChanged(TQ_LLONG imageId); + void slotImageDateChanged(TQ_LLONG imageId); + void slotImageCaptionChanged(TQ_LLONG imageId); + + void slotRecentTagsMenuActivated(int); + void slotAssignedTagsToggled(bool); + + void slotMoreMenu(); + void slotReadFromFileMetadataToDatabase(); + void slotWriteToFileMetadataFromDatabase(); + +private: + + ImageDescEditTabPriv* d; +}; + +} // NameSpace Digikam + +#endif // IMAGEDESCEDITTAB_H diff --git a/src/libs/imageproperties/imagepropertiescolorstab.cpp b/src/libs/imageproperties/imagepropertiescolorstab.cpp new file mode 100644 index 00000000..af85953b --- /dev/null +++ b/src/libs/imageproperties/imagepropertiescolorstab.cpp @@ -0,0 +1,799 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-11-17 + * Description : a tab to display colors information of 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++ includes. + +#include <cmath> + +// TQt includes. + +#include <tqlayout.h> +#include <tqspinbox.h> +#include <tqcombobox.h> +#include <tqlabel.h> +#include <tqwhatsthis.h> +#include <tqgroupbox.h> +#include <tqhbuttongroup.h> +#include <tqpushbutton.h> +#include <tqtooltip.h> +#include <tqvbox.h> +#include <tqscrollview.h> + +// KDE includes. + +#include <tdelocale.h> +#include <ksqueezedtextlabel.h> +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kdialogbase.h> +#include <kstandarddirs.h> +#include <ktabwidget.h> + +// Local includes. + +#include "ddebug.h" +#include "dimg.h" +#include "imagehistogram.h" +#include "histogramwidget.h" +#include "colorgradientwidget.h" +#include "navigatebarwidget.h" +#include "sharedloadsavethread.h" +#include "iccprofilewidget.h" +#include "cietonguewidget.h" +#include "imagepropertiescolorstab.h" +#include "imagepropertiescolorstab.moc" + +namespace Digikam +{ + +class ImagePropertiesColorsTabPriv +{ +public: + + enum MetadataTab + { + HISTOGRAM=0, + ICCPROFILE + }; + + ImagePropertiesColorsTabPriv() + { + imageLoaderThread = 0; + tab = 0; + channelCB = 0; + colorsCB = 0; + renderingCB = 0; + scaleBG = 0; + regionBG = 0; + minInterv = 0; + maxInterv = 0; + labelMeanValue = 0; + labelPixelsValue = 0; + labelStdDevValue = 0; + labelCountValue = 0; + labelMedianValue = 0; + labelPercentileValue = 0; + labelColorDepth = 0; + labelAlphaChannel = 0; + + iccProfileWidget = 0; + hGradient = 0; + histogramWidget = 0; + imageLoaderThread = 0; + + inLoadingProcess = false; + } + + bool inLoadingProcess; + + TQComboBox *channelCB; + TQComboBox *colorsCB; + TQComboBox *renderingCB; + + TQHButtonGroup *scaleBG; + TQHButtonGroup *regionBG; + + TQSpinBox *minInterv; + TQSpinBox *maxInterv; + + TQLabel *labelMeanValue; + TQLabel *labelPixelsValue; + TQLabel *labelStdDevValue; + TQLabel *labelCountValue; + TQLabel *labelMedianValue; + TQLabel *labelPercentileValue; + TQLabel *labelColorDepth; + TQLabel *labelAlphaChannel; + + TQString currentFilePath; + LoadingDescription currentLoadingDescription; + + TQRect selectionArea; + + TQByteArray embedded_profile; + + KTabWidget *tab; + + DImg image; + DImg imageSelection; + + ICCProfileWidget *iccProfileWidget; + ColorGradientWidget *hGradient; + HistogramWidget *histogramWidget; + SharedLoadSaveThread *imageLoaderThread; +}; + +ImagePropertiesColorsTab::ImagePropertiesColorsTab(TQWidget* parent, bool navBar) + : NavigateBarTab(parent) +{ + d = new ImagePropertiesColorsTabPriv; + + setupNavigateBar(navBar); + d->tab = new KTabWidget(this); + m_navigateBarLayout->addWidget(d->tab); + + // Histogram tab area ----------------------------------------------------- + + TQScrollView *sv = new TQScrollView(d->tab); + sv->viewport()->setBackgroundMode(TQt::PaletteBackground); + sv->setResizePolicy(TQScrollView::AutoOneFit); + sv->setFrameStyle(TQFrame::NoFrame); + + TQWidget* histogramPage = new TQWidget(sv->viewport()); + TQGridLayout *topLayout = new TQGridLayout(histogramPage, 8, 3, + KDialog::spacingHint(), KDialog::spacingHint()); + sv->addChild(histogramPage); + + TQLabel *label1 = new TQLabel(i18n("Channel:"), histogramPage); + label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter ); + d->channelCB = new TQComboBox( false, histogramPage ); + d->channelCB->insertItem( i18n("Luminosity") ); + d->channelCB->insertItem( i18n("Red") ); + d->channelCB->insertItem( i18n("Green") ); + d->channelCB->insertItem( i18n("Blue") ); + d->channelCB->insertItem( i18n("Alpha") ); + d->channelCB->insertItem( i18n("Colors") ); + TQWhatsThis::add( d->channelCB, i18n("<p>Select the histogram channel to display here:<p>" + "<b>Luminosity</b>: Display luminosity (perceived brightness) values.<p>" + "<b>Red</b>: Display the red image channel.<p>" + "<b>Green</b>: Display the green image channel.<p>" + "<b>Blue</b>: Display the blue image channel.<p>" + "<b>Alpha</b>: Display the alpha image channel. " + "This channel corresponds to the transparency value and " + "is supported by some image formats such as PNG or TIFF.<p>" + "<b>Colors</b>: Display all color channel values at the same time.")); + + d->scaleBG = new TQHButtonGroup(histogramPage); + d->scaleBG->setExclusive(true); + d->scaleBG->setFrameShape(TQFrame::NoFrame); + d->scaleBG->setInsideMargin( 0 ); + TQWhatsThis::add( d->scaleBG, i18n("<p>Select the histogram scale here.<p>" + "If the image's maximal values are small, you can use the linear scale.<p>" + "Logarithmic scale can be used when the maximal values are big; " + "if it is used, all values (small and large) will be visible on the " + "graph.")); + + TQPushButton *linHistoButton = new TQPushButton( d->scaleBG ); + TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) ); + d->scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram); + TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data"); + TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png"); + linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) ); + linHistoButton->setToggleButton(true); + + TQPushButton *logHistoButton = new TQPushButton( d->scaleBG ); + TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) ); + d->scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram); + TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data"); + directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png"); + logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) ); + logHistoButton->setToggleButton(true); + + TQLabel *label10 = new TQLabel(i18n("Colors:"), histogramPage); + label10->setAlignment ( TQt::AlignRight | TQt::AlignVCenter ); + d->colorsCB = new TQComboBox( false, histogramPage ); + d->colorsCB->insertItem( i18n("Red") ); + d->colorsCB->insertItem( i18n("Green") ); + d->colorsCB->insertItem( i18n("Blue") ); + d->colorsCB->setEnabled( false ); + TQWhatsThis::add( d->colorsCB, i18n("<p>Select the main color displayed with Colors Channel mode here:<p>" + "<b>Red</b>: Draw the red image channel in the foreground.<p>" + "<b>Green</b>: Draw the green image channel in the foreground.<p>" + "<b>Blue</b>: Draw the blue image channel in the foreground.<p>")); + + d->regionBG = new TQHButtonGroup(histogramPage); + d->regionBG->setExclusive(true); + d->regionBG->setFrameShape(TQFrame::NoFrame); + d->regionBG->setInsideMargin( 0 ); + d->regionBG->hide(); + TQWhatsThis::add( d->regionBG, i18n("<p>Select from which region the histogram will be computed here:<p>" + "<b>Full Image</b>: Compute histogram using the full image.<p>" + "<b>Selection</b>: Compute histogram using the current image " + "selection.")); + + TQPushButton *fullImageButton = new TQPushButton( d->regionBG ); + TQToolTip::add( fullImageButton, i18n( "<p>Full Image" ) ); + d->regionBG->insert(fullImageButton, HistogramWidget::FullImageHistogram); + TDEGlobal::dirs()->addResourceType("image-full", TDEGlobal::dirs()->kde_default("data") + "digikam/data"); + directory = TDEGlobal::dirs()->findResourceDir("image-full", "image-full.png"); + fullImageButton->setPixmap( TQPixmap( directory + "image-full.png" ) ); + fullImageButton->setToggleButton(true); + + TQPushButton *SelectionImageButton = new TQPushButton( d->regionBG ); + TQToolTip::add( SelectionImageButton, i18n( "<p>Selection" ) ); + d->regionBG->insert(SelectionImageButton, HistogramWidget::ImageSelectionHistogram); + TDEGlobal::dirs()->addResourceType("image-selection", TDEGlobal::dirs()->kde_default("data") + "digikam/data"); + directory = TDEGlobal::dirs()->findResourceDir("image-selection", "image-selection.png"); + SelectionImageButton->setPixmap( TQPixmap( directory + "image-selection.png" ) ); + SelectionImageButton->setToggleButton(true); + + // ------------------------------------------------------------- + + TQVBox *histoBox = new TQVBox(histogramPage); + d->histogramWidget = new HistogramWidget(256, 140, histoBox); + TQWhatsThis::add( d->histogramWidget, i18n("<p>This is the histogram drawing of the " + "selected image channel")); + TQLabel *space = new TQLabel(histoBox); + space->setFixedHeight(1); + d->hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal, 10, histoBox); + d->hGradient->setColors(TQColor("black"), TQColor("white")); + + // ------------------------------------------------------------- + + TQHBoxLayout *hlay2 = new TQHBoxLayout(KDialog::spacingHint()); + TQLabel *label3 = new TQLabel(i18n("Range:"), histogramPage); + label3->setAlignment(TQt::AlignLeft | TQt::AlignVCenter); + d->minInterv = new TQSpinBox(0, 255, 1, histogramPage); + d->minInterv->setValue(0); + TQWhatsThis::add(d->minInterv, i18n("<p>Select the minimal intensity " + "value of the histogram selection here.")); + d->maxInterv = new TQSpinBox(0, 255, 1, histogramPage); + d->maxInterv->setValue(255); + TQWhatsThis::add(d->minInterv, i18n("<p>Select the maximal intensity value " + "of the histogram selection here.")); + hlay2->addWidget(label3); + hlay2->addWidget(d->minInterv); + hlay2->addWidget(d->maxInterv); + + // ------------------------------------------------------------- + + TQGroupBox *gbox = new TQGroupBox(2, TQt::Horizontal, i18n("Statistics"), histogramPage); + TQWhatsThis::add( gbox, i18n("<p>Here you can see the statistical results calculated from the " + "selected histogram part. These values are available for all " + "channels.")); + + TQLabel *label5 = new TQLabel(i18n("Pixels:"), gbox); + label5->setAlignment(TQt::AlignLeft | TQt::AlignVCenter); + d->labelPixelsValue = new TQLabel(gbox); + d->labelPixelsValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter); + + TQLabel *label7 = new TQLabel(i18n("Count:"), gbox); + label7->setAlignment(TQt::AlignLeft | TQt::AlignVCenter); + d->labelCountValue = new TQLabel(gbox); + d->labelCountValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter); + + TQLabel *label4 = new TQLabel(i18n("Mean:"), gbox); + label4->setAlignment(TQt::AlignLeft | TQt::AlignVCenter); + d->labelMeanValue = new TQLabel(gbox); + d->labelMeanValue->setAlignment (TQt::AlignRight | TQt::AlignVCenter); + + TQLabel *label6 = new TQLabel(i18n("Std. deviation:"), gbox); + label6->setAlignment(TQt::AlignLeft | TQt::AlignVCenter); + d->labelStdDevValue = new TQLabel(gbox); + d->labelStdDevValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter); + + TQLabel *label8 = new TQLabel(i18n("Median:"), gbox); + label8->setAlignment(TQt::AlignLeft | TQt::AlignVCenter); + d->labelMedianValue = new TQLabel(gbox); + d->labelMedianValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter); + + TQLabel *label9 = new TQLabel(i18n("Percentile:"), gbox); + label9->setAlignment(TQt::AlignLeft | TQt::AlignVCenter); + d->labelPercentileValue = new TQLabel(gbox); + d->labelPercentileValue->setAlignment(TQt::AlignRight | TQt::AlignVCenter); + + TQLabel *label11 = new TQLabel(i18n("Color depth:"), gbox); + label11->setAlignment(TQt::AlignLeft | TQt::AlignVCenter); + d->labelColorDepth = new TQLabel(gbox); + d->labelColorDepth->setAlignment(TQt::AlignRight | TQt::AlignVCenter); + + TQLabel *label12 = new TQLabel(i18n("Alpha Channel:"), gbox); + label12->setAlignment(TQt::AlignLeft | TQt::AlignVCenter); + d->labelAlphaChannel = new TQLabel(gbox); + d->labelAlphaChannel->setAlignment(TQt::AlignRight | TQt::AlignVCenter); + + topLayout->addMultiCellWidget(label1, 1, 1, 0, 0); + topLayout->addMultiCellWidget(d->channelCB, 1, 1, 1, 1); + topLayout->addMultiCellWidget(d->scaleBG, 1, 1, 3, 3); + topLayout->addMultiCellWidget(label10, 2, 2, 0, 0); + topLayout->addMultiCellWidget(d->colorsCB, 2, 2, 1, 1); + topLayout->addMultiCellWidget(d->regionBG, 2, 2, 3, 3); + topLayout->addMultiCellWidget(histoBox, 3, 4, 0, 3); + topLayout->addMultiCellLayout(hlay2, 5, 5, 0, 3); + topLayout->addMultiCellWidget(gbox, 6, 6, 0, 3); + topLayout->setColStretch(2, 10); + topLayout->setRowStretch(7, 10); + + d->tab->insertTab(sv, i18n("Histogram"), ImagePropertiesColorsTabPriv::HISTOGRAM ); + + // ICC Profiles tab area --------------------------------------- + + TQScrollView *sv2 = new TQScrollView(d->tab); + sv2->viewport()->setBackgroundMode(TQt::PaletteBackground); + sv2->setResizePolicy(TQScrollView::AutoOneFit); + sv2->setFrameStyle(TQFrame::NoFrame); + + d->iccProfileWidget = new ICCProfileWidget(sv2->viewport()); + sv2->addChild(d->iccProfileWidget); + d->tab->insertTab(sv2, i18n("ICC profile"), ImagePropertiesColorsTabPriv::ICCPROFILE); + + // ------------------------------------------------------------- + + connect(d->channelCB, TQ_SIGNAL(activated(int)), + this, TQ_SLOT(slotChannelChanged(int))); + + connect(d->scaleBG, TQ_SIGNAL(released(int)), + this, TQ_SLOT(slotScaleChanged(int))); + + connect(d->colorsCB, TQ_SIGNAL(activated(int)), + this, TQ_SLOT(slotColorsChanged(int))); + + connect(d->regionBG, TQ_SIGNAL(released(int)), + this, TQ_SLOT(slotRenderingChanged(int))); + + connect(d->histogramWidget, TQ_SIGNAL(signalIntervalChanged( int, int )), + this, TQ_SLOT(slotUpdateInterval(int, int))); + + connect(d->histogramWidget, TQ_SIGNAL(signalMaximumValueChanged( int )), + this, TQ_SLOT(slotUpdateIntervRange(int))); + + connect(d->histogramWidget, TQ_SIGNAL(signalHistogramComputationDone(bool)), + this, TQ_SLOT(slotRefreshOptions(bool))); + + connect(d->histogramWidget, TQ_SIGNAL(signalHistogramComputationFailed(void)), + this, TQ_SLOT(slotHistogramComputationFailed(void))); + + connect(d->minInterv, TQ_SIGNAL(valueChanged (int)), + this, TQ_SLOT(slotMinValueChanged(int))); + + connect(d->maxInterv, TQ_SIGNAL(valueChanged (int)), + this, TQ_SLOT(slotMaxValueChanged(int))); + + // -- read config --------------------------------------------------------- + + TDEConfig* config = kapp->config(); + config->setGroup("Image Properties SideBar"); + d->tab->setCurrentPage(config->readNumEntry("ImagePropertiesColors Tab", + ImagePropertiesColorsTabPriv::HISTOGRAM)); + d->iccProfileWidget->setMode(config->readNumEntry("ICC Level", ICCProfileWidget::SIMPLE)); + d->iccProfileWidget->setCurrentItemByKey(config->readEntry("Current ICC Item", TQString())); + + d->channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity. + d->scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram)); + d->colorsCB->setCurrentItem(config->readNumEntry("Histogram Color", 0)); // Red. + d->regionBG->setButton(config->readNumEntry("Histogram Rendering", HistogramWidget::FullImageHistogram)); +} + +ImagePropertiesColorsTab::~ImagePropertiesColorsTab() +{ + // If there is a currently histogram computation when dialog is closed, + // stop it before the d->image data are deleted automatically! + d->histogramWidget->stopHistogramComputation(); + + TDEConfig* config = kapp->config(); + config->setGroup("Image Properties SideBar"); + config->writeEntry("ImagePropertiesColors Tab", d->tab->currentPageIndex()); + config->writeEntry("Histogram Channel", d->channelCB->currentItem()); + config->writeEntry("Histogram Scale", d->scaleBG->selectedId()); + config->writeEntry("Histogram Color", d->colorsCB->currentItem()); + config->writeEntry("Histogram Rendering", d->regionBG->selectedId()); + config->writeEntry("ICC Level", d->iccProfileWidget->getMode()); + config->writeEntry("Current ICC Item", d->iccProfileWidget->getCurrentItemKey()); + config->sync(); + + if (d->imageLoaderThread) + delete d->imageLoaderThread; + + if (d->histogramWidget) + delete d->histogramWidget; + + if (d->hGradient) + delete d->hGradient; + + delete d; +} + +void ImagePropertiesColorsTab::setData(const KURL& url, const TQRect &selectionArea, + DImg *img) +{ + // We might be getting duplicate events from AlbumIconView, + // which will cause all sorts of duplicate work. + // More importantly, while the loading thread can handle this pretty well, + // this will completely mess up the timing of progress info in the histogram widget. + // So filter here, before the stopHistogramComputation! + if (!img && url.path() == d->currentFilePath && d->inLoadingProcess) + return; + + // This is necessary to stop computation because d->image.bits() is currently used by + // threaded histogram algorithm. + d->histogramWidget->stopHistogramComputation(); + + d->currentFilePath = TQString(); + d->currentLoadingDescription = LoadingDescription(); + d->iccProfileWidget->loadFromURL(KURL()); + + // Clear information. + d->labelMeanValue->clear(); + d->labelPixelsValue->clear(); + d->labelStdDevValue->clear(); + d->labelCountValue->clear(); + d->labelMedianValue->clear(); + d->labelPercentileValue->clear(); + d->labelColorDepth->clear(); + d->labelAlphaChannel->clear(); + + if (url.isEmpty()) + { + setEnabled(false); + return; + } + + d->selectionArea = selectionArea; + d->image.reset(); + setEnabled(true); + + if (!img) + { + loadImageFromUrl(url); + } + else + { + d->image = img->copy(); + + if ( !d->image.isNull() ) + { + getICCData(); + + // If a selection area is done in Image Editor and if the current image is the same + // in Image Editor, then compute too the histogram for this selection. + if (d->selectionArea.isValid()) + { + d->imageSelection = d->image.copy(d->selectionArea); + d->histogramWidget->updateData(d->image.bits(), d->image.width(), d->image.height(), + d->image.sixteenBit(), d->imageSelection.bits(), + d->imageSelection.width(), d->imageSelection.height()); + d->regionBG->show(); + updateInformations(); + } + else + { + d->histogramWidget->updateData(d->image.bits(), d->image.width(), + d->image.height(), d->image.sixteenBit()); + d->regionBG->hide(); + updateInformations(); + } + } + else + { + d->histogramWidget->setLoadingFailed(); + d->iccProfileWidget->setLoadingFailed(); + slotHistogramComputationFailed(); + } + } +} + +void ImagePropertiesColorsTab::loadImageFromUrl(const KURL& url) +{ + // create thread on demand + if (!d->imageLoaderThread) + { + d->imageLoaderThread = new SharedLoadSaveThread(); + + connect(d->imageLoaderThread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription &, const DImg&)), + this, TQ_SLOT(slotLoadImageFromUrlComplete(const LoadingDescription &, const DImg&))); + + connect(d->imageLoaderThread, TQ_SIGNAL(signalMoreCompleteLoadingAvailable(const LoadingDescription &, const LoadingDescription &)), + this, TQ_SLOT(slotMoreCompleteLoadingAvailable(const LoadingDescription &, const LoadingDescription &))); + } + + LoadingDescription desc = LoadingDescription(url.path()); + + if (DImg::fileFormat(desc.filePath) == DImg::RAW) + { + // use raw settings optimized for speed + + DRawDecoding rawDecodingSettings = DRawDecoding(); + rawDecodingSettings.optimizeTimeLoading(); + desc = LoadingDescription(desc.filePath, rawDecodingSettings); + } + + if (d->currentLoadingDescription.equalsOrBetterThan(desc)) + return; + + d->currentFilePath = desc.filePath; + d->currentLoadingDescription = desc; + d->inLoadingProcess = true; + + d->imageLoaderThread->load(d->currentLoadingDescription, + SharedLoadSaveThread::AccessModeRead, + SharedLoadSaveThread::LoadingPolicyFirstRemovePrevious); + + d->histogramWidget->setDataLoading(); + d->iccProfileWidget->setDataLoading(); +} + +void ImagePropertiesColorsTab::slotLoadImageFromUrlComplete(const LoadingDescription &loadingDescription, const DImg& img) +{ + // Discard any leftover messages from previous, possibly aborted loads + if ( !loadingDescription.equalsOrBetterThan(d->currentLoadingDescription) ) + return; + + if ( !img.isNull() ) + { + d->histogramWidget->updateData(img.bits(), img.width(), img.height(), img.sixteenBit()); + + // As a safety precaution, this must be changed only after updateData is called, + // which stops computation because d->image.bits() is currently used by threaded histogram algorithm. + d->image = img; + d->regionBG->hide(); + updateInformations(); + getICCData(); + } + else + { + d->histogramWidget->setLoadingFailed(); + d->iccProfileWidget->setLoadingFailed(); + slotHistogramComputationFailed(); + } + d->inLoadingProcess = false; +} + +void ImagePropertiesColorsTab::slotMoreCompleteLoadingAvailable(const LoadingDescription &oldLoadingDescription, + const LoadingDescription &newLoadingDescription) +{ + if (oldLoadingDescription == d->currentLoadingDescription && + newLoadingDescription.equalsOrBetterThan(d->currentLoadingDescription)) + { + // Yes, we do want to stop our old time-optimized loading and chain to the current, more complete loading. + // Even the time-optimized raw loading takes significant time, and we must avoid two dcraw instances running + // at a time. + d->currentLoadingDescription = newLoadingDescription; + d->inLoadingProcess = true; + d->imageLoaderThread->load(newLoadingDescription, + SharedLoadSaveThread::AccessModeRead, + SharedLoadSaveThread::LoadingPolicyFirstRemovePrevious); + } +} + +void ImagePropertiesColorsTab::setSelection(const TQRect &selectionArea) +{ + // This is necessary to stop computation because d->image.bits() is currently used by + // threaded histogram algorithm. + + d->histogramWidget->stopHistogramComputation(); + d->selectionArea = selectionArea; + + if (d->selectionArea.isValid()) + { + d->imageSelection = d->image.copy(d->selectionArea); + d->histogramWidget->updateSelectionData(d->imageSelection.bits(), d->imageSelection.width(), + d->imageSelection.height(), d->imageSelection.sixteenBit()); + d->regionBG->show(); + } + else + { + d->regionBG->hide(); + slotRenderingChanged(HistogramWidget::FullImageHistogram); + } +} + +void ImagePropertiesColorsTab::slotRefreshOptions(bool /*sixteenBit*/) +{ + slotChannelChanged(d->channelCB->currentItem()); + slotScaleChanged(d->scaleBG->selectedId()); + slotColorsChanged(d->colorsCB->currentItem()); + + if (d->selectionArea.isValid()) + slotRenderingChanged(d->regionBG->selectedId()); +} + +void ImagePropertiesColorsTab::slotHistogramComputationFailed() +{ + d->imageSelection.reset(); + d->image.reset(); +} + +void ImagePropertiesColorsTab::slotChannelChanged(int channel) +{ + switch(channel) + { + case RedChannel: + d->histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram; + d->hGradient->setColors( TQColor( "black" ), TQColor( "red" ) ); + d->colorsCB->setEnabled(false); + break; + + case GreenChannel: + d->histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram; + d->hGradient->setColors( TQColor( "black" ), TQColor( "green" ) ); + d->colorsCB->setEnabled(false); + break; + + case BlueChannel: + d->histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram; + d->hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) ); + d->colorsCB->setEnabled(false); + break; + + case AlphaChannel: + d->histogramWidget->m_channelType = HistogramWidget::AlphaChannelHistogram; + d->hGradient->setColors( TQColor( "black" ), TQColor( "white" ) ); + d->colorsCB->setEnabled(false); + break; + + case ColorChannels: + d->histogramWidget->m_channelType = HistogramWidget::ColorChannelsHistogram; + d->hGradient->setColors( TQColor( "black" ), TQColor( "white" ) ); + d->colorsCB->setEnabled(true); + break; + + default: // Luminosity. + d->histogramWidget->m_channelType = HistogramWidget::ValueHistogram; + d->hGradient->setColors( TQColor( "black" ), TQColor( "white" ) ); + d->colorsCB->setEnabled(false); + break; + } + + d->histogramWidget->repaint(false); + updateStatistiques(); +} + +void ImagePropertiesColorsTab::slotScaleChanged(int scale) +{ + d->histogramWidget->m_scaleType = scale; + d->histogramWidget->repaint(false); +} + +void ImagePropertiesColorsTab::slotColorsChanged(int color) +{ + switch(color) + { + case AllColorsGreen: + d->histogramWidget->m_colorType = HistogramWidget::GreenColor; + break; + + case AllColorsBlue: + d->histogramWidget->m_colorType = HistogramWidget::BlueColor; + break; + + default: // Red. + d->histogramWidget->m_colorType = HistogramWidget::RedColor; + break; + } + + d->histogramWidget->repaint(false); + updateStatistiques(); +} + +void ImagePropertiesColorsTab::slotRenderingChanged(int rendering) +{ + d->histogramWidget->m_renderingType = rendering; + d->histogramWidget->repaint(false); + updateStatistiques(); +} + +void ImagePropertiesColorsTab::slotMinValueChanged(int min) +{ + // Called when user changes values of spin box. + // Communicate the change to histogram widget. + + // make the one control "push" the other + if (min == d->maxInterv->value()+1) + d->maxInterv->setValue(min); + d->maxInterv->setMinValue(min-1); + d->histogramWidget->slotMinValueChanged(min); + updateStatistiques(); +} + +void ImagePropertiesColorsTab::slotMaxValueChanged(int max) +{ + if (max == d->minInterv->value()-1) + d->minInterv->setValue(max); + d->minInterv->setMaxValue(max+1); + d->histogramWidget->slotMaxValueChanged(max); + updateStatistiques(); +} + +void ImagePropertiesColorsTab::slotUpdateInterval(int min, int max) +{ + // Called when value is set from within histogram widget. + // Block signals to prevent slotMinValueChanged and + // slotMaxValueChanged being called. + d->minInterv->blockSignals(true); + d->minInterv->setMaxValue(max+1); + d->minInterv->setValue(min); + d->minInterv->blockSignals(false); + + d->maxInterv->blockSignals(true); + d->maxInterv->setMinValue(min-1); + d->maxInterv->setValue(max); + d->maxInterv->blockSignals(false); + + updateStatistiques(); +} + +void ImagePropertiesColorsTab::slotUpdateIntervRange(int range) +{ + d->maxInterv->setMaxValue( range ); +} + +void ImagePropertiesColorsTab::updateInformations() +{ + d->labelColorDepth->setText(d->image.sixteenBit() ? i18n("16 bits") : i18n("8 bits")); + d->labelAlphaChannel->setText(d->image.hasAlpha() ? i18n("Yes") : i18n("No")); +} + +void ImagePropertiesColorsTab::updateStatistiques() +{ + TQString value; + int min = d->minInterv->value(); + int max = d->maxInterv->value(); + int channel = d->channelCB->currentItem(); + + if ( channel == HistogramWidget::ColorChannelsHistogram ) + channel = d->colorsCB->currentItem()+1; + + double mean = d->histogramWidget->m_imageHistogram->getMean(channel, min, max); + d->labelMeanValue->setText(value.setNum(mean, 'f', 1)); + + double pixels = d->histogramWidget->m_imageHistogram->getPixels(); + d->labelPixelsValue->setText(value.setNum((float)pixels, 'f', 0)); + + double stddev = d->histogramWidget->m_imageHistogram->getStdDev(channel, min, max); + d->labelStdDevValue->setText(value.setNum(stddev, 'f', 1)); + + double counts = d->histogramWidget->m_imageHistogram->getCount(channel, min, max); + d->labelCountValue->setText(value.setNum((float)counts, 'f', 0)); + + double median = d->histogramWidget->m_imageHistogram->getMedian(channel, min, max); + d->labelMedianValue->setText(value.setNum(median, 'f', 1)); + + double percentile = (pixels > 0 ? (100.0 * counts / pixels) : 0.0); + d->labelPercentileValue->setText(value.setNum(percentile, 'f', 1)); +} + +void ImagePropertiesColorsTab::getICCData() +{ + if (d->image.getICCProfil().isNull()) + { + d->iccProfileWidget->setLoadingFailed(); + } + else + { + d->embedded_profile = d->image.getICCProfil(); + d->iccProfileWidget->loadFromData(d->currentFilePath, d->embedded_profile); + } +} + +} // NameSpace Digikam + diff --git a/src/libs/imageproperties/imagepropertiescolorstab.h b/src/libs/imageproperties/imagepropertiescolorstab.h new file mode 100644 index 00000000..0e01cad3 --- /dev/null +++ b/src/libs/imageproperties/imagepropertiescolorstab.h @@ -0,0 +1,114 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-11-17 + * Description : a tab to display colors information of 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. + * ============================================================ */ + +#ifndef IMAGEPROPERTIESCOLORSTAB_H +#define IMAGEPROPERTIESCOLORSTAB_H + +// TQt includes. + +#include <tqwidget.h> +#include <tqcstring.h> + +// KDE includes. + +#include <kurl.h> + +// Local includes. + +#include "dimg.h" +#include "digikam_export.h" +#include "navigatebartab.h" + +class TQRect; + +namespace Digikam +{ + +class DImg; +class LoadingDescription; +class ImagePropertiesColorsTabPriv; + +class DIGIKAM_EXPORT ImagePropertiesColorsTab : public NavigateBarTab +{ + TQ_OBJECT + + +public: + + ImagePropertiesColorsTab(TQWidget* parent, bool navBar=true); + ~ImagePropertiesColorsTab(); + + void setData(const KURL& url=KURL(), const TQRect &selectionArea = TQRect(), + DImg *img=0); + + void setSelection(const TQRect &selectionArea); + +private: + + void loadImageFromUrl(const KURL& url); + void updateInformations(); + void updateStatistiques(); + void getICCData(); + +private slots: + + void slotRefreshOptions(bool sixteenBit); + void slotHistogramComputationFailed(void); + void slotChannelChanged(int channel); + void slotScaleChanged(int scale); + void slotColorsChanged(int color); + void slotRenderingChanged(int rendering); + void slotMinValueChanged(int); + void slotMaxValueChanged(int); + + void slotUpdateInterval(int min, int max); + void slotUpdateIntervRange(int range); + + void slotLoadImageFromUrlComplete(const LoadingDescription &loadingDescription, const DImg& img); + void slotMoreCompleteLoadingAvailable(const LoadingDescription &oldLoadingDescription, + const LoadingDescription &newLoadingDescription); + +private: + + enum ColorChannel + { + LuminosityChannel=0, + RedChannel, + GreenChannel, + BlueChannel, + AlphaChannel, + ColorChannels + }; + + enum AllColorsColorType + { + AllColorsRed=0, + AllColorsGreen, + AllColorsBlue + }; + + ImagePropertiesColorsTabPriv* d; +}; + +} // NameSpace Digikam + +#endif /* IMAGEPROPERTIESCOLORSTAB_H */ diff --git a/src/libs/imageproperties/imagepropertiesmetadatatab.cpp b/src/libs/imageproperties/imagepropertiesmetadatatab.cpp new file mode 100644 index 00000000..5a48aaec --- /dev/null +++ b/src/libs/imageproperties/imagepropertiesmetadatatab.cpp @@ -0,0 +1,201 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-11-17 + * Description : a tab to display metadata information of 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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqlayout.h> +#include <tqfile.h> +#include <tqlabel.h> +#include <tqpixmap.h> +#include <tqfileinfo.h> +#include <tqwhatsthis.h> + +// KDE includes. + +#include <tdelocale.h> +#include <tdeapplication.h> +#include <tdeconfig.h> +#include <kdialogbase.h> +#include <tdefileitem.h> +#include <ktabwidget.h> + +// Local includes. + +#include "ddebug.h" +#include "dmetadata.h" +#include "exifwidget.h" +#include "makernotewidget.h" +#include "iptcwidget.h" +#include "gpswidget.h" +#include "navigatebarwidget.h" +#include "imagepropertiesmetadatatab.h" +#include "imagepropertiesmetadatatab.moc" + +namespace Digikam +{ + +class ImagePropertiesMetadataTabPriv +{ +public: + + enum MetadataTab + { + EXIF=0, + MAKERNOTE, + IPTC, + GPS + }; + + ImagePropertiesMetadataTabPriv() + { + exifWidget = 0; + makernoteWidget = 0; + iptcWidget = 0; + gpsWidget = 0; + tab = 0; + } + + KTabWidget *tab; + + ExifWidget *exifWidget; + + MakerNoteWidget *makernoteWidget; + + IptcWidget *iptcWidget; + + GPSWidget *gpsWidget; +}; + +ImagePropertiesMetaDataTab::ImagePropertiesMetaDataTab(TQWidget* parent, bool navBar) + : NavigateBarTab(parent) +{ + d = new ImagePropertiesMetadataTabPriv; + + setupNavigateBar(navBar); + d->tab = new KTabWidget(this); + m_navigateBarLayout->addWidget(d->tab); + + // Exif tab area ----------------------------------------------------- + + d->exifWidget = new ExifWidget(d->tab); + d->tab->insertTab(d->exifWidget, i18n("EXIF"), ImagePropertiesMetadataTabPriv::EXIF); + + // Makernote tab area ----------------------------------------------------- + + d->makernoteWidget = new MakerNoteWidget(d->tab); + d->tab->insertTab(d->makernoteWidget, i18n("Makernote"), ImagePropertiesMetadataTabPriv::MAKERNOTE); + + // IPTC tab area --------------------------------------- + + d->iptcWidget = new IptcWidget(d->tab); + d->tab->insertTab(d->iptcWidget, i18n("IPTC"), ImagePropertiesMetadataTabPriv::IPTC); + + // GPS tab area --------------------------------------- + + d->gpsWidget = new GPSWidget(d->tab); + d->tab->insertTab(d->gpsWidget, i18n("GPS"), ImagePropertiesMetadataTabPriv::GPS); + + // -- read config --------------------------------------------------------- + + TDEConfig* config = kapp->config(); + config->setGroup("Image Properties SideBar"); + d->tab->setCurrentPage(config->readNumEntry("ImagePropertiesMetaData Tab", + ImagePropertiesMetadataTabPriv::EXIF)); + d->exifWidget->setMode(config->readNumEntry("EXIF Level", ExifWidget::SIMPLE)); + d->makernoteWidget->setMode(config->readNumEntry("MAKERNOTE Level", MakerNoteWidget::SIMPLE)); + d->iptcWidget->setMode(config->readNumEntry("IPTC Level", IptcWidget::SIMPLE)); + d->gpsWidget->setMode(config->readNumEntry("GPS Level", GPSWidget::SIMPLE)); + d->exifWidget->setCurrentItemByKey(config->readEntry("Current EXIF Item", TQString())); + d->makernoteWidget->setCurrentItemByKey(config->readEntry("Current MAKERNOTE Item", TQString())); + d->iptcWidget->setCurrentItemByKey(config->readEntry("Current IPTC Item", TQString())); + d->gpsWidget->setCurrentItemByKey(config->readEntry("Current GPS Item", TQString())); + d->gpsWidget->setWebGPSLocator(config->readNumEntry("Current Web GPS Locator", GPSWidget::MapQuest)); +} + +ImagePropertiesMetaDataTab::~ImagePropertiesMetaDataTab() +{ + TDEConfig* config = kapp->config(); + config->setGroup("Image Properties SideBar"); + config->writeEntry("ImagePropertiesMetaData Tab", d->tab->currentPageIndex()); + config->writeEntry("EXIF Level", d->exifWidget->getMode()); + config->writeEntry("MAKERNOTE Level", d->makernoteWidget->getMode()); + config->writeEntry("IPTC Level", d->iptcWidget->getMode()); + config->writeEntry("GPS Level", d->gpsWidget->getMode()); + config->writeEntry("Current EXIF Item", d->exifWidget->getCurrentItemKey()); + config->writeEntry("Current MAKERNOTE Item", d->makernoteWidget->getCurrentItemKey()); + config->writeEntry("Current IPTC Item", d->iptcWidget->getCurrentItemKey()); + config->writeEntry("Current GPS Item", d->gpsWidget->getCurrentItemKey()); + config->writeEntry("Current Web GPS Locator", d->gpsWidget->getWebGPSLocator()); + config->sync(); + + delete d; +} + +void ImagePropertiesMetaDataTab::setCurrentURL(const KURL& url) +{ + if (url.isEmpty()) + { + d->exifWidget->loadFromURL(url); + d->makernoteWidget->loadFromURL(url); + d->iptcWidget->loadFromURL(url); + d->gpsWidget->loadFromURL(url); + setEnabled(false); + return; + } + + setEnabled(true); + DMetadata metadata(url.path()); + + TQByteArray exifData = metadata.getExif(); + TQByteArray iptcData = metadata.getIptc(); + + d->exifWidget->loadFromData(url.filename(), exifData); + d->makernoteWidget->loadFromData(url.filename(), exifData); + d->iptcWidget->loadFromData(url.filename(), iptcData); + d->gpsWidget->loadFromData(url.filename(), exifData); +} + +void ImagePropertiesMetaDataTab::setCurrentData(const TQByteArray& exifData, + const TQByteArray& iptcData, + const TQString& filename) +{ + if (exifData.isEmpty() && iptcData.isEmpty()) + { + d->exifWidget->loadFromData(filename, exifData); + d->makernoteWidget->loadFromData(filename, exifData); + d->iptcWidget->loadFromData(filename, iptcData); + d->gpsWidget->loadFromData(filename, exifData); + setEnabled(false); + return; + } + + setEnabled(true); + + d->exifWidget->loadFromData(filename, exifData); + d->makernoteWidget->loadFromData(filename, exifData); + d->iptcWidget->loadFromData(filename, iptcData); + d->gpsWidget->loadFromData(filename, exifData); +} + +} // NameSpace Digikam + diff --git a/src/libs/imageproperties/imagepropertiesmetadatatab.h b/src/libs/imageproperties/imagepropertiesmetadatatab.h new file mode 100644 index 00000000..95b8ecb8 --- /dev/null +++ b/src/libs/imageproperties/imagepropertiesmetadatatab.h @@ -0,0 +1,68 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-11-17 + * Description : a tab to display metadata information of 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 IMAGEPROPERTIESMETADATATAB_H +#define IMAGEPROPERTIESMETADATATAB_H + +// TQt includes. + +#include <tqwidget.h> +#include <tqcstring.h> + +// KDE includes. + +#include <kurl.h> + +// Local includes. + +#include "digikam_export.h" +#include "navigatebartab.h" + +namespace Digikam +{ + +class ImagePropertiesMetadataTabPriv; + +class DIGIKAM_EXPORT ImagePropertiesMetaDataTab : public NavigateBarTab +{ + TQ_OBJECT + + +public: + + ImagePropertiesMetaDataTab(TQWidget* parent, bool navBar=true); + ~ImagePropertiesMetaDataTab(); + + void setCurrentURL(const KURL& url=KURL()); + void setCurrentData(const TQByteArray& exifData=TQByteArray(), + const TQByteArray& iptcData=TQByteArray(), + const TQString& filename=TQString()); + +private: + + ImagePropertiesMetadataTabPriv* d; +}; + +} // NameSpace Digikam + +#endif /* IMAGEPROPERTIESMETADATATAB_H */ diff --git a/src/libs/imageproperties/imagepropertiessidebar.cpp b/src/libs/imageproperties/imagepropertiessidebar.cpp new file mode 100644 index 00000000..67254388 --- /dev/null +++ b/src/libs/imageproperties/imagepropertiessidebar.cpp @@ -0,0 +1,150 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-11-17 + * Description : simple image properties side bar (without support + * of digiKam database). + * + * 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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqrect.h> +#include <tqsplitter.h> + +// KDE includes. + +#include <tdelocale.h> +#include <tdeconfig.h> +#include <tdeapplication.h> +#include <kcursor.h> +#include <tdeglobal.h> +#include <kiconloader.h> + +// Local includes. + +#include "ddebug.h" +#include "dimg.h" +#include "imagepropertiestab.h" +#include "imagepropertiesmetadatatab.h" +#include "imagepropertiescolorstab.h" +#include "imagepropertiessidebar.h" +#include "imagepropertiessidebar.moc" + +namespace Digikam +{ + +ImagePropertiesSideBar::ImagePropertiesSideBar(TQWidget *parent, const char *name, + TQSplitter *splitter, Side side, + bool mimimizedDefault, bool navBar) + : Sidebar(parent, name, side, mimimizedDefault) +{ + m_image = 0; + m_currentRect = TQRect(); + m_dirtyPropertiesTab = false; + m_dirtyMetadataTab = false; + m_dirtyColorTab = false; + + m_propertiesTab = new ImagePropertiesTab(parent, navBar); + m_metadataTab = new ImagePropertiesMetaDataTab(parent, navBar); + m_colorTab = new ImagePropertiesColorsTab(parent, navBar); + + setSplitter(splitter); + + appendTab(m_propertiesTab, SmallIcon("application-vnd.tde.info"), i18n("Properties")); + appendTab(m_metadataTab, SmallIcon("exifinfo"), i18n("Metadata")); + appendTab(m_colorTab, SmallIcon("blend"), i18n("Colors")); + + connect(this, TQ_SIGNAL(signalChangedTab(TQWidget*)), + this, TQ_SLOT(slotChangedTab(TQWidget*))); +} + +ImagePropertiesSideBar::~ImagePropertiesSideBar() +{ +} + +void ImagePropertiesSideBar::itemChanged(const KURL& url, const TQRect &rect, DImg *img) +{ + if (!url.isValid()) + return; + + m_currentURL = url; + m_currentRect = rect; + m_image = img; + m_dirtyPropertiesTab = false; + m_dirtyMetadataTab = false; + m_dirtyColorTab = false; + + slotChangedTab( getActiveTab() ); +} + +void ImagePropertiesSideBar::slotNoCurrentItem(void) +{ + m_currentURL = KURL(); + + m_propertiesTab->setCurrentURL(); + m_propertiesTab->setNavigateBarFileName(); + + m_metadataTab->setCurrentURL(); + m_metadataTab->setNavigateBarFileName(); + + m_colorTab->setData(); + m_colorTab->setNavigateBarFileName(); + + m_dirtyPropertiesTab = false; + m_dirtyMetadataTab = false; + m_dirtyColorTab = false; +} + +void ImagePropertiesSideBar::slotImageSelectionChanged(const TQRect &rect) +{ + m_currentRect = rect; + + if (m_dirtyColorTab) + m_colorTab->setSelection(rect); + else + slotChangedTab(m_colorTab); +} + +void ImagePropertiesSideBar::slotChangedTab(TQWidget* tab) +{ + if (!m_currentURL.isValid()) + return; + + setCursor(KCursor::waitCursor()); + + if (tab == m_propertiesTab && !m_dirtyPropertiesTab) + { + m_propertiesTab->setCurrentURL(m_currentURL); + m_dirtyPropertiesTab = true; + } + else if (tab == m_metadataTab && !m_dirtyMetadataTab) + { + m_metadataTab->setCurrentURL(m_currentURL); + m_dirtyMetadataTab = true; + } + else if (tab == m_colorTab && !m_dirtyColorTab) + { + m_colorTab->setData(m_currentURL, m_currentRect, m_image); + m_dirtyColorTab = true; + } + + unsetCursor(); +} + +} // NameSpace Digikam diff --git a/src/libs/imageproperties/imagepropertiessidebar.h b/src/libs/imageproperties/imagepropertiessidebar.h new file mode 100644 index 00000000..43e08df0 --- /dev/null +++ b/src/libs/imageproperties/imagepropertiessidebar.h @@ -0,0 +1,93 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-11-17 + * Description : simple image properties side bar (without support + * of digiKam database). + * + * 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. + * + * ============================================================ */ + +#ifndef IMAGEPROPERTIESSIDEBAR_H +#define IMAGEPROPERTIESSIDEBAR_H + +// KDE includes. + +#include <kurl.h> + +// Local includes. + +#include "sidebar.h" +#include "digikam_export.h" + +class TQSplitter; +class TQWidget; +class TQRect; + +namespace Digikam +{ + +class DImg; +class ImagePropertiesTab; +class ImagePropertiesMetaDataTab; +class ImagePropertiesColorsTab; + +class DIGIKAM_EXPORT ImagePropertiesSideBar : public Sidebar +{ + TQ_OBJECT + + +public: + + ImagePropertiesSideBar(TQWidget* parent, const char *name, TQSplitter *splitter, + Side side=Left, bool mimimizedDefault=false, bool navBar=false); + + ~ImagePropertiesSideBar(); + + virtual void itemChanged(const KURL& url, const TQRect &rect = TQRect(), DImg *img = 0); + +public slots: + + void slotImageSelectionChanged(const TQRect &rect); + virtual void slotNoCurrentItem(void); + + +protected slots: + + virtual void slotChangedTab(TQWidget* tab); + +protected: + + bool m_dirtyPropertiesTab; + bool m_dirtyMetadataTab; + bool m_dirtyColorTab; + + TQRect m_currentRect; + + KURL m_currentURL; + + DImg *m_image; + + ImagePropertiesTab *m_propertiesTab; + ImagePropertiesMetaDataTab *m_metadataTab; + ImagePropertiesColorsTab *m_colorTab; + +}; + +} // NameSpace Digikam + +#endif // IMAGEPROPERTIESSIDEBAR_H diff --git a/src/libs/imageproperties/imagepropertiessidebarcamgui.cpp b/src/libs/imageproperties/imagepropertiessidebarcamgui.cpp new file mode 100644 index 00000000..942c33e5 --- /dev/null +++ b/src/libs/imageproperties/imagepropertiessidebarcamgui.cpp @@ -0,0 +1,209 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2006-02-08 + * Description : simple image properties side bar used by + * camera gui. + * + * 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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqsplitter.h> + +// KDE includes. + +#include <tdelocale.h> +#include <tdeconfig.h> +#include <tdeapplication.h> +#include <kcursor.h> +#include <tdeglobal.h> +#include <kiconloader.h> + +// Local includes. + +#include "ddebug.h" +#include "dmetadata.h" +#include "gpiteminfo.h" +#include "cameraiconview.h" +#include "cameraiconitem.h" +#include "cameraitempropertiestab.h" +#include "imagepropertiesmetadatatab.h" +#include "statusnavigatebar.h" +#include "navigatebarwidget.h" +#include "imagepropertiessidebarcamgui.h" +#include "imagepropertiessidebarcamgui.moc" + +namespace Digikam +{ + +class ImagePropertiesSideBarCamGuiPriv +{ +public: + + ImagePropertiesSideBarCamGuiPriv() + { + dirtyMetadataTab = false; + dirtyCameraItemTab = false; + metadataTab = 0; + cameraItemTab = 0; + itemInfo = 0; + cameraView = 0; + cameraItem = 0; + exifData = TQByteArray(); + currentURL = KURL(); + } + + bool dirtyMetadataTab; + bool dirtyCameraItemTab; + + TQByteArray exifData; + + KURL currentURL; + + GPItemInfo *itemInfo; + + ImagePropertiesMetaDataTab *metadataTab; + + CameraIconView *cameraView; + + CameraIconViewItem *cameraItem; + + CameraItemPropertiesTab *cameraItemTab; +}; + +ImagePropertiesSideBarCamGui::ImagePropertiesSideBarCamGui(TQWidget *parent, const char *name, + TQSplitter *splitter, Side side, + bool mimimizedDefault) + : Sidebar(parent, name, side, mimimizedDefault) +{ + d = new ImagePropertiesSideBarCamGuiPriv; + d->cameraItemTab = new CameraItemPropertiesTab(parent, true); + d->metadataTab = new ImagePropertiesMetaDataTab(parent, true); + + setSplitter(splitter); + + appendTab(d->cameraItemTab, SmallIcon("application-vnd.tde.info"), i18n("Properties")); + appendTab(d->metadataTab, SmallIcon("exifinfo"), i18n("Metadata")); + + // ---------------------------------------------------------- + + connectNavigateSignals(d->cameraItemTab); + connectNavigateSignals(d->metadataTab); + + connect(this, TQ_SIGNAL(signalChangedTab(TQWidget*)), + this, TQ_SLOT(slotChangedTab(TQWidget*))); +} + +ImagePropertiesSideBarCamGui::~ImagePropertiesSideBarCamGui() +{ + delete d; +} + +void ImagePropertiesSideBarCamGui::connectNavigateSignals(NavigateBarTab *tab) +{ + connect(tab, TQ_SIGNAL(signalFirstItem()), + this, TQ_SIGNAL(signalFirstItem())); + + connect(tab, TQ_SIGNAL(signalPrevItem()), + this, TQ_SIGNAL(signalPrevItem())); + + connect(tab, TQ_SIGNAL(signalNextItem()), + this, TQ_SIGNAL(signalNextItem())); + + connect(tab, TQ_SIGNAL(signalLastItem()), + this, TQ_SIGNAL(signalLastItem())); +} + +void ImagePropertiesSideBarCamGui::itemChanged(GPItemInfo* itemInfo, const KURL& url, + const TQByteArray& exifData, + CameraIconView* view, CameraIconViewItem* item) +{ + if (!itemInfo) + return; + + d->exifData = exifData; + d->itemInfo = itemInfo; + d->currentURL = url; + d->dirtyMetadataTab = false; + d->dirtyCameraItemTab = false; + d->cameraView = view; + d->cameraItem = item; + + if (d->exifData.isEmpty()) + { + DMetadata metaData(d->currentURL.path()); + d->exifData = metaData.getExif(); + } + + slotChangedTab( getActiveTab() ); +} + +void ImagePropertiesSideBarCamGui::slotNoCurrentItem(void) +{ + d->itemInfo = 0; + d->cameraItem = 0; + d->exifData = TQByteArray(); + d->currentURL = KURL(); + d->dirtyMetadataTab = false; + d->dirtyCameraItemTab = false; + + d->cameraItemTab->setCurrentItem(); + d->metadataTab->setCurrentURL(); +} + +void ImagePropertiesSideBarCamGui::slotChangedTab(TQWidget* tab) +{ + if (!d->itemInfo) + return; + + setCursor(KCursor::waitCursor()); + + if (tab == d->cameraItemTab && !d->dirtyCameraItemTab) + { + d->cameraItemTab->setCurrentItem(d->itemInfo, + d->cameraItem->getDownloadName(), d->exifData, + d->currentURL); + + d->dirtyCameraItemTab = true; + } + else if (tab == d->metadataTab && !d->dirtyMetadataTab) + { + d->metadataTab->setCurrentData(d->exifData, TQByteArray(), + d->itemInfo->name); + + d->dirtyMetadataTab = true; + } + + // setting of NavigateBar, common for all tabs + NavigateBarTab *navtab = dynamic_cast<NavigateBarTab *>(tab); + if (navtab) + { + int currentItemType = StatusNavigateBar::ItemCurrent; + if (d->cameraView->firstItem() == d->cameraItem) + currentItemType = StatusNavigateBar::ItemFirst; + else if (d->cameraView->lastItem() == d->cameraItem) + currentItemType = StatusNavigateBar::ItemLast; + + navtab->setNavigateBarState(currentItemType); + navtab->setNavigateBarFileName(); + } + unsetCursor(); +} + +} // NameSpace Digikam diff --git a/src/libs/imageproperties/imagepropertiessidebarcamgui.h b/src/libs/imageproperties/imagepropertiessidebarcamgui.h new file mode 100644 index 00000000..3c2eafd0 --- /dev/null +++ b/src/libs/imageproperties/imagepropertiessidebarcamgui.h @@ -0,0 +1,87 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2006-02-08 + * Description : simple image properties side bar used by + * camera gui. + * + * 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 IMAGEPROPERTIESSIDEBARCAMGUI_H +#define IMAGEPROPERTIESSIDEBARCAMGUI_H + +// KDE includes. + +#include <kurl.h> + +// Local includes. + +#include "sidebar.h" +#include "digikam_export.h" + +class TQSplitter; +class TQWidget; + +namespace Digikam +{ + +class GPItemInfo; +class CameraIconView; +class CameraIconViewItem; +class NavigateBarTab; +class ImagePropertiesSideBarCamGuiPriv; + +class DIGIKAM_EXPORT ImagePropertiesSideBarCamGui : public Sidebar +{ + TQ_OBJECT + + +public: + + ImagePropertiesSideBarCamGui(TQWidget* parent, const char *name, TQSplitter *splitter, + Side side=Left, bool mimimizedDefault=false); + + ~ImagePropertiesSideBarCamGui(); + + void itemChanged(GPItemInfo* itemInfo, const KURL& url, const TQByteArray& exifData=TQByteArray(), + CameraIconView* view=0, CameraIconViewItem* item=0); + +public slots: + + virtual void slotNoCurrentItem(void); + +signals: + + void signalFirstItem(void); + void signalPrevItem(void); + void signalNextItem(void); + void signalLastItem(void); + +private slots: + + virtual void slotChangedTab(TQWidget* tab); + +private: + + ImagePropertiesSideBarCamGuiPriv* d; + void connectNavigateSignals(NavigateBarTab *tab); +}; + +} // NameSpace Digikam + +#endif // IMAGEPROPERTIESSIDEBARCAMGUI_H diff --git a/src/libs/imageproperties/imagepropertiessidebardb.cpp b/src/libs/imageproperties/imagepropertiessidebardb.cpp new file mode 100644 index 00000000..f3dc5f7a --- /dev/null +++ b/src/libs/imageproperties/imagepropertiessidebardb.cpp @@ -0,0 +1,368 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-11-17 + * Description : image properties side bar using data from + * digiKam database. + * + * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2007 by Marcel Wiesweg <marcel dot wiesweg 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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqrect.h> +#include <tqcolor.h> +#include <tqsplitter.h> + +// KDE includes. + +#include <tdelocale.h> +#include <tdeconfig.h> +#include <tdeapplication.h> +#include <kcursor.h> +#include <tdeglobal.h> +#include <kiconloader.h> + +// Local includes. + +#include "ddebug.h" +#include "dimg.h" +#include "imageinfo.h" +#include "imagedescedittab.h" +#include "imageattributeswatch.h" +#include "imagepropertiestab.h" +#include "imagepropertiesmetadatatab.h" +#include "imagepropertiescolorstab.h" +#include "imagepropertiessidebardb.h" +#include "imagepropertiessidebardb.moc" + +namespace Digikam +{ + +class ImagePropertiesSideBarDBPriv +{ +public: + + ImagePropertiesSideBarDBPriv() + { + desceditTab = 0; + dirtyDesceditTab = false; + hasPrevious = false; + hasNext = false; + hasImageInfoOwnership = false; + } + + bool dirtyDesceditTab; + + TQPtrList<ImageInfo> currentInfos; + + ImageDescEditTab *desceditTab; + + bool hasPrevious; + bool hasNext; + + bool hasImageInfoOwnership; +}; + +ImagePropertiesSideBarDB::ImagePropertiesSideBarDB(TQWidget *parent, const char *name, TQSplitter *splitter, + Side side, bool mimimizedDefault) + : ImagePropertiesSideBar(parent, name, splitter, side, mimimizedDefault, false) +{ + // Navigate bar is disabled by passing false to parent class constructor, and tab constructors + + d = new ImagePropertiesSideBarDBPriv; + d->desceditTab = new ImageDescEditTab(parent, false); + + appendTab(d->desceditTab, SmallIcon("imagecomment"), i18n("Captions/Tags")); + + // ---------------------------------------------------------- + + connect(this, TQ_SIGNAL(signalChangedTab(TQWidget*)), + this, TQ_SLOT(slotChangedTab(TQWidget*))); + + connect(d->desceditTab, TQ_SIGNAL(signalProgressBarMode(int, const TQString&)), + this, TQ_SIGNAL(signalProgressBarMode(int, const TQString&))); + + connect(d->desceditTab, TQ_SIGNAL(signalProgressValue(int)), + this, TQ_SIGNAL(signalProgressValue(int))); + + ImageAttributesWatch *watch = ImageAttributesWatch::instance(); + + connect(watch, TQ_SIGNAL(signalFileMetadataChanged(const KURL &)), + this, TQ_SLOT(slotFileMetadataChanged(const KURL &))); +} + +ImagePropertiesSideBarDB::~ImagePropertiesSideBarDB() +{ + delete d; +} + +void ImagePropertiesSideBarDB::itemChanged(ImageInfo *info, + const TQRect &rect, DImg *img) +{ + itemChanged(info->kurl(), info, rect, img); +} + +void ImagePropertiesSideBarDB::itemChanged(const KURL& url, const TQRect &rect, DImg *img) +{ + itemChanged(url, 0, rect, img); +} + +void ImagePropertiesSideBarDB::itemChanged(const KURL& url, ImageInfo *info, + const TQRect &rect, DImg *img) +{ + if ( !url.isValid() ) + return; + + m_currentURL = url; + + TQPtrList<ImageInfo> list; + if (info) + list.append(info); + + itemChanged(list, rect, img); +} + +void ImagePropertiesSideBarDB::itemChanged(TQPtrList<ImageInfo> infos) +{ + if (infos.isEmpty()) + return; + + m_currentURL = infos.first()->kurl(); + + itemChanged(infos, TQRect(), 0); +} + +void ImagePropertiesSideBarDB::itemChanged(TQPtrList<ImageInfo> infos, + const TQRect &rect, DImg *img) +{ + m_currentRect = rect; + m_image = img; + + // The list _may_ have autoDelete set to true. + // Keep old ImageInfo objects from being deleted + // until the tab has had the chance to save changes and clear lists. + TQPtrList<ImageInfo> temporaryList; + if (d->hasImageInfoOwnership) + { + temporaryList = d->currentInfos; + d->hasImageInfoOwnership = false; + } + + d->currentInfos = infos; + + m_dirtyPropertiesTab = false; + m_dirtyMetadataTab = false; + m_dirtyColorTab = false; + d->dirtyDesceditTab = false; + + // All tabs that store the ImageInfo list and access it after selection change + // must release the image info here. slotChangedTab only handles the active tab! + d->desceditTab->setItem(); + + slotChangedTab( getActiveTab() ); + + // now delete old objects, after slotChangedTab + for (ImageInfo *info = temporaryList.first(); info; info = temporaryList.next()) + { + delete info; + } +} + +void ImagePropertiesSideBarDB::takeImageInfoOwnership(bool takeOwnership) +{ + d->hasImageInfoOwnership = takeOwnership; +} + + +void ImagePropertiesSideBarDB::slotNoCurrentItem(void) +{ + ImagePropertiesSideBar::slotNoCurrentItem(); + + // All tabs that store the ImageInfo list and access it after selection change + // must release the image info here. slotChangedTab only handles the active tab! + d->desceditTab->setItem(); + + if (d->hasImageInfoOwnership) + { + for (ImageInfo *info = d->currentInfos.first(); info; info = d->currentInfos.next()) + { + delete info; + } + d->hasImageInfoOwnership = false; + } + d->currentInfos.clear(); + + d->desceditTab->setItem(); + d->dirtyDesceditTab = false; +} + +void ImagePropertiesSideBarDB::populateTags(void) +{ + d->desceditTab->populateTags(); +} + +void ImagePropertiesSideBarDB::slotChangedTab(TQWidget* tab) +{ + setCursor(KCursor::waitCursor()); + + // No database data available, for example in the case of image editor is + // started from camera GUI. + if (d->currentInfos.isEmpty()) + { + if (tab == m_propertiesTab && !m_dirtyPropertiesTab) + { + m_propertiesTab->setCurrentURL(m_currentURL); + m_dirtyPropertiesTab = true; + } + else if (tab == m_metadataTab && !m_dirtyMetadataTab) + { + if (m_image) + m_metadataTab->setCurrentData(m_image->getExif(), m_image->getIptc(), + m_currentURL.fileName()); + else + m_metadataTab->setCurrentURL(m_currentURL); + + m_dirtyMetadataTab = true; + } + else if (tab == m_colorTab && !m_dirtyColorTab) + { + m_colorTab->setData(m_currentURL, m_currentRect, m_image); + m_dirtyColorTab = true; + } + else if (tab == d->desceditTab && !d->dirtyDesceditTab) + { + // Do nothing here. We cannot get data from database ! + d->desceditTab->setItem(); + d->dirtyDesceditTab = true; + } + } + else if (d->currentInfos.count() == 1) // Data from database available... + { + if (tab == m_propertiesTab && !m_dirtyPropertiesTab) + { + m_propertiesTab->setCurrentURL(m_currentURL); + m_dirtyPropertiesTab = true; + } + else if (tab == m_metadataTab && !m_dirtyMetadataTab) + { + if (m_image) + m_metadataTab->setCurrentData(m_image->getExif(), m_image->getIptc(), + m_currentURL.fileName()); + else + m_metadataTab->setCurrentURL(m_currentURL); + + m_dirtyMetadataTab = true; + } + else if (tab == m_colorTab && !m_dirtyColorTab) + { + m_colorTab->setData(m_currentURL, m_currentRect, m_image); + m_dirtyColorTab = true; + } + else if (tab == d->desceditTab && !d->dirtyDesceditTab) + { + d->desceditTab->setItem(d->currentInfos.first()); + d->dirtyDesceditTab = true; + } + } + else // Data from database available, multiple selection + { + if (tab == m_propertiesTab && !m_dirtyPropertiesTab) + { + //TODO + m_propertiesTab->setCurrentURL(m_currentURL); + m_dirtyPropertiesTab = true; + } + else if (tab == m_metadataTab && !m_dirtyMetadataTab) + { + // any ideas? + m_metadataTab->setCurrentURL(); + m_dirtyMetadataTab = true; + } + else if (tab == m_colorTab && !m_dirtyColorTab) + { + // any ideas? + m_colorTab->setData(); + m_dirtyColorTab = true; + } + else if (tab == d->desceditTab && !d->dirtyDesceditTab) + { + d->desceditTab->setItems(d->currentInfos); + d->dirtyDesceditTab = true; + } + } + + unsetCursor(); +} + +void ImagePropertiesSideBarDB::slotFileMetadataChanged(const KURL &url) +{ + if (url == m_currentURL) + { + // trigger an update + m_dirtyMetadataTab = false; + + if (getActiveTab() == m_metadataTab) + { + // update now - reuse code form slotChangedTab + slotChangedTab( getActiveTab() ); + } + } +} + +void ImagePropertiesSideBarDB::slotAssignRating(int rating) +{ + d->desceditTab->assignRating(rating); +} + +void ImagePropertiesSideBarDB::slotAssignRatingNoStar() +{ + d->desceditTab->assignRating(0); +} + +void ImagePropertiesSideBarDB::slotAssignRatingOneStar() +{ + d->desceditTab->assignRating(1); +} + +void ImagePropertiesSideBarDB::slotAssignRatingTwoStar() +{ + d->desceditTab->assignRating(2); +} + +void ImagePropertiesSideBarDB::slotAssignRatingThreeStar() +{ + d->desceditTab->assignRating(3); +} + +void ImagePropertiesSideBarDB::slotAssignRatingFourStar() +{ + d->desceditTab->assignRating(4); +} + +void ImagePropertiesSideBarDB::slotAssignRatingFiveStar() +{ + d->desceditTab->assignRating(5); +} + +void ImagePropertiesSideBarDB::refreshTagsView() +{ + d->desceditTab->refreshTagsView(); +} + +} // NameSpace Digikam diff --git a/src/libs/imageproperties/imagepropertiessidebardb.h b/src/libs/imageproperties/imagepropertiessidebardb.h new file mode 100644 index 00000000..7037b648 --- /dev/null +++ b/src/libs/imageproperties/imagepropertiessidebardb.h @@ -0,0 +1,117 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2004-11-17 + * Description : image properties side bar using data from + * digiKam database. + * + * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2007 by Marcel Wiesweg <marcel dot wiesweg 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 IMAGEPROPERTIESSIDEBARDB_H +#define IMAGEPROPERTIESSIDEBARDB_H + +// TQt includes. + +#include <tqptrlist.h> + +// KDE includes. + +#include <kurl.h> + +// Local includes. + +#include "imagepropertiessidebar.h" +#include "digikam_export.h" + +class TQSplitter; +class TQWidget; +class TQRect; + +namespace Digikam +{ + +class DImg; +class AlbumIconView; +class AlbumIconItem; +class ImageInfo; +class NavigateBarTab; +class ImagePropertiesSideBarDBPriv; + +class DIGIKAM_EXPORT ImagePropertiesSideBarDB : public ImagePropertiesSideBar +{ + TQ_OBJECT + + +public: + + ImagePropertiesSideBarDB(TQWidget* parent, const char *name, TQSplitter *splitter, Side side=Left, + bool mimimizedDefault=false); + + ~ImagePropertiesSideBarDB(); + + virtual void itemChanged(const KURL& url, const TQRect &rect = TQRect(), DImg *img = 0); + + virtual void itemChanged(ImageInfo *info, const TQRect &rect = TQRect(), DImg *img = 0); + virtual void itemChanged(TQPtrList<ImageInfo> infos); + + void takeImageInfoOwnership(bool takeOwnership); + + void populateTags(void); + void refreshTagsView(); + +signals: + + void signalFirstItem(void); + void signalPrevItem(void); + void signalNextItem(void); + void signalLastItem(void); + void signalProgressBarMode(int, const TQString&); + void signalProgressValue(int); + +public slots: + + void slotAssignRating(int rating); + void slotAssignRatingNoStar(); + void slotAssignRatingOneStar(); + void slotAssignRatingTwoStar(); + void slotAssignRatingThreeStar(); + void slotAssignRatingFourStar(); + void slotAssignRatingFiveStar(); + + virtual void slotNoCurrentItem(void); + +private slots: + + void slotChangedTab(TQWidget* tab); + void slotFileMetadataChanged(const KURL &url); + +private: + + void itemChanged(const KURL& url, ImageInfo *info, + const TQRect &rect, DImg *img); + void itemChanged(TQPtrList<ImageInfo> infos, const TQRect &rect, DImg *img); + +private: + + ImagePropertiesSideBarDBPriv* d; +}; + +} // NameSpace Digikam + +#endif // IMAGEPROPERTIESSIDEBARDB_H diff --git a/src/libs/imageproperties/imagepropertiestab.cpp b/src/libs/imageproperties/imagepropertiestab.cpp new file mode 100644 index 00000000..7141c039 --- /dev/null +++ b/src/libs/imageproperties/imagepropertiestab.cpp @@ -0,0 +1,601 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2006-04-19 + * Description : A tab to display general image information + * + * 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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqlayout.h> +#include <tqstyle.h> +#include <tqfile.h> +#include <tqlabel.h> +#include <tqpixmap.h> +#include <tqfileinfo.h> +#include <tqwhatsthis.h> +#include <tqframe.h> +#include <tqscrollview.h> + +// KDE includes. + +#include <tdelocale.h> +#include <kdialogbase.h> +#include <tdefileitem.h> +#include <ksqueezedtextlabel.h> +#include <kseparator.h> + +// LibKDcraw includes. + +#include <libkdcraw/version.h> +#include <libkdcraw/kdcraw.h> + +#if KDCRAW_VERSION < 0x000106 +#include <libkdcraw/dcrawbinary.h> +#endif + +// Local includes. + +#include "ddebug.h" +#include "dmetadata.h" +#include "navigatebarwidget.h" +#include "imagepropertiestab.h" +#include "imagepropertiestab.moc" + +namespace Digikam +{ + +class ImagePropertiesTabPriv +{ +public: + + ImagePropertiesTabPriv() + { + settingsArea = 0; + title = 0; + file = 0; + folder = 0; + modifiedDate = 0; + size = 0; + owner = 0; + permissions = 0; + title2 = 0; + mime = 0; + dimensions = 0; + compression = 0; + bitDepth = 0; + colorMode = 0; + title3 = 0; + make = 0; + model = 0; + photoDate = 0; + aperture = 0; + focalLength = 0; + exposureTime = 0; + sensitivity = 0; + exposureMode = 0; + flash = 0; + whiteBalance = 0; + labelFile = 0; + labelFolder = 0; + labelFileModifiedDate = 0; + labelFileSize = 0; + labelFileOwner = 0; + labelFilePermissions = 0; + labelImageMime = 0; + labelImageDimensions = 0; + labelImageCompression = 0; + labelImageBitDepth = 0; + labelImageColorMode = 0; + labelPhotoMake = 0; + labelPhotoModel = 0; + labelPhotoDateTime = 0; + labelPhotoAperture = 0; + labelPhotoFocalLength = 0; + labelPhotoExposureTime = 0; + labelPhotoSensitivity = 0; + labelPhotoExposureMode = 0; + labelPhotoFlash = 0; + labelPhotoWhiteBalance = 0; + } + + TQLabel *title; + TQLabel *file; + TQLabel *folder; + TQLabel *modifiedDate; + TQLabel *size; + TQLabel *owner; + TQLabel *permissions; + + TQLabel *title2; + TQLabel *mime; + TQLabel *dimensions; + TQLabel *compression; + TQLabel *bitDepth; + TQLabel *colorMode; + + TQLabel *title3; + TQLabel *make; + TQLabel *model; + TQLabel *photoDate; + TQLabel *aperture; + TQLabel *focalLength; + TQLabel *exposureTime; + TQLabel *sensitivity; + TQLabel *exposureMode; + TQLabel *flash; + TQLabel *whiteBalance; + + TQFrame *settingsArea; + + KSqueezedTextLabel *labelFile; + KSqueezedTextLabel *labelFolder; + KSqueezedTextLabel *labelFileModifiedDate; + KSqueezedTextLabel *labelFileSize; + KSqueezedTextLabel *labelFileOwner; + KSqueezedTextLabel *labelFilePermissions; + + KSqueezedTextLabel *labelImageMime; + KSqueezedTextLabel *labelImageDimensions; + KSqueezedTextLabel *labelImageCompression; + KSqueezedTextLabel *labelImageBitDepth; + KSqueezedTextLabel *labelImageColorMode; + + KSqueezedTextLabel *labelPhotoMake; + KSqueezedTextLabel *labelPhotoModel; + KSqueezedTextLabel *labelPhotoDateTime; + KSqueezedTextLabel *labelPhotoAperture; + KSqueezedTextLabel *labelPhotoFocalLength; + KSqueezedTextLabel *labelPhotoExposureTime; + KSqueezedTextLabel *labelPhotoSensitivity; + KSqueezedTextLabel *labelPhotoExposureMode; + KSqueezedTextLabel *labelPhotoFlash; + KSqueezedTextLabel *labelPhotoWhiteBalance; +}; + +ImagePropertiesTab::ImagePropertiesTab(TQWidget* parent, bool navBar) + : NavigateBarTab(parent) +{ + d = new ImagePropertiesTabPriv; + + setupNavigateBar(navBar); + + TQScrollView *sv = new TQScrollView(this); + sv->viewport()->setBackgroundMode(TQt::PaletteBackground); + sv->setResizePolicy(TQScrollView::AutoOneFit); + sv->setFrameStyle(TQFrame::NoFrame); + + d->settingsArea = new TQFrame(sv->viewport()); + d->settingsArea->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken ); + d->settingsArea->setLineWidth( style().pixelMetric(TQStyle::PM_DefaultFrameWidth, this) ); + + sv->addChild(d->settingsArea); + m_navigateBarLayout->addWidget(sv); + + // -------------------------------------------------- + + TQGridLayout *settingsLayout = new TQGridLayout(d->settingsArea, 33, 1, KDialog::spacingHint(), 0); + + // -------------------------------------------------- + + d->title = new TQLabel(i18n("<big><b>File Properties</b></big>"), d->settingsArea); + d->file = new TQLabel(i18n("<b>File</b>:"), d->settingsArea); + d->folder = new TQLabel(i18n("<b>Folder</b>:"), d->settingsArea); + d->modifiedDate = new TQLabel(i18n("<b>Modified</b>:"), d->settingsArea); + d->size = new TQLabel(i18n("<b>Size</b>:"), d->settingsArea); + d->owner = new TQLabel(i18n("<b>Owner</b>:"), d->settingsArea); + d->permissions = new TQLabel(i18n("<b>Permissions</b>:"), d->settingsArea); + + KSeparator *line = new KSeparator(TQt::Horizontal, d->settingsArea); + d->title2 = new TQLabel(i18n("<big><b>Image Properties</b></big>"), d->settingsArea); + d->mime = new TQLabel(i18n("<b>Type</b>:"), d->settingsArea); + d->dimensions = new TQLabel(i18n("<b>Dimensions</b>:"), d->settingsArea); + d->compression = new TQLabel(i18n("<b>Compression</b>:"), d->settingsArea); + d->bitDepth = new TQLabel(i18n("<nobr><b>Bit depth</b></nobr>:"), d->settingsArea); + d->colorMode = new TQLabel(i18n("<nobr><b>Color mode</b></nobr>:"), d->settingsArea); + + KSeparator *line2 = new KSeparator(TQt::Horizontal, d->settingsArea); + d->title3 = new TQLabel(i18n("<big><b>Photograph Properties</b></big>"), d->settingsArea); + d->make = new TQLabel(i18n("<b>Make</b>:"), d->settingsArea); + d->model = new TQLabel(i18n("<b>Model</b>:"), d->settingsArea); + d->photoDate = new TQLabel(i18n("<b>Created</b>:"), d->settingsArea); + d->aperture = new TQLabel(i18n("<b>Aperture</b>:"), d->settingsArea); + d->focalLength = new TQLabel(i18n("<b>Focal</b>:"), d->settingsArea); + d->exposureTime = new TQLabel(i18n("<b>Exposure</b>:"), d->settingsArea); + d->sensitivity = new TQLabel(i18n("<b>Sensitivity</b>:"), d->settingsArea); + d->exposureMode = new TQLabel(i18n("<nobr><b>Mode/Program</b></nobr>:"), d->settingsArea); + d->flash = new TQLabel(i18n("<b>Flash</b>:"), d->settingsArea); + d->whiteBalance = new TQLabel(i18n("<nobr><b>White balance</b></nobr>:"), d->settingsArea); + + d->labelFile = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFolder = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFileModifiedDate = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFileSize = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFileOwner = new KSqueezedTextLabel(0, d->settingsArea); + d->labelFilePermissions = new KSqueezedTextLabel(0, d->settingsArea); + + d->labelImageMime = new KSqueezedTextLabel(0, d->settingsArea); + d->labelImageDimensions = new KSqueezedTextLabel(0, d->settingsArea); + d->labelImageCompression = new KSqueezedTextLabel(0, d->settingsArea); + d->labelImageBitDepth = new KSqueezedTextLabel(0, d->settingsArea); + d->labelImageColorMode = new KSqueezedTextLabel(0, d->settingsArea); + + d->labelPhotoMake = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoModel = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoDateTime = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoAperture = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoFocalLength = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoExposureTime = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoSensitivity = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoExposureMode = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoFlash = new KSqueezedTextLabel(0, d->settingsArea); + d->labelPhotoWhiteBalance = new KSqueezedTextLabel(0, d->settingsArea); + + int hgt = fontMetrics().height()-2; + d->title->setAlignment(TQt::AlignCenter); + d->file->setMaximumHeight(hgt); + d->folder->setMaximumHeight(hgt); + d->modifiedDate->setMaximumHeight(hgt); + d->size->setMaximumHeight(hgt); + d->owner->setMaximumHeight(hgt); + d->permissions->setMaximumHeight(hgt); + d->labelFile->setMaximumHeight(hgt); + d->labelFolder->setMaximumHeight(hgt); + d->labelFileModifiedDate->setMaximumHeight(hgt); + d->labelFileSize->setMaximumHeight(hgt); + d->labelFileOwner->setMaximumHeight(hgt); + d->labelFilePermissions->setMaximumHeight(hgt); + + d->title2->setAlignment(TQt::AlignCenter); + d->mime->setMaximumHeight(hgt); + d->dimensions->setMaximumHeight(hgt); + d->compression->setMaximumHeight(hgt); + d->bitDepth->setMaximumHeight(hgt); + d->colorMode->setMaximumHeight(hgt); + d->labelImageMime->setMaximumHeight(hgt); + d->labelImageDimensions->setMaximumHeight(hgt); + d->labelImageCompression->setMaximumHeight(hgt); + d->labelImageBitDepth->setMaximumHeight(hgt); + d->labelImageColorMode->setMaximumHeight(hgt); + + d->title3->setAlignment(TQt::AlignCenter); + d->make->setMaximumHeight(hgt); + d->model->setMaximumHeight(hgt); + d->photoDate->setMaximumHeight(hgt); + d->aperture->setMaximumHeight(hgt); + d->focalLength->setMaximumHeight(hgt); + d->exposureTime->setMaximumHeight(hgt); + d->sensitivity->setMaximumHeight(hgt); + d->exposureMode->setMaximumHeight(hgt); + d->flash->setMaximumHeight(hgt); + d->whiteBalance->setMaximumHeight(hgt); + d->labelPhotoMake->setMaximumHeight(hgt); + d->labelPhotoModel->setMaximumHeight(hgt); + d->labelPhotoDateTime->setMaximumHeight(hgt); + d->labelPhotoAperture->setMaximumHeight(hgt); + d->labelPhotoFocalLength->setMaximumHeight(hgt); + d->labelPhotoExposureTime->setMaximumHeight(hgt); + d->labelPhotoSensitivity->setMaximumHeight(hgt); + d->labelPhotoExposureMode->setMaximumHeight(hgt); + d->labelPhotoFlash->setMaximumHeight(hgt); + d->labelPhotoWhiteBalance->setMaximumHeight(hgt); + + // -------------------------------------------------- + + settingsLayout->addMultiCellWidget(d->title, 0, 0, 0, 1); + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 1, 1, 0, 1); + settingsLayout->addMultiCellWidget(d->file, 2, 2, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFile, 2, 2, 1, 1); + settingsLayout->addMultiCellWidget(d->folder, 3, 3, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFolder, 3, 3, 1, 1); + settingsLayout->addMultiCellWidget(d->modifiedDate, 4, 4, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFileModifiedDate, 4, 4, 1, 1); + settingsLayout->addMultiCellWidget(d->size, 5, 5, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFileSize, 5, 5, 1, 1); + settingsLayout->addMultiCellWidget(d->owner, 6, 6, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFileOwner, 6, 6, 1, 1); + settingsLayout->addMultiCellWidget(d->permissions, 7, 7, 0, 0); + settingsLayout->addMultiCellWidget(d->labelFilePermissions, 7, 7, 1, 1); + + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 8, 8, 0, 1); + settingsLayout->addMultiCellWidget(line, 9, 9, 0, 1); + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 10, 10, 0, 1); + + settingsLayout->addMultiCellWidget(d->title2, 11, 11, 0, 1); + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 12, 12, 0, 1); + settingsLayout->addMultiCellWidget(d->mime, 13, 13, 0, 0); + settingsLayout->addMultiCellWidget(d->labelImageMime, 13, 13, 1, 1); + settingsLayout->addMultiCellWidget(d->dimensions, 14, 14, 0, 0); + settingsLayout->addMultiCellWidget(d->labelImageDimensions, 14, 14, 1, 1); + settingsLayout->addMultiCellWidget(d->compression, 15, 15, 0, 0); + settingsLayout->addMultiCellWidget(d->labelImageCompression, 15, 15, 1, 1); + settingsLayout->addMultiCellWidget(d->bitDepth, 16, 16, 0, 0); + settingsLayout->addMultiCellWidget(d->labelImageBitDepth, 16, 16, 1, 1); + settingsLayout->addMultiCellWidget(d->colorMode, 17, 17, 0, 0); + settingsLayout->addMultiCellWidget(d->labelImageColorMode, 17, 17, 1, 1); + + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 18, 18, 0, 1); + settingsLayout->addMultiCellWidget(line2, 19, 19, 0, 1); + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 20, 20, 0, 1); + + settingsLayout->addMultiCellWidget(d->title3, 21, 21, 0, 1); + settingsLayout->addMultiCell(new TQSpacerItem(KDialog::spacingHint(), KDialog::spacingHint(), + TQSizePolicy::Minimum, TQSizePolicy::MinimumExpanding), 22, 22, 0, 1); + settingsLayout->addMultiCellWidget(d->make, 23, 23, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoMake, 23, 23, 1, 1); + settingsLayout->addMultiCellWidget(d->model, 24, 24, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoModel, 24, 24, 1, 1); + settingsLayout->addMultiCellWidget(d->photoDate, 25, 25, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoDateTime, 25, 25, 1, 1); + settingsLayout->addMultiCellWidget(d->aperture, 26, 26, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoAperture, 26, 26, 1, 1); + settingsLayout->addMultiCellWidget(d->focalLength, 27, 27, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoFocalLength, 27, 27, 1, 1); + settingsLayout->addMultiCellWidget(d->exposureTime, 28, 28, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoExposureTime, 28, 28, 1, 1); + settingsLayout->addMultiCellWidget(d->sensitivity, 29, 29, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoSensitivity, 29, 29, 1, 1); + settingsLayout->addMultiCellWidget(d->exposureMode, 30, 30, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoExposureMode, 30, 30, 1, 1); + settingsLayout->addMultiCellWidget(d->flash, 31, 31, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoFlash, 31, 31, 1, 1); + settingsLayout->addMultiCellWidget(d->whiteBalance, 32, 32, 0, 0); + settingsLayout->addMultiCellWidget(d->labelPhotoWhiteBalance, 32, 32, 1, 1); + + settingsLayout->setRowStretch(33, 10); + settingsLayout->setColStretch(1, 10); +} + +ImagePropertiesTab::~ImagePropertiesTab() +{ + delete d; +} + +void ImagePropertiesTab::setCurrentURL(const KURL& url) +{ + if (url.isEmpty()) + { + setNavigateBarFileName(); + + d->labelFile->setText(TQString()); + d->labelFolder->setText(TQString()); + d->labelFileModifiedDate->setText(TQString()); + d->labelFileSize->setText(TQString()); + d->labelFileOwner->setText(TQString()); + d->labelFilePermissions->setText(TQString()); + + d->labelImageMime->setText(TQString()); + d->labelImageDimensions->setText(TQString()); + d->labelImageCompression->setText(TQString()); + d->labelImageBitDepth->setText(TQString()); + d->labelImageColorMode->setText(TQString()); + + d->labelPhotoMake->setText(TQString()); + d->labelPhotoModel->setText(TQString()); + d->labelPhotoDateTime->setText(TQString()); + d->labelPhotoAperture->setText(TQString()); + d->labelPhotoFocalLength->setText(TQString()); + d->labelPhotoExposureTime->setText(TQString()); + d->labelPhotoSensitivity->setText(TQString()); + d->labelPhotoExposureMode->setText(TQString()); + d->labelPhotoFlash->setText(TQString()); + d->labelPhotoWhiteBalance->setText(TQString()); + + setEnabled(false); + return; + } + + setEnabled(true); + + TQString str; + TQString unavailable(i18n("<i>unavailable</i>")); + + KFileItem fi(KFileItem::Unknown, KFileItem::Unknown, url); + TQFileInfo fileInfo(url.path()); + DMetadata metaData(url.path()); + + // -- File system information ------------------------------------------ + + d->labelFile->setText(url.fileName()); + d->labelFolder->setText(url.directory()); + + TQDateTime modifiedDate = fileInfo.lastModified(); + str = TDEGlobal::locale()->formatDateTime(modifiedDate, true, true); + d->labelFileModifiedDate->setText(str); + + str = TQString("%1 (%2)").arg(TDEIO::convertSize(fi.size())) + .arg(TDEGlobal::locale()->formatNumber(fi.size(), 0)); + d->labelFileSize->setText(str); + + d->labelFileOwner->setText( TQString("%1 - %2").arg(fi.user()).arg(fi.group()) ); + d->labelFilePermissions->setText( fi.permissionsString() ); + + // -- Image Properties -------------------------------------------------- + + TQSize dims; + TQString compression, bitDepth, colorMode; +#if KDCRAW_VERSION < 0x000106 + TQString rawFilesExt(KDcrawIface::DcrawBinary::instance()->rawFiles()); +#else + TQString rawFilesExt(KDcrawIface::KDcraw::rawFiles()); +#endif + TQString ext = fileInfo.extension(false).upper(); + + if (!ext.isEmpty() && rawFilesExt.upper().contains(ext)) + { + d->labelImageMime->setText(i18n("RAW Image")); + compression = i18n("None"); + bitDepth = "48"; + dims = metaData.getImageDimensions(); + colorMode = i18n("Uncalibrated"); + } + else + { + d->labelImageMime->setText(fi.mimeComment()); + + KFileMetaInfo meta = fi.metaInfo(); + if (meta.isValid()) + { + if (meta.containsGroup("Jpeg EXIF Data")) // JPEG image ? + { + dims = meta.group("Jpeg EXIF Data").item("Dimensions").value().toSize(); + + TQString quality = meta.group("Jpeg EXIF Data").item("JPEG quality").value().toString(); + quality.isEmpty() ? compression = unavailable : + compression = i18n("JPEG quality %1").arg(quality); + bitDepth = meta.group("Jpeg EXIF Data").item("BitDepth").value().toString(); + colorMode = meta.group("Jpeg EXIF Data").item("ColorMode").value().toString(); + } + + if (meta.containsGroup("General")) + { + if (dims.isEmpty() ) + dims = meta.group("General").item("Dimensions").value().toSize(); + if (compression.isEmpty()) + compression = meta.group("General").item("Compression").value().toString(); + if (bitDepth.isEmpty()) + bitDepth = meta.group("General").item("BitDepth").value().toString(); + if (colorMode.isEmpty()) + colorMode = meta.group("General").item("ColorMode").value().toString(); + } + + if (meta.containsGroup("Technical")) + { + if (dims.isEmpty()) + dims = meta.group("Technical").item("Dimensions").value().toSize(); + if (compression.isEmpty()) + compression = meta.group("Technical").item("Compression").value().toString(); + if (bitDepth.isEmpty()) + bitDepth = meta.group("Technical").item("BitDepth").value().toString(); + if (colorMode.isEmpty()) + colorMode = meta.group("Technical").item("ColorMode").value().toString(); + } + } + } + + TQString mpixels; + mpixels.setNum(dims.width()*dims.height()/1000000.0, 'f', 2); + str = (!dims.isValid()) ? i18n("Unknown") : i18n("%1x%2 (%3Mpx)") + .arg(dims.width()).arg(dims.height()).arg(mpixels); + d->labelImageDimensions->setText(str); + d->labelImageCompression->setText(compression.isEmpty() ? unavailable : compression); + d->labelImageBitDepth->setText(bitDepth.isEmpty() ? unavailable : i18n("%1 bpp").arg(bitDepth)); + d->labelImageColorMode->setText(colorMode.isEmpty() ? unavailable : colorMode); + + // -- Photograph information ------------------------------------------ + // NOTA: If something is changed here, please updated albumfiletip section too. + + PhotoInfoContainer photoInfo = metaData.getPhotographInformations(); + + if (photoInfo.isEmpty()) + { + d->title3->hide(); + d->make->hide(); + d->model->hide(); + d->photoDate->hide(); + d->aperture->hide(); + d->focalLength->hide(); + d->exposureTime->hide(); + d->sensitivity->hide(); + d->exposureMode->hide(); + d->flash->hide(); + d->whiteBalance->hide(); + d->labelPhotoMake->hide(); + d->labelPhotoModel->hide(); + d->labelPhotoDateTime->hide(); + d->labelPhotoAperture->hide(); + d->labelPhotoFocalLength->hide(); + d->labelPhotoExposureTime->hide(); + d->labelPhotoSensitivity->hide(); + d->labelPhotoExposureMode->hide(); + d->labelPhotoFlash->hide(); + d->labelPhotoWhiteBalance->hide(); + } + else + { + d->title3->show(); + d->make->show(); + d->model->show(); + d->photoDate->show(); + d->aperture->show(); + d->focalLength->show(); + d->exposureTime->show(); + d->sensitivity->show(); + d->exposureMode->show(); + d->flash->show(); + d->whiteBalance->show(); + d->labelPhotoMake->show(); + d->labelPhotoModel->show(); + d->labelPhotoDateTime->show(); + d->labelPhotoAperture->show(); + d->labelPhotoFocalLength->show(); + d->labelPhotoExposureTime->show(); + d->labelPhotoSensitivity->show(); + d->labelPhotoExposureMode->show(); + d->labelPhotoFlash->show(); + d->labelPhotoWhiteBalance->show(); + } + + d->labelPhotoMake->setText(photoInfo.make.isEmpty() ? unavailable : photoInfo.make); + d->labelPhotoModel->setText(photoInfo.model.isEmpty() ? unavailable : photoInfo.model); + + if (photoInfo.dateTime.isValid()) + { + str = TDEGlobal::locale()->formatDateTime(photoInfo.dateTime, true, true); + d->labelPhotoDateTime->setText(str); + } + else + d->labelPhotoDateTime->setText(unavailable); + + d->labelPhotoAperture->setText(photoInfo.aperture.isEmpty() ? unavailable : photoInfo.aperture); + + if (photoInfo.focalLength35mm.isEmpty()) + d->labelPhotoFocalLength->setText(photoInfo.focalLength.isEmpty() ? unavailable : photoInfo.focalLength); + else + { + str = i18n("%1 (35mm: %2)").arg(photoInfo.focalLength).arg(photoInfo.focalLength35mm); + d->labelPhotoFocalLength->setText(str); + } + + d->labelPhotoExposureTime->setText(photoInfo.exposureTime.isEmpty() ? unavailable : photoInfo.exposureTime); + d->labelPhotoSensitivity->setText(photoInfo.sensitivity.isEmpty() ? unavailable : i18n("%1 ISO").arg(photoInfo.sensitivity)); + + if (photoInfo.exposureMode.isEmpty() && photoInfo.exposureProgram.isEmpty()) + d->labelPhotoExposureMode->setText(unavailable); + else if (!photoInfo.exposureMode.isEmpty() && photoInfo.exposureProgram.isEmpty()) + d->labelPhotoExposureMode->setText(photoInfo.exposureMode); + else if (photoInfo.exposureMode.isEmpty() && !photoInfo.exposureProgram.isEmpty()) + d->labelPhotoExposureMode->setText(photoInfo.exposureProgram); + else + { + str = TQString("%1 / %2").arg(photoInfo.exposureMode).arg(photoInfo.exposureProgram); + d->labelPhotoExposureMode->setText(str); + } + + d->labelPhotoFlash->setText(photoInfo.flash.isEmpty() ? unavailable : photoInfo.flash); + d->labelPhotoWhiteBalance->setText(photoInfo.whiteBalance.isEmpty() ? unavailable : photoInfo.whiteBalance); +} + +} // NameSpace Digikam diff --git a/src/libs/imageproperties/imagepropertiestab.h b/src/libs/imageproperties/imagepropertiestab.h new file mode 100644 index 00000000..2a69ce97 --- /dev/null +++ b/src/libs/imageproperties/imagepropertiestab.h @@ -0,0 +1,66 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2006-04-19 + * Description : A tab to display general image information + * + * 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 IMAGEPROPERTIESTAB_H +#define IMAGEPROPERTIESTAB_H + +// TQt includes. + +#include <tqwidget.h> +#include <tqstring.h> +#include <tqcolor.h> + +// KDE includes. + +#include <kurl.h> + +// Local includes. + +#include "digikam_export.h" +#include "navigatebartab.h" + +namespace Digikam +{ + +class ImagePropertiesTabPriv; + +class DIGIKAM_EXPORT ImagePropertiesTab : public NavigateBarTab +{ + TQ_OBJECT + + +public: + + ImagePropertiesTab(TQWidget* parent, bool navBar=true); + ~ImagePropertiesTab(); + + void setCurrentURL(const KURL& url=KURL()); + +private: + + ImagePropertiesTabPriv* d; +}; + +} // NameSpace Digikam + +#endif /* IMAGEPROPERTIESTAB_H */ diff --git a/src/libs/imageproperties/navigatebartab.cpp b/src/libs/imageproperties/navigatebartab.cpp new file mode 100644 index 00000000..d40ae134 --- /dev/null +++ b/src/libs/imageproperties/navigatebartab.cpp @@ -0,0 +1,146 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2007-01-04 + * Description : A parent tab class with a navigation bar + * + * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2007 by Marcel Wiesweg <marcel dot wiesweg 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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqlayout.h> +#include <tqwidgetstack.h> +#include <tqlabel.h> + +// Local includes. + +#include "statusnavigatebar.h" +#include "navigatebarwidget.h" +#include "navigatebartab.h" +#include "navigatebartab.moc" + +namespace Digikam +{ + +class NavigateBarTabPriv +{ +public: + + NavigateBarTabPriv() + { + stack = 0; + navigateBar = 0; + label = 0; + } + + TQWidgetStack *stack; + + TQLabel *label; + + NavigateBarWidget *navigateBar; +}; + +NavigateBarTab::NavigateBarTab(TQWidget* parent) + : TQWidget(parent, 0, TQt::WDestructiveClose) +{ + d = new NavigateBarTabPriv; + m_navigateBarLayout = 0; +} + +NavigateBarTab::~NavigateBarTab() +{ + delete d; +} + +void NavigateBarTab::setupNavigateBar(bool withBar) +{ + m_navigateBarLayout = new TQVBoxLayout(this); + + if (withBar) + { + d->stack = new TQWidgetStack(this); + m_navigateBarLayout->addWidget(d->stack); + + d->navigateBar = new NavigateBarWidget(d->stack, withBar); + d->stack->addWidget(d->navigateBar); + + connect(d->navigateBar, TQ_SIGNAL(signalFirstItem()), + this, TQ_SIGNAL(signalFirstItem())); + + connect(d->navigateBar, TQ_SIGNAL(signalPrevItem()), + this, TQ_SIGNAL(signalPrevItem())); + + connect(d->navigateBar, TQ_SIGNAL(signalNextItem()), + this, TQ_SIGNAL(signalNextItem())); + + connect(d->navigateBar, TQ_SIGNAL(signalLastItem()), + this, TQ_SIGNAL(signalLastItem())); + + d->label = new TQLabel(d->stack); + d->label->setAlignment(TQt::AlignCenter); + d->stack->addWidget(d->label); + } +} + +void NavigateBarTab::setNavigateBarState(bool hasPrevious, bool hasNext) +{ + if (!d->navigateBar) + return; + + d->stack->raiseWidget(d->navigateBar); + + if (hasPrevious && hasNext) + d->navigateBar->setButtonsState(StatusNavigateBar::ItemCurrent); + else if (!hasPrevious && hasNext) + d->navigateBar->setButtonsState(StatusNavigateBar::ItemFirst); + else if (hasPrevious && !hasNext) + d->navigateBar->setButtonsState(StatusNavigateBar::ItemLast); + else + d->navigateBar->setButtonsState(StatusNavigateBar::NoNavigation); +} + +void NavigateBarTab::setNavigateBarState(int itemType) +{ + if (!d->navigateBar) + return; + + d->stack->raiseWidget(d->navigateBar); + d->navigateBar->setButtonsState(itemType); +} + +void NavigateBarTab::setNavigateBarFileName(const TQString &name) +{ + if (!d->navigateBar) + return; + + d->stack->raiseWidget(d->navigateBar); + d->navigateBar->setFileName(name); +} + +void NavigateBarTab::setLabelText(const TQString &text) +{ + if (!d->label) + return; + + d->stack->raiseWidget(d->label); + d->label->setText(text); +} + +} // NameSpace Digikam + diff --git a/src/libs/imageproperties/navigatebartab.h b/src/libs/imageproperties/navigatebartab.h new file mode 100644 index 00000000..a93090e0 --- /dev/null +++ b/src/libs/imageproperties/navigatebartab.h @@ -0,0 +1,85 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2007-01-04 + * Description : A parent tab class with a navigation bar + * + * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2007 by Marcel Wiesweg <marcel dot wiesweg 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 NAVIGATEBARTAB_H +#define NAVIGATEBARTAB_H + +// TQt includes. + +#include <tqwidget.h> +#include <tqstring.h> + +// KDE includes. + +#include <kurl.h> + +// Local includes. + +#include "digikam_export.h" +#include "imagepropertiessidebar.h" + +class TQVBoxLayout; + +namespace Digikam +{ + +class NavigateBarWidget; +class NavigateBarTabPriv; + +class DIGIKAM_EXPORT NavigateBarTab : public TQWidget +{ + TQ_OBJECT + + +public: + + NavigateBarTab(TQWidget* parent); + ~NavigateBarTab(); + + void setNavigateBarState(bool hasPrevious, bool hasNext); + void setNavigateBarState(int itemType); + void setNavigateBarFileName(const TQString &name = TQString()); + void setLabelText(const TQString &text); + +signals: + + void signalFirstItem(void); + void signalPrevItem(void); + void signalNextItem(void); + void signalLastItem(void); + +protected: + + void setupNavigateBar(bool withBar); + +protected: + + TQVBoxLayout *m_navigateBarLayout; + NavigateBarTabPriv *d; + +}; + +} // NameSpace Digikam + +#endif /* NAVIGATEBARTAB_H */ diff --git a/src/libs/imageproperties/navigatebarwidget.cpp b/src/libs/imageproperties/navigatebarwidget.cpp new file mode 100644 index 00000000..9232c55e --- /dev/null +++ b/src/libs/imageproperties/navigatebarwidget.cpp @@ -0,0 +1,112 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2005-07-07 + * Description : a navigate bar with text + * + * Copyright (C) 2005-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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqlayout.h> + +// KDE includes. + +#include <ksqueezedtextlabel.h> +#include <kdialogbase.h> +#include <tdelocale.h> + +// Local includes. + +#include "statusnavigatebar.h" +#include "navigatebarwidget.h" +#include "navigatebarwidget.moc" + +namespace Digikam +{ + +class NavigateBarWidgetPriv +{ +public: + + NavigateBarWidgetPriv() + { + filename = 0; + navBar = 0; + } + + KSqueezedTextLabel *filename; + + StatusNavigateBar *navBar; +}; + +NavigateBarWidget::NavigateBarWidget(TQWidget *parent, bool show) + : TQWidget(parent, 0, TQt::WDestructiveClose) +{ + d = new NavigateBarWidgetPriv; + + TQHBoxLayout *lay = new TQHBoxLayout(this); + d->navBar = new StatusNavigateBar(this); + d->filename = new KSqueezedTextLabel(this); + + lay->addWidget(d->navBar); + lay->addSpacing( KDialog::spacingHint() ); + lay->addWidget(d->filename); + + if (!show) hide(); + + connect(d->navBar, TQ_SIGNAL(signalFirstItem()), + this, TQ_SIGNAL(signalFirstItem())); + + connect(d->navBar, TQ_SIGNAL(signalPrevItem()), + this, TQ_SIGNAL(signalPrevItem())); + + connect(d->navBar, TQ_SIGNAL(signalNextItem()), + this, TQ_SIGNAL(signalNextItem())); + + connect(d->navBar, TQ_SIGNAL(signalLastItem()), + this, TQ_SIGNAL(signalLastItem())); +} + +NavigateBarWidget::~NavigateBarWidget() +{ + delete d; +} + +void NavigateBarWidget::setFileName(TQString filename) +{ + d->filename->setText(filename); +} + +TQString NavigateBarWidget::getFileName() +{ + return (d->filename->text()); +} + +void NavigateBarWidget::setButtonsState(int itemType) +{ + d->navBar->setButtonsState(itemType); +} + +int NavigateBarWidget::getButtonsState() +{ + return (d->navBar->getButtonsState()); +} + +} // namespace Digikam + diff --git a/src/libs/imageproperties/navigatebarwidget.h b/src/libs/imageproperties/navigatebarwidget.h new file mode 100644 index 00000000..7be088ed --- /dev/null +++ b/src/libs/imageproperties/navigatebarwidget.h @@ -0,0 +1,70 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2005-07-07 + * Description : a navigate bar with text + * + * Copyright (C) 2005-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 NAVIGATEBARWIDGET_H +#define NAVIGATEBARWIDGET_H + +// TQt includes. + +#include <tqwidget.h> +#include <tqstring.h> + +// Local includes. + +#include "digikam_export.h" + +namespace Digikam +{ + +class NavigateBarWidgetPriv; + +class DIGIKAM_EXPORT NavigateBarWidget : public TQWidget +{ +TQ_OBJECT + + +public: + + NavigateBarWidget(TQWidget *parent=0, bool show=true); + ~NavigateBarWidget(); + + void setFileName(TQString filename=TQString()); + TQString getFileName(); + void setButtonsState(int itemType); + int getButtonsState(); + +signals: + + void signalFirstItem(void); + void signalPrevItem(void); + void signalNextItem(void); + void signalLastItem(void); + +private : + + NavigateBarWidgetPriv* d; +}; + +} // namespace Digikam + +#endif /* NAVIGATEBARWIDGET_H */ diff --git a/src/libs/imageproperties/talbumlistview.cpp b/src/libs/imageproperties/talbumlistview.cpp new file mode 100644 index 00000000..1369d228 --- /dev/null +++ b/src/libs/imageproperties/talbumlistview.cpp @@ -0,0 +1,528 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2006-18-12 + * Description : A list view to display digiKam Tags. + * + * Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2009 by Andi Clemens <andi dot clemens at gmx 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. + * + * ============================================================ */ + +// TQt includes. + +#include <tqheader.h> + +// KDE includes. + +#include <tdepopupmenu.h> +#include <tdelocale.h> +#include <kurl.h> +#include <kcursor.h> +#include <tdeapplication.h> +#include <kiconloader.h> +#include <tdemessagebox.h> +#include <tdeconfig.h> +#include <tdeglobalsettings.h> +#include <kdialogbase.h> + +// Local includes. + +#include "ddebug.h" +#include "albumiconitem.h" +#include "albumlister.h" +#include "albummanager.h" +#include "albumdb.h" +#include "album.h" +#include "albumsettings.h" +#include "imageinfo.h" +#include "navigatebarwidget.h" +#include "dragobjects.h" +#include "imageattributeswatch.h" +#include "albumthumbnailloader.h" +#include "statusprogressbar.h" +#include "talbumlistview.h" +#include "talbumlistview.moc" + +// X11 includes. + +extern "C" +{ +#include <X11/Xlib.h> +} + +namespace Digikam +{ + +TAlbumCheckListItem::TAlbumCheckListItem(TQListView* parent, TAlbum* album) + : FolderCheckListItem(parent, album->title(), TQCheckListItem::RadioButtonController) +{ + setDragEnabled(true); + m_album = album; + m_count = 0; + + if (m_album) + m_album->setExtraData(listView(), this); +} + +TAlbumCheckListItem::TAlbumCheckListItem(TQCheckListItem* parent, TAlbum* album) + : FolderCheckListItem(parent, album->title(), TQCheckListItem::CheckBox) +{ + setDragEnabled(true); + m_album = album; + m_count = 0; + + if (m_album) + m_album->setExtraData(listView(), this); +} + +void TAlbumCheckListItem::refresh() +{ + if (!m_album) return; + + if (AlbumSettings::instance()->getShowFolderTreeViewItemsCount() && + dynamic_cast<TAlbumCheckListItem*>(parent())) + { + if (isOpen()) + setText(0, TQString("%1 (%2)").arg(m_album->title()).arg(m_count)); + else + { + int countRecursive = m_count; + AlbumIterator it(m_album); + while ( it.current() ) + { + TAlbumCheckListItem *item = (TAlbumCheckListItem*)it.current()->extraData(listView()); + if (item) + countRecursive += item->count(); + ++it; + } + setText(0, TQString("%1 (%2)").arg(m_album->title()).arg(countRecursive)); + } + } + else + { + setText(0, m_album->title()); + } +} + +void TAlbumCheckListItem::stateChange(bool val) +{ + TQCheckListItem::stateChange(val); + ((TAlbumListView*)listView())->stateChanged(this); +} + +void TAlbumCheckListItem::setOpen(bool o) +{ + TQListViewItem::setOpen(o); + refresh(); +} + +TAlbum* TAlbumCheckListItem::album() const +{ + return m_album; +} + +int TAlbumCheckListItem::id() const +{ + return m_album ? m_album->id() : 0; +} + +void TAlbumCheckListItem::setCount(int count) +{ + m_count = count; + refresh(); +} + +int TAlbumCheckListItem::count() +{ + return m_count; +} + +void TAlbumCheckListItem::setStatus(MetadataHub::TagStatus status) +{ + if (status == MetadataHub::MetadataDisjoint) + { + if (type() != TQCheckListItem::RadioButtonController) setTristate(true); + setState(TQCheckListItem::NoChange); + } + else + { + if (type() != TQCheckListItem::RadioButtonController) setTristate(false); + setOn(status.hasTag); + } +} + +// ------------------------------------------------------------------------ + +TAlbumListView::TAlbumListView(TQWidget* parent) + : FolderView(parent, "TAlbumListView") +{ + addColumn(i18n("Tags")); + header()->hide(); + setResizeMode(TQListView::LastColumn); + setRootIsDecorated(true); + + setAcceptDrops(true); + viewport()->setAcceptDrops(true); + + connect(AlbumManager::instance(), TQ_SIGNAL(signalTAlbumsDirty(const TQMap<int, int>&)), + this, TQ_SLOT(slotRefresh(const TQMap<int, int>&))); +} + +TAlbumListView::~TAlbumListView() +{ + saveViewState(); +} + +void TAlbumListView::stateChanged(TAlbumCheckListItem *item) +{ + emit signalItemStateChanged(item); +} + +TQDragObject* TAlbumListView::dragObject() +{ + TAlbumCheckListItem *item = dynamic_cast<TAlbumCheckListItem*>(dragItem()); + if(!item) + return 0; + + if(!item->parent()) + return 0; + + TagDrag *t = new TagDrag(item->id(), this); + t->setPixmap(*item->pixmap(0)); + + return t; +} + +bool TAlbumListView::acceptDrop(const TQDropEvent *e) const +{ + TQPoint vp = contentsToViewport(e->pos()); + TAlbumCheckListItem *itemDrop = dynamic_cast<TAlbumCheckListItem*>(itemAt(vp)); + TAlbumCheckListItem *itemDrag = dynamic_cast<TAlbumCheckListItem*>(dragItem()); + + if(TagDrag::canDecode(e) || TagListDrag::canDecode(e)) + { + // Allow dragging at the root, to move the tag to the root + if(!itemDrop) + return true; + + // Dragging an item on itself makes no sense + if(itemDrag == itemDrop) + return false; + + // Dragging a parent on its child makes no sense + if(itemDrag && itemDrag->album()->isAncestorOf(itemDrop->album())) + return false; + + return true; + } + + if (ItemDrag::canDecode(e) && itemDrop && itemDrop->album()->parent()) + { + // Only other possibility is image items being dropped + // And allow this only if there is a Tag to be dropped + // on and also the Tag is not root. + return true; + } + + return false; +} + +void TAlbumListView::contentsDropEvent(TQDropEvent *e) +{ + TQListView::contentsDropEvent(e); + + if(!acceptDrop(e)) + return; + + TQPoint vp = contentsToViewport(e->pos()); + TAlbumCheckListItem *itemDrop = dynamic_cast<TAlbumCheckListItem*>(itemAt(vp)); + + if(TagDrag::canDecode(e)) + { + TQByteArray ba = e->encodedData("digikam/tag-id"); + TQDataStream ds(ba, IO_ReadOnly); + int tagID; + ds >> tagID; + + AlbumManager* man = AlbumManager::instance(); + TAlbum* talbum = man->findTAlbum(tagID); + + if(!talbum) + return; + + if (talbum == itemDrop->album()) + return; + + TDEPopupMenu popMenu(this); + popMenu.insertTitle(SmallIcon("digikam"), i18n("Tags")); + popMenu.insertItem(SmallIcon("goto"), i18n("&Move Here"), 10); + popMenu.insertSeparator(-1); + popMenu.insertItem(SmallIcon("cancel"), i18n("C&ancel"), 20); + popMenu.setMouseTracking(true); + int id = popMenu.exec(TQCursor::pos()); + + if(id == 10) + { + TAlbum *newParentTag = 0; + + if (!itemDrop) + { + // move dragItem to the root + newParentTag = AlbumManager::instance()->findTAlbum(0); + } + else + { + // move dragItem as child of dropItem + newParentTag = itemDrop->album(); + } + + TQString errMsg; + if (!AlbumManager::instance()->moveTAlbum(talbum, newParentTag, errMsg)) + { + KMessageBox::error(this, errMsg); + } + + if(itemDrop && !itemDrop->isOpen()) + itemDrop->setOpen(true); + } + + return; + } + + if (ItemDrag::canDecode(e)) + { + TAlbum *destAlbum = itemDrop->album(); + TAlbum *srcAlbum; + + KURL::List urls; + KURL::List kioURLs; + TQValueList<int> albumIDs; + TQValueList<int> imageIDs; + + if (!ItemDrag::decode(e, urls, kioURLs, albumIDs, imageIDs)) + return; + + if (urls.isEmpty() || kioURLs.isEmpty() || albumIDs.isEmpty() || imageIDs.isEmpty()) + return; + + // all the albumids will be the same + int albumID = albumIDs.first(); + srcAlbum = AlbumManager::instance()->findTAlbum(albumID); + if (!srcAlbum) + { + DWarning() << "Could not find source album of drag" + << endl; + return; + } + + int id = 0; + char keys_return[32]; + XQueryKeymap(x11Display(), keys_return); + int key_1 = XKeysymToKeycode(x11Display(), 0xFFE3); + int key_2 = XKeysymToKeycode(x11Display(), 0xFFE4); + + if(srcAlbum == destAlbum) + { + // Setting the dropped image as the album thumbnail + // If the ctrl key is pressed, when dropping the image, the + // thumbnail is set without a popup menu + if (((keys_return[key_1 / 8]) && (1 << (key_1 % 8))) || + ((keys_return[key_2 / 8]) && (1 << (key_2 % 8)))) + { + id = 12; + } + else + { + TDEPopupMenu popMenu(this); + popMenu.insertTitle(SmallIcon("digikam"), i18n("Tags")); + popMenu.insertItem(i18n("Set as Tag Thumbnail"), 12); + popMenu.insertSeparator(-1); + popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") ); + + popMenu.setMouseTracking(true); + id = popMenu.exec(TQCursor::pos()); + } + + if(id == 12) + { + TQString errMsg; + AlbumManager::instance()->updateTAlbumIcon(destAlbum, TQString(), + imageIDs.first(), errMsg); + } + return; + } + + // If a ctrl key is pressed while dropping the drag object, + // the tag is assigned to the images without showing a + // popup menu. + if (((keys_return[key_1 / 8]) && (1 << (key_1 % 8))) || + ((keys_return[key_2 / 8]) && (1 << (key_2 % 8)))) + { + id = 10; + } + else + { + TDEPopupMenu popMenu(this); + popMenu.insertTitle(SmallIcon("digikam"), i18n("Tags")); + popMenu.insertItem( SmallIcon("tag"), i18n("Assign Tag '%1' to Items") + .arg(destAlbum->prettyURL()), 10) ; + popMenu.insertSeparator(-1); + popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") ); + + popMenu.setMouseTracking(true); + id = popMenu.exec(TQCursor::pos()); + } + + if (id == 10) + { + emit signalProgressBarMode(StatusProgressBar::ProgressBarMode, + i18n("Assign tag to images. Please wait...")); + + AlbumLister::instance()->blockSignals(true); + AlbumManager::instance()->albumDB()->beginTransaction(); + int i=0; + for (TQValueList<int>::const_iterator it = imageIDs.begin(); + it != imageIDs.end(); ++it) + { + // create temporary ImageInfo object + ImageInfo info(*it); + + MetadataHub hub; + hub.load(&info); + hub.setTag(destAlbum, true); + hub.write(&info, MetadataHub::PartialWrite); + hub.write(info.filePath(), MetadataHub::FullWriteIfChanged); + + emit signalProgressValue((int)((i++/(float)imageIDs.count())*100.0)); + kapp->processEvents(); + } + AlbumLister::instance()->blockSignals(false); + AlbumManager::instance()->albumDB()->commitTransaction(); + + ImageAttributesWatch::instance()->imagesChanged(destAlbum->id()); + + emit signalProgressBarMode(StatusProgressBar::TextMode, TQString()); + } + } +} + +void TAlbumListView::refresh() +{ + TQListViewItemIterator it(this); + + while (it.current()) + { + TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(*it); + if (item) + item->refresh(); + ++it; + } +} + +void TAlbumListView::slotRefresh(const TQMap<int, int>& tagsStatMap) +{ + TQListViewItemIterator it(this); + + while (it.current()) + { + TAlbumCheckListItem* item = dynamic_cast<TAlbumCheckListItem*>(*it); + if (item) + { + if (item->album()) + { + int id = item->id(); + TQMap<int, int>::const_iterator it2 = tagsStatMap.find(id); + if ( it2 != tagsStatMap.end() ) + item->setCount(it2.data()); + } + } + ++it; + } + + refresh(); +} + +void TAlbumListView::loadViewState() +{ + TDEConfig *config = kapp->config(); + config->setGroup(name()); + + int selectedItem = config->readNumEntry("LastSelectedItem", 0); + + TQValueList<int> openFolders; + if(config->hasKey("OpenFolders")) + { + openFolders = config->readIntListEntry("OpenFolders"); + } + + TAlbumCheckListItem *item = 0; + TAlbumCheckListItem *foundItem = 0; + TQListViewItemIterator it(this->lastItem()); + + for( ; it.current(); --it) + { + item = dynamic_cast<TAlbumCheckListItem*>(it.current()); + if(!item) + continue; + + // Start the album root always open + if(openFolders.contains(item->id()) || item->id() == 0) + setOpen(item, true); + else + setOpen(item, false); + + if(item->id() == selectedItem) + { + // Save the found selected item so that it can be made visible. + foundItem = item; + } + } + + // Important note: this cannot be done inside the previous loop + // because opening folders prevents the visibility. + // Fixes bug #144815. + // (Looks a bit like a bug in TQt to me ...) + if (foundItem) + { + setSelected(foundItem, true); + ensureItemVisible(foundItem); + } +} + +void TAlbumListView::saveViewState() +{ + TDEConfig *config = kapp->config(); + config->setGroup(name()); + + TAlbumCheckListItem *item = dynamic_cast<TAlbumCheckListItem*>(selectedItem()); + if(item) + config->writeEntry("LastSelectedItem", item->id()); + else + config->writeEntry("LastSelectedItem", 0); + + TQValueList<int> openFolders; + TQListViewItemIterator it(this); + for( ; it.current(); ++it) + { + item = dynamic_cast<TAlbumCheckListItem*>(it.current()); + if(item && isOpen(item)) + openFolders.push_back(item->id()); + } + config->writeEntry("OpenFolders", openFolders); +} + +} // NameSpace Digikam diff --git a/src/libs/imageproperties/talbumlistview.h b/src/libs/imageproperties/talbumlistview.h new file mode 100644 index 00000000..b483706c --- /dev/null +++ b/src/libs/imageproperties/talbumlistview.h @@ -0,0 +1,109 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2006-18-12 + * Description : A list view to display digiKam Tags. + * + * Copyright (C) 2006-2009 by Gilles Caulier <caulier dot gilles at gmail dot com> + * Copyright (C) 2009 by Andi Clemens <andi dot clemens at gmx 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 TALBUMLISTVIEW_H +#define TALBUMLISTVIEW_H + +// Local includes. + +#include "digikam_export.h" +#include "metadatahub.h" +#include "folderitem.h" +#include "folderview.h" + +class TQDropEvent; +class TQMouseEvent; + +namespace Digikam +{ +class TAlbum; + +class DIGIKAM_EXPORT TAlbumCheckListItem : public FolderCheckListItem +{ +public: + + TAlbumCheckListItem(TQListView* parent, TAlbum* album); + + TAlbumCheckListItem(TQCheckListItem* parent, TAlbum* album); + + void setStatus(MetadataHub::TagStatus status); + void refresh(); + void setOpen(bool o); + TAlbum* album() const; + int id() const; + void setCount(int count); + int count(); + +private : + + void stateChange(bool val); + +private : + + int m_count; + + TAlbum *m_album; +}; + +// ------------------------------------------------------------------------ + +class DIGIKAM_EXPORT TAlbumListView : public FolderView +{ + TQ_OBJECT + + +public: + + TAlbumListView(TQWidget* parent); + ~TAlbumListView(); + + void stateChanged(TAlbumCheckListItem *item); + void refresh(); + void loadViewState(); + +signals: + + void signalProgressBarMode(int, const TQString&); + void signalProgressValue(int); + void signalItemStateChanged(TAlbumCheckListItem *item); + +protected: + + bool acceptDrop(const TQDropEvent *e) const; + void contentsDropEvent(TQDropEvent *e); + + TQDragObject* dragObject(); + +private slots: + + void slotRefresh(const TQMap<int, int>&); + +private: + + void saveViewState(); +}; + +} // NameSpace Digikam + +#endif // TALBUMLISTVIEW_H |