Skip to content

Commit df1c0e4

Browse files
authored
Feature/training feedback (#112)
* Add checkbox for training feedback to settings dialog * Make done regions white, refactor code for updating region color * Show full volume when no region selected * Add FeedbackDialog and other feedback classes * Reading and writing training feedback * Add feedback table filtering and split and merge columns
1 parent ffd9d9f commit df1c0e4

23 files changed

+712
-35
lines changed

qt/FeedbackDialog.cxx

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include "FeedbackDialog.h"
2+
3+
#include "Feedback.h"
4+
#include "FeedbackTable.h"
5+
#include "VisualizationContainer.h"
6+
7+
// Constructor
8+
FeedbackDialog::FeedbackDialog(QWidget* parent, VisualizationContainer* visualizationContainer)
9+
: QDialog(parent), visualizationContainer(visualizationContainer) {
10+
// Create the GUI from the Qt Designer file
11+
setupUi(this);
12+
13+
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
14+
15+
// Create table
16+
table = new FeedbackTable(this);
17+
table->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
18+
table->update(visualizationContainer->GetRegions());
19+
tableContainer->layout()->addWidget(table);
20+
21+
QObject::connect(table, &FeedbackTable::regionFeedback, this, &FeedbackDialog::on_regionFeedback);
22+
QObject::connect(table, &FeedbackTable::highlightRegion, this, &FeedbackDialog::on_highlightRegion);
23+
24+
updateRegions();
25+
}
26+
27+
FeedbackDialog::~FeedbackDialog() {
28+
if (table) delete table;
29+
}
30+
31+
void FeedbackDialog::updateRegions() {
32+
table->update(visualizationContainer->GetRegions());
33+
}
34+
35+
void FeedbackDialog::on_filterCheckBox_stateChanged(int state) {
36+
printf("%d\n", state);
37+
38+
table->setFilter(state != 0);
39+
}
40+
41+
void FeedbackDialog::on_regionFeedback(int label, Feedback::FeedbackType type, bool value) {
42+
visualizationContainer->SetRegionFeedback(label, type, value);
43+
}
44+
45+
void FeedbackDialog::on_highlightRegion(int label) {
46+
visualizationContainer->HighlightRegion((unsigned short)label);
47+
}

qt/FeedbackDialog.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef FeedbackDialog_H
2+
#define FeedbackDialog_H
3+
4+
#include "ui_FeedbackDialog.h"
5+
6+
#include "Feedback.h"
7+
8+
class FeedbackTable;
9+
class VisualizationContainer;
10+
11+
class FeedbackDialog : public QDialog, private Ui::FeedbackDialog {
12+
Q_OBJECT
13+
public:
14+
FeedbackDialog(QWidget* parent, VisualizationContainer* visualizationContainer);
15+
virtual ~FeedbackDialog();
16+
17+
void updateRegions();
18+
19+
public slots:
20+
// Use Qt's auto-connect magic to tie GUI widgets to slots,
21+
// removing the need to call connect() explicitly.
22+
// Names of the methods must follow the naming convention
23+
// on_<widget name>_<signal name>(<signal parameters>).
24+
void on_filterCheckBox_stateChanged(int state);
25+
26+
void on_regionFeedback(int label, Feedback::FeedbackType type, bool value);
27+
void on_highlightRegion(int label);
28+
29+
protected:
30+
FeedbackTable* table;
31+
VisualizationContainer* visualizationContainer;
32+
};
33+
34+
#endif

qt/FeedbackDialog.ui

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>FeedbackDialog</class>
4+
<widget class="QDialog" name="FeedbackDialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>400</width>
10+
<height>413</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Feedback Dialog</string>
15+
</property>
16+
<layout class="QVBoxLayout" name="verticalLayout">
17+
<item>
18+
<widget class="QGroupBox" name="tableContainer">
19+
<property name="title">
20+
<string>Regions</string>
21+
</property>
22+
<layout class="QVBoxLayout" name="verticalLayout_3">
23+
<item>
24+
<widget class="QCheckBox" name="filterCheckBox">
25+
<property name="text">
26+
<string>Filter by correction needed</string>
27+
</property>
28+
</widget>
29+
</item>
30+
<item>
31+
<layout class="QVBoxLayout" name="verticalLayout_2"/>
32+
</item>
33+
</layout>
34+
</widget>
35+
</item>
36+
<item>
37+
<widget class="QDialogButtonBox" name="buttonBox">
38+
<property name="orientation">
39+
<enum>Qt::Horizontal</enum>
40+
</property>
41+
<property name="standardButtons">
42+
<set>QDialogButtonBox::Close</set>
43+
</property>
44+
</widget>
45+
</item>
46+
</layout>
47+
</widget>
48+
<resources/>
49+
<connections>
50+
<connection>
51+
<sender>buttonBox</sender>
52+
<signal>accepted()</signal>
53+
<receiver>FeedbackDialog</receiver>
54+
<slot>accept()</slot>
55+
<hints>
56+
<hint type="sourcelabel">
57+
<x>248</x>
58+
<y>254</y>
59+
</hint>
60+
<hint type="destinationlabel">
61+
<x>157</x>
62+
<y>274</y>
63+
</hint>
64+
</hints>
65+
</connection>
66+
<connection>
67+
<sender>buttonBox</sender>
68+
<signal>rejected()</signal>
69+
<receiver>FeedbackDialog</receiver>
70+
<slot>reject()</slot>
71+
<hints>
72+
<hint type="sourcelabel">
73+
<x>316</x>
74+
<y>260</y>
75+
</hint>
76+
<hint type="destinationlabel">
77+
<x>286</x>
78+
<y>274</y>
79+
</hint>
80+
</hints>
81+
</connection>
82+
</connections>
83+
</ui>

qt/FeedbackTable.cxx

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#include "FeedbackTable.h"
2+
3+
#include <QApplication>
4+
#include <QHeaderView>
5+
#include <QTableWidgetItem>
6+
#include <QIcon>
7+
#include <QLabel>
8+
#include <QStyle>
9+
#include <QPushButton>
10+
#include <QSignalMapper>
11+
#include <QCheckBox>
12+
#include <QColorDialog>
13+
14+
#include "Feedback.h"
15+
#include "LabelColors.h"
16+
#include "Region.h"
17+
#include "RegionCollection.h"
18+
19+
FeedbackTable::FeedbackTable(QWidget* parent) : QTableWidget(parent) {
20+
QStringList headers;
21+
headers << "Id" << "Undertraced" << "Overtraced" << "Add to Slice" << "Remove Id" << "Split" << "Merge" << "Correct from Split/Merge";
22+
setColumnCount(headers.length());
23+
setHorizontalHeaderLabels(headers);
24+
verticalHeader()->setVisible(false);
25+
enableSorting();
26+
setMouseTracking(true);
27+
setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
28+
29+
regions = nullptr;
30+
31+
currentRegionLabel = 0;
32+
33+
filter = false;
34+
35+
QObject::connect(this, &FeedbackTable::cellEntered, this, &FeedbackTable::on_cellEntered);
36+
QObject::connect(this, &FeedbackTable::cellClicked, this, &FeedbackTable::on_cellClicked);
37+
}
38+
39+
void FeedbackTable::update() {
40+
if (!regions) return;
41+
42+
disableSorting();
43+
44+
std::vector<Region*> displayRegions;
45+
46+
for (RegionCollection::Iterator it = regions->Begin(); it != regions->End(); it++) {
47+
Region* region = regions->Get(it);
48+
49+
if (!filter || region->GetFeedback()->HasFeedback()) {
50+
displayRegions.push_back(region);
51+
}
52+
}
53+
54+
int numRegions = (int)displayRegions.size();
55+
setRowCount(numRegions);
56+
57+
// Add rows for each region
58+
for (int i = 0; i < numRegions; i++) {
59+
Region* region = displayRegions[i];
60+
int label = (int)region->GetLabel();
61+
62+
// Id
63+
QTableWidgetItem* idItem = new QTableWidgetItem();
64+
idItem->setData(0, label);
65+
idItem->setTextAlignment(Qt::AlignCenter);
66+
idItem->setFlags(Qt::ItemIsSelectable);
67+
68+
setItem(i, Id, idItem);
69+
70+
// Check boxes
71+
addCheckWidget(i, Undertraced, region->GetFeedback()->GetValue(Feedback::Undertraced));
72+
addCheckWidget(i, Overtraced, region->GetFeedback()->GetValue(Feedback::Overtraced));
73+
addCheckWidget(i, AddToSlice, region->GetFeedback()->GetValue(Feedback::AddToSlice));
74+
addCheckWidget(i, RemoveId, region->GetFeedback()->GetValue(Feedback::RemoveId));
75+
addCheckWidget(i, Split, region->GetFeedback()->GetValue(Feedback::Split));
76+
addCheckWidget(i, Merge, region->GetFeedback()->GetValue(Feedback::Merge));
77+
addCheckWidget(i, CorrectSplitMerge, region->GetFeedback()->GetValue(Feedback::CorrectSplitMerge));
78+
}
79+
80+
enableSorting();
81+
82+
selectRegionLabel(currentRegionLabel);
83+
}
84+
85+
void FeedbackTable::update(RegionCollection* regionCollection) {
86+
regions = regionCollection;
87+
88+
update();
89+
}
90+
91+
void FeedbackTable::selectRegionLabel(unsigned short label) {
92+
currentRegionLabel = label;
93+
QString labelString = QString::number(currentRegionLabel);
94+
95+
for (int i = 0; i < rowCount(); i++) {
96+
QTableWidgetItem* ti = item(i, 0);
97+
98+
if (ti->text() == labelString) {
99+
ti->setBackgroundColor(QColor("#1d91c0"));
100+
ti->setTextColor(QColor("white"));
101+
102+
scrollToItem(ti);
103+
}
104+
else {
105+
ti->setBackgroundColor(QColor("white"));
106+
ti->setTextColor(QColor("black"));
107+
}
108+
}
109+
}
110+
111+
void FeedbackTable::setFilter(bool filterRows) {
112+
filter = filterRows;
113+
114+
update();
115+
}
116+
117+
void FeedbackTable::on_cellEntered(int row, int column) {
118+
QString labelString = QString::number(currentRegionLabel);
119+
120+
if (column == Id) {
121+
// Highlight
122+
for (int i = 0; i < rowCount(); i++) {
123+
QTableWidgetItem* ti = item(i, 0);
124+
125+
if (ti->text() == labelString) continue;
126+
127+
if (i == row) {
128+
ti->setBackgroundColor(QColor("#bfe6f5"));
129+
}
130+
else {
131+
ti->setBackgroundColor(QColor("white"));
132+
}
133+
}
134+
135+
emit(highlightRegion(rowLabel(row)));
136+
}
137+
else {
138+
// Clear highlight
139+
for (int i = 0; i < rowCount(); i++) {
140+
QTableWidgetItem* ti = item(i, 0);
141+
142+
if (ti->text() == labelString) continue;
143+
144+
ti->setBackgroundColor(QColor("white"));
145+
}
146+
147+
emit(highlightRegion(0));
148+
}
149+
}
150+
151+
void FeedbackTable::on_cellClicked(int row, int column) {
152+
if (column == Id) return;
153+
154+
disableSorting();
155+
156+
QCheckBox * checkBox = (QCheckBox*)cellWidget(row, column);
157+
checkBox->toggle();
158+
159+
emit(regionFeedback(rowLabel(row), columnToFeedback(column), checkBox->isChecked()));
160+
161+
enableSorting();
162+
}
163+
164+
/*
165+
void FeedbackTable::leaveEvent(QEvent* event) {
166+
// Clear highlight
167+
QString labelString = QString::number(currentRegionLabel);
168+
169+
for (int i = 0; i < rowCount(); i++) {
170+
QTableWidgetItem* ti = item(i, 0);
171+
172+
if (ti->text() == labelString) continue;
173+
174+
ti->setBackgroundColor(QColor("white"));
175+
}
176+
177+
emit(highlightRegion(0));
178+
}
179+
*/
180+
181+
int FeedbackTable::rowLabel(int row) {
182+
return item(row, 0)->text().toInt();
183+
}
184+
185+
void FeedbackTable::disableSorting() {
186+
QObject::disconnect(horizontalHeader(), &QHeaderView::sortIndicatorChanged, this, &QTableWidget::resizeColumnsToContents);
187+
setSortingEnabled(false);
188+
}
189+
190+
void FeedbackTable::enableSorting() {
191+
setSortingEnabled(true);
192+
QObject::connect(horizontalHeader(), &QHeaderView::sortIndicatorChanged, this, &QTableWidget::resizeColumnsToContents);
193+
resizeColumnsToContents();
194+
}
195+
196+
void FeedbackTable::addCheckWidget(int row, int column, bool checked) {
197+
QTableWidgetItem* item = new QTableWidgetItem();
198+
item->setFlags(Qt::ItemIsSelectable);
199+
item->setData(0, checked);
200+
item->setTextColor(QColor("white"));
201+
202+
QCheckBox* checkBox = new QCheckBox();
203+
checkBox->setChecked(checked);
204+
checkBox->setStyleSheet("margin-left:auto;margin-right:auto;");
205+
checkBox->setAttribute(Qt::WA_TransparentForMouseEvents);
206+
207+
setItem(row, column, item);
208+
setCellWidget(row, column, checkBox);
209+
}
210+
211+
Feedback::FeedbackType FeedbackTable::columnToFeedback(int column) {
212+
switch (column) {
213+
case Undertraced: return Feedback::Undertraced;
214+
case Overtraced: return Feedback::Overtraced;
215+
case AddToSlice: return Feedback::AddToSlice;
216+
case RemoveId: return Feedback::RemoveId;
217+
case Split: return Feedback::Split;
218+
case Merge: return Feedback::Merge;
219+
case CorrectSplitMerge: return Feedback::CorrectSplitMerge;
220+
default: return Feedback::Undertraced;
221+
}
222+
}

0 commit comments

Comments
 (0)