summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorxiota2023-10-29 09:14:57 -0700
committerxiota2023-10-29 09:15:19 -0700
commit0ec92f44085bbe4cec12d750fd1b6168d363c573 (patch)
tree73247916ecfd634a49a7be686dac08f3b83fb023
parentbca61c1bd9e6ae02d7ae493996d131c570a2f3fb (diff)
downloadaur-0ec92f44085bbe4cec12d750fd1b6168d363c573.tar.gz
2.0.2.r11: update patches
-rw-r--r--.SRCINFO14
-rw-r--r--0001-modify-default-navigation-css.patch60
-rw-r--r--0002-skip-epub-version-check.patch1706
-rw-r--r--0003-don-t-write-version-and-modified-tags.patch108
-rw-r--r--PKGBUILD14
-rw-r--r--default_nav_css.patch21
-rw-r--r--skip_epub_version_check.patch27
-rw-r--r--skip_version_mod_tags.patch70
8 files changed, 1888 insertions, 132 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 9223efedafdd..2a37d4e1202c 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = sigil-git
pkgdesc = multi-platform EPUB2/EPUB3 ebook editor
- pkgver = 2.0.2.r6.gd223713e5
+ pkgver = 2.0.2.r11.gb9438a876
pkgrel = 1
url = https://github.com/Sigil-Ebook/Sigil
arch = x86_64
@@ -36,12 +36,12 @@ pkgbase = sigil-git
conflicts = sigil
options = !debug
source = sigil::git+https://github.com/Sigil-Ebook/Sigil.git
- source = default_nav_css.patch
- source = skip_epub_version_check.patch
- source = skip_version_mod_tags.patch
+ source = 0001-modify-default-navigation-css.patch
+ source = 0002-skip-epub-version-check.patch
+ source = 0003-don-t-write-version-and-modified-tags.patch
sha256sums = SKIP
- sha256sums = 3478ff361a34fd7cd7811d5103cbace91ecc790463684aaab9e21687b5553a28
- sha256sums = fc2bdc23d13b2e917f08608b516495b744f991642f73c1f6d943cf322a25fc11
- sha256sums = c74be3af315c9ffe181df6b465d0037f152f6078b953e6eeaab7b2932ae4c729
+ sha256sums = c01f2028fd2a77fa48ddeefc70b780d185131f81c8c3b3f4f3bfd670cd1d574f
+ sha256sums = d06138d38a2d29ca020ec575bd2aa975df48cf61bbad975140fe5f304e23f6b0
+ sha256sums = 4bddaaf8666e3d060ba51989c94d6c3a2c23a5b037dd69abe6c61af51b580720
pkgname = sigil-git
diff --git a/0001-modify-default-navigation-css.patch b/0001-modify-default-navigation-css.patch
new file mode 100644
index 000000000000..11332b2cbcee
--- /dev/null
+++ b/0001-modify-default-navigation-css.patch
@@ -0,0 +1,60 @@
+From 949f7e50053057b9443cfabef77f048f86301501 Mon Sep 17 00:00:00 2001
+From: xiota
+Date: Sun, 29 Oct 2023 03:50:46 -0700
+Subject: [PATCH 1/3] modify default navigation css
+
+---
+ src/BookManipulation/Book.cpp | 10 ++++++++++
+ src/BookManipulation/Book.cpp.rej | 19 +++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+ create mode 100644 src/BookManipulation/Book.cpp.rej
+
+diff --git a/src/BookManipulation/Book.cpp b/src/BookManipulation/Book.cpp
+index e8beaff..38344de 100644
+--- a/src/BookManipulation/Book.cpp
++++ b/src/BookManipulation/Book.cpp
+@@ -129,6 +129,16 @@ static const QString SGC_NAV_CSS_FILE =
+ "}\n\n"
+ "ol {\n"
+ " list-style-type: none;\n"
++ " padding-left: 1.5rem;\n"
++ "}\n\n"
++ "li > ol {\n"
++ " margin-bottom: 0.75rem;\n"
++ "}\n\n"
++ "li {\n"
++ " margin-top: 0.25rem;\n"
++ "}\n\n"
++ "a {\n"
++ " text-decoration: none;\n"
+ "}\n\n";
+
+
+diff --git a/src/BookManipulation/Book.cpp.rej b/src/BookManipulation/Book.cpp.rej
+new file mode 100644
+index 0000000..c14cd6f
+--- /dev/null
++++ b/src/BookManipulation/Book.cpp.rej
+@@ -0,0 +1,19 @@
++--- src/BookManipulation/Book.cpp
+++++ src/BookManipulation/Book.cpp
++@@ -126,6 +126,16 @@
++ "}\n\n"
++ "ol {\n"
++ " list-style-type: none;\n"
+++ " padding-left: 1.5rem;\n"
+++ "}\n\n"
+++ "li > ol {\n"
+++ " margin-bottom: 0.75rem;\n"
+++ "}\n\n"
+++ "li {\n"
+++ " margin-top: 0.25rem;\n"
+++ "}\n\n"
+++ "a {\n"
+++ " text-decoration: none;\n"
++ "}\n\n";
++
++
+--
+2.42.0
+
diff --git a/0002-skip-epub-version-check.patch b/0002-skip-epub-version-check.patch
new file mode 100644
index 000000000000..9cb5694f9e44
--- /dev/null
+++ b/0002-skip-epub-version-check.patch
@@ -0,0 +1,1706 @@
+From d13cbc01b92a3a16411823359741b3723376b17b Mon Sep 17 00:00:00 2001
+From: xiota
+Date: Sun, 29 Oct 2023 03:51:25 -0700
+Subject: [PATCH 2/3] skip epub version check
+
+Allows changing from epub2 to epub3 by directly editing
+the opf. Some data is lost and needs to be recreated
+(eg, table of contents).
+---
+ src/ResourceObjects/OPFResource.cpp | 14 -
+ src/ResourceObjects/OPFResource.cpp.orig | 1658 ++++++++++++++++++++++
+ 2 files changed, 1658 insertions(+), 14 deletions(-)
+ create mode 100644 src/ResourceObjects/OPFResource.cpp.orig
+
+diff --git a/src/ResourceObjects/OPFResource.cpp b/src/ResourceObjects/OPFResource.cpp
+index 4b7668d..7f7020b 100644
+--- a/src/ResourceObjects/OPFResource.cpp
++++ b/src/ResourceObjects/OPFResource.cpp
+@@ -1493,20 +1493,6 @@ void OPFResource::UpdateText(const OPFParser &p)
+ QString OPFResource::ValidatePackageVersion(const QString& source)
+ {
+ QString newsource = source;
+- QString orig_version = GetEpubVersion();
+- QRegularExpression pkgversion_search(PKG_VERSION, QRegularExpression::CaseInsensitiveOption);
+- QRegularExpressionMatch mo = pkgversion_search.match(newsource);
+- if (mo.hasMatch()) {
+- QString version = mo.captured(1);
+- if (version != orig_version) {
+- newsource.replace(mo.capturedStart(1), mo.capturedLength(1), orig_version);
+- if (!m_WarnedAboutVersion && !version.startsWith('1')) {
+- Utility::DisplayStdWarningDialog("Changing package version inside Sigil is not supported",
+- "Use an appropriate output plugin to make the initial conversion");
+- m_WarnedAboutVersion = true;
+- }
+- }
+- }
+ return newsource;
+ }
+
+diff --git a/src/ResourceObjects/OPFResource.cpp.orig b/src/ResourceObjects/OPFResource.cpp.orig
+new file mode 100644
+index 0000000..4b7668d
+--- /dev/null
++++ b/src/ResourceObjects/OPFResource.cpp.orig
+@@ -0,0 +1,1658 @@
++/************************************************************************
++**
++** Copyright (C) 2015-2023 Kevin B. Hendricks Stratford, ON Canada
++** Copyright (C) 2013 John Schember <john@nachtimwald.com>
++** Copyright (C) 2009-2011 Strahinja Markovic <strahinja.markovic@gmail.com>
++**
++** This file is part of Sigil.
++**
++** Sigil is free software: you can redistribute it and/or modify
++** it under the terms of the GNU General Public License as published by
++** the Free Software Foundation, either version 3 of the License, or
++** (at your option) any later version.
++**
++** Sigil is distributed in the hope that it will be useful,
++** but WITHOUT ANY WARRANTY; without even the implied warranty of
++** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++** GNU General Public License for more details.
++**
++** You should have received a copy of the GNU General Public License
++** along with Sigil. If not, see <http://www.gnu.org/licenses/>.
++**
++*************************************************************************/
++
++#include <memory>
++
++#include <QtCore/QBuffer>
++#include <QtCore/QDate>
++#include <QtCore/QDir>
++#include <QtCore/QFileInfo>
++#include <QtCore/QUuid>
++#include <QRegularExpression>
++#include <QRegularExpressionMatch>
++#include <QDateTime>
++#include <QDebug>
++
++#include "BookManipulation/CleanSource.h"
++#include "BookManipulation/XhtmlDoc.h"
++#include "BookManipulation/FolderKeeper.h"
++#include "Misc/Utility.h"
++#include "Misc/SettingsStore.h"
++#include "Misc/GuideItems.h"
++#include "Misc/Landmarks.h"
++#include "Misc/MediaTypes.h"
++#include "ResourceObjects/HTMLResource.h"
++#include "ResourceObjects/ImageResource.h"
++#include "ResourceObjects/NCXResource.h"
++#include "ResourceObjects/OPFResource.h"
++#include "ResourceObjects/NavProcessor.h"
++#include "sigil_constants.h"
++#include "sigil_exception.h"
++
++#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
++ #define QT_ENUM_SKIPEMPTYPARTS Qt::SkipEmptyParts
++ #define QT_ENUM_KEEPEMPTYPARTS Qt::KeepEmptyParts
++#else
++ #define QT_ENUM_SKIPEMPTYPARTS QString::SkipEmptyParts
++ #define QT_ENUM_KEEPEMPTYPARTS QString::KeepEmptyParts
++#endif
++
++static const QString SIGIL_VERSION_META_NAME = "Sigil version";
++static const QString OPF_XML_NAMESPACE = "http://www.idpf.org/2007/opf";
++static const QString FALLBACK_MIMETYPE = "text/plain";
++static const QString ITEM_ELEMENT_TEMPLATE = "<item id=\"%1\" href=\"%2\" media-type=\"%3\"/>";
++static const QString ITEMREF_ELEMENT_TEMPLATE = "<itemref idref=\"%1\"/>";
++static const QString OPF_REWRITTEN_COMMENT = "<!-- Your OPF file was broken so Sigil "
++ "tried to rebuild it for you. -->";
++
++static const QString PKG_VERSION = "<\\s*package[^>]*version\\s*=\\s*[\"\']([^\'\"]*)[\'\"][^>]*>";
++
++static const QString TEMPLATE_TEXT =
++ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
++ "<package version=\"2.0\" xmlns=\"http://www.idpf.org/2007/opf\" unique-identifier=\"BookId\">\n\n"
++ " <metadata xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:opf=\"http://www.idpf.org/2007/opf\">\n"
++ " <dc:identifier opf:scheme=\"UUID\" id=\"BookId\">urn:uuid:%1</dc:identifier>\n"
++ " <dc:language>%2</dc:language>\n"
++ " <dc:title>%3</dc:title>\n"
++ " </metadata>\n\n"
++ " <manifest>\n"
++ " </manifest>\n\n"
++ " <spine>\n"
++ " </spine>\n\n"
++ "</package>";
++
++/**
++ ** Epub 3 reserved prefix values for the package tag.
++ ** See http://www.idpf.org/epub/vocab/package/pfx/
++ **
++ ** Prefix IRI
++ ** --------- ---------------------------------------------------------
++ ** dcterms http://purl.org/dc/terms/
++ ** epubsc http://idpf.org/epub/vocab/sc/#
++ ** marc http://id.loc.gov/vocabulary/
++ ** media http://www.idpf.org/epub/vocab/overlays/#
++ ** onix http://www.editeur.org/ONIX/book/codelists/current.html#
++ ** rendition http://www.idpf.org/vocab/rendition/#
++ ** schema http://schema.org/
++ ** xsd http://www.w3.org/2001/XMLSchema#
++ **
++ **
++ ** Note single space is required after ":" that delimits the prefix
++ **
++ ** example:
++ **
++ ** <package …
++ ** prefix="foaf: http://xmlns.com/foaf/spec/
++ ** dbp: http://dbpedia.org/ontology/">
++ **
++ */
++
++// " <item id=\"nav\" href=\"Text/nav.xhtml\" media-type=\"application/xhtml+xml\" properties=\"nav\"/>\n"
++// " <itemref idref=\"nav\" linear=\"no\" />\n"
++
++
++static const QString TEMPLATE3_TEXT =
++ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
++ "<package version=\"3.0\" unique-identifier=\"BookId\" xmlns=\"http://www.idpf.org/2007/opf\">\n\n"
++ " <metadata xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"
++ " <dc:identifier id=\"BookId\">urn:uuid:%1</dc:identifier>\n"
++ " <dc:language>%2</dc:language>\n"
++ " <dc:title>%3</dc:title>\n"
++ " <meta property=\"dcterms:modified\">%4</meta>\n"
++ " </metadata>\n\n"
++ " <manifest>\n"
++ " </manifest>\n\n"
++ " <spine>\n"
++ " </spine>\n\n"
++ "</package>";
++
++
++OPFResource::OPFResource(const QString &mainfolder,
++ const QString &fullfilepath,
++ const QString &version,
++ QObject *parent)
++ : XMLResource(mainfolder, fullfilepath, parent),
++ m_NavResource(NULL),
++ m_WarnedAboutVersion(false)
++{
++ FillWithDefaultText(version);
++ // Make sure the file exists on disk.
++ // Among many reasons, this also solves the problem
++ // with the Book Browser not displaying an icon for this resource.
++ SaveToDisk();
++}
++
++
++// just renaming the opf (but not moving it) should not trigger
++// a need for other source updates
++// but we will need to rewrite the META-INF/container.xml
++bool OPFResource::RenameTo(const QString &new_filename)
++{
++ bool successful = Resource::RenameTo(new_filename);
++ if (successful) {
++ FolderKeeper::UpdateContainerXML(GetFullPathToBookFolder(), GetRelativePath());
++ }
++ return successful;
++}
++
++
++// moving the opf should trigger a need for many source updates
++// and the need to rewrite the META-INF/container.xml
++bool OPFResource::MoveTo(const QString &newbookpath)
++{
++ bool successful = Resource::MoveTo(newbookpath);
++ if (successful) {
++ FolderKeeper::UpdateContainerXML(GetFullPathToBookFolder(), GetRelativePath());
++ }
++ return successful;
++}
++
++
++Resource::ResourceType OPFResource::Type() const
++{
++ return Resource::OPFResourceType;
++}
++
++
++QString OPFResource::GetText() const
++{
++ return TextResource::GetText();
++}
++
++
++void OPFResource::SetText(const QString &text)
++{
++ emit TextChanging();
++ QWriteLocker locker(&GetLock());
++ QString source = ValidatePackageVersion(text);
++ TextResource::SetText(source);
++}
++
++
++bool OPFResource::LoadFromDisk()
++{
++ try {
++ const QString &text = Utility::ReadUnicodeTextFile(GetFullPath());
++ SetText(text);
++ emit LoadedFromDisk();
++ return true;
++ } catch (CannotOpenFile&) {
++ //
++ }
++ return false;
++}
++
++QList<Resource*> OPFResource::GetSpineOrderResources( const QList<Resource *> &resources)
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ const QHash<QString, Resource*> id_mapping = GetManifestIDResourceMapping(resources, p);
++ QList<Resource *> spine_order;
++ for (int i = 0; i < p.m_spine.count(); ++i) {
++ QString idref = p.m_spine.at(i).m_idref;
++ if (id_mapping.contains(idref)) {
++ spine_order << id_mapping[idref];
++ }
++ }
++ return spine_order;
++}
++
++QHash <Resource *, int> OPFResource::GetReadingOrderAll( const QList <Resource *> resources)
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QHash <Resource *, int> reading_order;
++ QHash<QString, int> id_order;
++ for (int i = 0; i < p.m_spine.count(); ++i) {
++ id_order[p.m_spine.at(i).m_idref] = i;
++ }
++ QHash<Resource *, QString> id_mapping = GetResourceManifestIDMapping(resources, p);
++ foreach(Resource *resource, resources) {
++ reading_order[resource] = id_order[id_mapping[resource]];
++ }
++ return reading_order;
++}
++
++
++int OPFResource::GetReadingOrder(const HTMLResource *html_resource) const
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ const Resource *resource = static_cast<const Resource *>(html_resource);
++ QString resource_id = GetResourceManifestID(resource, p);
++ for (int i = 0; i < p.m_spine.count(); ++i) {
++ QString idref = p.m_spine.at(i).m_idref;
++ if (resource_id == idref) {
++ return i;
++ }
++ }
++ return -1;
++}
++
++void OPFResource::MoveReadingOrder(const HTMLResource* from_resource, const HTMLResource* after_resource)
++{
++ QWriteLocker locker(&GetLock());
++ const Resource *from_res = static_cast<const Resource *>(from_resource);
++ const Resource *after_res = static_cast<const Resource *>(after_resource);
++ if (from_res == NULL || after_res == NULL) return;
++
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QString from_id = GetResourceManifestID(from_res, p);
++ QString after_id = GetResourceManifestID(after_res, p);
++
++ int from_pos = -1;
++ int after_pos = -1;
++ int spine_count = p.m_spine.count();
++ for (int i = 0; i < spine_count; i++) {
++ QString aref = p.m_spine.at(i).m_idref;
++ if (aref == from_id) from_pos = i;
++ if (aref == after_id) after_pos = i;
++ }
++
++ if ((from_pos < 0) || (after_pos < 0)) return;
++ if (from_pos >= spine_count || after_pos >= spine_count) return;
++ // a move is equivalent to the sequence insert(after, takeAt(from))
++ // if takeAt pos < after pos, it effectively increases the after position by one
++ // if takeAt pos > after pos, you need to increment after pos by 1
++ if (from_pos != after_pos + 1) {
++ if (from_pos > after_pos) after_pos += 1;
++ p.m_spine.move(from_pos, after_pos);
++ }
++ UpdateText(p);
++}
++
++
++QString OPFResource::GetMainIdentifierValue() const
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ int i = GetMainIdentifier(p);
++ if (i > -1) {
++ return QString(p.m_metadata.at(i).m_content);
++ }
++ return QString();
++}
++
++void OPFResource::SaveToDisk(bool book_wide_save)
++{
++ QString source = ValidatePackageVersion(CleanSource::ProcessXML(GetText(),"application/oebps-package+xml"));
++ // Work around for covers appearing on the Nook. Issue 942.
++ source = source.replace(QRegularExpression("<meta content=\"([^\"]+)\" name=\"cover\""), "<meta name=\"cover\" content=\"\\1\"");
++ TextResource::SetText(source);
++ TextResource::SaveToDisk(book_wide_save);
++}
++
++
++QString OPFResource::GetPackageVersion() const
++{
++ QReadLocker locker(&GetLock());
++ // The right way to do this is to properly parse the opf.
++ // That means invoking the embedded python code and lxml.
++ // As this code will be called many times and from many places
++ // convert it to a simple QRegualr expression query for speed.
++
++ // QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ // OPFParser p;
++ // p.parse(source);
++ // return p.m_package.m_version;
++
++ QString opftext = GetText();
++ QRegularExpression pkgversion_search(PKG_VERSION, QRegularExpression::CaseInsensitiveOption);
++ QRegularExpressionMatch pkgversion_mo = pkgversion_search.match(opftext);
++ QString version = "2.0";
++ if (pkgversion_mo.hasMatch()) {
++ version = pkgversion_mo.captured(1);
++ }
++ return version;
++}
++
++
++QString OPFResource::GetUUIDIdentifierValue()
++{
++ EnsureUUIDIdentifierPresent();
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ for (int i=0; i < p.m_metadata.count(); ++i) {
++ MetaEntry me = p.m_metadata.at(i);
++ if(me.m_name.startsWith("dc:identifier")) {
++ QString value = QString(me.m_content).remove("urn:uuid:");
++ if (!QUuid(value).isNull()) {
++ return value;
++ }
++ }
++ }
++ // EnsureUUIDIdentifierPresent should ensure we
++ // never reach here.
++ Q_ASSERT(false);
++ return QString();
++}
++
++
++void OPFResource::EnsureUUIDIdentifierPresent()
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ for (int i=0; i < p.m_metadata.count(); ++i) {
++ MetaEntry me = p.m_metadata.at(i);
++ if(me.m_name.startsWith("dc:identifier")) {
++ QString value = QString(me.m_content).remove("urn:uuid:");
++ if (!QUuid(value).isNull()) {
++ return;
++ }
++ }
++ }
++ QString uuid = Utility::CreateUUID();
++ // add in the proper identifier type prefix
++ if (!uuid.startsWith("urn:uuid:")) {
++ uuid = "urn:uuid:" + uuid;
++ }
++ WriteIdentifier("UUID", uuid, p);
++ UpdateText(p);
++}
++
++// This routine add the NCX to the OPF Mainifest
++// ncx_path is the full absolute file path to the ncx
++QString OPFResource::AddNCXItem(const QString &ncx_path, QString id)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QString ncx_bkpath = ncx_path.right(ncx_path.length() - GetFullPathToBookFolder().length() - 1);
++ QString ncx_rel_path = Utility::buildRelativePath(GetRelativePath(), ncx_bkpath);
++ int n = p.m_manifest.count();
++ ManifestEntry me;
++ me.m_id = GetUniqueID(id, p);
++ me.m_href = Utility::URLEncodePath(ncx_rel_path);
++ me.m_mtype = "application/x-dtbncx+xml";
++ p.m_manifest.append(me);
++ p.m_idpos[me.m_id] = n;
++ p.m_hrefpos[me.m_href] = n;
++ UpdateText(p);
++ return me.m_id;
++}
++
++
++void OPFResource::UpdateNCXOnSpine(const QString &new_ncx_id)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QString ncx_id = p.m_spineattr.m_atts.value(QString("toc"),"");
++ if (new_ncx_id != ncx_id) {
++ p.m_spineattr.m_atts[QString("toc")] = new_ncx_id;
++ UpdateText(p);
++ }
++}
++
++void OPFResource::RemoveNCXOnSpine()
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ p.m_spineattr.m_atts.remove("toc");
++ UpdateText(p);
++}
++
++
++void OPFResource::UpdateNCXLocationInManifest(const NCXResource *ncx)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QString ncx_id = p.m_spineattr.m_atts.value(QString("toc"), "");
++ int pos = p.m_idpos.value(ncx_id, -1);
++ if (pos > -1) {
++ ManifestEntry me = p.m_manifest.at(pos);
++ QString href = me.m_href;
++ QString new_href = Utility::URLEncodePath(GetRelativePathToResource(ncx));
++ me.m_href = new_href;
++ p.m_manifest.replace(pos, me);
++ p.m_hrefpos.remove(href);
++ p.m_hrefpos[new_href] = pos;
++ UpdateText(p);
++ }
++}
++
++
++void OPFResource::AddSigilVersionMeta()
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ for (int i=0; i < p.m_metadata.count(); ++i) {
++ MetaEntry me = p.m_metadata.at(i);
++ if ((me.m_name == "meta") && (me.m_atts.contains("name"))) {
++ QString name = me.m_atts[QString("name")];
++ if (name == SIGIL_VERSION_META_NAME) {
++ me.m_atts["content"] = QString(SIGIL_VERSION);
++ p.m_metadata.replace(i, me);
++ UpdateText(p);
++ return;
++ }
++ }
++ }
++ MetaEntry me;
++ me.m_name = "meta";
++ me.m_atts[QString("name")] = QString("Sigil version");
++ me.m_atts[QString("content")] = QString(SIGIL_VERSION);
++ p.m_metadata.append(me);
++ UpdateText(p);
++}
++
++
++bool OPFResource::IsCoverImage(const ImageResource *image_resource) const
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QString resource_id = GetResourceManifestID(image_resource, p);
++ return IsCoverImageCheck(resource_id, p);
++}
++
++
++bool OPFResource::IsCoverImageCheck(QString resource_id, const OPFParser & p) const
++{
++ int pos = GetCoverMeta(p);
++ if (pos > -1) {
++ MetaEntry me = p.m_metadata.at(pos);
++ return me.m_atts.value(QString("content"),QString("")) == resource_id;
++ }
++ return false;
++}
++
++
++bool OPFResource::CoverImageExists() const
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ return GetCoverMeta(p) > -1;
++}
++
++
++void OPFResource::AutoFixWellFormedErrors()
++{
++ QWriteLocker locker(&GetLock());
++ const QStringList TEXT_EXTS = QStringList() << "htm" << "html" << "xhtml";
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ // auto fill in spine from manifest if completely empty
++ if (p.m_spine.count() == 0) {
++ std::vector< std::pair< QString, QString > > txts;
++ for (int i=0; i < p.m_manifest.count(); i++) {
++ ManifestEntry me = p.m_manifest.at(i);
++ QString ahref = Utility::URLDecodePath(me.m_href);
++ QString aid = me.m_id;
++ QString ext = QFileInfo(ahref).suffix();
++ if ((me.m_mtype == "application/xhtml+xml") || TEXT_EXTS.contains(ext.toLower())) {
++ txts.push_back(std::make_pair(ahref, aid));
++ }
++ }
++ std::sort(txts.begin(), txts.end(), Utility::sort_string_pairs_by_first);
++ for (unsigned int j=0; j < txts.size(); j++) {
++ QString idref = txts.at(j).second;
++ SpineEntry sp;
++ sp.m_idref = idref;
++ p.m_spine << sp;
++ }
++ }
++ UpdateText(p);
++}
++
++
++QStringList OPFResource::GetSpineOrderBookPaths() const
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QStringList book_paths_in_reading_order;
++ for (int i=0; i < p.m_spine.count(); ++i) {
++ SpineEntry sp = p.m_spine.at(i);
++ QString idref = sp.m_idref;
++ int pos = p.m_idpos.value(idref,-1);
++ if (pos > -1) {
++ QString apath = Utility::URLDecodePath(p.m_manifest.at(pos).m_href);
++ book_paths_in_reading_order.append(Utility::buildBookPath(apath,GetFolder()));
++ }
++ }
++ return book_paths_in_reading_order;
++}
++
++QString OPFResource::GetPrimaryBookTitle() const
++{
++ QString title = "";
++ QStringList titles = GetDCMetadataValues("dc:title");
++ if (!titles.isEmpty()) {
++ title = titles.at(0);
++ }
++ return title;
++}
++
++QString OPFResource::GetPrimaryBookLanguage() const
++{
++ SettingsStore settings;
++ QString lang = settings.defaultMetadataLang();
++ QStringList languages = GetDCMetadataValues("dc:language");
++ if (!languages.isEmpty()) {
++ lang = languages.at(0);
++ }
++ return lang;
++}
++
++QList<MetaEntry> OPFResource::GetDCMetadata() const
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QList<MetaEntry> metadata;
++ for (int i=0; i < p.m_metadata.count(); ++i) {
++ if (p.m_metadata.at(i).m_name.startsWith("dc:")) {
++ MetaEntry me(p.m_metadata.at(i));
++ metadata.append(me);
++ }
++ }
++ return metadata;
++}
++
++
++QStringList OPFResource::GetDCMetadataValues(QString text) const
++{
++ QStringList metavalues;
++ foreach(MetaEntry meta, GetDCMetadata()) {
++ if (meta.m_name == text) {
++ metavalues.append(meta.m_content);
++ }
++ }
++ return metavalues;
++}
++
++
++void OPFResource::SetDCMetadata(const QList<MetaEntry> &metadata)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ // this will not work with refines so it needs to be fixed
++ RemoveDCElements(p);
++ foreach(MetaEntry book_meta, metadata) {
++ MetaEntry me(book_meta);
++ me.m_content = me.m_content.toHtmlEscaped();
++ p.m_metadata.append(me);
++ }
++ UpdateText(p);
++}
++
++
++void OPFResource::AddResource(const Resource *resource)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ ManifestEntry me;
++ me.m_id = GetUniqueID(GetValidID(resource->Filename()),p);
++ me.m_href = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ me.m_mtype = GetResourceMimetype(resource);
++ // Argh! If this is an new blank resource - it will have no content yet
++ // so trying to parse it here to check for manifest properties is a mistake
++ int n = p.m_manifest.count();
++ p.m_manifest.append(me);
++ p.m_idpos[me.m_id] = n;
++ p.m_hrefpos[me.m_href] = n;
++ if (resource->Type() == Resource::HTMLResourceType) {
++ SpineEntry se;
++ se.m_idref = me.m_id;
++ p.m_spine.append(se);
++ }
++ UpdateText(p);
++}
++
++void OPFResource::RemoveCoverImageProperty(QString& resource_id, OPFParser& p)
++{
++ // remove the cover image property from manifest with resource_id
++ if (!resource_id.isEmpty()) {
++ int pos = p.m_idpos.value(resource_id, -1);
++ if (pos >= 0 ) {
++ ManifestEntry me = p.m_manifest.at(p.m_idpos[resource_id]);
++ QString properties = me.m_atts.value("properties", "");
++ if (properties.contains("cover-image")) {
++ properties = properties.remove("cover-image");
++ properties = properties.simplified();
++ }
++ me.m_atts.remove("properties");
++ if (!properties.isEmpty()) {
++ me.m_atts["properties"] = properties;
++ }
++ p.m_manifest.replace(pos, me);
++ }
++ }
++}
++
++
++void OPFResource::AddCoverImageProperty(QString& resource_id, OPFParser& p)
++{
++ // add the cover image property from manifest with resource_id
++ if (!resource_id.isEmpty()) {
++ int pos = p.m_idpos.value(resource_id, -1);
++ if (pos >= 0 ) {
++ ManifestEntry me = p.m_manifest.at(p.m_idpos[resource_id]);
++ QString properties = me.m_atts.value("properties", "cover-image");
++ if (!properties.contains("cover-image")) {
++ properties = properties.append(" cover-image");
++ }
++ me.m_atts.remove("properties");
++ me.m_atts["properties"] = properties;
++ p.m_manifest.replace(pos, me);
++ }
++ }
++}
++
++
++void OPFResource::RemoveCoverMetaForImage(const Resource *resource, OPFParser& p)
++{
++ int pos = GetCoverMeta(p);
++ QString resource_id = GetResourceManifestID(resource, p);
++
++ // Remove entry if there is a cover in meta and if this file is marked as cover
++ if (pos > -1) {
++ MetaEntry me = p.m_metadata.at(pos);
++ if (me.m_atts.value(QString("content"),QString("")) == resource_id) {
++ p.m_metadata.removeAt(pos);
++ }
++ }
++}
++
++void OPFResource::AddCoverMetaForImage(const Resource *resource, OPFParser &p)
++{
++ int pos = GetCoverMeta(p);
++ QString resource_id = GetResourceManifestID(resource, p);
++
++ // If a cover entry exists, update its id, else create one
++ if (pos > -1) {
++ MetaEntry me = p.m_metadata.at(pos);
++ me.m_atts["content"] = resource_id;
++ p.m_metadata.replace(pos, me);
++ } else {
++ MetaEntry me;
++ me.m_name = "meta";
++ me.m_atts["name"] = "cover";
++ me.m_atts["content"] = QString(resource_id);
++ p.m_metadata.append(me);
++ }
++}
++
++
++void OPFResource::BulkRemoveResources(const QList<Resource *>resources)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ if (p.m_manifest.isEmpty()) return;
++
++ foreach(Resource * resource, resources) {
++ QString href = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ int pos = p.m_hrefpos.value(href, -1);
++ QString item_id = "";
++
++ // Delete the meta tag for cover images before deleting the manifest entry
++ if (resource->Type() == Resource::ImageResourceType) {
++ RemoveCoverMetaForImage(resource, p);
++ }
++ if (pos > -1) {
++ item_id = p.m_manifest.at(pos).m_id;
++ }
++ if (resource->Type() == Resource::HTMLResourceType) {
++ for (int i=0; i < p.m_spine.count(); ++i) {
++ QString idref = p.m_spine.at(i).m_idref;
++ if (idref == item_id) {
++ p.m_spine.removeAt(i);
++ break;
++ }
++ }
++ RemoveGuideReferenceForResource(resource, p);
++ QString version = GetEpubVersion();
++ if (version.startsWith('3')) {
++ NavProcessor navproc(GetNavResource());
++ navproc.RemoveLandmarkForResource(resource);
++ }
++ }
++ if (pos > -1) {
++ p.m_manifest.removeAt(pos);
++ // rebuild the maps since updating them item by item would be slower
++ p.m_idpos.clear();
++ p.m_hrefpos.clear();
++ for (int i=0; i < p.m_manifest.count(); ++i) {
++ p.m_idpos[p.m_manifest.at(i).m_id] = i;
++ p.m_hrefpos[p.m_manifest.at(i).m_href] = i;
++ }
++ }
++ }
++ UpdateText(p);
++}
++
++
++void OPFResource::RemoveResource(const Resource *resource)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ if (p.m_manifest.isEmpty()) return;
++ QString href = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ int pos = p.m_hrefpos.value(href, -1);
++ QString item_id = "";
++
++ // Delete the meta tag for cover images before deleting the manifest entry
++ if (resource->Type() == Resource::ImageResourceType) {
++ RemoveCoverMetaForImage(resource, p);
++ }
++ if (pos > -1) {
++ item_id = p.m_manifest.at(pos).m_id;
++ }
++ if (resource->Type() == Resource::HTMLResourceType) {
++ for (int i=0; i < p.m_spine.count(); ++i) {
++ QString idref = p.m_spine.at(i).m_idref;
++ if (idref == item_id) {
++ p.m_spine.removeAt(i);
++ break;
++ }
++ }
++ RemoveGuideReferenceForResource(resource, p);
++ QString version = GetEpubVersion();
++ if (version.startsWith('3')) {
++ NavProcessor navproc(GetNavResource());
++ navproc.RemoveLandmarkForResource(resource);
++ }
++ }
++ if (pos > -1) {
++ p.m_manifest.removeAt(pos);
++ // rebuild the maps since updating them item by item would be slower
++ p.m_idpos.clear();
++ p.m_hrefpos.clear();
++ for (int i=0; i < p.m_manifest.count(); ++i) {
++ p.m_idpos[p.m_manifest.at(i).m_id] = i;
++ p.m_hrefpos[p.m_manifest.at(i).m_href] = i;
++ }
++ }
++ UpdateText(p);
++}
++
++
++void OPFResource::ClearSemanticCodesInGuide()
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ foreach(GuideEntry ge, p.m_guide) {
++ p.m_guide.removeAt(0);
++ }
++ UpdateText(p);
++}
++
++
++void OPFResource::AddGuideSemanticCode(HTMLResource *html_resource, QString new_code, bool toggle)
++{
++ //first get primary book language
++ QString lang = GetPrimaryBookLanguage();
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QString current_code = GetGuideSemanticCodeForResource(html_resource, p);
++
++ if ((current_code != new_code) || !toggle) {
++ RemoveDuplicateGuideCodes(new_code, p);
++ SetGuideSemanticCodeForResource(new_code, html_resource, p, lang);
++ } else {
++ // If the current code is the same as the new one,
++ // we toggle it off.
++ RemoveGuideReferenceForResource(html_resource, p);
++ }
++ UpdateText(p);
++}
++
++QString OPFResource::GetGuideSemanticCodeForResource(const Resource *resource, const OPFParser &p) const
++{
++ QString gtype;
++ int pos = GetGuideReferenceForResourcePos(resource, p);
++ if (pos > -1) {
++ GuideEntry ge = p.m_guide.at(pos);
++ gtype = ge.m_type;
++ }
++ return gtype;
++}
++
++int OPFResource::GetGuideReferenceForResourcePos(const Resource *resource, const OPFParser &p) const
++{
++ QString href_to_resource_from_opf = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ for (int i=0; i < p.m_guide.count(); ++i) {
++ GuideEntry ge = p.m_guide.at(i);
++ QString href = ge.m_href;
++ QStringList parts = href.split('#', QT_ENUM_KEEPEMPTYPARTS);
++ if (parts.at(0) == href_to_resource_from_opf) {
++ return i;
++ }
++ }
++ return -1;
++}
++
++void OPFResource::RemoveDuplicateGuideCodes(QString code, OPFParser& p)
++{
++ // Industry best practice is to have only one
++ // <guide> reference type instance per xhtml file.
++ // For NoType, there is nothing to remove.
++ if (code.isEmpty()) return;
++ if (p.m_guide.isEmpty()) return;
++
++ // build up the list to be deleted in reverse order
++ QList<int> dellist;
++ for (int i = p.m_guide.count() - 1; i >= 0; --i) {
++ GuideEntry ge = p.m_guide.at(i);
++ QString gtype = ge.m_type;
++ if (gtype == code) {
++ dellist.append(i);
++ }
++ }
++ // remove them from the list in reverse order
++ foreach(int index, dellist) {
++ p.m_guide.removeAt(index);
++ }
++}
++
++void OPFResource::RemoveGuideReferenceForResource(const Resource *resource, OPFParser& p)
++{
++ // if guide hrefs use fragments, the same resource may be there in multiple
++ // guide entries. Since resource being deleted, remove them all
++ if (p.m_guide.isEmpty()) return;
++ int pos = GetGuideReferenceForResourcePos(resource, p);
++ while((pos > -1) && (!p.m_guide.isEmpty())) {
++ p.m_guide.removeAt(pos);
++ pos = GetGuideReferenceForResourcePos(resource, p);
++ }
++}
++
++
++void OPFResource::UpdateGuideFragments(QHash<QString,QString> &idupdates)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ for(int c=0; c < p.m_guide.size(); c++) {
++ GuideEntry ge = p.m_guide.at(c);
++ QString href = ge.m_href;
++ std::pair<QString, QString> parts = Utility::parseRelativeHREF(href);
++ QString apath = Utility::URLDecodePath(parts.first);
++ QString bkpath = Utility::buildBookPath(apath, GetFolder());
++ QString key = bkpath + parts.second;
++ QString newid = idupdates.value(key,"");
++ if (!newid.isEmpty()) {
++ // found a fragment id needing to be updated
++ parts.second = "#" + newid;
++ href = Utility::buildRelativeHREF(apath, parts.second);
++ ge.m_href = href;
++ p.m_guide[c] = ge;
++ }
++ }
++ UpdateText(p);
++}
++
++
++// first merged resource in list is the sink resource
++void OPFResource::UpdateGuideAfterMerge(QList<Resource*> &merged_resources, QHash<QString,QString> &section_id_map)
++{
++ if (merged_resources.isEmpty() || merged_resources.size() < 2) return;
++ Resource* sink_resource = merged_resources.at(0);
++ QString sink_bookpath = sink_resource->GetRelativePath();
++ QStringList merged_bookpaths;
++ for (int i=1; i < merged_resources.size(); i++) {
++ Resource* res = merged_resources.at(i);
++ merged_bookpaths << res->GetRelativePath();
++ }
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ for(int c=0; c < p.m_guide.size(); c++) {
++ GuideEntry ge = p.m_guide.at(c);
++ QString href = ge.m_href;
++ std::pair<QString, QString> parts = Utility::parseRelativeHREF(href);
++ QString apath = Utility::URLDecodePath(parts.first);
++ QString bkpath = Utility::buildBookPath(apath, GetFolder());
++ if (merged_bookpaths.contains(bkpath)) {
++ // need to redirect this bookpath to destination bookpath
++ // handle nay redirect to new injected section fragments
++ if (parts.second.isEmpty()) {
++ if (section_id_map.contains(bkpath)) {
++ parts.second = "#" + section_id_map[bkpath];
++ }
++ }
++ apath = Utility::buildRelativePath(GetRelativePath(), sink_bookpath);
++ href = Utility::buildRelativeHREF(apath, parts.second);
++ ge.m_href = href;
++ p.m_guide[c] = ge;
++ }
++ }
++ UpdateText(p);
++}
++
++void OPFResource::SetGuideSemanticCodeForResource(QString code, const Resource *resource, OPFParser& p, const QString &lang)
++{
++ if (code.isEmpty()) return;
++ int pos = GetGuideReferenceForResourcePos(resource, p);
++ QString title = GuideItems::instance()->GetTitle(code, lang);
++ if (pos > -1) {
++ GuideEntry ge = p.m_guide.at(pos);
++ ge.m_type = code;
++ ge.m_title = title;
++ p.m_guide.replace(pos, ge);
++ } else {
++ GuideEntry ge;
++ ge.m_type = code;
++ ge.m_title = title;
++ ge.m_href = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ p.m_guide.append(ge);
++ }
++}
++
++
++QString OPFResource::GetGuideSemanticCodeForResource(const Resource *resource) const
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ return GetGuideSemanticCodeForResource(resource, p);
++}
++
++
++QString OPFResource::GetGuideSemanticNameForResource(Resource *resource)
++{
++ return GuideItems::instance()->GetName(GetGuideSemanticCodeForResource(resource));
++}
++
++
++QHash <QString, QString> OPFResource::GetSemanticCodeForPaths()
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++
++ QHash <QString, QString> semantic_types;
++ foreach(GuideEntry ge, p.m_guide) {
++ QString href = ge.m_href;
++ QStringList parts = href.split('#', QT_ENUM_KEEPEMPTYPARTS);
++ QString apath = Utility::URLDecodePath(parts.at(0));
++ QString bkpath = Utility::buildBookPath(apath, GetFolder());
++ QString gtype = ge.m_type;
++ semantic_types[bkpath] = gtype;
++ }
++ return semantic_types;
++}
++
++
++QHash <QString, QString> OPFResource::GetGuideSemanticNameForPaths()
++{
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++
++ QHash <QString, QString> semantic_types;
++ foreach(GuideEntry ge, p.m_guide) {
++ QString href = ge.m_href;
++ QStringList parts = href.split('#', QT_ENUM_KEEPEMPTYPARTS);
++ QString gtype = ge.m_type;
++ QString apath = Utility::URLDecodePath(parts.at(0));
++ QString bkpath = Utility::buildBookPath(apath, GetFolder());
++ semantic_types[bkpath] = GuideItems::instance()->GetName(gtype);
++ }
++
++ // Cover image semantics don't use reference
++ int pos = GetCoverMeta(p);
++ if (pos > -1) {
++ MetaEntry me = p.m_metadata.at(pos);
++ QString cover_id = me.m_atts.value(QString("content"),QString(""));
++ ManifestEntry man = p.m_manifest.at(p.m_idpos[cover_id]);
++ QString apath = Utility::URLDecodePath(man.m_href);
++ QString bkpath = Utility::buildBookPath(apath, GetFolder());
++ semantic_types[bkpath] = GuideItems::instance()->GetName("cover");
++ }
++ return semantic_types;
++}
++
++
++void OPFResource::SetResourceAsCoverImage(ImageResource *image_resource)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QString resource_id = GetResourceManifestID(image_resource, p);
++
++ // First deal with any previous covers by removing
++ // related metadata and manifest properties
++ QString old_cover_resource_id;
++ int pos = GetCoverMeta(p);
++ if (pos > -1) {
++ MetaEntry me = p.m_metadata.at(pos);
++ old_cover_resource_id = me.m_atts.value(QString("content"),QString(""));
++ p.m_metadata.removeAt(pos);
++ }
++ if (!old_cover_resource_id.isEmpty()) {
++ if (p.m_package.m_version.startsWith("3")) {
++ RemoveCoverImageProperty(old_cover_resource_id, p);
++ }
++ }
++
++ // Now add in new metadata and manifest properties
++ AddCoverMetaForImage(image_resource, p);
++ if (p.m_package.m_version.startsWith("3")) {
++ AddCoverImageProperty(resource_id, p);
++ }
++ UpdateText(p);
++}
++
++
++// note: under epub3 spine elements may have page properties set, so simply clearing the
++// spine will lose these attributes. We should try to keep as much of the spine properties
++// and linear attributes as we can. Either that or make the HTML Resource remember its own
++// spine page properties, linear attribute, etc
++
++void OPFResource::UpdateSpineOrder(const QList<::HTMLResource *> html_files)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QList<SpineEntry> new_spine;
++ foreach(HTMLResource * html_resource, html_files) {
++ const Resource *resource = static_cast<const Resource *>(html_resource);
++ QString id = GetResourceManifestID(resource, p);
++ int found = -1;
++ for (int i = 0; i < p.m_spine.count(); ++i) {
++ SpineEntry se = p.m_spine.at(i);
++ if (se.m_idref == id) {
++ found = i;
++ break;
++ }
++ }
++ if (found > -1) {
++ new_spine.append(p.m_spine.at(found));
++ } else {
++ SpineEntry se;
++ se.m_idref = id;
++ new_spine.append(se);
++ }
++ }
++ p.m_spine.clear();
++ p.m_spine = new_spine;
++ UpdateText(p);
++}
++
++
++void OPFResource::ResourceRenamed(const Resource *resource, QString old_full_path)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ // first convert old_full_path to old_bkpath
++ QString old_bkpath = old_full_path.right(old_full_path.length() - GetFullPathToBookFolder().length() - 1);
++ QString old_href = Utility::URLEncodePath(Utility::buildRelativePath(GetRelativePath(), old_bkpath));
++ QString old_id;
++ QString new_id;
++ for (int i=0; i < p.m_manifest.count(); ++i) {
++ QString href = p.m_manifest.at(i).m_href;
++ if (href == old_href) {
++ ManifestEntry me = p.m_manifest.at(i);
++ QString old_me_href = me.m_href;
++ me.m_href = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ old_id = me.m_id;
++ p.m_idpos.remove(old_id);
++ new_id = GetUniqueID(GetValidID(resource->Filename()),p);
++ me.m_id = new_id;
++ p.m_idpos[new_id] = i;
++ p.m_hrefpos.remove(old_me_href);
++ p.m_hrefpos[me.m_href] = i;
++ p.m_manifest.replace(i, me);
++ break;
++ }
++ }
++ for (int i=0; i < p.m_spine.count(); ++i) {
++ QString idref = p.m_spine.at(i).m_idref;
++ if (idref == old_id) {
++ SpineEntry se = p.m_spine.at(i);
++ se.m_idref = new_id;
++ p.m_spine.replace(i, se);
++ break;
++ }
++ }
++ if (resource->Type() == Resource::NCXResourceType) {
++ // handle updating the ncx id on the spine if ncx renamed
++ QString ncx_id = p.m_spineattr.m_atts.value(QString("toc"),"");
++ if (new_id != ncx_id) {
++ p.m_spineattr.m_atts[QString("toc")] = new_id;
++ }
++ }
++ if (resource->Type() == Resource::ImageResourceType) {
++ // Change meta entry for cover if necessary
++ // Check using IDs since file is already renamed
++ if (IsCoverImageCheck(old_id, p)) {
++ // Add will automatically replace an existing id
++ // Assumes only one cover but removing duplicates
++ // can cause timing issues
++ AddCoverMetaForImage(resource, p);
++ }
++ }
++ UpdateText(p);
++}
++
++
++void OPFResource::ResourceMoved(const Resource *resource, QString old_full_path)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ // first convert old_full_path to old_bkpath
++ QString old_bkpath = old_full_path.right(old_full_path.length() - GetFullPathToBookFolder().length() - 1);
++ QString old_href = Utility::URLEncodePath(Utility::buildRelativePath(GetRelativePath(), old_bkpath));
++ // a move should not impact the id so leave the old unique manifest id unchanged
++ for (int i=0; i < p.m_manifest.count(); ++i) {
++ QString href = p.m_manifest.at(i).m_href;
++ if (href == old_href) {
++ ManifestEntry me = p.m_manifest.at(i);
++ QString old_me_href = me.m_href;
++ me.m_href = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ p.m_idpos[me.m_id] = i;
++ p.m_hrefpos.remove(old_me_href);
++ p.m_hrefpos[me.m_href] = i;
++ p.m_manifest.replace(i, me);
++ break;
++ }
++ }
++ UpdateText(p);
++}
++
++
++int OPFResource::GetCoverMeta(const OPFParser& p) const
++{
++ for (int i = 0; i < p.m_metadata.count(); ++i) {
++ MetaEntry me = p.m_metadata.at(i);
++ if ((me.m_name == "meta") && (me.m_atts.contains(QString("name")))) {
++ QString name = me.m_atts[QString("name")];
++ if (name == "cover") {
++ return i;
++ }
++ }
++ }
++ return -1;
++}
++
++
++int OPFResource::GetMainIdentifier(const OPFParser& p) const
++{
++ QString unique_identifier = p.m_package.m_uniqueid;
++ for (int i=0; i < p.m_metadata.count(); ++i) {
++ MetaEntry me = p.m_metadata.at(i);
++ if (me.m_name == "dc:identifier") {
++ QString id = me.m_atts.value("id", "");
++ if (id == unique_identifier) {
++ return i;
++ }
++ }
++ }
++ return -1;
++}
++
++QHash<QString, Resource*>OPFResource::GetManifestIDResourceMapping(const QList<Resource *> &resources,
++ const OPFParser &p)
++{
++ QHash<QString, Resource*> id_mapping;
++ foreach(Resource * resource, resources) {
++ QString href_path = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ int pos = p.m_hrefpos.value(href_path,-1);
++ if (pos > -1) {
++ id_mapping[ p.m_manifest.at(pos).m_id ] = resource;
++ }
++ }
++ return id_mapping;
++}
++
++
++QString OPFResource::GetResourceManifestID(const Resource *resource, const OPFParser& p) const
++{
++ QString href_path = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ int pos = p.m_hrefpos.value(href_path,-1);
++ if (pos > -1) {
++ return QString(p.m_manifest.at(pos).m_id);
++ }
++ qDebug() << "GetResourceMainfestID returning null" << href_path;
++ return QString();
++}
++
++
++QHash<Resource *, QString> OPFResource::GetResourceManifestIDMapping(const QList<Resource *> &resources,
++ const OPFParser& p)
++{
++ QHash<Resource *, QString> id_mapping;
++ QStringList keys = p.m_hrefpos.keys();
++ foreach(Resource * resource, resources) {
++ QString href_path = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ // empty relative path from the OPF is the OPF which will not have a manifest entry
++ if (!href_path.isEmpty()) {
++ int pos = p.m_hrefpos.value(href_path,-1);
++ if (pos > -1) {
++ id_mapping[ resource ] = p.m_manifest.at(pos).m_id;
++ } else {
++ qDebug() << "GetResourceMainifestIDMapping no map for" << href_path;
++ }
++ }
++ }
++ return id_mapping;
++}
++
++
++void OPFResource::RemoveDCElements(OPFParser& p)
++{
++ int pos = GetMainIdentifier(p);
++ // build list to be delted in reverse order
++ QList<int> dellist;
++ int n = p.m_metadata.count();
++ for (int i = n-1; i >= 0; --i) {
++ MetaEntry me = p.m_metadata.at(i);
++ if (me.m_name.startsWith("dc:")) {
++ if (i != pos) {
++ dellist.append(i);
++ }
++ }
++ }
++ // delete the MetaEntries in reverse order to not mess up indexes
++ foreach(int index, dellist) {
++ p.m_metadata.removeAt(index);
++ }
++}
++
++
++void OPFResource::WriteSimpleMetadata(const QString &metaname, const QString &metavalue, OPFParser& p)
++{
++ MetaEntry me;
++ me.m_name = QString("dc:") + metaname;
++ me.m_content = metavalue.toHtmlEscaped();
++ p.m_metadata.append(me);
++}
++
++
++void OPFResource::WriteIdentifier(const QString &metaname, const QString &metavalue, OPFParser& p)
++{
++ int pos = GetMainIdentifier(p);
++ if (pos > -1) {
++ MetaEntry me = p.m_metadata.at(pos);
++ QString scheme = me.m_atts.value(QString("scheme"),QString(""));
++ // epub3 no longer uses the scheme attribute
++ if (scheme.isEmpty() && me.m_content.startsWith("urn:uuid:")) scheme="UUID";
++ if ((metavalue == me.m_content) && (metaname == scheme)) {
++ return;
++ }
++ }
++ QString epubversion = GetEpubVersion();
++ MetaEntry me;
++ me.m_name = QString("dc:identifier");
++ // under the latest epub3 spec "scheme" is no longer an allowed attribute of dc:identifier
++ if (epubversion.startsWith('2')) {
++ me.m_atts[QString("opf:scheme")] = metaname;
++ }
++ if (metaname.toLower() == "uuid" && !metavalue.contains("urn:uuid:")) {
++ me.m_content = QString("urn:uuid:") + metavalue;
++ } else {
++ me.m_content = metavalue;
++ }
++ p.m_metadata.append(me);
++}
++
++QString OPFResource::AddModificationDateMeta()
++{
++ QString datetime;
++ QDateTime local(QDateTime::currentDateTime());
++ local.setTimeSpec(Qt::UTC);
++ datetime = local.toString(Qt::ISODate);
++
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++
++ QString epubversion = GetEpubVersion();
++ if (epubversion.startsWith('3')) {
++
++ // epub 3 set dcterms:modified date time in ISO 8601 format
++ // if an entry exists, update it
++ for (int i=0; i < p.m_metadata.count(); ++i) {
++ MetaEntry me = p.m_metadata.at(i);
++ if (me.m_name == QString("meta")) {
++ QString property = me.m_atts.value(QString("property"), QString(""));
++ if (property == QString("dcterms:modified")) {
++ me.m_content = datetime;
++ p.m_metadata.replace(i, me);
++ UpdateText(p);
++ return datetime;
++ }
++ }
++ }
++ // otherwize create a new entry
++ MetaEntry me;
++ me.m_name = QString("meta");
++ me.m_content = datetime;
++ me.m_atts["property"]="dcterms:modified";
++ p.m_metadata.append(me);
++ UpdateText(p);
++ return datetime;
++ }
++ // epub 2 version
++ QString date;
++ QDate d = QDate::currentDate();
++ // We can't use QDate.toString() because it will take into account the locale. Which mean we may not get Arabic
++ // numerals if the local uses it's own numbering system. So we use this instead to ensure we get a valid date per
++ // the epub spec.
++ QTextStream(&date) << d.year() << "-" << (d.month() < 10 ? "0" : "") << d.month() << "-" << (d.day() < 10 ? "0" : "") << d.day();
++ // if an entry exists, update it
++ for (int i=0; i < p.m_metadata.count(); ++i) {
++ MetaEntry me = p.m_metadata.at(i);
++ if (me.m_name == QString("dc:date")) {
++ QString etype = me.m_atts.value(QString("opf:event"), QString(""));
++ if (etype == QString("modification")) {
++ me.m_content = date;
++ p.m_metadata.replace(i, me);
++ UpdateText(p);
++ return datetime;
++ }
++
++ }
++ }
++ // otherwize create a new entry
++ MetaEntry me;
++ me.m_name = QString("dc:date");
++ me.m_content = date;
++ me.m_atts["xmlns:opf"]="http://www.idpf.org/2007/opf";
++ me.m_atts[QString("opf:event")] = QString("modification");
++ p.m_metadata.append(me);
++ UpdateText(p);
++ return datetime;
++}
++
++
++QString OPFResource::GetOPFDefaultText(const QString &version)
++{
++ SettingsStore ss;
++ QString defaultLanguage = ss.defaultMetadataLang();
++ if (version.startsWith('2')) {
++ return TEMPLATE_TEXT.arg(Utility::CreateUUID()).arg(defaultLanguage).arg(tr("[Title here]"));
++ }
++ // epub 3 set dcterms:modified date time in ISO 8601 format
++ QDateTime local(QDateTime::currentDateTime());
++ local.setTimeSpec(Qt::UTC);
++ QString datetime = local.toString(Qt::ISODate);
++ return TEMPLATE3_TEXT.arg(Utility::CreateUUID()).arg(defaultLanguage).arg(tr("[Main title here]")).arg(datetime);
++}
++
++
++void OPFResource::FillWithDefaultText(const QString &version)
++{
++ QString epubversion = version;
++ if (epubversion.isEmpty()) {
++ SettingsStore ss;
++ epubversion = ss.defaultVersion();
++ }
++ SetEpubVersion(epubversion);
++ SetText(GetOPFDefaultText(epubversion));
++}
++
++
++QString OPFResource::GetUniqueID(const QString &preferred_id, const OPFParser& p) const
++{
++ if (p.m_idpos.contains(preferred_id)) {
++ return QString("x").append(Utility::CreateUUID());
++ }
++ return preferred_id;
++}
++
++
++QString OPFResource::GetResourceMimetype(const Resource *resource) const
++{
++ QString mimetype = resource->GetMediaType();
++ if (mimetype.isEmpty()) {
++ mimetype = GetFileMimetype(resource->Filename());
++ }
++ return mimetype;
++}
++
++
++QString OPFResource::GetFileMimetype(const QString &filepath) const
++{
++ MediaTypes * MTMap = MediaTypes::instance();
++ QString extension = QFileInfo(filepath).suffix().toLower();
++ return MTMap->GetMediaTypeFromExtension(extension, FALLBACK_MIMETYPE);
++}
++
++
++void OPFResource::UpdateText(const OPFParser &p)
++{
++ TextResource::SetText(p.convert_to_xml());
++}
++
++
++QString OPFResource::ValidatePackageVersion(const QString& source)
++{
++ QString newsource = source;
++ QString orig_version = GetEpubVersion();
++ QRegularExpression pkgversion_search(PKG_VERSION, QRegularExpression::CaseInsensitiveOption);
++ QRegularExpressionMatch mo = pkgversion_search.match(newsource);
++ if (mo.hasMatch()) {
++ QString version = mo.captured(1);
++ if (version != orig_version) {
++ newsource.replace(mo.capturedStart(1), mo.capturedLength(1), orig_version);
++ if (!m_WarnedAboutVersion && !version.startsWith('1')) {
++ Utility::DisplayStdWarningDialog("Changing package version inside Sigil is not supported",
++ "Use an appropriate output plugin to make the initial conversion");
++ m_WarnedAboutVersion = true;
++ }
++ }
++ }
++ return newsource;
++}
++
++
++void OPFResource::UpdateManifestProperties(const QList<Resource*> resources)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ if (p.m_package.m_version != "3.0") {
++ return;
++ }
++ foreach(Resource* resource, resources) {
++ const HTMLResource* html_resource = static_cast<const HTMLResource *>(resource);
++ // do not overwrite the nav property, it must stay no matter what
++ if (html_resource != m_NavResource) {
++ QString href = Utility::URLEncodePath(GetRelativePathToResource(html_resource));
++ int pos = p.m_hrefpos.value(href, -1);
++ if ((pos >= 0) && (pos < p.m_manifest.count())) {
++ ManifestEntry me = p.m_manifest.at(pos);
++ QStringList properties = html_resource->GetManifestProperties();
++ me.m_atts.remove("properties");
++ if (properties.count() > 0) {
++ me.m_atts["properties"] = properties.join(QString(" "));
++ }
++ p.m_manifest.replace(pos, me);
++ }
++ }
++ }
++ // now add the cover-image properties
++ int metapos = GetCoverMeta(p);
++ if (metapos > -1) {
++ MetaEntry cmeta = p.m_metadata.at(metapos);
++ QString cover_id = cmeta.m_atts.value(QString("content"),QString(""));
++ if (!cover_id.isEmpty()) {
++ int pos = p.m_idpos.value(cover_id, -1);
++ if (pos >= 0 ) {
++ ManifestEntry me = p.m_manifest.at(p.m_idpos[cover_id]);
++ me.m_atts.remove("properties");
++ me.m_atts["properties"] = QString("cover-image");
++ p.m_manifest.replace(pos, me);
++ }
++ }
++ }
++ UpdateText(p);
++}
++
++
++QString OPFResource::GetManifestPropertiesForResource(const Resource * resource)
++{
++ QString properties;
++ if (!resource) return properties;
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ if (!p.m_package.m_version.startsWith("3")) {
++ return properties;
++ }
++ QString href = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ int pos = p.m_hrefpos.value(href, -1);
++ if ((pos >= 0) && (pos < p.m_manifest.count())) {
++ ManifestEntry me = p.m_manifest.at(pos);
++ properties = me.m_atts.value("properties","");
++ }
++ return properties;
++}
++
++
++QHash <QString, QString> OPFResource::GetManifestPropertiesForPaths()
++{
++ QHash <QString, QString> manifest_properties_all;
++ QString version = GetEpubVersion();
++ if (!version.startsWith('3')) {
++ return manifest_properties_all;
++ }
++ QReadLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ foreach(ManifestEntry me, p.m_manifest) {
++ QString apath = Utility::URLDecodePath(me.m_href);
++ if (me.m_atts.contains("properties")){
++ QString properties = me.m_atts["properties"];
++ apath = Utility::buildBookPath(apath, GetFolder());
++ manifest_properties_all[apath] = properties;
++ }
++ }
++ return manifest_properties_all;
++}
++
++
++HTMLResource * OPFResource::GetNavResource()const
++{
++ return m_NavResource;
++}
++
++
++void OPFResource::SetNavResource(HTMLResource * nav_resource)
++{
++ m_NavResource = nav_resource;
++ // Make sure the proper nav property is set in the opf manifest
++ if (m_NavResource) {
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QString href = Utility::URLEncodePath(GetRelativePathToResource(m_NavResource));
++ int pos = p.m_hrefpos.value(href, -1);
++ if ((pos >= 0) && (pos < p.m_manifest.count())) {
++ ManifestEntry me = p.m_manifest.at(pos);
++ me.m_atts["properties"] = QString("nav");
++ p.m_manifest.replace(pos, me);
++ }
++ UpdateText(p);
++ }
++}
++
++
++void OPFResource::SetItemRefLinear(Resource * resource, bool linear)
++{
++ QWriteLocker locker(&GetLock());
++ QString source = CleanSource::ProcessXML(GetText(),"application/oebps-package+xml");
++ OPFParser p;
++ p.parse(source);
++ QString resource_href_path = Utility::URLEncodePath(GetRelativePathToResource(resource));
++ int pos = p.m_hrefpos.value(resource_href_path, -1);
++ QString item_id = "";
++ if (pos > -1) {
++ item_id = p.m_manifest.at(pos).m_id;
++ if (resource->Type() == Resource::HTMLResourceType) {
++ for (int i=0; i < p.m_spine.count(); ++i) {
++ QString idref = p.m_spine.at(i).m_idref;
++ if (idref == item_id) {
++ SpineEntry se = p.m_spine.at(i);
++ se.m_atts.remove(QString("linear"));
++ // default is linear = "yes"
++ if (!linear) {
++ se.m_atts[QString("linear")] = QString("no");
++ }
++ p.m_spine.replace(i, se);
++ break;
++ }
++ }
++ }
++ UpdateText(p);
++ }
++}
+--
+2.42.0
+
diff --git a/0003-don-t-write-version-and-modified-tags.patch b/0003-don-t-write-version-and-modified-tags.patch
new file mode 100644
index 000000000000..7039c91ba00f
--- /dev/null
+++ b/0003-don-t-write-version-and-modified-tags.patch
@@ -0,0 +1,108 @@
+From 23d899891c3db7e09a72e16e2cfbadaee7285ebe Mon Sep 17 00:00:00 2001
+From: xiota
+Date: Sun, 29 Oct 2023 03:53:13 -0700
+Subject: [PATCH 3/3] don't write version and modified tags
+
+Don't write version and modification tags to the opf.
+Results in a somewhat cleaner opf.
+---
+ src/ResourceObjects/OPFResource.cpp | 30 +++---------------------
+ src/ResourceObjects/OPFResource.cpp.orig | 14 -----------
+ 2 files changed, 3 insertions(+), 41 deletions(-)
+
+diff --git a/src/ResourceObjects/OPFResource.cpp b/src/ResourceObjects/OPFResource.cpp
+index 7f7020b..5f79772 100644
+--- a/src/ResourceObjects/OPFResource.cpp
++++ b/src/ResourceObjects/OPFResource.cpp
+@@ -464,18 +464,11 @@ void OPFResource::AddSigilVersionMeta()
+ QString name = me.m_atts[QString("name")];
+ if (name == SIGIL_VERSION_META_NAME) {
+ me.m_atts["content"] = QString(SIGIL_VERSION);
+- p.m_metadata.replace(i, me);
+- UpdateText(p);
++ p.m_metadata.removeAt(i);
+ return;
+ }
+ }
+ }
+- MetaEntry me;
+- me.m_name = "meta";
+- me.m_atts[QString("name")] = QString("Sigil version");
+- me.m_atts[QString("content")] = QString(SIGIL_VERSION);
+- p.m_metadata.append(me);
+- UpdateText(p);
+ }
+
+
+@@ -1382,19 +1375,11 @@ QString OPFResource::AddModificationDateMeta()
+ QString property = me.m_atts.value(QString("property"), QString(""));
+ if (property == QString("dcterms:modified")) {
+ me.m_content = datetime;
+- p.m_metadata.replace(i, me);
+- UpdateText(p);
++ p.m_metadata.removeAt(i);
+ return datetime;
+ }
+ }
+ }
+- // otherwize create a new entry
+- MetaEntry me;
+- me.m_name = QString("meta");
+- me.m_content = datetime;
+- me.m_atts["property"]="dcterms:modified";
+- p.m_metadata.append(me);
+- UpdateText(p);
+ return datetime;
+ }
+ // epub 2 version
+@@ -1411,21 +1396,12 @@ QString OPFResource::AddModificationDateMeta()
+ QString etype = me.m_atts.value(QString("opf:event"), QString(""));
+ if (etype == QString("modification")) {
+ me.m_content = date;
+- p.m_metadata.replace(i, me);
+- UpdateText(p);
++ p.m_metadata.removeAt(i);
+ return datetime;
+ }
+
+ }
+ }
+- // otherwize create a new entry
+- MetaEntry me;
+- me.m_name = QString("dc:date");
+- me.m_content = date;
+- me.m_atts["xmlns:opf"]="http://www.idpf.org/2007/opf";
+- me.m_atts[QString("opf:event")] = QString("modification");
+- p.m_metadata.append(me);
+- UpdateText(p);
+ return datetime;
+ }
+
+diff --git a/src/ResourceObjects/OPFResource.cpp.orig b/src/ResourceObjects/OPFResource.cpp.orig
+index 4b7668d..7f7020b 100644
+--- a/src/ResourceObjects/OPFResource.cpp.orig
++++ b/src/ResourceObjects/OPFResource.cpp.orig
+@@ -1493,20 +1493,6 @@ void OPFResource::UpdateText(const OPFParser &p)
+ QString OPFResource::ValidatePackageVersion(const QString& source)
+ {
+ QString newsource = source;
+- QString orig_version = GetEpubVersion();
+- QRegularExpression pkgversion_search(PKG_VERSION, QRegularExpression::CaseInsensitiveOption);
+- QRegularExpressionMatch mo = pkgversion_search.match(newsource);
+- if (mo.hasMatch()) {
+- QString version = mo.captured(1);
+- if (version != orig_version) {
+- newsource.replace(mo.capturedStart(1), mo.capturedLength(1), orig_version);
+- if (!m_WarnedAboutVersion && !version.startsWith('1')) {
+- Utility::DisplayStdWarningDialog("Changing package version inside Sigil is not supported",
+- "Use an appropriate output plugin to make the initial conversion");
+- m_WarnedAboutVersion = true;
+- }
+- }
+- }
+ return newsource;
+ }
+
+--
+2.42.0
+
diff --git a/PKGBUILD b/PKGBUILD
index 51d37f928246..27128f2b16a8 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -8,7 +8,7 @@ _localepurge=
_pkgname=sigil
pkgname="$_pkgname-git"
-pkgver=2.0.2.r6.gd223713e5
+pkgver=2.0.2.r11.gb9438a876
pkgrel=1
pkgdesc='multi-platform EPUB2/EPUB3 ebook editor'
arch=('x86_64')
@@ -76,15 +76,15 @@ fi
options=(!debug)
source+=(
- 'default_nav_css.patch'
- 'skip_epub_version_check.patch'
- 'skip_version_mod_tags.patch'
+ '0001-modify-default-navigation-css.patch'
+ '0002-skip-epub-version-check.patch'
+ '0003-don-t-write-version-and-modified-tags.patch'
)
sha256sums+=(
- '3478ff361a34fd7cd7811d5103cbace91ecc790463684aaab9e21687b5553a28'
- 'fc2bdc23d13b2e917f08608b516495b744f991642f73c1f6d943cf322a25fc11'
- 'c74be3af315c9ffe181df6b465d0037f152f6078b953e6eeaab7b2932ae4c729'
+ 'c01f2028fd2a77fa48ddeefc70b780d185131f81c8c3b3f4f3bfd670cd1d574f'
+ 'd06138d38a2d29ca020ec575bd2aa975df48cf61bbad975140fe5f304e23f6b0'
+ '4bddaaf8666e3d060ba51989c94d6c3a2c23a5b037dd69abe6c61af51b580720'
)
prepare() {
diff --git a/default_nav_css.patch b/default_nav_css.patch
deleted file mode 100644
index fe49838156cb..000000000000
--- a/default_nav_css.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-Subject: [PATCH] modify default navigation css
-
---- old/src/BookManipulation/Book.cpp
-+++ new/src/BookManipulation/Book.cpp
-@@ -126,6 +126,16 @@
- "}\n\n"
- "ol {\n"
- " list-style-type: none;\n"
-+ " padding-left: 1.5rem;\n"
-+ "}\n\n"
-+ "li > ol {\n"
-+ " margin-bottom: 0.75rem;\n"
-+ "}\n\n"
-+ "li {\n"
-+ " margin-top: 0.25rem;\n"
-+ "}\n\n"
-+ "a {\n"
-+ " text-decoration: none;\n"
- "}\n\n";
-
-
diff --git a/skip_epub_version_check.patch b/skip_epub_version_check.patch
deleted file mode 100644
index b00f876b0952..000000000000
--- a/skip_epub_version_check.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-Subject: [PATCH] skip epub version check
-Description: allows changing from epub2 to epub3 by directly editing the opf
- some data is lost and needs to be recreated (eg, table of contents)
-
---- sigil.old/src/ResourceObjects/OPFResource.cpp
-+++ sigil.new/src/ResourceObjects/OPFResource.cpp
-@@ -1310,20 +1310,6 @@
- QString OPFResource::ValidatePackageVersion(const QString& source)
- {
- QString newsource = source;
-- QString orig_version = GetEpubVersion();
-- QRegularExpression pkgversion_search(PKG_VERSION, QRegularExpression::CaseInsensitiveOption);
-- QRegularExpressionMatch mo = pkgversion_search.match(newsource);
-- if (mo.hasMatch()) {
-- QString version = mo.captured(1);
-- if (version != orig_version) {
-- newsource.replace(mo.capturedStart(1), mo.capturedLength(1), orig_version);
-- if (!m_WarnedAboutVersion && !version.startsWith('1')) {
-- Utility::DisplayStdWarningDialog("Changing package version inside Sigil is not supported",
-- "Use an appropriate output plugin to make the initial conversion");
-- m_WarnedAboutVersion = true;
-- }
-- }
-- }
- return newsource;
- }
-
diff --git a/skip_version_mod_tags.patch b/skip_version_mod_tags.patch
deleted file mode 100644
index fdffc085a3a8..000000000000
--- a/skip_version_mod_tags.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-Subject: [PATCH] don't write version and modified tags
-Description: Don't write version and modification tags to the opf.
- Results in a somewhat cleaner opf.
-
---- sigil.old/src/ResourceObjects/OPFResource.cpp
-+++ sigil.new/src/ResourceObjects/OPFResource.cpp
-@@ -422,18 +422,11 @@
- QString name = me.m_atts[QString("name")];
- if (name == SIGIL_VERSION_META_NAME) {
- me.m_atts["content"] = QString(SIGIL_VERSION);
-- p.m_metadata.replace(i, me);
-- UpdateText(p);
-+ p.m_metadata.removeAt(i);
- return;
- }
- }
- }
-- MetaEntry me;
-- me.m_name = "meta";
-- me.m_atts[QString("name")] = QString("Sigil version");
-- me.m_atts[QString("content")] = QString(SIGIL_VERSION);
-- p.m_metadata.append(me);
-- UpdateText(p);
- }
-
-
-@@ -1199,19 +1192,11 @@
- QString property = me.m_atts.value(QString("property"), QString(""));
- if (property == QString("dcterms:modified")) {
- me.m_content = datetime;
-- p.m_metadata.replace(i, me);
-- UpdateText(p);
-+ p.m_metadata.removeAt(i);
- return datetime;
- }
- }
- }
-- // otherwize create a new entry
-- MetaEntry me;
-- me.m_name = QString("meta");
-- me.m_content = datetime;
-- me.m_atts["property"]="dcterms:modified";
-- p.m_metadata.append(me);
-- UpdateText(p);
- return datetime;
- }
- // epub 2 version
-@@ -1228,21 +1213,12 @@
- QString etype = me.m_atts.value(QString("opf:event"), QString(""));
- if (etype == QString("modification")) {
- me.m_content = date;
-- p.m_metadata.replace(i, me);
-- UpdateText(p);
-+ p.m_metadata.removeAt(i);
- return datetime;
- }
-
- }
- }
-- // otherwize create a new entry
-- MetaEntry me;
-- me.m_name = QString("dc:date");
-- me.m_content = date;
-- me.m_atts["xmlns:opf"]="http://www.idpf.org/2007/opf";
-- me.m_atts[QString("opf:event")] = QString("modification");
-- p.m_metadata.append(me);
-- UpdateText(p);
- return datetime;
- }
-