From 062208fdf4e5cab21a18ea1297c33e19bef004d4 Mon Sep 17 00:00:00 2001
From: Jarek Kobus <jaroslaw.kobus@nokia.com>
Date: Tue, 6 Dec 2011 16:45:07 +0100
Subject: [PATCH] Add a comand line editor for environment variables

Task-number: QTCREATORBUG-6499

Change-Id: I43df7bddd10776e0fdb192c668ab0d99a6fea7e6
Reviewed-by: Daniel Teske <daniel.teske@nokia.com>
Reviewed-by: hjk <qthjk@ovi.com>
---
 src/libs/utils/environment.cpp                |  10 ++
 src/libs/utils/environment.h                  |   1 +
 src/libs/utils/environmentmodel.cpp           |   1 +
 .../environmentitemswidget.cpp                | 154 ++++++++++++++++++
 .../projectexplorer/environmentitemswidget.h  |  81 +++++++++
 .../projectexplorer/environmentwidget.cpp     |  26 ++-
 .../projectexplorer/environmentwidget.h       |   1 +
 .../projectexplorer/projectexplorer.pro       |   6 +-
 8 files changed, 272 insertions(+), 8 deletions(-)
 create mode 100644 src/plugins/projectexplorer/environmentitemswidget.cpp
 create mode 100644 src/plugins/projectexplorer/environmentitemswidget.h

diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
index c0aaced90ee..d360f5f8c93 100644
--- a/src/libs/utils/environment.cpp
+++ b/src/libs/utils/environment.cpp
@@ -38,6 +38,16 @@
 
 namespace Utils {
 
+static bool sortEnvironmentItem(const EnvironmentItem &a, const EnvironmentItem &b)
+{
+    return a.name < b.name;
+}
+
+void EnvironmentItem::sort(QList<EnvironmentItem> *list)
+{
+    qSort(list->begin(), list->end(), &sortEnvironmentItem);
+}
+
 QList<EnvironmentItem> EnvironmentItem::fromStringList(const QStringList &list)
 {
     QList<EnvironmentItem> result;
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
index fb1f332e64c..07d3a3e9e41 100644
--- a/src/libs/utils/environment.h
+++ b/src/libs/utils/environment.h
@@ -58,6 +58,7 @@ public:
         return unset == other.unset && name == other.name && value == other.value;
     }
 
+    static void sort(QList<EnvironmentItem> *list);
     static QList<EnvironmentItem> fromStringList(const QStringList &list);
     static QStringList toStringList(const QList<EnvironmentItem> &list);
 };
diff --git a/src/libs/utils/environmentmodel.cpp b/src/libs/utils/environmentmodel.cpp
index 14b8a4ac5a1..edacf140d1f 100644
--- a/src/libs/utils/environmentmodel.cpp
+++ b/src/libs/utils/environmentmodel.cpp
@@ -366,6 +366,7 @@ void EnvironmentModel::setUserChanges(QList<Utils::EnvironmentItem> list)
     d->m_items = list;
     d->updateResultEnvironment();
     endResetModel();
+    emit userChangesChanged();
 }
 
 } // namespace Utils
