File indexing completed on 2024-05-12 16:28:24
0001 /* 0002 * This file is part of the KDE project 0003 * 0004 * Copyright (C) 2013 Arjen Hiemstra <ahiemstra@heimr.nl> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 * 0021 */ 0022 0023 #include "TextContentsModelImpl.h" 0024 0025 #include <KWDocument.h> 0026 #include <KWPage.h> 0027 #include <frames/KWTextFrameSet.h> 0028 #include <KoCanvasBase.h> 0029 #include <KoTextDocumentLayout.h> 0030 #include <KoTextLayoutRootArea.h> 0031 #include <styles/KoParagraphStyle.h> 0032 0033 using namespace Calligra::Components; 0034 0035 struct ContentsEntry { 0036 ContentsEntry() : level{0}, pageNumber{0}, page{nullptr} 0037 {} 0038 QString title; 0039 int level; 0040 int pageNumber; 0041 KWPage* page; 0042 }; 0043 0044 class TextContentsModelImpl::Private 0045 { 0046 public: 0047 Private() : useToC{false}, document{nullptr}, textDocument{nullptr}, layout{nullptr}, canvas{nullptr} 0048 { } 0049 0050 bool useToC; 0051 KWDocument* document; 0052 QTextDocument* textDocument; 0053 KoTextDocumentLayout* layout; 0054 KoCanvasBase* canvas; 0055 0056 QHash<int, QImage> thumbnails; 0057 QSize thumbnailSize; 0058 0059 QList<ContentsEntry> entries; 0060 }; 0061 0062 TextContentsModelImpl::TextContentsModelImpl(KoDocument* document, KoCanvasBase* canvas) 0063 : d{new Private} 0064 { 0065 d->document = qobject_cast<KWDocument*>(document); 0066 Q_ASSERT(d->document); 0067 if(d->document->mainFrameSet() && d->document->mainFrameSet()->document()) { 0068 d->textDocument = d->document->mainFrameSet()->document(); 0069 d->layout = qobject_cast<KoTextDocumentLayout*>(d->textDocument->documentLayout()); 0070 connect(d->layout, &KoTextDocumentLayout::finishedLayout, this, &TextContentsModelImpl::documentLayoutFinished); 0071 d->layout->scheduleLayout(); 0072 } 0073 d->canvas = canvas; 0074 } 0075 0076 TextContentsModelImpl::~TextContentsModelImpl() 0077 { 0078 delete d; 0079 } 0080 0081 int TextContentsModelImpl::rowCount() const 0082 { 0083 if(d->useToC && d->entries.count() > 0) { 0084 return d->entries.count(); 0085 } 0086 0087 return d->document->pageCount(); 0088 } 0089 0090 QVariant TextContentsModelImpl::data(int index, Calligra::Components::ContentsModel::Role role) const 0091 { 0092 if(d->useToC && d->entries.count() > 0) { 0093 auto entry = d->entries.at(index); 0094 switch(role) { 0095 case ContentsModel::TitleRole: 0096 return entry.title; 0097 case ContentsModel::LevelRole: 0098 return entry.level; 0099 case ContentsModel::ThumbnailRole: { 0100 if(d->thumbnails.contains(entry.pageNumber)) { 0101 return d->thumbnails.value(entry.pageNumber); 0102 } 0103 0104 if(d->thumbnailSize.isNull()) { 0105 return QImage{}; 0106 } 0107 0108 QImage thumb = entry.page->thumbnail(d->thumbnailSize, d->canvas->shapeManager()); 0109 d->thumbnails.insert(entry.pageNumber, thumb); 0110 return thumb; 0111 } 0112 case ContentsModel::ContentIndexRole: { 0113 return entry.pageNumber - 1; 0114 } 0115 default: 0116 return QVariant(); 0117 } 0118 } 0119 0120 //Fallback behaviour when we don't have a ToC 0121 KWPage page = d->document->pageManager()->page(index + 1); 0122 if(!page.isValid()) 0123 return QVariant(); 0124 0125 switch(role) { 0126 case ContentsModel::TitleRole: 0127 return i18n("Page %1", page.pageNumber()); 0128 case ContentsModel::LevelRole: 0129 return 0; 0130 case ContentsModel::ThumbnailRole: { 0131 if(d->thumbnails.contains(index)) { 0132 return d->thumbnails.value(index); 0133 } 0134 0135 if(d->thumbnailSize.isNull()) { 0136 return QImage{}; 0137 } 0138 0139 QImage thumb = page.thumbnail(d->thumbnailSize, d->canvas->shapeManager()); 0140 d->thumbnails.insert(index, thumb); 0141 return thumb; 0142 } 0143 case ContentsModel::ContentIndexRole: { 0144 return index; 0145 } 0146 default: 0147 return QVariant(); 0148 } 0149 } 0150 0151 void TextContentsModelImpl::setThumbnailSize(const QSize& size) 0152 { 0153 d->thumbnailSize = size; 0154 d->thumbnails.clear(); 0155 } 0156 0157 QImage TextContentsModelImpl::thumbnail(int index, int width) const 0158 { 0159 KWPage page = d->document->pageManager()->page( index + 1 ); 0160 return page.thumbnail(QSize{ width, int((page.height() / page.width()) * width)}, d->canvas->shapeManager()); 0161 } 0162 0163 void TextContentsModelImpl::setUseToC(bool newValue) 0164 { 0165 d->useToC = newValue; 0166 } 0167 0168 void TextContentsModelImpl::documentLayoutFinished() 0169 { 0170 QTextBlock block = d->textDocument->firstBlock(); 0171 d->entries.clear(); 0172 0173 while (block.isValid()) 0174 { 0175 QTextBlockFormat format = block.blockFormat(); 0176 if (format.hasProperty(KoParagraphStyle::OutlineLevel)) 0177 { 0178 ContentsEntry entry; 0179 entry.title = block.text(); 0180 entry.level = format.intProperty(KoParagraphStyle::OutlineLevel); 0181 0182 auto rootArea = d->layout->rootAreaForPosition(block.position()); 0183 if (rootArea) { 0184 if (rootArea->page()) { 0185 entry.pageNumber = rootArea->page()->visiblePageNumber(); 0186 entry.page = static_cast<KWPage*>(rootArea->page()); 0187 } 0188 } 0189 0190 d->entries.append(entry); 0191 } 0192 block = block.next(); 0193 } 0194 0195 emit listContentsCompleted(); 0196 }