diff --git a/addons/CMakeLists.txt b/addons/CMakeLists.txt --- a/addons/CMakeLists.txt +++ b/addons/CMakeLists.txt @@ -71,9 +71,6 @@ ecm_optional_add_subdirectory (snippets) endif() -# live preview of sources in target format -ecm_optional_add_subdirectory (preview) - # terminal tool view if(KF5Service_FOUND AND NOT WIN32) ecm_optional_add_subdirectory (konsole) diff --git a/addons/preview/CMakeLists.txt b/addons/preview/CMakeLists.txt deleted file mode 100644 --- a/addons/preview/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -add_definitions(-DTRANSLATION_DOMAIN=\"ktexteditorpreviewplugin\") - -include(ECMQtDeclareLoggingCategory) - -set(ktexteditorpreviewplugin_SRCS - ktexteditorpreviewplugin.cpp - ktexteditorpreviewview.cpp - previewwidget.cpp - kpartview.cpp -) - -ecm_qt_declare_logging_category(ktexteditorpreviewplugin_SRCS - HEADER ktexteditorpreview_debug.h - IDENTIFIER KTEPREVIEW - CATEGORY_NAME "ktexteditorpreviewplugin" -) - -add_library(ktexteditorpreviewplugin MODULE ${ktexteditorpreviewplugin_SRCS}) - -target_link_libraries(ktexteditorpreviewplugin - KF5::TextEditor - KF5::I18n -) - -install(TARGETS ktexteditorpreviewplugin DESTINATION ${KDE_INSTALL_PLUGINDIR}/ktexteditor) diff --git a/addons/preview/Messages.sh b/addons/preview/Messages.sh deleted file mode 100644 --- a/addons/preview/Messages.sh +++ /dev/null @@ -1,2 +0,0 @@ -#! /usr/bin/env bash -$XGETTEXT *.cpp -o $podir/ktexteditorpreviewplugin.pot diff --git a/addons/preview/kpartview.h b/addons/preview/kpartview.h deleted file mode 100644 --- a/addons/preview/kpartview.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2017 by Friedrich W. H. Kossebau - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef KTEXTEDITORPREVIEW_KPARTVIEW_H -#define KTEXTEDITORPREVIEW_KPARTVIEW_H - -// KF -#include - -// Qt -#include -#include - -namespace KTextEditor { -class Document; -} -namespace KParts { -class ReadOnlyPart; -} -class QLabel; -class QTemporaryFile; - -namespace KTextEditorPreview { - -/** - * Wrapper around a KPart which handles feeding it the content of a text document - * - * The class creates a KPart from the service description passed in the constructor - * and then takes care for feeding the content of the currently set text document - * to the KPart for preview in the target format, both on changes in the document - * or when a new document is set. - * - * The content is pushed via the KParts stream API, if the KPart instance - * supports it, or as fallback via the filesystem, using a QTemporaryFile instance. - * Updates are squashed via a timer, to reduce load. - */ -class KPartView : public QObject -{ - Q_OBJECT - -public: - /** - * Constructor - * - * @param service the description of the KPart which should be used, may not be a nullptr - * @param parent the object taking ownership, can be a nullptr - */ - KPartView(const KService::Ptr& service, QObject* parent); - ~KPartView() override; - - /** - * Returns the widget object, ownership is not transferred. - */ - QWidget* widget() const; - - KParts::ReadOnlyPart* kPart() const; - - /** - * Sets the current document whose content should be previewed by the KPart. - * - * @param document the document or, if there is none to preview, a nullptr - */ - void setDocument(KTextEditor::Document* document); - - /** - * Returns the current document whose content is previewed by the KPart. - * - * @return current document or, if there is none, a nullptr - */ - KTextEditor::Document* document() const; - - /** - * Sets whether the preview should be updating automatically on document changes or not. - * - * @param autoUpdating whether the preview should be updating automatically on document changes or not - */ - void setAutoUpdating(bool autoUpdating); - - /** - * Returns @c true if the preview is updating automatically on document changes, @c false otherwise. - */ - bool isAutoUpdating() const; - - /** - * Update preview to current document content. - */ - void updatePreview(); - -protected: - bool eventFilter(QObject* object, QEvent* event) override; - -private: - void triggerUpdatePreview(); - void handleOpenUrlRequest(const QUrl& url); - -private: - QLabel* m_errorLabel = nullptr; - KParts::ReadOnlyPart* m_part = nullptr; - KTextEditor::Document* m_document = nullptr; - - bool m_autoUpdating = true; - bool m_previewDirty = true; - QTimer m_updateSquashingTimer; - QTemporaryFile* m_bufferFile = nullptr; -}; - -} - -#endif diff --git a/addons/preview/kpartview.cpp b/addons/preview/kpartview.cpp deleted file mode 100644 --- a/addons/preview/kpartview.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2017 by Friedrich W. H. Kossebau - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "kpartview.h" - -#include - -// KF -#include - -#include -#include -#include -#include -#include - -// Qt -#include -#include -#include - - -using namespace KTextEditorPreview; - -// 300 ms as initial proposal, was found to be delay which worked for the -// author with the use-case of quickly peeking over to the preview while -// typing to see if things are working out as intended, without getting a -// having-to-wait feeling. -// Surely could get some more serious research what is a proper (default) value. -// Perhaps the whole update logic cpuld also be overhauled, to only do an -// update once there was at least xxx ms idle time to meet the use-case of -// quickly-peeking-over. And otherwise update in bigger intervals of -// 500-2000(?) ms, to cover the use-case of seeing from the corner of one's -// eye that something is changing while one is editing the sources. -static const int updateDelay = 300; // ms - -KPartView::KPartView(const KService::Ptr& service, QObject* parent) - : QObject(parent) -{ - QString errorString; - m_part = service->createInstance(nullptr, this, QVariantList(), &errorString); - - if (!m_part) { - m_errorLabel = new QLabel(errorString); - } else if (!m_part->widget()) { - // should not happen, but just be safe - delete m_part; - m_errorLabel = new QLabel(QStringLiteral("KPart provides no widget.")); - } else { - m_updateSquashingTimer.setSingleShot(true); - m_updateSquashingTimer.setInterval(updateDelay); - connect(&m_updateSquashingTimer, &QTimer::timeout, this, &KPartView::updatePreview); - - auto browserExtension = m_part->browserExtension(); - if (browserExtension) { - connect(browserExtension, &KParts::BrowserExtension::openUrlRequestDelayed, - this, &KPartView::handleOpenUrlRequest); - } - m_part->widget()->installEventFilter(this); - } -} - -KPartView::~KPartView() -{ - delete m_errorLabel; -} - -QWidget* KPartView::widget() const -{ - return m_part ? m_part->widget() : m_errorLabel; -} - -KParts::ReadOnlyPart* KPartView::kPart() const -{ - return m_part; -} - -KTextEditor::Document* KPartView::document() const -{ - return m_document; -} - -bool KPartView::isAutoUpdating() const -{ - return m_autoUpdating; -} - -void KPartView::setDocument(KTextEditor::Document* document) -{ - if (m_document == document) { - return; - } - if (!m_part) { - return; - } - - if (m_document) { - disconnect(m_document, &KTextEditor::Document::textChanged, this, &KPartView::triggerUpdatePreview); - m_updateSquashingTimer.stop(); - } - - m_document = document; - - // delete any temporary file, to trigger creation of a new if needed - // for some unique url/path of the temporary file for the new document (or use a counter ourselves?) - // but see comment for stream url - delete m_bufferFile; - m_bufferFile = nullptr; - - if (m_document) { - m_previewDirty = true; - updatePreview(); - connect(m_document, &KTextEditor::Document::textChanged, this, &KPartView::triggerUpdatePreview); - } else { - m_part->closeUrl(); - } -} - -void KPartView::setAutoUpdating(bool autoUpdating) -{ - if (m_autoUpdating == autoUpdating) { - return; - } - - m_autoUpdating = autoUpdating; - - if (m_autoUpdating) { - if (m_document && m_part && m_previewDirty) { - updatePreview(); - } - } else { - m_updateSquashingTimer.stop(); - } -} - -void KPartView::triggerUpdatePreview() -{ - m_previewDirty = true; - - if (m_part->widget()->isVisible() && m_autoUpdating && !m_updateSquashingTimer.isActive()) { - m_updateSquashingTimer.start(); - } -} - -void KPartView::updatePreview() -{ - if (!m_part->widget()->isVisible()) { - return; - } - - // TODO: some kparts seem to steal the focus after they have loaded a file, sometimes also async - // that possibly needs fixing in the respective kparts, as that could be considered non-cooperative - - // TODO: investigate if pushing of the data to the kpart could be done in a non-gui-thread, - // so their loading of the file (e.g. ReadOnlyPart::openFile() is sync design) does not block - - const auto mimeType = m_document->mimeType(); - KParts::OpenUrlArguments arguments; - arguments.setMimeType(mimeType); - m_part->setArguments(arguments); - - // try to stream the data to avoid filesystem I/O - // create url unique for this document - // TODO: encode existing url instead, and for yet-to-be-stored docs some other unique id - const QUrl streamUrl(QStringLiteral("ktexteditorpreview:/object/%1") - .arg(reinterpret_cast(m_document), 0, 16)); - if (m_part->openStream(mimeType, streamUrl)) { - qCDebug(KTEPREVIEW) << "Pushing data via streaming API, url:" << streamUrl.url(); - m_part->writeStream(m_document->text().toUtf8()); - m_part->closeStream(); - - m_previewDirty = false; - return; - } - - // have to go via filesystem for now, not nice - if (!m_bufferFile) { - m_bufferFile = new QTemporaryFile(this); - m_bufferFile->open(); - } else { - // reset position - m_bufferFile->seek(0); - } - const QUrl tempFileUrl(QUrl::fromLocalFile(m_bufferFile->fileName())); - qCDebug(KTEPREVIEW) << "Pushing data via temporary file, url:" << tempFileUrl.url(); - - // write current data - m_bufferFile->write(m_document->text().toUtf8()); - // truncate at end of new content - m_bufferFile->resize(m_bufferFile->pos()); - m_bufferFile->flush(); - - // TODO: find out why we need to send this queued - QMetaObject::invokeMethod(m_part, "openUrl", Qt::QueuedConnection, Q_ARG(QUrl, tempFileUrl)); - - m_previewDirty = false; -} - -void KPartView::handleOpenUrlRequest(const QUrl& url) -{ - QDesktopServices::openUrl(url); -} - -bool KPartView::eventFilter(QObject* object, QEvent* event) -{ - if (object == m_part->widget() && event->type() == QEvent::Show) { - if (m_document && m_autoUpdating && m_previewDirty) { - updatePreview(); - } - return true; - } - - return QObject::eventFilter(object, event); -} diff --git a/addons/preview/ktexteditorpreview.json b/addons/preview/ktexteditorpreview.json deleted file mode 100644 --- a/addons/preview/ktexteditorpreview.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "KPlugin": { - "Authors": [ - { - "Email": "kossebau@kde.org", - "Name": "Friedrich W. H. Kossebau", - "Name[ast]": "Friedrich W. H. Kossebau", - "Name[ca@valencia]": "Friedrich W. H. Kossebau", - "Name[ca]": "Friedrich W. H. Kossebau", - "Name[cs]": "Friedrich W. H. Kossebau", - "Name[da]": "Friedrich W. H. Kossebau", - "Name[de]": "Friedrich W. H. Kossebau", - "Name[el]": "Friedrich W. H. Kossebau", - "Name[en_GB]": "Friedrich W. H. Kossebau", - "Name[es]": "Friedrich W. H. Kossebau", - "Name[eu]": "Friedrich W. H. Kossebau", - "Name[fi]": "Friedrich W. H. Kossebau", - "Name[fr]": "Friedrich W. H. Kossebau", - "Name[gl]": "Friedrich W. H. Kossebau", - "Name[ia]": "Friedrich W. H. Kossebau", - "Name[it]": "Friedrich W. H. Kossebau", - "Name[ko]": "Friedrich W. H. Kossebau", - "Name[nl]": "Friedrich W. H. Kossebau", - "Name[nn]": "Friedrich W.H. Kossebau", - "Name[pl]": "Friedrich W. H. Kossebau", - "Name[pt]": "Friedrich W. H. Kossebau", - "Name[pt_BR]": "Friedrich W. H. Kossebau", - "Name[ru]": "Friedrich W. H. Kossebau", - "Name[sk]": "Friedrich W. H. Kossebau", - "Name[sl]": "Friedrich W. H. Kossebau", - "Name[sr@ijekavian]": "Фридрих В.Х. Косебау", - "Name[sr@ijekavianlatin]": "Fridrih V.H. Kosebau", - "Name[sr@latin]": "Fridrih V.H. Kosebau", - "Name[sr]": "Фридрих В.Х. Косебау", - "Name[sv]": "Friedrich W. H. Kossebau", - "Name[uk]": "Friedrich W. H. Kossebau", - "Name[x-test]": "xxFriedrich W. H. Kossebauxx", - "Name[zh_CN]": "Friedrich W. H. Kossebau", - "Name[zh_TW]": "Friedrich W. H. Kossebau" - } - ], - "Description": "Preview the document in the target format", - "Description[ast]": "Previsualiza los documentos nel formatu de destín", - "Description[ca@valencia]": "Vista prèvia del document en el format de destí", - "Description[ca]": "Vista prèvia del document en el format de destí", - "Description[da]": "Forhåndsvis dokumentet i målformatet", - "Description[de]": "Vorschau des Dokuments im Zielformat", - "Description[el]": "Προεπισκόπηση του εγγράφου στον τύπο αποθήκευσης προορισμού", - "Description[en_GB]": "Preview the document in the target format", - "Description[es]": "Mostrar vista previa del documento en el formato elegido", - "Description[eu]": "Aurreikusi dokumentua helburu formatuan", - "Description[fi]": "Esikatsele asiakirjaa kohdemuodossa", - "Description[fr]": "Aperçu du document dans le format de destination", - "Description[gl]": "Previsualizar o documento no formato de destino.", - "Description[ia]": "Vide preliminarmente le documento in le formato objectivo", - "Description[it]": "Anteprima del documento nel formato di destinazione", - "Description[ko]": "문서를 대상 형식으로 미리 보기", - "Description[nl]": "Het document bekijken in het doelformaat", - "Description[nn]": "Førehandsvis dokumentet i målformatet", - "Description[pl]": "Podejrzyj dokument w formacie docelowym", - "Description[pt]": "Mostra uma antevisão do documento no formato-alvo", - "Description[pt_BR]": "Visualize o documento no formato de destino", - "Description[ru]": "Предварительный просмотр документа в целевом формате", - "Description[sk]": "Náhľad dokumentu v cieľovom formáte", - "Description[sl]": "Predogled dokumenta v ciljni obliki", - "Description[sr@ijekavian]": "Прегледајте документ у циљном формату", - "Description[sr@ijekavianlatin]": "Pregledajte dokument u ciljnom formatu", - "Description[sr@latin]": "Pregledajte dokument u ciljnom formatu", - "Description[sr]": "Прегледајте документ у циљном формату", - "Description[sv]": "Förhandsgranska dokumentet i målformatet", - "Description[uk]": "Попередній перегляд документа у форматі призначення", - "Description[x-test]": "xxPreview the document in the target formatxx", - "Description[zh_CN]": "以目标格式预览文档", - "Description[zh_TW]": "以目標格式顯示文件預覽", - "Icon": "document-preview", - "Id": "ktexteditorpreview", - "Name": "Document Preview", - "Name[ast]": "Previsualización de documentos", - "Name[ca@valencia]": "Vista prèvia de document", - "Name[ca]": "Vista prèvia de document", - "Name[cs]": "Náhled na dokument", - "Name[da]": "Forhåndsvisning af dokument", - "Name[de]": "Dokumentvorschau", - "Name[el]": "Προεπισκόπηση εγγράφου", - "Name[en_GB]": "Document Preview", - "Name[es]": "Vista previa del documento", - "Name[eu]": "Dokumentua aurreikusi", - "Name[fi]": "Asiakirjan esikatselu", - "Name[fr]": "Aperçu de document", - "Name[gl]": "Vista previa do documento", - "Name[ia]": "Vista preliminar de documento", - "Name[it]": "Anteprima del documento", - "Name[ko]": "문서 미리 보기", - "Name[nl]": "Voorbeeld van document", - "Name[nn]": "Førehandsvising av dokument", - "Name[pl]": "Podgląd dokumentu", - "Name[pt]": "Antevisão do Documento", - "Name[pt_BR]": "Visualização do documento", - "Name[ru]": "Предварительный просмотр документа", - "Name[sk]": "Náhľad dokumentu", - "Name[sl]": "Predogled dokumenta", - "Name[sr@ijekavian]": "Преглед документа", - "Name[sr@ijekavianlatin]": "Pregled dokumenta", - "Name[sr@latin]": "Pregled dokumenta", - "Name[sr]": "Преглед документа", - "Name[sv]": "Dokumentförhandsgranskning", - "Name[uk]": "Перегляд документа", - "Name[x-test]": "xxDocument Previewxx", - "Name[zh_CN]": "文档预览", - "Name[zh_TW]": "文件預覽", - "ServiceTypes": [ - "KTextEditor/Plugin", - "KDevelop/Plugin" - ] - } -} diff --git a/addons/preview/ktexteditorpreviewplugin.h b/addons/preview/ktexteditorpreviewplugin.h deleted file mode 100644 --- a/addons/preview/ktexteditorpreviewplugin.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2017 by Friedrich W. H. Kossebau - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef KTEXTEDITORPREVIEWPLUGIN_H -#define KTEXTEDITORPREVIEWPLUGIN_H - -// KF -#include - -class KTextEditorPreviewPlugin : public KTextEditor::Plugin -{ - Q_OBJECT - -public: - /** - * Default constructor, with arguments as expected by KPluginFactory - */ - KTextEditorPreviewPlugin(QObject* parent, const QVariantList& args); - - ~KTextEditorPreviewPlugin() override; - -public: // KTextEditor::Plugin API - QObject* createView(KTextEditor::MainWindow* mainWindow) override; -}; - -#endif diff --git a/addons/preview/ktexteditorpreviewplugin.cpp b/addons/preview/ktexteditorpreviewplugin.cpp deleted file mode 100644 --- a/addons/preview/ktexteditorpreviewplugin.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2017 by Friedrich W. H. Kossebau - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "ktexteditorpreviewplugin.h" - -#include "ktexteditorpreviewview.h" -#include - -// KF -#include -#include - - -K_PLUGIN_FACTORY_WITH_JSON(KTextEditorPreviewPluginFactory, "ktexteditorpreview.json", registerPlugin();) - - -KTextEditorPreviewPlugin::KTextEditorPreviewPlugin(QObject* parent, const QVariantList& /*args*/) - : KTextEditor::Plugin(parent) -{ -} - -KTextEditorPreviewPlugin::~KTextEditorPreviewPlugin() = default; - -QObject* KTextEditorPreviewPlugin::createView(KTextEditor::MainWindow* mainwindow) -{ - return new KTextEditorPreviewView(this, mainwindow); -} - - -// needed for K_PLUGIN_FACTORY_WITH_JSON -#include diff --git a/addons/preview/ktexteditorpreviewview.h b/addons/preview/ktexteditorpreviewview.h deleted file mode 100644 --- a/addons/preview/ktexteditorpreviewview.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2017 by Friedrich W. H. Kossebau - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef KTEXTEDITORPREVIEWVIEW_H -#define KTEXTEDITORPREVIEWVIEW_H - -// KF -#include -// Qt -#include -#include - -namespace KTextEditorPreview { -class PreviewWidget; -} - -namespace KTextEditor { -class MainWindow; -class View; -} - -class KTextEditorPreviewPlugin; - -class QWidget; - -class KTextEditorPreviewView: public QObject, public KTextEditor::SessionConfigInterface -{ - Q_OBJECT - Q_INTERFACES(KTextEditor::SessionConfigInterface) - -public: - KTextEditorPreviewView(KTextEditorPreviewPlugin* plugin, KTextEditor::MainWindow* mainWindow); - ~KTextEditorPreviewView() override; - - void readSessionConfig(const KConfigGroup& config) override; - void writeSessionConfig(KConfigGroup& config) override; - -private: - QPointer m_toolView; - KTextEditorPreview::PreviewWidget* m_previewView; -}; - -#endif diff --git a/addons/preview/ktexteditorpreviewview.cpp b/addons/preview/ktexteditorpreviewview.cpp deleted file mode 100644 --- a/addons/preview/ktexteditorpreviewview.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2017 by Friedrich W. H. Kossebau - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "ktexteditorpreviewview.h" - -#include "ktexteditorpreviewplugin.h" -#include "previewwidget.h" - -// KF -#include -#include - -// Qt -#include -#include - -using namespace KTextEditorPreview; - -KTextEditorPreviewView::KTextEditorPreviewView(KTextEditorPreviewPlugin* plugin, KTextEditor::MainWindow* mainWindow) - : QObject(mainWindow) -{ - Q_UNUSED(plugin); - - m_toolView = mainWindow->createToolView(plugin, QStringLiteral("ktexteditorpreviewplugin"), - KTextEditor::MainWindow::Right, - QIcon::fromTheme(QStringLiteral("document-preview")), - i18n("Preview")); - - // add preview widget - m_previewView = new PreviewWidget(plugin, mainWindow, m_toolView.data()); - m_toolView->layout()->setMargin(0); - m_toolView->layout()->addWidget(m_previewView); - m_toolView->addActions(m_previewView->actions()); -} - -KTextEditorPreviewView::~KTextEditorPreviewView() -{ - delete m_toolView; -} - -void KTextEditorPreviewView::readSessionConfig(const KConfigGroup& config) -{ - m_previewView->readSessionConfig(config); -} - -void KTextEditorPreviewView::writeSessionConfig(KConfigGroup& config) -{ - m_previewView->writeSessionConfig(config); -} diff --git a/addons/preview/previewwidget.h b/addons/preview/previewwidget.h deleted file mode 100644 --- a/addons/preview/previewwidget.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2017 by Friedrich W. H. Kossebau - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef KTEXTEDITORPREVIEW_PREVIEWWIDGET_H -#define KTEXTEDITORPREVIEW_PREVIEWWIDGET_H - -// KF -#include -// Qt -#include - -class KTextEditorPreviewPlugin; - -namespace KTextEditor { -class MainWindow; -class View; -} -class KXMLGUIFactory; -class KToggleAction; -class KConfigGroup; - -class QWidgetAction; -class QMenu; - -namespace KTextEditorPreview { -class KPartView; - -/** - * The actual widget shown in the toolview. - * - * It either shows a label "No preview available." - * or the widget of the KPart currently used to preview - * the selected document in its target format. - * - * The preview can be locked to a document by checking off the - * lock action. If locked the currently shown document will not - * be changed if another view is activated, unless the document - * itself is closed, where then the label is shown instead. - */ -class PreviewWidget: public QStackedWidget, public KXMLGUIBuilder -{ - Q_OBJECT - -public: - /** - * Constructor - * - * @param core the plugin object - * @param mainWindow the main window with all the texteditor views - * @param parent widget object taking the ownership - */ - PreviewWidget(KTextEditorPreviewPlugin* core, KTextEditor::MainWindow* mainWindow, QWidget* parent); - ~PreviewWidget() override; - - void readSessionConfig(const KConfigGroup& configGroup); - void writeSessionConfig(KConfigGroup& configGroup) const; - -public: // KXMLGUIBuilder API - QWidget* createContainer(QWidget* parent, int index, - const QDomElement& element, QAction*& containerAction) override; - void removeContainer(QWidget* container, QWidget* parent, - QDomElement& element, QAction* containerAction) override; - -protected: - void showEvent(QShowEvent* event) override; - void hideEvent(QHideEvent* event) override; - -private Q_SLOTS: - /** - * Update the widget to the currently active view. - * - * If the document lock is set, this will not change the preview. - * Otherwise the preview will switch to the document of the now active view - * and show a preview for that, unless there is no matching kpart found. - * In that case, or if there is no active view, a label will be shown with - * "No preview available". - * - * @param view the view or, if there is none, a nullptr - */ - void setTextEditorView(KTextEditor::View* view); - -private: - void toggleDocumentLocking(bool locked); - void handleLockedDocumentClosing(); - void toggleAutoUpdating(bool autoRefreshing); - void updatePreview(); - void showAboutKPartPlugin(); - -private: - KToggleAction* m_lockAction; - KToggleAction* m_autoUpdateAction; - QAction* m_updateAction; - QWidgetAction* m_kPartMenuAction; - QMenu* m_kPartMenu; - QAction* m_aboutKPartAction; - - KTextEditorPreviewPlugin* const m_core; - KTextEditor::MainWindow* const m_mainWindow; - - KTextEditor::View* m_previewedTextEditorView = nullptr; - QString m_currentServiceId; - KPartView* m_partView = nullptr; - KXMLGUIFactory* m_xmlGuiFactory; -}; - -} - -#endif diff --git a/addons/preview/previewwidget.cpp b/addons/preview/previewwidget.cpp deleted file mode 100644 --- a/addons/preview/previewwidget.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2017 by Friedrich W. H. Kossebau - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "previewwidget.h" - -#include "ktexteditorpreviewplugin.h" -#include "kpartview.h" -#include - -// KF -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Qt -#include -#include -#include -#include -#include -#include -#include - - -using namespace KTextEditorPreview; - -PreviewWidget::PreviewWidget(KTextEditorPreviewPlugin* core, KTextEditor::MainWindow* mainWindow, - QWidget* parent) - : QStackedWidget(parent) - , KXMLGUIBuilder(this) - , m_core(core) - , m_mainWindow(mainWindow) - , m_xmlGuiFactory(new KXMLGUIFactory(this, this)) -{ - m_lockAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("object-unlocked")), i18n("Lock Current Document"), this); - m_lockAction->setToolTip(i18n("Lock preview to current document")); - m_lockAction->setCheckedState(KGuiItem(i18n("Unlock Current View"), QIcon::fromTheme(QStringLiteral("object-locked")), i18n("Unlock current view"))); - m_lockAction->setChecked(false); - connect(m_lockAction, &QAction::triggered, this, &PreviewWidget::toggleDocumentLocking); - addAction(m_lockAction); - - // TODO: better icon(s) - const QIcon autoUpdateIcon = QIcon::fromTheme(QStringLiteral("media-playback-start")); - m_autoUpdateAction = new KToggleAction(autoUpdateIcon, i18n("Automatically Update Preview"), this); - m_autoUpdateAction->setToolTip(i18n("Enable automatic updates of the preview to the current document content")); - m_autoUpdateAction->setCheckedState(KGuiItem(i18n("Manually Update Preview"), autoUpdateIcon, i18n("Disable automatic updates of the preview to the current document content"))); - m_autoUpdateAction->setChecked(false); - connect(m_autoUpdateAction, &QAction::triggered, this, &PreviewWidget::toggleAutoUpdating); - addAction(m_autoUpdateAction); - - m_updateAction = new QAction(QIcon::fromTheme(QStringLiteral("view-refresh")), i18n("Update Preview"), this); - m_updateAction->setToolTip(i18n("Update the preview to the current document content")); - connect(m_updateAction, &QAction::triggered, this, &PreviewWidget::updatePreview); - m_updateAction->setEnabled(false); - addAction(m_updateAction); - - // manually prepare a proper dropdown menu button, because Qt itself does not do what one would expect - // when adding a default menu->menuAction() to a QToolbar - const auto kPartMenuIcon = QIcon::fromTheme(QStringLiteral("application-menu")); - const auto kPartMenuText = i18n("View"); - m_kPartMenu = new QMenu(this); - QToolButton* toolButton = new QToolButton(); - toolButton->setMenu(m_kPartMenu); - toolButton->setIcon(kPartMenuIcon); - toolButton->setText(kPartMenuText); - toolButton->setPopupMode(QToolButton::InstantPopup); - - m_kPartMenuAction = new QWidgetAction(this); - m_kPartMenuAction->setIcon(kPartMenuIcon); - m_kPartMenuAction->setText(kPartMenuText); - m_kPartMenuAction->setMenu(m_kPartMenu); - m_kPartMenuAction->setDefaultWidget(toolButton); - m_kPartMenuAction->setEnabled(false); - addAction(m_kPartMenuAction); - - m_aboutKPartAction = new QAction(this); - connect(m_aboutKPartAction, &QAction::triggered, this, &PreviewWidget::showAboutKPartPlugin); - m_aboutKPartAction->setEnabled(false); - - auto label = new QLabel(i18n("No preview available."), this); - label->setAlignment(Qt::AlignHCenter); - addWidget(label); - - connect(m_mainWindow, &KTextEditor::MainWindow::viewChanged, - this, &PreviewWidget::setTextEditorView); - - setTextEditorView(m_mainWindow->activeView()); -} - -PreviewWidget::~PreviewWidget() = default; - -void PreviewWidget::readSessionConfig(const KConfigGroup& configGroup) -{ - // TODO: also store document id/url and see to catch the same document on restoring config - m_lockAction->setChecked(configGroup.readEntry("documentLocked", false)); - m_autoUpdateAction->setChecked(configGroup.readEntry("automaticUpdate", false)); -} - -void PreviewWidget::writeSessionConfig(KConfigGroup& configGroup) const -{ - configGroup.writeEntry("documentLocked", m_lockAction->isChecked()); - configGroup.writeEntry("automaticUpdate", m_autoUpdateAction->isChecked()); -} - -void PreviewWidget::setTextEditorView(KTextEditor::View* view) -{ - if ((m_previewedTextEditorView == view) || - !isVisible() || - m_lockAction->isChecked()) { - return; - } - - m_previewedTextEditorView = view; - - KService::Ptr service; - if (m_previewedTextEditorView) { - // TODO: mimetype is not set for new document which have not been saved yet. - // needs another way to get this info, or perhaps some proper fix in Kate/Kdevelop - // to guess the mimetype based on current content, selected mode/highlighting etc. - // which then also would needs a signal mimetypeChanged and handling here - const auto mimeType = m_previewedTextEditorView->document()->mimeType(); - service = KMimeTypeTrader::self()->preferredService(mimeType, QStringLiteral("KParts/ReadOnlyPart")); - if (service) { - qCDebug(KTEPREVIEW) << "Found preferred kpart service named" << service->name() - << "with library" <library() - << "for mimetype" << mimeType; - - if (service->library().isEmpty()) { - qCWarning(KTEPREVIEW) << "Discarding preferred kpart service due to empty library name:" << service->name(); - service.reset(); - } - - // no interest in kparts which also just display the text (like katepart itself) - // TODO: what about parts which also support importing plain text and turning into richer format - // and thus have it in their mimetypes list? - // could that perhaps be solved by introducing the concept of "native" and "imported" mimetypes? - // or making a distinction between source editors/viewers and final editors/viewers? - // latter would also help other source editors/viewers like a hexeditor, which "supports" any mimetype - if (service && service->mimeTypes().contains(QStringLiteral("text/plain"))) { - qCDebug(KTEPREVIEW) << "Blindly discarding preferred service as it also supports text/plain, to avoid useless plain/text preview."; - service.reset(); - } - } else { - qCDebug(KTEPREVIEW) << "Found no preferred kpart service for mimetype" << mimeType; - } - } - - // change of preview type? - // TODO: find a better id than library? - const QString serviceId = service ? service->library() : QString(); - - if (serviceId != m_currentServiceId) { - if (m_partView) { - // clear kpart menu - m_xmlGuiFactory->removeClient(m_partView->kPart()); - m_kPartMenu->clear(); - - removeWidget(m_partView->widget()); - delete m_partView; - } - - m_currentServiceId = serviceId; - - if (service) { - qCDebug(KTEPREVIEW) << "Creating new kpart service instance."; - m_partView = new KPartView(service, this); - m_partView->setAutoUpdating(m_autoUpdateAction->isChecked()); - int index = addWidget(m_partView->widget()); - setCurrentIndex(index); - - // update kpart menu - const auto kPart = m_partView->kPart(); - if (kPart) { - const auto kPartDisplayName = kPart->componentData().displayName(); - m_aboutKPartAction->setText(i18n("About %1", kPartDisplayName)); - m_xmlGuiFactory->addClient(kPart); - m_kPartMenu->addSeparator(); - m_kPartMenu->addAction(m_aboutKPartAction); - } - } else { - m_partView = nullptr; - } - } else { - if (m_partView) { - qCDebug(KTEPREVIEW) << "Reusing active kpart service instance."; - } - } - - if (m_partView) { - m_partView->setDocument(m_previewedTextEditorView->document()); - } - - m_updateAction->setEnabled(m_partView && !m_autoUpdateAction->isChecked()); - const bool hasKPart = (m_partView && m_partView->kPart()); - m_kPartMenuAction->setEnabled(hasKPart); - m_aboutKPartAction->setEnabled(hasKPart); -} - -void PreviewWidget::showEvent(QShowEvent* event) -{ - Q_UNUSED(event); - - m_updateAction->setEnabled(m_partView && !m_autoUpdateAction->isChecked()); - - setTextEditorView(m_mainWindow->activeView()); -} - -void PreviewWidget::hideEvent(QHideEvent* event) -{ - Q_UNUSED(event); - - // keep active part for reuse, but close preview document - if (m_partView) { - // TODO: we also get hide event in kdevelop when the view is changed, - // need to find out how to filter this out or how to fix kdevelop - // so currently keep the preview document -// m_partView->setDocument(nullptr); - } - - m_updateAction->setEnabled(false); -} - -void PreviewWidget::toggleDocumentLocking(bool locked) -{ - if (locked) { - if (!m_partView) { - // nothing to do - return; - } - auto document = m_partView->document(); - connect(document, &KTextEditor::Document::aboutToClose, - this, &PreviewWidget::handleLockedDocumentClosing); - } else { - if (m_partView) { - auto document = m_partView->document(); - disconnect(document, &KTextEditor::Document::aboutToClose, - this, &PreviewWidget::handleLockedDocumentClosing); - } - // jump tp current view - setTextEditorView(m_mainWindow->activeView()); - } -} - -void PreviewWidget::toggleAutoUpdating(bool autoRefreshing) -{ - if (!m_partView) { - // nothing to do - return; - } - - m_updateAction->setEnabled(!autoRefreshing && isVisible()); - m_partView->setAutoUpdating(autoRefreshing); -} - -void PreviewWidget::updatePreview() -{ - m_partView->updatePreview(); -} - -void PreviewWidget::handleLockedDocumentClosing() -{ - // remove any current partview - if (m_partView) { - removeWidget(m_partView->widget()); - delete m_partView; - m_partView = nullptr; - } - - m_currentServiceId.clear(); -} - -QWidget* PreviewWidget::createContainer(QWidget* parent, int index, const QDomElement& element, QAction*& containerAction) -{ - containerAction = nullptr; - - if (element.attribute(QStringLiteral("deleted")).toLower() == QLatin1String("true")) { - return nullptr; - } - - const QString tagName = element.tagName().toLower(); - // filter out things we do not support - // TODO: consider integrating the toolbars - if (tagName == QLatin1String("mainwindow") || - tagName == QLatin1String("toolbar") || - tagName == QLatin1String("statusbar")) { - return nullptr; - } - - if (tagName == QLatin1String("menubar")) { - return m_kPartMenu; - } - - return KXMLGUIBuilder::createContainer(parent, index, element, containerAction); -} - -void PreviewWidget::removeContainer(QWidget* container, QWidget* parent, - QDomElement& element, QAction* containerAction) -{ - if (container == m_kPartMenu) { - return; - } - - KXMLGUIBuilder::removeContainer(container, parent, element, containerAction); -} - -void PreviewWidget::showAboutKPartPlugin() -{ - if (m_partView && m_partView->kPart()) { - QPointer aboutDialog = new KAboutApplicationDialog(m_partView->kPart()->componentData(), this); - aboutDialog->exec(); - delete aboutDialog; - } -}