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

paulmthompson / WhiskerToolbox / 18389801194

09 Oct 2025 09:35PM UTC coverage: 71.943% (+0.1%) from 71.826%
18389801194

push

github

paulmthompson
add correlation matrix to filtering interface

207 of 337 new or added lines in 5 files covered. (61.42%)

867 existing lines in 31 files now uncovered.

49964 of 69449 relevant lines covered (71.94%)

1103.53 hits per line

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

16.4
/src/WhiskerToolbox/Media_Widget/MediaPoint_Widget/MediaPoint_Widget.cpp
1
#include "MediaPoint_Widget.hpp"
2
#include "ui_MediaPoint_Widget.h"
3

4
#include "DataManager/DataManager.hpp"
5
#include "DataManager/Points/Point_Data.hpp"
6
#include "Media_Widget/Media_Window/Media_Window.hpp"
7
#include "Media_Widget/DisplayOptions/DisplayOptions.hpp"
8

9
#include <iostream>
10
#include <cmath>
11
#include <QPointF>
12

13
MediaPoint_Widget::MediaPoint_Widget(std::shared_ptr<DataManager> data_manager, Media_Window * scene, QWidget * parent)
3✔
14
    : QWidget(parent),
15
      ui(new Ui::MediaPoint_Widget),
6✔
16
      _data_manager{std::move(data_manager)},
3✔
17
      _scene{scene}
6✔
18
{
19
    ui->setupUi(this);
3✔
20

21
    connect(ui->color_picker, &ColorPicker_Widget::colorChanged,
9✔
22
            this, &MediaPoint_Widget::_setPointColor);
6✔
23
    connect(ui->color_picker, &ColorPicker_Widget::alphaChanged,
9✔
24
            this, &MediaPoint_Widget::_setPointAlpha);
6✔
25
    
26
    // Connect point size controls
27
    connect(ui->point_size_slider, &QSlider::valueChanged,
9✔
28
            this, &MediaPoint_Widget::_setPointSize);
6✔
29
    connect(ui->point_size_spinbox, QOverload<int>::of(&QSpinBox::valueChanged),
9✔
30
            this, &MediaPoint_Widget::_setPointSize);
6✔
31
    
32
    // Connect marker shape control
33
    connect(ui->marker_shape_combo, QOverload<int>::of(&QComboBox::currentIndexChanged),
9✔
34
            this, &MediaPoint_Widget::_setMarkerShape);
6✔
35
    
36
    // Synchronize slider and spinbox
37
    connect(ui->point_size_slider, &QSlider::valueChanged,
9✔
38
            ui->point_size_spinbox, &QSpinBox::setValue);
6✔
39
    connect(ui->point_size_spinbox, QOverload<int>::of(&QSpinBox::valueChanged),
9✔
40
            ui->point_size_slider, &QSlider::setValue);
6✔
41
}
3✔
42

43
MediaPoint_Widget::~MediaPoint_Widget() {
6✔
44
    delete ui;
3✔
45
}
6✔
46

47
void MediaPoint_Widget::showEvent(QShowEvent * event) {
×
48

49
    static_cast<void>(event);
50

51
    std::cout << "Show Event" << std::endl;
×
52
    // Connect to the new signal that provides modifier information
53
    connect(_scene, &Media_Window::leftClickMediaWithEvent, this, &MediaPoint_Widget::_handlePointClickWithModifiers);
×
54

55
}
×
56

57
void MediaPoint_Widget::hideEvent(QHideEvent * event) {
3✔
58

59
    static_cast<void>(event);
60

61
    std::cout << "Hide Event" << std::endl;
3✔
62
    disconnect(_scene, &Media_Window::leftClickMediaWithEvent, this, &MediaPoint_Widget::_handlePointClickWithModifiers);
3✔
63
    _clearPointSelection(); // Clear selection when widget is hidden
3✔
64
}
3✔
65

