mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-23 18:32:53 +00:00
killed semantics support of gwenview with fire
This commit is contained in:
parent
94683c14de
commit
3bafcad0bd
44 changed files with 13 additions and 3038 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
|
@ -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>
|
|
@ -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>
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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()
|
||||
{
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue