21 #include "tageditwidget_p.h"
24 #include <klineedit.h>
25 #include <klocalizedstring.h>
26 #include <kmessagebox.h>
27 #include <kcheckableproxymodel.h>
29 #include <akonadi/changerecorder.h>
30 #include <akonadi/tagcreatejob.h>
31 #include <akonadi/tagdeletejob.h>
32 #include <akonadi/tagfetchscope.h>
33 #include <akonadi/tagattribute.h>
37 #include <QHBoxLayout>
39 #include <QListWidget>
40 #include <QPushButton>
42 #include <QVBoxLayout>
45 using namespace Akonadi;
47 class TagEditWidget::Private :
public QObject
51 Private(Akonadi::TagModel *model, QWidget *parent);
54 void slotTextEdited(
const QString &text);
55 void slotItemEntered(
const QModelIndex &index);
56 void showDeleteButton();
59 void slotCreateTagFinished(KJob *job);
60 void onRowsInserted(
const QModelIndex &parent,
int start,
int end);
63 void select(
const QModelIndex &parent,
int start,
int end, QItemSelectionModel::SelectionFlag selectionFlag);
65 UrlTag = Qt::UserRole + 1
69 Akonadi::Tag::List m_tags;
70 Akonadi::TagModel *m_model;
71 QListView *m_tagsView;
72 KCheckableProxyModel *m_checkableProxy;
73 QModelIndex m_deleteCandidate;
74 QPushButton *m_newTagButton;
75 KLineEdit *m_newTagEdit;
77 QPushButton *m_deleteButton;
78 QTimer *m_deleteButtonTimer;
81 TagEditWidget::Private::Private(Akonadi::TagModel *model, QWidget *parent)
90 m_deleteButtonTimer(0)
95 void TagEditWidget::Private::select(
const QModelIndex &parent,
int start,
int end, QItemSelectionModel::SelectionFlag selectionFlag)
97 QItemSelection selection;
98 for (
int i = start; i <= end; i++) {
99 const QModelIndex index = m_model->index(i, 0, parent);
101 if (m_tags.contains(insertedTag)) {
102 selection.select(index, index);
105 m_checkableProxy->selectionModel()->select(selection, selectionFlag);
108 void TagEditWidget::Private::onRowsInserted(
const QModelIndex &parent,
int start,
int end)
110 select(parent, start, end, QItemSelectionModel::Select);
113 void TagEditWidget::Private::slotCreateTag()
116 connect(createJob, SIGNAL(finished(KJob*)),
117 this, SLOT(slotCreateTagFinished(KJob*)));
119 m_newTagEdit->clear();
120 m_newTagEdit->setEnabled(
false);
121 m_newTagButton->setEnabled(
false);
124 void TagEditWidget::Private::slotCreateTagFinished(KJob *job)
127 KMessageBox::error(d, i18n(
"An error occurred while creating a new tag"),
128 i18n(
"Failed to create a new tag"));
131 m_newTagEdit->setEnabled(
true);
134 void TagEditWidget::Private::slotTextEdited(
const QString &text)
139 const QString tagText = text.simplified();
140 if (tagText.isEmpty()) {
141 m_newTagButton->setEnabled(
false);
146 const int count = m_model->rowCount();
148 for (
int i = 0; i < count; ++i) {
149 const QModelIndex index = m_model->index(i, 0, QModelIndex());
150 if (index.data(Qt::DisplayRole).toString() == tagText) {
155 m_newTagButton->setEnabled(!exists);
158 void TagEditWidget::Private::slotItemEntered(
const QModelIndex &index)
162 const QRect rect = m_tagsView->visualRect(index);
163 const int size = rect.height();
164 const int x = rect.right() - size;
165 const int y = rect.top();
166 m_deleteButton->move(x, y);
167 m_deleteButton->resize(size, size);
169 m_deleteCandidate = index;
170 m_deleteButtonTimer->start();
173 void TagEditWidget::Private::showDeleteButton()
175 m_deleteButton->show();
178 void TagEditWidget::Private::deleteTag()
180 Q_ASSERT(m_deleteCandidate.isValid());
182 const QString text = i18nc(
"@info",
183 "Do you really want to remove the tag <resource>%1</resource>?",
185 const QString caption = i18nc(
"@title",
"Delete tag");
186 const KGuiItem deleteItem(i18nc(
"@action:button",
"Delete"), KIcon(QLatin1String(
"edit-delete")));
187 const KGuiItem cancelItem(i18nc(
"@action:button",
"Cancel"), KIcon(QLatin1String(
"dialog-cancel")));
188 if (KMessageBox::warningYesNo(d, text, caption, deleteItem, cancelItem) == KMessageBox::Yes) {
193 TagEditWidget::TagEditWidget(Akonadi::TagModel *model, QWidget *parent,
bool enableSelection)
195 d(new Private(model, this))
197 QVBoxLayout *topLayout =
new QVBoxLayout(
this);
199 QItemSelectionModel *selectionModel =
new QItemSelectionModel(d->m_model,
this);
200 d->m_checkableProxy =
new KCheckableProxyModel(
this);
201 d->m_checkableProxy->setSourceModel(d->m_model);
202 d->m_checkableProxy->setSelectionModel(selectionModel);
203 connect(d->m_model, SIGNAL(rowsInserted(QModelIndex,
int,
int)), d.data(), SLOT(onRowsInserted(QModelIndex,
int,
int)));
205 d->m_tagsView =
new QListView(
this);
206 d->m_tagsView->setMouseTracking(
true);
207 d->m_tagsView->setSelectionMode(QAbstractItemView::NoSelection);
208 d->m_tagsView->installEventFilter(
this);
209 if (enableSelection) {
210 d->m_tagsView->setModel(d->m_checkableProxy);
212 d->m_tagsView->setModel(d->m_model);
214 connect(d->m_tagsView, SIGNAL(entered(QModelIndex)),
215 d.data(), SLOT(slotItemEntered(QModelIndex)));
217 d->m_newTagEdit =
new KLineEdit(
this);
218 d->m_newTagEdit->setClearButtonShown(
true);
219 connect(d->m_newTagEdit, SIGNAL(textEdited(QString)),
220 d.data(), SLOT(slotTextEdited(QString)));
222 d->m_newTagButton =
new QPushButton(i18nc(
"@label",
"Create new tag"));
223 d->m_newTagButton->setEnabled(
false);
224 connect(d->m_newTagButton , SIGNAL(clicked(
bool)),
225 d.data(), SLOT(slotCreateTag()));
227 QHBoxLayout *newTagLayout =
new QHBoxLayout();
228 newTagLayout->addWidget(d->m_newTagEdit, 1);
229 newTagLayout->addWidget(d->m_newTagButton);
231 if (enableSelection) {
232 QLabel *label =
new QLabel(i18nc(
"@label:textbox",
233 "Configure which tags should "
234 "be applied."),
this);
235 topLayout->addWidget(label);
237 topLayout->addWidget(d->m_tagsView);
238 topLayout->addLayout(newTagLayout);
240 setLayout(topLayout);
244 d->m_deleteButton =
new QPushButton(d->m_tagsView->viewport());
245 d->m_deleteButton->setIcon(KIcon(QLatin1String(
"edit-delete")));
246 d->m_deleteButton->setToolTip(i18nc(
"@info",
"Delete tag"));
247 d->m_deleteButton->hide();
248 connect(d->m_deleteButton, SIGNAL(clicked()), d.data(), SLOT(deleteTag()));
250 d->m_deleteButtonTimer =
new QTimer(
this);
251 d->m_deleteButtonTimer->setSingleShot(
true);
252 d->m_deleteButtonTimer->setInterval(500);
253 connect(d->m_deleteButtonTimer, SIGNAL(timeout()), d.data(), SLOT(showDeleteButton()));
256 TagEditWidget::~TagEditWidget()
261 void TagEditWidget::setSelection(
const Akonadi::Tag::List &tags)
264 d->select(QModelIndex(), 0, d->m_model->rowCount() - 1, QItemSelectionModel::ClearAndSelect);
267 Akonadi::Tag::List TagEditWidget::selection()
269 Akonadi::Tag::List list;
270 for (
int i = 0; i < d->m_checkableProxy->rowCount(); ++i) {
271 if (d->m_checkableProxy->selectionModel()->isRowSelected(i, QModelIndex())) {
272 const QModelIndex index = d->m_checkableProxy->index(i, 0, QModelIndex());
280 bool TagEditWidget::eventFilter(QObject *watched, QEvent *event)
282 if ((watched == d->m_tagsView) && (event->type() == QEvent::Leave)) {
283 d->m_deleteButtonTimer->stop();
284 d->m_deleteButton->hide();
286 return QWidget::eventFilter(watched, event);
290 #include "tageditwidget.moc"
Job that creates a new tag in the Akonadi storage.