66
void MediaPoint_Widget::setActiveKey(std::string const & key) {
×
67
    _active_key = key;
×
68
    ui->name_label->setText(QString::fromStdString(key));
×
69
    _selection_enabled = !key.empty();
×
70

71
    // Set the color picker to the current point color if available
72
    if (!key.empty()) {
×
73
        auto config = _scene->getPointConfig(key);
×
74

75
        if (config) {
×
76
            ui->color_picker->setColor(QString::fromStdString(config.value()->hex_color));
×
77
            ui->color_picker->setAlpha(static_cast<int>(config.value()->alpha * 100));
×
78
            
79
            // Set point size controls
80
            ui->point_size_slider->blockSignals(true);
×
81
            ui->point_size_spinbox->blockSignals(true);
×
82
            ui->point_size_slider->setValue(config.value()->point_size);
×
83
            ui->point_size_spinbox->setValue(config.value()->point_size);
×
84
            ui->point_size_slider->blockSignals(false);
×
85
            ui->point_size_spinbox->blockSignals(false);
×
86
            
87
            // Set marker shape control
88
            ui->marker_shape_combo->blockSignals(true);
×
89
            ui->marker_shape_combo->setCurrentIndex(static_cast<int>(config.value()->marker_shape));
×
90
            ui->marker_shape_combo->blockSignals(false);
×
91
        }
92
    }
93
}
×
94

95

96
void MediaPoint_Widget::_handlePointClickWithModifiers(qreal x_media, qreal y_media, Qt::KeyboardModifiers modifiers) {
×
97
    if (!_selection_enabled || _active_key.empty())
×
98
        return;
×
99

100
    // Check if Alt is held for point creation
101
    if (modifiers & Qt::AltModifier) {
×
102
        // Alt+click: add new point at current time
103
        _addPointAtCurrentTime(x_media, y_media);
×
104
        return;
×
105
    }
106

107
    // Check if Ctrl is held for point movement
UNCOV
108
    if (modifiers & Qt::ControlModifier) {
×
109
        // Ctrl+click: move selected point if one is selected
110
        if (_selected_point_id != 0) {
×
111
            _moveSelectedPoint(x_media, y_media);
×
112
        }
UNCOV
113
        return;
×
114
    }
115
    
116
    // Regular click: select nearby point if exists
UNCOV
117
    EntityId nearby_point = _findNearestPoint(x_media, y_media, _selection_threshold);
×
118
    if (nearby_point != 0) {
×
119
        _selectPoint(nearby_point);
×
120
    } else {
UNCOV
121
        _clearPointSelection();
×
122
    }
123
}
124

UNCOV
125
EntityId MediaPoint_Widget::_findNearestPoint(qreal x_media, qreal y_media, float max_distance) {
×
126
    if (_active_key.empty())
×
UNCOV
127
        return 0;
×
128
    
129
    auto point_data = _data_manager->getData<PointData>(_active_key);
×
130
    if (!point_data)
×
UNCOV
131
        return 0;
×
132
    
133
    auto current_time = _data_manager->getCurrentTime();
×
134
    
135
    // Handle timeframe conversion if necessary
136
    auto video_timeframe = _data_manager->getTime(TimeKey("time"));
×
UNCOV
137
    auto point_timeframe_key = _data_manager->getTimeKey(_active_key);
×
138
    
UNCOV
139
    if (!point_timeframe_key.empty()) {
×
140
        auto point_timeframe = _data_manager->getTime(point_timeframe_key);
×
141
        if (video_timeframe.get() != point_timeframe.get()) {
×
142
            current_time = video_timeframe->getTimeAtIndex(TimeFrameIndex(current_time));
×
143
            current_time = point_timeframe->getIndexAtTime(current_time).getValue();
×
144
        }
145
    }
×
146
    
147
    auto points = point_data->getAtTime(TimeFrameIndex(current_time));
×
148
    if (points.empty())
×
UNCOV
149
        return 0;
×
150
    float min_distance = max_distance;
×
151
    int closest_point_index = -1;
×
152
    for (const auto& point : points) {
×
UNCOV
153
        float dx = point.x - static_cast<float>(x_media);
×
UNCOV
154
        float dy = point.y - static_cast<float>(y_media);
×
UNCOV
155
        float distance = std::sqrt(dx * dx + dy * dy);
×
156

157
        if (distance < min_distance) {
×
158
            min_distance = distance;
×
159
            closest_point_index = &point - &points[0]; // Get index of the closest point
×
160
        }
161
        
162
    }
163

164
    if (closest_point_index != -1) {
×
165
        auto entity_ids = point_data->getEntityIdsAtTime(TimeFrameIndex(current_time));
×
UNCOV
166
        if (closest_point_index < static_cast<int>(entity_ids.size())) {
×
167
            return entity_ids[closest_point_index];
×
168
        }
UNCOV
169
    }
×
170
    
171
    return 0;
×
172
}
×
173

