killed semantics support of gwenview with fire

This commit is contained in:
Ivailo Monev 2014-11-19 19:44:19 +00:00
parent 94683c14de
commit 3bafcad0bd
44 changed files with 13 additions and 3038 deletions

View file

@ -9,22 +9,6 @@ include(MacroOptionalAddSubdirectory)
KDE4_NO_ENABLE_FINAL(gwenview)
## CMake options
set(GWENVIEW_SEMANTICINFO_BACKEND_NONE OFF)
set(GWENVIEW_SEMANTICINFO_BACKEND_FAKE OFF)
set(GWENVIEW_SEMANTICINFO_BACKEND_BALOO OFF)
set(GWENVIEW_SEMANTICINFO_BACKEND "Baloo" CACHE STRING "Semantic info backend for Gwenview (Baloo/Fake/None)")
# Init GWENVIEW_SEMANTICINFO_BACKEND_* vars
if (GWENVIEW_SEMANTICINFO_BACKEND STREQUAL "None")
set(GWENVIEW_SEMANTICINFO_BACKEND_NONE ON)
elseif (GWENVIEW_SEMANTICINFO_BACKEND STREQUAL "Fake")
set(GWENVIEW_SEMANTICINFO_BACKEND_FAKE ON)
else()
set(GWENVIEW_SEMANTICINFO_BACKEND_BALOO ON)
endif()
## Dependencies
find_package(JPEG)
macro_log_feature(JPEG_FOUND "libjpeg" "JPEG image manipulation support" "http://libjpeg.sourceforge.net/" TRUE)
@ -41,15 +25,6 @@ macro_log_feature(KIPI_FOUND "libkipi" "Provides various image manipulation and
find_package(LCMS2)
macro_log_feature(LCMS2_FOUND "LittleCMS" "Color management engine" "http://www.littlecms.com" TRUE "2.0")
if (NOT GWENVIEW_SEMANTICINFO_BACKEND_NONE)
# We need Baloo for all backends but "None"
find_package(Baloo)
macro_log_feature(Baloo_FOUND "Baloo Core Libraries" "Desktop-wide semantic information support" "https://projects.kde.org/projects/kde/kdelibs/baloo" TRUE)
find_package(KFileMetaData CONFIG)
macro_log_feature(KFileMetaData_FOUND "KFileMetaData Library" "A library for extracting file metadata" "https://projects.kde.org/kfilemetadata" TRUE)
endif()
find_package(LibKonq)
macro_log_feature(LIBKONQ_FOUND "libkonq" "Standard file management features" "http://www.kde.org" TRUE)

View file

@ -39,13 +39,6 @@ set(gwenview_SRCS
browsemainpage.cpp
)
if (NOT GWENVIEW_SEMANTICINFO_BACKEND_NONE)
set (gwenview_SRCS
${gwenview_SRCS}
semanticinfocontextmanageritem.cpp
)
endif()
if (KIPI_FOUND)
set (gwenview_SRCS
${gwenview_SRCS}
@ -61,17 +54,10 @@ kde4_add_ui_files(gwenview_SRCS
fullscreenconfigwidget.ui
generalconfigpage.ui
imageviewconfigpage.ui
semanticinfodialog.ui
startmainpage.ui
browsemainpage.ui
)
if (NOT GWENVIEW_SEMANTICINFO_BACKEND_NONE)
kde4_add_ui_files(gwenview_SRCS
semanticinfosidebaritem.ui
)
endif()
kde4_add_app_icon(gwenview_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/../icons/hi*-apps-gwenview.png")
kde4_add_executable(gwenview ${gwenview_SRCS})

View file

@ -49,9 +49,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include <lib/document/documentfactory.h>
#include <lib/gvdebug.h>
#include <lib/gwenviewconfig.h>
#include <lib/semanticinfo/abstractsemanticinfobackend.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/semanticinfo/tagmodel.h>
#include <lib/sorteddirmodel.h>
#include <lib/sorting.h>
#include <lib/archiveutils.h>
#include <lib/thumbnailview/previewitemdelegate.h>
@ -148,9 +146,6 @@ struct BrowseMainPagePrivate : public Ui_BrowseMainPage
addAction(i18nc("@action:inmenu", "Date"), PreviewItemDelegate::DateDetail);
addAction(i18nc("@action:inmenu", "Image Size"), PreviewItemDelegate::ImageSizeDetail);
addAction(i18nc("@action:inmenu", "File Size"), PreviewItemDelegate::FileSizeDetail);
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
addAction(i18nc("@action:inmenu", "Rating"), PreviewItemDelegate::RatingDetail);
#endif
#undef addAction
KActionCategory* file = new KActionCategory(i18nc("@title actions category", "File"), actionCollection);

View file

@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
// Local
#include <lib/document/documentfactory.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
namespace Gwenview
{

View file

@ -46,17 +46,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include <lib/datewidget.h>
#include <lib/flowlayout.h>
#include <lib/paintutils.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
#include <lib/timeutils.h>
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
// KDE
#include <kratingwidget.h>
// Local
#include <lib/semanticinfo/abstractsemanticinfobackend.h>
#include <lib/semanticinfo/tagmodel.h>
#endif
namespace Gwenview
{
@ -263,220 +255,6 @@ void DateFilterWidget::applyDateFilter()
d->mFilter->setDate(d->mDateWidget->date());
}
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
/**
* An AbstractSortedDirModelFilter which filters on file ratings
*/
class RatingFilter : public AbstractSortedDirModelFilter
{
public:
enum Mode {
GreaterOrEqual,
Equal,
LessOrEqual
};
RatingFilter(SortedDirModel* model)
: AbstractSortedDirModelFilter(model)
, mRating(0)
, mMode(GreaterOrEqual) {}
virtual bool needsSemanticInfo() const
{
return true;
}
virtual bool acceptsIndex(const QModelIndex& index) const
{
SemanticInfo info = model()->semanticInfoForSourceIndex(index);
switch (mMode) {
case GreaterOrEqual:
return info.mRating >= mRating;
case Equal:
return info.mRating == mRating;
default: /* LessOrEqual */
return info.mRating <= mRating;
}
}
void setRating(int value)
{
mRating = value;
model()->applyFilters();
}
void setMode(Mode mode)
{
mMode = mode;
model()->applyFilters();
}
private:
int mRating;
Mode mMode;
};
struct RatingWidgetPrivate
{
KComboBox* mModeComboBox;
KRatingWidget* mRatingWidget;
QPointer<RatingFilter> mFilter;
};
RatingFilterWidget::RatingFilterWidget(SortedDirModel* model)
: d(new RatingWidgetPrivate)
{
d->mModeComboBox = new KComboBox;
d->mModeComboBox->addItem(i18n("Rating >="), RatingFilter::GreaterOrEqual);
d->mModeComboBox->addItem(i18n("Rating =") , RatingFilter::Equal);
d->mModeComboBox->addItem(i18n("Rating <="), RatingFilter::LessOrEqual);
d->mRatingWidget = new KRatingWidget;
d->mRatingWidget->setHalfStepsEnabled(true);
d->mRatingWidget->setMaxRating(10);
QHBoxLayout* layout = new QHBoxLayout(this);
layout->setMargin(0);
layout->addWidget(d->mModeComboBox);
layout->addWidget(d->mRatingWidget);
d->mFilter = new RatingFilter(model);
QObject::connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)),
SLOT(updateFilterMode()));
QObject::connect(d->mRatingWidget, SIGNAL(ratingChanged(int)),
SLOT(slotRatingChanged(int)));
updateFilterMode();
}
RatingFilterWidget::~RatingFilterWidget()
{
delete d->mFilter;
delete d;
}
void RatingFilterWidget::slotRatingChanged(int value)
{
d->mFilter->setRating(value);
}
void RatingFilterWidget::updateFilterMode()
{
QVariant data = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex());
d->mFilter->setMode(RatingFilter::Mode(data.toInt()));
}
/**
* An AbstractSortedDirModelFilter which filters on associated tags
*/
class TagFilter : public AbstractSortedDirModelFilter
{
public:
TagFilter(SortedDirModel* model)
: AbstractSortedDirModelFilter(model)
, mWantMatchingTag(true)
{}
virtual bool needsSemanticInfo() const
{
return true;
}
virtual bool acceptsIndex(const QModelIndex& index) const
{
if (mTag.isEmpty()) {
return true;
}
SemanticInfo info = model()->semanticInfoForSourceIndex(index);
if (mWantMatchingTag) {
return info.mTags.contains(mTag);
} else {
return !info.mTags.contains(mTag);
}
}
void setTag(const SemanticInfoTag& tag)
{
mTag = tag;
model()->applyFilters();
}
void setWantMatchingTag(bool value)
{
mWantMatchingTag = value;
model()->applyFilters();
}
private:
SemanticInfoTag mTag;
bool mWantMatchingTag;
};
struct TagFilterWidgetPrivate
{
KComboBox* mModeComboBox;
QComboBox* mTagComboBox;
QPointer<TagFilter> mFilter;
};
TagFilterWidget::TagFilterWidget(SortedDirModel* model)
: d(new TagFilterWidgetPrivate)
{
d->mFilter = new TagFilter(model);
d->mModeComboBox = new KComboBox;
d->mModeComboBox->addItem(i18n("Tagged"), QVariant(true));
d->mModeComboBox->addItem(i18n("Not Tagged"), QVariant(false));
d->mTagComboBox = new QComboBox;
QHBoxLayout* layout = new QHBoxLayout(this);
layout->setMargin(0);
layout->addWidget(d->mModeComboBox);
layout->addWidget(d->mTagComboBox);
AbstractSemanticInfoBackEnd* backEnd = model->semanticInfoBackEnd();
backEnd->refreshAllTags();
TagModel* tagModel = TagModel::createAllTagsModel(this, backEnd);
QCompleter* completer = new QCompleter(d->mTagComboBox);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setModel(tagModel);
d->mTagComboBox->setCompleter(completer);
d->mTagComboBox->setInsertPolicy(QComboBox::NoInsert);
d->mTagComboBox->setEditable(true);
d->mTagComboBox->setModel(tagModel);
d->mTagComboBox->setCurrentIndex(-1);
connect(d->mTagComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateTagSetFilter()));
connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateTagSetFilter()));
QTimer::singleShot(0, d->mTagComboBox, SLOT(setFocus()));
}
TagFilterWidget::~TagFilterWidget()
{
delete d->mFilter;
delete d;
}
void TagFilterWidget::updateTagSetFilter()
{
QModelIndex index = d->mTagComboBox->model()->index(d->mTagComboBox->currentIndex(), 0);
if (!index.isValid()) {
kWarning() << "Invalid index";
return;
}
SemanticInfoTag tag = index.data(TagModel::TagRole).toString();
d->mFilter->setTag(tag);
bool wantMatchingTag = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex()).toBool();
d->mFilter->setWantMatchingTag(wantMatchingTag);
}
#endif
/**
* A container for all filter widgets. It features a close button on the right.
@ -566,10 +344,6 @@ FilterController::FilterController(QFrame* frame, SortedDirModel* dirModel)
d->addAction(i18nc("@action:inmenu", "Filter by Name"), SLOT(addFilterByName()));
d->addAction(i18nc("@action:inmenu", "Filter by Date"), SLOT(addFilterByDate()));
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
d->addAction(i18nc("@action:inmenu", "Filter by Rating"), SLOT(addFilterByRating()));
d->addAction(i18nc("@action:inmenu", "Filter by Tag"), SLOT(addFilterByTag()));
#endif
}
FilterController::~FilterController()
@ -592,17 +366,6 @@ void FilterController::addFilterByDate()
d->addFilter(new DateFilterWidget(d->mDirModel));
}
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
void FilterController::addFilterByRating()
{
d->addFilter(new RatingFilterWidget(d->mDirModel));
}
void FilterController::addFilterByTag()
{
d->addFilter(new TagFilterWidget(d->mDirModel));
}
#endif
void FilterController::slotFilterWidgetClosed()
{

View file

@ -70,38 +70,6 @@ private:
DateFilterWidgetPrivate* const d;
};
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
struct RatingWidgetPrivate;
class RatingFilterWidget : public QWidget
{
Q_OBJECT
public:
RatingFilterWidget(SortedDirModel*);
~RatingFilterWidget();
private Q_SLOTS:
void slotRatingChanged(int value);
void updateFilterMode();
private:
RatingWidgetPrivate* const d;
};
struct TagFilterWidgetPrivate;
class TagFilterWidget : public QWidget
{
Q_OBJECT
public:
TagFilterWidget(SortedDirModel*);
~TagFilterWidget();
private Q_SLOTS:
void updateTagSetFilter();
private:
TagFilterWidgetPrivate* const d;
};
#endif
struct FilterControllerPrivate;
/**
@ -120,10 +88,6 @@ public:
private Q_SLOTS:
void addFilterByName();
void addFilterByDate();
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
void addFilterByRating();
void addFilterByTag();
#endif
void slotFilterWidgetClosed();
private:

View file

@ -45,8 +45,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include <lib/historymodel.h>
#include <lib/hud/hudmessagebubble.h>
#include <lib/mimetypeutils.h>
#include <lib/semanticinfo/semanticinfodirmodel.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
#include <lib/transformimageoperation.h>
#include <mainwindow.h>
#include <saveallhelper.h>
@ -341,16 +340,6 @@ void GvCore::rotateRight(const KUrl& url)
applyTransform(url, ROT_90);
}
void GvCore::setRating(const KUrl& url, int rating)
{
QModelIndex index = d->mDirModel->indexForUrl(url);
if (!index.isValid()) {
kWarning() << "invalid index!";
return;
}
d->mDirModel->setData(index, rating, SemanticInfoDirModel::RatingRole);
}
static void clearModel(QAbstractItemModel* model)
{
model->removeRows(0, model->rowCount());

View file

@ -72,7 +72,6 @@ public Q_SLOTS:
void saveAs(const KUrl&);
void rotateLeft(const KUrl&);
void rotateRight(const KUrl&);
void setRating(const KUrl&, int);
private Q_SLOTS:
void slotConfigChanged();

View file

@ -50,7 +50,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include <lib/jpegcontent.h>
#include <lib/mimetypeutils.h>
#include <lib/timeutils.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
namespace Gwenview
{

View file

@ -76,9 +76,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "kipiexportaction.h"
#include "kipiinterface.h"
#endif
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
#include "semanticinfocontextmanageritem.h"
#endif
#include "preloader.h"
#include "savebar.h"
#include "sidebar.h"
@ -99,7 +96,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <lib/print/printhelper.h>
#include <lib/slideshow.h>
#include <lib/signalblocker.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
#include <lib/thumbnailprovider/thumbnailprovider.h>
#include <lib/thumbnailview/thumbnailbarview.h>
#include <lib/thumbnailview/thumbnailview.h>
@ -519,10 +516,6 @@ struct MainWindow::Private
InfoContextManagerItem* infoItem = new InfoContextManagerItem(mContextManager);
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
SemanticInfoContextManagerItem* semanticInfoItem = 0;
semanticInfoItem = new SemanticInfoContextManagerItem(mContextManager, actionCollection, mViewMainPage);
#endif
ImageOpsContextManagerItem* imageOpsItem =
new ImageOpsContextManagerItem(mContextManager, q);
@ -540,11 +533,6 @@ struct MainWindow::Private
page = new SideBarPage(i18n("Information"));
page->setObjectName(QLatin1String("information"));
page->addWidget(infoItem->widget());
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
if (semanticInfoItem) {
page->addWidget(semanticInfoItem->widget());
}
#endif
mSideBar->addPage(page);
page = new SideBarPage(i18n("Operations"));

View file

@ -1,466 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
// Self
#include "semanticinfocontextmanageritem.moc"
// Qt
#include <QEvent>
#include <QPainter>
#include <QShortcut>
#include <QSignalMapper>
#include <QStyle>
#include <QTimer>
// KDE
#include <KAction>
#include <KActionCategory>
#include <KActionCollection>
#include <KDebug>
#include <KDialog>
#include <KLocale>
#include <KRatingPainter>
// Local
#include "viewmainpage.h"
#include "sidebar.h"
#include "ui_semanticinfosidebaritem.h"
#include "ui_semanticinfodialog.h"
#include <lib/contextmanager.h>
#include <lib/documentview/documentview.h>
#include <lib/eventwatcher.h>
#include <lib/hud/hudwidget.h>
#include <lib/signalblocker.h>
#include <lib/widgetfloater.h>
#include <lib/semanticinfo/abstractsemanticinfobackend.h>
#include <lib/semanticinfo/semanticinfodirmodel.h>
#include <lib/semanticinfo/sorteddirmodel.h>
namespace Gwenview
{
static const int RATING_INDICATOR_HIDE_DELAY = 2000;
struct SemanticInfoDialog : public KDialog, public Ui_SemanticInfoDialog
{
SemanticInfoDialog(QWidget* parent)
: KDialog(parent)
{
setButtons(None);
QWidget* mainWidget = new QWidget;
setMainWidget(mainWidget);
setupUi(mainWidget);
mainWidget->layout()->setMargin(0);
setWindowTitle(mainWidget->windowTitle());
restoreDialogSize(configGroup());
}
~SemanticInfoDialog()
{
KConfigGroup group = configGroup();
saveDialogSize(group);
}
KConfigGroup configGroup() const
{
KSharedConfigPtr config = KGlobal::config();
return KConfigGroup(config, "SemanticInfoDialog");
}
};
/**
* A QGraphicsPixmapItem-like class, but which inherits from QGraphicsWidget
*/
class GraphicsPixmapWidget : public QGraphicsWidget
{
public:
void setPixmap(const QPixmap& pix)
{
mPix = pix;
setMinimumSize(pix.size());
}
void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
{
painter->drawPixmap(
(size().width() - mPix.width()) / 2,
(size().height() - mPix.height()) / 2,
mPix);
}
private:
QPixmap mPix;
};
class RatingIndicator : public HudWidget
{
public:
RatingIndicator()
: HudWidget()
, mPixmapWidget(new GraphicsPixmapWidget)
, mDeleteTimer(new QTimer(this))
{
updatePixmap(0);
setOpacity(0);
init(mPixmapWidget, OptionNone);
mDeleteTimer->setInterval(RATING_INDICATOR_HIDE_DELAY);
mDeleteTimer->setSingleShot(true);
connect(mDeleteTimer, SIGNAL(timeout()), SLOT(fadeOut()));
connect(this, SIGNAL(fadedOut()), SLOT(deleteLater()));
}
void setRating(int rating)
{
updatePixmap(rating);
update();
mDeleteTimer->start();
fadeIn();
}
private:
GraphicsPixmapWidget* mPixmapWidget;
QTimer* mDeleteTimer;
void updatePixmap(int rating)
{
KRatingPainter ratingPainter;
const int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
QPixmap pix(iconSize * 5 + ratingPainter.spacing() * 4, iconSize);
pix.fill(Qt::transparent);
{
QPainter painter(&pix);
ratingPainter.paint(&painter, pix.rect(), rating);
}
mPixmapWidget->setPixmap(pix);
}
};
struct SemanticInfoContextManagerItemPrivate : public Ui_SemanticInfoSideBarItem
{
SemanticInfoContextManagerItem* q;
SideBarGroup* mGroup;
KActionCollection* mActionCollection;
ViewMainPage* mViewMainPage;
QPointer<SemanticInfoDialog> mSemanticInfoDialog;
TagInfo mTagInfo;
KAction* mEditTagsAction;
QSignalMapper* mRatingMapper;
/** A list of all actions, so that we can disable them when necessary */
QList<KAction*> mActions;
QPointer<RatingIndicator> mRatingIndicator;
void setupGroup()
{
mGroup = new SideBarGroup(i18n("Semantic Information"));
q->setWidget(mGroup);
EventWatcher::install(mGroup, QEvent::Show, q, SLOT(update()));
QWidget* container = new QWidget;
setupUi(container);
container->layout()->setMargin(0);
mGroup->addWidget(container);
QObject::connect(mRatingWidget, SIGNAL(ratingChanged(int)),
q, SLOT(slotRatingChanged(int)));
QObject::connect(mRatingMapper, SIGNAL(mapped(int)),
mRatingWidget, SLOT(setRating(int)));
mDescriptionTextEdit->installEventFilter(q);
QObject::connect(mTagLabel, SIGNAL(linkActivated(QString)),
mEditTagsAction, SLOT(trigger()));
}
void setupActions()
{
KActionCategory* edit = new KActionCategory(i18nc("@title actions category", "Edit"), mActionCollection);
mEditTagsAction = edit->addAction("edit_tags");
mEditTagsAction->setText(i18nc("@action", "Edit Tags"));
mEditTagsAction->setShortcut(Qt::CTRL | Qt::Key_T);
QObject::connect(mEditTagsAction, SIGNAL(triggered()),
q, SLOT(showSemanticInfoDialog()));
mActions << mEditTagsAction;
mRatingMapper = new QSignalMapper(q);
for (int rating = 0; rating <= 5; ++rating) {
KAction* action = edit->addAction(QString("rate_%1").arg(rating));
if (rating == 0) {
action->setText(i18nc("@action Rating value of zero", "Zero"));
} else {
action->setText(QString(rating, QChar(0x22C6))); /* 0x22C6 is the 'star' character */
}
action->setShortcut(Qt::Key_0 + rating);
QObject::connect(action, SIGNAL(triggered()), mRatingMapper, SLOT(map()));
mRatingMapper->setMapping(action, rating * 2);
mActions << action;
}
QObject::connect(mRatingMapper, SIGNAL(mapped(int)), q, SLOT(slotRatingChanged(int)));
}
void updateTagLabel()
{
if (q->contextManager()->selectedFileItemList().isEmpty()) {
mTagLabel->clear();
return;
}
AbstractSemanticInfoBackEnd* backEnd = q->contextManager()->dirModel()->semanticInfoBackEnd();
TagInfo::ConstIterator
it = mTagInfo.constBegin(),
end = mTagInfo.constEnd();
QMap<QString, QString> labelMap;
for (; it != end; ++it) {
SemanticInfoTag tag = it.key();
QString label = backEnd->labelForTag(tag);
if (!it.value()) {
// Tag is not present for all urls
label += '*';
}
labelMap[label.toLower()] = label;
}
QStringList labels(labelMap.values());
QString editLink = i18n("Edit");
QString text = labels.join(", ") + QString(" <a href='edit'>%1</a>").arg(editLink);
mTagLabel->setText(text);
}
void updateSemanticInfoDialog()
{
mSemanticInfoDialog->mTagWidget->setEnabled(!q->contextManager()->selectedFileItemList().isEmpty());
mSemanticInfoDialog->mTagWidget->setTagInfo(mTagInfo);
}
};
SemanticInfoContextManagerItem::SemanticInfoContextManagerItem(ContextManager* manager, KActionCollection* actionCollection, ViewMainPage* viewMainPage)
: AbstractContextManagerItem(manager)
, d(new SemanticInfoContextManagerItemPrivate)
{
d->q = this;
d->mActionCollection = actionCollection;
d->mViewMainPage = viewMainPage;
connect(contextManager(), SIGNAL(selectionChanged()),
SLOT(slotSelectionChanged()));
connect(contextManager(), SIGNAL(selectionDataChanged()),
SLOT(update()));
connect(contextManager(), SIGNAL(currentDirUrlChanged(KUrl)),
SLOT(update()));
d->setupActions();
d->setupGroup();
}
SemanticInfoContextManagerItem::~SemanticInfoContextManagerItem()
{
delete d;
}
inline int ratingForVariant(const QVariant& variant)
{
if (variant.isValid()) {
return variant.toInt();
} else {
return 0;
}
}
void SemanticInfoContextManagerItem::slotSelectionChanged()
{
update();
}
void SemanticInfoContextManagerItem::update()
{
KFileItemList itemList = contextManager()->selectedFileItemList();
bool first = true;
int rating = 0;
QString description;
SortedDirModel* dirModel = contextManager()->dirModel();
// This hash stores for how many items the tag is present
// If you have 3 items, and only 2 have the "Holiday" tag,
// then tagHash["Holiday"] will be 2 at the end of the loop.
typedef QHash<QString, int> TagHash;
TagHash tagHash;
Q_FOREACH(const KFileItem & item, itemList) {
QModelIndex index = dirModel->indexForItem(item);
QVariant value = dirModel->data(index, SemanticInfoDirModel::RatingRole);
if (first) {
rating = ratingForVariant(value);
} else if (rating != ratingForVariant(value)) {
// Ratings aren't the same, reset
rating = 0;
}
QString indexDescription = index.data(SemanticInfoDirModel::DescriptionRole).toString();
if (first) {
description = indexDescription;
} else if (description != indexDescription) {
description.clear();
}
// Fill tagHash, incrementing the tag count if it's already there
TagSet tagSet = TagSet::fromVariant(index.data(SemanticInfoDirModel::TagsRole));
Q_FOREACH(const QString & tag, tagSet) {
TagHash::Iterator it = tagHash.find(tag);
if (it == tagHash.end()) {
tagHash[tag] = 1;
} else {
++it.value();
}
}
first = false;
}
{
SignalBlocker blocker(d->mRatingWidget);
d->mRatingWidget->setRating(rating);
}
d->mDescriptionTextEdit->setText(description);
// Init tagInfo from tagHash
d->mTagInfo.clear();
int itemCount = itemList.count();
TagHash::ConstIterator
it = tagHash.constBegin(),
end = tagHash.constEnd();
for (; it != end; ++it) {
QString tag = it.key();
int count = it.value();
d->mTagInfo[tag] = count == itemCount;
}
bool enabled = !contextManager()->selectedFileItemList().isEmpty();
Q_FOREACH(KAction * action, d->mActions) {
action->setEnabled(enabled);
}
d->updateTagLabel();
if (d->mSemanticInfoDialog) {
d->updateSemanticInfoDialog();
}
}
void SemanticInfoContextManagerItem::slotRatingChanged(int rating)
{
KFileItemList itemList = contextManager()->selectedFileItemList();
// Show rating indicator in view mode, and only if sidebar is not visible
if (d->mViewMainPage->isVisible() && !d->mRatingWidget->isVisible()) {
if (!d->mRatingIndicator.data()) {
d->mRatingIndicator = new RatingIndicator;
d->mViewMainPage->showMessageWidget(d->mRatingIndicator, Qt::AlignBottom | Qt::AlignHCenter);
}
d->mRatingIndicator->setRating(rating);
}
SortedDirModel* dirModel = contextManager()->dirModel();
Q_FOREACH(const KFileItem & item, itemList) {
QModelIndex index = dirModel->indexForItem(item);
dirModel->setData(index, rating, SemanticInfoDirModel::RatingRole);
}
}
void SemanticInfoContextManagerItem::storeDescription()
{
if (!d->mDescriptionTextEdit->document()->isModified()) {
return;
}
d->mDescriptionTextEdit->document()->setModified(false);
QString description = d->mDescriptionTextEdit->toPlainText();
KFileItemList itemList = contextManager()->selectedFileItemList();
SortedDirModel* dirModel = contextManager()->dirModel();
Q_FOREACH(const KFileItem & item, itemList) {
QModelIndex index = dirModel->indexForItem(item);
dirModel->setData(index, description, SemanticInfoDirModel::DescriptionRole);
}
}
void SemanticInfoContextManagerItem::assignTag(const SemanticInfoTag& tag)
{
KFileItemList itemList = contextManager()->selectedFileItemList();
SortedDirModel* dirModel = contextManager()->dirModel();
Q_FOREACH(const KFileItem & item, itemList) {
QModelIndex index = dirModel->indexForItem(item);
TagSet tags = TagSet::fromVariant(dirModel->data(index, SemanticInfoDirModel::TagsRole));
if (!tags.contains(tag)) {
tags << tag;
dirModel->setData(index, tags.toVariant(), SemanticInfoDirModel::TagsRole);
}
}
}
void SemanticInfoContextManagerItem::removeTag(const SemanticInfoTag& tag)
{
KFileItemList itemList = contextManager()->selectedFileItemList();
SortedDirModel* dirModel = contextManager()->dirModel();
Q_FOREACH(const KFileItem & item, itemList) {
QModelIndex index = dirModel->indexForItem(item);
TagSet tags = TagSet::fromVariant(dirModel->data(index, SemanticInfoDirModel::TagsRole));
if (tags.contains(tag)) {
tags.remove(tag);
dirModel->setData(index, tags.toVariant(), SemanticInfoDirModel::TagsRole);
}
}
}
void SemanticInfoContextManagerItem::showSemanticInfoDialog()
{
if (!d->mSemanticInfoDialog) {
d->mSemanticInfoDialog = new SemanticInfoDialog(d->mGroup);
d->mSemanticInfoDialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(d->mSemanticInfoDialog->mPreviousButton, SIGNAL(clicked()),
d->mActionCollection->action("go_previous"), SLOT(trigger()));
connect(d->mSemanticInfoDialog->mNextButton, SIGNAL(clicked()),
d->mActionCollection->action("go_next"), SLOT(trigger()));
connect(d->mSemanticInfoDialog->mButtonBox, SIGNAL(rejected()),
d->mSemanticInfoDialog, SLOT(close()));
AbstractSemanticInfoBackEnd* backEnd = contextManager()->dirModel()->semanticInfoBackEnd();
d->mSemanticInfoDialog->mTagWidget->setSemanticInfoBackEnd(backEnd);
connect(d->mSemanticInfoDialog->mTagWidget, SIGNAL(tagAssigned(SemanticInfoTag)),
SLOT(assignTag(SemanticInfoTag)));
connect(d->mSemanticInfoDialog->mTagWidget, SIGNAL(tagRemoved(SemanticInfoTag)),
SLOT(removeTag(SemanticInfoTag)));
}
d->updateSemanticInfoDialog();
d->mSemanticInfoDialog->show();
}
bool SemanticInfoContextManagerItem::eventFilter(QObject*, QEvent* event)
{
if (event->type() == QEvent::FocusOut) {
storeDescription();
}
return false;
}
} // namespace

