File indexing completed on 2024-04-28 15:52:00
0001 /* 0002 SPDX-FileCopyrightText: 2004-2006 Albert Astals Cid <aacid@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "toc.h" 0008 0009 // qt/kde includes 0010 #include <QContextMenuEvent> 0011 #include <QHeaderView> 0012 #include <QLayout> 0013 #include <QTreeView> 0014 #include <qdom.h> 0015 0016 #include <KLineEdit> 0017 #include <KLocalizedString> 0018 #include <KTitleWidget> 0019 0020 #include <kwidgetsaddons_version.h> 0021 0022 // local includes 0023 #include "core/action.h" 0024 #include "gui/tocmodel.h" 0025 #include "ktreeviewsearchline.h" 0026 #include "pageitemdelegate.h" 0027 #include "settings.h" 0028 0029 TOC::TOC(QWidget *parent, Okular::Document *document) 0030 : QWidget(parent) 0031 , m_document(document) 0032 { 0033 QVBoxLayout *mainlay = new QVBoxLayout(this); 0034 mainlay->setSpacing(6); 0035 0036 KTitleWidget *titleWidget = new KTitleWidget(this); 0037 titleWidget->setLevel(4); 0038 titleWidget->setText(i18n("Contents")); 0039 mainlay->addWidget(titleWidget); 0040 mainlay->setAlignment(titleWidget, Qt::AlignHCenter); 0041 m_searchLine = new KTreeViewSearchLine(this); 0042 mainlay->addWidget(m_searchLine); 0043 m_searchLine->setPlaceholderText(i18n("Search...")); 0044 m_searchLine->setCaseSensitivity(Okular::Settings::self()->contentsSearchCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive); 0045 m_searchLine->setRegularExpression(Okular::Settings::self()->contentsSearchRegularExpression()); 0046 connect(m_searchLine, &KTreeViewSearchLine::searchOptionsChanged, this, &TOC::saveSearchOptions); 0047 0048 m_treeView = new QTreeView(this); 0049 mainlay->addWidget(m_treeView); 0050 m_model = new TOCModel(document, m_treeView); 0051 m_treeView->setModel(m_model); 0052 m_treeView->setSortingEnabled(false); 0053 m_treeView->setRootIsDecorated(true); 0054 m_treeView->setAlternatingRowColors(true); 0055 m_treeView->setItemDelegate(new PageItemDelegate(m_treeView)); 0056 m_treeView->header()->hide(); 0057 m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows); 0058 connect(m_treeView, &QTreeView::clicked, this, &TOC::slotExecuted); 0059 connect(m_treeView, &QTreeView::activated, this, &TOC::slotExecuted); 0060 m_searchLine->setTreeView(m_treeView); 0061 } 0062 0063 TOC::~TOC() 0064 { 0065 m_document->removeObserver(this); 0066 } 0067 0068 void TOC::notifySetup(const QVector<Okular::Page *> & /*pages*/, int setupFlags) 0069 { 0070 if (!(setupFlags & Okular::DocumentObserver::DocumentChanged)) { 0071 return; 0072 } 0073 0074 // clear contents 0075 m_model->clear(); 0076 0077 // request synopsis description (is a dom tree) 0078 const Okular::DocumentSynopsis *syn = m_document->documentSynopsis(); 0079 if (!syn) { 0080 if (m_document->isOpened()) { 0081 // Make sure we clear the reload old model data 0082 m_model->setOldModelData(nullptr, QVector<QModelIndex>()); 0083 } 0084 Q_EMIT hasTOC(false); 0085 return; 0086 } 0087 0088 m_model->fill(syn); 0089 Q_EMIT hasTOC(!m_model->isEmpty()); 0090 } 0091 0092 void TOC::notifyCurrentPageChanged(int, int) 0093 { 0094 m_model->setCurrentViewport(m_document->viewport()); 0095 } 0096 0097 void TOC::prepareForReload() 0098 { 0099 if (m_model->isEmpty()) { 0100 return; 0101 } 0102 0103 const QVector<QModelIndex> list = expandedNodes(); 0104 TOCModel *m = m_model; 0105 m_model = new TOCModel(m_document, m_treeView); 0106 m_model->setOldModelData(m, list); 0107 m->setParent(nullptr); 0108 } 0109 0110 void TOC::rollbackReload() 0111 { 0112 if (!m_model->hasOldModelData()) { 0113 return; 0114 } 0115 0116 TOCModel *m = m_model; 0117 m_model = m->clearOldModelData(); 0118 m_model->setParent(m_treeView); 0119 delete m; 0120 } 0121 0122 void TOC::finishReload() 0123 { 0124 m_treeView->setModel(m_model); 0125 m_model->setParent(m_treeView); 0126 } 0127 0128 QVector<QModelIndex> TOC::expandedNodes(const QModelIndex &parent) const 0129 { 0130 QVector<QModelIndex> list; 0131 for (int i = 0; i < m_model->rowCount(parent); i++) { 0132 const QModelIndex index = m_model->index(i, 0, parent); 0133 if (m_treeView->isExpanded(index)) { 0134 list << index; 0135 } 0136 if (m_model->hasChildren(index)) { 0137 list << expandedNodes(index); 0138 } 0139 } 0140 return list; 0141 } 0142 0143 void TOC::reparseConfig() 0144 { 0145 m_searchLine->setCaseSensitivity(Okular::Settings::contentsSearchCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive); 0146 m_searchLine->setRegularExpression(Okular::Settings::contentsSearchRegularExpression()); 0147 m_treeView->update(); 0148 } 0149 0150 void TOC::slotExecuted(const QModelIndex &index) 0151 { 0152 if (!index.isValid()) { 0153 return; 0154 } 0155 0156 QString url = m_model->urlForIndex(index); 0157 if (!url.isEmpty()) { 0158 Okular::BrowseAction action(QUrl::fromLocalFile(url)); 0159 m_document->processAction(&action); 0160 return; 0161 } 0162 0163 QString externalFileName = m_model->externalFileNameForIndex(index); 0164 Okular::DocumentViewport viewport = m_model->viewportForIndex(index); 0165 if (!externalFileName.isEmpty()) { 0166 Okular::GotoAction action(externalFileName, viewport); 0167 m_document->processAction(&action); 0168 } else if (viewport.isValid()) { 0169 m_document->setViewport(viewport); 0170 } 0171 } 0172 0173 void TOC::saveSearchOptions() 0174 { 0175 Okular::Settings::setContentsSearchRegularExpression(m_searchLine->regularExpression()); 0176 Okular::Settings::setContentsSearchCaseSensitive(m_searchLine->caseSensitivity() == Qt::CaseSensitive ? true : false); 0177 Okular::Settings::self()->save(); 0178 } 0179 0180 void TOC::contextMenuEvent(QContextMenuEvent *e) 0181 { 0182 QModelIndex index = m_treeView->currentIndex(); 0183 if (!index.isValid()) { 0184 return; 0185 } 0186 0187 Okular::DocumentViewport viewport = m_model->viewportForIndex(index); 0188 0189 Q_EMIT rightClick(viewport, e->globalPos(), m_model->data(index).toString()); 0190 } 0191 0192 void TOC::expandRecursively() 0193 { 0194 QList<QModelIndex> worklist = {m_treeView->currentIndex()}; 0195 if (!worklist[0].isValid()) { 0196 return; 0197 } 0198 while (!worklist.isEmpty()) { 0199 QModelIndex index = worklist.takeLast(); 0200 m_treeView->expand(index); 0201 for (int i = 0; i < m_model->rowCount(index); i++) { 0202 worklist += m_model->index(i, 0, index); 0203 } 0204 } 0205 } 0206 0207 void TOC::collapseRecursively() 0208 { 0209 QList<QModelIndex> worklist = {m_treeView->currentIndex()}; 0210 if (!worklist[0].isValid()) { 0211 return; 0212 } 0213 while (!worklist.isEmpty()) { 0214 QModelIndex index = worklist.takeLast(); 0215 m_treeView->collapse(index); 0216 for (int i = 0; i < m_model->rowCount(index); i++) { 0217 worklist += m_model->index(i, 0, index); 0218 } 0219 } 0220 } 0221 0222 void TOC::expandAll() 0223 { 0224 m_treeView->expandAll(); 0225 } 0226 0227 void TOC::collapseAll() 0228 { 0229 m_treeView->collapseAll(); 0230 }