UNCOV
174
void MediaPoint_Widget::_selectPoint(EntityId point_id) {
×
UNCOV
175
    _selected_point_id = point_id;
×
176
    
177
    // Use Media_Window's selection system for visual feedback
178
    _scene->selectEntity(point_id, _active_key, "point");
×
179
    std::cout << "Selected point with ID: " << point_id << std::endl;
×
180
}
×
181

182
void MediaPoint_Widget::_clearPointSelection() {
3✔
183
    if (_selected_point_id != 0) {
3✔
184
        _selected_point_id = 0;
×
185
        _scene->clearAllSelections(); // Clear all selections in scene
×
186
        _scene->UpdateCanvas(); // Refresh to remove selection highlight
×
UNCOV
187
        std::cout << "Cleared point selection" << std::endl;
×
188
    }
189
}
3✔
190

191
void MediaPoint_Widget::_moveSelectedPoint(qreal x_media, qreal y_media) {
×
192
    if (_selected_point_id == 0 || _active_key.empty())
×
UNCOV
193
        return;
×
194
    
195
    auto current_time = _data_manager->getCurrentTime();
×
196
    
197
    // Handle timeframe conversion if necessary
198
    auto video_timeframe = _data_manager->getTime(TimeKey("time"));
×
UNCOV
199
    auto point_timeframe_key = _data_manager->getTimeKey(_active_key);
×
200
    
UNCOV
201
    if (!point_timeframe_key.empty()) {
×
202
        auto point_timeframe = _data_manager->getTime(point_timeframe_key);
×
203
        if (video_timeframe.get() != point_timeframe.get()) {
×
204
            current_time = video_timeframe->getTimeAtIndex(TimeFrameIndex(current_time));
×
UNCOV
205
            current_time = point_timeframe->getIndexAtTime(current_time).getValue();
×
206
        }
207
    }
×
208
    
209
    auto point = _data_manager->getData<PointData>(_active_key);
×
UNCOV
210
    if (point) {
×
211
        point->overwritePointAtTime(TimeFrameIndex(current_time), 
×
212
                                    Point2D<float>(static_cast<float>(x_media), static_cast<float>(y_media)));
213
        _scene->UpdateCanvas();
×
214
        std::cout << "Moved point to: (" << x_media << ", " << y_media << ")" << std::endl;
×
215
    }
216
}
×
217

218
void MediaPoint_Widget::_assignPoint(qreal x_media, qreal y_media) {
×
219
    // Legacy method - now just calls the move function for compatibility
220
    _moveSelectedPoint(x_media, y_media);
×
UNCOV
221
}
×
222