View file

@ -1,66 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
#ifndef SEMANTICINFOCONTEXTMANAGERITEM_H
#define SEMANTICINFOCONTEXTMANAGERITEM_H
// Qt
// KDE
// Local
#include "abstractcontextmanageritem.h"
#include <lib/semanticinfo/abstractsemanticinfobackend.h>
class KActionCollection;
namespace Gwenview
{
class ViewMainPage;
struct SemanticInfoContextManagerItemPrivate;
class SemanticInfoContextManagerItem : public AbstractContextManagerItem
{
Q_OBJECT
public:
SemanticInfoContextManagerItem(ContextManager*, KActionCollection*, ViewMainPage* viewMainPage);
~SemanticInfoContextManagerItem();
protected:
virtual bool eventFilter(QObject*, QEvent*);
private Q_SLOTS:
void slotSelectionChanged();
void update();
void slotRatingChanged(int rating);
void storeDescription();
void assignTag(const SemanticInfoTag&);
void removeTag(const SemanticInfoTag&);
void showSemanticInfoDialog();
private:
friend struct SemanticInfoContextManagerItemPrivate;
SemanticInfoContextManagerItemPrivate* const d;
};
} // namespace
#endif /* SEMANTICINFOCONTEXTMANAGERITEM_H */

View file

