10#include "snippetsmodel.h"
12#include <KConfigGroup>
13#include <KLocalizedString>
15#include <KSharedConfig>
23class MailCommon::SnippetItem
26 explicit SnippetItem(
bool isGroup =
false, SnippetItem *parent =
nullptr);
29 [[nodiscard]]
bool isGroup()
const;
31 void setName(
const QString &name);
32 [[nodiscard]] QString name()
const;
34 void setText(
const QString &text);
35 [[nodiscard]] QString text()
const;
37 void setKeyword(
const QString &text);
38 [[nodiscard]] QString keyword()
const;
40 void setKeySequence(
const QString &sequence);
41 [[nodiscard]] QString keySequence()
const;
43 void insertChild(
int row, SnippetItem *child);
44 void removeChild(SnippetItem *child);
45 [[nodiscard]] SnippetItem *child(
int row)
const;
46 [[nodiscard]]
int childCount()
const;
47 [[nodiscard]]
int row()
const;
48 [[nodiscard]] SnippetItem *parent()
const;
50 [[nodiscard]] QString subject()
const;
51 void setSubject(
const QString &subject);
53 [[nodiscard]] QString to()
const;
54 void setTo(
const QString &to);
56 [[nodiscard]] QString cc()
const;
57 void setCc(
const QString &cc);
59 [[nodiscard]] QString bcc()
const;
60 void setBcc(
const QString &bcc);
62 [[nodiscard]] QString attachment()
const;
63 void setAttachment(
const QString &attachment);
66 QList<SnippetItem *> mChildItems;
67 SnippetItem *mParentItem =
nullptr;
69 bool mIsGroup =
false;
81SnippetItem::SnippetItem(
bool isGroup, SnippetItem *parent)
87SnippetItem::~SnippetItem()
89 qDeleteAll(mChildItems);
93bool SnippetItem::isGroup()
const
98void SnippetItem::setName(
const QString &name)
103QString SnippetItem::name()
const
108void SnippetItem::setText(
const QString &text)
113QString SnippetItem::text()
const
118void SnippetItem::setKeyword(
const QString &text)
123QString SnippetItem::keyword()
const
128void SnippetItem::setKeySequence(
const QString &sequence)
130 mKeySequence = sequence;
133QString SnippetItem::keySequence()
const
138void SnippetItem::insertChild(
int row, SnippetItem *item)
140 mChildItems.
insert(row, item);
143void SnippetItem::removeChild(SnippetItem *item)
145 mChildItems.removeAll(item);
149SnippetItem *SnippetItem::child(
int row)
const
151 return mChildItems.value(row);
154int SnippetItem::childCount()
const
156 return mChildItems.count();
159SnippetItem *SnippetItem::parent()
const
164QString SnippetItem::subject()
const
169void SnippetItem::setSubject(
const QString &subject)
174QString SnippetItem::to()
const
179void SnippetItem::setTo(
const QString &to)
184QString SnippetItem::cc()
const
189void SnippetItem::setCc(
const QString &cc)
194QString SnippetItem::bcc()
const
199void SnippetItem::setBcc(
const QString &bcc)
204QString SnippetItem::attachment()
const
209void SnippetItem::setAttachment(
const QString &attachment)
211 mAttachment = attachment;
214int SnippetItem::row()
const
217 return mParentItem->mChildItems.indexOf(
const_cast<SnippetItem *
>(
this));
225 static SnippetsModel s_self;
229SnippetsModel::SnippetsModel(QObject *parent)
230 : QAbstractItemModel(parent)
232 mRootItem =
new SnippetItem(
true);
236SnippetsModel::~SnippetsModel()
241int SnippetsModel::columnCount(
const QModelIndex &)
const
246bool SnippetsModel::setData(
const QModelIndex &index,
const QVariant &value,
int role)
248 if (!index.isValid()) {
252 auto item =
static_cast<SnippetItem *
>(index.internalPointer());
265 item->setKeySequence(value.
toString());
289 item->setAttachment(value.
toString());
297QVariant SnippetsModel::data(
const QModelIndex &index,
int role)
const
299 if (!index.isValid()) {
303 auto item =
static_cast<SnippetItem *
>(index.internalPointer());
309 return item->isGroup();
315 return item->keySequence();
317 return item->keyword();
319 return item->subject();
327 return item->attachment();
333Qt::ItemFlags SnippetsModel::flags(
const QModelIndex &index)
const
337 if (index.isValid()) {
338 const SnippetItem *item =
static_cast<SnippetItem *
>(index.internalPointer());
339 if (!item->isGroup()) {
347QModelIndex SnippetsModel::index(
int row,
int column,
const QModelIndex &parent)
const
349 if (!
hasIndex(row, column, parent)) {
353 SnippetItem *parentItem =
nullptr;
355 if (!parent.isValid()) {
356 parentItem = mRootItem;
358 parentItem =
static_cast<SnippetItem *
>(parent.internalPointer());
361 SnippetItem *childItem = parentItem->child(row);
371 if (!index.isValid()) {
375 auto childItem =
static_cast<SnippetItem *
>(index.internalPointer());
376 SnippetItem *parentItem = childItem->parent();
378 if (parentItem == mRootItem) {
382 return createIndex(parentItem->row(), 0, parentItem);
385int SnippetsModel::rowCount(
const QModelIndex &parent)
const
387 SnippetItem *parentItem =
nullptr;
388 if (parent.column() > 0) {
392 if (!parent.isValid()) {
393 parentItem = mRootItem;
395 parentItem =
static_cast<SnippetItem *
>(parent.internalPointer());
398 return parentItem->childCount();
401bool SnippetsModel::insertRows(
int row,
int count,
const QModelIndex &parent)
403 SnippetItem *parentItem =
nullptr;
405 if (!parent.isValid()) {
406 parentItem = mRootItem;
408 parentItem =
static_cast<SnippetItem *
>(parent.internalPointer());
412 for (
int i = 0; i < count; ++i) {
413 auto snippet =
new SnippetItem(!parent.isValid(), parentItem);
414 parentItem->insertChild(row, snippet);
421bool SnippetsModel::removeRows(
int row,
int count,
const QModelIndex &parent)
423 SnippetItem *parentItem =
nullptr;
425 if (!parent.isValid()) {
426 parentItem = mRootItem;
428 parentItem =
static_cast<SnippetItem *
>(parent.internalPointer());
432 for (
int i = 0; i < count; ++i) {
433 parentItem->removeChild(parentItem->child(row));
440QStringList SnippetsModel::mimeTypes()
const
442 return QStringList() << QStringLiteral(
"text/x-kmail-textsnippet") << QStringLiteral(
"text/plain");
445QMimeData *SnippetsModel::mimeData(
const QModelIndexList &indexes)
const
447 if (indexes.isEmpty()) {
451 const QModelIndex index = indexes.first();
453 auto item =
static_cast<SnippetItem *
>(index.internalPointer());
454 if (item->isGroup()) {
458 auto mimeData =
new QMimeData();
460 QByteArray encodedData;
462 stream << index.parent().internalId() << item->name() << item->text() << item->keySequence() << item->keyword() << item->subject() << item->to()
463 << item->cc() << item->bcc() << item->attachment();
465 mimeData->setData(QStringLiteral(
"text/x-kmail-textsnippet"), encodedData);
466 mimeData->setText(item->text());
471bool SnippetsModel::dropMimeData(
const QMimeData *data,
Qt::DropAction action,
int row,
int column,
const QModelIndex &parent)
477 if (data->hasFormat(QStringLiteral(
"text/x-kmail-textsnippet"))) {
478 if (!parent.isValid()) {
486 row = rowCount(parent);
489 auto item =
static_cast<SnippetItem *
>(parent.internalPointer());
491 QByteArray encodedData = data->
data(QStringLiteral(
"text/x-kmail-textsnippet"));
504 stream >>
id >>
name >> text >>
keySequence >> keyword >> subject >> to >> cc >> bcc >> attachment;
505 if (item->isGroup()) {
508 const QModelIndex idx = index(row, 0, parent);
522 if (KMessageBox::ButtonCode::PrimaryAction
524 i18n(
"Do you want to update snippet?"),
525 i18nc(
"@title:window",
"Update snippet"),
526 KGuiItem(
i18nc(
"@action:button",
"Update")),
529 item->setSubject(subject);
537 }
else if (data->hasFormat(QStringLiteral(
"text/plain"))) {
541 const QString encodedData =
QString::fromUtf8(data->data(QStringLiteral(
"text/plain")));
542 if (!parent.isValid()) {
543 Q_EMIT addNewDndSnippset(encodedData);
546 auto item =
static_cast<SnippetItem *
>(parent.internalPointer());
548 if (item->isGroup()) {
549 Q_EMIT addNewDndSnippset(encodedData);
551 if (KMessageBox::ButtonCode::PrimaryAction
553 i18n(
"Do you want to update snippet?"),
554 i18nc(
"@title:window",
"Update snippet"),
555 KGuiItem(
i18nc(
"@action:button",
"Update")),
557 item->setText(encodedData);
570QModelIndex SnippetsModel::createGroup(
const QString &groupName)
573 const QModelIndex groupIndex = index(rowCount() - 1, 0, QModelIndex());
578void SnippetsModel::load(
const QString &filename)
582 const KConfigGroup snippetPartGroup = config->group(
"SnippetPart");
584 const int groupCount = snippetPartGroup.
readEntry(
"snippetGroupCount", 0);
586 for (
int i = 0; i < groupCount; ++i) {
587 const KConfigGroup group = config->group(QStringLiteral(
"SnippetGroup_%1").arg(i));
589 const QString groupName = group.
readEntry(
"Name");
592 const QModelIndex groupIndex = createGroup(groupName);
594 const int snippetCount = group.
readEntry(
"snippetCount", 0);
595 for (
int j = 0; j < snippetCount; ++j) {
596 const QString snippetName = group.
readEntry(QStringLiteral(
"snippetName_%1").arg(j), QString());
598 const QString snippetText = group.
readEntry(QStringLiteral(
"snippetText_%1").arg(j), QString());
600 const QString snippetKeySequence = group.
readEntry(QStringLiteral(
"snippetKeySequence_%1").arg(j), QString());
602 const QString snippetKeyword = group.
readEntry(QStringLiteral(
"snippetKeyword_%1").arg(j), QString());
604 const QString snippetSubject = group.
readEntry(QStringLiteral(
"snippetSubject_%1").arg(j), QString());
606 const QString to = group.
readEntry(QStringLiteral(
"snippetTo_%1").arg(j), QString());
608 const QString cc = group.
readEntry(QStringLiteral(
"snippetCc_%1").arg(j), QString());
610 const QString bcc = group.
readEntry(QStringLiteral(
"snippetBcc_%1").arg(j), QString());
612 const QString attachment = group.
readEntry(QStringLiteral(
"snippetAttachment_%1").arg(j), QString());
613 createSnippet(groupIndex, snippetName, snippetText, snippetKeySequence, snippetKeyword, snippetSubject, to, cc, bcc, attachment);
617 const KConfigGroup group = config->
group(
"SavedVariablesPart");
618 const int variablesCount = group.
readEntry(
"variablesCount", 0);
620 for (
int i = 0; i < variablesCount; ++i) {
621 const QString variableKey = group.
readEntry(QStringLiteral(
"variableName_%1").arg(i), QString());
623 const QString variableValue = group.
readEntry(QStringLiteral(
"variableValue_%1").arg(i), QString());
625 mSavedVariables.
insert(variableKey, variableValue);
629void SnippetsModel::createSnippet(
const QModelIndex &groupIndex,
630 const QString &snippetName,
631 const QString &snippetText,
632 const QString &snippetKeySequence,
633 const QString &snippetKeyword,
634 const QString &snippetSubject,
638 const QString &attachment)
640 insertRow(rowCount(groupIndex), groupIndex);
641 const QModelIndex modelIndex = index(rowCount(groupIndex) - 1, 0, groupIndex);
654 Q_EMIT updateActionCollection(QString(), snippetName,
QKeySequence::fromString(snippetKeySequence), snippetText, snippetSubject, to, cc, bcc, attachment);
657void SnippetsModel::setSavedVariables(
const QMap<QString, QString> &savedVariables)
659 mSavedVariables = savedVariables;
662QList<SnippetsInfo> SnippetsModel::snippetsInfo()
const
664 QList<SnippetsInfo> infos;
665 const int groupCount = rowCount();
667 for (
int i = 0; i < groupCount; ++i) {
668 const QModelIndex groupIndex = index(i, 0, QModelIndex());
669 const int snippetCount = rowCount(groupIndex);
670 for (
int j = 0; j < snippetCount; ++j) {
672 const QModelIndex modelIndex = index(j, 0, groupIndex);
684 info.text = snippetText;
685 info.newName = snippetName;
686 info.keyword = snippetKeyword;
688 info.subject = snippetSubject;
691 info.bcc = snippetBcc;
692 info.attachment = snippetAttachment;
700QMap<QString, QString> SnippetsModel::savedVariables()
const
702 return mSavedVariables;
705void SnippetsModel::save(
const QString &filename)
710 const QStringList lst = config->groupList();
711 for (
const QString &group : lst) {
712 config->deleteGroup(group);
716 KConfigGroup group = config->
group(
"SnippetPart");
718 const int groupCount = rowCount();
719 group.
writeEntry(
"snippetGroupCount", groupCount);
721 for (
int i = 0; i < groupCount; ++i) {
722 const QModelIndex groupIndex = index(i, 0, QModelIndex());
725 KConfigGroup group = config->
group(QStringLiteral(
"SnippetGroup_%1").arg(i));
728 const int snippetCount = rowCount(groupIndex);
730 group.
writeEntry(
"snippetCount", snippetCount);
731 for (
int j = 0; j < snippetCount; ++j) {
732 const QModelIndex modelIndex = index(j, 0, groupIndex);
745 group.
writeEntry(QStringLiteral(
"snippetName_%1").arg(j), snippetName);
747 group.
writeEntry(QStringLiteral(
"snippetText_%1").arg(j), snippetText);
749 if (!snippetKeySequence.
isEmpty()) {
750 group.
writeEntry(QStringLiteral(
"snippetKeySequence_%1").arg(j), snippetKeySequence);
752 if (!snippetKeyword.
isEmpty()) {
753 group.
writeEntry(QStringLiteral(
"snippetKeyword_%1").arg(j), snippetKeyword);
755 if (!snippetSubject.
isEmpty()) {
756 group.
writeEntry(QStringLiteral(
"snippetSubject_%1").arg(j), snippetSubject);
759 group.
writeEntry(QStringLiteral(
"snippetTo_%1").arg(j), snippetTo);
762 group.
writeEntry(QStringLiteral(
"snippetCc_%1").arg(j), snippetCc);
765 group.
writeEntry(QStringLiteral(
"snippetBcc_%1").arg(j), snippetBcc);
767 if (!snippetAttachment.
isEmpty()) {
768 group.
writeEntry(QStringLiteral(
"snippetAttachment_%1").arg(j), snippetAttachment);
775 KConfigGroup group = config->
group(
"SavedVariablesPart");
777 const int variablesCount = mSavedVariables.count();
778 group.
writeEntry(
"variablesCount", variablesCount);
781 QMap<QString, QString>::const_iterator it = mSavedVariables.cbegin();
782 const QMap<QString, QString>::const_iterator itEnd = mSavedVariables.cend();
783 for (; it != itEnd; ++it) {
784 group.
writeEntry(QStringLiteral(
"variableName_%1").arg(counter), it.key());
785 group.
writeEntry(QStringLiteral(
"variableValue_%1").arg(counter), it.value());
792#include "moc_snippetsmodel.cpp"
KConfigGroup group(const QString &group)
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
QString readEntry(const char *key, const char *aDefault=nullptr) const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
@ AttachmentRole
The Attachment of a snippet.
@ KeywordRole
The keyword which will replace by snippet.
@ CcRole
The Cc of a snippet.
@ SubjectRole
The subject of a snippet.
@ BccRole
The Cc of a snippet.
@ KeySequenceRole
The key sequence to activate a snippet.
@ IsGroupRole
Returns whether the index represents a group.
@ ToRole
The To of a snippet.
@ NameRole
The name of a snippet or group.
@ TextRole
The text of a snippet.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QAction * load(const QObject *recvr, const char *slot, QObject *parent)
QString name(const QVariant &location)
ButtonCode questionTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Notify)
void beginInsertRows(const QModelIndex &parent, int first, int last)
void beginRemoveRows(const QModelIndex &parent, int first, int last)
QModelIndex createIndex(int row, int column, const void *ptr) const const
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles)
virtual Qt::ItemFlags flags(const QModelIndex &index) const const
bool hasIndex(int row, int column, const QModelIndex &parent) const const
bool insertRow(int row, const QModelIndex &parent)
QKeySequence fromString(const QString &str, SequenceFormat format)
void append(QList< T > &&value)
QVariant data(int role) const const
QObject * parent() const const
QString fromUtf8(QByteArrayView str)
QString & insert(qsizetype position, QChar ch)
bool isEmpty() const const
void keySequence(QWidget *widget, const QKeySequence &keySequence)
QString toString() const const