File: GridEditor.cpp

package info (click to toggle)
dyssol 1.5.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 18,184 kB
  • sloc: cpp: 53,870; sh: 85; python: 59; makefile: 11
file content (220 lines) | stat: -rw-r--r-- 7,820 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/* Copyright (c) 2020, Dyssol Development Team.
 * Copyright (c) 2023, DyssolTEC GmbH.
 * All rights reserved. This file is part of Dyssol. See LICENSE file for license information. */

#include "GridEditor.h"
#include "Flowsheet.h"
#include "BaseUnit.h"
#include "ContainerFunctions.h"
#include "DyssolUtilities.h"
#include "DyssolStringConstants.h"
#include "SignalBlocker.h"
#include <QMessageBox>
#include <QStandardItem>


CGridEditor::CGridEditor(CFlowsheet* _flowsheet, const CMaterialsDatabase& _materialsDB, QWidget* _parent, Qt::WindowFlags _flags)
	: CQtDialog{ _parent, _flags }
	, m_materialsDB{ _materialsDB }
	, m_flowsheet{ _flowsheet }
	, m_grid{ _flowsheet->GetGrid() }
{
	ui.setupUi(this);
	ui.splitter->setSizes(QList{ 140, 400 });
	setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint);

	SetHelpLink("001_ui/gui.html#sec-gui-menu-setup-grids");
}

void CGridEditor::InitializeConnections() const
{
	connect(ui.treeGrids                                  , &CQtTree::currentItemChanged  , this, &CGridEditor::GridSelected);
	connect(ui.treeGrids                                  , &CQtTree::CheckBoxStateChanged, this, &CGridEditor::GridActivityChanged);
	connect(ui.buttonPlus                                 , &QPushButton::clicked         , this, &CGridEditor::AddDistributionClicked);
	connect(ui.buttonMinus                                , &QPushButton::clicked         , this, &CGridEditor::RemDistributionClicked);
	connect(ui.buttonBox->button(QDialogButtonBox::Apply) , &QPushButton::clicked         , this, &CGridEditor::ApplyChanges);
	connect(ui.buttonBox->button(QDialogButtonBox::Ok)    , &QPushButton::clicked         , this, &CGridEditor::accept);
	connect(ui.buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked         , this, &CGridEditor::reject);
}

void CGridEditor::setVisible(bool _visible)
{
	if (_visible && !isVisible())
		UpdateWholeView();
	QDialog::setVisible(_visible);
}

void CGridEditor::accept()
{
	if (ApplyChanges())
		QDialog::accept();
}

void CGridEditor::UpdateFromFlowsheet()
{
	if (isVisible())
		UpdateWholeView();
}

void CGridEditor::UpdateWholeView()
{
	UpdateGridsList();
	UpdateDimensionsList();
}

void CGridEditor::UpdateGridsList() const
{
	[[maybe_unused]] CSignalBlocker blocker{ ui.treeGrids };
	const auto oldData = ui.treeGrids->GetCurrentDataQStr(1); // key of currently selected entity
	ui.treeGrids->clear();
	ui.treeGrids->setColumnCount(2);
	const auto& mainGrid = m_flowsheet->GetGrid();
	// add global grid
	auto* global = ui.treeGrids->CreateItem();
	ui.treeGrids->SetCheckBox(global, 0, "", true)->setEnabled(false);
	ui.treeGrids->SetText(global, 1, "Global", "global");
	// add unit grids
	bool allSame = true;
	auto* units = ui.treeGrids->CreateItem(0, "Unit-specific", CQtTree::ItemNotSelectabledNotEditable, "unit-specific");
	for (const auto& u : m_flowsheet->GetAllUnits())
	{
		const bool exist = u->GetModel() != nullptr;
		const bool activ = exist && mainGrid != u->GetModel()->GetGrid();
		allSame &= !activ;
		auto* item = ui.treeGrids->CreateItem(units);
		ui.treeGrids->SetCheckBox(item, 0, "", activ)->setEnabled(exist);
		ui.treeGrids->SetText(item, 1, u->GetName(), QString::fromStdString(u->GetKey()));
		CQtTree::SetItemFlags(item, exist ? CQtTree::EFlags::ENABLED : CQtTree::EFlags::DISABLED);
	}
	// resize columns and expand/contract rows
	for (int i = 0; i < ui.treeGrids->columnCount(); ++i)
		ui.treeGrids->resizeColumnToContents(i);
	units->setExpanded(!allSame);
	// restore/set current item
	blocker.Unblock();
	ui.treeGrids->SetCurrentItem(oldData);
	if (!ui.treeGrids->currentItem())
		ui.treeGrids->SetCurrentItem("global");
}