@ -1,68 +0,0 @@
<ui version="4.0" >
<class>SemanticInfoDialog</class>
<widget class="QWidget" name="SemanticInfoDialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>323</width>
<height>355</height>
</rect>
</property>
<property name="windowTitle" >
<string>Tag Editor</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" >
<item>
<widget class="Gwenview::TagWidget" native="1" name="mTagWidget" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Expanding" hsizetype="Preferred" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" >
<item>
<widget class="QPushButton" name="mPreviousButton" >
<property name="text" >
<string>Previous</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mNextButton" >
<property name="text" >
<string>Next</string>
</property>
</widget>
</item>
<item>
<widget class="KDialogButtonBox" name="mButtonBox" >
<property name="standardButtons" >
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KDialogButtonBox</class>
<extends>QDialogButtonBox</extends>
<header>kdialogbuttonbox.h</header>
</customwidget>
<customwidget>
<class>Gwenview::TagWidget</class>
<extends>QWidget</extends>
<header location="global" >lib/semanticinfo/tagwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -1,99 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SemanticInfoSideBarItem</class>
<widget class="QWidget" name="SemanticInfoSideBarItem">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>231</width>
<height>183</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Rating:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="KRatingWidget" name="mRatingWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Tags:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="mTagLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="KTextEdit" name="mDescriptionTextEdit">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="acceptRichText">
<bool>false</bool>
</property>
<property name="clickMessage">
<string>Description</string>
</property>
<property name="checkSpellingEnabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KTextEdit</class>
<extends>QTextEdit</extends>
<header>ktextedit.h</header>
</customwidget>
<customwidget>
<class>KRatingWidget</class>
<extends>QFrame</extends>
<header>kratingwidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -43,9 +43,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include <lib/thumbnailview/abstractthumbnailviewhelper.h>
#include <lib/thumbnailview/previewitemdelegate.h>
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
#include <lib/semanticinfo/tagmodel.h>
#endif
namespace Gwenview
{
@ -101,14 +98,8 @@ struct StartMainPagePrivate : public Ui_StartMainPage
void setupSearchUi()
{
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_BALOO
mTagView->setModel(TagModel::createAllTagsModel(mTagView, mGvCore->semanticInfoBackEnd()));
mTagView->show();
mTagLabel->hide();
#else
mTagView->hide();
mTagLabel->hide();
#endif
}
void updateHistoryTab()
@ -208,14 +199,6 @@ StartMainPage::~StartMainPage()
void StartMainPage::slotTagViewClicked(const QModelIndex& index)
{
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_BALOO
if (!index.isValid()) {
return;
}
// FIXME: Check label encoding
const QString tag = index.data().toString();
emit urlSelected(KUrl("tags:/" + tag));
#endif
}
void StartMainPage::applyPalette(const QPalette& newPalette)

View file

@ -95,9 +95,6 @@ void ThumbnailViewHelper::showContextMenu(QWidget* parent)
d->addActionToMenu(popup, "file_link_to");
popup.addSeparator();
d->addActionToMenu(popup, "file_open_with");
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
d->addActionToMenu(popup, "edit_tags");
#endif
popup.addSeparator();
d->addActionToMenu(popup, "file_show_properties");
}