UNCOV
223
void MediaPoint_Widget::_addPointAtCurrentTime(qreal x_media, qreal y_media) {
×
224
    if (_active_key.empty())
×
UNCOV
225
        return;
×
226
    
227
    auto current_time = _data_manager->getCurrentTime();
×
228
    
229
    // Handle timeframe conversion if necessary
230
    auto video_timeframe = _data_manager->getTime(TimeKey("time"));
×
231
    auto point_timeframe_key = _data_manager->getTimeKey(_active_key);
×
232
    
UNCOV
233
    if (!point_timeframe_key.empty()) {
×
234
        auto point_timeframe = _data_manager->getTime(point_timeframe_key);
×
UNCOV
235
        if (video_timeframe.get() != point_timeframe.get()) {
×
236
            current_time = video_timeframe->getTimeAtIndex(TimeFrameIndex(current_time));
×
UNCOV
237
            current_time = point_timeframe->getIndexAtTime(current_time).getValue();
×
238
        }
239
    }
×
240
    
241
    auto point_data = _data_manager->getData<PointData>(_active_key);
×
242
    if (point_data) {
×
UNCOV
243
        Point2D<float> new_point(static_cast<float>(x_media), static_cast<float>(y_media));
×
244
        point_data->addAtTime(TimeFrameIndex(current_time), new_point);
×
UNCOV
245
        _scene->UpdateCanvas();
×
UNCOV
246
        std::cout << "Added new point at: (" << x_media << ", " << y_media << ") at time " << current_time << std::endl;
×
247
    }
248
}
×
249

250
void MediaPoint_Widget::_setPointColor(const QString& hex_color) {
×
251
    if (!_active_key.empty()) {
×
252
        auto point_opts = _scene->getPointConfig(_active_key);
×
253
        if (point_opts.has_value()) {
×
254
            point_opts.value()->hex_color = hex_color.toStdString();
×
255
        }
256
        _scene->UpdateCanvas();
×
257
    }
258
}
×
259

260
void MediaPoint_Widget::_setPointAlpha(int alpha) {
×
261
    float const alpha_float = static_cast<float>(alpha) / 100;
×
262

263
    if (!_active_key.empty()) {
×
264
        auto point_opts = _scene->getPointConfig(_active_key);
×
UNCOV
265
        if (point_opts.has_value()) {
×
266
            point_opts.value()->alpha = alpha_float;
×
267
        }
268
        _scene->UpdateCanvas();
×
269
    }
UNCOV
270
}
×
271

UNCOV
272
void MediaPoint_Widget::_setPointSize(int size) {
×
UNCOV
273
    if (!_active_key.empty()) {
×
UNCOV
274
        auto point_opts = _scene->getPointConfig(_active_key);
×
UNCOV
275
        if (point_opts.has_value()) {
×
UNCOV
276
            point_opts.value()->point_size = size;
×
277
        }
UNCOV
278
        _scene->UpdateCanvas();
×
279
    }
280
    
281
    // Synchronize slider and spinbox if the signal came from one of them
UNCOV
282
    QObject* sender_obj = sender();
×
UNCOV
283
    if (sender_obj == ui->point_size_slider) {
×
UNCOV
284
        ui->point_size_spinbox->blockSignals(true);
×
UNCOV
285
        ui->point_size_spinbox->setValue(size);
×
UNCOV
286
        ui->point_size_spinbox->blockSignals(false);
×
UNCOV
287
    } else if (sender_obj == ui->point_size_spinbox) {
×
UNCOV
288
        ui->point_size_slider->blockSignals(true);
×
UNCOV
289
        ui->point_size_slider->setValue(size);
×
UNCOV
290
        ui->point_size_slider->blockSignals(false);
×
291
    }
UNCOV
292
}
×
293

UNCOV
294
void MediaPoint_Widget::_setMarkerShape(int shapeIndex) {
×
UNCOV
295
    if (!_active_key.empty() && shapeIndex >= 0) {
×
UNCOV
296
        auto point_opts = _scene->getPointConfig(_active_key);
×
UNCOV
297
        if (point_opts.has_value()) {
×
UNCOV
298
            point_opts.value()->marker_shape = static_cast<PointMarkerShape>(shapeIndex);
×
299
        }
UNCOV
300
        _scene->UpdateCanvas();
×
301
    }
UNCOV
302
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc