• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

paulmthompson / WhiskerToolbox / 18080728054

28 Sep 2025 06:50PM UTC coverage: 70.231% (-0.08%) from 70.31%
18080728054

push

github

paulmthompson
can delete from group manager

29 of 108 new or added lines in 7 files covered. (26.85%)

44242 of 62995 relevant lines covered (70.23%)

1123.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.59
/src/WhiskerToolbox/GroupManagementWidget/GroupManagementWidget.cpp
1
#include "GroupManagementWidget.hpp"
2
#include "GroupManager.hpp"
3
#include "ui_GroupManagementWidget.h"
4

5
#include <QColorDialog>
6
#include <QDebug>
7
#include <QHeaderView>
8
#include <QPushButton>
9
#include <QTableWidget>
10
#include <QTableWidgetItem>
11
#include <QContextMenuEvent>
12
#include <QMenu>
13
#include <QAction>
14
#include <QMessageBox>
15

16
GroupManagementWidget::GroupManagementWidget(GroupManager * group_manager, QWidget * parent)
3✔
17
    : QWidget(parent),
18
      m_group_manager(group_manager),
3✔
19
      m_ui(new Ui::GroupManagementWidget()),
6✔
20
      m_updating_table(false) {
3✔
21

22
    m_ui->setupUi(this);
3✔
23
    setupUI();
3✔
24

25
    // Connect to GroupManager signals
26
    connect(m_group_manager, &GroupManager::groupCreated,
9✔
27
            this, &GroupManagementWidget::onGroupCreated);
6✔
28
    connect(m_group_manager, &GroupManager::groupRemoved,
9✔
29
            this, &GroupManagementWidget::onGroupRemoved);
6✔
30
    connect(m_group_manager, &GroupManager::groupModified,
9✔
31
            this, &GroupManagementWidget::onGroupModified);
6✔
32

33
    // Connect table signals
34
    connect(m_ui->groupsTable, &QTableWidget::itemChanged,
9✔
35
            this, &GroupManagementWidget::onItemChanged);
6✔
36
    connect(m_ui->groupsTable, &QTableWidget::itemSelectionChanged,
9✔
37
            this, &GroupManagementWidget::onSelectionChanged);
6✔
38

39
    // Connect button signals
40
    connect(m_ui->addButton, &QPushButton::clicked,
9✔
41
            this, &GroupManagementWidget::createNewGroup);
6✔
42
    connect(m_ui->removeButton, &QPushButton::clicked,
9✔
43
            this, &GroupManagementWidget::removeSelectedGroup);
6✔
44

45
    // Initial table refresh
46
    refreshTable();
3✔
47
    onSelectionChanged();// Update button states
3✔
48
}
3✔
49

50
GroupManagementWidget::~GroupManagementWidget() {
3✔
51
    delete m_ui;
3✔
52
}
3✔
53

54
void GroupManagementWidget::setupUI() {
3✔
55
    // Configure table headers
56
    QHeaderView * header = m_ui->groupsTable->horizontalHeader();
3✔
57
    header->setStretchLastSection(false);
3✔
58
    header->setSectionResizeMode(0, QHeaderView::Stretch);// Name column stretches
3✔
59
    header->setSectionResizeMode(1, QHeaderView::Fixed);  // Color column fixed width
3✔
60
    header->setSectionResizeMode(2, QHeaderView::Fixed);  // Members column fixed width
3✔
61
    m_ui->groupsTable->setColumnWidth(1, 50);             // Color button column width
3✔
62
    m_ui->groupsTable->setColumnWidth(2, 60);             // Members column width
3✔
63

64
    m_ui->groupsTable->verticalHeader()->setVisible(false);
3✔
65
}
3✔
66

67
void GroupManagementWidget::refreshTable() {
3✔
68
    m_updating_table = true;
3✔
69

70
    // Clear the table
71
    m_ui->groupsTable->setRowCount(0);
3✔
72

73
    // Add rows for all groups
74
    auto const & groups = m_group_manager->getGroups();
3✔
75
    int row = 0;
3✔
76
    for (auto it = groups.begin(); it != groups.end(); ++it) {
3✔
77
        addGroupRow(it.key(), row);
×
78
        row++;
×
79
    }
80

81
    m_updating_table = false;
3✔
82
}
6✔
83

84
void GroupManagementWidget::addGroupRow(int group_id, int row) {
4✔
85
    auto group = m_group_manager->getGroup(group_id);
4✔
86
    if (!group.has_value()) {
4✔
87
        return;
×
88
    }
89

90
    m_ui->groupsTable->insertRow(row);
4✔
91

92
    // Name column
93
    auto * name_item = new QTableWidgetItem(group.value().name);
4✔
94
    name_item->setData(Qt::UserRole, group_id);// Store group ID in the item
4✔
95
    m_ui->groupsTable->setItem(row, 0, name_item);
4✔
96

97
    // Color column
98
    QPushButton * color_button = createColorButton(group_id);
4✔
99
    updateColorButton(color_button, group.value().color);
4✔
100
    m_ui->groupsTable->setCellWidget(row, 1, color_button);
4✔
101

102
    // Members column
103
    int const member_count = m_group_manager->getGroupMemberCount(group_id);
4✔
104
    auto * members_item = new QTableWidgetItem(QString::number(member_count));
4✔
105
    members_item->setFlags(members_item->flags() & ~Qt::ItemIsEditable);// Make read-only
4✔
106
    members_item->setTextAlignment(Qt::AlignCenter);
4✔
107
    m_ui->groupsTable->setItem(row, 2, members_item);
4✔
108
}
4✔
109

