File indexing completed on 2025-01-05 05:23:24

0001 /*
0002     This file is part of the Okteta Kasten module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2008, 2010, 2012 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "documentinfotool.hpp"
0010 
0011 // lib
0012 #include "bytearraymodeliodevice.hpp"
0013 // Okteta Kasten core
0014 #include <Kasten/Okteta/ByteArrayDocument>
0015 // Kasten core
0016 #include <Kasten/DocumentSyncManager>
0017 #include <Kasten/AbstractModelSynchronizer>
0018 
0019 // Okteta core
0020 #include <Okteta/AbstractByteArrayModel>
0021 #include <Okteta/ArrayChangeMetricsList>
0022 // KF
0023 #include <KLocalizedString>
0024 // Qt
0025 #include <QApplication>
0026 #include <QTimer>
0027 #include <QUrl>
0028 #include <QMimeDatabase>
0029 
0030 namespace Kasten {
0031 
0032 static constexpr int mimeTypeUpdateTimeInterval = 500; // msec
0033 
0034 DocumentInfoTool::DocumentInfoTool(DocumentSyncManager* syncManager)
0035     : mDocumentSyncManager(syncManager)
0036     , mMimeTypeUpdateTimer(new QTimer(this))
0037 {
0038     setObjectName(QStringLiteral("DocumentInfo"));
0039 
0040     mMimeTypeUpdateTimer->setInterval(mimeTypeUpdateTimeInterval);
0041     mMimeTypeUpdateTimer->setSingleShot(true);
0042     connect(mMimeTypeUpdateTimer, &QTimer::timeout, this, &DocumentInfoTool::updateMimeType);
0043 }
0044 
0045 DocumentInfoTool::~DocumentInfoTool() = default;
0046 
0047 // TODO: file or document or ...?
0048 QString DocumentInfoTool::title() const { return i18nc("@title:window", "File Info"); }
0049 QString DocumentInfoTool::documentTitle() const
0050 {
0051     return mDocument ? mDocument->title() : QString();
0052 }
0053 
0054 QString DocumentInfoTool::location() const
0055 {
0056     QString result;
0057     if (mDocument) {
0058         const QUrl url = mDocumentSyncManager->urlOf(mDocument);
0059         result = url.toDisplayString(QUrl::PrettyDecoded | QUrl::PreferLocalFile);
0060     }
0061     return result;
0062 }
0063 
0064 int DocumentInfoTool::documentSize() const
0065 {
0066     int documentSize = -1;
0067     if (mByteArrayModel) {
0068         documentSize = mByteArrayModel->size();
0069     }
0070 
0071     return documentSize;
0072 }
0073 
0074 void DocumentInfoTool::setTargetModel(AbstractModel* model)
0075 {
0076     if (mSynchronizer) {
0077         mSynchronizer->disconnect(this);
0078     }
0079     if (mDocument) {
0080         mDocument->disconnect(this);
0081     }
0082     if (mByteArrayModel) {
0083         mByteArrayModel->disconnect(this);
0084     }
0085 
0086     mDocument = model ? model->findBaseModel<ByteArrayDocument*>() : nullptr;
0087     mByteArrayModel = mDocument ? mDocument->content() : nullptr;
0088 
0089     const bool hasDocument = (mDocument != nullptr);
0090     AbstractModelSynchronizer* synchronizer = nullptr;
0091     QString documentTitle;
0092     int documentSize = -1;
0093     if (hasDocument) {
0094         documentTitle = mDocument->title();
0095         documentSize = mByteArrayModel->size();
0096         synchronizer = mDocument->synchronizer();
0097 
0098         connect(mDocument, &ByteArrayDocument::titleChanged,
0099                 this, &DocumentInfoTool::documentTitleChanged);
0100         connect(mDocument, &ByteArrayDocument::synchronizerChanged,
0101                 this, &DocumentInfoTool::onSynchronizerChanged);
0102         connect(mByteArrayModel, &Okteta::AbstractByteArrayModel::contentsChanged,
0103                 this, &DocumentInfoTool::onContentsChanged);
0104     }
0105 
0106     onSynchronizerChanged(synchronizer);
0107 
0108     Q_EMIT documentTitleChanged(documentTitle);
0109     Q_EMIT documentSizeChanged(documentSize);
0110 }
0111 
0112 // TODO: should this be done in a worker thread, to not block the UI?
0113 void DocumentInfoTool::updateMimeType()
0114 {
0115     QMimeType currentMimeType;
0116 
0117     if (mDocument) {
0118         // TODO: also get file mode, if available, for findByNameAndContent()
0119         const QString filename = mDocumentSyncManager->urlOf(mDocument).fileName();
0120 
0121         Okteta::ByteArrayModelIoDevice byteArrayModelIoDevice(mByteArrayModel);
0122         QMimeDatabase db;
0123         currentMimeType = filename.isEmpty() ?
0124                           db.mimeTypeForData(&byteArrayModelIoDevice) :
0125                           db.mimeTypeForFileNameAndData(filename, &byteArrayModelIoDevice);
0126     }
0127 
0128     if (mMimeType != currentMimeType) {
0129         mMimeType = currentMimeType;
0130         Q_EMIT documentMimeTypeChanged(currentMimeType);
0131     }
0132 }
0133 
0134 void DocumentInfoTool::onContentsChanged()
0135 {
0136     if (!mMimeTypeUpdateTimer->isActive()) {
0137         mMimeTypeUpdateTimer->start();
0138     }
0139 
0140     Q_EMIT documentSizeChanged(mByteArrayModel->size());
0141 }
0142 
0143 void DocumentInfoTool::onSynchronizerChanged(AbstractModelSynchronizer* synchronizer)
0144 {
0145     // do an instant update, no need to delay
0146     if (mMimeTypeUpdateTimer->isActive()) {
0147         mMimeTypeUpdateTimer->stop();
0148     }
0149     updateMimeType();
0150 
0151     if (mSynchronizer) {
0152         mSynchronizer->disconnect(this);
0153     }
0154     mSynchronizer = synchronizer;
0155 
0156     if (mSynchronizer) {
0157         connect(mSynchronizer, &AbstractModelSynchronizer::urlChanged,
0158                 this, &DocumentInfoTool::onUrlChanged);
0159     }
0160 
0161     Q_EMIT locationChanged(location());
0162 }
0163 
0164 void DocumentInfoTool::onUrlChanged(const QUrl& url)
0165 {
0166     Q_UNUSED(url);
0167 
0168     Q_EMIT locationChanged(location());
0169 }
0170 
0171 }
0172 
0173 #include "moc_documentinfotool.cpp"