[prev in list] [next in list] [prev in thread] [next in thread]
List: nepomuk
Subject: [Nepomuk] Nepomuk Facets - next generation (or previous generation?)
From: Sebastian_Trüg <trueg () kde ! org>
Date: 2010-09-06 20:18:59
Message-ID: 4C854CB3.8040106 () kde ! org
[Download RAW message or body]
Good evening (or whatever),
after a lot of thinking, several setbacks, and some discussion, I went
back to Alessandro's original base design where each Facet is a QWidget.
Sounds stupid but sometimes I need to go all the way myself to see it. :P
Anyway, I was not able to solve all the problems with the previous
attempts and finally:
- Facets are a GUI-centric thing and make not much sense without a GUI.
- Does a Model really make sense (I know I was the one fighting for it
before)? I don't think so anymore for several reasons:
* It is very unlikely that we ever use the facets in different views.
* Not all facets can be displayed in a list (rating makes more sense
as stars)
* Several facets need buttons for custom ranges or similar which also
do not make much sense in views.
- The new approach allows to use Facets separately or through the
FacetWidgetController. And extending should be very easy by using one
of the base classes.
Attached you find a patch for kdelibs and kdebase (dolphin) for playing
around.
Comments?
Cheers,
Sebastian
["kdebase-apps-dolphin-facets.diff" (text/plain)]
commit 522480164c1717c07cc8b458ca019b6105370bd1
Author: Sebastian Trueg <trueg@kde.org>
Date: Mon Sep 6 21:53:55 2010 +0200
Test version of the new facet panel.
diff --git a/apps/dolphin/src/CMakeLists.txt b/apps/dolphin/src/CMakeLists.txt
index 0f51f29..f69e057 100644
--- a/apps/dolphin/src/CMakeLists.txt
+++ b/apps/dolphin/src/CMakeLists.txt
@@ -112,6 +112,7 @@ set(dolphin_SRCS
panels/folders/treeviewcontextmenu.cpp
panels/folders/folderspanel.cpp
panels/folders/paneltreeview.cpp
+ panels/facets/facetpanel.cpp
search/dolphinsearchbox.cpp
settings/general/behaviorsettingspage.cpp
settings/general/contextmenusettingspage.cpp
diff --git a/apps/dolphin/src/dolphinmainwindow.cpp \
b/apps/dolphin/src/dolphinmainwindow.cpp index e58b817..10dff1d 100644
--- a/apps/dolphin/src/dolphinmainwindow.cpp
+++ b/apps/dolphin/src/dolphinmainwindow.cpp
@@ -31,6 +31,7 @@
#include "panels/folders/folderspanel.h"
#include "panels/places/placespanel.h"
#include "panels/information/informationpanel.h"
+#include "panels/facets/facetpanel.h"
#include "settings/dolphinsettings.h"
#include "settings/dolphinsettingsdialog.h"
#include "statusbar/dolphinstatusbar.h"
@@ -1519,6 +1520,21 @@ void DolphinMainWindow::setupDockWidgets()
connect(this, SIGNAL(requestItemInfo(KFileItem)),
infoPanel, SLOT(requestDelayedItemInfo(KFileItem)));
+ // setup "Facets"
+ QDockWidget* facetDock = new QDockWidget(i18nc("@title:window", "Filter"));
+ facetDock->setObjectName("facetDock");
+ facetDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+ Panel* facetPanel = new FacetPanel(facetDock);
+ connect(facetPanel, SIGNAL(urlActivated(KUrl)), this, SLOT(handleUrl(KUrl)));
+ facetDock->setWidget(facetPanel);
+
+ QAction* facetAction = facetDock->toggleViewAction();
+ facetAction->setIcon(KIcon("dialog-facet"));
+
+ addDockWidget(Qt::RightDockWidgetArea, facetDock);
+ connect(this, SIGNAL(urlChanged(KUrl)),
+ facetPanel, SLOT(setUrl(KUrl)));
+
// setup "Folders"
QDockWidget* foldersDock = new QDockWidget(i18nc("@title:window", "Folders"));
foldersDock->setObjectName("foldersDock");
@@ -1590,6 +1606,7 @@ void DolphinMainWindow::setupDockWidgets()
panelsMenu->addAction(placesAction);
panelsMenu->addAction(infoAction);
panelsMenu->addAction(foldersAction);
+ panelsMenu->addAction(facetAction);
#ifndef Q_OS_WIN
panelsMenu->addAction(terminalAction);
#endif
diff --git a/apps/dolphin/src/panels/facets/facetpanel.cpp \
b/apps/dolphin/src/panels/facets/facetpanel.cpp new file mode 100644
index 0000000..6153da3
--- /dev/null
+++ b/apps/dolphin/src/panels/facets/facetpanel.cpp
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Sebastian Trueg <trueg@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 *
+ ***************************************************************************/
+
+#include "facetpanel.h"
+
+#include <nepomuk/filequery.h>
+#include <nepomuk/facetwidget.h>
+#include <nepomuk/facetwidgetcontroller.h>
+
+#include <kfileitem.h>
+#include <kio/jobclasses.h>
+#include <kio/job.h>
+
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QTreeView>
+#include <QtGui/QPushButton>
+#include <kdebug.h>
+
+
+FacetPanel::FacetPanel(QWidget* parent)
+ : Panel(parent)
+{
+ QVBoxLayout* layout = new QVBoxLayout(this);
+ m_buttonRemoveFolderRestriction = new QPushButton( i18n( "Remove folder \
restriction" ), this ); + connect( m_buttonRemoveFolderRestriction, SIGNAL( \
clicked() ), SLOT( slotRemoveFolderRestrictionClicked() ) ); +
+ layout->addWidget(m_buttonRemoveFolderRestriction);
+
+ Nepomuk::Query::FacetWidget* dateFacet = \
Nepomuk::Query::FacetWidget::createDateFacet( this ); + \
Nepomuk::Query::FacetWidget* typeFacet = \
Nepomuk::Query::FacetWidget::createFileTypeFacet( this ); + \
Nepomuk::Query::FacetWidget* prioFacet = \
Nepomuk::Query::FacetWidget::createPriorityFacet( this ); + \
Nepomuk::Query::FacetWidget* tagFacet = Nepomuk::Query::FacetWidget::createTagFacet( \
this ); + layout->addWidget( dateFacet );
+ layout->addWidget( typeFacet );
+ layout->addWidget( prioFacet );
+ layout->addWidget( tagFacet );
+
+ m_facetController = new Nepomuk::Query::FacetWidgetController( this );
+ m_facetController->addFacetWidget( dateFacet );
+ m_facetController->addFacetWidget( typeFacet );
+ m_facetController->addFacetWidget( prioFacet );
+ m_facetController->addFacetWidget( tagFacet );
+ connect(m_facetController, SIGNAL(queryChanged(Nepomuk::Query::Query)), \
SLOT(slotQueryChanged(Nepomuk::Query::Query)) ); +
+ // init to empty panel
+ setQuery(Nepomuk::Query::Query());
+}
+
+
+FacetPanel::~FacetPanel()
+{
+}
+
+void FacetPanel::setUrl(const KUrl& url)
+{
+ kDebug() << url;
+ Panel::setUrl(url);
+
+ // disable us
+ setQuery(Nepomuk::Query::Query());
+
+ // get the query from the item
+ m_lastSetUrlStatJob = KIO::stat(url, KIO::HideProgressInfo);
+ connect(m_lastSetUrlStatJob, SIGNAL(result(KJob*)),
+ this, SLOT(slotSetUrlStatFinished(KJob*)));
+}
+
+
+void FacetPanel::setQuery(const Nepomuk::Query::Query& query)
+{
+ kDebug() << query << query.isValid();
+
+ if (query.isValid()) {
+ m_buttonRemoveFolderRestriction->setVisible( query.isFileQuery() && \
!query.toFileQuery().includeFolders().isEmpty() ); + \
m_facetController->setQuery( query ); + kDebug() << "Rest query after facets:" \
<< m_facetController->baseQuery(); + setEnabled(true);
+ }
+ else {
+ setEnabled(false);
+ }
+}
+
+
+void FacetPanel::slotSetUrlStatFinished(KJob* job)
+{
+ m_lastSetUrlStatJob = 0;
+ kDebug() << url();
+ const KIO::UDSEntry uds = static_cast<KIO::StatJob*>(job)->statResult();
+ const QString nepomukQueryStr = uds.stringValue( \
KIO::UDSEntry::UDS_NEPOMUK_QUERY ); + kDebug() << nepomukQueryStr;
+ Nepomuk::Query::FileQuery nepomukQuery;
+ if ( !nepomukQueryStr.isEmpty() ) {
+ nepomukQuery = Nepomuk::Query::Query::fromString( nepomukQueryStr );
+ }
+ else if ( url().isLocalFile() ) {
+ // fallback query for local file URLs
+ nepomukQuery.addIncludeFolder(url());
+ }
+ kDebug() << nepomukQuery;
+ setQuery(nepomukQuery);
+}
+
+
+void FacetPanel::slotQueryChanged(const Nepomuk::Query::Query& query)
+{
+ kDebug() << query;
+ emit urlActivated(query.toSearchUrl());
+}
+
+
+void FacetPanel::slotRemoveFolderRestrictionClicked()
+{
+ Nepomuk::Query::FileQuery query = m_facetController->baseQuery();
+ query.setIncludeFolders( KUrl::List() );
+ query.setExcludeFolders( KUrl::List() );
+ m_facetController->setBaseQuery( query );
+ slotQueryChanged(m_facetController->constructQuery());
+}
diff --git a/apps/dolphin/src/panels/facets/facetpanel.h \
b/apps/dolphin/src/panels/facets/facetpanel.h new file mode 100644
index 0000000..c326e42
--- /dev/null
+++ b/apps/dolphin/src/panels/facets/facetpanel.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Sebastian Trueg <trueg@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 FACETPANEL_H
+#define FACETPANEL_H
+
+#include "../panel.h"
+#include <nepomuk/query.h>
+
+class KJob;
+class QPushButton;
+
+namespace Nepomuk {
+ namespace Query {
+ class FacetWidgetController;
+ }
+}
+
+class FacetPanel : public Panel
+{
+ Q_OBJECT
+
+public:
+ FacetPanel(QWidget* parent = 0);
+ ~FacetPanel();
+
+public slots:
+ void setUrl(const KUrl& url);
+ void setQuery(const Nepomuk::Query::Query& query);
+
+private Q_SLOTS:
+ void slotSetUrlStatFinished(KJob*);
+ void slotQueryChanged(const Nepomuk::Query::Query&);
+ void slotRemoveFolderRestrictionClicked();
+
+private:
+ KJob* m_lastSetUrlStatJob;
+
+ QPushButton* m_buttonRemoveFolderRestriction;
+ Nepomuk::Query::FacetWidgetController* m_facetController;
+};
+
+#endif // FACETPANEL_H
["kdelibs-nepomuk-query-facets.diff" (text/plain)]
commit 4716d19171e4308bb23dc94d5bf34e33d4254d8b
Author: Sebastian Trueg <trueg@kde.org>
Date: Mon Sep 6 21:47:48 2010 +0200
Finally a facet API:
A facet is a widget which provides a Term.
These terms will be combined through the FacetWidgetController.
A bunch of specialized FacetWidgets and static FacetWidget creation
methods make the life easier for app developers.
diff --git a/nepomuk/query/CMakeLists.txt b/nepomuk/query/CMakeLists.txt
index 86b7376..e4a5185 100644
--- a/nepomuk/query/CMakeLists.txt
+++ b/nepomuk/query/CMakeLists.txt
@@ -36,6 +36,14 @@ set(nepomukquery_SRC
../core/dbusconnectionpool.cpp
queryserializer.cpp
standardqueries.cpp
+ facetwidget.cpp
+ listfacetwidget.cpp
+ rangedfacetwidget.cpp
+ simplelistfacetwidget.cpp
+ dynamiclistfacetwidget.cpp
+ daterange.cpp
+ daterangeselectionwidget.cpp
+ facetwidgetcontroller.cpp
)
soprano_add_ontology(nepomukquery_SRC \
"${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nie/nie.trig" "NIE" "Nepomuk::Vocabulary" \
"trig") @@ -59,6 +67,8 @@ qt4_add_dbus_interface(nepomukquery_SRC
org.kde.nepomuk.Query.xml
queryinterface)
+kde4_add_ui_files(nepomukquery_SRC daterangeselectionwidget.ui)
+
kde4_add_library(nepomukquery ${LIBRARY_TYPE} ${nepomukquery_SRC})
set_target_properties(nepomukquery PROPERTIES VERSION ${GENERIC_LIB_VERSION} \
SOVERSION ${GENERIC_LIB_SOVERSION}) @@ -67,6 +77,7 @@ \
target_link_libraries(nepomukquery ${QT_QTCORE_LIBRARY}
${SOPRANO_LIBRARIES}
kdecore
+ kdeui
nepomuk
)
@@ -91,5 +102,11 @@ install(FILES
standardqueries.h
nepomukquery_export.h
standardqueries.h
+ facetwidget.h
+ listfacetwidget.h
+ rangedfacetwidget.h
+ simplelistfacetwidget.h
+ dynamiclistfacetwidget.h
+ facetwidgetcontroller.h
DESTINATION ${INCLUDE_INSTALL_DIR}/nepomuk COMPONENT Devel
)
diff --git a/nepomuk/query/daterange.cpp b/nepomuk/query/daterange.cpp
new file mode 100644
index 0000000..123d62b
--- /dev/null
+++ b/nepomuk/query/daterange.cpp
@@ -0,0 +1,151 @@
+/*
+ Copyright (c) 2009-2010 Sebastian Trueg <trueg@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) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor approved
+ by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "daterange.h"
+
+#include "kglobal.h"
+#include "klocale.h"
+#include "kcalendarsystem.h"
+
+#include <QtCore/QSharedData>
+
+
+class DateRange::Private : public QSharedData
+{
+public:
+ QDate m_start;
+ QDate m_end;
+};
+
+
+DateRange::DateRange( const QDate& s,
+ const QDate& e )
+ : d(new Private())
+{
+ d->m_start = s;
+ d->m_end = e;
+}
+
+
+DateRange::DateRange( const DateRange& other )
+{
+ d = other.d;
+}
+
+
+DateRange::~DateRange()
+{
+}
+
+
+DateRange& DateRange::operator=( const DateRange& other )
+{
+ d = other.d;
+ return *this;
+}
+
+
+QDate DateRange::start() const
+{
+ return d->m_start;
+}
+
+
+QDate DateRange::end() const
+{
+ return d->m_end;
+}
+
+
+bool DateRange::isValid() const
+{
+ return d->m_start.isValid() && d->m_end.isValid() && d->m_start <= d->m_end;
+}
+
+
+// static
+DateRange DateRange::today()
+{
+ return DateRange( QDate::currentDate(), QDate::currentDate() );
+}
+
+
+namespace {
+ /**
+ * Put \p day into the week range 1...7
+ */
+ int dateModulo( int day ) {
+ day = day%7;
+ if ( day == 0 )
+ return 7;
+ else
+ return day;
+ }
+}
+
+// static
+DateRange DateRange::thisWeek()
+{
+ return weekOf( QDate::currentDate() );
+}
+
+
+// static
+DateRange DateRange::weekOf( const QDate& date )
+{
+ const int weekStartDay = KGlobal::locale()->weekStartDay();
+ const int weekEndDay = dateModulo( weekStartDay+6 );
+
+ DateRange range;
+
+ if ( weekStartDay > date.dayOfWeek() )
+ range.d->m_start = date.addDays( - (date.dayOfWeek() + 7 - weekStartDay) );
+ else
+ range.d->m_start = date.addDays( - (date.dayOfWeek() - weekStartDay) );
+
+ if ( weekEndDay < date.dayOfWeek() )
+ range.d->m_end = date.addDays( weekEndDay + 7 - date.dayOfWeek() );
+ else
+ range.d->m_end = date.addDays( weekEndDay - date.dayOfWeek() );
+
+ return range;
+}
+
+
+// static
+DateRange DateRange::thisMonth()
+{
+ return monthOf( QDate::currentDate() );
+}
+
+
+// static
+DateRange DateRange::monthOf( const QDate& date )
+{
+ return DateRange( QDate( date.year(), date.month(), 1 ),
+ QDate( date.year(), date.month(), \
KGlobal::locale()->calendar()->daysInMonth( date ) ) ); +}
+
+
+bool operator==( const DateRange& r1, const DateRange& r2 )
+{
+ return r1.start() == r2.start() && r1.end() == r2.end();
+}
diff --git a/nepomuk/query/daterange.h b/nepomuk/query/daterange.h
new file mode 100644
index 0000000..5c00de2
--- /dev/null
+++ b/nepomuk/query/daterange.h
@@ -0,0 +1,104 @@
+/*
+ Copyright (c) 2009-2010 Sebastian Trueg <trueg@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) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor approved
+ by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef _DATE_RANGE_H_
+#define _DATE_RANGE_H_
+
+#include <QtCore/QDate>
+#include <QtCore/QSharedDataPointer>
+
+/**
+ * \brief A simple data structure storing a start and an end date.
+ *
+ * \author Sebastian Trueg <trueg@kde.org>
+ */
+class DateRange
+{
+public:
+ /**
+ * Create a new range
+ */
+ DateRange( const QDate& s = QDate(),
+ const QDate& e = QDate() );
+
+ /**
+ * Copy constructor
+ */
+ DateRange( const DateRange& other );
+
+ /**
+ * Destructor
+ */
+ ~DateRange();
+
+ /**
+ * Make this range a copy of \p other
+ */
+ DateRange& operator=( const DateRange& other );
+
+ /**
+ * Start date of the range.
+ */
+ QDate start() const;
+
+ /**
+ * End date of the range.
+ */
+ QDate end() const;
+
+ /**
+ * Checks if both start and end are valid dates
+ * and if end is after start.
+ */
+ bool isValid() const;
+
+ /**
+ * \returns a DateRange with both start and end
+ * dates set to QDate::currentDate()
+ */
+ static DateRange today();
+
+ /**
+ * Takes KLocale::weekStartDay() into account.
+ */
+ static DateRange thisWeek();
+
+ /**
+ * Takes KLocale::weekStartDay() into account.
+ */
+ static DateRange weekOf( const QDate& date );
+
+ static DateRange thisMonth();
+ static DateRange monthOf( const QDate& date );
+
+private:
+ class Private;
+ QSharedDataPointer<Private> d;
+};
+
+/**
+ * Comparison operator
+ *
+ * \related DateRange
+ */
+bool operator==( const DateRange& r1, const DateRange& r2 );
+
+#endif
diff --git a/nepomuk/query/daterangeselectionwidget.cpp \
b/nepomuk/query/daterangeselectionwidget.cpp new file mode 100644
index 0000000..41c1934
--- /dev/null
+++ b/nepomuk/query/daterangeselectionwidget.cpp
@@ -0,0 +1,336 @@
+/*
+ Copyright (c) 2009 Sebastian Trueg <trueg@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) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor approved
+ by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "daterangeselectionwidget.h"
+#include "ui_daterangeselectionwidget.h"
+#include "daterange.h"
+
+#include <QtGui/QToolButton>
+#include <QtGui/QCalendarWidget>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QDateEdit>
+#include <QtGui/QTextCharFormat>
+#include <QtGui/QPalette>
+#include <QtGui/QAction>
+#include <QtGui/QMenu>
+#include <QtCore/QHash>
+
+
+class DateRangeSelectionWidget::Private : public Ui::DateRangeSelectionWidgetBase
+{
+public:
+ void _k_anytimeClicked();
+ void _k_beforeClicked();
+ void _k_afterClicked();
+ void _k_rangeClicked();
+ void _k_rangeClicked( QAction* );
+ void _k_rangeStartEdited( const QDate& date );
+ void _k_rangeEndEdited( const QDate& date );
+ void _k_calendarDateClicked( const QDate& date );
+
+ void checkButton( QAbstractButton* button );
+ void setupPopupMenus();
+
+ void updateCalendar( const DateRange& range );
+ void updateEditBoxes( const DateRange& range );
+
+ void setRange( const DateRange& range );
+
+ QAction* findRangeAction( const DateRange& range );
+
+ DateRange m_range;
+
+ QAction* m_currentRangeAction;
+ QHash<QAction*, DateRange> m_rangeActionMap;
+
+ DateRangeSelectionWidget* q;
+};
+
+
+void DateRangeSelectionWidget::Private::_k_anytimeClicked()
+{
+ checkButton( m_anytimeButton );
+ setRange( DateRange() );
+
+ emit q->rangeChanged( m_range );
+}
+
+
+void DateRangeSelectionWidget::Private::_k_beforeClicked()
+{
+ if ( m_range.end().isValid() )
+ setRange( DateRange( QDate(), m_range.end() ) );
+ else if ( m_range.start().isValid() )
+ setRange( DateRange( QDate(), m_range.start() ) );
+ else
+ setRange( DateRange( QDate(), QDate::currentDate() ) );
+
+ emit q->rangeChanged( m_range );
+}
+
+
+void DateRangeSelectionWidget::Private::_k_afterClicked()
+{
+ if ( m_range.start().isValid() )
+ setRange( DateRange( m_range.start(), QDate() ) );
+ else if ( m_range.end().isValid() )
+ setRange( DateRange( m_range.end(), QDate() ) );
+ else
+ setRange( DateRange( QDate::currentDate(), QDate() ) );
+
+ emit q->rangeChanged( m_range );
+}
+
+
+void DateRangeSelectionWidget::Private::_k_rangeClicked()
+{
+ _k_rangeClicked( m_currentRangeAction );
+}
+
+
+void DateRangeSelectionWidget::Private::_k_rangeClicked( QAction* action )
+{
+ m_currentRangeAction = action;
+ m_rangesButton->setText( action->text() );
+ setRange( m_rangeActionMap[action] );
+
+ emit q->rangeChanged( m_range );
+}
+
+
+void DateRangeSelectionWidget::Private::_k_rangeStartEdited( const QDate& date )
+{
+ if ( date > m_range.end() )
+ setRange( DateRange( date, date ) );
+ else
+ setRange( DateRange( date, m_range.end() ) );
+
+ emit q->rangeChanged( m_range );
+}
+
+
+void DateRangeSelectionWidget::Private::_k_rangeEndEdited( const QDate& date )
+{
+ if ( date < m_range.start() )
+ setRange( DateRange( date, date ) );
+ else
+ setRange( DateRange( m_range.start(), date ) );
+
+ emit q->rangeChanged( m_range );
+}
+
+
+void DateRangeSelectionWidget::Private::_k_calendarDateClicked( const QDate& date )
+{
+ if ( QApplication::keyboardModifiers() & Qt::ShiftModifier ) {
+ if ( m_range.start().isValid() &&
+ date < m_range.start() ) {
+ setRange( DateRange( date, m_range.end().isValid() ? m_range.end() : \
m_range.start() ) ); + emit q->rangeChanged( m_range );
+ }
+ else if ( m_range.end().isValid() &&
+ date < m_range.end() ) {
+ setRange( DateRange( date, m_range.end() ) );
+ emit q->rangeChanged( m_range );
+ }
+ else if ( m_range.end().isValid() &&
+ date > m_range.end() ) {
+ setRange( DateRange( m_range.start().isValid() ? m_range.start() : \
m_range.end(), date ) ); + emit q->rangeChanged( m_range );
+ }
+ else if ( m_range.start().isValid() &&
+ date > m_range.start() ) {
+ setRange( DateRange( m_range.start(), date ) );
+ emit q->rangeChanged( m_range );
+ }
+ }
+ else if ( m_beforeButton->isChecked() ) {
+ setRange( DateRange( QDate(), date ) );
+ emit q->rangeChanged( m_range );
+ }
+ else if ( m_afterButton->isChecked() ) {
+ setRange( DateRange( date, QDate() ) );
+ emit q->rangeChanged( m_range );
+ }
+ else {
+ setRange( DateRange( date, date ) );
+ emit q->rangeChanged( m_range );
+ }
+}
+
+
+void DateRangeSelectionWidget::Private::checkButton( QAbstractButton* button )
+{
+ foreach( QAbstractButton* b, m_buttonGroup->buttons() ) {
+ b->setChecked( b == button );
+ }
+}
+
+
+void DateRangeSelectionWidget::Private::setupPopupMenus()
+{
+ QMenu* menu = new QMenu(m_rangesButton);
+
+ QAction* a = new QAction( menu );
+ a->setText( i18n( "Today" ) );
+ m_rangeActionMap.insert( a, DateRange::today() );
+ menu->addAction( a );
+
+ // today is the default
+ m_currentRangeAction = a;
+
+ a = new QAction( menu );
+ a->setText( i18n( "This Week" ) );
+ m_rangeActionMap.insert( a, DateRange::thisWeek() );
+ menu->addAction( a );
+
+ a = new QAction( menu );
+ a->setText( i18n( "This Month" ) );
+ m_rangeActionMap.insert( a, DateRange::thisMonth() );
+ menu->addAction( a );
+
+ m_rangesButton->setMenu( menu );
+}
+
+
+void DateRangeSelectionWidget::Private::updateCalendar( const DateRange& range )
+{
+ m_calendar->setDateTextFormat( QDate(), QTextCharFormat() );
+ if ( range.start().isValid() )
+ m_calendar->setSelectedDate( range.start() );
+ else if ( range.end().isValid() )
+ m_calendar->setSelectedDate( range.end() );
+ else
+ m_calendar->setSelectedDate( QDate::currentDate() );
+ if ( range.isValid() ) {
+ QTextCharFormat selectedFormat;
+ selectedFormat.setBackground( q->palette().color( QPalette::Highlight ) );
+ selectedFormat.setForeground( q->palette().color( QPalette::HighlightedText \
) ); + for ( QDate date = range.start(); date <= range.end(); date = \
date.addDays( 1 ) ) { + m_calendar->setDateTextFormat( date, \
selectedFormat ); + }
+ }
+}
+
+
+void DateRangeSelectionWidget::Private::updateEditBoxes( const DateRange& range )
+{
+ m_rangeStartEdit->blockSignals( true );
+ m_rangeEndEdit->blockSignals( true );
+
+ m_rangeStartEdit->setDate( range.start() );
+ m_rangeEndEdit->setDate( range.end() );
+ m_rangeStartEdit->setEnabled( range.start().isValid() );
+ m_rangeEndEdit->setEnabled( range.end().isValid() );
+
+ m_rangeStartEdit->blockSignals( false );
+ m_rangeEndEdit->blockSignals( false );
+}
+
+
+void DateRangeSelectionWidget::Private::setRange( const DateRange& range )
+{
+ m_range = range;
+
+ if ( range.isValid() ) {
+ if ( QAction* a = findRangeAction( range ) ) {
+ m_currentRangeAction = a;
+ m_rangesButton->setText( a->text() );
+ checkButton( m_rangesButton );
+ }
+ else {
+ checkButton( 0 );
+ }
+ }
+ else if ( range.start().isValid() ) {
+ checkButton( m_afterButton );
+ }
+ else if ( range.end().isValid() ) {
+ checkButton( m_beforeButton );
+ }
+ else {
+ checkButton( m_anytimeButton );
+ }
+
+ updateCalendar( range );
+ updateEditBoxes( range );
+}
+
+
+QAction* DateRangeSelectionWidget::Private::findRangeAction( const DateRange& range \
) +{
+ // We have only 3 elements in here, thus, looping over them is ok
+ for ( QHash<QAction*, DateRange>::const_iterator it = \
m_rangeActionMap.constBegin(); + it != m_rangeActionMap.constEnd(); ++it ) {
+ if ( it.value() == range )
+ return it.key();
+ }
+ return 0;
+}
+
+
+DateRangeSelectionWidget::DateRangeSelectionWidget( QWidget* parent )
+ : QWidget( parent ),
+ d( new Private() )
+{
+ d->q = this;
+ d->setupUi( this );
+ d->setupPopupMenus();
+
+ d->m_calendar->setFirstDayOfWeek( Qt::DayOfWeek( \
KGlobal::locale()->weekStartDay() ) ); + connect( d->m_anytimeButton, SIGNAL( \
clicked() ), + this, SLOT( _k_anytimeClicked() ) );
+ connect( d->m_beforeButton, SIGNAL( clicked() ),
+ this, SLOT( _k_beforeClicked() ) );
+ connect( d->m_afterButton, SIGNAL( clicked() ),
+ this, SLOT( _k_afterClicked() ) );
+ connect( d->m_rangesButton, SIGNAL( clicked() ),
+ this, SLOT( _k_rangeClicked() ) );
+ connect( d->m_rangesButton, SIGNAL( triggered(QAction*) ),
+ this, SLOT( _k_rangeClicked(QAction*) ) );
+ connect( d->m_rangeStartEdit, SIGNAL( dateChanged( QDate ) ),
+ this, SLOT( _k_rangeStartEdited( QDate ) ) );
+ connect( d->m_rangeEndEdit, SIGNAL( dateChanged( QDate ) ),
+ this, SLOT( _k_rangeEndEdited( QDate ) ) );
+ connect( d->m_calendar, SIGNAL( clicked( QDate ) ),
+ this, SLOT( _k_calendarDateClicked( QDate ) ) );
+
+ setRange( DateRange() );
+}
+
+
+DateRangeSelectionWidget::~DateRangeSelectionWidget()
+{
+}
+
+
+DateRange DateRangeSelectionWidget::range() const
+{
+ return d->m_range;
+}
+
+
+void DateRangeSelectionWidget::setRange( const DateRange& range )
+{
+ d->setRange( range );
+}
+
+#include "daterangeselectionwidget.moc"
diff --git a/nepomuk/query/daterangeselectionwidget.h \
b/nepomuk/query/daterangeselectionwidget.h new file mode 100644
index 0000000..d99a432
--- /dev/null
+++ b/nepomuk/query/daterangeselectionwidget.h
@@ -0,0 +1,68 @@
+/*
+ Copyright (c) 2009 Sebastian Trueg <trueg@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) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor approved
+ by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef _DATE_RANGE_SELECTION_WIDGET_H_
+#define _DATE_RANGE_SELECTION_WIDGET_H_
+
+#include <QtGui/QWidget>
+#include <QtCore/QDate>
+
+class DateRange;
+class QAction;
+
+class DateRangeSelectionWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DateRangeSelectionWidget( QWidget* parent = 0 );
+ ~DateRangeSelectionWidget();
+
+ /**
+ * One of:
+ * \li a range between two valid dates
+ * \li only a valid end date: all dates before that date
+ * \li only a valid start date: all dates after that date
+ * \li invalid range: anytime
+ */
+ DateRange range() const;
+
+public Q_SLOTS:
+ void setRange( const DateRange& range );
+
+Q_SIGNALS:
+ void rangeChanged( const DateRange& range );
+
+private:
+ class Private;
+ Private* const d;
+
+ Q_PRIVATE_SLOT( d, void _k_anytimeClicked() )
+ Q_PRIVATE_SLOT( d, void _k_beforeClicked() )
+ Q_PRIVATE_SLOT( d, void _k_afterClicked() )
+ Q_PRIVATE_SLOT( d, void _k_rangeClicked() )
+ Q_PRIVATE_SLOT( d, void _k_rangeClicked( QAction* ) )
+ Q_PRIVATE_SLOT( d, void _k_rangeStartEdited( const QDate& date ) )
+ Q_PRIVATE_SLOT( d, void _k_rangeEndEdited( const QDate& date ) )
+ Q_PRIVATE_SLOT( d, void _k_calendarDateClicked( const QDate& date ) )
+};
+
+#endif
diff --git a/nepomuk/query/daterangeselectionwidget.ui \
b/nepomuk/query/daterangeselectionwidget.ui new file mode 100644
index 0000000..30a3b62
--- /dev/null
+++ b/nepomuk/query/daterangeselectionwidget.ui
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <author>Sebastian Trueg <trueg@kde.org></author>
+ <class>DateRangeSelectionWidgetBase</class>
+ <widget class="QWidget" name="DateRangeSelectionWidgetBase">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>364</width>
+ <height>240</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QToolButton" name="m_anytimeButton">
+ <property name="text">
+ <string>Anytime</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <attribute name="buttonGroup">
+ <string>m_buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="m_beforeButton">
+ <property name="text">
+ <string>Before</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <attribute name="buttonGroup">
+ <string>m_buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="m_afterButton">
+ <property name="text">
+ <string>After</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <attribute name="buttonGroup">
+ <string>m_buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="m_rangesButton">
+ <property name="text">
+ <string>Today</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::MenuButtonPopup</enum>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <attribute name="buttonGroup">
+ <string>m_buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCalendarWidget" name="m_calendar"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QDateEdit" name="m_rangeStartEdit"/>
+ </item>
+ <item>
+ <widget class="QDateEdit" name="m_rangeEndEdit"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+ <buttongroups>
+ <buttongroup name="m_buttonGroup">
+ <property name="exclusive">
+ <bool>false</bool>
+ </property>
+ </buttongroup>
+ </buttongroups>
+</ui>
diff --git a/nepomuk/query/dynamiclistfacetwidget.cpp \
b/nepomuk/query/dynamiclistfacetwidget.cpp new file mode 100644
index 0000000..8133152
--- /dev/null
+++ b/nepomuk/query/dynamiclistfacetwidget.cpp
@@ -0,0 +1,154 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dynamiclistfacetwidget.h"
+#include "resource.h"
+#include "resourcemanager.h"
+#include "resourceterm.h"
+
+#include "query.h"
+#include "comparisonterm.h"
+
+#include <Soprano/Util/AsyncQuery>
+#include <Soprano/BindingSet>
+#include <Soprano/Node>
+
+#include <QtCore/QVariant>
+
+#include "kdebug.h"
+
+
+Q_DECLARE_METATYPE(Soprano::BindingSet)
+
+
+class Nepomuk::Query::DynamicListFacetWidget::Private
+{
+public:
+ Query m_populationQuery;
+ int m_limit;
+
+ int m_moreButtonId;
+
+ Soprano::Util::AsyncQuery* m_lastQuery;
+
+ void _k_populateNextResult(Soprano::Util::AsyncQuery*);
+ void _k_populateFinished(Soprano::Util::AsyncQuery*);
+
+ DynamicListFacetWidget* q;
+};
+
+
+void Nepomuk::Query::DynamicListFacetWidget::Private::_k_populateNextResult( \
Soprano::Util::AsyncQuery* query ) +{
+ kDebug();
+ if( q->count() == m_limit ) {
+ // TODO: add the more... button
+ }
+ else {
+ q->addButton( q->titleForResult( query->currentBindings() ), \
QVariant::fromValue( query->currentBindings() ) ); + }
+ query->next();
+}
+
+
+void Nepomuk::Query::DynamicListFacetWidget::Private::_k_populateFinished( \
Soprano::Util::AsyncQuery* query ) +{
+ kDebug();
+ // TODO: disable the busy thingi (once we have one)
+}
+
+
+Nepomuk::Query::DynamicListFacetWidget::DynamicListFacetWidget( QWidget* parent )
+ : ListFacetWidget( parent ),
+ d(new Private())
+{
+ d->q = this;
+ d->m_lastQuery = 0;
+ d->m_limit = 6; // TODO: make configurable
+ d->m_moreButtonId = -1;
+}
+
+
+Nepomuk::Query::DynamicListFacetWidget::~DynamicListFacetWidget()
+{
+ delete d;
+}
+
+
+void Nepomuk::Query::DynamicListFacetWidget::setPopulationQuery( const \
Nepomuk::Query::Query& query ) +{
+ d->m_populationQuery = query;
+}
+
+
+void Nepomuk::Query::DynamicListFacetWidget::populate()
+{
+ kDebug();
+ clear();
+ if( d->m_lastQuery ) {
+ d->m_lastQuery->disconnect();
+ d->m_lastQuery = 0;
+ }
+
+ // TODO: show some busy thingi
+
+ Query query( d->m_populationQuery );
+ query.setLimit( d->m_limit+1 );
+ kDebug() << query.toSparqlQuery();
+ d->m_lastQuery = Soprano::Util::AsyncQuery::executeQuery( \
ResourceManager::instance()->mainModel(), + \
query.toSparqlQuery(), + \
Soprano::Query::QueryLanguageSparql ); + connect( d->m_lastQuery, \
SIGNAL(nextReady(Soprano::Util::AsyncQuery*)), + this, \
SLOT(_k_populateNextResult(Soprano::Util::AsyncQuery*)) ); + connect( \
d->m_lastQuery, SIGNAL(finished(Soprano::Util::AsyncQuery*)), + this, \
SLOT(_k_populateFinished(Soprano::Util::AsyncQuery*)) ); +}
+
+
+QString Nepomuk::Query::DynamicListFacetWidget::titleForResult( const \
Soprano::BindingSet& bindings ) const +{
+ return Resource( bindings[0].uri() ).genericLabel();
+}
+
+
+Nepomuk::Query::Term Nepomuk::Query::DynamicListFacetWidget::termForResult( const \
Soprano::BindingSet& bindings ) const +{
+ return ComparisonTerm( Types::Property(), ResourceTerm( bindings[0].uri() ) );
+}
+
+
+Nepomuk::Query::Term Nepomuk::Query::DynamicListFacetWidget::termForButton( int \
button, const QVariant& data ) const +{
+ Q_UNUSED(button);
+ return termForResult( data.value<Soprano::BindingSet>() );
+}
+
+
+void Nepomuk::Query::DynamicListFacetWidget::buttonClicked( int button, const \
QVariant& data ) +{
+ if( button == d->m_moreButtonId ) {
+ // TODO: open dialog
+ }
+
+ ListFacetWidget::buttonClicked( button, data );
+}
+
+#include "dynamiclistfacetwidget.moc"
diff --git a/nepomuk/query/dynamiclistfacetwidget.h \
b/nepomuk/query/dynamiclistfacetwidget.h new file mode 100644
index 0000000..bcc806c
--- /dev/null
+++ b/nepomuk/query/dynamiclistfacetwidget.h
@@ -0,0 +1,68 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NEPOMUK_QUERY_DYNAMIC_LIST_FACET_WIDGET_H_
+#define _NEPOMUK_QUERY_DYNAMIC_LIST_FACET_WIDGET_H_
+
+#include "listfacetwidget.h"
+#include "nepomukquery_export.h"
+
+namespace Soprano {
+ class BindingSet;
+ namespace Util {
+ class AsyncQuery;
+ }
+}
+
+namespace Nepomuk {
+ namespace Query {
+ class Query;
+
+ class NEPOMUKQUERY_EXPORT DynamicListFacetWidget : public ListFacetWidget
+ {
+ Q_OBJECT
+
+ public:
+ DynamicListFacetWidget( QWidget* parent = 0 );
+ virtual ~DynamicListFacetWidget();
+
+ public Q_SLOTS:
+ void setPopulationQuery( const Nepomuk::Query::Query& query );
+ void populate();
+
+ protected:
+ virtual QString titleForResult( const Soprano::BindingSet& bindings ) \
const; + virtual Term termForResult( const Soprano::BindingSet& bindings ) \
const; +
+ private:
+ Term termForButton( int button, const QVariant& data ) const;
+ void buttonClicked( int button, const QVariant& data );
+
+ class Private;
+ Private* const d;
+
+ Q_PRIVATE_SLOT( d, void \
_k_populateNextResult(Soprano::Util::AsyncQuery*) ) + Q_PRIVATE_SLOT( d, \
void _k_populateFinished(Soprano::Util::AsyncQuery*) ) + };
+ }
+}
+
+#endif
diff --git a/nepomuk/query/facetwidget.cpp b/nepomuk/query/facetwidget.cpp
new file mode 100644
index 0000000..c2e961b
--- /dev/null
+++ b/nepomuk/query/facetwidget.cpp
@@ -0,0 +1,252 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "facetwidget.h"
+#include "simplelistfacetwidget.h"
+#include "rangedfacetwidget.h"
+#include "dynamiclistfacetwidget.h"
+#include "daterangeselectionwidget.h"
+#include "daterange.h"
+#include "query.h"
+
+#include <QtCore/QDate>
+#include <QtGui/QCursor>
+
+#include <Soprano/Vocabulary/NAO>
+#include <Soprano/BindingSet>
+
+#include "andterm.h"
+#include "orterm.h"
+#include "comparisonterm.h"
+#include "literalterm.h"
+#include "resourceterm.h"
+#include "resourcetypeterm.h"
+#include "standardqueries.h"
+#include "query.h"
+
+#include "tag.h"
+#include "property.h"
+#include "resource.h"
+
+#include "tmo.h"
+#include "nmo.h"
+#include "nco.h"
+#include "nfo.h"
+#include "nie.h"
+
+#include "kdebug.h"
+#include "kglobal.h"
+#include "klocale.h"
+#include "kcalendarsystem.h"
+#include "kdialog.h"
+
+
+class Nepomuk::Query::FacetWidget::Private
+{
+public:
+};
+
+
+Nepomuk::Query::FacetWidget::FacetWidget( QWidget* parent )
+ : QWidget( parent ),
+ d(new Private())
+{
+}
+
+
+Nepomuk::Query::FacetWidget::~FacetWidget()
+{
+ delete d;
+}
+
+
+bool Nepomuk::Query::FacetWidget::selectFromTerm( const Term& term )
+{
+ return doSelectFromTerm( term );
+}
+
+
+void Nepomuk::Query::FacetWidget::clearSelection()
+{
+ return doClearSelection();
+}
+
+
+void Nepomuk::Query::FacetWidget::setTermChanged()
+{
+ emit termChanged( term() );
+}
+
+
+// static
+Nepomuk::Query::FacetWidget* Nepomuk::Query::FacetWidget::createFileTypeFacet( \
QWidget* parent ) +{
+ SimpleListFacetWidget* w = new SimpleListFacetWidget( parent );
+ w->setSelectionMode( ListFacetWidget::MatchOne );
+ w->addTerm( i18n("Documents"),
+ ResourceTypeTerm(Nepomuk::Vocabulary::NFO::Document()) );
+
+ // need to check the mimetype as well since strigi is still not perfect
+ w->addTerm( i18n("Media"),
+ ResourceTypeTerm(Nepomuk::Vocabulary::NFO::Audio()) ||
+ ResourceTypeTerm(Nepomuk::Vocabulary::NFO::Video()) ||
+ ComparisonTerm(Nepomuk::Vocabulary::NIE::mimeType(), \
LiteralTerm(QLatin1String("video"))) || + \
ComparisonTerm(Nepomuk::Vocabulary::NIE::mimeType(), \
LiteralTerm(QLatin1String("audio"))) ); +
+ w->addTerm( i18n("Images"),
+ ResourceTypeTerm(Nepomuk::Vocabulary::NFO::Image()) );
+ return w;
+}
+
+
+// static
+Nepomuk::Query::FacetWidget* Nepomuk::Query::FacetWidget::createTypeFacet( QWidget* \
parent ) +{
+ SimpleListFacetWidget* w = new SimpleListFacetWidget( parent );
+ w->setSelectionMode( ListFacetWidget::MatchOne );
+ w->addTerm(i18n("Files"),
+ ResourceTypeTerm(Nepomuk::Vocabulary::NFO::FileDataObject()) );
+ w->addTerm(i18n("Contacts"),
+ ResourceTypeTerm(Nepomuk::Vocabulary::NCO::Contact()));
+ w->addTerm(i18n("Emails"),
+ ResourceTypeTerm(Nepomuk::Vocabulary::NMO::Email()));
+ w->addTerm(i18n("Tasks"),
+ ResourceTypeTerm(Nepomuk::Vocabulary::TMO::Task()));
+ w->addTerm(i18n("Tags"),
+ ResourceTypeTerm(Soprano::Vocabulary::NAO::Tag()));
+ return w;
+}
+
+
+namespace {
+ class DateRangeFacetWidget : public Nepomuk::Query::RangedFacetWidget
+ {
+ public:
+ DateRangeFacetWidget( QWidget* parent )
+ : RangedFacetWidget( parent ) {
+ setProperty( Nepomuk::Vocabulary::NIE::lastModified() );
+ }
+
+ protected:
+ Nepomuk::Query::Term buildRangeTerm( const QVariant& start, const QVariant& \
end ) const { + if( start.isValid() ) {
+ return Nepomuk::Query::dateRangeQuery( start.toDate(), end.toDate() \
).term(); + }
+ else {
+ return Nepomuk::Query::Term();
+ }
+ }
+
+ Nepomuk::Query::RangedFacetWidget::Range getCustomRange() const {
+ KDialog dlg;
+ dlg.setWindowFlags(Qt::Popup);
+ dlg.setButtons( KDialog::Ok );
+ DateRangeSelectionWidget* drw = new DateRangeSelectionWidget( &dlg );
+ drw->setRange( currentDateRange() );
+ dlg.setMainWidget( drw );
+ dlg.move(QCursor::pos());
+ dlg.exec();
+ DateRange range = drw->range();
+ return qMakePair( QVariant(range.start()), QVariant(range.end()) );
+ }
+
+ private:
+ DateRange currentDateRange() const {
+ Range range = currentRange();
+ return DateRange( range.first.toDate(), range.second.toDate() );
+ }
+ };
+}
+
+// static
+// FIXME: a dolphin instance which is running more than a day will have wrong date \
facets! +// We could add a special DateTerm which takes that into account and \
always uses the current datetime +Nepomuk::Query::FacetWidget* \
Nepomuk::Query::FacetWidget::createDateFacet( QWidget* parent ) +{
+ DateRangeFacetWidget* w = new DateRangeFacetWidget( parent );
+ const QDate today = QDate::currentDate();
+
+ w->addFixedValue( QDate(), i18n("Anytime") );
+ w->addFixedValue( today, i18n("Today") );
+ w->addFixedRange( today.addDays(-1), today.addDays(-1), i18n("Yesterday") );
+ const DateRange thisWeek = DateRange::thisWeek();
+ w->addFixedRange( thisWeek.start(),
+ thisWeek.end(),
+ i18n("This week") );
+ const DateRange thisMonth = DateRange::thisMonth();
+ w->addFixedRange( thisMonth.start(),
+ thisMonth.end(),
+ i18n("This month") );
+ w->addFixedRange( QDate( QDate::currentDate().year(), 1, 1 ),
+ QDate( QDate::currentDate().year(), 12, 31),
+ i18n("This year") );
+ w->addCustomRangeButton( i18n("Other date...") );
+ return w;
+}
+
+
+namespace {
+ class TagFacetWidget : public Nepomuk::Query::DynamicListFacetWidget
+ {
+ public:
+ TagFacetWidget( QWidget* parent )
+ : Nepomuk::Query::DynamicListFacetWidget( parent ) {
+
+ setSelectionMode(ListFacetWidget::MatchAll);
+
+ // get the most used tags
+ Nepomuk::Query::ComparisonTerm term( Soprano::Vocabulary::NAO::hasTag(), \
Nepomuk::Query::Term() ); + term.setSortWeight( 1, Qt::DescendingOrder );
+ term.setAggregateFunction( Nepomuk::Query::ComparisonTerm::Count );
+ setPopulationQuery( Nepomuk::Query::Query( \
Nepomuk::Query::ResourceTypeTerm( Soprano::Vocabulary::NAO::Tag() ) && \
term.inverted() ) ); + }
+ ~TagFacetWidget() {
+ }
+
+ private:
+ Nepomuk::Query::Term termForResult( const Soprano::BindingSet& bindings ) \
const { + return Soprano::Vocabulary::NAO::hasTag() == \
Nepomuk::Query::ResourceTerm( bindings[0].uri() ); + }
+ };
+}
+
+// static
+Nepomuk::Query::FacetWidget* Nepomuk::Query::FacetWidget::createTagFacet( QWidget* \
parent ) +{
+ TagFacetWidget* w = new TagFacetWidget( parent );
+ w->populate();
+ return w;
+}
+
+
+// static
+Nepomuk::Query::FacetWidget* Nepomuk::Query::FacetWidget::createPriorityFacet( \
QWidget* parent ) +{
+ SimpleListFacetWidget* w = new SimpleListFacetWidget( parent );
+ w->setSelectionMode(ListFacetWidget::Exclusive);
+ w->addTerm(i18n("No priority"), Term());
+ w->addTerm( i18n("Last modified"), standardQuery( LastModifiedFilesQuery \
).term() ); + w->addTerm( i18n("Most important"), standardQuery( \
MostImportantResourcesQuery ).term() ); + w->addTerm( i18n("Never opened"), \
standardQuery( NeverOpenedFilesQuery ).term() ); + return w;
+}
+
+#include "facetwidget.moc"
diff --git a/nepomuk/query/facetwidget.h b/nepomuk/query/facetwidget.h
new file mode 100644
index 0000000..cd67c08
--- /dev/null
+++ b/nepomuk/query/facetwidget.h
@@ -0,0 +1,77 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NEPOMUK_QUERY_FACET_WIDGET_H_
+#define _NEPOMUK_QUERY_FACET_WIDGET_H_
+
+#include <QtGui/QWidget>
+
+#include "term.h"
+#include "nepomukquery_export.h"
+
+namespace Nepomuk {
+ namespace Query {
+ class NEPOMUKQUERY_EXPORT FacetWidget : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ FacetWidget( QWidget* parent = 0 );
+ ~FacetWidget();
+
+ virtual Term term() const = 0;
+
+ static FacetWidget* createFileTypeFacet( QWidget* parent = 0 );
+ static FacetWidget* createTypeFacet( QWidget* parent = 0 );
+ static FacetWidget* createDateFacet( QWidget* parent = 0 );
+ static FacetWidget* createTagFacet( QWidget* parent = 0 );
+ static FacetWidget* createPriorityFacet( QWidget* parent = 0 );
+
+ public Q_SLOTS:
+ bool selectFromTerm( const Term& term );
+ void clearSelection();
+
+ Q_SIGNALS:
+ void termChanged( const Nepomuk::Query::Term& term );
+
+ protected Q_SLOTS:
+ /**
+ * Use this instead of emitting the termChanged() signal.
+ */
+ void setTermChanged();
+
+ protected:
+ /**
+ * Make \p term the term in the widget if possible.
+ * In other words: if this method returns \p true a subsequent call
+ * to term() has to return \p term.
+ */
+ virtual bool doSelectFromTerm( const Term& term ) = 0;
+ virtual void doClearSelection() = 0;
+
+ private:
+ class Private;
+ Private* d;
+ };
+ }
+}
+
+#endif
diff --git a/nepomuk/query/facetwidgetcontroller.cpp \
b/nepomuk/query/facetwidgetcontroller.cpp new file mode 100644
index 0000000..2399706
--- /dev/null
+++ b/nepomuk/query/facetwidgetcontroller.cpp
@@ -0,0 +1,169 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "facetwidgetcontroller.h"
+#include "facetwidget.h"
+
+#include "query.h"
+#include "andterm.h"
+
+
+class Nepomuk::Query::FacetWidgetController::Private
+{
+public:
+ QList<FacetWidget*> m_widgets;
+ Query m_baseQuery;
+
+ bool m_interalFacetUpdate;
+
+ QList<Nepomuk::Query::Term> selectedTerms() const;
+
+ void _k_termChanged( const Nepomuk::Query::Term& );
+
+ FacetWidgetController* q;
+};
+
+
+QList<Nepomuk::Query::Term> \
Nepomuk::Query::FacetWidgetController::Private::selectedTerms() const +{
+ QList<Nepomuk::Query::Term> terms;
+ Q_FOREACH( FacetWidget* w, m_widgets ) {
+ terms.append(w->term());
+ }
+ return terms;
+}
+
+
+void Nepomuk::Query::FacetWidgetController::Private::_k_termChanged( const \
Nepomuk::Query::Term& ) +{
+ if( !m_interalFacetUpdate ) {
+ emit q->queryChanged( q->constructQuery() );
+ }
+}
+
+
+Nepomuk::Query::FacetWidgetController::FacetWidgetController( QObject* parent )
+ : QObject( parent ),
+ d(new Private())
+{
+ d->q = this;
+ d->m_interalFacetUpdate = false;
+}
+
+
+Nepomuk::Query::FacetWidgetController::~FacetWidgetController()
+{
+ delete d;
+}
+
+
+Nepomuk::Query::Query Nepomuk::Query::FacetWidgetController::constructQuery() const
+{
+ Query query( d->m_baseQuery );
+ Q_FOREACH( const Term& term, d->selectedTerms() ) {
+ query.setTerm( query.term() && term );
+ }
+ return query.optimized();
+}
+
+
+Nepomuk::Query::Query Nepomuk::Query::FacetWidgetController::baseQuery() const
+{
+ return d->m_baseQuery;
+}
+
+
+Nepomuk::Query::Query Nepomuk::Query::FacetWidgetController::setQuery( const Query& \
query ) +{
+ d->m_interalFacetUpdate = true;
+
+ // reset all facets in the model
+ // ================================
+ Q_FOREACH( FacetWidget* w, d->m_widgets ) {
+ w->clearSelection();
+ }
+
+ // we extract all facets we can find and leave the rest in the query
+ // ================================
+ d->m_baseQuery = query.optimized();
+
+ // first we check if the main term is already a facet term
+ // (this way we can also handle facets that use AndTerms)
+ // ================================
+ Term term = d->m_baseQuery.term();
+ // if any of the facets contains the term, set it to selected
+ Q_FOREACH( FacetWidget* w, d->m_widgets ) {
+ if( w->selectFromTerm( term ) ) {
+ d->m_baseQuery.setTerm( Term() );
+ break;
+ }
+ }
+
+ // now go into an AndTerm and check each sub term for facet
+ // ================================
+ if( d->m_baseQuery.term().isAndTerm() ) {
+ AndTerm restAndTerm;
+ foreach( const Term& term, d->m_baseQuery.term().toAndTerm().subTerms() ) {
+ bool termFound = false;
+
+ // FIXME: we cannot use an exclusive widget twice!
+ // Example: we have an exclusive widget that can handle both term \
A and B + // we now call selectFromTerm(A) and \
selectFromTerm(B) + // both return true but only the \
latter is the one that sticks. + // thus, we implicitely \
drop A from the query! +
+ Q_FOREACH( FacetWidget* w, d->m_widgets ) {
+ if( w->selectFromTerm( term ) ) {
+ termFound = true;
+ break;
+ }
+ }
+
+ // we did not find a matching facet
+ if( !termFound )
+ restAndTerm.addSubTerm( term );
+ }
+
+ d->m_baseQuery.setTerm( restAndTerm );
+ }
+
+ d->m_interalFacetUpdate = false;
+
+ d->m_baseQuery = d->m_baseQuery.optimized();
+
+ return d->m_baseQuery;
+}
+
+
+void Nepomuk::Query::FacetWidgetController::setBaseQuery( const Query& query )
+{
+ d->m_baseQuery = query;
+}
+
+
+void Nepomuk::Query::FacetWidgetController::addFacetWidget( FacetWidget* widget )
+{
+ d->m_widgets << widget;
+ connect( widget, SIGNAL(termChanged(Nepomuk::Query::Term)),
+ this, SLOT(_k_termChanged(Nepomuk::Query::Term)) );
+}
+
+#include "facetwidgetcontroller.moc"
diff --git a/nepomuk/query/facetwidgetcontroller.h \
b/nepomuk/query/facetwidgetcontroller.h new file mode 100644
index 0000000..c6dda57
--- /dev/null
+++ b/nepomuk/query/facetwidgetcontroller.h
@@ -0,0 +1,88 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NEPOMUK_QUERY_FACET_WIDGET_CONTROLLER_H_
+#define _NEPOMUK_QUERY_FACET_WIDGET_CONTROLLER_H_
+
+#include <QtCore/QObject>
+
+#include "nepomukquery_export.h"
+
+namespace Nepomuk {
+ namespace Query {
+
+ class Query;
+ class FacetWidget;
+
+ /**
+ * \brief Manages a set of FacetWidget instances.
+ *
+ * \author Sebastian Trueg <trueg@kde.org>
+ */
+ class NEPOMUKQUERY_EXPORT FacetWidgetController : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ FacetWidgetController( QObject* parent = 0 );
+ ~FacetWidgetController();
+
+ /**
+ * \sa setBaseQuery()
+ */
+ Nepomuk::Query::Query baseQuery() const;
+
+ /**
+ * Construct a query from the selected facets in this model and \p \
baseQuery. + *
+ * \return A new query which combines the facets in this model with \p \
baseQuery. + */
+ Query constructQuery() const;
+
+ /**
+ * Extract as many facets from a query as possible. This method is not \
able to handle all + * kinds of queries but works well on queries created \
via constructQuery(). + *
+ * Facets supported by this model will be extracted from the \p query \
and configured + * accordingly in the model.
+ *
+ * \return The rest query after facets have been extracted. This is also \
saved as baseQuery(). + */
+ Nepomuk::Query::Query setQuery( const Query& query );
+
+ public Q_SLOTS:
+ void setBaseQuery( const Query& query );
+ void addFacetWidget( FacetWidget* widget );
+
+ Q_SIGNALS:
+ void queryChanged( const Nepomuk::Query::Query& query );
+
+ private:
+ class Private;
+ Private* const d;
+
+ Q_PRIVATE_SLOT( d, void _k_termChanged(const Nepomuk::Query::Term&) )
+ };
+ }
+}
+
+#endif
+
diff --git a/nepomuk/query/listfacetwidget.cpp b/nepomuk/query/listfacetwidget.cpp
new file mode 100644
index 0000000..c633ff9
--- /dev/null
+++ b/nepomuk/query/listfacetwidget.cpp
@@ -0,0 +1,410 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "listfacetwidget.h"
+#include "andterm.h"
+#include "orterm.h"
+
+#include <QtCore/QSet>
+#include <QtCore/QHash>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QRadioButton>
+#include <QtGui/QCheckBox>
+
+#include "kdebug.h"
+
+namespace {
+ class Button
+ {
+ public:
+ Button()
+ : button(0) {
+ }
+
+ ~Button() {
+ }
+
+ /// the title used for the button
+ QString title;
+
+ /// id used by ListFacetWidget - this is not the id in the button group
+ int id;
+
+ /// used data set in addButton
+ QVariant data;
+
+ /// the currently representing button instance
+ QAbstractButton* button;
+ };
+}
+
+class Nepomuk::Query::ListFacetWidget::Private
+{
+public:
+ Private()
+ : m_buttonIdCnt(0),
+ m_selectionMode(Exclusive) {
+ }
+
+ int indexOf( const Term& term ) const;
+ void rebuildButtons();
+ QAbstractButton* createButton( const QString& title );
+
+ void _k_buttonClicked( int );
+
+ QList<Nepomuk::Query::Term> m_terms;
+ QStringList m_titles;
+
+ QButtonGroup m_buttonGroup;
+ QVBoxLayout* m_layout;
+
+ /// all existing buttons
+ QList<Button> m_buttons;
+
+ /// a mapping from ids to indexes in m_buttons
+ QHash<int, int> m_buttonIdMap;
+
+ /// a mapping from m_buttonGroup ids to indexes in m_buttons
+ QHash<int, int> m_buttonGroupIdMap;
+
+ /// counter to create unique ids
+ int m_buttonIdCnt;
+
+ SelectionMode m_selectionMode;
+
+ ListFacetWidget* q;
+};
+
+
+int Nepomuk::Query::ListFacetWidget::Private::indexOf( const Term& term ) const
+{
+ for( int i = 0; i < m_buttons.count(); ++i ) {
+ const Button& button = m_buttons[i];
+ if( term == q->termForButton( button.id, button.data ) )
+ return i;
+ }
+ return -1;
+}
+
+
+void Nepomuk::Query::ListFacetWidget::Private::rebuildButtons()
+{
+ m_buttonGroupIdMap.clear();
+ Q_FOREACH( const Button& button, m_buttons ) {
+ delete button.button;
+ }
+ for( int i = 0; i < m_buttons.count(); ++i ) {
+ m_buttons[i].button = createButton( m_buttons[i].title );
+ m_buttonGroupIdMap[m_buttonGroup.id(m_buttons[i].button)] = i;
+ }
+ if( !m_buttons.isEmpty() && q->isExclusive() )
+ m_buttons.first().button->setChecked(true);
+}
+
+
+QAbstractButton* Nepomuk::Query::ListFacetWidget::Private::createButton( const \
QString& title ) +{
+ QAbstractButton* button = 0;
+ if( m_buttonGroup.exclusive() )
+ button = new QRadioButton( q );
+ else
+ button = new QCheckBox( q );
+ button->setText( title );
+ m_buttonGroup.addButton( button );
+ m_layout->addWidget( button );
+ return button;
+}
+
+
+void Nepomuk::Query::ListFacetWidget::Private::_k_buttonClicked( int id )
+{
+ kDebug() << id << m_buttonGroupIdMap[id] << \
m_buttons[m_buttonGroupIdMap[id]].id; + q->buttonClicked( \
m_buttons[m_buttonGroupIdMap[id]].id, m_buttons[m_buttonGroupIdMap[id]].data ); +}
+
+
+Nepomuk::Query::ListFacetWidget::ListFacetWidget( QWidget* parent )
+ : FacetWidget( parent ),
+ d(new Private())
+{
+ d->q = this;
+ d->m_layout = new QVBoxLayout( this );
+ connect( &d->m_buttonGroup, SIGNAL(buttonClicked(int)),
+ this, SLOT(_k_buttonClicked(int)) );
+}
+
+
+Nepomuk::Query::ListFacetWidget::~ListFacetWidget()
+{
+ delete d;
+}
+
+
+Nepomuk::Query::Term Nepomuk::Query::ListFacetWidget::term() const
+{
+ QList<Term> terms;
+ Q_FOREACH( const Button& button, d->m_buttons ) {
+ if( button.button->isChecked() )
+ terms << termForButton( button.id, button.data );
+ }
+
+ if( terms.isEmpty() ) {
+ return Term();
+ }
+ else if( terms.count() == 1 ) {
+ return terms.first();
+ }
+ else if( d->m_selectionMode == MatchAll ) {
+ AndTerm andTerm;
+ Q_FOREACH( const Term& term, terms ) {
+ andTerm.addSubTerm( term );
+ }
+ return andTerm;
+ }
+ else {
+ OrTerm andTerm;
+ Q_FOREACH( const Term& term, terms ) {
+ andTerm.addSubTerm( term );
+ }
+ return andTerm;
+ }
+}
+
+
+bool Nepomuk::Query::ListFacetWidget::isSelected( int index ) const
+{
+ return d->m_buttons[index].button->isChecked();
+}
+
+
+bool Nepomuk::Query::ListFacetWidget::isExclusive() const
+{
+ return d->m_buttonGroup.exclusive();
+}
+
+
+int Nepomuk::Query::ListFacetWidget::count() const
+{
+ return d->m_buttons.count();
+}
+
+
+Nepomuk::Query::Term Nepomuk::Query::ListFacetWidget::termAt( int i ) const
+{
+ return termForButton( d->m_buttons[i].id, d->m_buttons[i].data );
+}
+
+
+QString Nepomuk::Query::ListFacetWidget::titleAt( int i ) const
+{
+ return d->m_buttons.at(i).title;
+}
+
+Nepomuk::Query::ListFacetWidget::SelectionMode \
Nepomuk::Query::ListFacetWidget::selectionMode() const +{
+ return d->m_selectionMode;
+}
+
+
+void Nepomuk::Query::ListFacetWidget::clear()
+{
+ d->m_buttonIdMap.clear();
+ d->m_buttonGroupIdMap.clear();
+ Q_FOREACH( const Button& button, d->m_buttons ) {
+ delete button.button;
+ }
+ d->m_buttons.clear();
+ setTermChanged();
+}
+
+
+void Nepomuk::Query::ListFacetWidget::setSelected( int index, bool selected )
+{
+ if( d->m_buttons[index].button->isChecked() != selected ) {
+ d->m_buttons[index].button->setChecked( selected );
+ setTermChanged();
+ }
+}
+
+
+QSet<int> Nepomuk::Query::ListFacetWidget::selectedButtons() const
+{
+ QSet<int> buttons;
+ Q_FOREACH( const Button& button, d->m_buttons ) {
+ if( button.button->isChecked() )
+ buttons << button.id;
+ }
+ return buttons;
+}
+
+
+QAbstractButton* Nepomuk::Query::ListFacetWidget::button( int id ) const
+{
+ return d->m_buttons[d->m_buttonIdMap[id]].button;
+}
+
+
+QVariant Nepomuk::Query::ListFacetWidget::buttonData( int id ) const
+{
+ return d->m_buttons[d->m_buttonIdMap[id]].data;
+}
+
+
+int Nepomuk::Query::ListFacetWidget::addButton( const QString& title, const \
QVariant& data ) +{
+ Button button;
+ button.title = title;
+ button.id = ++d->m_buttonIdCnt;
+ button.data = data;
+ button.button = d->createButton( title );
+ d->m_buttonIdMap[button.id] = d->m_buttons.count();
+ d->m_buttonGroupIdMap[d->m_buttonGroup.id(button.button)] = \
d->m_buttons.count(); + d->m_buttons << button;
+ if( isExclusive() && selectedButtons().isEmpty() )
+ button.button->setChecked(true);
+ return button.id;
+}
+
+
+void Nepomuk::Query::ListFacetWidget::setButtonTitle( int id, const QString& title )
+{
+ if( d->m_buttonIdMap.contains( id ) ) {
+ d->m_buttons[d->m_buttonIdMap[id]].title = title;
+ d->m_buttons[d->m_buttonIdMap[id]].button->setText( title );
+ }
+ else {
+ kError() << "Unknown button id:" << id;
+ }
+}
+
+
+void Nepomuk::Query::ListFacetWidget::setButtonData( int id, const QVariant& data )
+{
+ if( d->m_buttonIdMap.contains( id ) ) {
+ d->m_buttons[d->m_buttonIdMap[id]].data = data;
+ }
+ else {
+ kError() << "Unknown button id:" << id;
+ }
+}
+
+
+void Nepomuk::Query::ListFacetWidget::setSelectionMode( SelectionMode mode )
+{
+ if( mode != d->m_selectionMode ) {
+ d->m_selectionMode = mode;
+ d->m_buttonGroup.setExclusive( mode == Exclusive );
+ d->rebuildButtons();
+ setTermChanged();
+ }
+}
+
+
+bool Nepomuk::Query::ListFacetWidget::doSelectFromTerm( const Term& term )
+{
+ // 1. check if term is in our list of terms
+ const int i = d->indexOf( term );
+ if( i >= 0 ) {
+ kDebug() << "Found term at" << i << term;
+ setSelected( i, true );
+ return true;
+ }
+
+ // 2. an OrTerm may be a set of terms in a MatchOne facet
+ // 3. an AndTerm may be a set of terms in a MatchAll facet
+ if( ( term.isOrTerm() &&
+ selectionMode() == MatchOne ) ||
+ ( term.isAndTerm() &&
+ selectionMode() == MatchAll ) ) {
+
+ QSet<int> selectedTerms;
+
+ // since single terms could consist of OrTerms or AndTerms as well
+ // and thus, could be "merged" into the surrounding term, we check
+ // every sensible combination of terms instead of only single ones
+
+ QList<Term> subTerms;
+ if( term.isAndTerm() )
+ subTerms = term.toAndTerm().subTerms();
+ else
+ subTerms = term.toOrTerm().subTerms();
+
+ while( !subTerms.isEmpty() ) {
+ bool found = false;
+ for( int len = 1; len <= subTerms.count(); ++len ) {
+ const QList<Term> excerpt = subTerms.mid( 0, len );
+ Term subTerm;
+ if( term.isAndTerm() )
+ subTerm = AndTerm(excerpt).optimized();
+ else
+ subTerm = OrTerm(excerpt).optimized();
+ const int i = d->indexOf( subTerm );
+ if( i >= 0 ) {
+ kDebug() << "Found term at" << i << subTerm;
+ selectedTerms << i;
+ subTerms = subTerms.mid(len);
+ found = true;
+ break;
+ }
+ }
+ if( !found ) {
+ kDebug() << "Term not found (not even as subterm):" << subTerms;
+ return false;
+ }
+ }
+
+ Q_FOREACH( int i, selectedTerms )
+ setSelected( i );
+
+ return true;
+ }
+
+ else {
+ kDebug() << "Term not found" << term;
+ return false;
+ }
+}
+
+
+void Nepomuk::Query::ListFacetWidget::doClearSelection()
+{
+ if( isExclusive() ) {
+ setSelected( 0, true );
+ }
+ else {
+ Q_FOREACH( const Button& button, d->m_buttons ) {
+ button.button->setChecked( false );
+ }
+ setTermChanged();
+ }
+}
+
+
+void Nepomuk::Query::ListFacetWidget::buttonClicked( int button, const QVariant& \
data ) +{
+ kDebug() << button;
+ Q_UNUSED( button );
+ Q_UNUSED( data );
+ setTermChanged();
+}
+
+#include "listfacetwidget.moc"
diff --git a/nepomuk/query/listfacetwidget.h b/nepomuk/query/listfacetwidget.h
new file mode 100644
index 0000000..d6095f7
--- /dev/null
+++ b/nepomuk/query/listfacetwidget.h
@@ -0,0 +1,100 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NEPOMUK_QUERY_LIST_FACET_WIDGET_H_
+#define _NEPOMUK_QUERY_LIST_FACET_WIDGET_H_
+
+#include "facetwidget.h"
+#include "nepomukquery_export.h"
+
+#include <QtCore/QSet>
+
+class QAbstractButton;
+
+namespace Nepomuk {
+ namespace Query {
+ class NEPOMUKQUERY_EXPORT ListFacetWidget : public FacetWidget
+ {
+ Q_OBJECT
+
+ public:
+ ListFacetWidget( QWidget* parent = 0 );
+ virtual ~ListFacetWidget();
+
+ Term term() const;
+
+ bool isSelected( int index ) const;
+
+ bool isExclusive() const;
+
+ int count() const;
+
+ Term termAt( int i ) const;
+
+ QString titleAt( int i ) const;
+
+ enum SelectionMode {
+ Exclusive,
+ MatchOne,
+ MatchAll
+ };
+
+ SelectionMode selectionMode() const;
+
+ public Q_SLOTS:
+ void clear();
+ void setSelected( int index, bool selected = true );
+ void setSelectionMode( SelectionMode mode );
+
+ protected:
+ /**
+ * \return A set of buttons ids.
+ */
+ QSet<int> selectedButtons() const;
+
+ QAbstractButton* button( int id ) const;
+ QVariant buttonData( int id ) const;
+
+ /**
+ * \return An id to identify the button.
+ */
+ int addButton( const QString& title, const QVariant& data = QVariant() \
); + void setButtonTitle( int id, const QString& title );
+ void setButtonData( int id, const QVariant& data );
+ bool doSelectFromTerm( const Term& term );
+ virtual void doClearSelection();
+
+ /**
+ * Default implementation calls setTermChanged()
+ */
+ virtual void buttonClicked( int button, const QVariant& data );
+ virtual Term termForButton( int button, const QVariant& data ) const = \
0; +
+ private:
+ class Private;
+ Private* const d;
+
+ Q_PRIVATE_SLOT( d, void _k_buttonClicked(int) )
+ };
+ }
+}
+
+#endif
diff --git a/nepomuk/query/rangedfacetwidget.cpp \
b/nepomuk/query/rangedfacetwidget.cpp new file mode 100644
index 0000000..bee1595
--- /dev/null
+++ b/nepomuk/query/rangedfacetwidget.cpp
@@ -0,0 +1,178 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rangedfacetwidget.h"
+#include "property.h"
+#include "variant.h"
+#include "term.h"
+#include "comparisonterm.h"
+
+#include <QtGui/QAbstractButton>
+
+#include "kdebug.h"
+
+Q_DECLARE_METATYPE(Nepomuk::Query::RangedFacetWidget::Range)
+
+class Nepomuk::Query::RangedFacetWidget::Private
+{
+public:
+ Private()
+ : m_lastCheckedButton(-1),
+ m_cutomRangeButtonId(-1) {
+ }
+
+ Types::Property m_property;
+ int m_lastCheckedButton;
+ int m_cutomRangeButtonId;
+};
+
+
+Nepomuk::Query::RangedFacetWidget::RangedFacetWidget( QWidget* parent )
+ : ListFacetWidget( parent ),
+ d(new Private())
+{
+ setSelectionMode( Exclusive );
+}
+
+
+Nepomuk::Query::RangedFacetWidget::~RangedFacetWidget()
+{
+ delete d;
+}
+
+
+Nepomuk::Types::Property Nepomuk::Query::RangedFacetWidget::property() const
+{
+ return d->m_property;
+}
+
+
+Nepomuk::Query::RangedFacetWidget::Range \
Nepomuk::Query::RangedFacetWidget::currentRange() const +{
+ return buttonData( d->m_lastCheckedButton ).value<Range>();
+}
+
+
+void Nepomuk::Query::RangedFacetWidget::setProperty( const Nepomuk::Types::Property& \
p ) +{
+ d->m_property = p;
+ setTermChanged();
+}
+
+
+void Nepomuk::Query::RangedFacetWidget::addFixedValue( const QVariant& value, const \
QString& customTitle ) +{
+ addFixedRange( value, value, customTitle );
+}
+
+
+void Nepomuk::Query::RangedFacetWidget::addFixedRange( const QVariant& start, const \
QVariant& end, const QString& customTitle ) +{
+ QString title( customTitle );
+ if( title.isEmpty() ) {
+ if( start == end )
+ title = start.toString();
+ else
+ title = start.toString() + '-' + end.toString();
+ }
+ int id = addButton( title, QVariant::fromValue( qMakePair( start, end ) ) );
+ if( d->m_lastCheckedButton < 0 )
+ d->m_lastCheckedButton = id;
+}
+
+
+void Nepomuk::Query::RangedFacetWidget::addCustomRangeButton( const QString& title )
+{
+ d->m_cutomRangeButtonId = addButton( title );
+ kDebug() << d->m_cutomRangeButtonId;
+ if( d->m_lastCheckedButton < 0 )
+ d->m_lastCheckedButton = d->m_cutomRangeButtonId;
+}
+
+
+Nepomuk::Query::Term Nepomuk::Query::RangedFacetWidget::buildRangeTerm( const \
QVariant& start, const QVariant& end ) const +{
+ if( start == end )
+ return d->m_property == Term::fromVariant( Variant( start ) );
+ else
+ return ( d->m_property >= Term::fromVariant( Variant( start ) ) && \
d->m_property <= Term::fromVariant( Variant( end ) ) ); +}
+
+
+Nepomuk::Query::RangedFacetWidget::Range \
Nepomuk::Query::RangedFacetWidget::getCustomRange() const +{
+ kDebug();
+ // FIXME
+ return qMakePair(QVariant(), QVariant());
+}
+
+
+void Nepomuk::Query::RangedFacetWidget::buttonClicked( int buttonId, const QVariant& \
data ) +{
+ kDebug() << buttonId;
+ if( buttonId == d->m_cutomRangeButtonId ) {
+ Range range = getCustomRange();
+ if( range.first.isValid() ) {
+ setButtonData( d->m_cutomRangeButtonId, QVariant::fromValue(range) );
+ d->m_lastCheckedButton = d->m_cutomRangeButtonId;
+
+ // check the appropriate button in case the user manually specified one \
of the fixed ranges + Term term = buildRangeTerm( range.first, \
range.second ); + for( int i = 0; i < count(); ++i ) {
+ if( termAt(i) == term ) {
+ setSelected( i );
+ break;
+ }
+ }
+ }
+ else {
+ kDebug() << "Invalid range. Restoring old:" << d->m_lastCheckedButton;
+ // restore previous selection
+ button( d->m_lastCheckedButton )->setChecked(true);
+ }
+ setTermChanged();
+ }
+ else {
+ d->m_lastCheckedButton = buttonId;
+ ListFacetWidget::buttonClicked( buttonId, data );
+ }
+}
+
+
+Nepomuk::Query::Term Nepomuk::Query::RangedFacetWidget::termForButton( int, const \
QVariant& data ) const +{
+ if( data.userType() == qMetaTypeId<Range>() ) {
+ Range range = data.value<Range>();
+ return buildRangeTerm( range.first, range.second );
+ }
+ else {
+ return Term();
+ }
+}
+
+
+void Nepomuk::Query::RangedFacetWidget::doClearSelection()
+{
+ ListFacetWidget::doClearSelection();
+ d->m_lastCheckedButton = *selectedButtons().begin();
+}
+
+#include "rangedfacetwidget.moc"
diff --git a/nepomuk/query/rangedfacetwidget.h b/nepomuk/query/rangedfacetwidget.h
new file mode 100644
index 0000000..ad21d3a
--- /dev/null
+++ b/nepomuk/query/rangedfacetwidget.h
@@ -0,0 +1,76 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NEPOMUK_QUERY_RANGED_FACET_WIDGET_H_
+#define _NEPOMUK_QUERY_RANGED_FACET_WIDGET_H_
+
+#include "listfacetwidget.h"
+#include "nepomukquery_export.h"
+
+#include <QtCore/QPair>
+#include <QtCore/QVariant>
+
+
+namespace Nepomuk {
+ namespace Types {
+ class Property;
+ }
+
+ namespace Query {
+ class NEPOMUKQUERY_EXPORT RangedFacetWidget : public ListFacetWidget
+ {
+ Q_OBJECT
+
+ public:
+ RangedFacetWidget( QWidget* parent = 0 );
+ virtual ~RangedFacetWidget();
+
+ Types::Property property() const;
+
+ typedef QPair<QVariant, QVariant> Range;
+
+ Range currentRange() const;
+
+ public Q_SLOTS:
+ /**
+ * Only used when buildRangeTerm() is not reimplemented.
+ */
+ void setProperty( const Nepomuk::Types::Property& p );
+ void addFixedValue( const QVariant& value, const QString& customTitle = \
QString() ); + void addFixedRange( const QVariant& start, const QVariant& \
end, const QString& customTitle = QString() ); + void \
addCustomRangeButton( const QString& title = QString() ); +
+ protected:
+ virtual Term buildRangeTerm( const QVariant& start, const QVariant& end \
) const; + virtual Range getCustomRange() const;
+
+ private:
+ void buttonClicked( int button, const QVariant& data );
+ Term termForButton( int button, const QVariant& data ) const;
+ void doClearSelection();
+
+ class Private;
+ Private* const d;
+ };
+ }
+}
+
+#endif
diff --git a/nepomuk/query/simplefacet.cpp b/nepomuk/query/simplefacet.cpp
new file mode 100644
index 0000000..6652076
--- /dev/null
+++ b/nepomuk/query/simplefacet.cpp
@@ -0,0 +1,177 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "simplefacet.h"
+#include "andterm.h"
+
+#include <QtCore/QSet>
+
+
+class Nepomuk::Query::SimpleFacet::Private
+{
+public:
+ Private()
+ : m_isExclusive(true) {
+ }
+
+ bool m_isExclusive;
+ QString m_title;
+
+ QList<Nepomuk::Query::Term> m_terms;
+ QList<QString> m_titles;
+
+ QSet<int> m_selectedFacets;
+};
+
+
+Nepomuk::Query::SimpleFacet::SimpleFacet( QObject* parent )
+ : Facet(parent),
+ d(new Private())
+{
+}
+
+
+Nepomuk::Query::SimpleFacet::~SimpleFacet()
+{
+ delete d;
+}
+
+
+QString Nepomuk::Query::SimpleFacet::title() const
+{
+ return d->m_title;
+}
+
+
+Nepomuk::Query::Term Nepomuk::Query::SimpleFacet::term() const
+{
+ if( d->m_terms.isEmpty() ||
+ d->m_selectedFacets.isEmpty() ) {
+ return Term();
+ }
+ else if( isExclusive() ) {
+ return termAt( *d->m_selectedFacets.constBegin() );
+ }
+ else {
+ AndTerm andTerm;
+ Q_FOREACH( int i, m_selectedFacets ) {
+ andTerm.addSubTerm( termAt(i) );
+ }
+ return andTerm;
+ }
+}
+
+
+void Nepomuk::Query::SimpleFacet::setTitle( const QString& title )
+{
+ d->m_title = title;
+}
+
+
+bool Nepomuk::Query::SimpleFacet::exclusive() const
+{
+ return d->m_isExclusive;
+}
+
+
+void Nepomuk::Query::SimpleFacet::setExclusive( bool exclusive )
+{
+ d->m_isExclusive = exclusive;
+ clearSelection();
+}
+
+
+int Nepomuk::Query::SimpleFacet::count() const
+{
+ return d->m_terms.count();
+}
+
+
+QList<Nepomuk::Query::Term> Nepomuk::Query::SimpleFacet::terms() const
+{
+ return d->m_terms;
+}
+
+
+Nepomuk::Query::Term Nepomuk::Query::SimpleFacet::termAt( int index ) const
+{
+ return d->m_terms[index];
+}
+
+
+QString Nepomuk::Query::SimpleFacet::titleAt( int index ) const
+{
+ return d->m_titles[index];
+}
+
+
+QString Nepomuk::Query::SimpleFacet::termTitle( const Term& term ) const
+{
+ return d->m_titles[d->m_terms.indexOf(term)];
+}
+
+
+void Nepomuk::Query::SimpleFacet::setTerms( const QMap<QString, \
Nepomuk::Query::Term>& terms ) +{
+ d->m_titles = terms.keys();
+ d->m_terms = terms.values();
+ clearSelection();
+}
+
+
+void Nepomuk::Query::SimpleFacet::addTerm( const QString& title, const \
Nepomuk::Query::Term& term ) +{
+ d->m_titles.append( title );
+ d->m_terms.append( term );
+ clearSelection();
+}
+
+
+void Nepomuk::Query::SimpleFacet::selectTerm( int index, bool selected = true )
+{
+ if( d->m_isExclusive ) {
+ if( d->m_selectedFacets.contains(index) && !selected ) {
+ clearSelection();
+ }
+ else if( selected ) {
+ d->m_selectedFacets.clear();
+ d->m_selectedFacets.append(index);
+ }
+ }
+ else if( selected ) {
+ d->m_selectedFacets.append(index);
+ }
+ else {
+ d->m_selectedFacets.removeAll(index);
+ }
+ setTermChanged();
+}
+
+
+void Nepomuk::Query::SimpleFacet::clearSelection()
+{
+ d->m_selectedFacets.clear();
+ if( d->m_isExclusive )
+ d->m_selectedFacets.append(0);
+ setTermChanged();
+}
+
+#include "simplefacet.moc"
diff --git a/nepomuk/query/simplefacet.h b/nepomuk/query/simplefacet.h
new file mode 100644
index 0000000..4d0e161
--- /dev/null
+++ b/nepomuk/query/simplefacet.h
@@ -0,0 +1,77 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NEPOMUK_QUERY_SIMPLE_FACET_H_
+#define _NEPOMUK_QUERY_SIMPLE_FACET_H_
+
+#include "facet.h"
+
+#include "nepomukquery_export.h"
+
+#include <QtCore/QMap>
+
+
+namespace Nepomuk {
+ namespace Query {
+ /**
+ * A simple facet using a list of terms.
+ *
+ * \author Sebastian Trueg <trueg@kde.org>
+ */
+ class NEPOMUKQUERY_EXPORT SimpleFacet : public Facet
+ {
+ Q_OBJECT
+
+ public:
+ SimpleFacet( QObject* parent );
+ virtual ~SimpleFacet();
+
+ virtual QString title() const;
+ virtual Term term() const;
+
+ void setTitle( const QString& title );
+
+ bool exclusive() const;
+ void setExclusive( bool exclusive );
+
+ virtual int count() const;
+
+ QList<Term> terms() const;
+
+ Term termAt( int index ) const;
+ QString titleAt( int index ) const;
+ QString termTitle( const Term& term ) const;
+
+ public Q_SLOTS:
+ void setTerms( const QMap<QString, Nepomuk::Query::Term>& terms );
+ void addTerm( const QString& title, const Nepomuk::Query::Term& term );
+
+ virtual void selectTerm( int index, bool selected = true );
+ virtual void clearSelection();
+
+ private:
+ class Private;
+ Private* d;
+ };
+ }
+}
+
+#endif
diff --git a/nepomuk/query/simplelistfacetwidget.cpp \
b/nepomuk/query/simplelistfacetwidget.cpp new file mode 100644
index 0000000..d8c84de
--- /dev/null
+++ b/nepomuk/query/simplelistfacetwidget.cpp
@@ -0,0 +1,57 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "simplelistfacetwidget.h"
+
+Q_DECLARE_METATYPE(Nepomuk::Query::Term)
+
+class Nepomuk::Query::SimpleListFacetWidget::Private
+{
+public:
+};
+
+
+Nepomuk::Query::SimpleListFacetWidget::SimpleListFacetWidget( QWidget* parent )
+ : ListFacetWidget( parent ),
+ d(new Private())
+{
+}
+
+
+Nepomuk::Query::SimpleListFacetWidget::~SimpleListFacetWidget()
+{
+ delete d;
+}
+
+
+void Nepomuk::Query::SimpleListFacetWidget::addTerm( const QString& title, const \
Nepomuk::Query::Term& term ) +{
+ addButton( title, QVariant::fromValue(term) );
+}
+
+
+Nepomuk::Query::Term Nepomuk::Query::SimpleListFacetWidget::termForButton( int \
button, const QVariant& data ) const +{
+ Q_UNUSED(button);
+ return data.value<Term>();
+}
+
+#include "simplelistfacetwidget.moc"
diff --git a/nepomuk/query/simplelistfacetwidget.h \
b/nepomuk/query/simplelistfacetwidget.h new file mode 100644
index 0000000..40cacbd
--- /dev/null
+++ b/nepomuk/query/simplelistfacetwidget.h
@@ -0,0 +1,51 @@
+/*
+ This file is part of the Nepomuk KDE project.
+ Copyright (C) 2010 Sebastian Trueg <trueg@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NEPOMUK_QUERY_SIMPLE_LIST_FACET_WIDGET_H_
+#define _NEPOMUK_QUERY_SIMPLE_LIST_FACET_WIDGET_H_
+
+#include "listfacetwidget.h"
+#include "nepomukquery_export.h"
+
+namespace Nepomuk {
+ namespace Query {
+ class NEPOMUKQUERY_EXPORT SimpleListFacetWidget : public ListFacetWidget
+ {
+ Q_OBJECT
+
+ public:
+ SimpleListFacetWidget( QWidget* parent = 0 );
+ ~SimpleListFacetWidget();
+
+ public Q_SLOTS:
+ void addTerm( const QString& title, const Nepomuk::Query::Term& term );
+
+ protected:
+ Term termForButton( int button, const QVariant& data ) const;
+
+ private:
+ class Private;
+ Private* const d;
+ };
+ }
+}
+
+#endif
_______________________________________________
Nepomuk mailing list
Nepomuk@kde.org
https://mail.kde.org/mailman/listinfo/nepomuk
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic