diff --git a/uploadjob.cpp b/uploadjob.cpp index 0280c6d..4503456 100644 --- a/uploadjob.cpp +++ b/uploadjob.cpp @@ -1,266 +1,273 @@ /*************************************************************************** * Copyright 2007 Niko Sams * * * * 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. * * * ***************************************************************************/ #include "uploadjob.h" #include #include #include #include #include #include #include "kdevuploaddebug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "uploadprojectmodel.h" UploadJob::UploadJob(KDevelop::IProject* project, UploadProjectModel* model, QWidget *parent) : QObject(parent), m_project(project), m_uploadProjectModel(model), m_onlyMarkUploaded(false), m_quickUpload(false), m_outputModel(nullptr) { m_progressDialog = new QProgressDialog(); m_progressDialog->setWindowTitle(i18n("Uploading files")); m_progressDialog->setLabelText(i18n("Preparing...")); m_progressDialog->setModal(true); } UploadJob::~UploadJob() { delete m_progressDialog; } void UploadJob::start() { m_progressBytesDone = 0; m_progressDialog->setLabelText(i18n("Calculating size...")); m_progressDialog->setValue(0); m_progressDialog->show(); int sumSize = 0; QModelIndex i; while((i = m_uploadProjectModel->nextRecursionIndex(i)).isValid()) { KDevelop::ProjectBaseItem* item = m_uploadProjectModel->item(i); Qt::CheckState checked = static_cast(m_uploadProjectModel ->data(i, Qt::CheckStateRole).toInt()); if (item->file() && checked != Qt::Unchecked) { KIO::UDSEntry entry; KIO::StatJob *statjob = KIO::stat(item->path().toUrl()); KJobWidgets::setWindow(statjob, m_progressDialog); if (statjob->exec()) { entry = statjob->statResult(); sumSize += entry.numberValue(KIO::UDSEntry::UDS_SIZE); } } } m_progressDialog->setMaximum(sumSize); m_uploadIndex = QModelIndex(); uploadNext(); } void UploadJob::uploadNext() { if (m_progressDialog->wasCanceled()) return; m_uploadIndex = m_uploadProjectModel->nextRecursionIndex(m_uploadIndex); if (!m_uploadIndex.isValid()) { //last index reached - completed appendLog(i18n("Upload completed")); emit uploadFinished(); delete this; return; } if (!m_uploadIndex.parent().isValid()) { //don't upload project root uploadNext(); return; } KDevelop::ProjectBaseItem* item = m_uploadProjectModel->item(m_uploadIndex); Qt::CheckState checked = static_cast(m_uploadProjectModel ->data(m_uploadIndex, Qt::CheckStateRole).toInt()); KDevelop::Path url; + QUrl localUrl = m_uploadProjectModel->currentProfileLocalUrl().adjusted(QUrl::StripTrailingSlash); + KDevelop::Path localPath = KDevelop::Path(localUrl.path()); + if (item->folder()) { url = item->folder()->path(); } else if (item->file()) { url = item->file()->path(); } - - QString relativeUrl(m_project->path().relativePath(url)); + + if(localPath.path().isEmpty()) { + localPath = m_project->path(); + } + + QString relativeUrl(localPath.relativePath(url)); if (isQuickUpload() && checked == Qt::Unchecked) { appendLog(i18n("File was not modified for %1: %2", m_uploadProjectModel->currentProfileName(), relativeUrl)); } if (!(item->file() || item->folder()) || checked == Qt::Unchecked) { uploadNext(); return; } QUrl dest = m_uploadProjectModel->currentProfileUrl().adjusted(QUrl::StripTrailingSlash); dest.setPath(dest.path() + "/" + relativeUrl); KIO::Job* job = nullptr; if (m_onlyMarkUploaded) { appendLog(i18n("Marked as uploaded for %1: %2", m_uploadProjectModel->currentProfileName(), relativeUrl)); m_uploadProjectModel->profileConfigGroup() .writeEntry(relativeUrl, QDateTime::currentDateTime()); uploadNext(); return; } else if (item->file()) { appendLog(i18n("Uploading to %1: %2", m_uploadProjectModel->currentProfileName(), relativeUrl)); qCDebug(KDEVUPLOAD) << "file_copy" << url.pathOrUrl() << dest; job = KIO::file_copy(url.toUrl(), dest, -1, KIO::Overwrite | KIO::HideProgressInfo); m_progressDialog->setLabelText(i18n("Uploading %1...", relativeUrl)); } else if (item->folder()) { KIO::StatJob *statjob = KIO::stat(dest, KIO::StatJob::DestinationSide, 0); KJobWidgets::setWindow(statjob, m_progressDialog); if (statjob->exec()) { appendLog(i18n("Directory in %1 already exists: %2", m_uploadProjectModel->currentProfileName(), relativeUrl)); m_uploadProjectModel->profileConfigGroup() .writeEntry(relativeUrl, QDateTime::currentDateTime()); uploadNext(); return; } else { appendLog(i18n("Creating directory in %1: %2", m_uploadProjectModel->currentProfileName(), relativeUrl)); qCDebug(KDEVUPLOAD) << "mkdir" << dest; job = KIO::mkdir(dest); } } else { uploadNext(); return; } KJobWidgets::setWindow(job, m_progressDialog); connect(job, SIGNAL(result(KJob*)), this, SLOT(uploadResult(KJob*))); connect(job, SIGNAL(processedSize(KJob*, qulonglong)), this, SLOT(processedSize(KJob*, qulonglong))); connect(job, SIGNAL(infoMessage(KJob*, QString)), this, SLOT(uploadInfoMessage(KJob*, QString))); connect(m_progressDialog, SIGNAL(canceled()), this, SLOT(cancelClicked())); connect(m_progressDialog, SIGNAL(rejected()), job, SLOT(kill())); job->start(); } void UploadJob::cancelClicked() { appendLog(i18n("Upload canceled")); deleteLater(); } void UploadJob::uploadResult(KJob* job) { if (job->error()) { if (job->error() == KIO::ERR_USER_CANCELED) { cancelClicked(); return; } appendLog(i18n("Upload error: %1", job->errorString())); job->uiDelegate()->showErrorMessage(); deleteLater(); return; } KDevelop::ProjectBaseItem* item = m_uploadProjectModel->item(m_uploadIndex); QUrl url; if (item->file()) { url = item->file()->path().toUrl(); } else if (item->folder()) { url = item->folder()->path().toUrl(); } m_uploadProjectModel->profileConfigGroup() .writeEntry(m_project->path().relativePath(KDevelop::Path(url)), QDateTime::currentDateTime()); m_uploadProjectModel->profileConfigGroup().sync(); KIO::UDSEntry entry; KIO::StatJob *statjob = KIO::stat(url, nullptr); KJobWidgets::setWindow(statjob, m_progressDialog); if (statjob->exec()) { entry = statjob->statResult(); m_progressBytesDone += entry.numberValue(KIO::UDSEntry::UDS_SIZE); } m_progressDialog->setValue(m_progressBytesDone); uploadNext(); } void UploadJob::processedSize(KJob*, qulonglong size) { m_progressDialog->setValue(m_progressBytesDone + size); } void UploadJob::uploadInfoMessage(KJob*, const QString& plain) { m_progressDialog->setLabelText(plain); } void UploadJob::setOutputModel(QStandardItemModel* model) { m_outputModel = model; } QStandardItemModel* UploadJob::outputModel() { return m_outputModel; } QStandardItem* UploadJob::appendLog(const QString& message) { if (m_outputModel) { QStandardItem* item = new QStandardItem(message); m_outputModel->appendRow(item); return item; } else { return nullptr; } } void UploadJob::setQuickUpload(bool v) { m_quickUpload = v; } bool UploadJob::isQuickUpload() { return m_quickUpload; } // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/uploadpreferences.cpp b/uploadpreferences.cpp index c212b8b..87896d8 100644 --- a/uploadpreferences.cpp +++ b/uploadpreferences.cpp @@ -1,123 +1,125 @@ /*************************************************************************** * Copyright 2007 Niko Sams * * * * 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. * * * ***************************************************************************/ #include "uploadpreferences.h" #include #include #include #include #include #include #include #include "uploadprofilemodel.h" #include "ui_uploadpreferences.h" #include "uploadprofiledlg.h" #include "uploadprofileitem.h" using namespace KDevelop; UploadPreferences::UploadPreferences( KDevelop::IPlugin* plugin, const KDevelop::ProjectConfigOptions& options, QWidget* parent ) : ProjectConfigPage(plugin, options, parent) { IProject* project = options.project; m_ui = new Ui::UploadPreferences(); m_ui->setupUi(this); m_model = new UploadProfileModel(); m_model->setProject(project); m_ui->profilesList->setModel(m_model); connect(m_model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(changed())); connect(m_model, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(changed())); connect(m_ui->addProfileButton, SIGNAL(clicked()), this, SLOT(addProfile())); connect(m_ui->modifyProfileButton, SIGNAL(clicked()), this, SLOT(modifyProfile())); connect(m_ui->removeProfileButton, SIGNAL(clicked()), this, SLOT(removeProfile())); connect(m_ui->profilesList, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(modifyProfile())); m_dlg = new UploadProfileDlg(this); } UploadPreferences::~UploadPreferences( ) { delete m_ui; } void UploadPreferences::reset() { ProjectConfigPage::reset(); } void UploadPreferences::apply() { m_model->submit(); + m_model->revert(); ProjectConfigPage::apply(); } void UploadPreferences::defaults() { ProjectConfigPage::defaults(); } void UploadPreferences::addProfile() { UploadProfileItem* i = new UploadProfileItem(); + i->setLocalUrl(QUrl(m_model->project()->path().path())); if (m_model->rowCount() == 0) { i->setDefault(true); } m_model->appendRow(i); if (m_dlg->editProfile(i) == QDialog::Rejected) { m_model->removeRow(i->index().row()); } } void UploadPreferences::removeProfile() { Q_FOREACH(QModelIndex index, m_ui->profilesList->selectionModel()->selectedIndexes()) { m_model->removeRow(index.row()); } } void UploadPreferences::modifyProfile() { Q_FOREACH(QModelIndex index, m_ui->profilesList->selectionModel()->selectedIndexes()) { UploadProfileItem* i = m_model->uploadItem(index); if (i) { m_dlg->editProfile(i); } } } QString UploadPreferences::name() const { return i18n("Upload"); } QString UploadPreferences::fullName() const { return i18n("Configure Upload settings"); } QIcon UploadPreferences::icon() const { return QIcon::fromTheme(QStringLiteral("go-up")); } // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/uploadprofiledlg.cpp b/uploadprofiledlg.cpp index aa4724b..53ab51e 100644 --- a/uploadprofiledlg.cpp +++ b/uploadprofiledlg.cpp @@ -1,140 +1,156 @@ /*************************************************************************** * Copyright 2007 Niko Sams * * * * 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. * * * ***************************************************************************/ #include "uploadprofiledlg.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_uploadprofiledlg.h" #include "uploadprofileitem.h" UploadProfileDlg::UploadProfileDlg(QWidget *parent) : QDialog (parent) { setWindowTitle(i18n("Upload Profile")); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); QWidget* widget = new QWidget(this); m_ui = new Ui::UploadProfileDlg(); m_ui->setupUi(widget); + m_ui->browseButtonLocal->setIcon(QIcon::fromTheme("document-open")); + connect(m_ui->browseButtonLocal, SIGNAL(clicked()), this, SLOT(browseLocal())); m_ui->browseButton->setIcon(QIcon::fromTheme("document-open")); connect(m_ui->browseButton, SIGNAL(clicked()), this, SLOT(browse())); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotAcceptButtonClicked())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); mainLayout->addWidget(widget); mainLayout->addWidget(buttonBox); QStringList protocols = KProtocolInfo::protocols(); protocols.sort(); Q_FOREACH (QString p, protocols) { QUrl u; u.setScheme(p); if (KProtocolManager::supportsWriting(u) && KProtocolManager::supportsMakeDir(u) && KProtocolManager::supportsDeleting(u)) { m_ui->comboProtocol->addItem(p); } } } UploadProfileDlg::~UploadProfileDlg() { delete m_ui; } int UploadProfileDlg::editProfile(UploadProfileItem* item) { m_ui->lineProfileName->setText(item->text()); m_ui->defaultProfile->setChecked(item->isDefault()); + m_ui->lineLocalPath->setText(item->localUrl().toString()); updateUrl(item->url()); int result = exec(); if (result == QDialog::Accepted) { item->setText(m_ui->lineProfileName->text()); item->setUrl(currentUrl()); + QUrl localUrl = QUrl(m_ui->lineLocalPath->text()); + item->setLocalUrl(localUrl); item->setDefault(m_ui->defaultProfile->checkState() == Qt::Checked); } return result; } QUrl UploadProfileDlg::currentUrl() { QUrl url; url.setHost(m_ui->lineHost->text()); url.setUserName(m_ui->lineUser->text()); url.setPath(m_ui->linePath->text()); if (m_ui->port->text().toInt() > 0) url.setPort(m_ui->port->text().toInt()); url.setScheme(m_ui->comboProtocol->currentText()); return url; } void UploadProfileDlg::updateUrl(const QUrl& url) { m_ui->lineHost->setText(url.host()); m_ui->lineUser->setText(url.userName()); m_ui->linePath->setText(url.path()); if (url.port() > 0) { m_ui->port->setText(QString::number(url.port())); } else { m_ui->port->setText(""); } int index = m_ui->comboProtocol->findData(url.scheme(), Qt::DisplayRole); m_ui->comboProtocol->setCurrentIndex(index); } void UploadProfileDlg::browse() { -#if QT_VERSION >= 0x050400 QUrl chosenDir = QFileDialog::getExistingDirectoryUrl(this, QString(), currentUrl()); -#else - QFileDialog dialog(this); - dialog.setDirectoryUrl(currentUrl()); - dialog.setOptions(QFileDialog::ShowDirsOnly); - dialog.exec(); - QUrl chosenDir = dialog.selectedUrls().first(); -#endif + if(chosenDir.isValid()) { updateUrl(chosenDir); } } + +void UploadProfileDlg::browseLocal() +{ + QUrl chosenDir = QFileDialog::getExistingDirectoryUrl(this, QString(), m_ui->lineLocalPath->text()); + + if(chosenDir.isValid()) { + m_ui->lineLocalPath->setText(chosenDir.path()); + } +} + void UploadProfileDlg::slotAcceptButtonClicked() { KIO::StatJob* statJob = KIO::stat(currentUrl()); statJob->setSide(KIO::StatJob::DestinationSide); KJobWidgets::setWindow(statJob, this); bool dirExists = statJob->exec(); if (!dirExists) { KMessageBox::sorry(this, i18n("The specified URL does not exist.")); return; } + + //TODO: check if local dir is subpath of project dir + QString selectedLocalPath = m_ui->lineLocalPath->text(); + if(!QDir(selectedLocalPath).exists()) { + KMessageBox::sorry(this, i18n("The specified local directory does not exist.")); + return; + } + QDialog::accept(); } // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/uploadprofiledlg.h b/uploadprofiledlg.h index 5617436..fa9f4d9 100644 --- a/uploadprofiledlg.h +++ b/uploadprofiledlg.h @@ -1,68 +1,73 @@ /*************************************************************************** * Copyright 2007 Niko Sams * * * * 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. * * * ***************************************************************************/ #ifndef UPLOADPROFILEDLG_H #define UPLOADPROFILEDLG_H #include class QUrl; class QListWidgetItem; namespace Ui { class UploadProfileDlg; } class UploadProfileItem; /** * Dialog to edit a upload profile */ class UploadProfileDlg : public QDialog { Q_OBJECT public: UploadProfileDlg( QWidget *parent = nullptr ); ~UploadProfileDlg() override; public Q_SLOTS: /** * Opens the Dialog to edit an upload profile * @return dialog's result code, Accepted or Rejected. */ int editProfile(UploadProfileItem* item); private Q_SLOTS: /** * Opens a directory browser to select the path */ void browse(); + /** + * Opens a directory browser to select the local path + */ + void browseLocal(); protected Q_SLOTS: /** * Implemented to accept() not if the entered url does not exist */ virtual void slotAcceptButtonClicked(); private: /** * Builds the Url from the current entered data */ QUrl currentUrl(); /** * Sets the values of the widgets to the given url */ void updateUrl( const QUrl& url ); Ui::UploadProfileDlg* m_ui; + }; #endif // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/uploadprofiledlg.ui b/uploadprofiledlg.ui index e47b8a1..ecd5d56 100644 --- a/uploadprofiledlg.ui +++ b/uploadprofiledlg.ui @@ -1,191 +1,221 @@ UploadProfileDlg 0 0 457 191 0 0 Profile &name: false lineProfileName &Protocol: false comboProtocol &Host: false lineHost 0 0 Po&rt: false port 0 0 &User: false lineUser Qt::Horizontal QSizePolicy::Expanding 111 20 + + + &Local Path: + + + false + + + linePath + + + + + + + + + + + + + 0 + 0 + + + + + + + Pa&th: false linePath - + 0 0 - + Use as &default profile KLineEdit QLineEdit
klineedit.h
lineProfileName comboProtocol lineHost port lineUser linePath browseButton defaultProfile
diff --git a/uploadprofileitem.cpp b/uploadprofileitem.cpp index 92907ac..e15b433 100644 --- a/uploadprofileitem.cpp +++ b/uploadprofileitem.cpp @@ -1,78 +1,86 @@ /*************************************************************************** * Copyright 2007 Niko Sams * * * * 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. * * * ***************************************************************************/ #include "uploadprofileitem.h" #include #include #include #include "uploadprofilemodel.h" UploadProfileItem::UploadProfileItem() { setEditable(false); } void UploadProfileItem::setUrl(const QUrl& url) { setData(url, UrlRole); } +void UploadProfileItem::setLocalUrl(const QUrl& url) +{ + setData(url, LocalUrlRole); +} void UploadProfileItem::setDefault(bool isDefault) { setData(isDefault, IsDefaultRole); if (isDefault) { setIcon(QIcon::fromTheme("rating")); UploadProfileModel* m; if (model() && (m = dynamic_cast(model()))) { for (int i = 0; i < m->rowCount(); i++) { UploadProfileItem* item = m->uploadItem(i); if (item && item != this) { item->setDefault(false); } } } } else { setIcon(QIcon()); } } void UploadProfileItem::setProfileNr(const QString& nr) { setData(nr, ProfileNrRole); } QUrl UploadProfileItem::url() const { return data(UrlRole).value(); } +QUrl UploadProfileItem::localUrl() const +{ + return data(LocalUrlRole).value(); +} bool UploadProfileItem::isDefault() const { return data(IsDefaultRole).toBool(); } QString UploadProfileItem::profileNr() const { return data(ProfileNrRole).toString(); } KConfigGroup UploadProfileItem::profileConfigGroup() const { UploadProfileModel* m = nullptr; if (!profileNr().isEmpty() && model() && (m = dynamic_cast(model()))) { return m->project()->projectConfiguration()->group("Upload").group("Profile"+profileNr()); } return KConfigGroup(); } // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/uploadprofileitem.h b/uploadprofileitem.h index 86fc424..edc62fa 100644 --- a/uploadprofileitem.h +++ b/uploadprofileitem.h @@ -1,63 +1,66 @@ /*************************************************************************** * Copyright 2007 Niko Sams * * * * 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. * * * ***************************************************************************/ #ifndef UPLOADPROFILEITEM_H #define UPLOADPROFILEITEM_H #include class QUrl; class KConfigGroup; class UploadProfileItem : public QStandardItem { enum { UrlRole = Qt::UserRole+1, - IsDefaultRole = Qt::UserRole+2, - ProfileNrRole = Qt::UserRole+3 + IsDefaultRole, + ProfileNrRole, + LocalUrlRole }; public: UploadProfileItem(); ~UploadProfileItem() override {} void setUrl(const QUrl& url); + void setLocalUrl(const QUrl& url); /** * Set if this item is the default upload-profile. * Sets default to false for all other items in this model */ void setDefault(bool isDefault); /** * Set the profile-number, which is used as group-name in the config */ void setProfileNr(const QString& nr); QUrl url() const; + QUrl localUrl() const; bool isDefault() const; /** * Returns the profile-number, which is used as group-name in the config */ QString profileNr() const; /** * Returns the KConfigGroup for this upload profile if one exists */ KConfigGroup profileConfigGroup() const; int type() const override { return UserType+1; } }; #endif // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/uploadprofilemodel.cpp b/uploadprofilemodel.cpp index 3952854..39d20ca 100644 --- a/uploadprofilemodel.cpp +++ b/uploadprofilemodel.cpp @@ -1,122 +1,125 @@ /*************************************************************************** * Copyright 2007 Niko Sams * * * * 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. * * * ***************************************************************************/ #include "uploadprofilemodel.h" #include #include #include #include #include "uploadprofileitem.h" UploadProfileModel::UploadProfileModel(QObject* parent) : QStandardItemModel(parent) { KSettings::Dispatcher::registerComponent(QStringLiteral("kdevupload"), this, "revert"); } bool UploadProfileModel::removeRow(int row, const QModelIndex & parent) { UploadProfileItem* i = uploadItem(row); if (i && !i->profileNr().isEmpty()) { m_deltedProfileNrs << i->profileNr(); } return QStandardItemModel::removeRow(row, parent); } UploadProfileItem* UploadProfileModel::uploadItem(int row, int column) const { QStandardItem* i = item(row, column); if (i) { return dynamic_cast(i); } return nullptr; } UploadProfileItem* UploadProfileModel::uploadItem(const QModelIndex& index) const { QStandardItem* i = itemFromIndex(index); if (i) { return dynamic_cast(i); } return nullptr; } void UploadProfileModel::setProject(KDevelop::IProject* project) { m_project = project; revert(); } KDevelop::IProject* UploadProfileModel::project() { return m_project; } void UploadProfileModel::revert() { KConfigGroup group = m_project->projectConfiguration()->group("Upload"); QString defProfile = group.readEntry("default", QString()); int row = 0; Q_FOREACH (QString g, group.groupList()) { if (g.startsWith("Profile")) { QUrl url = group.group(g).readEntry("url", QUrl()); + QUrl localUrl = group.group(g).readEntry("localUrl", QUrl()); QString name = group.group(g).readEntry("name", QString()); UploadProfileItem* i = uploadItem(row); if (!i) { i = new UploadProfileItem(); insertRow(row, i); } i->setText(name); i->setUrl(url); + i->setLocalUrl(localUrl); i->setProfileNr(g.mid(7)); //group-name i->setDefault(i->profileNr() == defProfile); ++row; } } for (int i = row; i < rowCount(); ++i) { qDeleteAll(takeRow(i)); } } bool UploadProfileModel::submit() { KConfigGroup group = m_project->projectConfiguration()->group("Upload"); Q_FOREACH (QString i, m_deltedProfileNrs) { group.group("Profile" + i).deleteGroup(); } int maxProfileNr = 0; for (int i = 0; i < rowCount(); i++) { UploadProfileItem* item = uploadItem(i); if (item) { maxProfileNr = qMax(item->profileNr().toInt(), maxProfileNr); } } QString defaultProfileNr; for (int i = 0; i < rowCount(); i++) { UploadProfileItem* item = uploadItem(i); if (item) { if (item->profileNr().isEmpty()) { item->setProfileNr(QString::number(++maxProfileNr)); } KConfigGroup profileGroup = group.group("Profile" + item->profileNr()); profileGroup.writeEntry("url", item->url().toString()); + profileGroup.writeEntry("localUrl", item->localUrl().toString()); profileGroup.writeEntry("name", item->text()); if (item->isDefault()) { defaultProfileNr = item->profileNr(); } } } group.writeEntry("default", defaultProfileNr); return true; } // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/uploadprojectmodel.cpp b/uploadprojectmodel.cpp index 92ecb3a..780addd 100644 --- a/uploadprojectmodel.cpp +++ b/uploadprojectmodel.cpp @@ -1,254 +1,259 @@ /*************************************************************************** * Copyright 2007 Niko Sams * * * * 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. * * * ***************************************************************************/ #include "uploadprojectmodel.h" #include #include #include #include "kdevuploaddebug.h" #include #include #include UploadProjectModel::UploadProjectModel(KDevelop::IProject* project, QObject *parent) : QSortFilterProxyModel(parent), m_project(project), m_rootItem(nullptr) { } UploadProjectModel::~UploadProjectModel() { } bool UploadProjectModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const { QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); KDevelop::ProjectBaseItem* item = projectModel()->itemFromIndex(index); if (!item) return false; if (item->project() != m_project) return false; if (!m_rootItem) return true; //is source a child of rootItem? QModelIndex i = index; while(i.isValid()) { if (m_rootItem->index() == i) return true; i = i.parent(); } //is source a parent of rootItem? i = m_rootItem->index(); while (i.isValid()) { if (index == i) return true; i = i.parent(); } return false; } Qt::ItemFlags UploadProjectModel::flags(const QModelIndex & index) const { Qt::ItemFlags ret = QSortFilterProxyModel::flags(index); ret |= Qt::ItemIsUserCheckable; ret &= ~Qt::ItemIsEditable; return ret; } QVariant UploadProjectModel::data(const QModelIndex & indx, int role) const { if (indx.isValid() && role == Qt::CheckStateRole) { KDevelop::ProjectBaseItem* i = item(indx); if (i->file() && m_profileConfigGroup.isValid()) { if (m_checkStates.contains(indx)) { return m_checkStates.value(indx); } else { qCDebug(KDEVUPLOAD) << "project folder" << m_project->path().path() << "file" << i << i->file(); qCDebug(KDEVUPLOAD) << "file url" << i->file()->path().path(); QString url = m_project->path().relativePath(i->file()->path()); qCDebug(KDEVUPLOAD) << "resulting url" << url; QDateTime uploadTime(m_profileConfigGroup.readEntry(url, QDateTime())); if (uploadTime.isValid()) { KFileItem fileItem(i->file()->path().toUrl()); QDateTime modTime = fileItem.time(KFileItem::ModificationTime); if (modTime > uploadTime) { return Qt::Checked; } else { return Qt::Unchecked; } } else { return Qt::Checked; } } } else if (i->folder() && m_profileConfigGroup.isValid()) { if (!rowCount(indx)) { //empty folder - should be uploaded too if (m_checkStates.contains(indx)) { return m_checkStates.value(indx); } else { //don't check for ModificationTime as we do for files QString url = m_project->path().relativePath(i->folder()->path()); QDateTime uploadTime(m_profileConfigGroup.readEntry(url, QDateTime())); if (uploadTime.isValid()) { return Qt::Unchecked; } else { return Qt::Checked; } } } bool allChecked = true; bool noneChecked = true; for (int j = 0; j < rowCount(indx); j++) { Qt::CheckState s = static_cast(data(index(j, 0, indx), role).toInt()); if (s == Qt::Checked) { noneChecked = false; } else if (s == Qt::Unchecked) { allChecked = false; } else { return Qt::PartiallyChecked; } } if (allChecked) { return Qt::Checked; } else if (noneChecked) { return Qt::Unchecked; } return Qt::PartiallyChecked; } else { return QVariant(); } } return QSortFilterProxyModel::data(indx, role); } bool UploadProjectModel::setData ( const QModelIndex & indx, const QVariant & value, int role) { if (indx.isValid() && role == Qt::CheckStateRole) { KDevelop::ProjectBaseItem* i = item(indx); if (i->file()) { Qt::CheckState s = static_cast(value.toInt()); m_checkStates.insert(indx, s); emit dataChanged(indx, indx); return true; } else if (i->folder()) { if (!rowCount(indx)) { //empty folder - should be uploaded too Qt::CheckState s = static_cast(value.toInt()); m_checkStates.insert(indx, s); emit dataChanged(indx, indx); } else { //recursive check/uncheck QModelIndex i = indx; while((i = nextRecursionIndex(i, indx)).isValid()) { setData(i, value, role); } } emit dataChanged(indx, indx); return true; } } return QSortFilterProxyModel::setData(indx, value, role); } void UploadProjectModel::setProfileConfigGroup(const KConfigGroup& group) { beginResetModel(); m_profileConfigGroup = group; m_checkStates.clear(); endResetModel(); } KConfigGroup UploadProjectModel::profileConfigGroup() const { return m_profileConfigGroup; } KDevelop::ProjectModel* UploadProjectModel::projectModel() const { return qobject_cast(sourceModel()); } KDevelop::ProjectBaseItem* UploadProjectModel::item(const QModelIndex& index) const { return projectModel()->itemFromIndex(mapToSource(index)); } QModelIndex UploadProjectModel::nextRecursionIndex(const QModelIndex& current, const QModelIndex& root) const { QModelIndex ret; if (rowCount(current) > 0) { //firstChild return index(0, 0, current); } else if (current != root && current.isValid() && current.row()+1 < rowCount(current.parent())) { //nextSibling return index(current.row()+1, 0, current.parent()); } QModelIndex i = current; while (i.parent() != root && i.isValid() && i.parent().isValid()) { if (i.parent().row()+1 < rowCount(i.parent().parent())) { //parent+.nextSibling return index(i.parent().row()+1, 0, i.parent().parent()); } i = i.parent(); } //finished return QModelIndex(); } void UploadProjectModel::setRootItem(KDevelop::ProjectBaseItem* item) { beginResetModel(); m_rootItem = item; endResetModel(); } QString UploadProjectModel::currentProfileName() { return m_profileConfigGroup.readEntry("name", QString()); } QUrl UploadProjectModel::currentProfileUrl() { return m_profileConfigGroup.readEntry("url", QUrl()); } +QUrl UploadProjectModel::currentProfileLocalUrl() +{ + return m_profileConfigGroup.readEntry("localUrl", QUrl()); +} + void UploadProjectModel::checkAll() { setData(index(0, 0), Qt::Checked, Qt::CheckStateRole); } void UploadProjectModel::checkModified() { QMapIterator i(m_checkStates); m_checkStates.clear(); while (i.hasNext()) { i.next(); emit dataChanged(i.key(), i.key()); } } void UploadProjectModel::checkInvert() { QModelIndex index; while((index = nextRecursionIndex(index)).isValid()) { KDevelop::ProjectBaseItem* i = item(index); if (!(i->folder() && rowCount(index) > 0)) { //invert files and empty folders Qt::CheckState v = static_cast(data(index, Qt::CheckStateRole).toInt()); if (v == Qt::Unchecked) v = Qt::Checked; else v = Qt::Unchecked; setData(index, v, Qt::CheckStateRole); } } } // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/uploadprojectmodel.h b/uploadprojectmodel.h index 5c2a188..eb3fcd5 100644 --- a/uploadprojectmodel.h +++ b/uploadprojectmodel.h @@ -1,111 +1,116 @@ /*************************************************************************** * Copyright 2007 Niko Sams * * * * 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. * * * ***************************************************************************/ #ifndef UPLOADPROJECTMODEL_H #define UPLOADPROJECTMODEL_H #include #include #include namespace KDevelop { class IProject; class ProjectModel; class ProjectBaseItem; } class QUrl; /** * ProxyModel that adds checkboxes for upload status to the ProjectModel. * * Reads out the modified time of files and compares it with the last upload time * to automatically select changed items. */ class UploadProjectModel : public QSortFilterProxyModel { Q_OBJECT public: UploadProjectModel( KDevelop::IProject* project, QObject *parent = nullptr ); ~UploadProjectModel() override; QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const override; bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ) override; Qt::ItemFlags flags ( const QModelIndex & index ) const override; bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const override; /** * Sets the profile KConfigGroup where the uploadtimes are stored. * called when user changes the active upload-profile. */ void setProfileConfigGroup(const KConfigGroup& group); /** * Returns the KConfigGroup with the current upload-profile. */ KConfigGroup profileConfigGroup() const; /** * Convenience function that returns the casted project-model. */ KDevelop::ProjectModel* projectModel() const; /** * Convenience function that returns a casted project-item for an index. */ KDevelop::ProjectBaseItem* item(const QModelIndex& index) const; /** * Helper-function to iterate recursive through the project-tree. * @param current the current index, start with QModelIndex() * @param root set to valid QModelIndex if a different root should be used * @return the next model-index in the iteration */ QModelIndex nextRecursionIndex(const QModelIndex& current, const QModelIndex& root = QModelIndex()) const; void setRootItem(KDevelop::ProjectBaseItem* item); /** * Returns the name of the current Upload Profile (which is set through setProfileConfigGroup) */ QString currentProfileName(); /** * Returns the url of the current Upload Profile (which is set through setProfileConfigGroup) */ QUrl currentProfileUrl(); + + /** + * Returns the local url of the current Upload Profile (which is set through setProfileConfigGroup) + */ + QUrl currentProfileLocalUrl(); public Q_SLOTS: /** * Checks all items */ void checkAll(); /** * Checks all modified items */ void checkModified(); /** * Inverts the checkStatus of all items */ void checkInvert(); private: KDevelop::IProject* m_project; ///< current project KConfigGroup m_profileConfigGroup; ///< KConfigGroup for active upload-profile QMap m_checkStates; ///< holds the user-modified states of the checkboxes KDevelop::ProjectBaseItem* m_rootItem; ///< rootItem, tree is only displayed from here }; #endif // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on