CodePaster: Register type safe service object

Use Q_DECLARE_INTERFACE et al.
This provides a way to have the dependency on code pasting
optional in the using plugins (VCS, diff editor), while
still being able to use a nice API to perform the pasting itself.

Change-Id: Ia61e0066d552e45031f4aa7fd1f6693b68f92384
Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com>
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
This commit is contained in:
Eike Ziller
2015-06-29 14:22:17 +02:00
parent 81272a9fdb
commit ce96a8b80a
11 changed files with 135 additions and 64 deletions

View File

@@ -0,0 +1,57 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CODEPASTERSERVICE_H
#define CODEPASTERSERVICE_H
#include <QObject>
#include <QString>
namespace CodePaster {
class Service
{
public:
virtual ~Service() {}
virtual void postText(const QString &text, const QString &mimeType) = 0;
virtual void postCurrentEditor() = 0;
virtual void postClipboard() = 0;
};
} // CodePaster
QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(CodePaster::Service, "CodePaster::Service")
QT_END_NAMESPACE
#endif // CODEPASTERSERVICE_H

View File

@@ -13,7 +13,8 @@ HEADERS += cpasterplugin.h \
fileshareprotocol.h \ fileshareprotocol.h \
fileshareprotocolsettingspage.h \ fileshareprotocolsettingspage.h \
kdepasteprotocol.h \ kdepasteprotocol.h \
urlopenprotocol.h urlopenprotocol.h \
codepasterservice.h
SOURCES += cpasterplugin.cpp \ SOURCES += cpasterplugin.cpp \
settingspage.cpp \ settingspage.cpp \

View File