void CGridEditor::UpdateDimensionsList()
{
	[[maybe_unused]] CSignalBlocker blocker{ ui.listDims };
	ui.listDims->clear();
	for (const auto& dim : m_grid.GetGridDimensions())
	{
		auto* widget = AddGridDimension(*dim);
		// disable the item with compounds
		if (dim->DimensionType() == DISTR_COMPOUNDS)
			widget->setEnabled(false);
	}
}

void CGridEditor::GridSelected()
{
	const auto key = ui.treeGrids->GetCurrentDataQStr(1).toStdString();
	const auto* unit = m_flowsheet->GetUnit(key);
	const auto* model = unit ? unit->GetModel() : nullptr;
	if (key != "global" && model)
		m_grid = model->GetGrid();
	else
		m_grid = m_flowsheet->GetGrid();
	UpdateDimensionsList();
}

void CGridEditor::GridActivityChanged(const QCheckBox* _checkbox, const QTreeWidgetItem* _item)
{
	if (_checkbox->isChecked()) return;
	const auto key = ui.treeGrids->GetDataQStr(_item, 1).toStdString();
	auto* model = m_flowsheet->GetUnit(key)->GetModel();
	if (!model) return UpdateGridsList();
	const auto name = QString::fromStdString(m_flowsheet->GetUnit(key)->GetName());
	const auto reply = QMessageBox::question(this, "Confirm removal", tr("Set global grid to unit '%1'?").arg(name), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
	if (reply != QMessageBox::Yes) return UpdateGridsList();
	model->SetGrid(m_flowsheet->GetGrid());
	m_flowsheet->UpdateGrids(); // notify the flowsheet
	GridSelected();				// update selection and view
}

void CGridEditor::AddDistributionClicked()
{
	[[maybe_unused]] CSignalBlocker blocker{ ui.listDims };
	AddGridDimension(CGridDimensionNumeric{ DISTR_UNDEFINED });
}

void CGridEditor::RemDistributionClicked()
{
	const int row = ui.listDims->currentRow();
	if (row <= 0 || row >= ui.listDims->count()) return;
	const auto* widget = dynamic_cast<CDimensionParameters*>(ui.listDims->itemWidget(ui.listDims->currentItem()));
	const int iName = GetDistributionTypeIndex(widget->GetDistributionType());
	const auto name = iName != -1 ? DISTR_NAMES[iName] : "";
	const auto reply = QMessageBox::question(this, "Confirm removal", tr("Remove distribution '%1'?").arg(name), QMessageBox::Yes | QMessageBox::No);
	if (reply != QMessageBox::Yes) return;
	delete ui.listDims->takeItem(row);
}

CDimensionParameters* CGridEditor::AddGridDimension(const CGridDimension& _dim)
{
	[[maybe_unused]] CSignalBlocker blocker{ ui.listDims };
	const auto widget = new CDimensionParameters{ _dim, m_materialsDB, this };
	auto* item = new QListWidgetItem();
	item->setData(Qt::UserRole, E2I(_dim.DimensionType()));
	item->setSizeHint(widget->minimumSizeHint() * 1.1);
	ui.listDims->addItem(item);
	ui.listDims->setItemWidget(item, widget);
	return widget;
}

bool CGridEditor::ApplyChanges()
{
	if (!IsValid()) return false;

	QApplication::setOverrideCursor(Qt::WaitCursor);

	// build the grid
	CMultidimensionalGrid newGrid;
	for (int i = 0; i < ui.listDims->count(); ++i)
		newGrid.AddDimension(dynamic_cast<CDimensionParameters*>(ui.listDims->itemWidget(ui.listDims->item(i)))->GetGrid());

	// set the grid
	const auto key = ui.treeGrids->GetCurrentDataQStr(1).toStdString();
	if (key.empty()) return false;
	if (key == "global")
		m_flowsheet->SetMainGrid(newGrid);
	else if (auto* model = m_flowsheet->GetUnit(key)->GetModel())
	{
		model->SetGrid(newGrid);
		m_flowsheet->UpdateGrids(); // notify the flowsheet
	}

	// update widgets
	UpdateGridsList();
	emit DataChanged();

	QApplication::restoreOverrideCursor();
	return true;
}

bool CGridEditor::IsValid()
{
	std::vector<EDistrTypes> allTypes(ui.listDims->count());
	for (int i = 0; i < ui.listDims->count(); ++i)
		allTypes[i] = dynamic_cast<CDimensionParameters*>(ui.listDims->itemWidget(ui.listDims->item(i)))->GetDistributionType();
	if (!VectorUnique(allTypes))
	{
		QMessageBox::warning(this, "Warning", StrConst::GE_ErrorDuplicates);
		return false;
	}

	for (int i = 0; i < ui.listDims->count(); ++i)
	{
		const auto widget = dynamic_cast<CDimensionParameters*>(ui.listDims->itemWidget(ui.listDims->item(i)));
		if (!widget->IsValid())
		{
			QMessageBox::warning(this, "Warning", widget->LastMessage());
			return false;
		}
	}
	return true;
}