Warning, file /office/calligra/gemini/DocumentListModel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 * SPDX-FileCopyrightText: 2014 Dan Leinir Turthra Jensen <admin@leinir.dk> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "DocumentListModel.h" 0008 0009 #include <QDebug> 0010 #include <QDirIterator> 0011 #include <QRunnable> 0012 #include <QThreadPool> 0013 #include <QTimer> 0014 #include <QLocale> 0015 0016 #include <KSharedConfig> 0017 #include <KConfigGroup> 0018 0019 /*#include <QSparqlConnection> 0020 #include <QSparqlResult> 0021 #include <QSparqlError>*/ 0022 #include <kfileitem.h> 0023 0024 0025 QDebug operator<<(QDebug dbg, const DocumentListModel::DocumentInfo& d) { 0026 dbg.nospace() << d.filePath << "," << d.fileName << "," << d.docType << "," << d.fileSize << "," << d.authorName << "," << d.accessedTime << "," << d.modifiedTime << "," << d.uuid; 0027 return dbg.space(); 0028 }; 0029 0030 const QString SearchThread::textDocumentType = QString("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#PaginatedTextDocument"); 0031 const QString SearchThread::presentationType = QString("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#PresentationDocument"); 0032 const QString SearchThread::spreadsheetType = QString("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#SpreadsheetDocument"); 0033 0034 SearchThread::SearchThread(const QHash<QString, DocumentListModel::DocumentType> &docTypes, QObject *parent) 0035 : QObject(parent), m_abort(false), m_docTypes(docTypes) 0036 { 0037 } 0038 0039 SearchThread::~SearchThread() 0040 { 0041 } 0042 0043 void SearchThread::run() 0044 { 0045 // Keeping this code around, in case Tracker later blows up horribly and we 0046 // have to rapidly reenable the filesystem only support 0047 // Get documents from the device storage's document directory... 0048 QString documentsDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); 0049 QStringList nameFilters; 0050 for (QHash<QString, DocumentListModel::DocumentType>::const_iterator it = m_docTypes.constBegin(); it != m_docTypes.constEnd(); ++it) 0051 nameFilters.append("*." + it.key()); 0052 0053 QDirIterator it(documentsDir, nameFilters, QDir::Files, QDirIterator::Subdirectories); 0054 while (it.hasNext() && !m_abort) { 0055 it.next(); 0056 DocumentListModel::DocumentInfo info; 0057 info.fileName = it.fileName(); 0058 info.authorName = "-"; 0059 info.filePath = it.filePath(); 0060 info.modifiedTime = it.fileInfo().lastModified(); 0061 info.accessedTime = it.fileInfo().lastRead(); 0062 info.fileSize = QString("%1").arg(it.fileInfo().size()); 0063 info.docType = m_docTypes.value(info.filePath.split('.').last()); 0064 info.uuid = "not known..."; 0065 emit documentFound(info); 0066 } 0067 0068 emit finished(); 0069 } 0070 0071 DocumentListModel::DocumentListModel(QObject *parent) 0072 : QAbstractListModel(parent) 0073 , m_searchThread(0) 0074 , m_groupBy(GroupByName) 0075 , m_filter(UnknownType) 0076 { 0077 qRegisterMetaType<DocumentInfo>(); 0078 0079 m_docTypes["odt"] = TextDocumentType; 0080 m_docTypes["doc"] = TextDocumentType; 0081 m_docTypes["docx"] = TextDocumentType; 0082 m_docTypes["odp"] = PresentationType; 0083 m_docTypes["ppt"] = PresentationType; 0084 m_docTypes["pptx"] = PresentationType; 0085 m_docTypes["ods"] = SpreadsheetType; 0086 m_docTypes["xls"] = SpreadsheetType; 0087 m_docTypes["xlsx"] = SpreadsheetType; 0088 } 0089 0090 DocumentListModel::~DocumentListModel() 0091 { 0092 stopSearch(); 0093 } 0094 0095 QHash<int, QByteArray> DocumentListModel::roleNames() const 0096 { 0097 QHash<int, QByteArray> roleNames = QAbstractListModel::roleNames(); 0098 roleNames[FileNameRole] = "fileName"; 0099 roleNames[FilePathRole] = "filePath"; 0100 roleNames[DocTypeRole] = "docType"; 0101 roleNames[SectionCategoryRole] = "sectionCategory"; 0102 roleNames[FileSizeRole] = "fileSize"; 0103 roleNames[AuthorNameRole] = "authorName"; 0104 roleNames[AccessedTimeRole] = "accessedTime"; 0105 roleNames[ModifiedTimeRole] = "modifiedTime"; 0106 roleNames[UUIDRole] = "uuid"; 0107 return roleNames; 0108 } 0109 0110 void DocumentListModel::startSearch() 0111 { 0112 if (m_searchThread) { 0113 qDebug() << "Already searching or finished search"; 0114 return; 0115 } 0116 m_searchThread = new SearchThread(m_docTypes); 0117 connect(m_searchThread, &SearchThread::documentFound, this, &DocumentListModel::addDocument); 0118 connect(m_searchThread, &SearchThread::finished, this, &DocumentListModel::searchFinished); 0119 m_searchThread->setAutoDelete(false); 0120 QThreadPool::globalInstance()->start(m_searchThread); 0121 } 0122 0123 void DocumentListModel::stopSearch() 0124 { 0125 if (m_searchThread) 0126 m_searchThread->abort(); 0127 } 0128 0129 void DocumentListModel::searchFinished() 0130 { 0131 Q_ASSERT(m_searchThread); 0132 delete m_searchThread; 0133 m_searchThread = 0; 0134 } 0135 0136 void DocumentListModel::addDocument(const DocumentInfo &info) 0137 { 0138 if(m_allDocumentInfos.contains(info)) 0139 { 0140 qDebug() << "Attempted to add duplicate entry" << info; 0141 return; 0142 } 0143 0144 m_allDocumentInfos.append(info); 0145 0146 if(m_filter == UnknownType || info.docType == m_filter) { 0147 beginInsertRows(QModelIndex(), m_currentDocumentInfos.count(), m_currentDocumentInfos.count()); 0148 m_currentDocumentInfos.append(info); 0149 endInsertRows(); 0150 } 0151 } 0152 0153 int DocumentListModel::rowCount(const QModelIndex &parent) const 0154 { 0155 if(parent.isValid()) 0156 return 0; 0157 return m_currentDocumentInfos.count(); 0158 } 0159 0160 int DocumentListModel::columnCount(const QModelIndex &parent) const 0161 { 0162 if (parent.isValid()) 0163 return 0; 0164 return 1; 0165 } 0166 0167 QVariant DocumentListModel::data(const QModelIndex &index, int role) const 0168 { 0169 if (!index.isValid()) 0170 return QVariant(); 0171 const int row = index.row(); 0172 const DocumentInfo &info = m_currentDocumentInfos[row]; 0173 0174 switch (role) { 0175 case FileNameRole: // intentional fall through 0176 case Qt::DisplayRole: return info.fileName; 0177 case FilePathRole: return info.filePath; 0178 case DocTypeRole: return info.docType; 0179 case FileSizeRole: return info.fileSize; 0180 case AuthorNameRole: return info.authorName; 0181 case AccessedTimeRole: return prettyTime(info.accessedTime); 0182 case ModifiedTimeRole: return prettyTime(info.modifiedTime); 0183 case UUIDRole: return info.uuid; 0184 case SectionCategoryRole: 0185 return m_groupBy == GroupByName ? info.fileName[0].toUpper() : info.docType; 0186 default: return QVariant(); 0187 } 0188 } 0189 0190 QString DocumentListModel::prettyTime(QDateTime theTime) 0191 { 0192 // QT5TODO: used to be KLocale::FancyShortDate, but no such thing with QLocale (also static anyway) 0193 return QLocale().toString(theTime, QLocale::ShortFormat); 0194 } 0195 0196 QVariant DocumentListModel::headerData(int section, Qt::Orientation orientation, int role) const 0197 { 0198 if (orientation == Qt::Vertical || role != Qt::DisplayRole) 0199 return QVariant(); 0200 switch (section) { 0201 case 0: return tr("Filename"); 0202 case 1: return tr("Path"); 0203 case 2: return tr("Type"); 0204 case 3: return tr("Size"); 0205 case 4: return tr("Author"); 0206 case 5: return tr("Last Accessed"); 0207 case 6: return tr("Last Modified"); 0208 default: return QVariant(); 0209 } 0210 } 0211 0212 void DocumentListModel::groupBy(GroupBy role) 0213 { 0214 if (m_groupBy == role) 0215 return; 0216 m_groupBy = role; 0217 relayout(); 0218 } 0219 0220 void DocumentListModel::relayout() 0221 { 0222 beginResetModel(); 0223 emit layoutAboutToBeChanged(); 0224 0225 QList<DocumentInfo> newList; 0226 foreach(const DocumentInfo &docInfo, m_allDocumentInfos) { 0227 if(m_filter == UnknownType || docInfo.docType == m_filter) { 0228 qDebug() << docInfo.filePath; 0229 newList.append(docInfo); 0230 } 0231 } 0232 0233 m_currentDocumentInfos = newList; 0234 emit layoutChanged(); 0235 endResetModel(); 0236 } 0237 0238 void DocumentListModel::classBegin() 0239 { 0240 } 0241 0242 DocumentListModel::DocumentType DocumentListModel::filter() 0243 { 0244 return m_filter; 0245 } 0246 0247 QString DocumentListModel::documentsFolder() const 0248 { 0249 return QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); 0250 } 0251 0252 void DocumentListModel::setFilter(DocumentListModel::DocumentType newFilter) 0253 { 0254 m_filter = newFilter; 0255 relayout(); 0256 emit filterChanged(); 0257 } 0258 0259 void DocumentListModel::componentComplete() 0260 { 0261 beginResetModel(); 0262 endResetModel(); 0263 startSearch(); 0264 } 0265