Commit d510de6b authored by Tobias Koenig's avatar Tobias Koenig

Add edit field for categories

CCMAIL: annew@kde.org

svn path=/trunk/KDE/kdepimlibs/; revision=1072327
parent 8bf58da4
find_package(Nepomuk)
macro_log_feature(Nepomuk_FOUND "Nepomuk" "The Nepomuk libraries" "http://www.kde.org" TRUE "" "Nepomuk extends the search and tagging functionalities in KMail and Akonadi")
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
......@@ -21,6 +25,7 @@ kde4_add_kcfg_files(akonadicontact_actions_SRCS actions/contactactionssettings.k
set(akonadicontact_editor_SRCS
editor/addresseditwidget.cpp
editor/categorieseditwidget.cpp
editor/contacteditorwidget.cpp
editor/dateeditwidget.cpp
editor/displaynameeditwidget.cpp
......@@ -30,10 +35,12 @@ set(akonadicontact_editor_SRCS
editor/imagewidget.cpp
editor/imeditwidget.cpp
editor/kdatepickerpopup.cpp
editor/kedittagsdialog.cpp
editor/nameeditwidget.cpp
editor/phoneeditwidget.cpp
editor/secrecyeditwidget.cpp
editor/soundeditwidget.cpp
editor/tagwidget.cpp
)
set(akonadicontact_LIB_SRC
......@@ -75,14 +82,16 @@ target_link_libraries(akonadi-contact akonadi-kde
kcal
${KDE4_KDEUI_LIBS}
${KDE4_KIO_LIBS}
${KDE4_PHONON_LIBS})
${KDE4_PHONON_LIBS}
${NEPOMUK_LIBRARIES})
target_link_libraries(akonadi-contact LINK_INTERFACE_LIBRARIES
akonadi-kde
kabc
kcal
${KDE4_KDEUI_LIBS}
${KDE4_KIO_LIBS}
${KDE4_PHONON_LIBS})
${KDE4_PHONON_LIBS}
${NEPOMUK_LIBRARIES})
set_target_properties(akonadi-contact PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION})
......
/*
This file is part of Akonadi Contact.
Copyright (c) 2009 Tobias Koenig <tokoe@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "categorieseditwidget.h"
#include "tagwidget.h"
#include <akonadi/item.h>
#include <kabc/addressee.h>
#include <kcombobox.h>
#include <kdialog.h>
#include <klocale.h>
#include <nepomuk/tag.h>
#include <QtCore/QString>
#include <QtGui/QHBoxLayout>
CategoriesEditWidget::CategoriesEditWidget( QWidget *parent )
: QWidget( parent )
{
QHBoxLayout *layout = new QHBoxLayout( this );
layout->setMargin( 0 );
layout->setSpacing( KDialog::spacingHint() );
mTagWidget = new TagWidget( this );
layout->addWidget( mTagWidget );
}
CategoriesEditWidget::~CategoriesEditWidget()
{
}
void CategoriesEditWidget::setReadOnly( bool readOnly )
{
mTagWidget->setEnabled( !readOnly );
}
void CategoriesEditWidget::loadContact( const KABC::Addressee &contact )
{
QList<Nepomuk::Tag> tags;
const QStringList categories = contact.categories();
foreach ( const QString &category, categories )
tags.append( Nepomuk::Tag( category ) );
mTagWidget->setTags( tags );
}
void CategoriesEditWidget::storeContact( KABC::Addressee &contact ) const
{
QStringList categories;
const QList<Nepomuk::Tag> tags = mTagWidget->tags();
foreach ( const Nepomuk::Tag &tag, tags )
categories.append( tag.genericLabel() );
contact.setCategories( categories );
}
#include "categorieseditwidget.moc"
/*
This file is part of Akonadi Contact.
Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef CATEGORIESEDITWIDGET_H
#define CATEGORIESEDITWIDGET_H
#include <QtGui/QWidget>
#include <kabc/addressee.h>
class TagWidget;
/**
* @short A widget for editing the categories of a contact.
*/
class CategoriesEditWidget : public QWidget
{
Q_OBJECT
public:
explicit CategoriesEditWidget( QWidget *parent = 0 );
~CategoriesEditWidget();
void loadContact( const KABC::Addressee &contact );
void storeContact( KABC::Addressee &contact ) const;
void setReadOnly( bool readOnly );
private:
TagWidget *mTagWidget;
};
#endif
......@@ -22,6 +22,7 @@
#include "contacteditorwidget.h"
#include "addresseditwidget.h"
#include "categorieseditwidget.h"
#include "contacteditorpageplugin.h"
#include "contactmetadata_p.h"
#include "dateeditwidget.h"
......@@ -88,6 +89,8 @@ class ContactEditorWidget::Private
// widgets from phones group
PhoneEditWidget *mPhonesWidget;
CategoriesEditWidget *mCategoriesWidget;
// widgets from addresses group
AddressEditWidget *mAddressesWidget;
......@@ -237,6 +240,19 @@ void ContactEditorWidget::Private::initGuiContactTab()
phonesLayout->addWidget( mPhonesWidget, 0, 0 );
phonesLayout->setRowStretch( 1, 1 );
// setup categories section
QHBoxLayout *categoriesLayout = new QHBoxLayout;
label = new QLabel( i18n( "Categories:" ) );
label->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
mCategoriesWidget = new CategoriesEditWidget;
label->setBuddy( mCategoriesWidget );
categoriesLayout->addWidget( label );
categoriesLayout->addWidget( mCategoriesWidget );
layout->addLayout( categoriesLayout );
}
void ContactEditorWidget::Private::initGuiLocationTab()
......@@ -486,6 +502,9 @@ void ContactEditorWidget::loadContact( const KABC::Addressee &contact, const Ako
// phones group
d->mPhonesWidget->loadContact( contact );
// categories section
d->mCategoriesWidget->loadContact( contact );
// address group
d->mAddressesWidget->loadContact( contact );
......@@ -541,6 +560,9 @@ void ContactEditorWidget::storeContact( KABC::Addressee &contact, Akonadi::Conta
// phones group
d->mPhonesWidget->storeContact( contact );
// categories section
d->mCategoriesWidget->storeContact( contact );
// address group
d->mAddressesWidget->storeContact( contact );
......@@ -595,6 +617,9 @@ void ContactEditorWidget::setReadOnly( bool readOnly )
// widgets from phones group
d->mPhonesWidget->setReadOnly( readOnly );
// widgets from categories section
d->mCategoriesWidget->setReadOnly( readOnly );
// widgets from addresses group
d->mAddressesWidget->setReadOnly( readOnly );
......
/*****************************************************************************
* Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License version 2 as published by the Free Software Foundation. *
* *
* 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 *
* Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public License *
* along with this library; see the file COPYING.LIB. If not, write to *
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301, USA. *
*****************************************************************************/
#include "kedittagsdialog_p.h"
#include <kicon.h>
#include <klineedit.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <QEvent>
#include <QHBoxLayout>
#include <QLabel>
#include <QListWidget>
#include <QPushButton>
#include <QTimer>
#include <QVBoxLayout>
#include <QWidget>
KEditTagsDialog::KEditTagsDialog(const QList<Nepomuk::Tag>& tags,
QWidget* parent,
Qt::WFlags flags) :
KDialog(parent, flags),
m_tags(tags),
m_tagsList(0),
m_newTagItem(0),
m_deleteCandidate(0),
m_newTagEdit(0),
m_deleteButtonTimer(0)
{
const QString caption = (tags.count() > 0) ?
i18nc("@title:window", "Change Tags") :
i18nc("@title:window", "Add Tags");
setCaption(caption);
setButtons(KDialog::Ok | KDialog::Cancel);
setDefaultButton(KDialog::Ok);
QWidget* mainWidget = new QWidget(this);
QVBoxLayout* topLayout = new QVBoxLayout(mainWidget);
QLabel* label = new QLabel(i18nc("@label:textbox",
"Configure which tags should "
"be applied."), this);
m_tagsList = new QListWidget(this);
m_tagsList->setMouseTracking(true);
m_tagsList->setSortingEnabled(true);
m_tagsList->setSelectionMode(QAbstractItemView::NoSelection);
m_tagsList->installEventFilter(this);
connect(m_tagsList, SIGNAL(itemEntered(QListWidgetItem*)),
this, SLOT(slotItemEntered(QListWidgetItem*)));
connect(m_tagsList, SIGNAL(itemEntered(QListWidgetItem*)),
this, SLOT(slotItemEntered(QListWidgetItem*)));
QLabel* newTagLabel = new QLabel(i18nc("@label", "Create new tag:"));
m_newTagEdit = new KLineEdit(this);
m_newTagEdit->setClearButtonShown(true);
connect(m_newTagEdit, SIGNAL(textEdited(const QString&)),
this, SLOT(slotTextEdited(const QString&)));
QHBoxLayout* newTagLayout = new QHBoxLayout();
newTagLayout->addWidget(newTagLabel);
newTagLayout->addWidget(m_newTagEdit, 1);
topLayout->addWidget(label);
topLayout->addWidget(m_tagsList);
topLayout->addLayout(newTagLayout);
setMainWidget(mainWidget);
loadTags();
// create the delete button, which is shown when
// hovering the items
m_deleteButton = new QPushButton(m_tagsList->viewport());
m_deleteButton->setIcon(KIcon(QLatin1String("edit-delete")));
m_deleteButton->setToolTip(i18nc("@info", "Delete tag"));
m_deleteButton->hide();
connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(deleteTag()));
m_deleteButtonTimer = new QTimer(this);
m_deleteButtonTimer->setSingleShot(true);
m_deleteButtonTimer->setInterval(500);
connect(m_deleteButtonTimer, SIGNAL(timeout()), this, SLOT(showDeleteButton()));
}
KEditTagsDialog::~KEditTagsDialog()
{
}
QList<Nepomuk::Tag> KEditTagsDialog::tags() const
{
return m_tags;
}
bool KEditTagsDialog::eventFilter(QObject* watched, QEvent* event)
{
if ((watched == m_tagsList) && (event->type() == QEvent::Leave)) {
m_deleteButtonTimer->stop();
m_deleteButton->hide();
}
return KDialog::eventFilter(watched, event);
}
void KEditTagsDialog::slotButtonClicked(int button)
{
if (button == KDialog::Ok) {
// update m_tags with the checked values, so
// that the caller of the KEditTagsDialog can
// receive the tags by KEditTagsDialog::tags()
m_tags.clear();
const int count = m_tagsList->count();
for (int i = 0; i < count; ++i) {
QListWidgetItem* item = m_tagsList->item(i);
if (item->checkState() == Qt::Checked) {
const QString label = item->data(Qt::UserRole).toString();
Nepomuk::Tag tag(label);
tag.setLabel(label);
m_tags.append(tag);
}
}
accept();
} else {
KDialog::slotButtonClicked(button);
}
}
void KEditTagsDialog::slotTextEdited(const QString& text)
{
// Remove unnecessary spaces from a new tag is
// mandatory, as the user cannot see the difference
// between a tag "Test" and "Test ".
const QString tagText = text.simplified();
if (tagText.isEmpty()) {
removeNewTagItem();
return;
}
// Check whether the new tag already exists. If this
// is the case, remove the new tag item.
const int count = m_tagsList->count();
for (int i = 0; i < count; ++i) {
const QListWidgetItem* item = m_tagsList->item(i);
const bool remove = (item->text() == tagText) &&
((m_newTagItem == 0) || (m_newTagItem != item));
if (remove) {
m_tagsList->scrollToItem(item);
removeNewTagItem();
return;
}
}
// There is no tag in the list with the the passed text.
if (m_newTagItem == 0) {
m_newTagItem = new QListWidgetItem(tagText, m_tagsList);
} else {
m_newTagItem->setText(tagText);
}
m_newTagItem->setData(Qt::UserRole, tagText);
m_newTagItem->setCheckState(Qt::Checked);
m_tagsList->scrollToItem(m_newTagItem);
}
void KEditTagsDialog::slotItemEntered(QListWidgetItem* item)
{
// align the delete-button to stay on the right border
// of the item
const QRect rect = m_tagsList->visualItemRect(item);
const int size = rect.height();
const int x = rect.right() - size;
const int y = rect.top();
m_deleteButton->move(x, y);
m_deleteButton->resize(size, size);
m_deleteCandidate = item;
m_deleteButtonTimer->start();
}
void KEditTagsDialog::showDeleteButton()
{
m_deleteButton->show();
}
void KEditTagsDialog::deleteTag()
{
Q_ASSERT(m_deleteCandidate != 0);
const QString text = i18nc("@info",
"Should the tag <resource>%1</resource> really be deleted for all files?",
m_deleteCandidate->text());
const QString caption = i18nc("@title", "Delete tag");
const KGuiItem deleteItem(i18nc("@action:button", "Delete"), KIcon(QLatin1String("edit-delete")));
const KGuiItem cancelItem(i18nc("@action:button", "Cancel"), KIcon(QLatin1String("dialog-cancel")));
if (KMessageBox::warningYesNo(this, text, caption, deleteItem, cancelItem) == KMessageBox::Yes) {
const QString label = m_deleteCandidate->data(Qt::UserRole).toString();
Nepomuk::Tag tag(label);
tag.remove();
// clear list and reload it
for (int i = m_tagsList->count() - 1; i >= 0; --i) {
QListWidgetItem* item = m_tagsList->takeItem(i);
delete item;
}
loadTags();
}
}
void KEditTagsDialog::loadTags()
{
// load all available tags and mark those tags as checked
// that have been passed to the KEditTagsDialog
const QList<Nepomuk::Tag> tags = Nepomuk::Tag::allTags();
foreach (const Nepomuk::Tag& tag, tags) {
const QString label = tag.label();
QListWidgetItem* item = new QListWidgetItem(label, m_tagsList);
item->setData(Qt::UserRole, label);
bool check = false;
foreach (const Nepomuk::Tag& selectedTag, m_tags) {
if (selectedTag.label() == label) {
check = true;
break;
}
}
item->setCheckState(check ? Qt::Checked : Qt::Unchecked);
}
}
void KEditTagsDialog::removeNewTagItem()
{
if (m_newTagItem != 0) {
const int row = m_tagsList->row(m_newTagItem);
m_tagsList->takeItem(row);
delete m_newTagItem;
m_newTagItem = 0;
}
}
#include "kedittagsdialog_p.moc"
/*****************************************************************************
* Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License version 2 as published by the Free Software Foundation. *
* *
* 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 *
* Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public License *
* along with this library; see the file COPYING.LIB. If not, write to *
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301, USA. *
*****************************************************************************/
#ifndef KEDIT_TAGS_DIALOG_H
#define KEDIT_TAGS_DIALOG_H
#include <kdialog.h>
#include <nepomuk/tag.h>
class KLineEdit;
class QListWidget;
class QListWidgetItem;
class QPushButton;
class QTimer;
/**
* @brief Dialog to edit a list of Nepomuk tags.
*
* It is possible for the user to add existing tags,
* create new tags or to remove tags.
*
* @see KMetaDataConfigurationDialog
*/
class KEditTagsDialog : public KDialog
{
Q_OBJECT
public:
KEditTagsDialog(const QList<Nepomuk::Tag>& tags,
QWidget* parent = 0,
Qt::WFlags flags = 0);
virtual ~KEditTagsDialog();
QList<Nepomuk::Tag> tags() const;
virtual bool eventFilter(QObject* watched, QEvent* event);
protected slots:
virtual void slotButtonClicked(int button);
private slots:
void slotTextEdited(const QString& text);
void slotItemEntered(QListWidgetItem* item);
void showDeleteButton();
void deleteTag();
private:
void loadTags();
void removeNewTagItem();
private:
QList<Nepomuk::Tag> m_tags;
QListWidget* m_tagsList;
QListWidgetItem* m_newTagItem;
QListWidgetItem* m_deleteCandidate;
KLineEdit* m_newTagEdit;
QPushButton* m_deleteButton;
QTimer* m_deleteButtonTimer;
};
#endif
/*
This file is part of Akonadi Contact.
Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "tagwidget.h"
#include "kedittagsdialog_p.h"
#include <kicon.h>
#include <klocale.h>
#include <QtGui/QHBoxLayout>
#include <QtGui/QLabel>
#include <QtGui/QToolButton>
TagWidget::TagWidget( QWidget *parent )
: QWidget( parent )