diff --git a/plugins/perforce/CMakeLists.txt b/plugins/perforce/CMakeLists.txt --- a/plugins/perforce/CMakeLists.txt +++ b/plugins/perforce/CMakeLists.txt @@ -4,12 +4,16 @@ IDENTIFIER PLUGIN_PERFORCE CATEGORY_NAME "kdevelop.plugins.perforce" ) +set(kdevperforce_UIS + ui/perforceimportmetadatawidget.ui +) set(kdevperforce_PART_SRCS + ui/perforceimportmetadatawidget.cpp perforceplugin.cpp perforcepluginmetadata.cpp ${kdevperforce_LOG_PART_SRCS} ) - +ki18n_wrap_ui(kdevperforce_PART_SRCS ${kdevperforce_UIS}) kdevplatform_add_plugin(kdevperforce JSON kdevperforce.json SOURCES ${kdevperforce_PART_SRCS}) target_link_libraries(kdevperforce diff --git a/plugins/perforce/perforceplugin.cpp b/plugins/perforce/perforceplugin.cpp --- a/plugins/perforce/perforceplugin.cpp +++ b/plugins/perforce/perforceplugin.cpp @@ -16,6 +16,7 @@ ***************************************************************************/ #include "perforceplugin.h" +#include "ui/perforceimportmetadatawidget.h" #include "debug.h" #include "qtcompat_p.h" @@ -135,9 +136,9 @@ return i18n("Perforce"); } -KDevelop::VcsImportMetadataWidget* PerforcePlugin::createImportMetadataWidget(QWidget* /*parent*/) +KDevelop::VcsImportMetadataWidget* PerforcePlugin::createImportMetadataWidget(QWidget* parent) { - return nullptr; + return new PerforceImportMetadataWidget(parent); } bool PerforcePlugin::isValidRemoteRepositoryUrl(const QUrl& remoteLocation) diff --git a/plugins/perforce/tests/CMakeLists.txt b/plugins/perforce/tests/CMakeLists.txt --- a/plugins/perforce/tests/CMakeLists.txt +++ b/plugins/perforce/tests/CMakeLists.txt @@ -5,6 +5,7 @@ set(perforceplugintest_SRCS test_perforce.cpp ../perforceplugin.cpp + ../ui/perforceimportmetadatawidget.cpp ${kdevperforce_LOG_PART_SRCS} ) diff --git a/plugins/perforce/ui/perforceimportmetadatawidget.h b/plugins/perforce/ui/perforceimportmetadatawidget.h new file mode 100644 --- /dev/null +++ b/plugins/perforce/ui/perforceimportmetadatawidget.h @@ -0,0 +1,63 @@ +/*************************************************************************** +* This file is part of KDevelop Perforce plugin, KDE project * +* * +* Copyright 2018 Morten Danielsen Volden * +* * +* 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, see . * +***************************************************************************/ + +#ifndef KDEVPLATFORM_PERFORCEIMPORTMETADATAWIDGET_H +#define KDEVPLATFORM_PERFORCEIMPORTMETADATAWIDGET_H + +#include "ui_perforceimportmetadatawidget.h" + +#include + +/** + * Asks the user for all options needed to import an existing directory into + * a Perforce repository + */ +class KDEVPLATFORMVCS_EXPORT PerforceImportMetadataWidget + : public KDevelop::VcsImportMetadataWidget +{ + Q_OBJECT + +public: + PerforceImportMetadataWidget(QWidget* parent = nullptr); + + QUrl source() const override; + KDevelop::VcsLocation destination() const override; + // TODO: Is not used, it returns an empty string + QString message() const override; + void setSourceLocation(const KDevelop::VcsLocation&) override; + void setSourceLocationEditable(bool) override; + void setMessage(const QString& message) override; + bool hasValidData() const override; + +private Q_SLOTS: + void testP4setup(); + +private: + + bool validateP4executable(); + + bool validateP4port(const QString& projectDir) const; + + bool validateP4user(const QString& projectDir) const; + + Ui::PerforceImportMetadataWidget* m_ui; + QString m_errorDescription; +}; + +#endif diff --git a/plugins/perforce/ui/perforceimportmetadatawidget.cpp b/plugins/perforce/ui/perforceimportmetadatawidget.cpp new file mode 100644 --- /dev/null +++ b/plugins/perforce/ui/perforceimportmetadatawidget.cpp @@ -0,0 +1,210 @@ +/*************************************************************************** +* This file is part of KDevelop Perforce plugin, KDE project * +* * +* Copyright 2018 Morten Danielsen Volden * +* * +* 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, see . * +***************************************************************************/ + +#include "perforceimportmetadatawidget.h" + +#include + +#include +#include +#include +#include + +using namespace KDevelop; + +PerforceImportMetadataWidget::PerforceImportMetadataWidget(QWidget* parent) + : VcsImportMetadataWidget(parent) + , m_ui(new Ui::PerforceImportMetadataWidget) +{ + m_ui->setupUi(this); + + m_ui->executableLoc->setText("/usr/bin/p4"); + m_ui->p4portEdit->setText("perforce:1666"); + + QProcessEnvironment curEnv = QProcessEnvironment::systemEnvironment(); + m_ui->p4configEdit->setText(curEnv.contains("P4CONFIG") ? curEnv.value("P4CONFIG") : ""); + m_ui->p4portEdit->setText(curEnv.contains("P4PORT") ? curEnv.value("P4PORT") : ""); + m_ui->p4userEdit->setText(curEnv.contains("P4USER") ? curEnv.value("P4USER") : ""); + curEnv.contains("P4CONFIG") ? m_ui->radioButtonConfig->setChecked(true) : m_ui->radioButtonVariables->setChecked(true); + curEnv.contains("P4CONFIG") ? m_ui->p4configEdit->setEnabled(true) : m_ui->p4configEdit->setEnabled(false); + + m_ui->sourceLoc->setEnabled(false); + m_ui->sourceLoc->setMode(KFile::Directory); + + m_ui->errorMsg->setTextColor(QColor(255, 0, 0)); + m_ui->errorMsg->setReadOnly(true); + + m_ui->p4clientEdit->setEditable(true); + + connect(m_ui->p4clientEdit, static_cast(&KComboBox::returnPressed), this, &PerforceImportMetadataWidget::changed ); + + connect(m_ui->radioButtonConfig, &QRadioButton::clicked, m_ui->p4configEdit, &QLineEdit::setEnabled); + connect(m_ui->radioButtonVariables, &QRadioButton::clicked, m_ui->p4configEdit, &QLineEdit::setDisabled); + + connect(m_ui->testP4setupButton, &QPushButton::pressed, this, &PerforceImportMetadataWidget::testP4setup); +} + +QUrl PerforceImportMetadataWidget::source() const +{ + return m_ui->sourceLoc->url(); +} + +VcsLocation PerforceImportMetadataWidget::destination() const +{ + VcsLocation dest; + dest.setRepositoryServer(m_ui->p4portEdit->text()); + dest.setUserData(QVariant::fromValue(m_ui->p4userEdit->text())); + dest.setRepositoryBranch(m_ui->p4clientEdit->itemText(0)); + return dest; +} + +QString PerforceImportMetadataWidget::message() const +{ + return QString(); + //TODO: return m_ui->message->toPlainText(); +} + +void PerforceImportMetadataWidget::setSourceLocation(const VcsLocation& url) +{ + m_ui->sourceLoc->setUrl(url.localUrl()); +} + +void PerforceImportMetadataWidget::setSourceLocationEditable(bool enable) +{ + m_ui->sourceLoc->setEnabled(enable); +} + +void PerforceImportMetadataWidget::setMessage(const QString& message) +{ + Q_UNUSED(message); + + //FIXME: correct ui field needs to be set + //m_ui->message->setText(message); +} + +bool PerforceImportMetadataWidget::hasValidData() const +{ + // FIXME: It has valid data if testP4setup has completed correctly. AND client name has been set to something + return !m_ui->p4clientEdit->itemText(0).isEmpty(); +} + +void PerforceImportMetadataWidget::testP4setup() +{ + m_ui->errorMsg->clear(); + m_ui->p4clientEdit->clear(); + + if (!validateP4executable()) + return; + + QDir execDir(m_ui->sourceLoc->url().toLocalFile()); + QTemporaryDir tmpDir; + if (!execDir.exists()) + execDir = tmpDir.path(); + + if(!validateP4port(execDir.path())) + return; + + if(!validateP4user(execDir.path())) + return; + + emit changed(); +} + +bool PerforceImportMetadataWidget::validateP4executable() +{ + if (QStandardPaths::findExecutable(m_ui->executableLoc->url().toLocalFile()).isEmpty()) { + m_ui->errorMsg->setText("Unable to find perforce executable. Is it installed on the system? Is it in your PATH?"); + return false; + } + return true; +} + +bool PerforceImportMetadataWidget::validateP4user(const QString& projectDir) const +{ + QProcess exec; + QProcessEnvironment p4execEnvironment; + p4execEnvironment.insert(QString("P4PORT"), m_ui->p4portEdit->displayText()); + exec.setWorkingDirectory(projectDir); + exec.setProcessEnvironment(p4execEnvironment); + exec.start(m_ui->executableLoc->url().toLocalFile(), QStringList() << QStringLiteral("workspaces") << + QStringLiteral("-u") << m_ui->p4userEdit->text() + ); + exec.waitForFinished(); + + QString processStdout(exec.readAllStandardOutput()); + QString processStderr(exec.readAllStandardError()); + +// std::cout << "Exited with code: " << exec.exitCode() << std::endl; +// std::cout << "Exited with stdout" << processStdout.toStdString() << std::endl; +// std::cout << "Exited with stderr" << processStderr.toStdString() << std::endl; + if (exec.exitCode() != 0) { + if(!processStderr.isEmpty()) { + m_ui->errorMsg->setText(processStderr); + } else { + QString msg("P4 Client failed with exit code: "); + msg += QString::number(exec.exitCode()); + m_ui->errorMsg->setText(msg); + } + return false; + } + if(!processStdout.isEmpty()) { + QStringList clientCmdOutput = processStdout.split("\n",QString::SkipEmptyParts); + QStringList clientItems; + for(QString const& clientLine : clientCmdOutput) { + QStringList wordsInLine = clientLine.split(" "); + // Client mvo_testkdevinteg 2017/05/22 root C:\P4repo 'Created by mvo. ' -- Line would be expected to look like so + clientItems.append(wordsInLine.at(1)); + } + m_ui->p4clientEdit->addItems(clientItems); + } + return true; +} + +bool PerforceImportMetadataWidget::validateP4port(const QString& projectDir) const +{ + QProcess exec; + QProcessEnvironment p4execEnvironment; + p4execEnvironment.insert(QString("P4PORT"), m_ui->p4portEdit->displayText()); + QTextStream out(stdout); + for (QString x : p4execEnvironment.toStringList()) { + out << x << endl; + } + + exec.setWorkingDirectory(projectDir); + exec.setProcessEnvironment(p4execEnvironment); + exec.start(m_ui->executableLoc->url().toLocalFile(), QStringList() << QStringLiteral("info")); + exec.waitForFinished(); + //QString processStdout(exec.readAllStandardOutput()); + QString processStderr(exec.readAllStandardError()); + + //std::cout << "Exited with code: " << exec.exitCode() << std::endl; + //std::cout << "Exited with stdout" << processStdout.toStdString() << std::endl; + //std::cout << "Exited with stderr" << processStderr.toStdString() << std::endl; + if (exec.exitCode() != 0) { + if(!processStderr.isEmpty()) { + m_ui->errorMsg->setText(processStderr); + } else { + QString msg("P4 Client failed with error code: "); + msg += QString::number(exec.exitCode()); + m_ui->errorMsg->setText(msg); + } + return false; + } + return true; +} diff --git a/plugins/perforce/ui/perforceimportmetadatawidget.ui b/plugins/perforce/ui/perforceimportmetadatawidget.ui new file mode 100644 --- /dev/null +++ b/plugins/perforce/ui/perforceimportmetadatawidget.ui @@ -0,0 +1,238 @@ + + + PerforceImportMetadataWidget + + + + 0 + 0 + 581 + 339 + + + + Import + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Source directory: + + + + + + + + + + P4 executable: + + + + + + + + + + P4 Port + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + The format of P4PORT for Perforce applications is protocol:host:port, or port by itself if both the Perforce application and versioning service are running on the same host. Port numbers must be in the range 1024 through 32767 + + + + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + P4 User + + + + + + + Current Perforce user name. By default, the Perforce username is the same as the OS username + + + + + + + P4 Client + + + + + + + Name of current client workspace on the Perforce server + + + + + + + P4 Config + + + + + + + false + + + Contains a file name without a path. The specified file is used to store other Perforce environment variables + + + + + + + + 50 + 0 + + + + Test + + + + + + + * { background-color: rgba(0, 0, 0, 0); } + + + + + + + true + + + + 0 + 0 + + + + + 250 + 0 + + + + Qt::LeftToRight + + + false + + + + + + true + + + false + + + false + + + + + 7 + 10 + 100 + 30 + + + + Config File + + + true + + + + + + 115 + 10 + 140 + 31 + + + + User/Port Config + + + + + + + + + KComboBox + QComboBox +
kcombobox.h
+
+ + KUrlRequester + QWidget +
kurlrequester.h
+ 1 +
+
+ + +