File indexing completed on 2024-04-21 04:35:57

0001 /***************************************************************************
0002 *   Copyright 2007 Niko Sams <niko.sams@gmail.com>                        *
0003 *                                                                         *
0004 *   This program is free software; you can redistribute it and/or modify  *
0005 *   it under the terms of the GNU General Public License as published by  *
0006 *   the Free Software Foundation; either version 2 of the License, or     *
0007 *   (at your option) any later version.                                   *
0008 *                                                                         *
0009 ***************************************************************************/
0010 
0011 #include "kdevuploadplugin.h"
0012 
0013 #include <QAction>
0014 #include <QVBoxLayout>
0015 #include <QSignalMapper>
0016 #include <QStandardItemModel>
0017 #include <QItemDelegate>
0018 #include "kdevuploaddebug.h"
0019 
0020 #include <KPluginFactory>
0021 #include <KLocalizedString>
0022 #include <kparts/mainwindow.h>
0023 #include <kactioncollection.h>
0024 #include <kactionmenu.h>
0025 
0026 #include <interfaces/icore.h>
0027 #include <interfaces/iproject.h>
0028 #include <interfaces/iprojectcontroller.h>
0029 #include <interfaces/iuicontroller.h>
0030 #include <interfaces/iplugincontroller.h>
0031 #include <interfaces/context.h>
0032 #include <interfaces/contextmenuextension.h>
0033 #include <project/projectconfigpage.h>
0034 #include <project/projectmodel.h>
0035 #include <outputview/ioutputview.h>
0036 #include <serialization/indexedstring.h>
0037 
0038 #include "uploaddialog.h"
0039 #include "profilesfiletree.h"
0040 #include "uploadjob.h"
0041 #include "uploadprojectmodel.h"
0042 #include "uploadprofilemodel.h"
0043 #include "uploadprofileitem.h"
0044 #include "uploadpreferences.h"
0045 #include "allprofilesmodel.h"
0046 #include <interfaces/idocumentcontroller.h>
0047 
0048 #include "version.h"
0049 
0050 K_PLUGIN_FACTORY_WITH_JSON(UploadFactory, "kdevupload.json", registerPlugin<UploadPlugin>(); )
0051 
0052 class FilesTreeViewFactory: public KDevelop::IToolViewFactory{
0053   public:
0054     FilesTreeViewFactory(UploadPlugin* plugin, AllProfilesModel* model)
0055                 : m_plugin(plugin), m_allProfilesModel(model) {}
0056 
0057     QWidget* create(QWidget *parent = nullptr) override
0058     {
0059         ProfilesFileTree* w = new ProfilesFileTree(m_plugin, parent);
0060         w->setModel(m_allProfilesModel);
0061         return w;
0062     }
0063 
0064     QString id() const override
0065     {
0066         return "org.quanta.UploadFactory";
0067     }
0068 
0069     Qt::DockWidgetArea defaultPosition() const override
0070     {
0071         return Qt::RightDockWidgetArea;
0072     }
0073 
0074     private:
0075         UploadPlugin* m_plugin;
0076         AllProfilesModel* m_allProfilesModel;
0077 };
0078 
0079 UploadPlugin::UploadPlugin(QObject *parent, const QVariantList &)
0080 : KDevelop::IPlugin(QStringLiteral("kdevupload"), parent),  m_outputModel(nullptr), m_filesTreeViewFactory(nullptr)
0081 {
0082     connect(core()->projectController(), SIGNAL(projectOpened(KDevelop::IProject*)),
0083                    this, SLOT(projectOpened(KDevelop::IProject*)));
0084     connect(core()->projectController(), SIGNAL(projectClosed(KDevelop::IProject*)),
0085                    this, SLOT(projectClosed(KDevelop::IProject*)));
0086     connect(core()->documentController(), SIGNAL(documentActivated(KDevelop::IDocument*)),
0087                 SLOT(documentActivated(KDevelop::IDocument*)));
0088     connect(core()->documentController(), SIGNAL(documentClosed(KDevelop::IDocument*)),
0089                 SLOT(documentClosed(KDevelop::IDocument*)));
0090 
0091     setXMLFile( QStringLiteral( "kdevupload.rc" ) );
0092 
0093     m_allProfilesModel = new AllProfilesModel(this);
0094     connect(m_allProfilesModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
0095                     this, SLOT(profilesRowChanged()));
0096     connect(m_allProfilesModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
0097                     this, SLOT(profilesRowChanged()));
0098     connect(m_allProfilesModel, SIGNAL(modelReset()),
0099                     this, SLOT(profilesRowChanged()));
0100 
0101     setupActions();
0102 }
0103 
0104 UploadPlugin::~UploadPlugin()
0105 {
0106 }
0107 
0108 void UploadPlugin::setupActions()
0109 {
0110     m_signalMapper = new QSignalMapper(this);
0111     connect(m_signalMapper, SIGNAL(mapped(QObject*)),
0112             this, SLOT(projectUpload(QObject*)));
0113     m_projectUploadActionMenu = new KActionMenu(i18n("&Upload Project"), this);
0114     m_projectUploadActionMenu->setIcon(QIcon::fromTheme("go-up"));
0115     m_projectUploadActionMenu->setToolTip(i18n("Upload project"));
0116     m_projectUploadActionMenu->setVisible(false); //make it visible when there are upload profiles
0117     actionCollection()->addAction("project_upload", m_projectUploadActionMenu);
0118 
0119     m_quickUploadCurrentFile = actionCollection()->addAction("quick_upload_current_file");
0120     m_quickUploadCurrentFile->setText( i18n("&Quick Upload Current File") );
0121     m_quickUploadCurrentFile->setIcon(QIcon::fromTheme("go-up"));
0122     m_projectUploadActionMenu->setEnabled(false);
0123     connect(m_quickUploadCurrentFile, SIGNAL(triggered(bool)), SLOT(quickUploadCurrentFile()));
0124 }
0125 
0126 void UploadPlugin::projectOpened(KDevelop::IProject* project)
0127 {
0128     UploadProfileModel* model = new UploadProfileModel();
0129     model->setProject(project);
0130     m_projectProfileModels.insert(project, model);
0131     m_allProfilesModel->addModel(model);
0132 
0133     documentActivated(core()->documentController()->activeDocument());
0134 }
0135 
0136 void UploadPlugin::projectClosed(KDevelop::IProject* project)
0137 {
0138     QAction* action = m_projectUploadActions.value(project);
0139     if (action) {
0140         m_projectUploadActions.remove(project);
0141         m_projectUploadActionMenu->removeAction(action);
0142         delete action;
0143     }
0144     UploadProfileModel* model = m_projectProfileModels.value(project);
0145     if (model) {
0146         m_projectProfileModels.remove(project);
0147         m_allProfilesModel->removeModel(model);
0148         delete model;
0149     }
0150 }
0151 
0152 
0153 void UploadPlugin::documentActivated(KDevelop::IDocument* doc)
0154 {
0155     if (!doc) {
0156         m_quickUploadCurrentFile->setEnabled(false);
0157         return;
0158     }
0159     KDevelop::IProject* project = core()->projectController()->findProjectForUrl(doc->url());
0160     if (!project) {
0161         m_quickUploadCurrentFile->setEnabled(false);
0162         return;
0163     }
0164     QList<KDevelop::ProjectFileItem*> files = project->filesForPath(KDevelop::IndexedString(doc->url()));
0165     if (files.isEmpty()) {
0166         m_quickUploadCurrentFile->setEnabled(false);
0167         return;
0168     }
0169     UploadProfileModel* profileModel = m_projectProfileModels.value(project);
0170     if (!profileModel || !profileModel->rowCount()) {
0171         m_quickUploadCurrentFile->setEnabled(false);
0172         return;
0173     }
0174 
0175     m_quickUploadCurrentFile->setEnabled(true);
0176 }
0177 
0178 
0179 void UploadPlugin::documentClosed(KDevelop::IDocument* )
0180 {
0181     m_quickUploadCurrentFile->setEnabled(false);
0182 }
0183 
0184 
0185 void UploadPlugin::projectUpload(QObject* p)
0186 {
0187     KDevelop::IProject* project = qobject_cast<KDevelop::IProject*>(p);
0188     if (project) {
0189         UploadDialog dialog(project, this, core()->uiController()->activeMainWindow());
0190         UploadProfileModel* model = m_projectProfileModels.value(project);
0191         dialog.setProfileModel(model);
0192         dialog.exec();
0193     }
0194 }
0195 
0196 KDevelop::ContextMenuExtension UploadPlugin::contextMenuExtension(KDevelop::Context* context, QWidget* parent)
0197 {
0198     if (context->type() == KDevelop::Context::ProjectItemContext) {
0199         KDevelop::ContextMenuExtension cmExtension;
0200         KDevelop::ProjectItemContext *itemCtx = dynamic_cast<KDevelop::ProjectItemContext*>(context);
0201         if (itemCtx) {
0202             m_ctxUrlList.clear();
0203             Q_FOREACH (KDevelop::ProjectBaseItem* _item, itemCtx->items()) {
0204                 if (_item->folder() || _item->file()) {
0205                     m_ctxUrlList << _item;
0206                 }
0207             }
0208             if (!m_ctxUrlList.isEmpty()) {
0209                 KDevelop::IProject* project = m_ctxUrlList.at(0)->project();
0210                 UploadProfileModel* model = m_projectProfileModels.value(project);
0211                 if (model && model->rowCount()) {
0212                     QAction *action;
0213                     action = new QAction(i18n("Upload..."), parent);
0214                     action->setIcon(QIcon::fromTheme("go-up"));
0215                     connect(action, SIGNAL(triggered()), this, SLOT(upload()));
0216                     cmExtension.addAction(KDevelop::ContextMenuExtension::FileGroup, action);
0217     
0218                     action = new QAction(i18n("Quick Upload"), parent);
0219                     action->setIcon(QIcon::fromTheme("go-up"));
0220                     connect(action, SIGNAL(triggered()), this, SLOT(quickUpload()));
0221                     cmExtension.addAction(KDevelop::ContextMenuExtension::FileGroup, action);
0222                     
0223                     return cmExtension;
0224                 }
0225             }
0226         }
0227     }
0228     return KDevelop::IPlugin::contextMenuExtension(context, parent);
0229 }
0230 
0231 int UploadPlugin::perProjectConfigPages() const
0232 {
0233     return 1;
0234 }
0235 
0236 
0237 KDevelop::ConfigPage* UploadPlugin::perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent)
0238 {
0239     return number == 0 ? new UploadPreferences(this, options, parent) : nullptr;
0240 }
0241 
0242 void UploadPlugin::upload()
0243 {
0244     if (m_ctxUrlList.isEmpty()) return;
0245     KDevelop::IProject* project = m_ctxUrlList.at(0)->project();
0246 
0247     UploadDialog dialog(project, this, core()->uiController()->activeMainWindow());
0248     UploadProfileModel* model = m_projectProfileModels.value(project);
0249     dialog.setProfileModel(model);
0250     dialog.setRootItem(m_ctxUrlList.at(0));
0251     dialog.exec();
0252 }
0253 void UploadPlugin::quickUpload()
0254 {
0255     if (m_ctxUrlList.isEmpty()) return;
0256     KDevelop::IProject* project = m_ctxUrlList.at(0)->project();
0257 
0258     UploadProjectModel* model = new UploadProjectModel(project);
0259     model->setSourceModel(project->projectItem()->model());
0260     model->setRootItem(m_ctxUrlList.at(0));
0261 
0262     UploadProfileModel* profileModel = m_projectProfileModels.value(project);
0263     for (int i = 0; i < profileModel->rowCount(); i++) {
0264         UploadProfileItem* item = profileModel->uploadItem(i);
0265         if (item->isDefault()) {
0266             KConfigGroup c = item->profileConfigGroup();
0267             if (c.isValid()) {
0268                 model->setProfileConfigGroup(c);
0269             }
0270             break;
0271         }
0272     }
0273 
0274     UploadJob* job = new UploadJob(project, model, core()->uiController()->activeMainWindow());
0275     job->setQuickUpload(true);
0276     job->setOutputModel(outputModel());
0277     job->start();
0278 }
0279 
0280 
0281 void UploadPlugin::quickUploadCurrentFile()
0282 {
0283     KDevelop::IDocument* doc = core()->documentController()->activeDocument();
0284     if (!doc) return;
0285     KDevelop::IProject* project = KDevelop::ICore::self()->projectController()->findProjectForUrl(doc->url());
0286     if (!project) return;
0287     QList<KDevelop::ProjectFileItem*> files = project->filesForPath(KDevelop::IndexedString(doc->url()));
0288     if (files.isEmpty()) return;
0289 
0290     UploadProjectModel* model = new UploadProjectModel(project);
0291     model->setSourceModel(project->projectItem()->model());
0292     model->setRootItem(files.first());
0293 
0294     UploadProfileModel* profileModel = m_projectProfileModels.value(project);
0295     for (int i = 0; i < profileModel->rowCount(); i++) {
0296         UploadProfileItem* item = profileModel->uploadItem(i);
0297         if (item->isDefault()) {
0298             KConfigGroup c = item->profileConfigGroup();
0299             if (c.isValid()) {
0300                 model->setProfileConfigGroup(c);
0301             }
0302             break;
0303         }
0304     }
0305 
0306     UploadJob* job = new UploadJob(project, model, core()->uiController()->activeMainWindow());
0307     job->setQuickUpload(true);
0308     job->setOutputModel(outputModel());
0309     job->start();
0310 
0311 }
0312 
0313 
0314 QStandardItemModel* UploadPlugin::outputModel()
0315 {
0316     if (m_outputModel) return m_outputModel;
0317     IPlugin* plugin = core()->pluginController()->pluginForExtension( "org.kdevelop.IOutputView" );
0318     Q_ASSERT(plugin);
0319     if (plugin) {
0320         KDevelop::IOutputView* view = plugin->extension<KDevelop::IOutputView>();
0321         int tvid = view->registerToolView(i18n("Upload"));
0322         int id = view->registerOutputInToolView(tvid, i18n("Output"), KDevelop::IOutputView::AllowUserClose | KDevelop::IOutputView::AutoScroll);
0323         m_outputModel = new QStandardItemModel(this);
0324 
0325         view->setModel(id, m_outputModel);
0326         view->setDelegate(id, new QItemDelegate(m_outputModel));
0327 
0328         return m_outputModel;
0329     }
0330     return nullptr;
0331 }
0332 
0333 void UploadPlugin::profilesRowChanged()
0334 {
0335     if (m_allProfilesModel->rowCount()) {
0336         if (!m_filesTreeViewFactory) {
0337             m_filesTreeViewFactory = new FilesTreeViewFactory(this, m_allProfilesModel);
0338             core()->uiController()->addToolView(i18n("Upload Profiles"), m_filesTreeViewFactory);
0339         }
0340     } else {
0341         if (m_filesTreeViewFactory) {
0342             core()->uiController()->removeToolView(m_filesTreeViewFactory);
0343             m_filesTreeViewFactory = nullptr;
0344         }
0345     }
0346     Q_FOREACH(UploadProfileModel* model, m_projectProfileModels) {
0347         KDevelop::IProject* project = model->project();
0348         
0349         if (model->rowCount()) {
0350             if (!m_projectUploadActions.contains(project)) {
0351                 QAction* action = new QAction(project->name(), m_projectUploadActionMenu);
0352                 connect(action, SIGNAL(triggered()), m_signalMapper, SLOT(map()));
0353                 m_signalMapper->setMapping(action, project);
0354                 m_projectUploadActions.insert(project, action);
0355                 m_projectUploadActionMenu->addAction(action);
0356                 m_projectUploadActionMenu->setVisible(true);
0357             }
0358         } else {
0359             if (m_projectUploadActions.contains(project)) {
0360                 QAction* action = m_projectUploadActions.value(project);
0361                 m_projectUploadActions.remove(project);
0362                 m_projectUploadActionMenu->removeAction(action);
0363                 m_signalMapper->removeMappings(action);
0364                 delete action;
0365             }
0366         }
0367     }
0368     
0369     if (m_projectUploadActions.isEmpty()) {
0370         m_projectUploadActionMenu->setVisible(false);
0371     }
0372 }
0373 
0374 #include "kdevuploadplugin.moc"
0375 // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on