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 #include "uploadjob.h"
0011 
0012 #include <QPushButton>
0013 #include <QHeaderView>
0014 #include <QStandardItemModel>
0015 #include <QtWidgets/QProgressDialog>
0016 #include <QUrl>
0017 #include <QDir>
0018 #include "kdevuploaddebug.h"
0019 
0020 #include <kconfiggroup.h>
0021 #include <kmessagebox.h>
0022 #include <kio/job.h>
0023 #include <kio/copyjob.h>
0024 #include <kio/jobuidelegate.h>
0025 #include <KLocalizedString>
0026 #include <kjob.h>
0027 #include <kjobwidgets.h>
0028 
0029 #include <interfaces/iproject.h>
0030 #include <interfaces/iprojectcontroller.h>
0031 #include <project/projectmodel.h>
0032 #include <util/path.h>
0033 
0034 #include "uploadprojectmodel.h"
0035 
0036 UploadJob::UploadJob(KDevelop::IProject* project, UploadProjectModel* model, QWidget *parent)
0037     : QObject(parent), m_project(project), m_uploadProjectModel(model),
0038       m_onlyMarkUploaded(false), m_quickUpload(false), m_outputModel(nullptr)
0039 {
0040     m_progressDialog = new QProgressDialog();
0041     m_progressDialog->setWindowTitle(i18n("Uploading files"));
0042     m_progressDialog->setLabelText(i18n("Preparing..."));
0043     m_progressDialog->setModal(true);
0044 }
0045 
0046 UploadJob::~UploadJob()
0047 {
0048     delete m_progressDialog;
0049 }
0050 
0051 void UploadJob::start()
0052 {
0053     m_progressBytesDone = 0;
0054     m_progressDialog->setLabelText(i18n("Calculating size..."));
0055     m_progressDialog->setValue(0);
0056     m_progressDialog->show();
0057 
0058     int sumSize = 0;
0059     QModelIndex i;
0060     while((i = m_uploadProjectModel->nextRecursionIndex(i)).isValid()) {
0061         KDevelop::ProjectBaseItem* item = m_uploadProjectModel->item(i);
0062         Qt::CheckState checked = static_cast<Qt::CheckState>(m_uploadProjectModel
0063                                 ->data(i, Qt::CheckStateRole).toInt());
0064         if (item->file() && checked != Qt::Unchecked) {
0065             KIO::UDSEntry entry;
0066             KIO::StatJob *statjob = KIO::stat(item->path().toUrl());
0067             KJobWidgets::setWindow(statjob, m_progressDialog);
0068             if (statjob->exec()) {
0069                 entry = statjob->statResult();
0070                 sumSize += entry.numberValue(KIO::UDSEntry::UDS_SIZE);
0071             }
0072         }
0073     }
0074     m_progressDialog->setMaximum(sumSize);
0075 
0076     m_uploadIndex = QModelIndex();
0077     uploadNext();
0078 }
0079 
0080 void UploadJob::uploadNext()
0081 {
0082     if (m_progressDialog->wasCanceled()) return;
0083 
0084     m_uploadIndex = m_uploadProjectModel->nextRecursionIndex(m_uploadIndex);
0085 
0086     if (!m_uploadIndex.isValid()) {
0087         //last index reached - completed
0088         appendLog(i18n("Upload completed"));
0089         emit uploadFinished();
0090         delete this;
0091         return;
0092     }
0093 
0094     if (!m_uploadIndex.parent().isValid()) {
0095         //don't upload project root
0096         uploadNext();
0097         return;
0098     }
0099 
0100     KDevelop::ProjectBaseItem* item = m_uploadProjectModel->item(m_uploadIndex);
0101 
0102     Qt::CheckState checked = static_cast<Qt::CheckState>(m_uploadProjectModel
0103                             ->data(m_uploadIndex, Qt::CheckStateRole).toInt());
0104 
0105     KDevelop::Path url;
0106     QUrl localUrl = m_uploadProjectModel->currentProfileLocalUrl().adjusted(QUrl::StripTrailingSlash);
0107 
0108     KDevelop::Path localPath = KDevelop::Path(localUrl.path());
0109     
0110     if (item->folder()) {
0111         url = item->folder()->path();
0112     } else if (item->file()) {
0113         url = item->file()->path();
0114     }
0115     
0116     if(localPath.path().isEmpty()) {
0117         localPath = m_project->path();        
0118     }
0119     
0120     QString relativeUrl(localPath.relativePath(url));
0121 
0122     if (isQuickUpload() && checked == Qt::Unchecked) {
0123         appendLog(i18n("File was not modified for %1: %2",
0124                             m_uploadProjectModel->currentProfileName(),
0125                             relativeUrl));
0126     }
0127 
0128     if (!(item->file() || item->folder()) || checked == Qt::Unchecked) {
0129         uploadNext();
0130         return;
0131     }
0132 
0133     QUrl dest = m_uploadProjectModel->currentProfileUrl().adjusted(QUrl::StripTrailingSlash);
0134     dest.setPath(dest.path() + "/" + relativeUrl);
0135     KIO::Job* job = nullptr;
0136 
0137     if (m_onlyMarkUploaded) {
0138         appendLog(i18n("Marked as uploaded for %1: %2",
0139                             m_uploadProjectModel->currentProfileName(),
0140                             relativeUrl));
0141         m_uploadProjectModel->profileConfigGroup()
0142                 .writeEntry(relativeUrl,
0143                             QDateTime::currentDateTime());
0144         uploadNext();
0145         return;
0146     } else if (item->file()) {
0147         appendLog(i18n("Uploading to %1: %2",
0148                             m_uploadProjectModel->currentProfileName(),
0149                             relativeUrl));
0150         qCDebug(KDEVUPLOAD) << "file_copy" << url.pathOrUrl() << dest;
0151         job = KIO::file_copy(url.toUrl(), dest, -1, KIO::Overwrite | KIO::HideProgressInfo);
0152         m_progressDialog->setLabelText(i18n("Uploading %1...", relativeUrl));
0153     } else if (item->folder()) {
0154         KIO::StatJob *statjob = KIO::stat(dest, KIO::StatJob::DestinationSide, 0);
0155         KJobWidgets::setWindow(statjob, m_progressDialog);
0156         if (statjob->exec()) {
0157             appendLog(i18n("Directory in %1 already exists: %2",
0158                                 m_uploadProjectModel->currentProfileName(),
0159                                 relativeUrl));
0160             m_uploadProjectModel->profileConfigGroup()
0161                     .writeEntry(relativeUrl,
0162                                 QDateTime::currentDateTime());
0163             uploadNext();
0164             return;
0165         } else {
0166             appendLog(i18n("Creating directory in %1: %2",
0167                                 m_uploadProjectModel->currentProfileName(),
0168                                 relativeUrl));
0169             qCDebug(KDEVUPLOAD) << "mkdir" << dest;
0170             job = KIO::mkdir(dest);
0171         }
0172     } else {
0173         uploadNext();
0174         return;
0175     }
0176 
0177     KJobWidgets::setWindow(job, m_progressDialog);
0178     connect(job, SIGNAL(result(KJob*)),
0179             this, SLOT(uploadResult(KJob*)));
0180     connect(job, SIGNAL(processedSize(KJob*, qulonglong)),
0181             this, SLOT(processedSize(KJob*, qulonglong)));
0182     connect(job, SIGNAL(infoMessage(KJob*, QString)),
0183             this, SLOT(uploadInfoMessage(KJob*, QString)));
0184 
0185     connect(m_progressDialog, SIGNAL(canceled()),
0186             this, SLOT(cancelClicked()));
0187     connect(m_progressDialog, SIGNAL(rejected()),
0188             job, SLOT(kill()));
0189     job->start();
0190 }
0191 
0192 void UploadJob::cancelClicked()
0193 {
0194     appendLog(i18n("Upload canceled"));
0195     deleteLater();
0196 }
0197 
0198 
0199 void UploadJob::uploadResult(KJob* job)
0200 {
0201     if (job->error()) {
0202         if (job->error() == KIO::ERR_USER_CANCELED) {
0203             cancelClicked();
0204             return;
0205         }
0206         appendLog(i18n("Upload error: %1", job->errorString()));
0207         job->uiDelegate()->showErrorMessage();
0208         deleteLater();
0209         return;
0210     }
0211 
0212     KDevelop::ProjectBaseItem* item = m_uploadProjectModel->item(m_uploadIndex);
0213     QUrl url;
0214     if (item->file()) {
0215         url = item->file()->path().toUrl();
0216     } else if (item->folder()) {
0217         url = item->folder()->path().toUrl();
0218     }
0219     m_uploadProjectModel->profileConfigGroup()
0220         .writeEntry(m_project->path().relativePath(KDevelop::Path(url)), QDateTime::currentDateTime());
0221     m_uploadProjectModel->profileConfigGroup().sync();
0222 
0223     KIO::UDSEntry entry;
0224     KIO::StatJob *statjob = KIO::stat(url, nullptr);
0225     KJobWidgets::setWindow(statjob, m_progressDialog);
0226     if (statjob->exec()) {
0227         entry = statjob->statResult();
0228         m_progressBytesDone += entry.numberValue(KIO::UDSEntry::UDS_SIZE);
0229     }
0230     m_progressDialog->setValue(m_progressBytesDone);
0231 
0232     uploadNext();
0233 }
0234 
0235 void UploadJob::processedSize(KJob*, qulonglong size)
0236 {
0237     m_progressDialog->setValue(m_progressBytesDone + size);
0238 }
0239 
0240 void UploadJob::uploadInfoMessage(KJob*, const QString& plain)
0241 {
0242     m_progressDialog->setLabelText(plain);
0243 }
0244 
0245 void UploadJob::setOutputModel(QStandardItemModel* model)
0246 {
0247     m_outputModel = model;
0248 }
0249 QStandardItemModel* UploadJob::outputModel()
0250 {
0251     return m_outputModel;
0252 }
0253 QStandardItem* UploadJob::appendLog(const QString& message)
0254 {
0255     if (m_outputModel) {
0256         QStandardItem* item = new QStandardItem(message);
0257         m_outputModel->appendRow(item);
0258         return item;
0259     } else {
0260         return nullptr;
0261     }
0262 }
0263 void UploadJob::setQuickUpload(bool v)
0264 {
0265     m_quickUpload = v;
0266 }
0267 
0268 bool UploadJob::isQuickUpload()
0269 {
0270     return m_quickUpload;
0271 }
0272 
0273 // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on