diff --git a/qrenderdoc/Windows/Dialogs/CaptureDialog.cpp b/qrenderdoc/Windows/Dialogs/CaptureDialog.cpp index 6558c77e7..05aefa0b6 100644 --- a/qrenderdoc/Windows/Dialogs/CaptureDialog.cpp +++ b/qrenderdoc/Windows/Dialogs/CaptureDialog.cpp @@ -29,6 +29,7 @@ #include "3rdparty/toolwindowmanager/ToolWindowManager.h" #include "Code/QRDUtils.h" #include "Code/qprocessinfo.h" +#include "Windows/Dialogs/EnvironmentEditor.h" #include "Windows/Dialogs/VirtualFileDialog.h" #include "LiveCapture.h" #include "ui_CaptureDialog.h" @@ -498,7 +499,15 @@ void CaptureDialog::on_workDirBrowse_clicked() void CaptureDialog::on_envVarEdit_clicked() { - // TODO Env Editor + EnvironmentEditor envEditor(this); + + for(const EnvironmentModification &mod : m_EnvModifications) + envEditor.addModification(mod, true); + + int res = RDDialog::show(&envEditor); + + if(res) + setEnvironmentModifications(envEditor.modifications()); } void CaptureDialog::on_toggleGlobal_clicked() diff --git a/qrenderdoc/Windows/Dialogs/EnvironmentEditor.cpp b/qrenderdoc/Windows/Dialogs/EnvironmentEditor.cpp new file mode 100644 index 000000000..5806cc718 --- /dev/null +++ b/qrenderdoc/Windows/Dialogs/EnvironmentEditor.cpp @@ -0,0 +1,260 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2016-2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "EnvironmentEditor.h" +#include +#include +#include +#include "Code/QRDUtils.h" +#include "ui_EnvironmentEditor.h" + +Q_DECLARE_METATYPE(EnvironmentModification); + +EnvironmentEditor::EnvironmentEditor(QWidget *parent) + : QDialog(parent), ui(new Ui::EnvironmentEditor) +{ + ui->setupUi(this); + + auto commitLambda = [this](QKeyEvent *event) { + if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) + on_addUpdate_clicked(); + }; + + QObject::connect(ui->name, &RDLineEdit::keyPress, commitLambda); + QObject::connect(ui->value, &RDLineEdit::keyPress, commitLambda); + + auto separatorLambda = [this]() { ui->separator->setEnabled(!ui->setValue->isChecked()); }; + + QObject::connect(ui->setValue, &QRadioButton::toggled, separatorLambda); + QObject::connect(ui->prependValue, &QRadioButton::toggled, separatorLambda); + QObject::connect(ui->appendValue, &QRadioButton::toggled, separatorLambda); + + ui->separator->addItems({ + ToQStr(eEnvSep_Platform), ToQStr(eEnvSep_SemiColon), ToQStr(eEnvSep_Colon), ToQStr(eEnvSep_None), + }); + + ui->separator->setCurrentIndex(0); + + ui->setValue->setChecked(true); + ui->name->setFocus(); + + m_Completer = new QCompleter({}, this); + + ui->name->setCompleter(m_Completer); + + ui->variables->header()->setSectionResizeMode(0, QHeaderView::Interactive); + ui->variables->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + + ui->variables->setClearSelectionOnFocusLoss(false); + ui->variables->sortByColumn(0, Qt::DescendingOrder); + + ui->variables->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); +} + +EnvironmentEditor::~EnvironmentEditor() +{ + delete ui; +} + +void EnvironmentEditor::on_name_textChanged(const QString &text) +{ + int idx = existingIndex(); + + if(idx >= 0) + { + ui->addUpdate->setText(tr("Update")); + ui->deleteButton->setEnabled(true); + + ui->variables->clearSelection(); + ui->variables->topLevelItem(idx)->setSelected(true); + } + else + { + ui->addUpdate->setText(tr("Add")); + ui->deleteButton->setEnabled(false); + + ui->addUpdate->setEnabled(!text.trimmed().isEmpty()); + } +} + +void EnvironmentEditor::on_variables_keyPress(QKeyEvent *event) +{ + if(event->key() == Qt::Key_Delete && ui->deleteButton->isEnabled()) + on_deleteButton_clicked(); +} + +void EnvironmentEditor::on_variables_currentItemChanged(QTreeWidgetItem *current, + QTreeWidgetItem *previous) +{ + QList sel = ui->variables->selectedItems(); + + if(sel.isEmpty()) + return; + + EnvironmentModification mod = sel[0]->data(0, Qt::UserRole).value(); + + if(!mod.variable.isEmpty()) + { + ui->name->setText(mod.variable); + ui->value->setText(mod.value); + ui->separator->setCurrentIndex((int)mod.separator); + + if(mod.type == eEnvMod_Set) + ui->setValue->setChecked(true); + else if(mod.type == eEnvMod_Append) + ui->appendValue->setChecked(true); + else if(mod.type == eEnvMod_Prepend) + ui->prependValue->setChecked(true); + } +} + +void EnvironmentEditor::on_addUpdate_clicked() +{ + EnvironmentModification mod; + mod.variable = ui->name->text(); + mod.value = ui->value->text(); + mod.separator = (EnvironmentSeparator)ui->separator->currentIndex(); + + if(ui->appendValue->isChecked()) + mod.type = eEnvMod_Append; + else if(ui->prependValue->isChecked()) + mod.type = eEnvMod_Prepend; + else + mod.type = eEnvMod_Set; + + addModification(mod, false); + + on_name_textChanged(ui->name->text()); +} + +void EnvironmentEditor::on_deleteButton_clicked() +{ + QList sel = ui->variables->selectedItems(); + + if(sel.isEmpty()) + return; + + delete ui->variables->takeTopLevelItem(ui->variables->indexOfTopLevelItem(sel[0])); + + on_name_textChanged(ui->name->text()); +} + +int EnvironmentEditor::existingIndex() +{ + QString name = ui->name->text(); + + for(int i = 0; i < ui->variables->topLevelItemCount(); i++) + if(ui->variables->topLevelItem(i)->text(0) == name) + return i; + + return -1; +} + +void EnvironmentEditor::addModification(EnvironmentModification mod, bool silent) +{ + if(mod.variable.trimmed() == "") + { + if(!silent) + RDDialog::critical(this, tr("Invalid variable"), + tr("Environment variable cannot be just whitespace")); + + return; + } + + QTreeWidgetItem *node = NULL; + + int idx = existingIndex(); + + if(idx < 0) + { + node = makeTreeNode({mod.variable, mod.GetTypeString(), mod.value}); + ui->variables->addTopLevelItem(node); + } + else + { + node = ui->variables->topLevelItem(idx); + node->setText(0, mod.variable); + node->setText(1, mod.GetTypeString()); + node->setText(2, mod.value); + } + + node->setData(0, Qt::UserRole, QVariant::fromValue(mod)); + + ui->variables->clearSelection(); + node->setSelected(true); + + delete m_Completer; + + QStringList names; + for(int i = 0; i < ui->variables->topLevelItemCount(); i++) + names << ui->variables->topLevelItem(i)->text(0); + + m_Completer = new QCompleter(names, this); + + ui->name->setCompleter(m_Completer); +} + +QList EnvironmentEditor::modifications() +{ + QList ret; + + for(int i = 0; i < ui->variables->topLevelItemCount(); i++) + { + EnvironmentModification mod = + ui->variables->topLevelItem(i)->data(0, Qt::UserRole).value(); + + if(!mod.variable.isEmpty()) + ret.push_back(mod); + } + + return ret; +} + +void EnvironmentEditor::on_buttonBox_accepted() +{ + int idx = existingIndex(); + + if(idx >= 0 || ui->name->text().isEmpty()) + { + accept(); + return; + } + + QMessageBox::StandardButton res = RDDialog::question( + this, tr("Variable not added"), + tr("You did not add the variable modification you were editing. Add it now?"), + RDDialog::YesNoCancel, QMessageBox::Yes); + + if(res == QMessageBox::Yes) + { + on_addUpdate_clicked(); + } + else if(res == QMessageBox::Cancel) + { + // don't close + return; + } + + accept(); +} diff --git a/qrenderdoc/Windows/Dialogs/EnvironmentEditor.h b/qrenderdoc/Windows/Dialogs/EnvironmentEditor.h new file mode 100644 index 000000000..8c2d6b695 --- /dev/null +++ b/qrenderdoc/Windows/Dialogs/EnvironmentEditor.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +#include +#include "Code/RenderManager.h" + +namespace Ui +{ +class EnvironmentEditor; +} + +class QTreeWidgetItem; +class QCompleter; + +class EnvironmentEditor : public QDialog +{ + Q_OBJECT + +public: + explicit EnvironmentEditor(QWidget *parent = 0); + ~EnvironmentEditor(); + + void addModification(EnvironmentModification mod, bool silent); + QList modifications(); + +public slots: + // automatic slots + void on_name_textChanged(const QString &text); + void on_addUpdate_clicked(); + void on_deleteButton_clicked(); + void on_variables_keyPress(QKeyEvent *event); + void on_variables_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void on_buttonBox_accepted(); + +private: + Ui::EnvironmentEditor *ui; + QCompleter *m_Completer; + + int existingIndex(); +}; diff --git a/qrenderdoc/Windows/Dialogs/EnvironmentEditor.ui b/qrenderdoc/Windows/Dialogs/EnvironmentEditor.ui new file mode 100644 index 000000000..5b770a805 --- /dev/null +++ b/qrenderdoc/Windows/Dialogs/EnvironmentEditor.ui @@ -0,0 +1,237 @@ + + + EnvironmentEditor + + + + 0 + 0 + 542 + 418 + + + + Environment Variables + + + true + + + + 2 + + + 2 + + + 2 + + + 2 + + + 4 + + + + + QFrame::Panel + + + QFrame::Plain + + + QAbstractItemView::NoEditTriggers + + + true + + + 0 + + + false + + + false + + + true + + + + Name + + + + + Modification + + + + + Value + + + + + + + + + 100 + 0 + + + + Environment Variable + + + + 0 + + + + + Name + + + + + + + + + + Value + + + + + + + + + + + + + + 1 + 0 + + + + Modification type + + + + + + Set Value + + + + + + + Append Value + + + + + + + Prepend Value + + + + + + + + + + + + + 25 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Add / Update + + + + + + + Delete + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + RDLineEdit + QLineEdit +
Widgets/Extended/RDLineEdit.h
+
+ + RDTreeWidget + QTreeWidget +
Widgets/Extended/RDTreeWidget.h
+
+
+ + + + buttonBox + rejected() + EnvironmentEditor + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/qrenderdoc/qrenderdoc.pro b/qrenderdoc/qrenderdoc.pro index 63e2f665a..23fd98cc3 100644 --- a/qrenderdoc/qrenderdoc.pro +++ b/qrenderdoc/qrenderdoc.pro @@ -146,7 +146,8 @@ SOURCES += Code/qrenderdoc.cpp \ Windows/Dialogs/VirtualFileDialog.cpp \ Windows/Dialogs/RemoteManager.cpp \ Windows/PixelHistoryView.cpp \ - Widgets/PipelineFlowChart.cpp + Widgets/PipelineFlowChart.cpp \ + Windows/Dialogs/EnvironmentEditor.cpp HEADERS += Code/CaptureContext.h \ Code/qprocessinfo.h \ @@ -195,7 +196,8 @@ HEADERS += Code/CaptureContext.h \ Windows/Dialogs/VirtualFileDialog.h \ Windows/Dialogs/RemoteManager.h \ Windows/PixelHistoryView.h \ - Widgets/PipelineFlowChart.h + Widgets/PipelineFlowChart.h \ + Windows/Dialogs/EnvironmentEditor.h FORMS += Windows/Dialogs/AboutDialog.ui \ Windows/MainWindow.ui \ @@ -223,7 +225,8 @@ FORMS += Windows/Dialogs/AboutDialog.ui \ Windows/Dialogs/SuggestRemoteDialog.ui \ Windows/Dialogs/VirtualFileDialog.ui \ Windows/Dialogs/RemoteManager.ui \ - Windows/PixelHistoryView.ui + Windows/PixelHistoryView.ui \ + Windows/Dialogs/EnvironmentEditor.ui RESOURCES += Resources/resources.qrc diff --git a/qrenderdoc/qrenderdoc_local.vcxproj b/qrenderdoc/qrenderdoc_local.vcxproj index f26fb55a6..b0ac6c4cf 100644 --- a/qrenderdoc/qrenderdoc_local.vcxproj +++ b/qrenderdoc/qrenderdoc_local.vcxproj @@ -641,6 +641,7 @@ + @@ -708,6 +709,7 @@ + @@ -858,6 +860,7 @@ + @@ -1024,6 +1027,12 @@ MOC %(Filename).h $(IntDir)generated\moc_%(Filename).cpp + + %(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe;%(AdditionalInputs) + $(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -D_WIN32 -D_WIN64 -DRENDERDOC_PLATFORM_WIN32 -DSCINTILLA_QT=1 -DSCI_LEXER=1 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1900 -I$(ProjectDir) -I$(SolutionDir)\renderdoc\api\replay -I$(ProjectDir)3rdparty\qt\$(Platform)\mkspecs/win32-msvc2015 -I$(ProjectDir)3rdparty\qt\$(Platform)\include -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtWidgets -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtGui -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtCore %(Fullpath) -o $(IntDir)generated\moc_%(Filename).cpp + MOC %(Filename).h + $(IntDir)generated\moc_%(Filename).cpp + %(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe;%(AdditionalInputs) $(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe -DUNICODE -DWIN32 -DWIN64 -D_WIN32 -D_WIN64 -DRENDERDOC_PLATFORM_WIN32 -DSCINTILLA_QT=1 -DSCI_LEXER=1 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1900 -I$(ProjectDir) -I$(SolutionDir)\renderdoc\api\replay -I$(ProjectDir)3rdparty\qt\$(Platform)\mkspecs/win32-msvc2015 -I$(ProjectDir)3rdparty\qt\$(Platform)\include -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtWidgets -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtGui -I$(ProjectDir)3rdparty\qt\$(Platform)\include\QtCore %(Fullpath) -o $(IntDir)generated\moc_%(Filename).cpp @@ -1189,6 +1198,12 @@ $(IntDir)generated\ui_%(Filename).h Designer + + %(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe;%(AdditionalInputs) + $(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe %(Fullpath) -o $(IntDir)generated\ui_%(Filename).h + UIC %(Filename).ui + $(IntDir)generated\ui_%(Filename).h + %(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe;%(AdditionalInputs) $(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe %(Fullpath) -o $(IntDir)generated\ui_%(Filename).h diff --git a/qrenderdoc/qrenderdoc_local.vcxproj.filters b/qrenderdoc/qrenderdoc_local.vcxproj.filters index b51a2a975..30b5a80fc 100644 --- a/qrenderdoc/qrenderdoc_local.vcxproj.filters +++ b/qrenderdoc/qrenderdoc_local.vcxproj.filters @@ -531,6 +531,12 @@ Generated Files + + Generated Files + + + Windows\Dialogs + @@ -1235,5 +1241,11 @@ Widgets + + Windows\Dialogs + + + Windows\Dialogs + \ No newline at end of file