View file

@ -52,7 +52,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <lib/gvdebug.h>
#include <lib/gwenviewconfig.h>
#include <lib/paintutils.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
#include <lib/slidecontainer.h>
#include <lib/slideshow.h>
#include <lib/statusbartoolbutton.h>

View file

@ -1,5 +1 @@
#cmakedefine Baloo_FOUND 1
#cmakedefine GWENVIEW_SEMANTICINFO_BACKEND_NONE 1
#cmakedefine GWENVIEW_SEMANTICINFO_BACKEND_FAKE 1
#cmakedefine GWENVIEW_SEMANTICINFO_BACKEND_BALOO 1
#cmakedefine KIPI_FOUND 1

View file

@ -39,7 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include <lib/kindproxymodel.h>
#include <lib/gwenviewconfig.h>
#include <lib/recursivedirmodel.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
#include <lib/thumbnailview/abstractthumbnailviewhelper.h>
#include <lib/thumbnailview/previewitemdelegate.h>
#include <documentdirfinder.h>

View file

@ -123,7 +123,6 @@ set(gwenviewlib_SRCS
iodevicejpegsourcemanager.cpp
jpegcontent.cpp
kindproxymodel.cpp
semanticinfo/sorteddirmodel.cpp
memoryutils.cpp
mimetypeutils.cpp
paintutils.cpp
@ -159,34 +158,10 @@ set(gwenviewlib_SRCS
widgetfloater.cpp
zoomslider.cpp
zoomwidget.cpp
sorteddirmodel.cpp
${GV_JPEG_DIR}/transupp.c
)
if (NOT GWENVIEW_SEMANTICINFO_BACKEND_NONE)
set(gwenviewlib_SRCS
${gwenviewlib_SRCS}
semanticinfo/abstractsemanticinfobackend.cpp
semanticinfo/semanticinfodirmodel.cpp
semanticinfo/tagitemdelegate.cpp
semanticinfo/tagmodel.cpp
semanticinfo/tagwidget.cpp
)
endif()
if (GWENVIEW_SEMANTICINFO_BACKEND_FAKE)
set(gwenviewlib_SRCS
${gwenviewlib_SRCS}
semanticinfo/fakesemanticinfobackend.cpp
)
endif()
if (GWENVIEW_SEMANTICINFO_BACKEND_BALOO)
set(gwenviewlib_SRCS
${gwenviewlib_SRCS}
semanticinfo/baloosemanticinfobackend.cpp
)
endif()
set_source_files_properties(
exiv2imageloader.cpp
imagemetainfomodel.cpp
@ -229,10 +204,4 @@ if (WIN32)
target_link_libraries(gwenviewlib ${EXPAT_LIBRARIES})
endif()
if (NOT GWENVIEW_SEMANTICINFO_BACKEND_NONE)
target_link_libraries(gwenviewlib
${BALOO_LIBRARIES}
)
endif()
install(TARGETS gwenviewlib ${INSTALL_TARGETS_DEFAULT_ARGS})

View file

@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// Local
#include <lib/document/documentfactory.h>
#include <lib/gvdebug.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
namespace Gwenview
{

View file

@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include <KFilePlacesModel>
// Local
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
namespace Gwenview
{

View file

@ -1,59 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
// Self
#include "abstractsemanticinfobackend.moc"
// Qt
#include <QStringList>
#include <QVariant>
// KDE
// Local
namespace Gwenview
{
TagSet::TagSet()
: QSet<SemanticInfoTag>() {}
TagSet::TagSet(const QSet<SemanticInfoTag>& set)
: QSet<QString>(set) {}
QVariant TagSet::toVariant() const
{
QStringList lst = toList();
return QVariant(lst);
}
TagSet TagSet::fromVariant(const QVariant& variant)
{
QStringList lst = variant.toStringList();
return TagSet::fromList(lst);
}
AbstractSemanticInfoBackEnd::AbstractSemanticInfoBackEnd(QObject* parent)
: QObject(parent)
{
qRegisterMetaType<SemanticInfo>("SemanticInfo");
}
} // namespace

View file

@ -1,104 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
#ifndef ABSTRACTSEMANTICINFOBACKEND_H
#define ABSTRACTSEMANTICINFOBACKEND_H
#include <lib/gwenviewlib_export.h>
// Qt
#include <QObject>
#include <QSet>
// KDE
// Local
class KUrl;
namespace Gwenview
{
typedef QString SemanticInfoTag;
/**
* This class represents the set of tags associated to an url.
*
* It provides convenience methods to convert to and from QVariant, which are
* useful to communicate with SemanticInfoDirModel.
*/
class GWENVIEWLIB_EXPORT TagSet : public QSet<SemanticInfoTag>
{
public:
TagSet();
TagSet(const QSet<SemanticInfoTag>&);
QVariant toVariant() const;
static TagSet fromVariant(const QVariant&);
};
/**
* A POD struct used by AbstractSemanticInfoBackEnd to store the metadata
* associated to an url.
*/
struct SemanticInfo
{
int mRating;
QString mDescription;
TagSet mTags;
};
/**
* An abstract class, used by SemanticInfoDirModel to store and retrieve metadata.
*/
class AbstractSemanticInfoBackEnd : public QObject
{
Q_OBJECT
public:
AbstractSemanticInfoBackEnd(QObject* parent);
virtual TagSet allTags() const = 0;
virtual void refreshAllTags() = 0;
virtual void storeSemanticInfo(const KUrl&, const SemanticInfo&) = 0;
virtual void retrieveSemanticInfo(const KUrl&) = 0;
virtual QString labelForTag(const SemanticInfoTag&) const = 0;
/**
* Return a tag for a label. Will emit tagAdded() if the tag had to be
* created.
*/
virtual SemanticInfoTag tagForLabel(const QString&) = 0;
Q_SIGNALS:
void semanticInfoRetrieved(const KUrl&, const SemanticInfo&);
/**
* Emitted whenever a new tag is added to allTags()
*/
void tagAdded(const SemanticInfoTag&, const QString& label);
};
} // namespace
#endif /* ABSTRACTSEMANTICINFOBACKEND_H */

View file

@ -1,121 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
Copyright 2014 Vishesh Handa <me@vhanda.in>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
// Self
#include "baloosemanticinfobackend.h"
// Local
#include <lib/gvdebug.h>
// Qt
#include <QStringList>
// KDE
#include <KDebug>
#include <KUrl>
// Baloo
#include <baloo/file.h>
#include <baloo/filefetchjob.h>
#include <baloo/filemodifyjob.h>
#include <baloo/taglistjob.h>
namespace Gwenview
{
struct BalooSemanticInfoBackend::Private
{
TagSet mAllTags;
};
BalooSemanticInfoBackend::BalooSemanticInfoBackend(QObject* parent)
: AbstractSemanticInfoBackEnd(parent)
, d(new BalooSemanticInfoBackend::Private)
{
}
BalooSemanticInfoBackend::~BalooSemanticInfoBackend()
{
delete d;
}
TagSet BalooSemanticInfoBackend::allTags() const
{
if (d->mAllTags.empty()) {
const_cast<BalooSemanticInfoBackend*>(this)->refreshAllTags();
}
return d->mAllTags;
}
void BalooSemanticInfoBackend::refreshAllTags()
{
Baloo::TagListJob* job = new Baloo::TagListJob();
job->exec();
d->mAllTags.clear();
Q_FOREACH(const QString& tag, job->tags()) {
d->mAllTags << tag;
}
}
void BalooSemanticInfoBackend::storeSemanticInfo(const KUrl& url, const SemanticInfo& semanticInfo)
{
Baloo::File file(url.toLocalFile());
file.setRating(semanticInfo.mRating);
file.setUserComment(semanticInfo.mDescription);
file.setTags(semanticInfo.mTags.toList());
Baloo::FileModifyJob* job = new Baloo::FileModifyJob(file);
job->start();
}
void BalooSemanticInfoBackend::retrieveSemanticInfo(const KUrl& url)
{
Baloo::FileFetchJob* job = new Baloo::FileFetchJob(url.toLocalFile());
connect(job, SIGNAL(finished(KJob*)), this, SLOT(slotFetchFinished(KJob*)));
job->start();
}
void BalooSemanticInfoBackend::slotFetchFinished(KJob* job)
{
Baloo::FileFetchJob* fjob = static_cast<Baloo::FileFetchJob*>(job);
Baloo::File file = fjob->file();
SemanticInfo si;
si.mRating = file.rating();
si.mDescription = file.userComment();
si.mTags = file.tags().toSet();
emit semanticInfoRetrieved(KUrl::fromLocalFile(file.url()), si);
}
QString BalooSemanticInfoBackend::labelForTag(const SemanticInfoTag& uriString) const
{
return uriString;
}
SemanticInfoTag BalooSemanticInfoBackend::tagForLabel(const QString& label)
{
return label;
}
} // namespace

View file

@ -1,71 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
Copyright 2014 Vishesh Handa <me@vhanda.in>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
#ifndef BALOOSEMANTICINFOBACKEND_H
#define BALOOSEMANTICINFOBACKEND_H
#include <lib/gwenviewlib_export.h>
// Qt
// KDE
// Local
#include "abstractsemanticinfobackend.h"
class KJob;
namespace Gwenview
{
/**
* A real metadata backend using Baloo to store and retrieve metadata.
*/
class GWENVIEWLIB_EXPORT BalooSemanticInfoBackend : public AbstractSemanticInfoBackEnd
{
Q_OBJECT
public:
BalooSemanticInfoBackend(QObject* parent);
~BalooSemanticInfoBackend();
virtual TagSet allTags() const;
virtual void refreshAllTags();
virtual void storeSemanticInfo(const KUrl&, const SemanticInfo&);
virtual void retrieveSemanticInfo(const KUrl&);
virtual QString labelForTag(const SemanticInfoTag&) const;
virtual SemanticInfoTag tagForLabel(const QString&);
private Q_SLOTS:
void slotFetchFinished(KJob* job);
private:
struct Private;
Private* const d;
};
} // namespace
#endif /* BALOOSEMANTICINFOBACKEND_H */

View file

@ -1,105 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
// Self
#include "fakesemanticinfobackend.moc"
// Qt
#include <QStringList>
// KDE
#include <KUrl>
// Local
namespace Gwenview
{
FakeSemanticInfoBackEnd::FakeSemanticInfoBackEnd(QObject* parent, InitializeMode mode)
: AbstractSemanticInfoBackEnd(parent)
, mInitializeMode(mode)
{
mAllTags
<< tagForLabel("beach")
<< tagForLabel("mountains")
<< tagForLabel("wallpaper")
;
}
void FakeSemanticInfoBackEnd::storeSemanticInfo(const KUrl& url, const SemanticInfo& semanticInfo)
{
mSemanticInfoForUrl[url] = semanticInfo;
mergeTagsWithAllTags(semanticInfo.mTags);
}
void FakeSemanticInfoBackEnd::mergeTagsWithAllTags(const TagSet& set)
{
int size = mAllTags.size();
mAllTags |= set;
if (mAllTags.size() > size) {
//emit allTagsUpdated();
}
}
TagSet FakeSemanticInfoBackEnd::allTags() const
{
return mAllTags;
}
void FakeSemanticInfoBackEnd::refreshAllTags()
{
}
void FakeSemanticInfoBackEnd::retrieveSemanticInfo(const KUrl& url)
{
if (!mSemanticInfoForUrl.contains(url)) {
QString urlString = url.url();
SemanticInfo semanticInfo;
if (mInitializeMode == InitializeRandom) {
semanticInfo.mRating = int(urlString.length()) % 6;
semanticInfo.mDescription = url.fileName();
QStringList lst = url.path().split('/');
Q_FOREACH(const QString & token, lst) {
if (!token.isEmpty()) {
semanticInfo.mTags << '#' + token.toLower();
}
}
semanticInfo.mTags << QString("#length-%1").arg(url.fileName().length());
mergeTagsWithAllTags(semanticInfo.mTags);
} else {
semanticInfo.mRating = 0;
}
mSemanticInfoForUrl[url] = semanticInfo;
}
emit semanticInfoRetrieved(url, mSemanticInfoForUrl.value(url));
}
QString FakeSemanticInfoBackEnd::labelForTag(const SemanticInfoTag& tag) const
{
return tag[1].toUpper() + tag.mid(2);
}
SemanticInfoTag FakeSemanticInfoBackEnd::tagForLabel(const QString& label)
{
return '#' + label.toLower();
}
} // namespace

View file

@ -1,71 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
#ifndef FAKESEMANTICINFOBACKEND_H
#define FAKESEMANTICINFOBACKEND_H
#include <lib/gwenviewlib_export.h>
// Qt
#include <QHash>
// KDE
#include <KUrl>
// Local
#include "abstractsemanticinfobackend.h"
namespace Gwenview
{
/**
* A fake metadata backend, useful to test the ui layer.
* It provides fake rating values based on the image url.
*/
class GWENVIEWLIB_EXPORT FakeSemanticInfoBackEnd : public AbstractSemanticInfoBackEnd
{
Q_OBJECT
public:
enum InitializeMode { InitializeEmpty, InitializeRandom };
FakeSemanticInfoBackEnd(QObject* parent, InitializeMode initializeMode);
virtual TagSet allTags() const;
virtual void refreshAllTags();
virtual void storeSemanticInfo(const KUrl&, const SemanticInfo&);
virtual void retrieveSemanticInfo(const KUrl&);
virtual QString labelForTag(const SemanticInfoTag&) const;
virtual SemanticInfoTag tagForLabel(const QString&);
private:
void mergeTagsWithAllTags(const TagSet&);
QHash<KUrl, SemanticInfo> mSemanticInfoForUrl;
InitializeMode mInitializeMode;
TagSet mAllTags;
};
} // namespace
#endif /* FAKESEMANTICINFOBACKEND_H */

View file

@ -1,258 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
// Self
#include "semanticinfodirmodel.moc"
#include <config-gwenview.h>
// Qt
#include <QHash>
// KDE
#include <KDebug>
// Local
#include "abstractsemanticinfobackend.h"
#include "../archiveutils.h"
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_FAKE
#include "fakesemanticinfobackend.h"
#elif defined(GWENVIEW_SEMANTICINFO_BACKEND_BALOO)
#include "baloosemanticinfobackend.h"
#else
#ifdef __GNUC__
#error No metadata backend defined
#endif
#endif
namespace Gwenview
{
struct SemanticInfoCacheItem
{
SemanticInfoCacheItem()
: mValid(false)
{}
QPersistentModelIndex mIndex;
bool mValid;
SemanticInfo mInfo;
};
typedef QHash<KUrl, SemanticInfoCacheItem> SemanticInfoCache;
struct SemanticInfoDirModelPrivate
{
SemanticInfoCache mSemanticInfoCache;
AbstractSemanticInfoBackEnd* mBackEnd;
};
SemanticInfoDirModel::SemanticInfoDirModel(QObject* parent)
: KDirModel(parent)
, d(new SemanticInfoDirModelPrivate)
{
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_FAKE
d->mBackEnd = new FakeSemanticInfoBackEnd(this, FakeSemanticInfoBackEnd::InitializeRandom);
#elif defined(GWENVIEW_SEMANTICINFO_BACKEND_BALOO)
d->mBackEnd = new BalooSemanticInfoBackend(this);
#endif
connect(d->mBackEnd, SIGNAL(semanticInfoRetrieved(KUrl,SemanticInfo)),
SLOT(slotSemanticInfoRetrieved(KUrl,SemanticInfo)),
Qt::QueuedConnection);
connect(this, SIGNAL(modelAboutToBeReset()),
SLOT(slotModelAboutToBeReset()));
connect(this, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int)));
}
SemanticInfoDirModel::~SemanticInfoDirModel()
{
delete d;
}
void SemanticInfoDirModel::clearSemanticInfoCache()
{
d->mSemanticInfoCache.clear();
}
bool SemanticInfoDirModel::semanticInfoAvailableForIndex(const QModelIndex& index) const
{
if (!index.isValid()) {
return false;
}
KFileItem item = itemForIndex(index);
if (item.isNull()) {
return false;
}
SemanticInfoCache::const_iterator it = d->mSemanticInfoCache.constFind(item.targetUrl());
if (it == d->mSemanticInfoCache.constEnd()) {
return false;
}
return it.value().mValid;
}
SemanticInfo SemanticInfoDirModel::semanticInfoForIndex(const QModelIndex& index) const
{
if (!index.isValid()) {
kWarning() << "invalid index";
return SemanticInfo();
}
KFileItem item = itemForIndex(index);
if (item.isNull()) {
kWarning() << "no item for index";
return SemanticInfo();
}
return d->mSemanticInfoCache.value(item.targetUrl()).mInfo;
}
void SemanticInfoDirModel::retrieveSemanticInfoForIndex(const QModelIndex& index)
{
if (!index.isValid()) {
return;
}
KFileItem item = itemForIndex(index);
if (item.isNull()) {
kWarning() << "invalid item";
return;
}
if (ArchiveUtils::fileItemIsDirOrArchive(item)) {
return;
}
SemanticInfoCacheItem cacheItem;
cacheItem.mIndex = QPersistentModelIndex(index);
d->mSemanticInfoCache[item.targetUrl()] = cacheItem;
d->mBackEnd->retrieveSemanticInfo(item.targetUrl());
}
QVariant SemanticInfoDirModel::data(const QModelIndex& index, int role) const
{
if (role == RatingRole || role == DescriptionRole || role == TagsRole) {
KFileItem item = itemForIndex(index);
if (item.isNull()) {
return QVariant();
}
SemanticInfoCache::ConstIterator it = d->mSemanticInfoCache.constFind(item.targetUrl());
if (it != d->mSemanticInfoCache.constEnd()) {
if (!it.value().mValid) {
return QVariant();
}
const SemanticInfo& info = it.value().mInfo;
if (role == RatingRole) {
return info.mRating;
} else if (role == DescriptionRole) {
return info.mDescription;
} else if (role == TagsRole) {
return info.mTags.toVariant();
} else {
// We should never reach this part
Q_ASSERT(0);
return QVariant();
}
} else {
const_cast<SemanticInfoDirModel*>(this)->retrieveSemanticInfoForIndex(index);
return QVariant();
}
} else {
return KDirModel::data(index, role);
}
}
bool SemanticInfoDirModel::setData(const QModelIndex& index, const QVariant& data, int role)
{
if (role == RatingRole || role == DescriptionRole || role == TagsRole) {
KFileItem item = itemForIndex(index);
if (item.isNull()) {
kWarning() << "no item found for this index";
return false;
}
KUrl url = item.targetUrl();
SemanticInfoCache::iterator it = d->mSemanticInfoCache.find(url);
if (it == d->mSemanticInfoCache.end()) {
kWarning() << "No index for" << url;
return false;
}
if (!it.value().mValid) {
kWarning() << "Semantic info cache for" << url << "is invalid";
return false;
}
SemanticInfo& semanticInfo = it.value().mInfo;
if (role == RatingRole) {
semanticInfo.mRating = data.toInt();
} else if (role == DescriptionRole) {
semanticInfo.mDescription = data.toString();
} else if (role == TagsRole) {
semanticInfo.mTags = TagSet::fromVariant(data);
} else {
// We should never reach this part
Q_ASSERT(0);
}
emit dataChanged(index, index);
d->mBackEnd->storeSemanticInfo(url, semanticInfo);
return true;
} else {
return KDirModel::setData(index, data, role);
}
}
void SemanticInfoDirModel::slotSemanticInfoRetrieved(const KUrl& url, const SemanticInfo& semanticInfo)
{
SemanticInfoCache::iterator it = d->mSemanticInfoCache.find(url);
if (it == d->mSemanticInfoCache.end()) {
kWarning() << "No index for" << url;
return;
}
SemanticInfoCacheItem& cacheItem = it.value();
if (!cacheItem.mIndex.isValid()) {
kWarning() << "Index for" << url << "is invalid";
return;
}
cacheItem.mInfo = semanticInfo;
cacheItem.mValid = true;
emit dataChanged(cacheItem.mIndex, cacheItem.mIndex);
}
void SemanticInfoDirModel::slotRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end)
{
for (int pos = start; pos <= end; ++pos) {
QModelIndex idx = index(pos, 0, parent);
KFileItem item = itemForIndex(idx);
if (item.isNull()) {
continue;
}
d->mSemanticInfoCache.remove(item.targetUrl());
}
}
void SemanticInfoDirModel::slotModelAboutToBeReset()
{
d->mSemanticInfoCache.clear();
}
AbstractSemanticInfoBackEnd* SemanticInfoDirModel::semanticInfoBackEnd() const
{
return d->mBackEnd;
}
} // namespace

View file

@ -1,84 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
#ifndef SEMANTICINFODIRMODEL_H
#define SEMANTICINFODIRMODEL_H
// Qt
// KDE
#include <KDirModel>
// Local
class KUrl;
namespace Gwenview
{
class AbstractSemanticInfoBackEnd;
struct SemanticInfo;
struct SemanticInfoDirModelPrivate;
/**
* Extends KDirModel by providing read/write access to image metadata such as
* rating, tags and descriptions.
*/
class SemanticInfoDirModel : public KDirModel
{
Q_OBJECT
public:
enum {
RatingRole = 0x21a43a51,
DescriptionRole = 0x26FB33FA,
TagsRole = 0x0462F0A8
};
SemanticInfoDirModel(QObject* parent);
~SemanticInfoDirModel();
void clearSemanticInfoCache();
bool semanticInfoAvailableForIndex(const QModelIndex&) const;
void retrieveSemanticInfoForIndex(const QModelIndex&);
SemanticInfo semanticInfoForIndex(const QModelIndex&) const;
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex& index, const QVariant& data, int role = Qt::EditRole);
AbstractSemanticInfoBackEnd* semanticInfoBackEnd() const;
Q_SIGNALS:
void semanticInfoRetrieved(const KUrl&, const SemanticInfo&);
private:
SemanticInfoDirModelPrivate* const d;
private Q_SLOTS:
void slotSemanticInfoRetrieved(const KUrl& url, const SemanticInfo&);
void slotRowsAboutToBeRemoved(const QModelIndex&, int, int);
void slotModelAboutToBeReset();
};
} // namespace
#endif /* SEMANTICINFODIRMODEL_H */

