Warning, file /office/calligra/libs/widgets/KoResourceTaggingManager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  *    This file is part of the KDE project
0003  *    Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
0004  *    Copyright (c) 2007 Jan Hambrecht <jaham@gmx.net>
0005  *    Copyright (c) 2007 Sven Langkamp <sven.langkamp@gmail.com>
0006  *    Copyright (C) 2011 Srikanth Tiyyagura <srikanth.tulasiram@gmail.com>
0007  *    Copyright (c) 2011 José Luis Vergara <pentalis@gmail.com>
0008  *    Copyright (c) 2013 Sascha Suelzer <s.suelzer@gmail.com>
0009  *
0010  *    This library is free software; you can redistribute it and/or
0011  *    modify it under the terms of the GNU Library General Public
0012  *    License as published by the Free Software Foundation; either
0013  *    version 2 of the License, or (at your option) any later version.
0014  *
0015  *    This library is distributed in the hope that it will be useful,
0016  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0018  *    Library General Public License for more details.
0019  *
0020  *    You should have received a copy of the GNU Library General Public License
0021  *    along with this library; see the file COPYING.LIB.  If not, write to
0022  *    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0023  *    Boston, MA 02110-1301, USA.
0024  */
0025 
0026 #include "KoResourceTaggingManager.h"
0027 
0028 #include <QInputDialog>
0029 #include <QMessageBox>
0030 #include <QPointer>
0031 
0032 #include <WidgetsDebug.h>
0033 
0034 #include <klocalizedstring.h>
0035 #include <ksharedconfig.h>
0036 
0037 #include "KoTagFilterWidget.h"
0038 #include "KoTagChooserWidget.h"
0039 #include "KoResourceModel.h"
0040 #include "KoResource.h"
0041 #include "KoResourceItemChooserContextMenu.h"
0042 
0043 #include <kconfiggroup.h>
0044 
0045 class TaggedResourceSet
0046 {
0047 public:
0048     TaggedResourceSet()
0049     {}
0050 
0051     TaggedResourceSet(const QString& tagName, const QList<KoResource*>& resources)
0052         : tagName(tagName)
0053         , resources(resources)
0054     {}
0055 
0056     QString tagName;
0057     QList<KoResource*> resources;
0058 };
0059 
0060 
0061 class KoResourceTaggingManager::Private
0062 {
0063 public:
0064     QString currentTag;
0065     QList<KoResource*> originalResources;
0066     TaggedResourceSet lastDeletedTag;
0067 
0068     KoTagChooserWidget* tagChooser;
0069     KoTagFilterWidget* tagFilter;
0070 
0071     QCompleter* tagCompleter;
0072 
0073     QPointer<KoResourceModel> model;
0074 };
0075 
0076 
0077 KoResourceTaggingManager::KoResourceTaggingManager(KoResourceModel *model, QWidget* parent)
0078     : QObject(parent)
0079     , d(new Private())
0080 {
0081     d->model = model;
0082 
0083     d->tagChooser = new KoTagChooserWidget(parent);
0084     d->tagChooser->addReadOnlyItem("All"); // not translatable until other tags made translatable!
0085     d->tagChooser->addItems(d->model->tagNamesList());
0086 
0087     d->tagFilter = new KoTagFilterWidget(parent);
0088 
0089     connect(d->tagChooser, SIGNAL(tagChosen(QString)),
0090             this, SLOT(tagChooserIndexChanged(QString)));
0091     connect(d->tagChooser, SIGNAL(newTagRequested(QString)),
0092             this, SLOT(contextCreateNewTag(QString)));
0093     connect(d->tagChooser, SIGNAL(tagDeletionRequested(QString)),
0094             this, SLOT(removeTagFromComboBox(QString)));
0095     connect(d->tagChooser, SIGNAL(tagRenamingRequested(QString,QString)),
0096             this, SLOT(renameTag(QString,QString)));
0097     connect(d->tagChooser, SIGNAL(tagUndeletionRequested(QString)),
0098             this, SLOT(undeleteTag(QString)));
0099     connect(d->tagChooser, SIGNAL(tagUndeletionListPurgeRequested()),
0100             this, SLOT(purgeTagUndeleteList()));
0101 
0102     connect(d->tagFilter, SIGNAL(saveButtonClicked()),
0103             this, SLOT(tagSaveButtonPressed()));
0104     connect(d->tagFilter, SIGNAL(filterTextChanged(QString)),
0105             this, SLOT(tagSearchLineEditTextChanged(QString)));
0106 
0107     connect(d->model, SIGNAL(tagBoxEntryAdded(QString)),
0108             this, SLOT(syncTagBoxEntryAddition(QString)));
0109     connect(d->model, SIGNAL(tagBoxEntryRemoved(QString)),
0110             this, SLOT(syncTagBoxEntryRemoval(QString)));
0111     connect(d->model, SIGNAL(tagBoxEntryModified()),
0112             this, SLOT(syncTagBoxEntries()));
0113 
0114     // FIXME: fix tag completer
0115     // d->tagCompleter = new QCompleter(this);
0116     //  d->tagSearchLineEdit->setCompleter(d->tagCompleter);
0117 
0118     syncTagBoxEntries();
0119 }
0120 
0121 KoResourceTaggingManager::~KoResourceTaggingManager()
0122 {
0123     delete d;
0124 }
0125 
0126 void KoResourceTaggingManager::showTaggingBar(bool show)
0127 {
0128     show ? d->tagFilter->show() : d->tagFilter->hide();
0129     show ? d->tagChooser->show() : d->tagChooser->hide();
0130 
0131     blockSignals(!show);
0132 
0133     QString tag("All");
0134     if (show) {
0135         KConfigGroup group =  KSharedConfig::openConfig()->group("SelectedTags");
0136         tag = group.readEntry<QString>(d->model->serverType(), "All");
0137     }
0138 
0139     d->tagChooser->setCurrentIndex(d->tagChooser->findIndexOf(tag));
0140 }
0141 
0142 void KoResourceTaggingManager::purgeTagUndeleteList()
0143 {
0144     d->lastDeletedTag = TaggedResourceSet();
0145     d->tagChooser->setUndeletionCandidate(QString());
0146 }
0147 
0148 void KoResourceTaggingManager::undeleteTag(const QString & tagToUndelete)
0149 {
0150     QString tagName = tagToUndelete;
0151     QStringList allTags = availableTags();
0152 
0153     if (allTags.contains(tagName)) {
0154         bool ok;
0155         tagName = QInputDialog::getText(
0156                       d->tagChooser, i18n("Unable to undelete tag"),
0157                       i18n("<qt>The tag you are trying to undelete already exists in tag list.<br>Please enter a new, unique name for it.</qt>"),
0158                       QLineEdit::Normal,
0159                       tagName, &ok);
0160 
0161         if (!ok || allTags.contains(tagName) || tagName.isEmpty()) {
0162             QMessageBox msgBox;
0163             msgBox.setIcon(QMessageBox::Warning);
0164             msgBox.setText(i18n("Tag was not undeleted."));
0165             msgBox.exec();
0166             return;
0167         }
0168     }
0169 
0170     QList<KoResource*> serverResources = d->model->serverResources();
0171 
0172     foreach(KoResource * resource, d->lastDeletedTag.resources) {
0173         if (serverResources.contains(resource)) {
0174             addResourceTag(resource, tagName);
0175         }
0176     }
0177     d->model->tagCategoryAdded(tagName);
0178     d->tagChooser->setCurrentIndex(d->tagChooser->findIndexOf(tagName));
0179     d->tagChooser->setUndeletionCandidate(QString());
0180     d->lastDeletedTag = TaggedResourceSet();
0181 }
0182 
0183 QStringList KoResourceTaggingManager::availableTags() const
0184 {
0185     return d->tagChooser->allTags();
0186 }
0187 
0188 void KoResourceTaggingManager::addResourceTag(KoResource* resource, const QString& tagName)
0189 {
0190     QStringList tagsList = d->model->assignedTagsList(resource);
0191     if (tagsList.isEmpty()) {
0192         d->model->addTag(resource, tagName);
0193     } else {
0194         foreach(const QString & tag, tagsList) {
0195             if (tag.compare(tagName)) {
0196                 d->model->addTag(resource, tagName);
0197             }
0198         }
0199     }
0200 }
0201 
0202 void KoResourceTaggingManager::syncTagBoxEntryAddition(const QString& tag)
0203 {
0204     d->tagChooser->insertItem(tag);
0205 }
0206 
0207 void KoResourceTaggingManager::contextCreateNewTag(const QString& tag)
0208 {
0209     if (!tag.isEmpty()) {
0210         d->model->addTag(0, tag);
0211         d->model->tagCategoryAdded(tag);
0212         d->tagChooser->setCurrentIndex(d->tagChooser->findIndexOf(tag));
0213         updateTaggedResourceView();
0214     }
0215 }
0216 
0217 void KoResourceTaggingManager::contextCreateNewTag(KoResource* resource , const QString& tag)
0218 {
0219     if (!tag.isEmpty()) {
0220         d->model->tagCategoryAdded(tag);
0221         if (resource) {
0222             addResourceTag(resource, tag);
0223         }
0224     }
0225 }
0226 
0227 void KoResourceTaggingManager::syncTagBoxEntryRemoval(const QString& tag)
0228 {
0229     d->tagChooser->removeItem(tag);
0230 }
0231 
0232 void KoResourceTaggingManager::syncTagBoxEntries()
0233 {
0234     QStringList tags = d->model->tagNamesList();
0235 
0236     foreach (const QString &tag, tags) {
0237         d->tagChooser->insertItem(tag);
0238     }
0239 }
0240 
0241 void KoResourceTaggingManager::contextAddTagToResource(KoResource* resource, const QString& tag)
0242 {
0243     addResourceTag(resource, tag);
0244     d->model->tagCategoryMembersChanged();
0245     updateTaggedResourceView();
0246 }
0247 
0248 void KoResourceTaggingManager::contextRemoveTagFromResource(KoResource* resource, const QString& tag)
0249 {
0250     removeResourceTag(resource, tag);
0251     d->model->tagCategoryMembersChanged();
0252     updateTaggedResourceView();
0253 }
0254 
0255 void KoResourceTaggingManager::removeTagFromComboBox(const QString &tag)
0256 {
0257     QList<KoResource*> resources = d->model->currentlyVisibleResources();
0258     foreach(KoResource * resource, resources) {
0259         removeResourceTag(resource, tag);
0260     }
0261     d->model->tagCategoryRemoved(tag);
0262     d->lastDeletedTag = TaggedResourceSet(tag, resources);
0263     d->tagChooser->setUndeletionCandidate(tag);
0264 }
0265 
0266 void KoResourceTaggingManager::removeResourceTag(KoResource* resource, const QString& tagName)
0267 {
0268     QStringList tagsList = d->model->assignedTagsList(resource);
0269 
0270     foreach(const QString & oldName, tagsList) {
0271         if (!oldName.compare(tagName)) {
0272             d->model->deleteTag(resource, oldName);
0273         }
0274     }
0275 }
0276 
0277 void KoResourceTaggingManager::renameTag(const QString &oldName, const QString& newName)
0278 {
0279     if (!d->model->tagNamesList().contains(newName)) {
0280         QList<KoResource*> resources = d->model->currentlyVisibleResources();
0281 
0282         foreach(KoResource * resource, resources) {
0283             removeResourceTag(resource, oldName);
0284             addResourceTag(resource, newName);
0285         }
0286         contextCreateNewTag(newName);
0287         d->model->tagCategoryRemoved(oldName);
0288         d->model->tagCategoryAdded(newName);
0289     }
0290 }
0291 
0292 void KoResourceTaggingManager::updateTaggedResourceView()
0293 {
0294     d->model->setCurrentTag(d->currentTag);
0295     d->model->updateServer();
0296     d->originalResources = d->model->currentlyVisibleResources();
0297 }
0298 
0299 void KoResourceTaggingManager::tagChooserIndexChanged(const QString& lineEditText)
0300 {
0301     if (!d->tagChooser->selectedTagIsReadOnly()) {
0302         d->currentTag = lineEditText;
0303         d->tagFilter->allowSave(true);
0304         d->model->enableResourceFiltering(true);
0305     } else {
0306         d->model->enableResourceFiltering(false);
0307         d->tagFilter->allowSave(false);
0308         d->currentTag.clear();
0309     }
0310 
0311     d->tagFilter->clear();
0312     updateTaggedResourceView();
0313 }
0314 
0315 QString KoResourceTaggingManager::currentTag()
0316 {
0317     return d->tagChooser->currentlySelectedTag();
0318 }
0319 
0320 void KoResourceTaggingManager::tagSearchLineEditTextChanged(const QString& lineEditText)
0321 {
0322     if (d->tagChooser->selectedTagIsReadOnly()) {
0323         d->model->enableResourceFiltering(!lineEditText.isEmpty());
0324     } else {
0325         d->model->enableResourceFiltering(true);
0326     }
0327 
0328     d->model->searchTextChanged(lineEditText);
0329     d->model->updateServer();
0330 
0331     ///FIXME: fix completer
0332     //     d->tagCompleter = new QCompleter(tagNamesList(lineEditText),this);
0333     //    d->tagSearchLineEdit->setCompleter(d->tagCompleter);
0334 }
0335 
0336 void KoResourceTaggingManager::tagSaveButtonPressed()
0337 {
0338     if (!d->tagChooser->selectedTagIsReadOnly()) {
0339         QList<KoResource*> newResources = d->model->currentlyVisibleResources();
0340         foreach(KoResource * oldRes, d->originalResources) {
0341             if (!newResources.contains(oldRes))
0342                 removeResourceTag(oldRes, d->currentTag);
0343         }
0344         foreach(KoResource * newRes, newResources) {
0345             if (!d->originalResources.contains(newRes))
0346                 addResourceTag(newRes, d->currentTag);
0347         }
0348         d->model->tagCategoryMembersChanged();
0349     }
0350     updateTaggedResourceView();
0351 }
0352 
0353 void KoResourceTaggingManager::contextMenuRequested(KoResource* resource, const QStringList& resourceTags, const QPoint& pos)
0354 {
0355     /* no visible tag chooser usually means no intended tag interaction,
0356      * context menu makes no sense then either */
0357     if (!resource || !d->tagChooser->isVisible())
0358         return;
0359 
0360     KoResourceItemChooserContextMenu menu(resource,
0361                                           resourceTags,
0362                                           d->tagChooser->currentlySelectedTag(),
0363                                           d->tagChooser->allTags());
0364 
0365     connect(&menu, SIGNAL(resourceTagAdditionRequested(KoResource*,QString)),
0366             this, SLOT(contextAddTagToResource(KoResource*,QString)));
0367 
0368     connect(&menu, SIGNAL(resourceTagRemovalRequested(KoResource*,QString)),
0369             this, SLOT(contextRemoveTagFromResource(KoResource*,QString)));
0370 
0371     connect(&menu, SIGNAL(resourceAssignmentToNewTagRequested(KoResource*,QString)),
0372             this, SLOT(contextCreateNewTag(KoResource*,QString)));
0373     menu.exec(pos);
0374 }
0375 
0376 void KoResourceTaggingManager::contextMenuRequested(KoResource* currentResource, QPoint pos)
0377 {
0378     if (currentResource) {
0379         contextMenuRequested(currentResource, d->model->assignedTagsList(currentResource), pos);
0380     }
0381 }
0382 
0383 KoTagChooserWidget* KoResourceTaggingManager::tagChooserWidget()
0384 {
0385     return d->tagChooser;
0386 }
0387 
0388 KoTagFilterWidget* KoResourceTaggingManager::tagFilterWidget()
0389 {
0390     return d->tagFilter;
0391 }
0392