[kdevplatform] /: Move away from our patch export system

Aleix Pol aleixpol at kde.org
Wed May 13 02:48:09 UTC 2015


Git commit f3bf2c0dd472ee43f550399dc91997ea52a9714b by Aleix Pol.
Committed on 13/05/2015 at 02:46.
Pushed by apol into branch 'master'.

Move away from our patch export system

Use instead the Purpose framework, where I ported the reviewboard and
pastebin plugins.
Keep it as an optional dependency for now as it's not a very important
feature and Purpose is not yet released.

CCMAIL: kdevelop-devel at kde.org

M  +0    -3    plugins/CMakeLists.txt
D  +0    -7    plugins/pastebin/CMakeLists.txt
D  +0    -4    plugins/pastebin/Messages.sh
D  +0    -75   plugins/pastebin/kdevpastebin.json
D  +0    -104  plugins/pastebin/pastebinplugin.cpp
D  +0    -50   plugins/pastebin/pastebinplugin.h
M  +13   -3    plugins/patchreview/CMakeLists.txt
M  +2    -14   plugins/patchreview/patchreview.cpp
M  +0    -1    plugins/patchreview/patchreview.h
M  +28   -15   plugins/patchreview/patchreviewtoolview.cpp
M  +2    -0    plugins/patchreview/patchreviewtoolview.h
D  +0    -128  plugins/patchreview/standardpatchexport.cpp
D  +0    -53   plugins/patchreview/standardpatchexport.h
D  +0    -13   plugins/reviewboard/CMakeLists.txt
D  +0    -4    plugins/reviewboard/Messages.sh
D  +0    -22   plugins/reviewboard/debug.cpp
D  +0    -26   plugins/reviewboard/debug.h
D  +-    --    plugins/reviewboard/icons/128-apps-reviewboard.png
D  +-    --    plugins/reviewboard/icons/16-apps-reviewboard.png
D  +0    -3    plugins/reviewboard/icons/CMakeLists.txt
D  +0    -73   plugins/reviewboard/kdevreviewboard.json
D  +0    -372  plugins/reviewboard/reviewboardjobs.cpp
D  +0    -168  plugins/reviewboard/reviewboardjobs.h
D  +0    -145  plugins/reviewboard/reviewboardplugin.cpp
D  +0    -50   plugins/reviewboard/reviewboardplugin.h
D  +0    -164  plugins/reviewboard/reviewpatch.ui
D  +0    -262  plugins/reviewboard/reviewpatchdialog.cpp
D  +0    -83   plugins/reviewboard/reviewpatchdialog.h
D  +0    -15   plugins/reviewboard/tests/CMakeLists.txt
D  +0    -77   plugins/reviewboard/tests/main.cpp
M  +0    -2    vcs/CMakeLists.txt
D  +0    -28   vcs/interfaces/ipatchexporter.cpp
D  +0    -42   vcs/interfaces/ipatchexporter.h

http://commits.kde.org/kdevplatform/f3bf2c0dd472ee43f550399dc91997ea52a9714b

diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index 8640b90..94835fe 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -18,7 +18,6 @@ add_subdirectory(documentswitcher)
 add_subdirectory(patchreview)
 add_subdirectory(openwith)
 add_subdirectory(grepview)
-add_subdirectory(pastebin)
 add_subdirectory(codeutils)
 add_subdirectory(git)
 add_subdirectory(bazaar)
