|
|
|
/* ============================================================
|
|
|
|
*
|
|
|
|
* This file is a part of digiKam project
|
|
|
|
* http://www.digikam.org
|
|
|
|
*
|
|
|
|
* Date : 2006-21-12
|
|
|
|
* Description : a embedded view to show the image preview widget.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006-2009 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 <tqpainter.h>
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <tqvaluevector.h>
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
#include <tqtoolbutton.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
|
|
|
|
// KDE includes.
|
|
|
|
|
|
|
|
#include <kdialogbase.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kservice.h>
|
|
|
|
#include <krun.h>
|
|
|
|
#include <ktrader.h>
|
|
|
|
#include <kmimetype.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <kcursor.h>
|
|
|
|
#include <kdatetbl.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <kapplication.h>
|
|
|
|
|
|
|
|
// LibKipi includes.
|
|
|
|
|
|
|
|
#include <libkipi/pluginloader.h>
|
|
|
|
#include <libkipi/plugin.h>
|
|
|
|
|
|
|
|
// Local includes.
|
|
|
|
|
|
|
|
#include "dimg.h"
|
|
|
|
#include "ddebug.h"
|
|
|
|
#include "albumdb.h"
|
|
|
|
#include "albummanager.h"
|
|
|
|
#include "albumsettings.h"
|
|
|
|
#include "albumwidgetstack.h"
|
|
|
|
#include "imageinfo.h"
|
|
|
|
#include "dmetadata.h"
|
|
|
|
#include "dpopupmenu.h"
|
|
|
|
#include "metadatahub.h"
|
|
|
|
#include "paniconwidget.h"
|
|
|
|
#include "previewloadthread.h"
|
|
|
|
#include "loadingdescription.h"
|
|
|
|
#include "tagspopupmenu.h"
|
|
|
|
#include "ratingpopupmenu.h"
|
|
|
|
#include "themeengine.h"
|
|
|
|
#include "imagepreviewview.h"
|
|
|
|
#include "imagepreviewview.moc"
|
|
|
|
|
|
|
|
namespace Digikam
|
|
|
|
{
|
|
|
|
|
|
|
|
class ImagePreviewViewPriv
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
ImagePreviewViewPriv()
|
|
|
|
{
|
|
|
|
panIconPopup = 0;
|
|
|
|
panIconWidget = 0;
|
|
|
|
cornerButton = 0;
|
|
|
|
previewThread = 0;
|
|
|
|
previewPreloadThread = 0;
|
|
|
|
imageInfo = 0;
|
|
|
|
parent = 0;
|
|
|
|
hasPrev = false;
|
|
|
|
hasNext = false;
|
|
|
|
loadFullImageSize = false;
|
|
|
|
currentFitWindowZoom = 0;
|
|
|
|
previewSize = 1024;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool hasPrev;
|
|
|
|
bool hasNext;
|
|
|
|
bool loadFullImageSize;
|
|
|
|
|
|
|
|
int previewSize;
|
|
|
|
|
|
|
|
double currentFitWindowZoom;
|
|
|
|
|
|
|
|
TQString path;
|
|
|
|
TQString nextPath;
|
|
|
|
TQString previousPath;
|
|
|
|
|
|
|
|
TQToolButton *cornerButton;
|
|
|
|
|
|
|
|
KPopupFrame *panIconPopup;
|
|
|
|
|
|
|
|
PanIconWidget *panIconWidget;
|
|
|
|
|
|
|
|
DImg preview;
|
|
|
|
|
|
|
|
ImageInfo *imageInfo;
|
|
|
|
|
|
|
|
PreviewLoadThread *previewThread;
|
|
|
|
PreviewLoadThread *previewPreloadThread;
|
|
|
|
|
|
|
|
AlbumWidgetStack *parent;
|
|
|
|
};
|
|
|
|
|
|
|
|
ImagePreviewView::ImagePreviewView(AlbumWidgetStack *parent)
|
|
|
|
: PreviewWidget(parent)
|
|
|
|
{
|
|
|
|
d = new ImagePreviewViewPriv;
|
|
|
|
d->parent = parent;
|
|
|
|
|
|
|
|
// get preview size from screen size, but limit from VGA to WTQXGA
|
|
|
|
d->previewSize = TQMAX(KApplication::desktop()->height(),
|
|
|
|
KApplication::desktop()->width());
|
|
|
|
if (d->previewSize < 640)
|
|
|
|
d->previewSize = 640;
|
|
|
|
if (d->previewSize > 2560)
|
|
|
|
d->previewSize = 2560;
|
|
|
|
|
|
|
|
setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding);
|
|
|
|
|
|
|
|
d->cornerButton = new TQToolButton(this);
|
|
|
|
d->cornerButton->setIconSet(SmallIcon("move"));
|
|
|
|
d->cornerButton->hide();
|
|
|
|
TQToolTip::add(d->cornerButton, i18n("Pan the image to a region"));
|
|
|
|
setCornerWidget(d->cornerButton);
|
|
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
|
|
|
|
|
|
connect(d->cornerButton, TQT_SIGNAL(pressed()),
|
|
|
|
this, TQT_SLOT(slotCornerButtonPressed()));
|
|
|
|
|
|
|
|
connect(this, TQT_SIGNAL(signalShowNextImage()),
|
|
|
|
this, TQT_SIGNAL(signalNextItem()));
|
|
|
|
|
|
|
|
connect(this, TQT_SIGNAL(signalShowPrevImage()),
|
|
|
|
this, TQT_SIGNAL(signalPrevItem()));
|
|
|
|
|
|
|
|
connect(this, TQT_SIGNAL(signalRightButtonClicked()),
|
|
|
|
this, TQT_SLOT(slotContextMenu()));
|
|
|
|
|
|
|
|
connect(this, TQT_SIGNAL(signalLeftButtonClicked()),
|
|
|
|
this, TQT_SIGNAL(signalBack2Album()));
|
|
|
|
|
|
|
|
connect(ThemeEngine::instance(), TQT_SIGNAL(signalThemeChanged()),
|
|
|
|
this, TQT_SLOT(slotThemeChanged()));
|
|
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
|
|
|
|
|
|
slotReset();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImagePreviewView::~ImagePreviewView()
|
|
|
|
{
|
|
|
|
delete d->previewThread;
|
|
|
|
delete d->previewPreloadThread;
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::setLoadFullImageSize(bool b)
|
|
|
|
{
|
|
|
|
d->loadFullImageSize = b;
|
|
|
|
reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::setImage(const DImg& image)
|
|
|
|
{
|
|
|
|
d->preview = image;
|
|
|
|
|
|
|
|
updateZoomAndSize(true);
|
|
|
|
|
|
|
|
viewport()->setUpdatesEnabled(true);
|
|
|
|
viewport()->update();
|
|
|
|
}
|
|
|
|
|
|
|
|
DImg& ImagePreviewView::getImage() const
|
|
|
|
{
|
|
|
|
return d->preview;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::reload()
|
|
|
|
{
|
|
|
|
// cache is cleaned from AlbumIconView::refreshItems
|
|
|
|
setImagePath(d->path);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::setPreviousNextPaths(const TQString& previous, const TQString &next)
|
|
|
|
{
|
|
|
|
d->nextPath = next;
|
|
|
|
d->previousPath = previous;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::setImagePath(const TQString& path)
|
|
|
|
{
|
|
|
|
setCursor( KCursor::waitCursor() );
|
|
|
|
|
|
|
|
d->path = path;
|
|
|
|
d->nextPath = TQString();
|
|
|
|
d->previousPath = TQString();
|
|
|
|
|
|
|
|
if (d->path.isEmpty())
|
|
|
|
{
|
|
|
|
slotReset();
|
|
|
|
unsetCursor();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!d->previewThread)
|
|
|
|
{
|
|
|
|
d->previewThread = new PreviewLoadThread();
|
|
|
|
connect(d->previewThread, TQT_SIGNAL(signalImageLoaded(const LoadingDescription &, const DImg &)),
|
|
|
|
this, TQT_SLOT(slotGotImagePreview(const LoadingDescription &, const DImg&)));
|
|
|
|
}
|
|
|
|
if (!d->previewPreloadThread)
|
|
|
|
{
|
|
|
|
d->previewPreloadThread = new PreviewLoadThread();
|
|
|
|
connect(d->previewPreloadThread, TQT_SIGNAL(signalImageLoaded(const LoadingDescription &, const DImg &)),
|
|
|
|
this, TQT_SLOT(slotNextPreload()));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d->loadFullImageSize)
|
|
|
|
d->previewThread->loadHighQuality(LoadingDescription(path, 0, AlbumSettings::instance()->getExifRotate()));
|
|
|
|
else
|
|
|
|
d->previewThread->load(LoadingDescription(path, d->previewSize, AlbumSettings::instance()->getExifRotate()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotGotImagePreview(const LoadingDescription &description, const DImg& preview)
|
|
|
|
{
|
|
|
|
if (description.filePath != d->path)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (preview.isNull())
|
|
|
|
{
|
|
|
|
d->parent->setPreviewMode(AlbumWidgetStack::PreviewImageMode);
|
|
|
|
TQPixmap pix(visibleWidth(), visibleHeight());
|
|
|
|
pix.fill(ThemeEngine::instance()->baseColor());
|
|
|
|
TQPainter p(&pix);
|
|
|
|
TQFileInfo info(d->path);
|
|
|
|
p.setPen(TQPen(ThemeEngine::instance()->textRegColor()));
|
|
|
|
p.drawText(0, 0, pix.width(), pix.height(),
|
|
|
|
TQt::AlignCenter|TQt::WordBreak,
|
|
|
|
i18n("Cannot display preview for\n\"%1\"")
|
|
|
|
.arg(info.fileName()));
|
|
|
|
p.end();
|
|
|
|
// three copies - but the image is small
|
|
|
|
setImage(DImg(pix.convertToImage()));
|
|
|
|
d->parent->previewLoaded();
|
|
|
|
emit signalPreviewLoaded(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DImg img(preview);
|
|
|
|
if (AlbumSettings::instance()->getExifRotate())
|
|
|
|
d->previewThread->exifRotate(img, description.filePath);
|
|
|
|
d->parent->setPreviewMode(AlbumWidgetStack::PreviewImageMode);
|
|
|
|
setImage(img);
|
|
|
|
d->parent->previewLoaded();
|
|
|
|
emit signalPreviewLoaded(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsetCursor();
|
|
|
|
slotNextPreload();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotNextPreload()
|
|
|
|
{
|
|
|
|
TQString loadPath;
|
|
|
|
if (!d->nextPath.isNull())
|
|
|
|
{
|
|
|
|
loadPath = d->nextPath;
|
|
|
|
d->nextPath = TQString();
|
|
|
|
}
|
|
|
|
else if (!d->previousPath.isNull())
|
|
|
|
{
|
|
|
|
loadPath = d->previousPath;
|
|
|
|
d->previousPath = TQString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (d->loadFullImageSize)
|
|
|
|
d->previewThread->loadHighQuality(LoadingDescription(loadPath, 0,
|
|
|
|
AlbumSettings::instance()->getExifRotate()));
|
|
|
|
else
|
|
|
|
d->previewPreloadThread->load(LoadingDescription(loadPath, d->previewSize,
|
|
|
|
AlbumSettings::instance()->getExifRotate()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::setImageInfo(ImageInfo* info, ImageInfo *previous, ImageInfo *next)
|
|
|
|
{
|
|
|
|
d->imageInfo = info;
|
|
|
|
d->hasPrev = previous;
|
|
|
|
d->hasNext = next;
|
|
|
|
|
|
|
|
if (d->imageInfo)
|
|
|
|
setImagePath(info->filePath());
|
|
|
|
else
|
|
|
|
setImagePath();
|
|
|
|
|
|
|
|
setPreviousNextPaths(previous ? previous->filePath() : TQString(),
|
|
|
|
next ? next->filePath() : TQString());
|
|
|
|
}
|
|
|
|
|
|
|
|
ImageInfo* ImagePreviewView::getImageInfo() const
|
|
|
|
{
|
|
|
|
return d->imageInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotContextMenu()
|
|
|
|
{
|
|
|
|
RatingPopupMenu *ratingMenu = 0;
|
|
|
|
TagsPopupMenu *assignTagsMenu = 0;
|
|
|
|
TagsPopupMenu *removeTagsMenu = 0;
|
|
|
|
|
|
|
|
if (!d->imageInfo)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//-- Open With Actions ------------------------------------
|
|
|
|
|
|
|
|
KURL url(d->imageInfo->kurl().path());
|
|
|
|
KMimeType::Ptr mimePtr = KMimeType::findByURL(url, 0, true, true);
|
|
|
|
|
|
|
|
TQValueVector<KService::Ptr> serviceVector;
|
|
|
|
KTrader::OfferList offers = KTrader::self()->query(mimePtr->name(), "Type == 'Application'");
|
|
|
|
|
|
|
|
TQPopupMenu openWithMenu;
|
|
|
|
|
|
|
|
KTrader::OfferList::Iterator iter;
|
|
|
|
KService::Ptr ptr;
|
|
|
|
int index = 100;
|
|
|
|
|
|
|
|
for( iter = offers.begin(); iter != offers.end(); ++iter )
|
|
|
|
{
|
|
|
|
ptr = *iter;
|
|
|
|
openWithMenu.insertItem( ptr->pixmap(KIcon::Small), ptr->name(), index++);
|
|
|
|
serviceVector.push_back(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
//-- Navigate actions -------------------------------------------
|
|
|
|
|
|
|
|
DPopupMenu popmenu(this);
|
|
|
|
popmenu.insertItem(SmallIcon("back"), i18n("Back"), 10);
|
|
|
|
if (!d->hasPrev) popmenu.setItemEnabled(10, false);
|
|
|
|
|
|
|
|
popmenu.insertItem(SmallIcon("forward"), i18n("Forward"), 11);
|
|
|
|
if (!d->hasNext) popmenu.setItemEnabled(11, false);
|
|
|
|
|
|
|
|
popmenu.insertItem(SmallIcon("folder_image"), i18n("Back to Album"), 15);
|
|
|
|
|
|
|
|
//-- Edit actions -----------------------------------------------
|
|
|
|
|
|
|
|
popmenu.insertSeparator();
|
|
|
|
popmenu.insertItem(SmallIcon("slideshow"), i18n("SlideShow"), 16);
|
|
|
|
popmenu.insertItem(SmallIcon("editimage"), i18n("Edit..."), 12);
|
|
|
|
popmenu.insertItem(SmallIcon("lighttableadd"), i18n("Add to Light Table"), 17);
|
|
|
|
popmenu.insertItem(i18n("Open With"), &openWithMenu, 13);
|
|
|
|
|
|
|
|
// Merge in the KIPI plugins actions ----------------------------
|
|
|
|
|
|
|
|
KIPI::PluginLoader* kipiPluginLoader = KIPI::PluginLoader::instance();
|
|
|
|
KIPI::PluginLoader::PluginList pluginList = kipiPluginLoader->pluginList();
|
|
|
|
|
|
|
|
for (KIPI::PluginLoader::PluginList::const_iterator it = pluginList.begin();
|
|
|
|
it != pluginList.end(); ++it)
|
|
|
|
{
|
|
|
|
KIPI::Plugin* plugin = (*it)->plugin();
|
|
|
|
|
|
|
|
if (plugin && (*it)->name() == "JPEGLossless")
|
|
|
|
{
|
|
|
|
DDebug() << "Found JPEGLossless plugin" << endl;
|
|
|
|
|
|
|
|
KActionPtrList actionList = plugin->actions();
|
|
|
|
|
|
|
|
for (KActionPtrList::const_iterator iter = actionList.begin();
|
|
|
|
iter != actionList.end(); ++iter)
|
|
|
|
{
|
|
|
|
KAction* action = *iter;
|
|
|
|
|
|
|
|
if (TQString::fromLatin1(action->name())
|
|
|
|
== TQString::fromLatin1("jpeglossless_rotate"))
|
|
|
|
{
|
|
|
|
action->plug(&popmenu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-- Trash action -------------------------------------------
|
|
|
|
|
|
|
|
popmenu.insertSeparator();
|
|
|
|
popmenu.insertItem(SmallIcon("edittrash"), i18n("Move to Trash"), 14);
|
|
|
|
|
|
|
|
// Bulk assignment/removal of tags --------------------------
|
|
|
|
|
|
|
|
TQ_LLONG id = d->imageInfo->id();
|
|
|
|
TQValueList<TQ_LLONG> idList;
|
|
|
|
idList.append(id);
|
|
|
|
|
|
|
|
assignTagsMenu = new TagsPopupMenu(idList, 1000, TagsPopupMenu::ASSIGN);
|
|
|
|
removeTagsMenu = new TagsPopupMenu(idList, 2000, TagsPopupMenu::REMOVE);
|
|
|
|
|
|
|
|
popmenu.insertSeparator();
|
|
|
|
|
|
|
|
popmenu.insertItem(i18n("Assign Tag"), assignTagsMenu);
|
|
|
|
int i = popmenu.insertItem(i18n("Remove Tag"), removeTagsMenu);
|
|
|
|
|
|
|
|
connect(assignTagsMenu, TQT_SIGNAL(signalTagActivated(int)),
|
|
|
|
this, TQT_SLOT(slotAssignTag(int)));
|
|
|
|
|
|
|
|
connect(removeTagsMenu, TQT_SIGNAL(signalTagActivated(int)),
|
|
|
|
this, TQT_SLOT(slotRemoveTag(int)));
|
|
|
|
|
|
|
|
AlbumDB* db = AlbumManager::instance()->albumDB();
|
|
|
|
if (!db->hasTags( idList ))
|
|
|
|
popmenu.setItemEnabled(i, false);
|
|
|
|
|
|
|
|
popmenu.insertSeparator();
|
|
|
|
|
|
|
|
// Assign Star Rating -------------------------------------------
|
|
|
|
|
|
|
|
ratingMenu = new RatingPopupMenu();
|
|
|
|
|
|
|
|
connect(ratingMenu, TQT_SIGNAL(activated(int)),
|
|
|
|
this, TQT_SLOT(slotAssignRating(int)));
|
|
|
|
|
|
|
|
popmenu.insertItem(i18n("Assign Rating"), ratingMenu);
|
|
|
|
|
|
|
|
// --------------------------------------------------------
|
|
|
|
|
|
|
|
int idm = popmenu.exec(TQCursor::pos());
|
|
|
|
|
|
|
|
switch(idm)
|
|
|
|
{
|
|
|
|
case 10: // Back
|
|
|
|
{
|
|
|
|
emit signalPrevItem();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 11: // Forward
|
|
|
|
{
|
|
|
|
emit signalNextItem();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 12: // Edit...
|
|
|
|
{
|
|
|
|
emit signalEditItem();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 14: // Move to trash
|
|
|
|
{
|
|
|
|
emit signalDeleteItem();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 15: // Back to album
|
|
|
|
{
|
|
|
|
emit signalBack2Album();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 16: // SlideShow
|
|
|
|
{
|
|
|
|
emit signalSlideShow();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 17: // Place onto Light Table
|
|
|
|
{
|
|
|
|
emit signalInsert2LightTable();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open With...
|
|
|
|
if (idm >= 100 && idm < 1000)
|
|
|
|
{
|
|
|
|
KService::Ptr imageServicePtr = serviceVector[idm-100];
|
|
|
|
KRun::run(*imageServicePtr, url);
|
|
|
|
}
|
|
|
|
|
|
|
|
serviceVector.clear();
|
|
|
|
delete assignTagsMenu;
|
|
|
|
delete removeTagsMenu;
|
|
|
|
delete ratingMenu;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotAssignTag(int tagID)
|
|
|
|
{
|
|
|
|
if (d->imageInfo)
|
|
|
|
{
|
|
|
|
MetadataHub hub;
|
|
|
|
hub.load(d->imageInfo);
|
|
|
|
hub.setTag(tagID, true);
|
|
|
|
hub.write(d->imageInfo, MetadataHub::PartialWrite);
|
|
|
|
hub.write(d->imageInfo->filePath(), MetadataHub::FullWriteIfChanged);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotRemoveTag(int tagID)
|
|
|
|
{
|
|
|
|
if (d->imageInfo)
|
|
|
|
{
|
|
|
|
MetadataHub hub;
|
|
|
|
hub.load(d->imageInfo);
|
|
|
|
hub.setTag(tagID, false);
|
|
|
|
hub.write(d->imageInfo, MetadataHub::PartialWrite);
|
|
|
|
hub.write(d->imageInfo->filePath(), MetadataHub::FullWriteIfChanged);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotAssignRating(int rating)
|
|
|
|
{
|
|
|
|
rating = TQMIN(5, TQMAX(0, rating));
|
|
|
|
if (d->imageInfo)
|
|
|
|
{
|
|
|
|
MetadataHub hub;
|
|
|
|
hub.load(d->imageInfo);
|
|
|
|
hub.setRating(rating);
|
|
|
|
hub.write(d->imageInfo, MetadataHub::PartialWrite);
|
|
|
|
hub.write(d->imageInfo->filePath(), MetadataHub::FullWriteIfChanged);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotThemeChanged()
|
|
|
|
{
|
|
|
|
setBackgroundColor(ThemeEngine::instance()->baseColor());
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotCornerButtonPressed()
|
|
|
|
{
|
|
|
|
if (d->panIconPopup)
|
|
|
|
{
|
|
|
|
d->panIconPopup->hide();
|
|
|
|
delete d->panIconPopup;
|
|
|
|
d->panIconPopup = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->panIconPopup = new KPopupFrame(this);
|
|
|
|
PanIconWidget *pan = new PanIconWidget(d->panIconPopup);
|
|
|
|
pan->setImage(180, 120, getImage());
|
|
|
|
d->panIconPopup->setMainWidget(pan);
|
|
|
|
|
|
|
|
TQRect r((int)(contentsX() / zoomFactor()), (int)(contentsY() / zoomFactor()),
|
|
|
|
(int)(visibleWidth() / zoomFactor()), (int)(visibleHeight() / zoomFactor()));
|
|
|
|
pan->setRegionSelection(r);
|
|
|
|
pan->setMouseFocus();
|
|
|
|
|
|
|
|
connect(pan, TQT_SIGNAL(signalSelectionMoved(const TQRect&, bool)),
|
|
|
|
this, TQT_SLOT(slotPanIconSelectionMoved(const TQRect&, bool)));
|
|
|
|
|
|
|
|
connect(pan, TQT_SIGNAL(signalHiden()),
|
|
|
|
this, TQT_SLOT(slotPanIconHiden()));
|
|
|
|
|
|
|
|
TQPoint g = mapToGlobal(viewport()->pos());
|
|
|
|
g.setX(g.x()+ viewport()->size().width());
|
|
|
|
g.setY(g.y()+ viewport()->size().height());
|
|
|
|
d->panIconPopup->popup(TQPoint(g.x() - d->panIconPopup->width(),
|
|
|
|
g.y() - d->panIconPopup->height()));
|
|
|
|
|
|
|
|
pan->setCursorToLocalRegionSelectionCenter();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotPanIconHiden()
|
|
|
|
{
|
|
|
|
d->cornerButton->blockSignals(true);
|
|
|
|
d->cornerButton->animateClick();
|
|
|
|
d->cornerButton->blockSignals(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::slotPanIconSelectionMoved(const TQRect& r, bool b)
|
|
|
|
{
|
|
|
|
setContentsPos((int)(r.x()*zoomFactor()), (int)(r.y()*zoomFactor()));
|
|
|
|
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
d->panIconPopup->hide();
|
|
|
|
delete d->panIconPopup;
|
|
|
|
d->panIconPopup = 0;
|
|
|
|
slotPanIconHiden();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::zoomFactorChanged(double zoom)
|
|
|
|
{
|
|
|
|
updateScrollBars();
|
|
|
|
|
|
|
|
if (horizontalScrollBar()->isVisible() || verticalScrollBar()->isVisible())
|
|
|
|
d->cornerButton->show();
|
|
|
|
else
|
|
|
|
d->cornerButton->hide();
|
|
|
|
|
|
|
|
PreviewWidget::zoomFactorChanged(zoom);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::resizeEvent(TQResizeEvent* e)
|
|
|
|
{
|
|
|
|
if (!e) return;
|
|
|
|
|
|
|
|
TQScrollView::resizeEvent(e);
|
|
|
|
|
|
|
|
if (!d->imageInfo)
|
|
|
|
d->cornerButton->hide();
|
|
|
|
|
|
|
|
updateZoomAndSize(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::updateZoomAndSize(bool alwaysFitToWindow)
|
|
|
|
{
|
|
|
|
// Set zoom for fit-in-window as minimum, but dont scale up images
|
|
|
|
// that are smaller than the available space, only scale down.
|
|
|
|
double zoom = calcAutoZoomFactor(ZoomInOnly);
|
|
|
|
setZoomMin(zoom);
|
|
|
|
setZoomMax(zoom*12.0);
|
|
|
|
|
|
|
|
// Is currently the zoom factor set to fit to window? Then set it again to fit the new size.
|
|
|
|
if (zoomFactor() < zoom || alwaysFitToWindow || zoomFactor() == d->currentFitWindowZoom)
|
|
|
|
{
|
|
|
|
setZoomFactor(zoom);
|
|
|
|
}
|
|
|
|
|
|
|
|
// store which zoom factor means it is fit to window
|
|
|
|
d->currentFitWindowZoom = zoom;
|
|
|
|
|
|
|
|
updateContentsSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ImagePreviewView::previewWidth()
|
|
|
|
{
|
|
|
|
return d->preview.width();
|
|
|
|
}
|
|
|
|
|
|
|
|
int ImagePreviewView::previewHeight()
|
|
|
|
{
|
|
|
|
return d->preview.height();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ImagePreviewView::previewIsNull()
|
|
|
|
{
|
|
|
|
return d->preview.isNull();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::resetPreview()
|
|
|
|
{
|
|
|
|
d->preview = DImg();
|
|
|
|
d->path = TQString();
|
|
|
|
d->imageInfo = 0;
|
|
|
|
|
|
|
|
updateZoomAndSize(true);
|
|
|
|
emit signalPreviewLoaded(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImagePreviewView::paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh)
|
|
|
|
{
|
|
|
|
DImg img = d->preview.smoothScaleSection(sx, sy, sw, sh, tileSize(), tileSize());
|
|
|
|
TQPixmap pix2 = img.convertToPixmap();
|
|
|
|
bitBlt(pix, 0, 0, &pix2, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // NameSpace Digikam
|