File indexing completed on 2024-05-12 16:06:53
0001 /* 0002 SPDX-FileCopyrightText: 2012 Marco Martin <mart@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "documentitem.h" 0008 0009 #include <QMimeDatabase> 0010 #include <QQmlEngine> 0011 0012 #ifdef Q_OS_ANDROID 0013 #include <QCoreApplication> 0014 #include <QJniObject> 0015 #endif 0016 0017 #include <core/bookmarkmanager.h> 0018 #include <core/document_p.h> 0019 #include <core/page.h> 0020 0021 #include "gui/signatureguiutils.h" 0022 0023 DocumentItem::DocumentItem(QObject *parent) 0024 : QObject(parent) 0025 , m_thumbnailObserver(nullptr) 0026 , m_pageviewObserver(nullptr) 0027 , m_searchInProgress(false) 0028 { 0029 qmlRegisterUncreatableType<TOCModel>("org.kde.okular.private", 1, 0, "TOCModel", QStringLiteral("Do not create objects of this type.")); 0030 qmlRegisterUncreatableType<SignatureModel>("org.kde.okular.private", 1, 0, "SignatureModel", QStringLiteral("Do not create objects of this type.")); 0031 Okular::Settings::instance(QStringLiteral("okularproviderrc")); 0032 m_document = new Okular::Document(nullptr); 0033 m_tocModel = new TOCModel(m_document, this); 0034 m_signaturesModel = new SignatureModel(m_document, this); 0035 0036 connect(m_document, &Okular::Document::searchFinished, this, &DocumentItem::searchFinished); 0037 connect(m_document->bookmarkManager(), &Okular::BookmarkManager::bookmarksChanged, this, &DocumentItem::bookmarkedPagesChanged); 0038 connect(m_document->bookmarkManager(), &Okular::BookmarkManager::bookmarksChanged, this, &DocumentItem::bookmarksChanged); 0039 connect(m_document, &Okular::Document::error, this, &DocumentItem::error); 0040 connect(m_document, &Okular::Document::warning, this, &DocumentItem::warning); 0041 connect(m_document, &Okular::Document::notice, this, &DocumentItem::notice); 0042 } 0043 0044 DocumentItem::~DocumentItem() 0045 { 0046 delete m_signaturesModel; 0047 delete m_document; 0048 } 0049 0050 void DocumentItem::setUrl(const QUrl &url) 0051 { 0052 openUrl(url, {}); 0053 } 0054 0055 void DocumentItem::openUrl(const QUrl &url, const QString &password) 0056 { 0057 m_document->closeDocument(); 0058 // TODO: password 0059 QMimeDatabase db; 0060 0061 QUrl realUrl = url; // NOLINT(performance-unnecessary-copy-initialization) because of the ifdef below this can't be const & 0062 0063 #ifdef Q_OS_ANDROID 0064 realUrl = 0065 QUrl(QJniObject(QNativeInterface::QAndroidApplication::context()).callObjectMethod("contentUrlToFd", "(Ljava/lang/String;)Ljava/lang/String;", QJniObject::fromString(url.toString(QUrl::FullyEncoded)).object<jstring>()).toString()); 0066 #endif 0067 0068 const QString path = realUrl.isLocalFile() ? realUrl.toLocalFile() : QStringLiteral("-"); 0069 0070 const Okular::Document::OpenResult res = m_document->openDocument(path, realUrl, db.mimeTypeForUrl(realUrl), password); 0071 0072 m_tocModel->clear(); 0073 m_tocModel->fill(m_document->documentSynopsis()); 0074 m_tocModel->setCurrentViewport(m_document->viewport()); 0075 0076 m_matchingPages.clear(); 0077 for (uint i = 0; i < m_document->pages(); ++i) { 0078 m_matchingPages << (int)i; 0079 } 0080 m_needsPassword = res == Okular::Document::OpenNeedsPassword; 0081 Q_EMIT matchingPagesChanged(); 0082 Q_EMIT urlChanged(); 0083 Q_EMIT pageCountChanged(); 0084 Q_EMIT openedChanged(); 0085 Q_EMIT needsPasswordChanged(); 0086 Q_EMIT supportsSearchingChanged(); 0087 Q_EMIT windowTitleForDocumentChanged(); 0088 Q_EMIT bookmarkedPagesChanged(); 0089 0090 KMessageWidget::MessageType messageType; 0091 QString message; 0092 std::tie(messageType, message) = SignatureGuiUtils::documentSignatureMessageWidgetText(m_document); 0093 if (!message.isEmpty()) { 0094 if (messageType == KMessageWidget::Information) { 0095 Q_EMIT notice(message, -1); 0096 } else if (messageType == KMessageWidget::Warning) { 0097 Q_EMIT warning(message, -1); 0098 } else { 0099 qWarning() << "Unexpected message type" << messageType; 0100 } 0101 } 0102 } 0103 0104 QString DocumentItem::windowTitleForDocument() const 0105 { 0106 // If 'DocumentTitle' should be used, check if the document has one. If 0107 // either case is false, use the file name. 0108 QString title = Okular::Settings::displayDocumentNameOrPath() == Okular::Settings::EnumDisplayDocumentNameOrPath::Path ? m_document->currentDocument().toDisplayString(QUrl::PreferLocalFile) : m_document->currentDocument().fileName(); 0109 0110 if (Okular::Settings::displayDocumentTitle()) { 0111 const QString docTitle = m_document->metaData(QStringLiteral("DocumentTitle")).toString(); 0112 0113 if (!docTitle.isEmpty() && !docTitle.trimmed().isEmpty()) { 0114 title = docTitle; 0115 } 0116 } 0117 0118 return title; 0119 } 0120 0121 QUrl DocumentItem::url() const 0122 { 0123 return m_document->currentDocument(); 0124 } 0125 0126 void DocumentItem::setCurrentPage(int page) 0127 { 0128 m_document->setViewportPage(page); 0129 m_tocModel->setCurrentViewport(m_document->viewport()); 0130 Q_EMIT currentPageChanged(); 0131 } 0132 0133 int DocumentItem::currentPage() const 0134 { 0135 return m_document->currentPage(); 0136 } 0137 0138 bool DocumentItem::isOpened() const 0139 { 0140 return m_document->isOpened(); 0141 } 0142 0143 int DocumentItem::pageCount() const 0144 { 0145 return m_document->pages(); 0146 } 0147 0148 QVariantList DocumentItem::matchingPages() const 0149 { 0150 return m_matchingPages; 0151 } 0152 0153 TOCModel *DocumentItem::tableOfContents() const 0154 { 0155 return m_tocModel; 0156 } 0157 0158 SignatureModel *DocumentItem::signaturesModel() const 0159 { 0160 return m_signaturesModel; 0161 } 0162 0163 QVariantList DocumentItem::bookmarkedPages() const 0164 { 0165 QList<int> list; 0166 QSet<int> pages; 0167 const KBookmark::List bMarks = m_document->bookmarkManager()->bookmarks(); 0168 for (const KBookmark &bookmark : bMarks) { 0169 Okular::DocumentViewport viewport(bookmark.url().fragment()); 0170 pages << viewport.pageNumber; 0171 } 0172 list = pages.values(); 0173 std::sort(list.begin(), list.end()); 0174 0175 QVariantList variantList; 0176 for (const int page : std::as_const(list)) { 0177 variantList << page; 0178 } 0179 return variantList; 0180 } 0181 0182 QStringList DocumentItem::bookmarks() const 0183 { 0184 QStringList list; 0185 const KBookmark::List bMarks = m_document->bookmarkManager()->bookmarks(); 0186 for (const KBookmark &bookmark : bMarks) { 0187 list << bookmark.url().toString(); 0188 } 0189 return list; 0190 } 0191 0192 bool DocumentItem::supportsSearching() const 0193 { 0194 return m_document->supportsSearching(); 0195 } 0196 0197 bool DocumentItem::isSearchInProgress() const 0198 { 0199 return m_searchInProgress; 0200 } 0201 0202 void DocumentItem::searchText(const QString &text) 0203 { 0204 if (text.isEmpty()) { 0205 resetSearch(); 0206 return; 0207 } 0208 m_document->cancelSearch(); 0209 m_document->resetSearch(PAGEVIEW_SEARCH_ID); 0210 m_document->searchText(PAGEVIEW_SEARCH_ID, text, true, Qt::CaseInsensitive, Okular::Document::AllDocument, true, QColor(100, 100, 200, 40)); 0211 0212 if (!m_searchInProgress) { 0213 m_searchInProgress = true; 0214 Q_EMIT searchInProgressChanged(); 0215 } 0216 } 0217 0218 void DocumentItem::resetSearch() 0219 { 0220 m_document->resetSearch(PAGEVIEW_SEARCH_ID); 0221 m_matchingPages.clear(); 0222 for (uint i = 0; i < m_document->pages(); ++i) { 0223 m_matchingPages << (int)i; 0224 } 0225 if (m_searchInProgress) { 0226 m_searchInProgress = false; 0227 Q_EMIT searchInProgressChanged(); 0228 } 0229 0230 Q_EMIT matchingPagesChanged(); 0231 } 0232 0233 void DocumentItem::setPassword(const QString &password) 0234 { 0235 openUrl(m_document->currentDocument(), password); 0236 } 0237 0238 Okular::Document *DocumentItem::document() 0239 { 0240 return m_document; 0241 } 0242 0243 Observer *DocumentItem::thumbnailObserver() 0244 { 0245 if (!m_thumbnailObserver) { 0246 m_thumbnailObserver = new Observer(this); 0247 } 0248 0249 return m_thumbnailObserver; 0250 } 0251 0252 Observer *DocumentItem::pageviewObserver() 0253 { 0254 if (!m_pageviewObserver) { 0255 m_pageviewObserver = new Observer(this); 0256 } 0257 0258 return m_pageviewObserver; 0259 } 0260 0261 void DocumentItem::searchFinished(int id, Okular::Document::SearchStatus endStatus) 0262 { 0263 Q_UNUSED(endStatus) 0264 0265 if (id != PAGEVIEW_SEARCH_ID) { 0266 return; 0267 } 0268 0269 m_matchingPages.clear(); 0270 for (uint i = 0; i < m_document->pages(); ++i) { 0271 if (m_document->page(i)->hasHighlights(id)) { 0272 m_matchingPages << (int)i; 0273 } 0274 } 0275 0276 if (m_searchInProgress) { 0277 m_searchInProgress = false; 0278 Q_EMIT searchInProgressChanged(); 0279 } 0280 Q_EMIT matchingPagesChanged(); 0281 } 0282 0283 // Observer 0284 0285 Observer::Observer(DocumentItem *parent) 0286 : QObject(parent) 0287 , m_document(parent) 0288 { 0289 parent->document()->addObserver(this); 0290 } 0291 0292 Observer::~Observer() 0293 { 0294 } 0295 0296 void Observer::notifyPageChanged(int page, int flags) 0297 { 0298 Q_EMIT pageChanged(page, flags); 0299 }