View file

@ -1,151 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
// Self
#include <tagitemdelegate.moc>
// Qt
#include <QAbstractItemView>
#include <QPainter>
#include <QToolButton>
// KDE
#include <KDebug>
#include <KDialog>
#include <KIconLoader>
#include <KLocale>
// Local
#include <lib/semanticinfo/tagmodel.h>
namespace Gwenview
{
TagItemDelegate::TagItemDelegate(QAbstractItemView* view)
: KWidgetItemDelegate(view, view)
{
#define pm(x) view->style()->pixelMetric(QStyle::x)
mMargin = pm(PM_ToolBarItemMargin);
mSpacing = pm(PM_ToolBarItemSpacing);
#undef pm
const int iconSize = KIconLoader::global()->currentSize(KIconLoader::Toolbar);
const QSize sz = view->style()->sizeFromContents(QStyle::CT_ToolButton, 0, QSize(iconSize, iconSize));
mButtonSize = qMax(sz.width(), sz.height());
}
QList<QWidget*> TagItemDelegate::createItemWidgets() const
{
#define initButton(x) \
(x)->setAutoRaise(true); \
setBlockedEventTypes((x), QList<QEvent::Type>() \
<< QEvent::MouseButtonPress \
<< QEvent::MouseButtonRelease \
<< QEvent::MouseButtonDblClick);
QToolButton* assignToAllButton = new QToolButton;
initButton(assignToAllButton);
assignToAllButton->setIcon(KIcon("fill-color")); /* FIXME: Probably not the appropriate icon */
assignToAllButton->setToolTip(i18nc("@info:tooltip", "Assign this tag to all selected images"));
connect(assignToAllButton, SIGNAL(clicked()), SLOT(slotAssignToAllButtonClicked()));
QToolButton* removeButton = new QToolButton;
initButton(removeButton);
removeButton->setIcon(KIcon("list-remove"));
connect(removeButton, SIGNAL(clicked()), SLOT(slotRemoveButtonClicked()));
#undef initButton
return QList<QWidget*>() << removeButton << assignToAllButton;
}
void TagItemDelegate::updateItemWidgets(const QList<QWidget*> widgets, const QStyleOptionViewItem& option, const QPersistentModelIndex& index) const
{
const bool fullyAssigned = index.data(TagModel::AssignmentStatusRole).toInt() == int(TagModel::FullyAssigned);
QToolButton* removeButton = static_cast<QToolButton*>(widgets[0]);
QToolButton* assignToAllButton = static_cast<QToolButton*>(widgets[1]);
QSize buttonSize(mButtonSize, option.rect.height() - 2 * mMargin);
removeButton->resize(buttonSize);
assignToAllButton->resize(buttonSize);
removeButton->move(option.rect.width() - mButtonSize - mMargin, mMargin);
if (fullyAssigned) {
assignToAllButton->hide();
} else {
assignToAllButton->move(removeButton->x() - mButtonSize - mSpacing, mMargin);
}
}
void TagItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
if (!index.isValid()) {
return;
}
const bool selected = option.state & QStyle::State_Selected;
const bool fullyAssigned = index.data(TagModel::AssignmentStatusRole).toInt() == int(TagModel::FullyAssigned);
itemView()->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0);
QRect textRect = option.rect;
textRect.setLeft(textRect.left() + mMargin);
textRect.setWidth(textRect.width() - mButtonSize - mMargin - mSpacing);
if (!fullyAssigned) {
textRect.setWidth(textRect.width() - mButtonSize - mSpacing);
}
painter->setPen(option.palette.color(QPalette::Normal,
selected
? QPalette::HighlightedText
: QPalette::Text));
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, index.data().toString());
}
QSize TagItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
const int width = option.fontMetrics.width(index.data().toString());
const int height = qMax(mButtonSize, option.fontMetrics.height());
return QSize(width + 2 * mMargin, height + 2 * mMargin);
}
void TagItemDelegate::slotRemoveButtonClicked()
{
const QModelIndex index = focusedIndex();
if (!index.isValid()) {
kWarning() << "!index.isValid()";
return;
}
emit removeTagRequested(index.data(TagModel::TagRole).toString());
}
void TagItemDelegate::slotAssignToAllButtonClicked()
{
const QModelIndex index = focusedIndex();
if (!index.isValid()) {
kWarning() << "!index.isValid()";
return;
}
emit assignTagToAllRequested(index.data(TagModel::TagRole).toString());
}
} // namespace

