File indexing completed on 2024-04-28 11:45:05

0001 /*
0002     SPDX-FileCopyrightText: 2009 Milian Wolff <mail@milianw.de>
0003     SPDX-FileCopyrightText: 2002 John Firebaugh <jfirebaugh@kde.org>
0004     SPDX-FileCopyrightText: 2001 Christoph Cullmann <cullmann@kde.org>
0005     SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org>
0006     SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #include "exporter.h"
0012 #include "abstractexporter.h"
0013 #include "htmlexporter.h"
0014 
0015 #include <ktexteditor/document.h>
0016 #include <ktexteditor/view.h>
0017 
0018 #include <KLocalizedString>
0019 
0020 #include <QApplication>
0021 #include <QClipboard>
0022 #include <QFileDialog>
0023 #include <QMimeData>
0024 #include <QTextCodec>
0025 
0026 void KateExporter::exportToClipboard()
0027 {
0028     if (!m_view->selection()) {
0029         return;
0030     }
0031 
0032     QMimeData *data = new QMimeData();
0033 
0034     QString s;
0035     QTextStream output(&s, QIODevice::WriteOnly);
0036     exportData(true, output);
0037 
0038     data->setHtml(s);
0039     data->setText(s);
0040 
0041     QApplication::clipboard()->setMimeData(data);
0042 }
0043 
0044 void KateExporter::exportToFile(const QString &file)
0045 {
0046     QFile savefile(file);
0047     if (!savefile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
0048         return;
0049     }
0050 
0051     QTextStream outputStream(&savefile);
0052     exportData(false, outputStream);
0053 }
0054 
0055 void KateExporter::exportData(const bool useSelection, QTextStream &output)
0056 {
0057     const KTextEditor::Range range = useSelection ? m_view->selectionRange() : m_view->document()->documentRange();
0058     const bool blockwise = useSelection ? m_view->blockSelection() : false;
0059 
0060     if ((blockwise || range.onSingleLine()) && (range.start().column() > range.end().column())) {
0061         return;
0062     }
0063 
0064     output.setCodec(QTextCodec::codecForName("UTF-8"));
0065 
0066     /// TODO: add more exporters
0067     std::unique_ptr<AbstractExporter> exporter = std::make_unique<HTMLExporter>(m_view, output, !useSelection);
0068 
0069     const KTextEditor::Attribute::Ptr noAttrib(nullptr);
0070 
0071     for (int i = range.start().line(); (i <= range.end().line()) && (i < m_view->document()->lines()); ++i) {
0072         const QString &line = m_view->document()->line(i);
0073 
0074         const QList<KTextEditor::AttributeBlock> attribs = m_view->lineAttributes(i);
0075 
0076         int lineStart = 0;
0077         int remainingChars = line.length();
0078         if (blockwise || range.onSingleLine()) {
0079             lineStart = range.start().column();
0080             remainingChars = range.columnWidth();
0081         } else if (i == range.start().line()) {
0082             lineStart = range.start().column();
0083         } else if (i == range.end().line()) {
0084             remainingChars = range.end().column();
0085         }
0086 
0087         int handledUntil = lineStart;
0088 
0089         for (const KTextEditor::AttributeBlock &block : attribs) {
0090             // honor (block-) selections
0091             if (block.start + block.length <= lineStart) {
0092                 continue;
0093             } else if (block.start >= lineStart + remainingChars) {
0094                 break;
0095             }
0096             int start = qMax(block.start, lineStart);
0097             if (start > handledUntil) {
0098                 exporter->exportText(line.mid(handledUntil, start - handledUntil), noAttrib);
0099             }
0100             int length = qMin(block.length, remainingChars);
0101             exporter->exportText(line.mid(start, length), block.attribute);
0102             handledUntil = start + length;
0103         }
0104 
0105         if (handledUntil < lineStart + remainingChars) {
0106             exporter->exportText(line.mid(handledUntil, remainingChars), noAttrib);
0107         }
0108 
0109         exporter->closeLine(i == range.end().line());
0110     }
0111 
0112     output.flush();
0113 }