File: ReactionWidget.cpp

package info (click to toggle)
dyssol 1.5.0-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 18,204 kB
  • sloc: cpp: 53,870; sh: 85; python: 59; makefile: 11
file content (111 lines) | stat: -rw-r--r-- 5,171 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
/* Copyright (c) 2021, Dyssol Development Team. All rights reserved. This file is part of Dyssol. See LICENSE file for license information. */

#include "ReactionWidget.h"
#include "ContainerFunctions.h"
#include "MaterialsDatabase.h"
#include "DyssolUtilities.h"
#include "SignalBlocker.h"
#include <QScrollBar>

CReactionWidget::CReactionWidget(CChemicalReaction* _reaction, const std::vector<std::string>* _compounds, const CMaterialsDatabase* _database, QWidget* _parent)
	: QWidget{ _parent }
	, m_reaction{ _reaction }
	, m_compounds{ _compounds }
	, m_database{ _database }
{
	ui.setupUi(this);
	m_radioGroup.setExclusive(true);
	InitializeConnections();
	UpdateWholeView();
}

void CReactionWidget::InitializeConnections() const
{
	connect(ui.buttonAddSubstance   , &QPushButton::clicked             , this, &CReactionWidget::AddSubstance   );
	connect(ui.buttonRemoveSubstance, &QPushButton::clicked             , this, &CReactionWidget::RemoveSubstance);
	connect(ui.tableSubstances      , &CQtTable::itemChanged            , this, &CReactionWidget::ApplyChanges   );
	connect(ui.tableSubstances      , &CQtTable::RadioButtonStateChanged, this, &CReactionWidget::ApplyChanges   );
	connect(ui.tableSubstances      , &CQtTable::ComboBoxIndexChanged   , this, &CReactionWidget::ApplyChanges   );
}

void CReactionWidget::UpdateWholeView()
{
	if (!m_reaction) return;
	[[maybe_unused]] CSignalBlocker blocker{ ui.tableSubstances, &m_radioGroup };

	// clean radio buttons
	for (auto* b : m_radioGroup.buttons())
		m_radioGroup.removeButton(b);

	// currently selected rows
	const auto selection = ui.tableSubstances->GetCurrentCellPos();

	// update substances
	ui.tableSubstances->clearContents();
	auto substances = m_reaction->GetSubstances();
	ui.tableSubstances->setRowCount(static_cast<int>(substances.size()));
	for (int i = 0; i < static_cast<int>(substances.size()); ++i)
	{
		auto* radio = ui.tableSubstances->SetRadioButton(i, ECols::BASE, static_cast<int>(m_reaction->GetBaseSubstanceIndex()) == i);
		m_radioGroup.addButton(radio, i);
		ui.tableSubstances->SetItemEditable(i, ECols::NU, std::abs(substances[i]->nu));
		ui.tableSubstances->SetComboBox(i, ECols::MATERIAL, m_database->GetCompoundsNames(*m_compounds), *m_compounds, substances[i]->key);
		ui.tableSubstances->SetComboBox(i, ECols::PHASE, { "", "Solid", "Liquid", "Gas" }, vector_cast<size_t>(std::vector{ EPhase::UNDEFINED, EPhase::SOLID, EPhase::LIQUID, EPhase::VAPOR }), E2I(substances[i]->phase));
		ui.tableSubstances->SetComboBox(i, ECols::TYPE, { "Reactant", "Product" }, vector_cast<size_t>(std::vector{ CChemicalReaction::ESubstance::REACTANT, CChemicalReaction::ESubstance::PRODUCT }), E2I(substances[i]->GetType()));
		ui.tableSubstances->SetItemEditable(i, ECols::ORDER, std::abs(substances[i]->order));
	}

	// restore selection
	ui.tableSubstances->SetCurrentCellPos(selection);

	ui.tableSubstances->resizeColumnsToContents();
	ui.tableSubstances->resizeRowsToContents();
}

void CReactionWidget::AddSubstance()
{
	if (!m_reaction) return;
	m_reaction->AddSubstance({ "", -1, 0, EPhase::SOLID });
	UpdateWholeView();
	emit SubstancesNumberChanged();
}

void CReactionWidget::RemoveSubstance()
{
	if (!m_reaction) return;
	m_reaction->RemoveSubstance(ui.tableSubstances->currentRow());
	UpdateWholeView();
	emit SubstancesNumberChanged();
}

void CReactionWidget::ApplyChanges() const
{
	if (!m_reaction) return;

	m_reaction->SetBaseSubstance(m_radioGroup.checkedId());
	auto substances = m_reaction->GetSubstances();
	for (int i = 0; i < static_cast<int>(substances.size()); ++i)
	{
		substances[i]->nu = ui.tableSubstances->GetItemText(i, ECols::NU).toDouble();
		substances[i]->order = ui.tableSubstances->GetItemText(i, ECols::ORDER).toDouble();
		// reactants must be negative, products must bo positive
		if (ui.tableSubstances->GetComboBox(i, ECols::TYPE)->currentData().toUInt() != static_cast<uint>(substances[i]->GetType()))
			substances[i]->nu = -substances[i]->nu;
		if (ui.tableSubstances->GetComboBox(i, ECols::MATERIAL)->currentIndex() != -1)
			substances[i]->key = ui.tableSubstances->GetComboBox(i, ECols::MATERIAL)->currentData().toString().toStdString();
		if (ui.tableSubstances->GetComboBox(i, ECols::PHASE)->currentIndex() != -1)
			substances[i]->phase = static_cast<EPhase>(ui.tableSubstances->GetComboBox(i, ECols::PHASE)->currentData().toUInt());
	}
}

QSize CReactionWidget::sizeHint() const
{
	if (!m_reaction) return QWidget::sizeHint();
	const int number = static_cast<int>(m_reaction->GetSubstancesNumber());
	const int constHeight = ui.layoutButtons->sizeHint().height() + ui.tableSubstances->horizontalHeader()->height() + ui.verticalLayout->spacing() + ui.verticalLayout->contentsMargins().top() + ui.verticalLayout->contentsMargins().bottom() + 4;
	const int varHeight = number != 0 ? ui.tableSubstances->verticalHeader()->sectionSize(0) * number : 0;
	const int scrollHeight = ui.tableSubstances->horizontalScrollBar()->isVisible() ? ui.tableSubstances->horizontalScrollBar()->height() : 0;
	const int w = ui.tableSubstances->horizontalHeader()->width();
	const int h = constHeight + varHeight + scrollHeight;
	return QSize{ w, h };
}