View file

@ -1,67 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
#ifndef TAGITEMDELEGATE_H
#define TAGITEMDELEGATE_H
// KDE
#include <KWidgetItemDelegate>
namespace Gwenview
{
typedef QString SemanticInfoTag;
class TagItemDelegate : public KWidgetItemDelegate
{
Q_OBJECT
public:
TagItemDelegate(QAbstractItemView* view);
protected:
virtual QList<QWidget*> createItemWidgets() const;
virtual void updateItemWidgets(const QList<QWidget*> widgets,
const QStyleOptionViewItem& option,
const QPersistentModelIndex& /*index*/) const;
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
virtual QSize sizeHint(const QStyleOptionViewItem &/*option*/,
const QModelIndex &/*index*/) const;
Q_SIGNALS:
void removeTagRequested(const SemanticInfoTag& tag);
void assignTagToAllRequested(const SemanticInfoTag& tag);
private Q_SLOTS:
void slotRemoveButtonClicked();
void slotAssignToAllButtonClicked();
private:
int mButtonSize;
int mMargin;
int mSpacing;
};
} // namespace
#endif /* TAGITEMDELEGATE_H */

View file

@ -1,128 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
// Self
#include "tagmodel.moc"
// Qt
// KDE
#include <KDebug>
#include <KIcon>
// Local
#include "abstractsemanticinfobackend.h"
namespace Gwenview
{
struct TagModelPrivate
{
AbstractSemanticInfoBackEnd* mBackEnd;
};
static QStandardItem* createItem(const SemanticInfoTag& tag, const QString& label, TagModel::AssignmentStatus status)
{
QStandardItem* item = new QStandardItem(label);
item->setData(tag, TagModel::TagRole);
item->setData(label.toLower(), TagModel::SortRole);
item->setData(status, TagModel::AssignmentStatusRole);
item->setData(KIcon("mail-tagged.png"), Qt::DecorationRole);
return item;
}
TagModel::TagModel(QObject* parent)
: QStandardItemModel(parent)
, d(new TagModelPrivate)
{
d->mBackEnd = 0;
setSortRole(SortRole);
}
TagModel::~TagModel()
{
delete d;
}
void TagModel::setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd)
{
d->mBackEnd = backEnd;
}
void TagModel::setTagSet(const TagSet& set)
{
clear();
Q_FOREACH(const SemanticInfoTag & tag, set) {
QString label = d->mBackEnd->labelForTag(tag);
QStandardItem* item = createItem(tag, label, TagModel::FullyAssigned);
appendRow(item);
}
sort(0);
}
void TagModel::addTag(const SemanticInfoTag& tag, const QString& _label, TagModel::AssignmentStatus status)
{
int row;
QString label = _label.isEmpty() ? d->mBackEnd->labelForTag(tag) : _label;
const QString sortLabel = label.toLower();
// This is not optimal, implement dichotomic search if necessary
for (row = 0; row < rowCount(); ++row) {
const QModelIndex idx = index(row, 0);
if (idx.data(SortRole).toString().compare(sortLabel) > 0) {
break;
}
}
if (row > 0) {
QStandardItem* _item = item(row - 1);
Q_ASSERT(_item);
if (_item->data(TagRole).toString() == tag) {
// Update, do not add
_item->setData(label.toLower(), SortRole);
_item->setData(status, AssignmentStatusRole);
return;
}
}
QStandardItem* _item = createItem(tag, label, status);
insertRow(row, _item);
}
void TagModel::removeTag(const SemanticInfoTag& tag)
{
// This is not optimal, implement dichotomic search if necessary
for (int row = 0; row < rowCount(); ++row) {
if (index(row, 0).data(TagRole).toString() == tag) {
removeRow(row);
return;
}
}
}
TagModel* TagModel::createAllTagsModel(QObject* parent, AbstractSemanticInfoBackEnd* backEnd)
{
TagModel* tagModel = new TagModel(parent);
tagModel->setSemanticInfoBackEnd(backEnd);
tagModel->setTagSet(backEnd->allTags());
connect(backEnd, SIGNAL(tagAdded(SemanticInfoTag,QString)),
tagModel, SLOT(addTag(SemanticInfoTag,QString)));
return tagModel;
}
} // namespace

