KTextEditor

katebuffer.cpp
1/*
2 SPDX-FileCopyrightText: 2000 Waldo Bastian <bastian@kde.org>
3 SPDX-FileCopyrightText: 2002-2004 Christoph Cullmann <cullmann@kde.org>
4 SPDX-FileCopyrightText: 2007 Mirko Stocker <me@misto.ch>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "katebuffer.h"
10#include "kateautoindent.h"
11#include "kateconfig.h"
12#include "katedocument.h"
13#include "kateglobal.h"
14#include "katehighlight.h"
15#include "katepartdebug.h"
16#include "katesyntaxmanager.h"
17#include "ktexteditor/message.h"
18
19#include <KEncodingProber>
20#include <KLocalizedString>
21
22#include <QDate>
23#include <QFile>
24#include <QFileInfo>
25#include <QStringEncoder>
26#include <QTextStream>
27
28/**
29 * Create an empty buffer. (with one block with one empty line)
30 */
31KateBuffer::KateBuffer(KTextEditor::DocumentPrivate *doc)
32 : Kate::TextBuffer(doc)
33 , m_doc(doc)
34 , m_brokenEncoding(false)
35 , m_tooLongLinesWrapped(false)
36 , m_longestLineLoaded(0)
37 , m_highlight(nullptr)
38 , m_tabWidth(8)
39 , m_lineHighlighted(0)
40{
41}
42
43/**
44 * Cleanup on destruction
45 */
46KateBuffer::~KateBuffer() = default;
47
49{
50 if (!startEditing()) {
51 return;
52 }
53}
54
56{
57 // not finished, do nothing
58 if (!finishEditing()) {
59 return;
60 }
61
62 // nothing change, OK
63 if (!editingChangedBuffer()) {
64 return;
65 }
66
67 // if we arrive here, line changed should be OK
68 Q_ASSERT(editingMinimalLineChanged() != -1);
69 Q_ASSERT(editingMaximalLineChanged() != -1);
71
73}
74
76{
77 // no highlighting, nothing to do
78 if (!m_highlight) {
79 return;
80 }
81
82 // if we don't touch the highlighted area => fine
83 if (editingMinimalLineChanged() > m_lineHighlighted) {
84 return;
85 }
86
87 // really update highlighting
88 // look one line too far, needed for linecontinue stuff
89 doHighlight(editingMinimalLineChanged(), editingMaximalLineChanged() + 1, true);
90}
91
93{
94 // call original clear function
96
97 // reset the state
98 m_brokenEncoding = false;
99 m_tooLongLinesWrapped = false;
100 m_longestLineLoaded = 0;
101
102 // back to line 0 with hl
103 m_lineHighlighted = 0;
104}
105
106bool KateBuffer::openFile(const QString &m_file, bool enforceTextCodec)
107{
108 // first: setup fallback and normal encoding
109 const auto proberType = (KEncodingProber::ProberType)KateGlobalConfig::global()->value(KateGlobalConfig::EncodingProberType).toInt();
110 setEncodingProberType(proberType);
111 setFallbackTextCodec(KateGlobalConfig::global()->fallbackEncoding());
112 setTextCodec(m_doc->config()->encoding());
113
114 // setup eol
115 setEndOfLineMode((EndOfLineMode)m_doc->config()->eol());
116
117 // NOTE: we do not remove trailing spaces on load. This was discussed
118 // over the years again and again. bugs: 306926, 239077, ...
119
120 // line length limit
121 setLineLengthLimit(m_doc->lineLengthLimit());
122
123 // then, try to load the file
124 m_brokenEncoding = false;
125 m_tooLongLinesWrapped = false;
126 m_longestLineLoaded = 0;
127
128 // allow non-existent files without error, if local file!
129 // will allow to do "kate newfile.txt" without error messages but still fail if e.g. you mistype a url
130 // and it can't be fetched via fish:// or other strange things in kio happen...
131 // just clear() + exit with success!
132
133 QFileInfo fileInfo(m_file);
134 if (m_doc->url().isLocalFile() && !fileInfo.exists()) {
135 clear();
136 KTextEditor::Message *message = new KTextEditor::Message(i18nc("short translation, user created new file", "New file"), KTextEditor::Message::Warning);
138 message->setAutoHide(1000);
139 m_doc->postMessage(message);
140
141 // remember error
142 m_doc->m_openingError = true;
143 return true;
144 }
145
146 // check if this is a normal file or not, avoids to open char devices or directories!
147 // else clear buffer and break out with error
148 if (!fileInfo.isFile()) {
149 clear();
150 return false;
151 }
152
153 // try to load
154 if (!load(m_file, m_brokenEncoding, m_tooLongLinesWrapped, m_longestLineLoaded, enforceTextCodec)) {
155 return false;
156 }
157
158 // save back encoding
159 m_doc->config()->setEncoding(textCodec());
160
161 // set eol mode, if a eol char was found
162 if (m_doc->config()->allowEolDetection()) {
163 m_doc->config()->setEol(endOfLineMode());
164 }
165
166 // generate a bom?
167 if (generateByteOrderMark()) {
168 m_doc->config()->setBom(true);
169 }
170
171 // okay, loading did work
172 return true;
173}
174
176{
177 // hardcode some Unicode encodings which can encode all chars
178 if (const auto setEncoding = QStringConverter::encodingForName(m_doc->config()->encoding().toUtf8().constData())) {
179 for (const auto encoding : {QStringConverter::Utf8,
186 if (setEncoding == encoding) {
187 return true;
188 }
189 }
190 }
191
192 QStringEncoder encoder(m_doc->config()->encoding().toUtf8().constData());
193 for (int i = 0; i < lines(); i++) {
194 {
195 // actual encoding happens not during the call to encode() but
196 // during the conversion to QByteArray, so we need to force it
197 QByteArray result = encoder.encode(line(i).text());
198 Q_UNUSED(result);
199 }
200 if (encoder.hasError()) {
201 qCDebug(LOG_KTE) << QLatin1String("ENC NAME: ") << m_doc->config()->encoding();
202 qCDebug(LOG_KTE) << QLatin1String("STRING LINE: ") << line(i).text();
203 qCDebug(LOG_KTE) << QLatin1String("ENC WORKING: FALSE");
204
205 return false;
206 }
207 }
208
209 return true;
210}
211
212bool KateBuffer::saveFile(const QString &m_file)
213{
214 // first: setup fallback and normal encoding
215 const auto proberType = (KEncodingProber::ProberType)KateGlobalConfig::global()->value(KateGlobalConfig::EncodingProberType).toInt();
216 setEncodingProberType(proberType);
217 setFallbackTextCodec(KateGlobalConfig::global()->fallbackEncoding());
218 setTextCodec(m_doc->config()->encoding());
219
220 // setup eol
221 setEndOfLineMode((EndOfLineMode)m_doc->config()->eol());
222
223 // generate bom?
224 setGenerateByteOrderMark(m_doc->config()->bom());
225
226 // try to save
227 if (!save(m_file)) {
228 return false;
229 }
230
231 // no longer broken encoding, or we don't care
232 m_brokenEncoding = false;
233 m_tooLongLinesWrapped = false;
234 m_longestLineLoaded = 0;
235
236 // okay
237 return true;
238}
239
240void KateBuffer::ensureHighlighted(int line, int lookAhead)
241{
242 // valid line at all?
243 if (line < 0 || line >= lines()) {
244 return;
245 }
246
247 // already hl up-to-date for this line?
248 if (line < m_lineHighlighted) {
249 return;
250 }
251
252 // update hl until this line + max lookAhead
253 int end = qMin(line + lookAhead, lines() - 1);
254
255 // ensure we have enough highlighted
256 doHighlight(m_lineHighlighted, end, false);
257}
258
260{
261 // call original
263
264 if (m_lineHighlighted > position.line() + 1) {
265 m_lineHighlighted++;
266 }
267}
268
270{
271 // reimplemented, so first call original
273
274 if (m_lineHighlighted > line) {
275 --m_lineHighlighted;
276 }
277}
278
279void KateBuffer::setTabWidth(int w)
280{
281 if ((m_tabWidth != w) && (m_tabWidth > 0)) {
282 m_tabWidth = w;
283
284 if (m_highlight && m_highlight->foldingIndentationSensitive()) {
286 }
287 }
288}
289
291{
292 KateHighlighting *h = KateHlManager::self()->getHl(hlMode);
293
294 // aha, hl will change
295 if (h != m_highlight) {
296 bool invalidate = !h->noHighlighting();
297
298 if (m_highlight) {
299 invalidate = true;
300 }
301
302 m_highlight = h;
303
304 if (invalidate) {
306 }
307
308 // inform the document that the hl was really changed
309 // needed to update attributes and more ;)
310 m_doc->bufferHlChanged();
311
312 // try to set indentation
313 if (!h->indentation().isEmpty()) {
314 m_doc->config()->setIndentationMode(h->indentation());
315 }
316 }
317}
318
320{
321 m_lineHighlighted = 0;
322}
323
324void KateBuffer::doHighlight(int startLine, int endLine, bool invalidate)
325{
326 // no hl around, no stuff to do
327 if (!m_highlight || m_highlight->noHighlighting()) {
328 return;
329 }
330
331#ifdef BUFFER_DEBUGGING
332 QTime t;
333 t.start();
334 qCDebug(LOG_KTE) << "HIGHLIGHTED START --- NEED HL, LINESTART: " << startLine << " LINEEND: " << endLine;
335 qCDebug(LOG_KTE) << "HL UNTIL LINE: " << m_lineHighlighted;
336#endif
337
338 // if possible get previous line, otherwise create 0 line.
339 Kate::TextLine prevLine = (startLine >= 1) ? plainLine(startLine - 1) : Kate::TextLine();
340
341 // here we are atm, start at start line in the block
342 int current_line = startLine;
343 int start_spellchecking = -1;
344 int last_line_spellchecking = -1;
345 bool ctxChanged = false;
346 // loop over the lines of the block, from startline to endline or end of block
347 // if stillcontinue forces us to do so
348 for (; current_line < qMin(endLine + 1, lines()); ++current_line) {
349 // handle one line
350 ctxChanged = false;
351 Kate::TextLine textLine = plainLine(current_line);
352 m_highlight->doHighlight((current_line >= 1) ? &prevLine : nullptr, &textLine, ctxChanged);
353 prevLine = textLine;
354
355 // write back the computed info to the textline stored in the buffer
356 setLineMetaData(current_line, textLine);
357
358#ifdef BUFFER_DEBUGGING
359 // debug stuff
360 qCDebug(LOG_KTE) << "current line to hl: " << current_line;
361 qCDebug(LOG_KTE) << "text length: " << textLine->length() << " attribute list size: " << textLine->attributesList().size();
362
363 const QList<int> &ml(textLine->attributesList());
364 for (int i = 2; i < ml.size(); i += 3) {
365 qCDebug(LOG_KTE) << "start: " << ml.at(i - 2) << " len: " << ml.at(i - 1) << " at: " << ml.at(i) << " ";
366 }
367 qCDebug(LOG_KTE);
368#endif
369
370 // need we to continue ?
371 bool stillcontinue = ctxChanged;
372 if (stillcontinue && start_spellchecking < 0) {
373 start_spellchecking = current_line;
374 } else if (!stillcontinue && start_spellchecking >= 0) {
375 last_line_spellchecking = current_line;
376 }
377 }
378
379 // perhaps we need to adjust the maximal highlighted line
380 int oldHighlighted = m_lineHighlighted;
381 if (ctxChanged || current_line > m_lineHighlighted) {
382 m_lineHighlighted = current_line;
383 }
384
385 // tag the changed lines !
386 if (invalidate) {
387#ifdef BUFFER_DEBUGGING
388 qCDebug(LOG_KTE) << "HIGHLIGHTED TAG LINES: " << startLine << current_line;
389#endif
390
391 Q_EMIT tagLines({startLine, qMax(current_line, oldHighlighted)});
392
393 if (start_spellchecking >= 0 && lines() > 0) {
394 Q_EMIT respellCheckBlock(start_spellchecking,
395 qMin(lines() - 1, (last_line_spellchecking == -1) ? qMax(current_line, oldHighlighted) : last_line_spellchecking));
396 }
397 }
398
399#ifdef BUFFER_DEBUGGING
400 qCDebug(LOG_KTE) << "HIGHLIGHTED END --- NEED HL, LINESTART: " << startLine << " LINEEND: " << endLine;
401 qCDebug(LOG_KTE) << "HL UNTIL LINE: " << m_lineHighlighted;
402 qCDebug(LOG_KTE) << "HL DYN COUNT: " << KateHlManager::self()->countDynamicCtxs() << " MAX: " << m_maxDynamicContexts;
403 qCDebug(LOG_KTE) << "TIME TAKEN: " << t.elapsed();
404#endif
405}
406
407KateHighlighting::Foldings KateBuffer::computeFoldings(int line)
408{
409 // no hightlighting, no work
410 KateHighlighting::Foldings foldings;
411 if (!m_highlight || m_highlight->noHighlighting()) {
412 return foldings;
413 }
414
415 // ensure we did highlight at least until the previous line
416 if (line > 0) {
417 ensureHighlighted(line - 1, 0);
418 }
419
420 // highlight the given line with passed foldings vector to fill
421 Kate::TextLine prevLine = (line >= 1) ? plainLine(line - 1) : Kate::TextLine();
422 Kate::TextLine textLine = plainLine(line);
423 bool ctxChanged = false;
424 m_highlight->doHighlight((line >= 1) ? &prevLine : nullptr, &textLine, ctxChanged, &foldings);
425 return foldings;
426}
427
428std::pair<bool, bool> KateBuffer::isFoldingStartingOnLine(int startLine)
429{
430 // ensure valid input
431 if (startLine < 0 || startLine >= lines()) {
432 return {false, false};
433 }
434
435 // no highlighting, no folding, ATM
436 if (!m_highlight || m_highlight->noHighlighting()) {
437 return {false, false};
438 }
439
440 // first: get the wanted start line highlighted
441 ensureHighlighted(startLine);
442 const auto startTextLine = plainLine(startLine);
443
444 // we prefer token based folding
445 if (startTextLine.markedAsFoldingStartAttribute()) {
446 return {true, false};
447 }
448
449 // check for indentation based folding
450 if (m_highlight->foldingIndentationSensitive() && (tabWidth() > 0) && startTextLine.highlightingState().indentationBasedFoldingEnabled()
451 && !m_highlight->isEmptyLine(&startTextLine)) {
452 // do some look ahead if this line might be a folding start
453 // we limit this to avoid runtime disaster
454 int linesVisited = 0;
455 while (startLine + 1 < lines()) {
456 const auto nextLine = plainLine(++startLine);
457 if (!m_highlight->isEmptyLine(&nextLine)) {
458 const bool foldingStart = startTextLine.indentDepth(tabWidth()) < nextLine.indentDepth(tabWidth());
459 return {foldingStart, foldingStart};
460 }
461
462 // ensure some sensible limit of look ahead
463 constexpr int lookAheadLimit = 64;
464 if (++linesVisited > lookAheadLimit) {
465 break;
466 }
467 }
468 }
469
470 // no folding start of any kind
471 return {false, false};
472}
473
475{
476 // check for start, will trigger highlighting, too, and rule out bad lines
477 const auto [foldingStart, foldingIndentationSensitive] = isFoldingStartingOnLine(startLine);
478 if (!foldingStart) {
480 }
481
482 // now: decided if indentation based folding or not!
483 if (foldingIndentationSensitive) {
484 // get our start indentation level
485 const auto startTextLine = plainLine(startLine);
486 const int startIndentation = startTextLine.indentDepth(tabWidth());
487
488 // search next line with indentation level <= our one
489 int lastLine = startLine + 1;
490 for (; lastLine < lines(); ++lastLine) {
491 // get line
492 Kate::TextLine textLine = plainLine(lastLine);
493
494 // indentation higher than our start line? continue
495 if (startIndentation < textLine.indentDepth(tabWidth())) {
496 continue;
497 }
498
499 // empty line? continue
500 if (m_highlight->isEmptyLine(&textLine)) {
501 continue;
502 }
503
504 // else, break
505 break;
506 }
507
508 // lastLine is always one too much
509 --lastLine;
510
511 // backtrack all empty lines, we don't want to add them to the fold!
512 while (lastLine > startLine) {
513 const auto l = plainLine(lastLine);
514 if (m_highlight->isEmptyLine(&l)) {
515 --lastLine;
516 } else {
517 break;
518 }
519 }
520
521 // we shall not fold one-liners
522 if (lastLine == startLine) {
524 }
525
526 // be done now
527 return KTextEditor::Range(KTextEditor::Cursor(startLine, 0), KTextEditor::Cursor(lastLine, plainLine(lastLine).length()));
528 }
529
530 // 'normal' attribute based folding, aka token based like '{' BLUB '}'
531
532 // first step: search the first region type, that stays open for the start line
533 int openedRegionType = -1;
534 int openedRegionOffset = -1;
535 {
536 // mapping of type to "first" offset of it and current number of not matched openings
537 QHash<int, QPair<int, int>> foldingStartToOffsetAndCount;
538
539 // walk over all attributes of the line and compute the matchings
540 const auto startLineAttributes = computeFoldings(startLine);
541 for (size_t i = 0; i < startLineAttributes.size(); ++i) {
542 // folding close?
543 if (startLineAttributes[i].foldingRegion.type() == KSyntaxHighlighting::FoldingRegion::End) {
544 // search for this type, try to decrement counter, perhaps erase element!
545 auto end = foldingStartToOffsetAndCount.find(startLineAttributes[i].foldingRegion.id());
546 if (end != foldingStartToOffsetAndCount.end()) {
547 if (end.value().second > 1) {
548 --(end.value().second);
549 } else {
550 foldingStartToOffsetAndCount.erase(end);
551 }
552 }
553 }
554
555 // folding open?
556 if (startLineAttributes[i].foldingRegion.type() == KSyntaxHighlighting::FoldingRegion::Begin) {
557 // search for this type, either insert it, with current offset or increment counter!
558 auto start = foldingStartToOffsetAndCount.find(startLineAttributes[i].foldingRegion.id());
559 if (start != foldingStartToOffsetAndCount.end()) {
560 ++(start.value().second);
561 } else {
562 foldingStartToOffsetAndCount.insert(startLineAttributes[i].foldingRegion.id(), qMakePair(startLineAttributes[i].offset, 1));
563 }
564 }
565 }
566
567 // compute first type with offset
568 QHashIterator<int, QPair<int, int>> hashIt(foldingStartToOffsetAndCount);
569 while (hashIt.hasNext()) {
570 hashIt.next();
571 if (openedRegionOffset == -1 || hashIt.value().first < openedRegionOffset) {
572 openedRegionType = hashIt.key();
573 openedRegionOffset = hashIt.value().first;
574 }
575 }
576 }
577
578 // no opening region found, bad, nothing to do
579 if (openedRegionType == -1) {
581 }
582
583 // second step: search for matching end region marker!
584 int countOfOpenRegions = 1;
585 for (int line = startLine + 1; line < lines(); ++line) {
586 // search for matching end marker
587 const auto lineAttributes = computeFoldings(line);
588 for (size_t i = 0; i < lineAttributes.size(); ++i) {
589 // matching folding close?
590 if (lineAttributes[i].foldingRegion.type() == KSyntaxHighlighting::FoldingRegion::End && lineAttributes[i].foldingRegion.id() == openedRegionType) {
591 --countOfOpenRegions;
592
593 // end reached?
594 // compute resulting range!
595 if (countOfOpenRegions == 0) {
596 // Don't return a valid range without content!
597 if (line - startLine == 1) {
599 }
600
601 // return computed range
602 return KTextEditor::Range(KTextEditor::Cursor(startLine, openedRegionOffset), KTextEditor::Cursor(line, lineAttributes[i].offset));
603 }
604 }
605
606 // matching folding open?
607 if (lineAttributes[i].foldingRegion.type() == KSyntaxHighlighting::FoldingRegion::Begin
608 && lineAttributes[i].foldingRegion.id() == openedRegionType) {
609 ++countOfOpenRegions;
610 }
611 }
612 }
613
614 // if we arrive here, the opened range spans to the end of the document!
615 return KTextEditor::Range(KTextEditor::Cursor(startLine, openedRegionOffset), KTextEditor::Cursor(lines() - 1, plainLine(lines() - 1).length()));
616}
617
618#include "moc_katebuffer.cpp"
The Cursor represents a position in a Document.
Definition cursor.h:75
constexpr int line() const noexcept
Retrieve the line on which this cursor is situated.
Definition cursor.h:174
This class holds a Message to display in Views.
Definition message.h:94
@ TopInView
show message as view overlay in the top right corner.
Definition message.h:123
void setAutoHide(int delay=0)
Set the auto hide time to delay milliseconds.
@ Warning
warning message type
Definition message.h:109
void setPosition(MessagePosition position)
Sets the position of the message to position.
An object representing a section of text, from one Cursor to another.
static constexpr Range invalid() noexcept
Returns an invalid range.
~KateBuffer() override
Goodbye buffer.
KTextEditor::Range computeFoldingRangeForStartLine(int startLine)
For a given line, compute the folding range that starts there to be used to fold e....
bool openFile(const QString &m_file, bool enforceTextCodec)
Open a file, use the given filename.
std::pair< bool, bool > isFoldingStartingOnLine(int startLine)
For a given line, compute if folding starts here.
void wrapLine(const KTextEditor::Cursor position) override
Wrap line at given cursor position.
void clear() override
Clear the buffer.
KateBuffer(KTextEditor::DocumentPrivate *doc)
Create an empty buffer.
bool canEncode()
Can the current codec handle all chars.
Kate::TextLine plainLine(int lineno)
Return line lineno.
Definition katebuffer.h:158
void setHighlight(int hlMode)
Use highlight for highlighting.
void updateHighlighting()
Update highlighting of the lines in last edit transaction.
void ensureHighlighted(int line, int lookAhead=64)
Update highlighting of given line line, if needed.
void tagLines(KTextEditor::LineRange lineRange)
Emitted when the highlighting of a certain range has changed.
void editEnd()
finish some editing action
bool saveFile(const QString &m_file)
Save the buffer to a file, use the given filename + codec + end of line chars (internal use of qtexts...
KateHighlighting::Foldings computeFoldings(int line)
Compute folding vector for the given line, will internally do a re-highlighting.
void unwrapLine(int line) override
Unwrap given line.
void invalidateHighlighting()
Invalidate highlighting of whole buffer.
void editStart()
start some editing action
QVariant value(const int key) const
Get a config value.
void setEncodingProberType(KEncodingProber::ProberType proberType)
Set encoding prober type for this buffer to use for load.
void setLineLengthLimit(int lineLengthLimit)
Set line length limit.
virtual bool save(const QString &filename)
Save the current buffer content to the given file.
TextLine line(int line) const
Retrieve a text line.
virtual void wrapLine(const KTextEditor::Cursor position)
Wrap line at given cursor position.
int editingMaximalLineChanged() const
Get maximal line number changed by last editing transaction.
void setFallbackTextCodec(const QString &codec)
Set fallback codec for this buffer to use for load.
virtual void unwrapLine(int line)
Unwrap given line.
bool editingChangedBuffer() const
Query information from the last editing transaction: was the content of the buffer changed?...
int lines() const
Lines currently stored in this buffer.
EndOfLineMode endOfLineMode() const
Get end of line mode.
void setLineMetaData(int line, const TextLine &textLine)
Transfer all non text attributes for the given line from the given text line to the one in the buffer...
bool generateByteOrderMark() const
Generate byte order mark on save?
QString textCodec() const
Get codec for this buffer.
void setEndOfLineMode(EndOfLineMode endOfLineMode)
Set end of line mode for this buffer, not allowed to be set to unknown.
void setTextCodec(const QString &codec)
Set codec for this buffer to use for load/save.
virtual bool load(const QString &filename, bool &encodingErrors, bool &tooLongLinesWrapped, int &longestLineLoaded, bool enforceTextCodec)
Load the given file.
virtual bool startEditing()
Start an editing transaction, the wrapLine/unwrapLine/insertText and removeText functions are only al...
EndOfLineMode
End of line mode.
virtual void clear()
Clears the buffer, reverts to initial empty state.
int editingMinimalLineChanged() const
Get minimal line number changed by last editing transaction.
virtual bool finishEditing()
Finish an editing transaction.
void setGenerateByteOrderMark(bool generateByteOrderMark)
Generate byte order mark on save.
Class representing a single text line.
const QString & text() const
Accessor to the text contained in this line.
const QList< Attribute > & attributesList() const
Accessor to attributes.
int indentDepth(int tabWidth) const
Returns the indentation depth with each tab expanded into tabWidth characters.
int length() const
Returns the line's length.
Q_SCRIPTABLE Q_NOREPLY void start()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
bool exists(const QString &path)
bool isFile() const const
iterator end()
iterator erase(const_iterator pos)
iterator find(const Key &key)
iterator insert(const Key &key, const T &value)
bool hasNext() const const
const Key & key() const const
const T & value() const const
Q_EMITQ_EMIT
bool isEmpty() const const
std::optional< Encoding > encodingForName(const char *name)
bool hasError() const const
DecodedData< QStringView > encode(QStringView in)
int toInt(bool *ok) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jun 21 2024 12:02:52 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.