38#include "../util/btassert.h"
39#include "../util/btconnect.h"
40#include "../util/cresmgr.h"
41#include "../util/directory.h"
42#include "../util/tool.h"
50#define CURRENT_SYNTAX_VERSION 1
67 : m_parent(other.m_parent)
68 , m_text(other.m_text)
73 void setText(QString
const & text) { m_text = text; }
75 QString
const &
text()
const {
return m_text; }
77 virtual QString
toolTip()
const {
return {}; }
79 virtual Qt::ItemFlags
flags() const noexcept {
return Qt::NoItemFlags; }
81 virtual QIcon
const &
icon() const noexcept {
82 static QIcon
const noIcon;
81 virtual QIcon
const &
icon() const noexcept {
…}
107 const QString &
description,
const QString & title);
112 Qt::ItemFlags
flags() const noexcept final
override {
113 return Qt::ItemIsSelectable
114 | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled
112 Qt::ItemFlags
flags() const noexcept final
override {
…}
118 QIcon
const &
icon() const noexcept final
override
119 {
return CResMgr::mainIndex::bookmark::icon(); }
118 QIcon
const &
icon() const noexcept final
override {
…}
136 QString toolTip()
const override;
160 Qt::ItemFlags
flags() const noexcept final
override {
161 return Qt::ItemIsSelectable | Qt::ItemIsEditable
162 | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled
160 Qt::ItemFlags
flags() const noexcept final
override {
…}
166 QIcon
const &
icon() const noexcept final
override
167 {
return CResMgr::mainIndex::closedFolder::icon(); }
166 QIcon
const &
icon() const noexcept final
override {
…}
173 m_children.append(child);
176 QList<BookmarkItemBase *> &
children() noexcept {
return m_children; }
177 QList<BookmarkItemBase *>
const &
children() const noexcept
178 {
return m_children; }
177 QList<BookmarkItemBase *>
const &
children() const noexcept {
…}
183 m_children.insert(index, child);
187 for (
auto *
const c : children)
188 insertChild(index++, c);
192 delete m_children[index];
193 m_children.removeAt(index);
232 m_saveTimer.setInterval(30 * 1000);
233 m_saveTimer.setSingleShot(
true);
239 + QStringLiteral(
"/bookmarks.xml");
248 template <
typename T>
250 {
return dynamic_cast<T *
>(item(index)); }
253 if(m_defaultModel == q_ptr){
254 if(!m_saveTimer.isActive())
261 QList<BookmarkItemBase *>
loadTree(QString fileName = QString()) {
262 QList<BookmarkItemBase*> itemList;
265 QString bookmarksFile = loadXmlFromFile(fileName);
266 if (bookmarksFile.isNull())
267 return QList<BookmarkItemBase*>();
269 doc.setContent(bookmarksFile);
270 QDomElement document = doc.documentElement();
271 if (document.tagName() != QStringLiteral(
"SwordBookmarks")) {
272 qWarning(
"Not a BibleTime Bookmark XML file");
273 return QList<BookmarkItemBase*>();
276 QDomElement child = document.firstChild().toElement();
278 while ( !child.isNull() && child.parentNode() == document) {
281 if (!child.nextSibling().isNull()) {
282 child = child.nextSibling().toElement();
285 child = QDomElement();
261 QList<BookmarkItemBase *>
loadTree(QString fileName = QString()) {
…}
295 if (element.tagName() == QStringLiteral(
"Folder")) {
297 if (element.hasAttribute(QStringLiteral(
"caption"))) {
298 newFolder->
setText(element.attribute(
299 QStringLiteral(
"caption")));
301 QDomNodeList childList = element.childNodes();
302 for (
int i = 0; i < childList.length(); i++) {
303 QDomElement newElement = childList.at(i).toElement();
304 handleXmlElement(newElement, newFolder);
308 if (element.tagName() == QStringLiteral(
"Bookmark")) {
310 if (element.hasAttribute(QStringLiteral(
"modulename"))) {
313 element.attribute(QStringLiteral(
"modulename")));
315 if (element.hasAttribute(QStringLiteral(
"key"))) {
317 element.attribute(QStringLiteral(
"key")));
319 if (element.hasAttribute(QStringLiteral(
"description"))) {
321 element.attribute(QStringLiteral(
"description")));
323 if (element.hasAttribute(QStringLiteral(
"title"))) {
325 element.attribute(QStringLiteral(
"title")));
327 return newBookmarkItem;
334 if (fileName.isEmpty())
335 fileName = defaultBookmarksFile();
338 t.setAutoDetectUnicode(
false);
339 t.setEncoding(QStringConverter::Utf8);
341 QFile file(fileName);
342 if (!file.open(QIODevice::ReadOnly))
354 QDomDocument doc(QStringLiteral(
"DOC"));
356 doc.createProcessingInstruction(
357 QStringLiteral(
"xml"),
358 QStringLiteral(
"version=\"1.0\" encoding=\"UTF-8\"")));
361 doc.createElement(QStringLiteral(
"SwordBookmarks"));
362 content.setAttribute(QStringLiteral(
"syntaxVersion"),
364 doc.appendChild(content);
368 for (
auto const *
const itemPtr : rootItem->
children())
369 saveItem(itemPtr, content);
370 return doc.toString();
380 parentElement.ownerDocument().createElement(
381 QStringLiteral(
"Folder"));
382 elem.setAttribute(QStringLiteral(
"caption"), folderItem->
text());
384 parentElement.appendChild(elem);
386 for (
auto const *
const itemPtr : folderItem->
children())
387 saveItem(itemPtr, elem);
389 else if ((bookmarkItem =
dynamic_cast<BookmarkItem const *
>(item))) {
391 parentElement.ownerDocument().createElement(
392 QStringLiteral(
"Bookmark"));
394 elem.setAttribute(QStringLiteral(
"key"),
396 elem.setAttribute(QStringLiteral(
"description"),
398 elem.setAttribute(QStringLiteral(
"modulename"),
400 elem.setAttribute(QStringLiteral(
"moduledescription"),
405 if (!bookmarkItem->
text().isEmpty()) {
406 elem.setAttribute(QStringLiteral(
"title"), bookmarkItem->
text());
408 parentElement.appendChild(elem);
436 for (
auto const *
const childItem : children())
439 if (folder->hasDescendant(childItem))
446 for (
auto const *
const subitem : children()) {
454 newFolder->
addChild(bmFolder->deepCopy());
462 const QString & description,
463 const QString & title)
464 : m_description(description)
465 , m_moduleName(module.name())
471 sword::VerseKey vk(key.toUtf8().constData(), key.toUtf8().constData(),
472 static_cast<sword::VerseKey *
>(module.
swordModule().getKey())->getVersificationSystem());
492 , m_description(other.m_description)
493 , m_moduleName(other.m_moduleName)
504 return englishKeyName;
507 QString returnKeyName = englishKeyName;
510 sword::VerseKey vk(englishKeyName.toUtf8().constData(), englishKeyName.toUtf8().constData(),
511 static_cast<sword::VerseKey *
>(
module()->swordModule().getKey())->getVersificationSystem());
514 returnKeyName = k.key();
517 return returnKeyName;
521 auto const *
const m =
module();
530 std::unique_ptr<CSwordKey> k(m->createKey());
538 auto const & txt =
text();
540 return QStringLiteral(
"<b>%1)</b><hr>%2").arg(header,
description());
541 return QStringLiteral(
"<b>%1)</b><br>%2<hr>%3")
561 if(d->m_saveTimer.isActive())
570 if (
auto const *
const f =
dynamic_cast<BookmarkFolder *
>(d->item(
parent)))
571 return f->children().size();
586 auto const *
const f =
dynamic_cast<BookmarkFolder *
>(d->item(
parent));
587 if (f && f->children().size() > row && row >= 0)
588 return createIndex(row, column, f->children()[row]);
589 return QModelIndex();
595 const BookmarkItemBase * i = d->item(
index);
596 return (i->parent() ==
nullptr || i->parent()->parent() ==
nullptr) ?
597 QModelIndex() : createIndex(i->parent()->index(), 0, i->parent());
603 const BookmarkItemBase * i = d->item(
index);
607 case Qt::DisplayRole:
610 case Qt::ToolTipRole:
612 case Qt::DecorationRole:
617 return QStringLiteral(
"bookmark");
619 return QStringLiteral(
"folder");
628 return d->item(
index)->flags();
633 Q_UNUSED(orientation)
642 BookmarkItemBase * i = d->item(
index);
643 if (role == Qt::DisplayRole || role == Qt::EditRole) {
644 i->setText(val.toString());
645 if(
dynamic_cast<BookmarkFolder *
>(i) ||
dynamic_cast<BookmarkItem *
>(i))
655 if (
auto *
const f =
dynamic_cast<BookmarkFolder *
>(d->item(
parent))) {
656 BT_ASSERT(row + count <= f->children().size());
657 beginRemoveRows(
parent, row, row + count - 1);
658 for(
int i = 0; i < count; ++i)
670 if (
auto *
const f =
dynamic_cast<BookmarkFolder *
>(d->item(
parent))) {
672 beginInsertRows(
parent, row, row + count - 1);
673 for(
int i = 0; i < count; ++i)
674 f->insertChild(row,
new BookmarkItemBase);
683 BT_ASSERT(
dynamic_cast<BookmarkFolder *
>(d->item(rootItem)));
684 auto const serializedTree =
685 d->serializeTreeFromRootItem(
686 static_cast<BookmarkFolder *
>(d->item(rootItem)));
687 if (fileName.isEmpty())
692 if(d->m_saveTimer.isActive())
693 d->m_saveTimer.stop();
700 BT_ASSERT(
dynamic_cast<BookmarkFolder *
>(d->item(rootItem)));
701 auto *
const i =
static_cast<BookmarkFolder *
>(d->item(rootItem));
702 QList<BookmarkItemBase *> items = d->loadTree(fileName);
704 if(!rootItem.isValid() && fileName.isEmpty()) {
705 BT_ASSERT(!d->m_defaultModel &&
"Only one default model allowed!");
708 d->m_defaultModel =
this;
711 if(items.size() == 0)
714 auto const numChildren = i->children().size();
715 beginInsertRows(rootItem, numChildren, numChildren + items.size() - 1);
716 i->insertChildren(numChildren, items);
724 return d->itemAs<BookmarkFolder
const>(
index);
737 auto *
const targetFolder =
static_cast<BookmarkFolder *
>(d->item(
parent));
739 bool bookmarksOnly =
true;
740 bool targetIncluded =
false;
741 bool moreThanOneFolder =
false;
743 QList<BookmarkItemBase *> newList;
745 for (
auto const &
index : toCopy) {
746 if (BookmarkFolder
const *
const folder =
747 d->itemAs<BookmarkFolder
const>(
index))
749 bookmarksOnly =
false;
750 if (toCopy.count() > 1) {
751 moreThanOneFolder =
true;
754 if (folder->hasDescendant(d->item(
parent))) {
755 targetIncluded =
true;
764 if (!bookmarksOnly && toCopy.count() == 1)
765 newList.append(d->itemAs<BookmarkFolder
const>(toCopy[0])->deepCopy());
766 if (!bookmarksOnly && toCopy.count() > 1) {
768 moreThanOneFolder =
true;
771 if (moreThanOneFolder || targetIncluded) {
776 beginInsertRows(
parent, row, row + newList.size() - 1);
778 targetFolder->insertChildren(row, newList);
808 return i->description();
823 QModelIndex
const &
parent,
827 QString
const & title)
831 if (BookmarkFolder *
const i = d->itemAs<BookmarkFolder>(
parent)) {
837 i->insertChild(
r, c);
843 return createIndex(c->index(), 0, c);
845 return QModelIndex();
852 if (BookmarkFolder *
const i = d->itemAs<BookmarkFolder>(
parent)) {
853 beginInsertRows(
parent, row, row);
855 BookmarkFolder * c =
new BookmarkFolder(name.isEmpty() ? QObject::tr(
"New folder") : name);
856 i->insertChild(row, c);
862 return createIndex(c->index(), 0, c);
864 return QModelIndex();
871 if (BookmarkFolder
const *
const f =
872 d->itemAs<BookmarkFolder
const>(baseIndex))
873 return f->hasDescendant(d->item(testIndex));
879 return i1->text().localeAwareCompare(i2->text()) < 0;
884 return i1->text().localeAwareCompare(i2->text()) > 0;
888 Qt::SortOrder
const order)
892 if(BookmarkFolder *
const f = d->itemAs<BookmarkFolder>(
parent)) {
893 QList<BookmarkFolder *> parents;
894 if(f == d->m_rootItem) {
895 QList<BookmarkItemBase *> items;
897 for(
int i = 0; i < items.size(); ++i) {
898 if (
auto *
const ff =
dynamic_cast<BookmarkFolder *
>(items[i])){
899 items.append(ff->children());
907 for (
auto *
const f : parents) {
908 Q_EMIT layoutAboutToBeChanged();
910 QModelIndexList indexes;
911 for(
int i = 0; i < f->children().size(); ++i)
912 indexes.append(createIndex(i, 0, f->children()[i]));
914 std::sort(f->children().begin(),
916 order == Qt::AscendingOrder
920 for(
int i = 0; i < f->children().size(); ++i) {
921 BookmarkItemBase * iii = f->children()[i];
922 for(
int ii = 0; ii < indexes.size(); ++ii)
923 if(iii == indexes[ii].internalPointer())
924 changePersistentIndex(createIndex(ii, 0, iii), createIndex(i, 0, iii));
926 Q_EMIT layoutChanged();
934 static auto const staticRoleNames = {
935 std::make_pair(
static_cast<int>(Qt::DisplayRole),
936 QByteArrayLiteral(
"display")),
937 std::make_pair(
static_cast<int>(Qt::DecorationRole),
938 QByteArrayLiteral(
"icon")),
939 std::make_pair(
static_cast<int>(Qt::EditRole),
940 QByteArrayLiteral(
"edit")),
941 std::make_pair(
static_cast<int>(
TypeRole),
942 QByteArrayLiteral(
"itemtype"))
944 return staticRoleNames;
bool BtBookmarksModelSortAscending(BookmarkItemBase *i1, BookmarkItemBase *i2)
#define CURRENT_SYNTAX_VERSION
bool BtBookmarksModelSortDescending(BookmarkItemBase *i1, BookmarkItemBase *i2)
BtConfig & btConfig()
This is a shortchand for BtConfig::getInstance().
QString const & key() const noexcept
QString const & description() const noexcept
QString const & module() const noexcept
QList< BookmarkItemBase * > loadTree(QString fileName=QString())
BtBookmarksModelPrivate(BtBookmarksModel *parent)
T * itemAs(QModelIndex const &index) const
static QString defaultBookmarksFile()
QString loadXmlFromFile(QString fileName=QString())
BookmarkItemBase * handleXmlElement(QDomElement &element, BookmarkFolder *parent)
void saveItem(BookmarkItemBase const *item, QDomElement &parentElement)
BookmarkFolder * m_rootItem
QString serializeTreeFromRootItem(BookmarkFolder *rootItem)
static BtBookmarksModel * m_defaultModel
~BtBookmarksModelPrivate()
BookmarkItemBase * item(const QModelIndex &index) const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void copyItems(int row, const QModelIndex &parent, const QModelIndexList &toCopy)
Copies item to target position.
bool isBookmark(const QModelIndex &index) const
bool hasDescendant(const QModelIndex &baseIndex, const QModelIndex &testIndex) const
bool isFolder(const QModelIndex &index) const
void sortItems(QModelIndex const &parent=QModelIndex(), Qt::SortOrder const order=Qt::AscendingOrder)
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QString description(const QModelIndex &index) const
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QHash< int, QByteArray > roleNames() const override
~BtBookmarksModel() override
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
void setDescription(const QModelIndex &index, const QString &description)
set descritpion for index.
QModelIndex parent(const QModelIndex &index) const override
bool load(QString fileName=QString(), const QModelIndex &rootItem=QModelIndex())
Import bookmarks from file.
BtBookmarksModel(QObject *parent=nullptr)
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
CSwordModuleInfo * module(const QModelIndex &index) const
bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QModelIndex addFolder(int row, const QModelIndex &parent, const QString &name=QString())
add new folder.
bool save(QString fileName=QString(), const QModelIndex &rootItem=QModelIndex())
Save bookmarks or specified branch to file.
BtBookmarksModelPrivate *const d_ptr
QModelIndex addBookmark(int const row, QModelIndex const &parent, CSwordModuleInfo const &module, QString const &key, QString const &description=QString(), QString const &title=QString())
add new item with given parameters
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QString key(const QModelIndex &index) const
FilterOptions getFilterOptions() const
CSwordModuleInfo * findModuleByName(const QString &name) const
Searches for a module with the given name.
static CSwordBackend & instance() noexcept
void setFilterOptions(const FilterOptions &options)
QString config(const CSwordModuleInfo::ConfigEntry entry) const
QString const & name() const
sword::SWModule & swordModule() const
CSwordKey implementation for Sword's VerseKey.
void insertChild(int index, BookmarkItemBase *child)
BookmarkFolder * deepCopy() const
QList< BookmarkItemBase * > const & children() const noexcept
bool hasDescendant(BookmarkItemBase const *item) const
QList< BookmarkItemBase * > m_children
void insertChildren(int index, QList< BookmarkItemBase * > children)
QList< BookmarkItemBase * > & children() noexcept
void removeChild(int index)
Qt::ItemFlags flags() const noexcept final override
void addChild(BookmarkItemBase *child)
QIcon const & icon() const noexcept final override
~BookmarkFolder() final override
void setText(QString const &text)
virtual Qt::ItemFlags flags() const noexcept
BookmarkItemBase(BookmarkFolder *parent=nullptr)
BookmarkItemBase(const BookmarkItemBase &other)
QString const & text() const
virtual QString toolTip() const
virtual ~BookmarkItemBase()
void setParent(BookmarkFolder *parent)
BookmarkFolder * m_parent
virtual QIcon const & icon() const noexcept
BookmarkFolder * parent() const
QString const & moduleName() const
Qt::ItemFlags flags() const noexcept final override
BookmarkItem(const CSwordModuleInfo &module, const QString &key, const QString &description, const QString &title)
void setModule(QString const &moduleName)
QString const & description() const
CSwordModuleInfo * module() const
BookmarkItem(BookmarkFolder *parent)
QString const & englishKey() const
void setKey(QString const &key)
QIcon const & icon() const noexcept final override
void setDescription(QString const &description)
QString toolTip() const override
QStringList r(content.left(bodyIndex))
QString toHeader(QString const &key, QString const &moduleName)
const QDir & getUserBaseDir()