View file

@ -1,83 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
#ifndef TAGMODEL_H
#define TAGMODEL_H
#include <lib/gwenviewlib_export.h>
// Qt
#include <QStandardItemModel>
// KDE
// Local
namespace Gwenview
{
typedef QString SemanticInfoTag;
class AbstractSemanticInfoBackEnd;
class TagSet;
struct TagModelPrivate;
class GWENVIEWLIB_EXPORT TagModel : public QStandardItemModel
{
Q_OBJECT
public:
TagModel(QObject*);
~TagModel();
enum {
TagRole = Qt::UserRole,
SortRole,
AssignmentStatusRole
};
enum AssignmentStatus {
PartiallyAssigned,
FullyAssigned
};
void setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd*);
void setTagSet(const TagSet& set);
/**
* Convenience method to create a TagModel showing all tags available in
* AbstractSemanticInfoBackEnd
*/
static TagModel* createAllTagsModel(QObject* parent, AbstractSemanticInfoBackEnd*);
public Q_SLOTS:
/**
* Add a new tag. If label is empty, backend will be queried for it
*/
void addTag(const SemanticInfoTag& tag, const QString& label = QString(), AssignmentStatus status = FullyAssigned);
void removeTag(const SemanticInfoTag& tag);
private:
TagModelPrivate* const d;
};
} // namespace
#endif /* TAGMODEL_H */

View file

@ -1,255 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
// Self
#include "tagwidget.moc"
// Qt
#include <QComboBox>
#include <QCompleter>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLineEdit>
#include <QListView>
#include <QSortFilterProxyModel>
#include <QTimer>
#include <QVBoxLayout>
// KDE
#include <KDebug>
#include <KPushButton>
// Local
#include <lib/semanticinfo/tagitemdelegate.h>
#include <lib/semanticinfo/tagmodel.h>
namespace Gwenview
{
class TagCompleterModel : public QSortFilterProxyModel
{
public:
TagCompleterModel(QObject* parent)
: QSortFilterProxyModel(parent)
{
}
void setTagInfo(const TagInfo& tagInfo)
{
mExcludedTagSet.clear();
TagInfo::ConstIterator
it = tagInfo.begin(),
end = tagInfo.end();
for (; it != end; ++it) {
if (it.value()) {
mExcludedTagSet << it.key();
}
}
invalidate();
}
void setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd)
{
setSourceModel(TagModel::createAllTagsModel(this, backEnd));
}
protected:
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent);
SemanticInfoTag tag = sourceIndex.data(TagModel::TagRole).toString();
return !mExcludedTagSet.contains(tag);
}
private:
TagSet mExcludedTagSet;
};
/**
* A simple class to eat return keys. We use it to avoid propagating the return
* key from our KLineEdit to a dialog using TagWidget.
* We can't use KLineEdit::setTrapReturnKey() because it does not play well
* with QCompleter, it only deals with KCompletion.
*/
class ReturnKeyEater : public QObject
{
public:
ReturnKeyEater(QObject* parent = 0)
: QObject(parent)
{}
protected:
virtual bool eventFilter(QObject*, QEvent* event)
{
if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
switch (keyEvent->key()) {
case Qt::Key_Return:
case Qt::Key_Enter:
return true;
default:
return false;
}
}
return false;
}
};
struct TagWidgetPrivate
{
TagWidget* q;
TagInfo mTagInfo;
QListView* mListView;
QComboBox* mComboBox;
KPushButton* mAddButton;
AbstractSemanticInfoBackEnd* mBackEnd;
TagCompleterModel* mTagCompleterModel;
TagModel* mAssignedTagModel;
void setupWidgets()
{
mListView = new QListView;
TagItemDelegate* delegate = new TagItemDelegate(mListView);
QObject::connect(delegate, SIGNAL(removeTagRequested(SemanticInfoTag)),
q, SLOT(removeTag(SemanticInfoTag)));
QObject::connect(delegate, SIGNAL(assignTagToAllRequested(SemanticInfoTag)),
q, SLOT(assignTag(SemanticInfoTag)));
mListView->setItemDelegate(delegate);
mListView->setModel(mAssignedTagModel);
mComboBox = new QComboBox;
mComboBox->setEditable(true);
mComboBox->setInsertPolicy(QComboBox::NoInsert);
mTagCompleterModel = new TagCompleterModel(q);
QCompleter* completer = new QCompleter(q);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setModel(mTagCompleterModel);
mComboBox->setCompleter(completer);
mComboBox->setModel(mTagCompleterModel);
mAddButton = new KPushButton;
mAddButton->setIcon(KIcon("list-add"));
mAddButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QObject::connect(mAddButton, SIGNAL(clicked()),
q, SLOT(addTagFromComboBox()));
QVBoxLayout* layout = new QVBoxLayout(q);
layout->setMargin(0);
layout->addWidget(mListView);
QHBoxLayout* hLayout = new QHBoxLayout;
hLayout->addWidget(mComboBox);
hLayout->addWidget(mAddButton);
layout->addLayout(hLayout);
q->setTabOrder(mComboBox, mListView);
}
void fillTagModel()
{
Q_ASSERT(mBackEnd);
mAssignedTagModel->clear();
TagInfo::ConstIterator
it = mTagInfo.constBegin(),
end = mTagInfo.constEnd();
for (; it != end; ++it) {
mAssignedTagModel->addTag(
it.key(),
QString(),
it.value() ? TagModel::FullyAssigned : TagModel::PartiallyAssigned);
}
}
void updateCompleterModel()
{
mTagCompleterModel->setTagInfo(mTagInfo);
}
};
TagWidget::TagWidget(QWidget* parent)
: QWidget(parent)
, d(new TagWidgetPrivate)
{
d->q = this;
d->mBackEnd = 0;
d->mAssignedTagModel = new TagModel(this);
d->setupWidgets();
installEventFilter(new ReturnKeyEater(this));
connect(d->mComboBox->lineEdit(), SIGNAL(returnPressed()),
SLOT(addTagFromComboBox()));
}
TagWidget::~TagWidget()
{
delete d;
}
void TagWidget::setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd* backEnd)
{
d->mBackEnd = backEnd;
d->mAssignedTagModel->setSemanticInfoBackEnd(backEnd);
d->mTagCompleterModel->setSemanticInfoBackEnd(backEnd);
}
void TagWidget::setTagInfo(const TagInfo& tagInfo)
{
d->mTagInfo = tagInfo;
d->fillTagModel();
d->updateCompleterModel();
}
void TagWidget::addTagFromComboBox()
{
Q_ASSERT(d->mBackEnd);
QString label = d->mComboBox->currentText();
if (label.isEmpty()) {
return;
}
assignTag(d->mBackEnd->tagForLabel(label.trimmed()));
// Use a QTimer because if the tag is new, it will be inserted in the model
// and QComboBox will sometimes select it. At least it does so when the
// model is empty.
QTimer::singleShot(0, d->mComboBox, SLOT(clearEditText()));
}
void TagWidget::assignTag(const SemanticInfoTag& tag)
{
d->mTagInfo[tag] = true;
d->mAssignedTagModel->addTag(tag);
d->updateCompleterModel();
emit tagAssigned(tag);
}
void TagWidget::removeTag(const SemanticInfoTag& tag)
{
d->mTagInfo.remove(tag);
d->mAssignedTagModel->removeTag(tag);
d->updateCompleterModel();
emit tagRemoved(tag);
}
} // namespace

View file

@ -1,65 +0,0 @@
// vim: set tabstop=4 shiftwidth=4 expandtab:
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
*/
#ifndef TAGWIDGET_H
#define TAGWIDGET_H
#include <lib/gwenviewlib_export.h>
// Qt
#include <QMap>
#include <QWidget>
// KDE
// Local
#include <lib/semanticinfo/abstractsemanticinfobackend.h>
namespace Gwenview
{
typedef QMap<SemanticInfoTag, bool> TagInfo;
struct TagWidgetPrivate;
class GWENVIEWLIB_EXPORT TagWidget : public QWidget
{
Q_OBJECT
public:
TagWidget(QWidget* parent = 0);
~TagWidget();
void setTagInfo(const TagInfo&);
void setSemanticInfoBackEnd(AbstractSemanticInfoBackEnd*);
Q_SIGNALS:
void tagAssigned(const SemanticInfoTag&);
void tagRemoved(const SemanticInfoTag&);
private Q_SLOTS:
void addTagFromComboBox();
void assignTag(const SemanticInfoTag& tag);
void removeTag(const SemanticInfoTag&);
private:
TagWidgetPrivate* const d;
};
} // namespace
#endif /* TAGWIDGET_H */

View file