@@ -53,5 +52,3 @@ set_package_properties(SubversionLibrary PROPERTIES
 if(SubversionLibrary_FOUND)
     ecm_optional_add_subdirectory(subversion)
 endif()
-
-ecm_optional_add_subdirectory(reviewboard)
diff --git a/plugins/pastebin/CMakeLists.txt b/plugins/pastebin/CMakeLists.txt
deleted file mode 100644
index 878b4ad..0000000
--- a/plugins/pastebin/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-add_definitions(-DTRANSLATION_DOMAIN=\"kdevpastebin\")
-set(kdevpastebin_PART_SRCS
-    pastebinplugin.cpp
-)
-
-kdevplatform_add_plugin(kdevpastebin JSON kdevpastebin.json SOURCES ${kdevpastebin_PART_SRCS})
-target_link_libraries(kdevpastebin KDev::Vcs)
diff --git a/plugins/pastebin/Messages.sh b/plugins/pastebin/Messages.sh
deleted file mode 100644
index b78095d..0000000
--- a/plugins/pastebin/Messages.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-#$EXTRACTRC `find . -name \*.rc` `find . -name \*.ui` >> rc.cpp
-$XGETTEXT `find . -name \*.cc -o -name \*.cpp -o -name \*.h` -o $podir/kdevpastebin.pot
-#rm -f rc.cpp
diff --git a/plugins/pastebin/kdevpastebin.json b/plugins/pastebin/kdevpastebin.json
deleted file mode 100644
index c7fdf9d..0000000
--- a/plugins/pastebin/kdevpastebin.json
+++ /dev/null
@@ -1,75 +0,0 @@
-{
-    "KPlugin": {
-        "Authors": [
-            {
-                "Name": "Aleix Pol"
-            }
-        ], 
-        "Category": "Utilities", 
-        "Description": "This plugin helps you upload your patches to Pastebin service", 
-        "Description[ar]": "تساعدك هذه الملحقة على رفع رقعك إلى خدمة بيست​بن", 
-        "Description[ca]": "Aquest connector ajuda a exportar pedaços al servei Pastebin", 
-        "Description[de]": "Dieses Modul hilft Ihnen, Ihre Patches zu einen Pastebin-Dienst hochzuladen.", 
-        "Description[en_GB]": "This plugin helps you upload your patches to Pastebin service", 
-        "Description[es]": "Este complemento le ayuda a enviar parches al servicio Pastebin", 
-        "Description[fi]": "Tämä liitännäinen opastaa sinua kopioidessasi korjauksiasi Pastebin-palveluun", 
-        "Description[gl]": "Este complemento facilítalle enviar os seus parches ao servizo Pastebin", 
-        "Description[it]": "Questa estensione consente di caricare le tue patch su Pastebin", 
-        "Description[nl]": "Deze plugin helpt u om uw patches naar de Pastebin-service te uploaden", 
-        "Description[pl]": "Wtyczka ta pomaga ci wysyłać swoje łatki do usługi Pastebin", 
-        "Description[pt]": "Este 'plugin' ajuda-o a enviar as suas modificações para o serviço Pastebin", 
-        "Description[pt_BR]": "Este plugin o auxilia a enviar suas modificações para o serviço Pastebin", 
-        "Description[sk]": "Tento plugin vám pomôže nahrať vaše záplaty na službu Pastebin", 
-        "Description[sl]": "Vstavek vam pomaga pri pošiljanju popravkov na storitev Pastebin", 
-        "Description[sv]": "Det här insticksprogrammet hjälper till att ladda upp programfixar till tjänsten Pastebin", 
-        "Description[tr]": "Bu eklenti yamalarınızı Pastebin servisine yüklemenize yardımcı olur", 
-        "Description[uk]": "За допомогою цього додатка ви зможете вивантажувати ваші латки до служби Pastebin", 
-        "Description[x-test]": "xxThis plugin helps you upload your patches to Pastebin servicexx", 
-        "Description[zh_CN]": "此插件帮助您将补丁上传到 Pastebin 服务", 
-        "Icon": "edit-paste", 
-        "Id": "kdevpastebin", 
-        "License": "GPL", 
-        "Name": "Pastebin", 
-        "Name[ar]": "بيست​بن", 
-        "Name[bs]": "Pastebin", 
-        "Name[ca at valencia]": "Pastebin", 
-        "Name[ca]": "Pastebin", 
-        "Name[da]": "Pastebin", 
-        "Name[de]": "Pastebin", 
-        "Name[el]": "Pastebin", 
-        "Name[en_GB]": "Pastebin", 
-        "Name[es]": "Pastebin", 
-        "Name[et]": "Pastebin", 
-        "Name[fi]": "Pastebin", 
-        "Name[ga]": "Pastebin", 
-        "Name[gl]": "Pastebin", 
-        "Name[hu]": "Pastebin", 
-        "Name[it]": "Pastebin", 
-        "Name[kk]": "Pastebin", 
-        "Name[mr]": "पेस्टबिन", 
-        "Name[nb]": "Pastebin", 
-        "Name[nds]": "Pastebin", 
-        "Name[nl]": "Pastebin", 
-        "Name[pl]": "Pastebin", 
-        "Name[pt]": "Pastebin", 
-        "Name[pt_BR]": "Colagem", 
-        "Name[ru]": "Pastebin", 
-        "Name[sk]": "Pastebin", 
-        "Name[sl]": "Pastebin", 
-        "Name[sv]": "Pastebin", 
-        "Name[tr]": "Pastebin", 
-        "Name[ug]": "Pastebin", 
-        "Name[uk]": "Pastebin", 
-        "Name[x-test]": "xxPastebinxx", 
-        "Name[zh_CN]": "Pastebin", 
-        "Name[zh_TW]": "Pastebin", 
-        "ServiceTypes": [
-            "KDevelop/Plugin"
-        ]
-    }, 
-    "X-KDevelop-Category": "Global", 
-    "X-KDevelop-Interfaces": [
-        "org.kdevelop.IPatchExporter"
-    ], 
-    "X-KDevelop-Mode": "GUI"
-}
\ No newline at end of file
diff --git a/plugins/pastebin/pastebinplugin.cpp b/plugins/pastebin/pastebinplugin.cpp
deleted file mode 100644
index 84ce63d..0000000
--- a/plugins/pastebin/pastebinplugin.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "pastebinplugin.h"
-
-#include <QFile>
-#include <QVariantList>
-
-#include <vcs/interfaces/ipatchsource.h>
-
-#include <KIO/TransferJob>
-#include <KJobTrackerInterface>
-#include <KLocalizedString>
-#include <KMessageBox>
-#include <KPluginFactory>
-
-using namespace KDevelop;
-
-Q_LOGGING_CATEGORY(PLUGIN_PASTEBIN, "kdevplatform.plugins.pastebin")
-K_PLUGIN_FACTORY_WITH_JSON(KDevPastebinFactory, "kdevpastebin.json", registerPlugin<PastebinPlugin>();)
-
-PastebinPlugin::PastebinPlugin ( QObject* parent, const QVariantList& )
-    : IPlugin ( "kdevpastebin", parent )
-{
-    KDEV_USE_EXTENSION_INTERFACE( KDevelop::IPatchExporter )
-}
-
-PastebinPlugin::~PastebinPlugin()
-{}
-
-namespace
-{
-QByteArray urlToData(const QUrl& url)
-{
-    QByteArray ret;
-    if(url.isLocalFile()) {
-        QFile f(url.toLocalFile());
-        Q_ASSERT(f.exists());
-        bool corr=f.open(QFile::ReadOnly | QFile::Text);
-        Q_ASSERT(corr);
-        Q_UNUSED(corr);
-
-        ret = f.readAll();
-
-    } else {
-//TODO: add downloading the data
-    }
-    return ret;
-}
-}
-
-void PastebinPlugin::exportPatch(IPatchSource::Ptr source)
-{
-    qCDebug(PLUGIN_PASTEBIN) << "exporting patch to pastebin" << source->file();
-    QByteArray bytearray = "api_option=paste&api_paste_private=1&api_paste_name=kdevelop-pastebin-plugin&api_paste_expire_date=1D&api_paste_format=diff&api_dev_key=0c8b6add8e0f6d53f61fe5ce870a1afa&api_paste_code="+QUrl::toPercentEncoding(urlToData(source->file()), "/");
-
-    QUrl url("http://pastebin.com/api/api_post.php");
-
-    KIO::TransferJob *tf = KIO::http_post(url, bytearray);
-
-    tf->addMetaData("content-type","Content-Type: application/x-www-form-urlencoded");
-    connect(tf, &KIO::TransferJob::data, this, &PastebinPlugin::data);
-
-    m_result.insert(tf, QByteArray());
-    KIO::getJobTracker()->registerJob(tf);
-}
-
-void PastebinPlugin::data(KIO::Job* job, const QByteArray &data)
-{
-    QMap< KIO::Job*, QString >::iterator it = m_result.find(job);
-    Q_ASSERT(it!=m_result.end());
-    if (data.isEmpty()) {
-        if (job->error()) {
-            KMessageBox::error(0, job->errorString());
-        } else if (it->isEmpty() || it->startsWith("ERROR")) {
-            KMessageBox::error(0, *it);
-        } else {
-            QString htmlLink=QStringLiteral("<a href='%1'>%1</a>").arg(*it);
-            KMessageBox::information(0, i18nc("The parameter is the link where the patch is stored", "<qt>You can find your patch at:<br/>%1</qt>", htmlLink), QString(), QString(), KMessageBox::AllowLink | KMessageBox::Notify);
-        }
-        m_result.erase(it);
-    } else {
-        *it += data;
-    }
-}
-
-#include "pastebinplugin.moc"
diff --git a/plugins/pastebin/pastebinplugin.h b/plugins/pastebin/pastebinplugin.h
deleted file mode 100644
index c206b86..0000000
--- a/plugins/pastebin/pastebinplugin.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef KDEVPLATFORM_PLUGIN_PASTEBINPLUGIN_H
-#define KDEVPLATFORM_PLUGIN_PASTEBINPLUGIN_H
-
-#include <interfaces/iplugin.h>
-#include <vcs/interfaces/ipatchexporter.h>
-
-#include <QLoggingCategory>
-Q_DECLARE_LOGGING_CATEGORY(PLUGIN_PASTEBIN)
-
-namespace KIO {
-class Job;
-}
-
-class PastebinPlugin : public KDevelop::IPlugin, KDevelop::IPatchExporter
-{
-    Q_OBJECT
-    Q_INTERFACES( KDevelop::IPatchExporter )
-    public:
-        PastebinPlugin ( QObject* parent, const QList<QVariant>& args  );
-        virtual ~PastebinPlugin();
-
-        virtual void exportPatch(KDevelop::IPatchSource::Ptr source) override;
-
-    public slots:
-        void data(KIO::Job* job, const QByteArray &data);
-    private:
-        QMap<KIO::Job*, QString> m_result;
-};
-
-#endif
diff --git a/plugins/patchreview/CMakeLists.txt b/plugins/patchreview/CMakeLists.txt
index 1a927c0..1928db0 100644
--- a/plugins/patchreview/CMakeLists.txt
+++ b/plugins/patchreview/CMakeLists.txt
@@ -1,5 +1,13 @@
-add_definitions(-DTRANSLATION_DOMAIN=\"kdevpatchreview\")
 find_package(LibKompareDiff2 5.0 REQUIRED)
+find_package(KDEExperimentalPurpose QUIET)
+set_package_properties(KDEExperimentalPurpose PROPERTIES DESCRIPTION "EXPERIMENTAL. Support for patch sharing"
+                       URL "https://projects.kde.org/projects/playground/libs/purpose"
+                       TYPE OPTIONAL
+                      )
+
+
+
+add_definitions(-DTRANSLATION_DOMAIN=\"kdevpatchreview\")
 kde_enable_exceptions()
 include_directories(${LIBKOMPAREDIFF2_INCLUDE_DIR})
 
@@ -8,14 +16,16 @@ set(patchreview_PART_SRCS
     patchhighlighter.cpp
     patchreviewtoolview.cpp
     localpatchsource.cpp
-    standardpatchexport.cpp
 )
 
 ki18n_wrap_ui(patchreview_PART_SRCS patchreview.ui localpatchwidget.ui)
 
 kdevplatform_add_plugin(kdevpatchreview JSON kdevpatchreview.json SOURCES ${patchreview_PART_SRCS})
 target_link_libraries(kdevpatchreview KF5::IconThemes KF5::TextEditor KF5::Parts KDev::Interfaces KDev::Util KDev::Language KDev::Vcs KDev::Sublime ${LIBKOMPAREDIFF2_LIBRARIES})
-
+if (KDEExperimentalPurpose_FOUND)
+    target_compile_definitions(kdevpatchreview PRIVATE WITH_PURPOSE)
+    target_link_libraries(kdevpatchreview KDEExperimental::PurposeWidgets)
+endif()
 ########### install files ###############
 
 install(FILES kdevpatchreview.rc DESTINATION ${KXMLGUI_INSTALL_DIR}/kdevpatchreview)
diff --git a/plugins/patchreview/patchreview.cpp b/plugins/patchreview/patchreview.cpp
index f42fec0..30bb0ed 100644
--- a/plugins/patchreview/patchreview.cpp
+++ b/plugins/patchreview/patchreview.cpp
@@ -25,7 +25,6 @@
 #include <interfaces/idocument.h>
 #include <interfaces/icore.h>
 #include <interfaces/iplugincontroller.h>
-#include <interfaces/ipatchexporter.h>
 #include <interfaces/idocumentcontroller.h>
 #include <interfaces/iuicontroller.h>
 
@@ -329,12 +328,11 @@ void PatchReviewPlugin::closeReview()
         removeHighlighting();
         m_modelList.reset( 0 );
 
-        emit patchChanged();
-
         if( !dynamic_cast<LocalPatchSource*>( m_patch.data() ) ) {
             // make sure "show" button still openes the file dialog to open a custom patch file
             setPatch( new LocalPatchSource );
-        }
+        } else
+            emit patchChanged();
 
         Sublime::MainWindow* w = dynamic_cast<Sublime::MainWindow*>( ICore::self()->uiController()->activeMainWindow() );
         if( w->area()->objectName() == "review" ) {
@@ -553,16 +551,6 @@ QWidget* PatchReviewPlugin::createToolView( QWidget* parent ) {
     return new PatchReviewToolView( parent, this );
 }
 
-void PatchReviewPlugin::exporterSelected( QAction* action ) {
-    IPlugin* exporter = qobject_cast<IPlugin*>( action->data().value<QObject*>() );
-
-    if( exporter ) {
-        qCDebug(PLUGIN_PATCHREVIEW) << "exporting patch" << exporter << action->text();
-        // for git projects, m_patch will be a VCSDiffPatchSource instance
-        exporter->extension<IPatchExporter>()->exportPatch( patch() );
-    }
-}
-
 void PatchReviewPlugin::areaChanged(Sublime::Area* area)
 {
     bool reviewing = area->objectName() == "review";
diff --git a/plugins/patchreview/patchreview.h b/plugins/patchreview/patchreview.h
index d26d93f..cf122d2 100644
--- a/plugins/patchreview/patchreview.h
+++ b/plugins/patchreview/patchreview.h
@@ -96,7 +96,6 @@ private Q_SLOTS :
     void documentClosed( KDevelop::IDocument* );
     void textDocumentCreated( KDevelop::IDocument* );
     void documentSaved( KDevelop::IDocument* );
-    void exporterSelected( QAction* action );
     void closeReview();
 
 private:
diff --git a/plugins/patchreview/patchreviewtoolview.cpp b/plugins/patchreview/patchreviewtoolview.cpp
index df805cf..11dca4d 100644
--- a/plugins/patchreview/patchreviewtoolview.cpp
+++ b/plugins/patchreview/patchreviewtoolview.cpp
@@ -14,7 +14,6 @@
 #include "patchreviewtoolview.h"
 #include "localpatchsource.h"
 #include "patchreview.h"
-#include "standardpatchexport.h"
 #include "debug.h"
 #include <libkomparediff2/diffmodellist.h>
 #include <libkomparediff2/komparemodellist.h>
@@ -37,10 +36,15 @@
 
 #include <QFileInfo>
 #include <QMenu>
+#include <QJsonObject>
+#include <QJsonArray>
 
+#include <KMessageBox>
 #include <KLocalizedString>
 #include <KTextEditor/Document>
 #include <KTextEditor/View>
+#include <Purpose/AlternativesModel>
+#include <PurposeWidgets/Menu>
 
 using namespace KDevelop;
 
@@ -118,6 +122,14 @@ void PatchReviewToolView::startingNewReview()
 void PatchReviewToolView::patchChanged() {
     fillEditFromPatch();
     kompareModelChanged();
+
+    auto p = m_plugin->patch();
+#ifdef WITH_PURPOSE
+    m_exportMenu->model()->setInputData(QJsonObject {
+        { QStringLiteral("urls"), QJsonArray { p->file().toString() } },
+        { QStringLiteral("mimeType"), { QStringLiteral("text/x-patch") } },
+    });
+#endif
 }
 
 PatchReviewToolView::~PatchReviewToolView()
@@ -199,20 +211,21 @@ void PatchReviewToolView::showEditDialog() {
     m_editPatch.testsButton->setIcon( QIcon::fromTheme( "preflight-verifier" ) );
     m_editPatch.finishReview->setDefaultAction(m_plugin->finishReviewAction());
 
-    QMenu* exportMenu = new QMenu( m_editPatch.exportReview );
-    StandardPatchExport* stdactions = new StandardPatchExport( m_plugin, this );
-    stdactions->addActions( exportMenu );
-    connect(exportMenu, &QMenu::triggered, m_plugin, &PatchReviewPlugin::exporterSelected);
-
-    IPluginController* pluginManager = ICore::self()->pluginController();
-    foreach( IPlugin* p, pluginManager->allPluginsForExtension( "org.kdevelop.IPatchExporter" ) )
-    {
-        KPluginMetaData info = pluginManager->pluginInfo( p );
-        QAction* action = exportMenu->addAction( QIcon::fromTheme( info.iconName() ), info.name() );
-        action->setData( qVariantFromValue<QObject*>( p ) );
-    }
-
-    m_editPatch.exportReview->setMenu( exportMenu );
+#ifdef WITH_PURPOSE
+    m_exportMenu = new Purpose::Menu(this);
+    connect(m_exportMenu, &Purpose::Menu::finished, this, [](const QJsonObject &output, int error, const QString &message) {
+        if (error==0) {
+            KMessageBox::information(0, i18n("<qt>You can find the new request at:<br /><a href='%1'>%1</a> </qt>", output["url"].toString()),
+                                    QString(), QString(), KMessageBox::AllowLink);
+        } else {
+            QMessageBox::warning(nullptr, i18n("Error exporting"), i18n("Couldn't export the patch.\n%1", message));
+        }
+    });
+    m_exportMenu->model()->setPluginType("Export");
+    m_editPatch.exportReview->setMenu( m_exportMenu );
+#else
+    m_editPatch.exportReview->setEnabled(false);
+#endif
 
     connect( m_editPatch.previousHunk, &QToolButton::clicked, this, &PatchReviewToolView::prevHunk );
     connect( m_editPatch.nextHunk, &QToolButton::clicked, this, &PatchReviewToolView::nextHunk );
diff --git a/plugins/patchreview/patchreviewtoolview.h b/plugins/patchreview/patchreviewtoolview.h
index 415b55f..3855320 100644
--- a/plugins/patchreview/patchreviewtoolview.h
+++ b/plugins/patchreview/patchreviewtoolview.h
@@ -24,6 +24,7 @@
 namespace Sublime { class Area; }
 namespace KDevelop { class IDocument; }
 namespace KParts { class Part; }
+namespace Purpose { class Menu; }
 
 class QStandardItem;
 class KJob;
@@ -94,6 +95,7 @@ private:
     QPointer< QWidget > m_customWidget;
     QAction* m_selectAllAction;
     QAction* m_deselectAllAction;
+    Purpose::Menu* m_exportMenu;
 
     class PatchFilesModel* m_fileModel;
 public slots:
diff --git a/plugins/patchreview/standardpatchexport.cpp b/plugins/patchreview/standardpatchexport.cpp
deleted file mode 100644
index 529796b..0000000
--- a/plugins/patchreview/standardpatchexport.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "standardpatchexport.h"
-
-#include <QFileDialog>
-#include <QIcon>
-#include <QMenu>
-#include <QStandardPaths>
-
-#include <KIO/CopyJob>
-#include <KLocalizedString>
-#include <KProcess>
-#include <KToolInvocation>
-
-#include <interfaces/icore.h>
-#include <interfaces/ipatchexporter.h>
-#include <interfaces/iruncontroller.h>
-#include "patchreview.h"
-
-class StandardExporter : public KDevelop::IPatchExporter
-{
-public:
-    virtual QString name() const = 0;
-    virtual QIcon icon() const = 0;
-};
-
-class KIOExport : public StandardExporter
-{
-    virtual void exportPatch( KDevelop::IPatchSource::Ptr source ) override {
-        QUrl dest = QFileDialog::getSaveFileUrl();
-        if( !dest.isEmpty() ) { //We let KDE do the rest of the job including the notification
-            KIO::CopyJob* job = KIO::copy( source->file(), dest );
-            KIO::getJobTracker()->registerJob( job );
-        }
-    }
-
-    virtual QIcon icon() const override { return QIcon::fromTheme( "document-save" ); }
-    virtual QString name() const override { return i18n( "Save As..." ); }
-};
-
-class EMailExport : public StandardExporter
-{
-    virtual void exportPatch( KDevelop::IPatchSource::Ptr source ) override {
-        KToolInvocation::invokeMailer( QString(), QString(), QString(), QString(), QString(), QString(), QStringList() << source->file().toLocalFile() );
-    }
-
-    virtual QIcon icon() const override { return QIcon::fromTheme( "internet-mail" ); }
-    virtual QString name() const override { return i18n( "Send..." ); }
-};
-
-class TelepathyExport : public StandardExporter
-{
-public:
-    virtual void exportPatch( KDevelop::IPatchSource::Ptr source ) override {
-        KProcess::startDetached( QStringList() << "ktp-send-file" << source->file().toDisplayString(QUrl::PreferLocalFile) );
-    }
-
-    static bool isAvailable() { return !QStandardPaths::findExecutable( "ktp-send-file" ).isEmpty(); }
-    virtual QIcon icon() const override { return QIcon::fromTheme( "telepathy-kde" ); }
-    virtual QString name() const override { return i18n( "Send to contact..." ); }
-};
-
-class KompareExport : public StandardExporter
-{
-public:
-    KompareExport() {}
-
-    virtual void exportPatch( KDevelop::IPatchSource::Ptr source ) override {
-        KProcess::startDetached( QStringList("kompare") << source->baseDir().toDisplayString(QUrl::PreferLocalFile) << source->file().toDisplayString(QUrl::PreferLocalFile) );
-    }
-
-    static bool isAvailable() { return !QStandardPaths::findExecutable( "kompare" ).isEmpty(); }
-    virtual QIcon icon() const override { return QIcon::fromTheme( "kompare" ); }
-    virtual QString name() const override { return i18n( "Side view (Kompare)..." ); }
-
-};
-
-StandardPatchExport::StandardPatchExport( PatchReviewPlugin* plugin, QObject* parent )
-    : QObject( parent )
-    , m_plugin( plugin )
-{
-    m_exporters.append( new KIOExport );
-    m_exporters.append( new EMailExport );
-
-    if( KompareExport::isAvailable() ) {
-        m_exporters.append( new KompareExport );
-    }
-    if( TelepathyExport::isAvailable() ) {
-        m_exporters.append( new TelepathyExport );
-    }
-}
-
-StandardPatchExport::~StandardPatchExport() {
-    qDeleteAll( m_exporters );
-}
-
-Q_DECLARE_METATYPE( StandardExporter* );
-
-void StandardPatchExport::addActions( QMenu* m ) {
-    foreach( StandardExporter* exp, m_exporters ) {
-        QAction* act = m->addAction( exp->icon(), exp->name(), this, SLOT( runExport() ) );
-        act->setData( qVariantFromValue( exp ) );
-    }
-}
-
-void StandardPatchExport::runExport() {
-    QAction* act = qobject_cast< QAction* >( sender() );
-    StandardExporter* exp = act->data().value< StandardExporter* >();
-    exp->exportPatch( m_plugin->patch() );
-}
diff --git a/plugins/patchreview/standardpatchexport.h b/plugins/patchreview/standardpatchexport.h
deleted file mode 100644
index 430e24f..0000000
--- a/plugins/patchreview/standardpatchexport.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef KDEVPLATFORM_PLUGIN_STANDARDPATCHEXPORT_H
-#define KDEVPLATFORM_PLUGIN_STANDARDPATCHEXPORT_H
-
-#include <QObject>
-
-class QMenu;
-class QAction;
-class PatchReviewPlugin;
-class StandardExporter;
-
-/**
- * This class contains the minimum patch export interfaces that we won't want to have
- * as a plugin like the save as and the send by e-mail
- */
-
-class StandardPatchExport : public QObject
-{
-    Q_OBJECT
-public:
-    StandardPatchExport( PatchReviewPlugin* plugin, QObject* parent = 0 );
-    virtual ~StandardPatchExport();
-
-    void addActions( QMenu* m );
-
-public slots:
-    void runExport();
-
-private:
-    PatchReviewPlugin* m_plugin;
-    QList<StandardExporter*> m_exporters;
-};
-
-#endif // KDEVPLATFORM_PLUGIN_STANDARDPATCHEXPORT_H
diff --git a/plugins/reviewboard/CMakeLists.txt b/plugins/reviewboard/CMakeLists.txt
deleted file mode 100644
index 06cdc5e..0000000
--- a/plugins/reviewboard/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-add_definitions(-DTRANSLATION_DOMAIN=\"kdevreviewboard\")
-add_subdirectory(icons)
-add_subdirectory(tests)
-
-set(kdevreviewboard_PART_SRCS
-    reviewboardplugin.cpp
-    reviewpatchdialog.cpp
-    reviewboardjobs.cpp
-    debug.cpp
-)
-ki18n_wrap_ui(kdevreviewboard_PART_SRCS reviewpatch.ui)
-kdevplatform_add_plugin(kdevreviewboard JSON kdevreviewboard.json SOURCES ${kdevreviewboard_PART_SRCS})
-target_link_libraries(kdevreviewboard KDev::Interfaces KDev::Vcs KF5::I18n Qt5::Core)
diff --git a/plugins/reviewboard/Messages.sh b/plugins/reviewboard/Messages.sh
deleted file mode 100644
index 4b13032..0000000
--- a/plugins/reviewboard/Messages.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-$EXTRACTRC `find . -name \*.rc` `find . -name \*.ui` >> rc.cpp
-$XGETTEXT `find . -not -path \*/tests/\* -name \*.cpp -o -name \*.cc -o -name \*.h` -o $podir/kdevreviewboard.pot
-rm -f rc.cpp
diff --git a/plugins/reviewboard/debug.cpp b/plugins/reviewboard/debug.cpp
deleted file mode 100644
index dc57483..0000000
--- a/plugins/reviewboard/debug.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * This file is part of KDevelop
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "debug.h"
-
-Q_LOGGING_CATEGORY(PLUGIN_REVIEWBOARD, "kdevplatform.plugins.reviewboard")
diff --git a/plugins/reviewboard/debug.h b/plugins/reviewboard/debug.h
deleted file mode 100644
index 9c2ee73..0000000
--- a/plugins/reviewboard/debug.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This file is part of KDevelop
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef KDEVPLATFORM_REVIEWBOARD_DEBUG_H
-#define KDEVPLATFORM_REVIEWBOARD_DEBUG_H
-
-#include <QLoggingCategory>
-Q_DECLARE_LOGGING_CATEGORY(PLUGIN_REVIEWBOARD)
-
-#endif
diff --git a/plugins/reviewboard/icons/128-apps-reviewboard.png b/plugins/reviewboard/icons/128-apps-reviewboard.png
deleted file mode 100644
index 6da63ae..0000000
Binary files a/plugins/reviewboard/icons/128-apps-reviewboard.png and /dev/null differ
diff --git a/plugins/reviewboard/icons/16-apps-reviewboard.png b/plugins/reviewboard/icons/16-apps-reviewboard.png
deleted file mode 100644
index 2c134bc..0000000
Binary files a/plugins/reviewboard/icons/16-apps-reviewboard.png and /dev/null differ
diff --git a/plugins/reviewboard/icons/CMakeLists.txt b/plugins/reviewboard/icons/CMakeLists.txt
deleted file mode 100644
index e694486..0000000
--- a/plugins/reviewboard/icons/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-ecm_install_icons(ICONS 16-apps-reviewboard.png 128-apps-reviewboard.png
-                  DESTINATION ${ICON_INSTALL_DIR}
-                  THEME hicolor)
diff --git a/plugins/reviewboard/kdevreviewboard.json b/plugins/reviewboard/kdevreviewboard.json
deleted file mode 100644
index a102f66..0000000
--- a/plugins/reviewboard/kdevreviewboard.json
+++ /dev/null
@@ -1,73 +0,0 @@
-{
-    "KPlugin": {
-        "Authors": [
-            {
-                "Name": "Aleix Pol"
-            }
-        ], 
-        "Category": "Utilities", 
-        "Description": "ReviewBoard integration for KDevelop", 
-        "Description[ar]": "تكامل لوحة المراجعات بمطوّرك", 
-        "Description[ca]": "Integració de ReviewBoard (Taula de revisió) pel KDevelop", 
-        "Description[de]": "ReviewBoard-Integration für KDevelop", 
-        "Description[en_GB]": "ReviewBoard integration for KDevelop", 
-        "Description[es]": "Integración de ReviewBoard para KDevelop", 
-        "Description[fi]": "ReviewBoard-integrointi KDevelop-ympäristöön", 
-        "Description[gl]": "Integración do ReviewBoard para KDevelop", 
-        "Description[it]": "Integrazione ReviewBoard per KDevelop", 
-        "Description[nl]": "ReviewBoard-integratie voor KDevelop", 
-        "Description[pl]": "Integracja tablic przeglądu dla KDevelop", 
-        "Description[pt]": "Integração do ReviewBoard no KDevelop", 
-        "Description[pt_BR]": "Integração do ReviewBoard para o KDevelop", 
-        "Description[sk]": "Integrácia ReviewBoard pre KDevelop", 
-        "Description[sl]": "Vgradnja orodja ReviewBoard v KDevelop", 
-        "Description[sv]": "Integrering av Reviewboard i KDevelop", 
-        "Description[tr]": "KDevelop için ReviewBoard tümleştirmesi", 
-        "Description[uk]": "Інтеграція ReviewBoard з KDevelop", 
-        "Description[x-test]": "xxReviewBoard integration for KDevelopxx", 
-        "Description[zh_CN]": "KDevelop 的 ReviewBoard 集成", 
-        "Icon": "reviewboard", 
-        "Id": "kdevreviewboard", 
-        "License": "GPL", 
-        "Name": "ReviewBoard", 
-        "Name[ar]": "لوحة المراجعات", 
-        "Name[bs]": "ReviewBoard", 
-        "Name[ca at valencia]": "ReviewBoard", 
-        "Name[ca]": "Taula de revisió", 
-        "Name[da]": "ReviewBoard", 
-        "Name[de]": "ReviewBoard", 
-        "Name[el]": "ReviewBoard", 
-        "Name[en_GB]": "ReviewBoard", 
-        "Name[es]": "ReviewBoard", 
-        "Name[et]": "ReviewBoard", 
-        "Name[fi]": "ReviewBoard", 
-        "Name[gl]": "ReviewBoard", 
-        "Name[hu]": "ReviewBoard", 
-        "Name[it]": "ReviewBoard", 
-        "Name[kk]": "ReviewBoard", 
-        "Name[nb]": "ReviewBoard", 
-        "Name[nds]": "ReviewBoard", 
-        "Name[nl]": "ReviewBoard", 
-        "Name[pl]": "Tablica przeglądowa", 
-        "Name[pt]": "ReviewBoard", 
-        "Name[pt_BR]": "ReviewBoard", 
-        "Name[ru]": "ReviewBoard", 
-        "Name[sk]": "ReviewBoard", 
-        "Name[sl]": "ReviewBoard", 
-        "Name[sv]": "Reviewboard", 
-        "Name[tr]": "Gözden Geçirme Tahtası", 
-        "Name[ug]": "ReviewBoard", 
-        "Name[uk]": "ReviewBoard", 
-        "Name[x-test]": "xxReviewBoardxx", 
-        "Name[zh_CN]": "ReviewBoard", 
-        "Name[zh_TW]": "ReviewBoard", 
-        "ServiceTypes": [
-            "KDevelop/Plugin"
-        ]
-    }, 
-    "X-KDevelop-Category": "Global", 
-    "X-KDevelop-Interfaces": [
-        "org.kdevelop.IPatchExporter"
-    ], 
-    "X-KDevelop-Mode": "GUI"
-}
\ No newline at end of file
diff --git a/plugins/reviewboard/reviewboardjobs.cpp b/plugins/reviewboard/reviewboardjobs.cpp
deleted file mode 100644
index 1c4a5e7..0000000
--- a/plugins/reviewboard/reviewboardjobs.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "reviewboardjobs.h"
-#include "debug.h"
-
-#include <interfaces/icore.h>
-#include <interfaces/iruncontroller.h>
-
-#include <QFile>
-#include <QJsonDocument>
-#include <QMimeDatabase>
-#include <QMimeType>
-#include <QNetworkReply>
-#include <QNetworkRequest>
-#include <QUrlQuery>
-
-#include <KLocalizedString>
-#include <KRandom>
-
-using namespace ReviewBoard;
-
-QByteArray ReviewBoard::urlToData(const QUrl& url)
-{
-    QByteArray ret;
-    if (url.isLocalFile()) {
-        QFile f(url.toLocalFile());
-        Q_ASSERT(f.exists());
-        bool corr=f.open(QFile::ReadOnly | QFile::Text);
-        Q_ASSERT(corr);
-        Q_UNUSED(corr);
-
-        ret = f.readAll();
-
-    } else {
-//TODO: add downloading the data
-    }
-    return ret;
-}
-namespace
-{
-static const QByteArray m_boundary = "----------" + KRandom::randomString( 42 + 13 ).toLatin1();
-
-QByteArray multipartFormData(const QList<QPair<QString, QVariant> >& values)
-{
-    QByteArray form_data;
-    foreach(const auto& val, values)
-    {
-        QByteArray hstr("--");
-        hstr += m_boundary;
-        hstr += "\r\n";
-        hstr += "Content-Disposition: form-data; name=\"";
-        hstr += val.first.toLatin1();
-        hstr += "\"";
-
-        //File
-        if (val.second.type()==QVariant::Url) {
-            QUrl path=val.second.toUrl();
-            hstr += "; filename=\"" + path.fileName().toLatin1() + "\"";
-            const QMimeType mime = QMimeDatabase().mimeTypeForUrl(path);
-            if (!mime.name().isEmpty()) {
-                hstr += "\r\nContent-Type: ";
-                hstr += mime.name().toLatin1().constData();
-            }
-        }
-        //
-
-        hstr += "\r\n\r\n";
-
-        // append body
-        form_data.append(hstr);
-        if (val.second.type()==QVariant::Url)
-            form_data += urlToData(val.second.toUrl());
-        else
-            form_data += val.second.toByteArray();
-        form_data.append("\r\n");
-        //EOFILE
-    }
-
-    form_data += QByteArray("--" + m_boundary + "--\r\n");
-
-    return form_data;
-}
-
-QByteArray multipartFormData(const QVariantMap& values)
-{
-    QList<QPair<QString, QVariant> > vals;
-    for(QVariantMap::const_iterator it = values.constBegin(), itEnd = values.constEnd(); it!=itEnd; ++it) {
-        vals += qMakePair<QString, QVariant>(it.key(), it.value());
-    }
-    return multipartFormData(vals);
-}
-
-}
-
-HttpCall::HttpCall(const QUrl& s, const QString& apiPath, const QList<QPair<QString,QString> >& queryParameters, Method method, const QByteArray& post, bool multipart, QObject* parent)
-    : KJob(parent)
-    , m_reply(nullptr)
-    , m_post(post)
-    , m_multipart(multipart)
-    , m_method(method)
-{
-    m_requrl=s;
-    m_requrl.setPath(m_requrl.path() + '/' + apiPath);
-    QUrlQuery query;
-    for(QList<QPair<QString,QString> >::const_iterator i = queryParameters.begin(); i < queryParameters.end(); i++) {
-        query.addQueryItem(i->first, i->second);
-    }
-    m_requrl.setQuery(query);
-}
-
-void HttpCall::start()
-{
-    QNetworkRequest r(m_requrl);
-
-    if(!m_requrl.userName().isEmpty()) {
-        QByteArray head = "Basic " + m_requrl.userInfo().toLatin1().toBase64();
-        r.setRawHeader("Authorization", head);
-    }
-
-    if(m_multipart) {
-        r.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
-        r.setHeader(QNetworkRequest::ContentLengthHeader, QString::number(m_post.size()));
-        r.setRawHeader( "Content-Type", "multipart/form-data; boundary=" + m_boundary );
-    }
-
-    switch(m_method) {
-        case Get:
-            m_reply=m_manager.get(r);
-            break;
-        case Post:
-            m_reply=m_manager.post(r, m_post);
-            break;
-        case Put:
-            m_reply=m_manager.put(r, m_post);
-            break;
-    }
-    connect(m_reply, &QNetworkReply::finished, this, &HttpCall::onFinished);
-
-//     qCDebug(PLUGIN_REVIEWBOARD) << "starting... requrl=" << m_requrl << "post=" << m_post;
-}
-
-QVariant HttpCall::result() const
-{
-    Q_ASSERT(m_reply->isFinished());
-    return m_result;
-}
-
-void HttpCall::onFinished()
-{
-    if (m_reply->error()) {
-        setError(55);
-        setErrorText(i18n("Error %1 while accessing %2", m_reply->error(), m_reply->request().url().toDisplayString()));
-        emitResult();
-        return;
-    }
-    QByteArray receivedData = m_reply->readAll();
-    QJsonParseError error;
-    QJsonDocument parser = QJsonDocument::fromJson(receivedData, &error);
-    const QVariant output = parser.toVariant();
-
-    if (error.error == 0) {
-        m_result = output;
-    } else {
-        setError(1);
-        setErrorText(i18n("JSON error: %1", error.errorString()));
-    }
-
-    if (output.toMap().value("stat").toString()!="ok") {
-        setError(2);
-        setErrorText(i18n("Request Error: %1", output.toMap().value("err").toMap().value("msg").toString()));
-    }
-
-    qCDebug(PLUGIN_REVIEWBOARD) << "parsing..." << receivedData;
-    emitResult();
-}
-
-NewRequest::NewRequest(const QUrl& server, const QString& projectPath, QObject* parent)
-    : ReviewRequest(server, 0, parent), m_project(projectPath)
-{
-    m_newreq = new HttpCall(this->server(), "/api/review-requests/", {}, HttpCall::Post, "repository="+projectPath.toLatin1(), false, this);
-    connect(m_newreq, &HttpCall::finished, this, &NewRequest::done);
-}
-
-void NewRequest::start()
-{
-    m_newreq->start();
-}
-
-void NewRequest::done()
-{
-    if (m_newreq->error()) {
-        qCDebug(PLUGIN_REVIEWBOARD) << "Could not create the new request" << m_newreq->errorString();
-        setError(2);
-        setErrorText(i18n("Could not create the new request:\n%1", m_newreq->errorString()));
-    } else {
-        QVariant res = m_newreq->result();
-        setRequestId(res.toMap()["review_request"].toMap()["id"].toString());
-        Q_ASSERT(!requestId().isEmpty());
-    }
-
-    emitResult();
-}
-
-
-SubmitPatchRequest::SubmitPatchRequest(const QUrl& server, const QUrl& patch, const QString& basedir, const QString& id, QObject* parent)
-    : ReviewRequest(server, id, parent), m_patch(patch), m_basedir(basedir)
-{
-    QList<QPair<QString, QVariant> > vals;
-    vals += QPair<QString, QVariant>("basedir", m_basedir);
-    vals += QPair<QString, QVariant>("path", qVariantFromValue<QUrl>(m_patch));
-
-    m_uploadpatch = new HttpCall(this->server(), "/api/review-requests/"+requestId()+"/diffs/", {}, HttpCall::Post, multipartFormData(vals), true, this);
-    connect(m_uploadpatch, &HttpCall::finished, this, &SubmitPatchRequest::done);
-}
-
-void SubmitPatchRequest::start()
-{
-    m_uploadpatch->start();
-}
-
-void SubmitPatchRequest::done()
-{
-    if (m_uploadpatch->error()) {
-        qCDebug(PLUGIN_REVIEWBOARD) << "Could not upload the patch" << m_uploadpatch->errorString();
-        setError(3);
-        setErrorText(i18n("Could not upload the patch"));
-    }
-
-    emitResult();
-}
-
-ProjectsListRequest::ProjectsListRequest(const QUrl& server, QObject* parent)
-    : KJob(parent), m_server(server)
-{
-}
-
-void ProjectsListRequest::start()
-{
-    requestRepositoryList(0);
-}
-
-QVariantList ProjectsListRequest::repositories() const
-{
-    return m_repositories;
-}
-
-void ProjectsListRequest::requestRepositoryList(int startIndex)
-{
-    QList<QPair<QString,QString> > repositoriesParameters;
-
-    // In practice, the web API will return at most 200 repos per call, so just hardcode that value here
-    repositoriesParameters << qMakePair<QString,QString>(QStringLiteral("max-results"), QStringLiteral("200"));
-    repositoriesParameters << qMakePair<QString,QString>(QStringLiteral("start"), QString::number(startIndex));
-
-    HttpCall* repositoriesCall = new HttpCall(m_server, "/api/repositories/", repositoriesParameters, HttpCall::Get, "", false, this);
-    connect(repositoriesCall, &HttpCall::finished, this, &ProjectsListRequest::done);
-
-    repositoriesCall->start();
-}
-
-void ProjectsListRequest::done(KJob* job)
-{
-    // TODO error
-    // TODO max iterations
-    HttpCall* repositoriesCall = qobject_cast<HttpCall*>(job);
-    QMap<QString, QVariant> resultMap = repositoriesCall->result().toMap();
-    const int totalResults = repositoriesCall->result().toMap()["total_results"].toInt();
-    m_repositories << repositoriesCall->result().toMap()["repositories"].toList();
-
-    if (m_repositories.count() < totalResults) {
-        requestRepositoryList(m_repositories.count());
-    } else {
-        emitResult();
-    }
-}
-
-ReviewListRequest::ReviewListRequest(const QUrl& server, const QString& user, const QString& reviewStatus, QObject* parent)
-    : KJob(parent), m_server(server), m_user(user), m_reviewStatus(reviewStatus)
-{
-}
-
-void ReviewListRequest::start()
-{
-    requestReviewList(0);
-}
-
-QVariantList ReviewListRequest::reviews() const
-{
-    return m_reviews;
-}
-
-void ReviewListRequest::requestReviewList(int startIndex)
-{
-    QList<QPair<QString,QString> > reviewParameters;
-
-    // In practice, the web API will return at most 200 repos per call, so just hardcode that value here
-    reviewParameters << qMakePair<QString,QString>(QStringLiteral("max-results"), QStringLiteral("200"));
-    reviewParameters << qMakePair<QString,QString>(QStringLiteral("start"), QString::number(startIndex));
-    reviewParameters << qMakePair<QString,QString>(QStringLiteral("from-user"), m_user);
-    reviewParameters << qMakePair<QString,QString>(QStringLiteral("status"), m_reviewStatus);
-
-    HttpCall* reviewsCall = new HttpCall(m_server, "/api/review-requests/", reviewParameters, HttpCall::Get, "", false, this);
-    connect(reviewsCall, &HttpCall::finished, this, &ReviewListRequest::done);
-
-    reviewsCall->start();
-}
-
-void ReviewListRequest::done(KJob* job)
-{
-    // TODO error
-    // TODO max iterations
-    if (job->error()) {
-        qCDebug(PLUGIN_REVIEWBOARD) << "Could not get reviews list" << job->errorString();
-        setError(3);
-        setErrorText(i18n("Could not get reviews list"));
-        emitResult();
-    }
-
-    HttpCall* reviewsCall = qobject_cast<HttpCall*>(job);
-    QMap<QString, QVariant> resultMap = reviewsCall->result().toMap();
-    const int totalResults = resultMap["total_results"].toInt();
-
-    m_reviews << resultMap["review_requests"].toList();
-
-    if (m_reviews.count() < totalResults) {
-        requestReviewList(m_reviews.count());
-    } else {
-        emitResult();
-    }
-}
-
-UpdateRequest::UpdateRequest(const QUrl& server, const QString& id, const QVariantMap& newValues, QObject* parent)
-    : ReviewRequest(server, id, parent)
-{
-    m_req = new HttpCall(this->server(), "/api/review-requests/"+id+"/draft/", {}, HttpCall::Put, multipartFormData(newValues), true, this);
-    connect(m_req, &HttpCall::finished, this, &UpdateRequest::done);
-}
-
-void UpdateRequest::start()
-{
-    m_req->start();
-}
-
-void UpdateRequest::done()
-{
-    if (m_req->error()) {
-        qCWarning(PLUGIN_REVIEWBOARD) << "Could not set all metadata to the review" << m_req->errorString() << m_req->property("result");
-        setError(3);
-        setErrorText(i18n("Could not set metadata"));
-    }
-
-    emitResult();
-}
-
diff --git a/plugins/reviewboard/reviewboardjobs.h b/plugins/reviewboard/reviewboardjobs.h
deleted file mode 100644
index 1c18915..0000000
--- a/plugins/reviewboard/reviewboardjobs.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef KDEVPLATFORM_PLUGIN_REVIEWBOARDJOBS_H
-#define KDEVPLATFORM_PLUGIN_REVIEWBOARDJOBS_H
-
-#include <QList>
-#include <QNetworkAccessManager>
-#include <QPair>
-#include <QUrl>
-
-#include <KJob>
-
-class QNetworkReply;
-
-namespace ReviewBoard
-{
-    /**
-     * Http call to the specified service.
-     * Converts returned json data to a QVariant to be used from actual API calls
-     *
-     * @note It is reviewboard-agnostic.
-     */
-    class HttpCall : public KJob
-    {
-        Q_OBJECT
-        Q_PROPERTY(QVariant result READ result);
-        public:
-            enum Method { Get, Put, Post };
-
-            HttpCall(const QUrl& s, const QString& apiPath, const QList<QPair<QString,QString> >& queryParameters, Method m, const QByteArray& post, bool multipart, QObject* parent);
-
-            virtual void start() override;
-
-            QVariant result() const;
-
-        private slots:
-            void onFinished();
-
-        private:
-            QVariant m_result;
-            QNetworkReply* m_reply;
-            QUrl m_requrl;
-            QByteArray m_post;
-
-            QNetworkAccessManager m_manager;
-            bool m_multipart;
-            Method m_method;
-    };
-
-    class ReviewRequest : public KJob
-    {
-        Q_OBJECT
-        public:
-            ReviewRequest(const QUrl& server, const QString& id, QObject* parent)
-                          : KJob(parent), m_server(server), m_id(id) {}
-            QString requestId() const { return m_id; }
-            void setRequestId(QString id) { m_id = id; }
-            QUrl server() const { return m_server; }
-
-        private:
-            QUrl m_server;
-            QString m_id;
-    };
-
-    class NewRequest : public ReviewRequest
-    {
-        Q_OBJECT
-        public:
-            NewRequest(const QUrl& server, const QString& project, QObject* parent = 0);
-            virtual void start() override;
-
-        private slots:
-            void done();
-
-        private:
-            HttpCall* m_newreq;
-            QString m_project;
-    };
-
-    class UpdateRequest : public ReviewRequest
-    {
-        Q_OBJECT
-        public:
-            UpdateRequest(const QUrl& server, const QString& id, const QVariantMap& newValues, QObject* parent = nullptr);
-            virtual void start() override;
-
-        private slots:
-            void done();
-
-        private:
-            HttpCall* m_req;
-            QString m_project;
-    };
-
-    class SubmitPatchRequest : public ReviewRequest
-    {
-        Q_OBJECT
-        public:
-            SubmitPatchRequest(const QUrl &server, const QUrl& patch, const QString& basedir, const QString& id, QObject* parent = 0);
-            virtual void start() override;
-
-        private slots:
-            void done();
-
-        private:
-            HttpCall* m_uploadpatch;
-            QUrl m_patch;
-            QString m_basedir;
-    };
-
-    class ProjectsListRequest : public KJob
-    {
-        Q_OBJECT
-        public:
-            ProjectsListRequest(const QUrl &server, QObject* parent = 0);
-            virtual void start() override;
-            QVariantList repositories() const;
-
-        private slots:
-            void requestRepositoryList(int startIndex);
-            void done(KJob* done);
-
-        private:
-            QUrl m_server;
-            QVariantList m_repositories;
-    };
-
-    class ReviewListRequest : public KJob
-    {
-        Q_OBJECT
-        public:
-            ReviewListRequest(const QUrl& server, const QString& user, const QString& reviewStatus, QObject* parent = 0);
-            virtual void start() override;
-            QVariantList reviews() const;
-
-        private slots:
-            void requestReviewList(int startIndex);
-            void done(KJob* done);
-
-        private:
-            QUrl m_server;
-            QString m_user;
-            QString m_reviewStatus;
-            QVariantList m_reviews;
-    };
-
-    QByteArray urlToData(const QUrl&);
-}
-
-#endif
diff --git a/plugins/reviewboard/reviewboardplugin.cpp b/plugins/reviewboard/reviewboardplugin.cpp
deleted file mode 100644
index a12df05..0000000
--- a/plugins/reviewboard/reviewboardplugin.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "reviewboardplugin.h"
-
-#include <QDialog>
-#include <QUrl>
-#include <QVariantList>
-
-#include <KConfigGroup>
-#include <KLocalizedString>
-#include <KMessageBox>
-#include <KPluginFactory>
-
-#include <interfaces/icore.h>
-#include <interfaces/iruncontroller.h>
-#include <interfaces/iprojectcontroller.h>
-#include <interfaces/iproject.h>
-#include <vcs/interfaces/ibasicversioncontrol.h>
-#include <vcs/interfaces/ipatchsource.h>
-#include <vcs/vcsjob.h>
-
-#include "reviewpatchdialog.h"
-#include "reviewboardjobs.h"
-#include "debug.h"
-
-using namespace KDevelop;
-
-typedef QPair<QString, QVariant> VariantPair;
-Q_DECLARE_METATYPE(QList<VariantPair>);
-
-K_PLUGIN_FACTORY_WITH_JSON(KDevReviewBoardFactory, "kdevreviewboard.json", registerPlugin<ReviewBoardPlugin>(); )
-
-ReviewBoardPlugin::ReviewBoardPlugin ( QObject* parent, const QVariantList& )
-    : IPlugin ( "kdevreviewboard", parent )
-{
-    KDEV_USE_EXTENSION_INTERFACE( KDevelop::IPatchExporter )
-}
-
-ReviewBoardPlugin::~ReviewBoardPlugin()
-{}
-
-void ReviewBoardPlugin::exportPatch(IPatchSource::Ptr source)
-{
-    QUrl dirUrl = source->baseDir();
-    m_source = source;
-    ReviewPatchDialog d(dirUrl);
-
-    IProject* p = ICore::self()->projectController()->findProjectForUrl(dirUrl.adjusted(QUrl::StripTrailingSlash));
-
-    if(p) {
-        KConfigGroup versionedConfig = p->projectConfiguration()->group("ReviewBoard");
-
-        if(versionedConfig.hasKey("server")) d.setServer(versionedConfig.readEntry<QUrl>("server", QUrl()));
-        if(versionedConfig.hasKey("username")) d.setUsername(versionedConfig.readEntry("username", QString()));
-        if(versionedConfig.hasKey("baseDir")) d.setBaseDir(versionedConfig.readEntry("baseDir", "/"));
-        if(versionedConfig.hasKey("repository")) d.setRepository(versionedConfig.readEntry("repository", QString()));
-    }
-
-    int ret = d.exec();
-    if(ret==QDialog::Accepted) {
-        KJob* job;
-        if (d.isUpdateReview()) {
-            job=new ReviewBoard::SubmitPatchRequest(d.server(), source->file(), d.baseDir(), d.review());
-            connect(job, &KJob::finished, this, &ReviewBoardPlugin::reviewDone);
-        } else {
-            job=new ReviewBoard::NewRequest(d.server(), d.repository());
-            job->setProperty("extraData", d.extraData());
-            connect(job, &KJob::finished, this, &ReviewBoardPlugin::reviewCreated);
-        }
-        job->setProperty("baseDir", d.baseDir());
-
-        job->start();
-
-        if(p) {
-            KConfigGroup versionedConfig = p->projectConfiguration()->group("ReviewBoard");
-
-            // We store username in a diferent field. Unset it from server.
-            QUrl storeServer(d.server());
-            storeServer.setUserName(QString());
-            // Don't store password in plaintext inside .kdev4
-            storeServer.setPassword(QString());
-
-            versionedConfig.writeEntry<QUrl>("server", storeServer);
-            versionedConfig.writeEntry("username", d.username());
-            versionedConfig.writeEntry("baseDir", d.baseDir());
-            versionedConfig.writeEntry("repository", d.repository());
-        }
-    }
-}
-
-void ReviewBoardPlugin::reviewDone(KJob* j)
-{
-    if(j->error()==0) {
-        ReviewBoard::SubmitPatchRequest const * job = qobject_cast<ReviewBoard::SubmitPatchRequest*>(j);
-        QUrl url = job->server();
-        url.setUserInfo(QString());
-        QString requrl = QStringLiteral("%1/r/%2/").arg(url.toDisplayString(QUrl::PreferLocalFile)).arg(job->requestId());
-
-        KMessageBox::information(0, i18n("<qt>You can find the new request at:<br /><a href='%1'>%1</a> </qt>", requrl),
-                                    QString(), QString(), KMessageBox::AllowLink);
-    } else {
-        KMessageBox::error(0, j->errorText());
-    }
-}
-
-void ReviewBoardPlugin::reviewCreated(KJob* j)
-{
-    if (j->error()==0) {
-        ReviewBoard::NewRequest const * job = qobject_cast<ReviewBoard::NewRequest*>(j);
-
-        //This will provide things like groups and users for review from .reviewboardrc
-        QVariantMap extraData = job->property("extraData").toMap();
-        if (!extraData.isEmpty()) {
-            KJob* updateJob = new ReviewBoard::UpdateRequest(job->server(), job->requestId(), extraData);
-            updateJob->start();
-        }
-
-        // for git projects, m_source will be a VCSDiffPatchSource instance
-        ReviewBoard::SubmitPatchRequest* submitPatchJob=new ReviewBoard::SubmitPatchRequest(job->server(), m_source->file(), j->property("baseDir").toString(), job->requestId());
-        connect(submitPatchJob, &ReviewBoard::SubmitPatchRequest::finished, this, &ReviewBoardPlugin::reviewDone);
-        submitPatchJob->start();
-    } else {
-        KMessageBox::error(0, j->errorText());
-    }
-}
-
-#include "reviewboardplugin.moc"
diff --git a/plugins/reviewboard/reviewboardplugin.h b/plugins/reviewboard/reviewboardplugin.h
deleted file mode 100644
index 821f92c..0000000
--- a/plugins/reviewboard/reviewboardplugin.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef KDEVPLATFORM_PLUGIN_REVIEWBOARDPLUGIN_H
-#define KDEVPLATFORM_PLUGIN_REVIEWBOARDPLUGIN_H
-
-#include <interfaces/iplugin.h>
-#include <vcs/interfaces/ipatchexporter.h>
-
-class KJob;
-namespace KIO {
-class Job;
-}
-
-class ReviewBoardPlugin : public KDevelop::IPlugin, KDevelop::IPatchExporter
-{
-    Q_OBJECT
-    Q_INTERFACES( KDevelop::IPatchExporter )
-    public:
-        ReviewBoardPlugin(QObject* parent, const QList<QVariant>& args);
-        virtual ~ReviewBoardPlugin();
-
-        virtual void exportPatch(KDevelop::IPatchSource::Ptr source) override;
-
-    public slots:
-        void reviewDone(KJob* j);
-        void reviewCreated(KJob* j);
-
-    private:
-        KDevelop::IPatchSource::Ptr m_source;
-};
-
-#endif
diff --git a/plugins/reviewboard/reviewpatch.ui b/plugins/reviewboard/reviewpatch.ui
deleted file mode 100644
index 71e026f..0000000
--- a/plugins/reviewboard/reviewpatch.ui
+++ /dev/null
@@ -1,164 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ReviewPatch</class>
- <widget class="QWidget" name="ReviewPatch">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>356</width>
-    <height>339</height>
-   </rect>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <widget class="QGroupBox" name="groupBox_2">
-     <property name="title">
-      <string>Destination</string>
-     </property>
-     <layout class="QFormLayout" name="formLayout">
-      <property name="fieldGrowthPolicy">
-       <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
-      </property>
-      <item row="0" column="0">
-       <widget class="QLabel" name="label">
-        <property name="text">
-         <string>Server</string>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="1">
-       <widget class="KUrlRequester" name="server"/>
-      </item>
-      <item row="1" column="0">
-       <widget class="QLabel" name="label_2">
-        <property name="text">
-         <string>Base Dir:</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="1">
-       <widget class="QLineEdit" name="basedir">
-        <property name="text">
-         <string>/</string>
-        </property>
-        <property name="placeholderText">
-         <string>Where this project was checked out from</string>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QGroupBox" name="groupBox">
-     <property name="title">
-      <string>Authentication</string>
-     </property>
-     <layout class="QFormLayout" name="formLayout_2">
-      <property name="fieldGrowthPolicy">
-       <enum>QFormLayout::ExpandingFieldsGrow</enum>
-      </property>
-      <item row="0" column="0">
-       <widget class="QLabel" name="label_3">
-        <property name="text">
-         <string>Username:</string>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="1">
-       <widget class="QLineEdit" name="username">
-        <property name="placeholderText">
-         <string>User name in the specified service</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="0">
-       <widget class="QLabel" name="label_4">
-        <property name="text">
-         <string>Password:</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="1">
-       <widget class="QLineEdit" name="password">
-        <property name="echoMode">
-         <enum>QLineEdit::Password</enum>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QGroupBox" name="repositoriesBox">
-     <property name="enabled">
-      <bool>true</bool>
-     </property>
-     <property name="title">
-      <string>Repository</string>
-     </property>
-     <layout class="QVBoxLayout" name="verticalLayout_2">
-      <item>
-       <widget class="QComboBox" name="repositories"/>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QGroupBox" name="reviewsBox">
-     <property name="title">
-      <string>Update review</string>
-     </property>
-     <layout class="QFormLayout" name="formLayout_3">
-      <item row="0" column="0">
-       <widget class="QCheckBox" name="reviewCheckbox">
-        <property name="text">
-         <string/>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="1">
-       <widget class="QComboBox" name="reviews">
-        <property name="enabled">
-         <bool>false</bool>
-        </property>
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>16777215</width>
-          <height>23</height>
-         </size>
-        </property>
-        <property name="insertPolicy">
-         <enum>QComboBox::InsertAlphabetically</enum>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QDialogButtonBox" name="buttonBox">
-     <property name="standardButtons">
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-     </property>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <customwidgets>
-  <customwidget>
-   <class>KUrlRequester</class>
-   <extends>QFrame</extends>
-   <header>kurlrequester.h</header>
-  </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/plugins/reviewboard/reviewpatchdialog.cpp b/plugins/reviewboard/reviewpatchdialog.cpp
deleted file mode 100644
index 349cfdf..0000000
--- a/plugins/reviewboard/reviewpatchdialog.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "reviewpatchdialog.h"
-
-#include <QDialog>
-#include <QDialogButtonBox>
-
-#include <KLocalizedString>
-
-#include "ui_reviewpatch.h"
-#include "reviewboardjobs.h"
-#include "debug.h"
-
-ReviewPatchDialog::ReviewPatchDialog(const QUrl& dirUrl, QWidget* parent)
-    : QDialog(parent)
-{
-    m_ui = new Ui::ReviewPatch;
-    m_ui->setupUi(this);
-
-    connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &ReviewPatchDialog::accept);
-    connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &ReviewPatchDialog::reject);
-
-    connect(m_ui->server, &KUrlRequester::textChanged, this, &ReviewPatchDialog::serverChanged);
-    connect(m_ui->reviewCheckbox, &QCheckBox::stateChanged, this, &ReviewPatchDialog::reviewCheckboxChanged);
-
-    if (dirUrl.isLocalFile()) {
-        QDir d(dirUrl.toLocalFile());
-        while(!QFile::exists(d.filePath(".reviewboardrc"))) {
-            if(!d.cdUp())
-                break;
-        }
-        if(!d.isRoot())
-            initializeFromRC(d.filePath(".reviewboardrc"));
-    }
-}
-
-ReviewPatchDialog::~ReviewPatchDialog()
-{
-    delete m_ui;
-}
-
-void ReviewPatchDialog::setBaseDir(const QString& repo)
-{
-    m_ui->basedir->setText(repo);
-}
-
-void ReviewPatchDialog::setServer(const QUrl& server)
-{
-    m_ui->server->setUrl(server);
-}
-
-void ReviewPatchDialog::setUsername(const QString& user)
-{
-    m_ui->username->setText(user);
-}
-
-void ReviewPatchDialog::setRepository(const QString& repo)
-{
-    m_preferredRepository = repo;
-}
-
-QString ReviewPatchDialog::baseDir() const
-{
-    return m_ui->basedir->text();
-}
-
-QUrl ReviewPatchDialog::server() const
-{
-    QUrl server=m_ui->server->url();
-    server.setUserName(m_ui->username->text());
-    server.setPassword(m_ui->password->text());
-    return server;
-}
-
-QString ReviewPatchDialog::username() const
-{
-    return m_ui->username->text();
-}
-
-void ReviewPatchDialog::serverChanged()
-{
-    m_ui->repositories->clear();
-    //TODO reviewboards with private repositories don't work. Use user/pass if set.
-    ReviewBoard::ProjectsListRequest* repo = new ReviewBoard::ProjectsListRequest(m_ui->server->url(), this);
-    connect(repo, &ReviewBoard::ProjectsListRequest::finished, this, &ReviewPatchDialog::receivedProjects);
-    repo->start();
-}
-
-void ReviewPatchDialog::receivedProjects(KJob* job)
-{
-    // TODO:  check error
-    ReviewBoard::ProjectsListRequest* pl=dynamic_cast<ReviewBoard::ProjectsListRequest*>(job);
-    QVariantList repos = pl->repositories();
-    // Add default value with no repo selected.
-    m_ui->repositories->addItem(i18n("Repository not selected"), 0);
-
-    foreach(const QVariant& repo, repos) {
-        QVariantMap repoMap=repo.toMap();
-        m_ui->repositories->addItem(repoMap["name"].toString(), repoMap["path"]);
-    }
-
-    connect(m_ui->repositories, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ReviewPatchDialog::repositoryChanged);
-
-    QAbstractItemModel* model = m_ui->repositories->model();
-    if(!m_preferredRepository.isEmpty()) {
-        QModelIndexList idxs = model->match(model->index(0,0), Qt::UserRole, m_preferredRepository, 1, Qt::MatchExactly);
-        if(idxs.isEmpty()) {
-            idxs = model->match(model->index(0,0), Qt::DisplayRole, QUrl::fromUserInput(m_preferredRepository).fileName(), 1, Qt::MatchExactly);
-        }
-        if(!idxs.isEmpty()) {
-            m_ui->repositories->setCurrentIndex(idxs.first().row());
-        } else
-            qCDebug(PLUGIN_REVIEWBOARD) << "couldn't find the repository" << m_preferredRepository;
-    }
-    m_ui->repositoriesBox->setEnabled(job->error()==0);
-}
-
-QString ReviewPatchDialog::repository() const
-{
-    QComboBox* repositories = m_ui->repositories;
-    if(repositories->currentIndex() != -1) {
-        return repositories->itemData(repositories->currentIndex(), Qt::UserRole).toString();
-    }
-    return QString();
-}
-
-void ReviewPatchDialog::repositoryChanged(int index)
-{
-    m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled((!isUpdateReview() && index > 0) || m_ui->reviews->currentIndex() != -1);
-}
-
-void ReviewPatchDialog::reviewCheckboxChanged(int status)
-{
-    if (status == Qt::Checked) {
-        m_ui->reviews->setEnabled(true);
-        connect(m_ui->username, &QLineEdit::editingFinished, this, &ReviewPatchDialog::updateReviews);
-        connect(m_ui->password, &QLineEdit::editingFinished, this, &ReviewPatchDialog::updateReviews);
-        connect(m_ui->server, static_cast<void(KUrlRequester::*)()>(&KUrlRequester::returnPressed), this, &ReviewPatchDialog::updateReviews);
-        connect(m_ui->repositories, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ReviewPatchDialog::updateReviewsList);
-    } else {
-        m_ui->reviews->setEnabled(false);
-        disconnect(m_ui->username, &QLineEdit::editingFinished, this, &ReviewPatchDialog::updateReviews);
-        disconnect(m_ui->password, &QLineEdit::editingFinished, this, &ReviewPatchDialog::updateReviews);
-        disconnect(m_ui->server, static_cast<void(KUrlRequester::*)()>(&KUrlRequester::returnPressed), this, &ReviewPatchDialog::updateReviews);
-        disconnect(m_ui->repositories, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ReviewPatchDialog::updateReviewsList);
-    }
-    updateReviews();
-}
-
-void ReviewPatchDialog::receivedReviews(KJob* job)
-{
-    m_reviews.clear();
-    // TODO: check errors
-    QVariantList reviews = dynamic_cast<ReviewBoard::ReviewListRequest*>(job)->reviews();
-    foreach(const QVariant& review, reviews) {
-        QVariantMap reviewMap = review.toMap();
-        QVariantMap repoMap = reviewMap["links"].toMap()["repository"].toMap();
-        m_reviews.insert(repoMap["title"].toString(), qMakePair<QString, QVariant>(reviewMap["summary"].toString(), reviewMap["id"]));
-    }
-
-    updateReviewsList();
-}
-
-QString ReviewPatchDialog::review() const
-{
-    return m_ui->reviews->itemData(m_ui->reviews->currentIndex(), Qt::UserRole).toString();
-}
-
-void ReviewPatchDialog::updateReviews()
-{
-    if (isUpdateReview()) {
-        //TODO: reviewboards with private reviews don't work. Use user/pass if set.
-        if (!m_ui->server->text().isEmpty() && !m_ui->username->text().isEmpty()) {
-            ReviewBoard::ReviewListRequest* repo = new ReviewBoard::ReviewListRequest(m_ui->server->url(), username(), "pending", this);
-            connect(repo, &ReviewBoard::ReviewListRequest::finished, this, &ReviewPatchDialog::receivedReviews);
-            repo->start();
-        }
-    } else {
-        // Clear reviews combobox and enable OK Button if a repository is selected.
-        m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(m_ui->repositories->currentIndex() != -1);
-    }
-}
-
-bool ReviewPatchDialog::isUpdateReview()
-{
-    return m_ui->reviewCheckbox->checkState() == Qt::Checked;
-}
-
-void ReviewPatchDialog::updateReviewsList()
-{
-    QString repo = m_ui->repositories->currentText();
-    QPair<QString, QVariant> kv;
-    m_ui->reviews->clear();
-
-    if (m_ui->repositories->currentIndex() < 1) {
-        // Show all Review
-        foreach (const QString& key, m_reviews.uniqueKeys()) {
-            foreach (kv, m_reviews.values(key)) {
-                 m_ui->reviews->addItem(kv.first, kv.second);
-            }
-        }
-    } else {
-        // Filter using actual repository.
-        foreach (kv, m_reviews.values(repo)) {
-            m_ui->reviews->addItem(kv.first, kv.second);
-        }
-    }
-
-    m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(m_ui->reviews->currentIndex() != -1);
-}
-
-void ReviewPatchDialog::initializeFromRC(const QString& filePath)
-{
-    //The .reviewboardrc files are python files, we'll read and if it doesn't work
-    //Well bad luck. See: http://www.reviewboard.org/docs/rbtools/dev/rbt/configuration/
-
-    QRegExp rx("([\\w_]+) *= *[\"'](.*)[\"']");
-    QFile f(filePath);
-    if(!f.open(QFile::ReadOnly | QFile::Text))
-        return;
-
-    QHash<QString, QString> values;
-    QTextStream stream(&f);
-    for(; !stream.atEnd(); ) {
-        if(rx.exactMatch(stream.readLine())) {
-            values.insert(rx.cap(1), rx.cap(2));
-        }
-    }
-
-    if(values.contains("REVIEWBOARD_URL"))
-        setServer(QUrl(values["REVIEWBOARD_URL"]));
-    if(values.contains("REPOSITORY"))
-        setRepository(values["REPOSITORY"]);
-    addExtraData(QStringLiteral("target_groups"), values["TARGET_GROUPS"]);
-    addExtraData(QStringLiteral("target_people"), values["TARGET_PEOPLE"]);
-    addExtraData(QStringLiteral("branch"), values["BRANCH"]);
-    qCDebug(PLUGIN_REVIEWBOARD) << "found:" << values;
-}
-
-void ReviewPatchDialog::addExtraData(const QString& key, const QVariant &value)
-{
-    if (value.isValid())
-        m_extraData.insert(key, value);
-}
diff --git a/plugins/reviewboard/reviewpatchdialog.h b/plugins/reviewboard/reviewpatchdialog.h
deleted file mode 100644
index c87f4bb..0000000
--- a/plugins/reviewboard/reviewpatchdialog.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * This file is part of KDevelop
- * Copyright 2010-2012 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program 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 program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef KDEVPLATFORM_PLUGIN_REVIEWPATCHDIALOG_H
-#define KDEVPLATFORM_PLUGIN_REVIEWPATCHDIALOG_H
-
-#include <QDialog>
-#include <QUrl>
-#include <QVariantMap>
-
-class QItemSelection;
-class QModelIndex;
-
-class KJob;
-
-namespace Ui {
-    class ReviewPatch;
-}
-
-class ReviewPatchDialog : public QDialog
-{
-    Q_OBJECT
-    public:
-        ReviewPatchDialog(const QUrl& dirUrl, QWidget* parent = 0);
-        virtual ~ReviewPatchDialog();
-
-        void setBaseDir(const QString& dir);
-        void setServer(const QUrl& server);
-        void setUsername(const QString& user);
-
-        /** @returns the server url with the username and password */
-        QUrl server() const;
-
-        /** @returns the selected base directory for the patch */
-        QString baseDir() const;
-        QString repository() const;
-        QString username() const;
-
-        void setRepository(const QString& repo);
-
-        QString review() const;
-
-        bool isUpdateReview();
-
-        QVariantMap extraData() const { return m_extraData; }
-
-    private slots:
-        void serverChanged();
-        void receivedProjects(KJob* job);
-        void repositoryChanged(int index);
-        void receivedReviews(KJob* job);
-        void reviewCheckboxChanged(int status);
-        void updateReviews();
-        void updateReviewsList();
-
-    private:
-        void addExtraData(const QString& key, const QVariant& value);
-        void initializeFromRC(const QString& filePath);
-
-        Ui::ReviewPatch* m_ui;
-        QString m_preferredRepository;
-        QMultiHash<QString, QPair<QString, QVariant> > m_reviews;
-        QVariantMap m_extraData;
-};
-
-#endif
diff --git a/plugins/reviewboard/tests/CMakeLists.txt b/plugins/reviewboard/tests/CMakeLists.txt
deleted file mode 100644
index 4e85dbb..0000000
--- a/plugins/reviewboard/tests/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-include_directories(.. ${CMAKE_CURRENT_BINARY_DIR}/..)
-
-set(reviewboardtest_SRCS
-    main.cpp
-    ../reviewpatchdialog.cpp
-    ../reviewboardjobs.cpp
-    ../debug.cpp
-)
-
-ki18n_wrap_ui(reviewboardtest_SRCS ../reviewpatch.ui)
-
-add_executable(reviewboardtest ${reviewboardtest_SRCS})
-target_link_libraries(reviewboardtest KDev::Interfaces KF5::KIOWidgets)
-
-
diff --git a/plugins/reviewboard/tests/main.cpp b/plugins/reviewboard/tests/main.cpp
deleted file mode 100644
index c4f5561..0000000
--- a/plugins/reviewboard/tests/main.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*************************************************************************************
- *  Copyright (C) 2010 by Aleix Pol <aleixpol at kde.org>                               *
- *                                                                                   *
- *  This program is free software; you can redistribute it and/or                    *
- *  modify it under the terms of the GNU General Public License                      *
- *  as published by the Free Software Foundation; either version 2                   *
- *  of the License, or (at your option) any later version.                           *
- *                                                                                   *
- *  This program 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 General Public License for more details.                                     *
- *                                                                                   *
- *  You should have received a copy of the GNU General Public License                *
- *  along with this program; if not, write to the Free Software                      *
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
- *************************************************************************************/
-
-#include <QtCore/QCommandLineOption>
-#include <QtCore/QCommandLineParser>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
-#include <QtWidgets/QApplication>
-
-#include <KAboutData>
-#include <KLocalizedString>
-#include <KMessageBox>
-#include <QCommandLineParser>
-
-#include "reviewpatchdialog.h"
-#include "reviewboardjobs.h"
-
-int main(int argc, char *argv[])
-{
-    KAboutData about("reviewboardtest", i18n(("ReviewBoard Test")), "0.10", i18n("Test ReviewBoard support"),
-        KAboutLicense::GPL, i18n("(C) 2010 Aleix Pol Gonzalez"));
-    about.addAuthor( i18n("Aleix Pol Gonzalez"), QString(), "aleixpol at kde.org" );
-
-    QApplication app(argc, argv);
-    KAboutData::setApplicationData(about);
-    QCommandLineParser parser;
-    parser.addVersionOption();
-    parser.addHelpOption();
-    parser.addPositionalArgument("patch", i18n( "Patch" ));
-    parser.addOption(QCommandLineOption(QLatin1String("basedir <dir>"), i18n( "Base Directory" )));
-    parser.addOption(QCommandLineOption(QLatin1String("id <id>"), i18n( "Review request ID" )));
-    about.setupCommandLine(&parser);
-    parser.process(app);
-    about.processCommandLine(&parser);
-
-    ReviewPatchDialog d(QUrl::fromLocalFile(QDir::currentPath()));
-    int ret=d.exec();
-    if(ret==QDialog::Accepted) {
-        QUrl url = d.server();
-        ReviewBoard::ReviewRequest* job;
-        if (parser.positionalArguments().count() == 0) {
-            job = new ReviewBoard::NewRequest(d.server(), d.repository());
-        } else {
-            QUrl patch = QUrl::fromUserInput(parser.positionalArguments()[0]);
-            QString basedir=parser.value("basedir");
-            QString id=parser.value("id");
-            qDebug() << "patch:" << patch << ", basedir:" << basedir;
-            job = new ReviewBoard::SubmitPatchRequest(d.server(), patch, basedir, id);
-        }
-        bool corr = job->exec();
-        if(corr) {
-            url.setUserInfo(QString());
-            QString requrl = QStringLiteral("%1/r/%2/").arg(url.toDisplayString(QUrl::PreferLocalFile)).arg(job->requestId());
-
-            KMessageBox::information(0, i18n("<qt>You can find the new request at:<br /><a href='%1'>%1</a> </qt>", requrl));
-        } else {
-            KMessageBox::error(0, job->errorText());
-        }
-    }
-
-    return ret!=QDialog::Accepted;
-}
diff --git a/vcs/CMakeLists.txt b/vcs/CMakeLists.txt
index 29a8d26..486d288 100644
--- a/vcs/CMakeLists.txt
+++ b/vcs/CMakeLists.txt
@@ -43,7 +43,6 @@ set(KDevPlatformVcs_LIB_SRCS
     interfaces/ibasicversioncontrol.cpp
     interfaces/icontentawareversioncontrol.cpp
     interfaces/ipatchdocument.cpp
-    interfaces/ipatchexporter.cpp
     interfaces/ipatchsource.cpp
 )
 
@@ -104,7 +103,6 @@ install(FILES
     interfaces/ibrowsableversioncontrol.h
     interfaces/irepositoryversioncontrol.h
     interfaces/ipatchdocument.h
-    interfaces/ipatchexporter.h
     interfaces/ipatchsource.h
     DESTINATION ${INCLUDE_INSTALL_DIR}/kdevplatform/vcs/interfaces COMPONENT Devel
 )
diff --git a/vcs/interfaces/ipatchexporter.cpp b/vcs/interfaces/ipatchexporter.cpp
deleted file mode 100644
index 6a2ac33..0000000
--- a/vcs/interfaces/ipatchexporter.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/* This file is part of KDevelop
- *
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include "ipatchexporter.h"
-
-using namespace KDevelop;
-
-IPatchExporter::~IPatchExporter()
-{
-
-}
diff --git a/vcs/interfaces/ipatchexporter.h b/vcs/interfaces/ipatchexporter.h
deleted file mode 100644
index 44eb606..0000000
--- a/vcs/interfaces/ipatchexporter.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* This file is part of KDevelop
- *
- * Copyright 2010 Aleix Pol Gonzalez <aleixpol at kde.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef KDEVPLATFORM_IPATCHEXPORTER_H
-#define KDEVPLATFORM_IPATCHEXPORTER_H
-
-#include <vcs/vcsexport.h>
-#include "ipatchsource.h"
-
-class QWidget;
-namespace KDevelop
-{
-
-class KDEVPLATFORMVCS_EXPORT IPatchExporter
-{
-    public:
-        virtual ~IPatchExporter();
-        
-        virtual void exportPatch(IPatchSource::Ptr source) = 0;
-};
-
-}
-Q_DECLARE_INTERFACE( KDevelop::IPatchExporter, "org.kdevelop.IPatchExporter" )
-
-#endif


More information about the KDevelop-devel mailing list