1 /*
2 This file is part of the Okteta Kasten module, made within the KDE community.
3
4 SPDX-FileCopyrightText: 2008, 2010, 2012 Friedrich W. H. Kossebau <kossebau@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8
9 #include "documentinfotool.hpp"
10
11 // lib
12 #include "bytearraymodeliodevice.hpp"
13 // Okteta Kasten core
14 #include <Kasten/Okteta/ByteArrayDocument>
15 // Kasten core
16 #include <Kasten/DocumentSyncManager>
17 #include <Kasten/AbstractModelSynchronizer>
18
19 // Okteta core
20 #include <Okteta/AbstractByteArrayModel>
21 #include <Okteta/ArrayChangeMetricsList>
22 // KF
23 #include <KLocalizedString>
24 // Qt
25 #include <QApplication>
26 #include <QTimer>
27 #include <QUrl>
28 #include <QMimeDatabase>
29
30 namespace Kasten {
31
32 static constexpr int mimeTypeUpdateTimeInterval = 500; // msec
33
DocumentInfoTool(DocumentSyncManager * syncManager)34 DocumentInfoTool::DocumentInfoTool(DocumentSyncManager* syncManager)
35 : mDocumentSyncManager(syncManager)
36 , mMimeTypeUpdateTimer(new QTimer(this))
37 {
38 setObjectName(QStringLiteral("DocumentInfo"));
39
40 mMimeTypeUpdateTimer->setInterval(mimeTypeUpdateTimeInterval);
41 mMimeTypeUpdateTimer->setSingleShot(true);
42 connect(mMimeTypeUpdateTimer, &QTimer::timeout, this, &DocumentInfoTool::updateMimeType);
43 }
44
45 DocumentInfoTool::~DocumentInfoTool() = default;
46
47 // TODO: file or document or ...?
title() const48 QString DocumentInfoTool::title() const { return i18nc("@title:window", "File Info"); }
documentTitle() const49 QString DocumentInfoTool::documentTitle() const
50 {
51 return mDocument ? mDocument->title() : QString();
52 }
53
location() const54 QString DocumentInfoTool::location() const
55 {
56 QString result;
57 if (mDocument) {
58 const QUrl url = mDocumentSyncManager->urlOf(mDocument);
59 result = url.toDisplayString(QUrl::PrettyDecoded | QUrl::PreferLocalFile);
60 }
61 return result;
62 }
63
documentSize() const64 int DocumentInfoTool::documentSize() const
65 {
66 int documentSize = -1;
67 if (mByteArrayModel) {
68 documentSize = mByteArrayModel->size();
69 }
70
71 return documentSize;
72 }
73
setTargetModel(AbstractModel * model)74 void DocumentInfoTool::setTargetModel(AbstractModel* model)
75 {
76 if (mSynchronizer) {
77 mSynchronizer->disconnect(this);
78 }
79 if (mDocument) {
80 mDocument->disconnect(this);
81 }
82 if (mByteArrayModel) {
83 mByteArrayModel->disconnect(this);
84 }
85
86 mDocument = model ? model->findBaseModel<ByteArrayDocument*>() : nullptr;
87 mByteArrayModel = mDocument ? mDocument->content() : nullptr;
88
89 const bool hasDocument = (mDocument != nullptr);
90 AbstractModelSynchronizer* synchronizer = nullptr;
91 QString documentTitle;
92 int documentSize = -1;
93 if (hasDocument) {
94 documentTitle = mDocument->title();
95 documentSize = mByteArrayModel->size();
96 synchronizer = mDocument->synchronizer();
97
98 connect(mDocument, &ByteArrayDocument::titleChanged,
99 this, &DocumentInfoTool::documentTitleChanged);
100 connect(mDocument, &ByteArrayDocument::synchronizerChanged,
101 this, &DocumentInfoTool::onSynchronizerChanged);
102 connect(mByteArrayModel, &Okteta::AbstractByteArrayModel::contentsChanged,
103 this, &DocumentInfoTool::onContentsChanged);
104 }
105
106 onSynchronizerChanged(synchronizer);
107
108 emit documentTitleChanged(documentTitle);
109 emit documentSizeChanged(documentSize);
110 }
111
112 // TODO: should this be done in a worker thread, to not block the UI?
updateMimeType()113 void DocumentInfoTool::updateMimeType()
114 {
115 QMimeType currentMimeType;
116
117 if (mDocument) {
118 // TODO: also get file mode, if available, for findByNameAndContent()
119 const QString filename = mDocumentSyncManager->urlOf(mDocument).fileName();
120
121 Okteta::ByteArrayModelIoDevice byteArrayModelIoDevice(mByteArrayModel);
122 QMimeDatabase db;
123 currentMimeType = filename.isEmpty() ?
124 db.mimeTypeForData(&byteArrayModelIoDevice) :
125 db.mimeTypeForFileNameAndData(filename, &byteArrayModelIoDevice);
126 }
127
128 if (mMimeType != currentMimeType) {
129 mMimeType = currentMimeType;
130 emit documentMimeTypeChanged(currentMimeType);
131 }
132 }
133
onContentsChanged()134 void DocumentInfoTool::onContentsChanged()
135 {
136 if (!mMimeTypeUpdateTimer->isActive()) {
137 mMimeTypeUpdateTimer->start();
138 }
139
140 emit documentSizeChanged(mByteArrayModel->size());
141 }
142
onSynchronizerChanged(AbstractModelSynchronizer * synchronizer)143 void DocumentInfoTool::onSynchronizerChanged(AbstractModelSynchronizer* synchronizer)
144 {
145 // do an instant update, no need to delay
146 if (mMimeTypeUpdateTimer->isActive()) {
147 mMimeTypeUpdateTimer->stop();
148 }
149 updateMimeType();
150
151 if (mSynchronizer) {
152 mSynchronizer->disconnect(this);
153 }
154 mSynchronizer = synchronizer;
155
156 if (mSynchronizer) {
157 connect(mSynchronizer, &AbstractModelSynchronizer::urlChanged,
158 this, &DocumentInfoTool::onUrlChanged);
159 }
160
161 emit locationChanged(location());
162 }
163
onUrlChanged(const QUrl & url)164 void DocumentInfoTool::onUrlChanged(const QUrl& url)
165 {
166 Q_UNUSED(url);
167
168 emit locationChanged(location());
169 }
170
171 }
172