Warning, file /office/marknote/src/documenthandler.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 // SPDX-FileCopyrightText: 2017 The Qt Company Ltd. 0002 // SPDX-License-Identifier: BSD-3-Clause 0003 0004 #include "documenthandler.h" 0005 0006 #include <QDebug> 0007 #include <QFile> 0008 #include <QFileInfo> 0009 #include <QFileSelector> 0010 #include <QMimeDatabase> 0011 #include <QQmlFile> 0012 #include <QQmlFileSelector> 0013 #include <QQuickTextDocument> 0014 #include <QTextCharFormat> 0015 #include <QTextDocument> 0016 0017 DocumentHandler::DocumentHandler(QObject *parent) 0018 : QObject(parent) 0019 , m_document(nullptr) 0020 , m_cursorPosition(-1) 0021 , m_selectionStart(0) 0022 , m_selectionEnd(0) 0023 { 0024 } 0025 0026 QQuickTextDocument *DocumentHandler::document() const 0027 { 0028 return m_document; 0029 } 0030 0031 void DocumentHandler::setDocument(QQuickTextDocument *document) 0032 { 0033 if (document == m_document) 0034 return; 0035 0036 if (m_document) 0037 m_document->textDocument()->disconnect(this); 0038 m_document = document; 0039 if (m_document) 0040 connect(m_document->textDocument(), &QTextDocument::modificationChanged, this, &DocumentHandler::modifiedChanged); 0041 Q_EMIT documentChanged(); 0042 } 0043 0044 int DocumentHandler::cursorPosition() const 0045 { 0046 return m_cursorPosition; 0047 } 0048 0049 void DocumentHandler::setCursorPosition(int position) 0050 { 0051 if (position == m_cursorPosition) 0052 return; 0053 0054 m_cursorPosition = position; 0055 reset(); 0056 Q_EMIT cursorPositionChanged(); 0057 } 0058 0059 int DocumentHandler::selectionStart() const 0060 { 0061 return m_selectionStart; 0062 } 0063 0064 void DocumentHandler::setSelectionStart(int position) 0065 { 0066 if (position == m_selectionStart) 0067 return; 0068 0069 m_selectionStart = position; 0070 Q_EMIT selectionStartChanged(); 0071 } 0072 0073 int DocumentHandler::selectionEnd() const 0074 { 0075 return m_selectionEnd; 0076 } 0077 0078 void DocumentHandler::setSelectionEnd(int position) 0079 { 0080 if (position == m_selectionEnd) 0081 return; 0082 0083 m_selectionEnd = position; 0084 Q_EMIT selectionEndChanged(); 0085 } 0086 0087 QString DocumentHandler::fontFamily() const 0088 { 0089 QTextCursor cursor = textCursor(); 0090 if (cursor.isNull()) 0091 return QString(); 0092 QTextCharFormat format = cursor.charFormat(); 0093 return format.font().family(); 0094 } 0095 0096 void DocumentHandler::setFontFamily(const QString &family) 0097 { 0098 QTextCharFormat format; 0099 format.setFontFamilies({family}); 0100 mergeFormatOnWordOrSelection(format); 0101 Q_EMIT fontFamilyChanged(); 0102 } 0103 0104 QColor DocumentHandler::textColor() const 0105 { 0106 QTextCursor cursor = textCursor(); 0107 if (cursor.isNull()) 0108 return QColor(Qt::black); 0109 QTextCharFormat format = cursor.charFormat(); 0110 return format.foreground().color(); 0111 } 0112 0113 void DocumentHandler::setTextColor(const QColor &color) 0114 { 0115 QTextCharFormat format; 0116 format.setForeground(QBrush(color)); 0117 mergeFormatOnWordOrSelection(format); 0118 Q_EMIT textColorChanged(); 0119 } 0120 0121 Qt::Alignment DocumentHandler::alignment() const 0122 { 0123 QTextCursor cursor = textCursor(); 0124 if (cursor.isNull()) 0125 return Qt::AlignLeft; 0126 return textCursor().blockFormat().alignment(); 0127 } 0128 0129 void DocumentHandler::setAlignment(Qt::Alignment alignment) 0130 { 0131 QTextBlockFormat format; 0132 format.setAlignment(alignment); 0133 QTextCursor cursor = textCursor(); 0134 cursor.mergeBlockFormat(format); 0135 Q_EMIT alignmentChanged(); 0136 } 0137 0138 bool DocumentHandler::bold() const 0139 { 0140 QTextCursor cursor = textCursor(); 0141 if (cursor.isNull()) 0142 return false; 0143 return textCursor().charFormat().fontWeight() == QFont::Bold; 0144 } 0145 0146 void DocumentHandler::setBold(bool bold) 0147 { 0148 QTextCharFormat format; 0149 format.setFontWeight(bold ? QFont::Bold : QFont::Normal); 0150 mergeFormatOnWordOrSelection(format); 0151 Q_EMIT boldChanged(); 0152 } 0153 0154 bool DocumentHandler::italic() const 0155 { 0156 QTextCursor cursor = textCursor(); 0157 if (cursor.isNull()) 0158 return false; 0159 return textCursor().charFormat().fontItalic(); 0160 } 0161 0162 void DocumentHandler::setItalic(bool italic) 0163 { 0164 QTextCharFormat format; 0165 format.setFontItalic(italic); 0166 mergeFormatOnWordOrSelection(format); 0167 Q_EMIT italicChanged(); 0168 } 0169 0170 bool DocumentHandler::underline() const 0171 { 0172 QTextCursor cursor = textCursor(); 0173 if (cursor.isNull()) 0174 return false; 0175 return textCursor().charFormat().fontUnderline(); 0176 } 0177 0178 void DocumentHandler::setUnderline(bool underline) 0179 { 0180 QTextCharFormat format; 0181 format.setFontUnderline(underline); 0182 mergeFormatOnWordOrSelection(format); 0183 Q_EMIT underlineChanged(); 0184 } 0185 0186 int DocumentHandler::fontSize() const 0187 { 0188 QTextCursor cursor = textCursor(); 0189 if (cursor.isNull()) 0190 return 0; 0191 QTextCharFormat format = cursor.charFormat(); 0192 return format.font().pointSize(); 0193 } 0194 0195 void DocumentHandler::setFontSize(int size) 0196 { 0197 if (size <= 0) 0198 return; 0199 0200 QTextCursor cursor = textCursor(); 0201 if (cursor.isNull()) 0202 return; 0203 0204 if (!cursor.hasSelection()) 0205 cursor.select(QTextCursor::WordUnderCursor); 0206 0207 if (cursor.charFormat().property(QTextFormat::FontPointSize).toInt() == size) 0208 return; 0209 0210 QTextCharFormat format; 0211 format.setFontPointSize(size); 0212 mergeFormatOnWordOrSelection(format); 0213 Q_EMIT fontSizeChanged(); 0214 } 0215 0216 QString DocumentHandler::fileName() const 0217 { 0218 const QString filePath = QQmlFile::urlToLocalFileOrQrc(m_fileUrl); 0219 const QString fileName = QFileInfo(filePath).fileName(); 0220 if (fileName.isEmpty()) 0221 return QStringLiteral("untitled.txt"); 0222 return fileName; 0223 } 0224 0225 QString DocumentHandler::fileType() const 0226 { 0227 return QFileInfo(fileName()).suffix(); 0228 } 0229 0230 QUrl DocumentHandler::fileUrl() const 0231 { 0232 return m_fileUrl; 0233 } 0234 0235 void DocumentHandler::load(const QUrl &fileUrl) 0236 { 0237 if (fileUrl == m_fileUrl) 0238 return; 0239 0240 QQmlEngine *engine = qmlEngine(this); 0241 if (!engine) { 0242 qWarning() << "load() called before DocumentHandler has QQmlEngine"; 0243 return; 0244 } 0245 0246 const QUrl path = QQmlFileSelector::get(engine)->selector()->select(fileUrl); 0247 const QString fileName = QQmlFile::urlToLocalFileOrQrc(path); 0248 if (QFile::exists(fileName)) { 0249 QFile file(fileName); 0250 if (file.open(QFile::ReadOnly)) { 0251 QByteArray data = file.readAll(); 0252 if (QTextDocument *doc = textDocument()) { 0253 doc->setBaseUrl(path.adjusted(QUrl::RemoveFilename)); 0254 Q_EMIT loaded(QString::fromUtf8(data), Qt::MarkdownText); 0255 doc->setModified(false); 0256 } 0257 0258 reset(); 0259 } 0260 } 0261 0262 m_fileUrl = fileUrl; 0263 Q_EMIT fileUrlChanged(); 0264 } 0265 0266 void DocumentHandler::saveAs(const QUrl &fileUrl) 0267 { 0268 QTextDocument *doc = textDocument(); 0269 if (!doc) 0270 return; 0271 0272 const QString filePath = fileUrl.toLocalFile(); 0273 QFile file(filePath); 0274 if (!file.open(QFile::WriteOnly | QFile::Truncate)) { 0275 Q_EMIT error(tr("Cannot save: ") + file.errorString()); 0276 return; 0277 } 0278 file.write(doc->toMarkdown().toUtf8()); 0279 file.close(); 0280 0281 if (fileUrl == m_fileUrl) 0282 return; 0283 0284 m_fileUrl = fileUrl; 0285 Q_EMIT fileUrlChanged(); 0286 } 0287 0288 void DocumentHandler::reset() 0289 { 0290 Q_EMIT fontFamilyChanged(); 0291 Q_EMIT alignmentChanged(); 0292 Q_EMIT boldChanged(); 0293 Q_EMIT italicChanged(); 0294 Q_EMIT underlineChanged(); 0295 Q_EMIT fontSizeChanged(); 0296 Q_EMIT textColorChanged(); 0297 } 0298 0299 QTextCursor DocumentHandler::textCursor() const 0300 { 0301 QTextDocument *doc = textDocument(); 0302 if (!doc) 0303 return QTextCursor(); 0304 0305 QTextCursor cursor = QTextCursor(doc); 0306 if (m_selectionStart != m_selectionEnd) { 0307 cursor.setPosition(m_selectionStart); 0308 cursor.setPosition(m_selectionEnd, QTextCursor::KeepAnchor); 0309 } else { 0310 cursor.setPosition(m_cursorPosition); 0311 } 0312 return cursor; 0313 } 0314 0315 QTextDocument *DocumentHandler::textDocument() const 0316 { 0317 if (!m_document) 0318 return nullptr; 0319 0320 return m_document->textDocument(); 0321 } 0322 0323 void DocumentHandler::mergeFormatOnWordOrSelection(const QTextCharFormat &format) 0324 { 0325 QTextCursor cursor = textCursor(); 0326 if (!cursor.hasSelection()) 0327 cursor.select(QTextCursor::WordUnderCursor); 0328 cursor.mergeCharFormat(format); 0329 } 0330 0331 bool DocumentHandler::modified() const 0332 { 0333 return m_document && m_document->textDocument()->isModified(); 0334 } 0335 0336 void DocumentHandler::setModified(bool m) 0337 { 0338 if (m_document) 0339 m_document->textDocument()->setModified(m); 0340 }