110
QPushButton * GroupManagementWidget::createColorButton(int group_id) {
4✔
111
    auto * button = new QPushButton();
4✔
112
    button->setMaximumSize(30, 20);
4✔
113
    button->setMinimumSize(30, 20);
4✔
114
    button->setProperty("group_id", group_id);
4✔
115

116
    connect(button, &QPushButton::clicked,
12✔
117
            this, &GroupManagementWidget::onColorButtonClicked);
8✔
118

119
    return button;
4✔
120
}
121

122
void GroupManagementWidget::updateColorButton(QPushButton * button, QColor const & color) {
10✔
123
    QString const style = QString("QPushButton { background-color: %1; border: 1px solid #666; }")
30✔
124
                            .arg(color.name());
20✔
125
    button->setStyleSheet(style);
10✔
126
}
20✔
127

128
void GroupManagementWidget::createNewGroup() {
×
129
    QString const name = QString("Group %1").arg(m_group_manager->getGroups().size() + 1);
×
130
    m_group_manager->createGroup(name);
×
131
}
×
132

133
void GroupManagementWidget::removeSelectedGroup() {
×
134
    int const current_row = m_ui->groupsTable->currentRow();
×
135
    if (current_row < 0) {
×
136
        return;
×
137
    }
138

139
    int const group_id = getGroupIdForRow(current_row);
×
140
    if (group_id != -1) {
×
141
        m_group_manager->removeGroup(group_id);
×
142
    }
143
}
144

145
void GroupManagementWidget::onGroupCreated(int group_id) {
4✔
146
    if (!m_updating_table) {
4✔
147
        int const row = m_ui->groupsTable->rowCount();
4✔
148
        addGroupRow(group_id, row);
4✔
149
    }
150
}
4✔
151

152
void GroupManagementWidget::onGroupRemoved(int group_id) {
1✔
153
    if (!m_updating_table) {
1✔
154
        int const row = findRowForGroupId(group_id);
1✔
155
        if (row >= 0) {
1✔
156
            m_ui->groupsTable->removeRow(row);
1✔
157
        }
158
    }
159
}
1✔
160

161
void GroupManagementWidget::onGroupModified(int group_id) {
6✔
162
    if (!m_updating_table) {
6✔
163
        int const row = findRowForGroupId(group_id);
6✔
164
        if (row >= 0) {
6✔
165
            auto group = m_group_manager->getGroup(group_id);
6✔
166
            if (group.has_value()) {
6✔
167
                // Update name
168
                QTableWidgetItem * name_item = m_ui->groupsTable->item(row, 0);
6✔
169
                if (name_item) {
6✔
170
                    m_updating_table = true;
6✔
171
                    name_item->setText(group.value().name);
6✔
172
                    m_updating_table = false;
6✔
173
                }
174

175
                // Update color button
176
                auto * color_button = qobject_cast<QPushButton *>(m_ui->groupsTable->cellWidget(row, 1));
6✔
177
                if (color_button) {
6✔
178
                    updateColorButton(color_button, group.value().color);
6✔
179
                }
180

181
                // Update member count
182
                QTableWidgetItem * members_item = m_ui->groupsTable->item(row, 2);
6✔
183
                if (members_item) {
6✔
184
                    int const member_count = m_group_manager->getGroupMemberCount(group_id);
6✔
185
                    members_item->setText(QString::number(member_count));
6✔
186
                }
187
            }
188
        }
6✔
189
    }
190
}
6✔
191

192
void GroupManagementWidget::onPointAssignmentsChanged(std::unordered_set<int> const & affected_groups) {
×
193
    if (!m_updating_table) {
×
194
        // Update member counts for all affected groups
195
        for (int const group_id: affected_groups) {
×
196
            int const row = findRowForGroupId(group_id);
×
197
            if (row >= 0) {
×
198
                QTableWidgetItem * members_item = m_ui->groupsTable->item(row, 2);
×
199
                if (members_item) {
×
200
                    int const member_count = m_group_manager->getGroupMemberCount(group_id);
×
201
                    members_item->setText(QString::number(member_count));
×
202
                }
203
            }
204
        }
205
    }
206
}
×
207