@@ -70,32 +70,29 @@ using namespace TextEditor;
namespace CodePaster { namespace CodePaster {
/*! /*!
\class CodePaster::CodePasterService \class CodePaster::Service
\brief The CodePasterService class is a service registered with PluginManager \brief The CodePaster::Service class is a service registered with PluginManager
that provides CodePaster \c post() functionality. that provides CodePaster \c post() functionality.
\sa ExtensionSystem::PluginManager::getObjectByClassName, ExtensionSystem::invoke
\sa VcsBase::VcsBaseEditorWidget
*/ */
CodePasterService::CodePasterService(QObject *parent) : CodePasterServiceImpl::CodePasterServiceImpl(QObject *parent) :
QObject(parent) QObject(parent)
{ {
} }
void CodePasterService::postText(const QString &text, const QString &mimeType) void CodePasterServiceImpl::postText(const QString &text, const QString &mimeType)
{ {
QTC_ASSERT(CodepasterPlugin::instance(), return); QTC_ASSERT(CodepasterPlugin::instance(), return);
CodepasterPlugin::instance()->post(text, mimeType); CodepasterPlugin::instance()->post(text, mimeType);
} }
void CodePasterService::postCurrentEditor() void CodePasterServiceImpl::postCurrentEditor()
{ {
QTC_ASSERT(CodepasterPlugin::instance(), return); QTC_ASSERT(CodepasterPlugin::instance(), return);
CodepasterPlugin::instance()->post(CodepasterPlugin::PasteEditor); CodepasterPlugin::instance()->post(CodepasterPlugin::PasteEditor);
} }
void CodePasterService::postClipboard() void CodePasterServiceImpl::postClipboard()
{ {
QTC_ASSERT(CodepasterPlugin::instance(), return); QTC_ASSERT(CodepasterPlugin::instance(), return);
CodepasterPlugin::instance()->post(CodepasterPlugin::PasteClipboard); CodepasterPlugin::instance()->post(CodepasterPlugin::PasteClipboard);
@@ -176,7 +173,7 @@ bool CodepasterPlugin::initialize(const QStringList &arguments, QString *errorMe
connect(m_fetchUrlAction, &QAction::triggered, this, &CodepasterPlugin::fetchUrl); connect(m_fetchUrlAction, &QAction::triggered, this, &CodepasterPlugin::fetchUrl);
cpContainer->addAction(command); cpContainer->addAction(command);
addAutoReleasedObject(new CodePasterService); addAutoReleasedObject(new CodePasterServiceImpl);
return true; return true;
} }

View File

@@ -31,6 +31,8 @@
#ifndef CPASTERPLUGIN_H #ifndef CPASTERPLUGIN_H
#define CPASTERPLUGIN_H #define CPASTERPLUGIN_H
#include "codepasterservice.h"
#include <extensionsystem/iplugin.h> #include <extensionsystem/iplugin.h>
#include <QStringList> #include <QStringList>
@@ -46,16 +48,17 @@ class CustomPoster;
struct Settings; struct Settings;
class Protocol; class Protocol;
class CodePasterService : public QObject class CodePasterServiceImpl : public QObject, public CodePaster::Service
{ {
Q_OBJECT Q_OBJECT
Q_INTERFACES(CodePaster::Service)
public: public:
explicit CodePasterService(QObject *parent = 0); explicit CodePasterServiceImpl(QObject *parent = 0);
public slots: public slots:
void postText(const QString &text, const QString &mimeType); void postText(const QString &text, const QString &mimeType) override;
void postCurrentEditor(); void postCurrentEditor() override;
void postClipboard(); void postClipboard() override;
}; };
class CodepasterPlugin : public ExtensionSystem::IPlugin class CodepasterPlugin : public ExtensionSystem::IPlugin

View File

@@ -9,6 +9,10 @@ QtcPlugin {
Depends { name: "Core" } Depends { name: "Core" }
Depends { name: "TextEditor" } Depends { name: "TextEditor" }
pluginRecommends: [
"CodePaster"
]
files: [ files: [
"diffeditor.cpp", "diffeditor.cpp",
"diffeditor.h", "diffeditor.h",

View File

@@ -5,3 +5,5 @@ QTC_LIB_DEPENDS += \
QTC_PLUGIN_DEPENDS += \ QTC_PLUGIN_DEPENDS += \
texteditor \ texteditor \
coreplugin coreplugin
QTC_PLUGIN_RECOMMENDS += \
cpaster

View File

@@ -56,8 +56,11 @@
#include <coreplugin/minisplitter.h> #include <coreplugin/minisplitter.h>
#include <coreplugin/patchtool.h> #include <coreplugin/patchtool.h>
#include <cpaster/codepasterservice.h>
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>
#include <utils/tooltip/tooltip.h> #include <utils/tooltip/tooltip.h>
using namespace Core; using namespace Core;
@@ -894,11 +897,14 @@ void SideBySideDiffEditorWidget::slotLeftContextMenuRequested(QMenu *menu,
int chunkIndex) int chunkIndex)
{ {
menu->addSeparator(); menu->addSeparator();
QAction *sendChunkToCodePasterAction = if (ExtensionSystem::PluginManager::getObject<CodePaster::Service>()) {
menu->addAction(tr("Send Chunk to CodePaster...")); // optional code pasting service
connect(sendChunkToCodePasterAction, &QAction::triggered, QAction *sendChunkToCodePasterAction =
this, &SideBySideDiffEditorWidget::slotSendChunkToCodePaster); menu->addAction(tr("Send Chunk to CodePaster..."));
menu->addSeparator(); connect(sendChunkToCodePasterAction, &QAction::triggered,
this, &SideBySideDiffEditorWidget::slotSendChunkToCodePaster);
menu->addSeparator();
}
QAction *applyAction = menu->addAction(tr("Apply Chunk...")); QAction *applyAction = menu->addAction(tr("Apply Chunk..."));
connect(applyAction, &QAction::triggered, this, &SideBySideDiffEditorWidget::slotApplyChunk); connect(applyAction, &QAction::triggered, this, &SideBySideDiffEditorWidget::slotApplyChunk);
applyAction->setEnabled(false); applyAction->setEnabled(false);
@@ -929,11 +935,14 @@ void SideBySideDiffEditorWidget::slotRightContextMenuRequested(QMenu *menu,
int chunkIndex) int chunkIndex)
{ {
menu->addSeparator(); menu->addSeparator();
QAction *sendChunkToCodePasterAction = if (ExtensionSystem::PluginManager::getObject<CodePaster::Service>()) {
menu->addAction(tr("Send Chunk to CodePaster...")); // optional code pasting service
connect(sendChunkToCodePasterAction, &QAction::triggered, QAction *sendChunkToCodePasterAction =
this, &SideBySideDiffEditorWidget::slotSendChunkToCodePaster); menu->addAction(tr("Send Chunk to CodePaster..."));
menu->addSeparator(); connect(sendChunkToCodePasterAction, &QAction::triggered,
this, &SideBySideDiffEditorWidget::slotSendChunkToCodePaster);
menu->addSeparator();
}
QAction *revertAction = menu->addAction(tr("Revert Chunk...")); QAction *revertAction = menu->addAction(tr("Revert Chunk..."));
connect(revertAction, &QAction::triggered, this, &SideBySideDiffEditorWidget::slotRevertChunk); connect(revertAction, &QAction::triggered, this, &SideBySideDiffEditorWidget::slotRevertChunk);
revertAction->setEnabled(false); revertAction->setEnabled(false);
@@ -961,21 +970,15 @@ void SideBySideDiffEditorWidget::slotSendChunkToCodePaster()
if (!m_document) if (!m_document)
return; return;
// Retrieve service by soft dependency.
auto pasteService = ExtensionSystem::PluginManager::getObject<CodePaster::Service>();
QTC_ASSERT(pasteService, return);
const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, false); const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, false);
if (patch.isEmpty()) if (patch.isEmpty())
return; return;
// Retrieve service by soft dependency. pasteService->postText(patch, QLatin1String(Constants::DIFF_EDITOR_MIMETYPE));
QObject *pasteService
= ExtensionSystem::PluginManager::getObjectByClassName(QLatin1String("CodePaster::CodePasterService"));
if (pasteService) {
QMetaObject::invokeMethod(pasteService, "postText",
Q_ARG(QString, patch),
Q_ARG(QString, QLatin1String(DiffEditor::Constants::DIFF_EDITOR_MIMETYPE)));
} else {
QMessageBox::information(this, tr("Unable to Paste"),
tr("Code pasting services are not available."));
}
} }
void SideBySideDiffEditorWidget::slotApplyChunk() void SideBySideDiffEditorWidget::slotApplyChunk()

View File

@@ -54,8 +54,11 @@
#include <coreplugin/patchtool.h> #include <coreplugin/patchtool.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <cpaster/codepasterservice.h>
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h>
#include <utils/tooltip/tooltip.h> #include <utils/tooltip/tooltip.h>
//static const int FILE_LEVEL = 1; //static const int FILE_LEVEL = 1;
@@ -189,10 +192,13 @@ void UnifiedDiffEditorWidget::addContextMenuActions(QMenu *menu,
menu->addSeparator(); menu->addSeparator();
menu->addSeparator(); menu->addSeparator();
QAction *sendChunkToCodePasterAction = if (ExtensionSystem::PluginManager::getObject<CodePaster::Service>()) {
menu->addAction(tr("Send Chunk to CodePaster...")); // optional code pasting service
connect(sendChunkToCodePasterAction, &QAction::triggered, QAction *sendChunkToCodePasterAction =
this, &UnifiedDiffEditorWidget::slotSendChunkToCodePaster); menu->addAction(tr("Send Chunk to CodePaster..."));
connect(sendChunkToCodePasterAction, &QAction::triggered,
this, &UnifiedDiffEditorWidget::slotSendChunkToCodePaster);
}
QAction *applyAction = menu->addAction(tr("Apply Chunk...")); QAction *applyAction = menu->addAction(tr("Apply Chunk..."));
connect(applyAction, &QAction::triggered, this, &UnifiedDiffEditorWidget::slotApplyChunk); connect(applyAction, &QAction::triggered, this, &UnifiedDiffEditorWidget::slotApplyChunk);
QAction *revertAction = menu->addAction(tr("Revert Chunk...")); QAction *revertAction = menu->addAction(tr("Revert Chunk..."));
@@ -229,23 +235,16 @@ void UnifiedDiffEditorWidget::slotSendChunkToCodePaster()
if (!m_document) if (!m_document)
return; return;
// Retrieve service by soft dependency.
auto pasteService = ExtensionSystem::PluginManager::getObject<CodePaster::Service>();
QTC_ASSERT(pasteService, return);
const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, false); const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, false);
if (patch.isEmpty()) if (patch.isEmpty())
return; return;
// Retrieve service by soft dependency. pasteService->postText(patch, QLatin1String(Constants::DIFF_EDITOR_MIMETYPE));
QObject *pasteService =
ExtensionSystem::PluginManager::getObjectByClassName(
QLatin1String("CodePaster::CodePasterService"));
if (pasteService) {
QMetaObject::invokeMethod(pasteService, "postText",
Q_ARG(QString, patch),
Q_ARG(QString, QLatin1String(DiffEditor::Constants::DIFF_EDITOR_MIMETYPE)));
} else {
QMessageBox::information(this, tr("Unable to Paste"),
tr("Code pasting services are not available."));
}
} }
void UnifiedDiffEditorWidget::slotApplyChunk() void UnifiedDiffEditorWidget::slotApplyChunk()

View File

@@ -13,6 +13,10 @@ QtcPlugin {
Depends { name: "ProjectExplorer" } Depends { name: "ProjectExplorer" }
Depends { name: "CppTools" } Depends { name: "CppTools" }
pluginRecommends: [
"CodePaster"
]
files: [ files: [
"baseannotationhighlighter.cpp", "baseannotationhighlighter.cpp",
"baseannotationhighlighter.h", "baseannotationhighlighter.h",

View File

@@ -9,3 +9,5 @@ QTC_PLUGIN_DEPENDS += \
texteditor \ texteditor \
projectexplorer \ projectexplorer \
cpptools cpptools
QTC_PLUGIN_RECOMMENDS += \
cpaster

View File

@@ -40,6 +40,7 @@
#include <coreplugin/vcsmanager.h> #include <coreplugin/vcsmanager.h>
#include <coreplugin/patchtool.h> #include <coreplugin/patchtool.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <cpaster/codepasterservice.h>
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <projectexplorer/editorconfiguration.h> #include <projectexplorer/editorconfiguration.h>
#include <projectexplorer/projectexplorer.h> #include <projectexplorer/projectexplorer.h>
@@ -953,9 +954,12 @@ void VcsBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e)
switch (d->m_parameters->type) { switch (d->m_parameters->type) {
case LogOutput: // log might have diff case LogOutput: // log might have diff
case DiffOutput: { case DiffOutput: {
menu->addSeparator(); if (ExtensionSystem::PluginManager::getObject<CodePaster::Service>()) {
connect(menu->addAction(tr("Send to CodePaster...")), &QAction::triggered, // optional code pasting service
this, &VcsBaseEditorWidget::slotPaste); menu->addSeparator();
connect(menu->addAction(tr("Send to CodePaster...")), &QAction::triggered,
this, &VcsBaseEditorWidget::slotPaste);
}
menu->addSeparator(); menu->addSeparator();
// Apply/revert diff chunk. // Apply/revert diff chunk.
const DiffChunk chunk = diffChunk(cursorForPosition(e->pos())); const DiffChunk chunk = diffChunk(cursorForPosition(e->pos()));
@@ -1472,14 +1476,9 @@ QStringList VcsBaseEditorWidget::annotationPreviousVersions(const QString &) con
void VcsBaseEditorWidget::slotPaste() void VcsBaseEditorWidget::slotPaste()
{ {
// Retrieve service by soft dependency. // Retrieve service by soft dependency.
QObject *pasteService = auto pasteService = ExtensionSystem::PluginManager::getObject<CodePaster::Service>();
ExtensionSystem::PluginManager::getObjectByClassName(QLatin1String("CodePaster::CodePasterService")); QTC_ASSERT(pasteService, return);
if (pasteService) { pasteService->postCurrentEditor();
QMetaObject::invokeMethod(pasteService, "postCurrentEditor");
} else {
QMessageBox::information(this, tr("Unable to Paste"),
tr("Code pasting services are not available."));
}
} }
void VcsBaseEditorWidget::showProgressIndicator() void VcsBaseEditorWidget::showProgressIndicator()