diff --git a/src/plugins/projectexplorer/environmentitemswidget.cpp b/src/plugins/projectexplorer/environmentitemswidget.cpp
new file mode 100644
index 00000000000..2935b960132
--- /dev/null
+++ b/src/plugins/projectexplorer/environmentitemswidget.cpp
@@ -0,0 +1,154 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "environmentitemswidget.h"
+
+#include <utils/environment.h>
+#include <texteditor/snippets/snippeteditor.h>
+#include <texteditor/texteditorsettings.h>
+
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QDialogButtonBox>
+
+namespace ProjectExplorer {
+
+class EnvironmentItemsWidgetPrivate
+{
+public:
+    QList<Utils::EnvironmentItem> cleanUp(
+            const QList<Utils::EnvironmentItem> &items) const;
+    TextEditor::BaseTextEditorWidget *m_editor;
+};
+
+QList<Utils::EnvironmentItem> EnvironmentItemsWidgetPrivate::cleanUp(
+        const QList<Utils::EnvironmentItem> &items) const
+{
+    QList<Utils::EnvironmentItem> uniqueItems;
+    QSet<QString> uniqueSet;
+    for (int i = items.count() - 1; i >= 0; i--) {
+        Utils::EnvironmentItem item = items.at(i);
+#if defined(Q_OS_WIN)
+        item.name = item.name.toUpper();
+#endif
+        const QString &itemName = item.name;
+        QString emptyName = itemName;
+        emptyName.remove(QLatin1Char(' '));
+        if (!emptyName.isEmpty() && !uniqueSet.contains(itemName)) {
+            uniqueItems.prepend(item);
+            uniqueSet.insert(itemName);
+        }
+    }
+    return uniqueItems;
+}
+
+EnvironmentItemsWidget::EnvironmentItemsWidget(QWidget *parent) :
+    QWidget(parent), d(new EnvironmentItemsWidgetPrivate)
+{
+    d->m_editor = new TextEditor::SnippetEditorWidget(this);
+    TextEditor::TextEditorSettings *settings = TextEditor::TextEditorSettings::instance();
+    d->m_editor->setFontSettings(settings->fontSettings());
+    QVBoxLayout *layout = new QVBoxLayout(this);
+    layout->addWidget(d->m_editor);
+}
+
+EnvironmentItemsWidget::~EnvironmentItemsWidget()
+{
+    delete d;
+}
+
+void EnvironmentItemsWidget::setEnvironmentItems(const QList<Utils::EnvironmentItem> &items)
+{
+    QList<Utils::EnvironmentItem> sortedItems = items;
+    Utils::EnvironmentItem::sort(&sortedItems);
+    QStringList list = Utils::EnvironmentItem::toStringList(sortedItems);
+    d->m_editor->document()->setPlainText(list.join(QLatin1String("\n")));
+}
+
+QList<Utils::EnvironmentItem> EnvironmentItemsWidget::environmentItems() const
+{
+    const QStringList list = d->m_editor->document()->toPlainText().split(QLatin1String("\n"));
+    QList<Utils::EnvironmentItem> items = Utils::EnvironmentItem::fromStringList(list);
+    return d->cleanUp(items);
+}
+
+
+
+class EnvironmentItemsDialogPrivate
+{
+public:
+    EnvironmentItemsWidget *m_editor;
+};
+
+EnvironmentItemsDialog::EnvironmentItemsDialog(QWidget *parent) :
+    QDialog(parent), d(new EnvironmentItemsDialogPrivate)
+{
+    resize(640, 480);
+    d->m_editor = new EnvironmentItemsWidget(this);
+    QDialogButtonBox *box = new QDialogButtonBox(
+            QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
+    connect(box, SIGNAL(accepted()), this, SLOT(accept()));
+    connect(box, SIGNAL(rejected()), this, SLOT(reject()));
+    QVBoxLayout *layout = new QVBoxLayout(this);
+    layout->addWidget(d->m_editor);
+    layout->addWidget(box);
+    setWindowTitle(tr("Edit Environment"));
+}
+
+EnvironmentItemsDialog::~EnvironmentItemsDialog()
+{
+    delete d;
+}
+
+void EnvironmentItemsDialog::setEnvironmentItems(const QList<Utils::EnvironmentItem> &items)
+{
+    d->m_editor->setEnvironmentItems(items);
+}
+
+QList<Utils::EnvironmentItem> EnvironmentItemsDialog::environmentItems() const
+{
+    return d->m_editor->environmentItems();
+}
+
+QList<Utils::EnvironmentItem> EnvironmentItemsDialog::getEnvironmentItems(QWidget *parent,
+                const QList<Utils::EnvironmentItem> &initial, bool *ok)
+{
+    EnvironmentItemsDialog dlg(parent);
+    dlg.setEnvironmentItems(initial);
+    bool result = dlg.exec() == QDialog::Accepted;
+    if (ok)
+        *ok = result;
+    if (result)
+        return dlg.environmentItems();
+    return QList<Utils::EnvironmentItem>();
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/environmentitemswidget.h b/src/plugins/projectexplorer/environmentitemswidget.h
new file mode 100644
index 00000000000..e1eb883d1da
--- /dev/null
+++ b/src/plugins/projectexplorer/environmentitemswidget.h
@@ -0,0 +1,81 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef ENVIRONMENTITEMSWIDGET_H
+#define ENVIRONMENTITEMSWIDGET_H
+
+#include <QDialog>
+
+namespace Utils {
+class EnvironmentItem;
+}
+
+namespace ProjectExplorer {
+class EnvironmentItemsWidgetPrivate;
+
+class EnvironmentItemsWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit EnvironmentItemsWidget(QWidget *parent = 0);
+    ~EnvironmentItemsWidget();
+
+    void setEnvironmentItems(const QList<Utils::EnvironmentItem> &items);
+    QList<Utils::EnvironmentItem> environmentItems() const;
+
+private:
+    EnvironmentItemsWidgetPrivate *d;
+};
+
+
+class EnvironmentItemsDialogPrivate;
+
+class EnvironmentItemsDialog : public QDialog
+{
+    Q_OBJECT
+public:
+    explicit EnvironmentItemsDialog(QWidget *parent = 0);
+    ~EnvironmentItemsDialog();
+
+    void setEnvironmentItems(const QList<Utils::EnvironmentItem> &items);
+    QList<Utils::EnvironmentItem> environmentItems() const;
+
+    static QList<Utils::EnvironmentItem> getEnvironmentItems(QWidget *parent,
+                    const QList<Utils::EnvironmentItem> &initial, bool *ok = 0);
+
+private:
+    EnvironmentItemsDialogPrivate *d;
+};
+
+} // namespace ProjectExplorer
+
+#endif // ENVIRONMENTITEMSWIDGET_H
diff --git a/src/plugins/projectexplorer/environmentwidget.cpp b/src/plugins/projectexplorer/environmentwidget.cpp
index 5ede0b772cd..353e07b1f32 100644
--- a/src/plugins/projectexplorer/environmentwidget.cpp
+++ b/src/plugins/projectexplorer/environmentwidget.cpp
@@ -31,6 +31,7 @@
 **************************************************************************/
 
 #include "environmentwidget.h"
+#include "environmentitemswidget.h"
 
 #include <utils/detailswidget.h>
 #include <utils/environment.h>
@@ -61,6 +62,7 @@ public:
     QPushButton *m_addButton;
     QPushButton *m_resetButton;
     QPushButton *m_unsetButton;
+    QPushButton *m_batchEditButton;
 };
 
 EnvironmentWidget::EnvironmentWidget(QWidget *parent, QWidget *additionalDetailsWidget)
@@ -127,6 +129,11 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, QWidget *additionalDetails
 
     QSpacerItem *verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
     buttonLayout->addItem(verticalSpacer);
+
+    d->m_batchEditButton = new QPushButton(this);
+    d->m_batchEditButton->setText(tr("&Batch Edit..."));
+    buttonLayout->addWidget(d->m_batchEditButton);
+
     horizontalLayout->addLayout(buttonLayout);
     vbox2->addLayout(horizontalLayout);
 
@@ -143,6 +150,8 @@ EnvironmentWidget::EnvironmentWidget(QWidget *parent, QWidget *additionalDetails
             this, SLOT(removeEnvironmentButtonClicked()));
     connect(d->m_unsetButton, SIGNAL(clicked(bool)),
             this, SLOT(unsetEnvironmentButtonClicked()));
+    connect(d->m_batchEditButton, SIGNAL(clicked(bool)),
+            this, SLOT(batchEditEnvironmentButtonClicked()));
     connect(d->m_environmentView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
             this, SLOT(environmentCurrentIndexChanged(QModelIndex)));
 
@@ -187,15 +196,10 @@ void EnvironmentWidget::setUserChanges(const QList<Utils::EnvironmentItem> &list
     updateSummaryText();
 }
 
-bool sortEnvironmentItem(const Utils::EnvironmentItem &a, const Utils::EnvironmentItem &b)
-{
-    return a.name < b.name;
-}
-
 void EnvironmentWidget::updateSummaryText()
 {
     QList<Utils::EnvironmentItem> list = d->m_model->userChanges();
-    qSort(list.begin(), list.end(), &sortEnvironmentItem);
+    Utils::EnvironmentItem::sort(&list);
 
     QString text;
     foreach (const Utils::EnvironmentItem &item, list) {
@@ -261,6 +265,16 @@ void EnvironmentWidget::unsetEnvironmentButtonClicked()
         d->m_model->unsetVariable(name);
 }
 
+void EnvironmentWidget::batchEditEnvironmentButtonClicked()
+{
+    const QList<Utils::EnvironmentItem> changes = d->m_model->userChanges();
+
+    bool ok;
+    const QList<Utils::EnvironmentItem> newChanges = EnvironmentItemsDialog::getEnvironmentItems(this, changes, &ok);
+    if (ok)
+        d->m_model->setUserChanges(newChanges);
+}
+
 void EnvironmentWidget::environmentCurrentIndexChanged(const QModelIndex &current)
 {
     if (current.isValid()) {
diff --git a/src/plugins/projectexplorer/environmentwidget.h b/src/plugins/projectexplorer/environmentwidget.h
index 9c6f3993a09..3b536e6aa64 100644
--- a/src/plugins/projectexplorer/environmentwidget.h
+++ b/src/plugins/projectexplorer/environmentwidget.h
@@ -70,6 +70,7 @@ private slots:
     void addEnvironmentButtonClicked();
     void removeEnvironmentButtonClicked();
     void unsetEnvironmentButtonClicked();
+    void batchEditEnvironmentButtonClicked();
     void environmentCurrentIndexChanged(const QModelIndex &current);
     void invalidateCurrentIndex();
     void updateSummaryText();
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index 42b2d501baf..2862a0c64c4 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -102,7 +102,8 @@ HEADERS += projectexplorer.h \
     gcctoolchainfactories.h \
     appoutputpane.h \
     codestylesettingspropertiespage.h \
-    settingsaccessor.h
+    settingsaccessor.h \
+    environmentitemswidget.h
 
 SOURCES += projectexplorer.cpp \
     abi.cpp \
@@ -188,7 +189,8 @@ SOURCES += projectexplorer.cpp \
     publishing/publishingwizardselectiondialog.cpp \
     appoutputpane.cpp \
     codestylesettingspropertiespage.cpp \
-    settingsaccessor.cpp
+    settingsaccessor.cpp \
+    environmentitemswidget.cpp
 
 FORMS += processstep.ui \
     toolchainoptionspage.ui \
-- 
GitLab