Warning, file /libraries/baloo-widgets/src/kedittagsdialog.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2009 Peter Penz <peter.penz@gmx.at> 0003 SPDX-FileCopyrightText: 2014 Vishesh Handa <me@vhanda.in> 0004 SPDX-FileCopyrightText: 2017 James D. Smith <smithjd15@gmail.com 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #include "kedittagsdialog_p.h" 0010 0011 #include <KLocalizedString> 0012 0013 #include <QDialogButtonBox> 0014 #include <QHBoxLayout> 0015 #include <QLabel> 0016 #include <QLineEdit> 0017 #include <QPushButton> 0018 #include <QTreeWidget> 0019 #include <QVBoxLayout> 0020 #include <QWidget> 0021 0022 #include <Baloo/TagListJob> 0023 0024 KEditTagsDialog::KEditTagsDialog(const QStringList &tags, QWidget *parent) 0025 : QDialog(parent) 0026 , m_tags(tags) 0027 { 0028 const QString captionText = (tags.count() > 0) ? i18nc("@title:window", "Edit Tags") : i18nc("@title:window", "Add Tags"); 0029 setWindowTitle(captionText); 0030 auto buttonBox = new QDialogButtonBox(this); 0031 0032 buttonBox->addButton(i18n("Save"), QDialogButtonBox::AcceptRole); 0033 buttonBox->addButton(QDialogButtonBox::Cancel); 0034 0035 connect(buttonBox, &QDialogButtonBox::accepted, this, &KEditTagsDialog::slotAcceptedButtonClicked); 0036 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0037 0038 auto topLayout = new QVBoxLayout; 0039 setLayout(topLayout); 0040 0041 auto label = new QLabel(i18nc("@label:textbox", 0042 "Configure which tags should " 0043 "be applied."), 0044 this); 0045 0046 m_tagTree = new QTreeWidget(); 0047 m_tagTree->setSortingEnabled(true); 0048 m_tagTree->setSelectionMode(QAbstractItemView::NoSelection); 0049 m_tagTree->setHeaderHidden(true); 0050 0051 auto newTagLabel = new QLabel(i18nc("@label", "Create new tag:")); 0052 m_newTagEdit = new QLineEdit(this); 0053 m_newTagEdit->setClearButtonEnabled(true); 0054 m_newTagEdit->setFocus(); 0055 connect(m_newTagEdit, &QLineEdit::textEdited, this, &KEditTagsDialog::slotTextEdited); 0056 connect(m_tagTree, &QTreeWidget::itemActivated, this, &KEditTagsDialog::slotItemActivated); 0057 0058 auto newTagLayout = new QHBoxLayout(); 0059 newTagLayout->addWidget(newTagLabel); 0060 newTagLayout->addWidget(m_newTagEdit, 1); 0061 0062 topLayout->addWidget(label); 0063 topLayout->addWidget(m_tagTree); 0064 topLayout->addLayout(newTagLayout); 0065 topLayout->addWidget(buttonBox); 0066 0067 resize(sizeHint()); 0068 0069 auto job = new Baloo::TagListJob(); 0070 connect(job, &Baloo::TagListJob::finished, [this](KJob *job) { 0071 auto tjob = static_cast<Baloo::TagListJob *>(job); 0072 m_allTags = tjob->tags(); 0073 loadTagWidget(); 0074 }); 0075 0076 job->start(); 0077 } 0078 0079 KEditTagsDialog::~KEditTagsDialog() = default; 0080 0081 QStringList KEditTagsDialog::tags() const 0082 { 0083 return m_tags; 0084 } 0085 0086 void KEditTagsDialog::slotAcceptedButtonClicked() 0087 { 0088 m_tags.clear(); 0089 0090 for (const QTreeWidgetItem *item : std::as_const(m_allTagTreeItems)) { 0091 if (item->checkState(0) == Qt::Checked) { 0092 m_tags << qvariant_cast<QString>(item->data(0, Qt::UserRole)); 0093 } 0094 } 0095 0096 accept(); 0097 } 0098 0099 void KEditTagsDialog::slotItemActivated(const QTreeWidgetItem *item, int column) 0100 { 0101 Q_UNUSED(column) 0102 0103 const auto tag = qvariant_cast<QString>(item->data(0, Qt::UserRole)); 0104 m_newTagEdit->setText(tag + QLatin1Char('/')); 0105 m_newTagEdit->setFocus(); 0106 } 0107 0108 void KEditTagsDialog::slotTextEdited(const QString &text) 0109 { 0110 // Remove unnecessary spaces from a new tag is 0111 // mandatory, as the user cannot see the difference 0112 // between a tag "Test" and "Test ". 0113 QString tagText = text.simplified(); 0114 while (tagText.endsWith(QLatin1String("//"))) { 0115 tagText.chop(1); 0116 m_newTagEdit->setText(tagText); 0117 return; 0118 } 0119 0120 // Remove all tree items related to the previous new tag 0121 const QStringList splitTag = m_newTag.split(QLatin1Char('/'), Qt::SkipEmptyParts); 0122 for (int i = splitTag.size() - 1; i >= 0 && i < splitTag.size(); --i) { 0123 QString itemTag = m_newTag.section(QLatin1Char('/'), 0, i, QString::SectionSkipEmpty); 0124 QTreeWidgetItem *item = m_allTagTreeItems.value(itemTag); 0125 0126 if (!m_allTags.contains(m_newTag) && (item->childCount() == 0)) { 0127 if (i != 0) { 0128 QTreeWidgetItem *parentItem = item->parent(); 0129 parentItem->removeChild(item); 0130 } else { 0131 const int row = m_tagTree->indexOfTopLevelItem(item); 0132 m_tagTree->takeTopLevelItem(row); 0133 } 0134 0135 m_allTagTreeItems.remove(itemTag); 0136 } 0137 0138 if (!m_tags.contains(itemTag)) { 0139 item->setCheckState(0, Qt::Unchecked); 0140 } 0141 0142 item->setExpanded(false); 0143 } 0144 0145 if (!tagText.isEmpty()) { 0146 m_newTag = tagText; 0147 modifyTagWidget(tagText); 0148 m_tagTree->sortItems(0, Qt::SortOrder::AscendingOrder); 0149 } else { 0150 m_newTag.clear(); 0151 m_allTagTreeItems.clear(); 0152 m_tagTree->clear(); 0153 loadTagWidget(); 0154 } 0155 } 0156 0157 void KEditTagsDialog::loadTagWidget() 0158 { 0159 for (const QString &tag : std::as_const(m_tags)) { 0160 modifyTagWidget(tag); 0161 } 0162 0163 for (const QString &tag : std::as_const(m_allTags)) { 0164 modifyTagWidget(tag); 0165 } 0166 0167 m_tagTree->sortItems(0, Qt::SortOrder::AscendingOrder); 0168 } 0169 0170 void KEditTagsDialog::modifyTagWidget(const QString &tag) 0171 { 0172 const QStringList splitTag = tag.split(QLatin1Char('/'), Qt::SkipEmptyParts); 0173 for (int i = 0; i < splitTag.size(); ++i) { 0174 QTreeWidgetItem *item; 0175 QString itemTag = tag.section(QLatin1Char('/'), 0, i, QString::SectionSkipEmpty); 0176 0177 if (!m_allTagTreeItems.contains(itemTag)) { 0178 item = new QTreeWidgetItem(); 0179 item->setText(0, splitTag.at(i)); 0180 item->setIcon(0, QIcon::fromTheme(QLatin1String("tag"))); 0181 item->setData(0, Qt::UserRole, itemTag); 0182 m_allTagTreeItems.insert(itemTag, item); 0183 QString parentTag = tag.section(QLatin1Char('/'), 0, (i - 1), QString::SectionSkipEmpty); 0184 QTreeWidgetItem *parentItem = m_allTagTreeItems.value(parentTag); 0185 0186 if (i != 0) { 0187 parentItem->addChild(item); 0188 } else { 0189 m_tagTree->addTopLevelItem(item); 0190 } 0191 } else { 0192 item = m_allTagTreeItems.value(itemTag); 0193 } 0194 0195 if (!m_allTags.contains(tag)) { 0196 m_tagTree->scrollToItem(item, QAbstractItemView::PositionAtCenter); 0197 } 0198 0199 if (((item->childCount() != 0) && m_tags.contains(tag)) || (m_newTag == tag)) { 0200 item->setExpanded(true); 0201 } else if (item->parent() && m_tags.contains(tag)) { 0202 item->parent()->setExpanded(true); 0203 } 0204 0205 const bool check = (m_tags.contains(itemTag) || (m_newTag == itemTag)); 0206 item->setCheckState(0, check ? Qt::Checked : Qt::Unchecked); 0207 } 0208 }