@ -30,12 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// Local
#include <lib/archiveutils.h>
#include <lib/timeutils.h>
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_NONE
#include <KDirModel>
#else
#include "abstractsemanticinfobackend.h"
#include "semanticinfodirmodel.h"
#endif
namespace Gwenview
{
@ -58,11 +53,7 @@ AbstractSortedDirModelFilter::~AbstractSortedDirModelFilter()
struct SortedDirModelPrivate
{
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_NONE
KDirModel* mSourceModel;
#else
SemanticInfoDirModel* mSourceModel;
#endif
QStringList mBlackListedExtensions;
QList<AbstractSortedDirModelFilter*> mFilters;
QTimer mDelayedApplyFiltersTimer;
@ -73,11 +64,7 @@ SortedDirModel::SortedDirModel(QObject* parent)
: KDirSortFilterProxyModel(parent)
, d(new SortedDirModelPrivate)
{
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_NONE
d->mSourceModel = new KDirModel(this);
#else
d->mSourceModel = new SemanticInfoDirModel(this);
#endif
setSourceModel(d->mSourceModel);
d->mDelayedApplyFiltersTimer.setInterval(0);
d->mDelayedApplyFiltersTimer.setSingleShot(true);
@ -133,9 +120,6 @@ KDirLister* SortedDirModel::dirLister() const
void SortedDirModel::reload()
{
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
d->mSourceModel->clearSemanticInfoCache();
#endif
dirLister()->updateDirectory(dirLister()->url());
}
@ -205,19 +189,6 @@ bool SortedDirModel::filterAcceptsRow(int row, const QModelIndex& parent) const
return false;
}
}
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
if (!d->mSourceModel->semanticInfoAvailableForIndex(index)) {
Q_FOREACH(const AbstractSortedDirModelFilter * filter, d->mFilters) {
// Make sure we have semanticinfo, otherwise retrieve it and
// return false, we will be called again later when it is
// there.
if (filter->needsSemanticInfo()) {
d->mSourceModel->retrieveSemanticInfoForIndex(index);
return false;
}
}
}
#endif
Q_FOREACH(const AbstractSortedDirModelFilter * filter, d->mFilters) {
if (!filter->acceptsIndex(index)) {
@ -230,19 +201,9 @@ bool SortedDirModel::filterAcceptsRow(int row, const QModelIndex& parent) const
AbstractSemanticInfoBackEnd* SortedDirModel::semanticInfoBackEnd() const
{
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_NONE
return 0;
#else
return d->mSourceModel->semanticInfoBackEnd();
#endif
}
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
SemanticInfo SortedDirModel::semanticInfoForSourceIndex(const QModelIndex& sourceIndex) const
{
return d->mSourceModel->semanticInfoForIndex(sourceIndex);
}
#endif
void SortedDirModel::applyFilters()
{

View file

@ -42,9 +42,6 @@ namespace Gwenview
class AbstractSemanticInfoBackEnd;
struct SortedDirModelPrivate;
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
struct SemanticInfo;
#endif
class SortedDirModel;
class GWENVIEWLIB_EXPORT AbstractSortedDirModelFilter : public QObject
@ -107,9 +104,6 @@ public:
AbstractSemanticInfoBackEnd* semanticInfoBackEnd() const;
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
SemanticInfo semanticInfoForSourceIndex(const QModelIndex& sourceIndex) const;
#endif
bool hasDocuments() const;

View file

@ -41,9 +41,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include <KLineEdit>
#include <KLocale>
#include <KUrl>
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
#include <kratingpainter.h>
#endif
// Local
#include "archiveutils.h"
@ -53,9 +50,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include "thumbnailview.h"
#include "timeutils.h"
#include "tooltipwidget.h"
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
#include "../semanticinfo/semanticinfodirmodel.h"
#endif
// Define this to be able to fine tune the rendering of the selection
// background through a config file
@ -126,9 +120,6 @@ struct PreviewItemDelegatePrivate
QToolButton* mFullScreenButton;
QToolButton* mRotateLeftButton;
QToolButton* mRotateRightButton;
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
KRatingPainter mRatingPainter;
#endif
QPersistentModelIndex mIndexUnderCursor;
QSize mThumbnailSize;
@ -229,29 +220,10 @@ struct PreviewItemDelegatePrivate
ratingRowHeight());
}
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
int ratingFromCursorPosition(const QRect& ratingRect) const
{
const QPoint pos = mView->viewport()->mapFromGlobal(QCursor::pos());
return mRatingPainter.ratingFromPosition(ratingRect, pos);
}
#endif
bool mouseButtonEventFilter(QEvent::Type type)
{
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
const QRect rect = ratingRectFromIndexRect(mView->visualRect(mIndexUnderCursor));
const int rating = ratingFromCursorPosition(rect);
if (rating == -1) {
return false;
}
if (type == QEvent::MouseButtonRelease) {
q->setDocumentRatingRequested(urlForIndex(mIndexUnderCursor) , rating);
}
return true;
#else
return false;
#endif
}
QPoint saveButtonPosition(const QRect& itemRect) const
@ -358,12 +330,6 @@ struct PreviewItemDelegatePrivate
void drawRating(QPainter* painter, const QRect& rect, const QVariant& value)
{
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
const int rating = value.toInt();
const QRect ratingRect = ratingRectFromIndexRect(rect);
const int hoverRating = ratingFromCursorPosition(ratingRect);
mRatingPainter.paint(painter, ratingRect, rating, hoverRating);
#endif
}
bool isTextElided(const QString& text) const
@ -495,9 +461,6 @@ struct PreviewItemDelegatePrivate
int ratingRowHeight() const
{
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
return qMax(mView->fontMetrics().ascent(), int(KIconLoader::SizeSmall));
#endif
return 0;
}
@ -596,11 +559,6 @@ PreviewItemDelegate::PreviewItemDelegate(ThumbnailView* view)
connect(view, SIGNAL(rowsInsertedSignal(QModelIndex,int,int)),
SLOT(slotRowsChanged()));
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
d->mRatingPainter.setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
d->mRatingPainter.setLayoutDirection(view->layoutDirection());
d->mRatingPainter.setMaxRating(10);
#endif
connect(view, SIGNAL(thumbnailSizeChanged(QSize)),
SLOT(setThumbnailSize(QSize)));
@ -815,9 +773,6 @@ void PreviewItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
}
if (!isDirOrArchive && (d->mDetails & PreviewItemDelegate::RatingDetail)) {
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
d->drawRating(painter, rect, index.data(SemanticInfoDirModel::RatingRole));
#endif
}
#ifdef DEBUG_DRAW_CURRENT

View file

@ -32,9 +32,6 @@ gv_add_unit_test(documenttest testutils.cpp)
gv_add_unit_test(transformimageoperationtest)
gv_add_unit_test(jpegcontenttest)
gv_add_unit_test(thumbnailprovidertest testutils.cpp)
if (NOT GWENVIEW_SEMANTICINFO_BACKEND_NONE)
gv_add_unit_test(semanticinfobackendtest)
endif()
gv_add_unit_test(timeutilstest)
gv_add_unit_test(placetreemodeltest testutils.cpp)
gv_add_unit_test(urlutilstest)

View file

@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// Local
#include <lib/contextmanager.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
#include <testutils.h>
// Qt

View file

@ -1,137 +0,0 @@
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// Local
#include "semanticinfobackendtest.moc"
// Qt
#include <QSignalSpy>
// KDE
#include <KDebug>
#include <KRandom>
#include <KTemporaryFile>
#include <qtest_kde.h>
// Local
#include "testutils.h"
#include <config-gwenview.h>
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_FAKE
#include <lib/semanticinfo/fakesemanticinfobackend.h>
#elif defined(GWENVIEW_SEMANTICINFO_BACKEND_BALOO)
#include <lib/semanticinfo/baloosemanticinfobackend.h>
#else
#ifdef __GNUC__
#error No metadata backend defined
#endif
#endif
QTEST_KDEMAIN(Gwenview::SemanticInfoBackEndTest, GUI)
namespace Gwenview
{
SemanticInfoBackEndClient::SemanticInfoBackEndClient(AbstractSemanticInfoBackEnd* backEnd)
: mBackEnd(backEnd)
{
connect(backEnd, SIGNAL(semanticInfoRetrieved(KUrl,SemanticInfo)),
SLOT(slotSemanticInfoRetrieved(KUrl,SemanticInfo)));
}
void SemanticInfoBackEndClient::slotSemanticInfoRetrieved(const KUrl& url, const SemanticInfo& semanticInfo)
{
mSemanticInfoForUrl[url] = semanticInfo;
}
void SemanticInfoBackEndTest::initTestCase()
{
qRegisterMetaType<KUrl>("KUrl");
qRegisterMetaType<QString>("SemanticInfoTag");
}
void SemanticInfoBackEndTest::init()
{
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_FAKE
mBackEnd = new FakeSemanticInfoBackEnd(0, FakeSemanticInfoBackEnd::InitializeEmpty);
#elif defined(GWENVIEW_SEMANTICINFO_BACKEND_BALOO)
mBackEnd = new BalooSemanticInfoBackend(0);
#endif
}
void SemanticInfoBackEndTest::cleanup()
{
delete mBackEnd;
mBackEnd = 0;
}
/**
* Get and set the rating of a temp file
*/
void SemanticInfoBackEndTest::testRating()
{
KTemporaryFile temp;
temp.setSuffix(".metadatabackendtest");
QVERIFY(temp.open());
KUrl url;
url.setPath(temp.fileName());
SemanticInfoBackEndClient client(mBackEnd);
QSignalSpy spy(mBackEnd, SIGNAL(semanticInfoRetrieved(KUrl,SemanticInfo)));
mBackEnd->retrieveSemanticInfo(url);
QVERIFY(waitForSignal(spy));
SemanticInfo semanticInfo = client.semanticInfoForUrl(url);
QCOMPARE(semanticInfo.mRating, 0);
semanticInfo.mRating = 5;
mBackEnd->storeSemanticInfo(url, semanticInfo);
}
#if 0
// Disabled because Baloo does not work like Nepomuk: it does not create tags
// independently of files.
void SemanticInfoBackEndTest::testTagForLabel()
{
QSignalSpy spy(mBackEnd, SIGNAL(tagAdded(SemanticInfoTag,QString)));
TagSet oldAllTags = mBackEnd->allTags();
QString label = "testTagForLabel-" + KRandom::randomString(5);
SemanticInfoTag tag1 = mBackEnd->tagForLabel(label);
QVERIFY(!tag1.isEmpty());
QVERIFY(!oldAllTags.contains(tag1));
QVERIFY(mBackEnd->allTags().contains(tag1));
// This is a new tag, we should receive a signal
QCOMPARE(spy.count(), 1);
SemanticInfoTag tag2 = mBackEnd->tagForLabel(label);
QCOMPARE(tag1, tag2);
// This is not a new tag, we should not receive a signal
QCOMPARE(spy.count(), 1);
QString label2 = mBackEnd->labelForTag(tag2);
QCOMPARE(label, label2);
}
#endif
} // namespace

View file

@ -1,78 +0,0 @@
/*
Gwenview: an image viewer
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef SEMANTICINFOBACKENDTEST_H
#define SEMANTICINFOBACKENDTEST_H
// Qt
#include <QHash>
#include <QObject>
// KDE
#include <KUrl>
// Local
#include <lib/semanticinfo/abstractsemanticinfobackend.h>
namespace Gwenview
{
/**
* Helper class which gathers the metadata retrieved when
* AbstractSemanticInfoBackEnd::retrieveSemanticInfo() is called.
*/
class SemanticInfoBackEndClient : public QObject
{
Q_OBJECT
public:
SemanticInfoBackEndClient(AbstractSemanticInfoBackEnd*);
SemanticInfo semanticInfoForUrl(const KUrl& url) const
{
return mSemanticInfoForUrl.value(url);
}
private Q_SLOTS:
void slotSemanticInfoRetrieved(const KUrl&, const SemanticInfo&);
private:
QHash<KUrl, SemanticInfo> mSemanticInfoForUrl;
AbstractSemanticInfoBackEnd* mBackEnd;
};
class SemanticInfoBackEndTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void init();
void cleanup();
void testRating();
#if 0
void testTagForLabel();
#endif
private:
AbstractSemanticInfoBackEnd* mBackEnd;
};
} // namespace
#endif // SEMANTICINFOBACKENDTEST_H

View file

@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// Local
#include <testutils.h>
#include <lib/semanticinfo/sorteddirmodel.h>
#include <lib/sorteddirmodel.h>
// Qt