208
void GroupManagementWidget::onItemChanged(QTableWidgetItem * item) {
13✔
209
    if (m_updating_table || !item || item->column() != 0) {
13✔
210
        return;// Only handle name column changes
9✔
211
    }
212

213
    int const group_id = item->data(Qt::UserRole).toInt();
4✔
214
    QString const new_name = item->text().trimmed();
4✔
215

216
    if (new_name.isEmpty()) {
4✔
217
        // Don't allow empty names, revert to original
218
        m_updating_table = true;
×
219
        auto group = m_group_manager->getGroup(group_id);
×
220
        if (group.has_value()) {
×
221
            item->setText(group.value().name);
×
222
        }
223
        m_updating_table = false;
×
224
        return;
×
225
    }
×
226

227
    // Update the group name
228
    m_group_manager->setGroupName(group_id, new_name);
4✔
229
}
4✔
230

231
void GroupManagementWidget::onColorButtonClicked() {
×
232
    auto * button = qobject_cast<QPushButton *>(sender());
×
233
    if (!button) {
×
234
        return;
×
235
    }
236

237
    int const group_id = button->property("group_id").toInt();
×
238
    auto group = m_group_manager->getGroup(group_id);
×
239
    if (!group.has_value()) {
×
240
        return;
×
241
    }
242

243
    QColor const new_color = QColorDialog::getColor(group.value().color, this, "Select Group Color");
×
244
    if (new_color.isValid() && new_color != group.value().color) {
×
245
        m_group_manager->setGroupColor(group_id, new_color);
×
246
    }
247
}
×
248

249
void GroupManagementWidget::onSelectionChanged() {
3✔
250
    bool const has_selection = m_ui->groupsTable->currentRow() >= 0;
3✔
251
    m_ui->removeButton->setEnabled(has_selection);
3✔
252
}
3✔
253

254
int GroupManagementWidget::getGroupIdForRow(int row) const {
7✔
255
    QTableWidgetItem * item = m_ui->groupsTable->item(row, 0);
7✔
256
    return item ? item->data(Qt::UserRole).toInt() : -1;
14✔
257
}
258

259
int GroupManagementWidget::findRowForGroupId(int group_id) const {
7✔
260
    for (int row = 0; row < m_ui->groupsTable->rowCount(); ++row) {
7✔
261
        if (getGroupIdForRow(row) == group_id) {
7✔
262
            return row;
7✔
263
        }
264
    }
265
    return -1;
×
266
}
267

NEW
268
void GroupManagementWidget::contextMenuEvent(QContextMenuEvent * event) {
×
NEW
269
    showContextMenu(event->globalPos());
×
NEW
270
}
×
271

NEW
272
void GroupManagementWidget::showContextMenu(QPoint const & pos) {
×
273
    // Get the group at the current position
NEW
274
    int const current_row = m_ui->groupsTable->currentRow();
×
NEW
275
    if (current_row < 0) {
×
NEW
276
        return;
×
277
    }
278

NEW
279
    int const group_id = getGroupIdForRow(current_row);
×
NEW
280
    if (group_id == -1) {
×
NEW
281
        return;
×
282
    }
283

284
    // Create context menu
NEW
285
    QMenu context_menu(this);
×
286
    
287
    // Add delete group and entities action
NEW
288
    QAction * delete_action = context_menu.addAction("Delete Group and All Data");
×
NEW
289
    delete_action->setIcon(QIcon::fromTheme("edit-delete"));
×
290
    
291
    // Show the menu and handle the action
NEW
292
    QAction * selected_action = context_menu.exec(pos);
×
NEW
293
    if (selected_action == delete_action) {
×
NEW
294
        deleteSelectedGroupAndEntities();
×
295
    }
NEW
296
}
×
297

NEW
298
void GroupManagementWidget::deleteSelectedGroupAndEntities() {
×
NEW
299
    int const current_row = m_ui->groupsTable->currentRow();
×
NEW
300
    if (current_row < 0) {
×
NEW
301
        return;
×
302
    }
303

NEW
304
    int const group_id = getGroupIdForRow(current_row);
×
NEW
305
    if (group_id == -1) {
×
NEW
306
        return;
×
307
    }
308

309
    // Get group info for confirmation dialog
NEW
310
    auto group = m_group_manager->getGroup(group_id);
×
NEW
311
    if (!group.has_value()) {
×
NEW
312
        return;
×
313
    }
314

NEW
315
    int const member_count = m_group_manager->getGroupMemberCount(group_id);
×
316
    
317
    // Show confirmation dialog
NEW
318
    QMessageBox::StandardButton reply = QMessageBox::question(
×
319
        this,
320
        "Delete Group and Data",
NEW
321
        QString("Are you sure you want to delete group '%1' and all %2 entities in it?\n\nThis action cannot be undone.")
×
NEW
322
            .arg(group.value().name)
×
NEW
323
            .arg(member_count),
×
324
        QMessageBox::Yes | QMessageBox::No,
325
        QMessageBox::No
NEW
326
    );
×
327

NEW
328
    if (reply == QMessageBox::Yes) {
×
329
        // Delete the group and all its entities
NEW
330
        m_group_manager->deleteGroupAndEntities(group_id);
×
331
    }
NEW
332
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc