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

paulmthompson / WhiskerToolbox / 18045385035

26 Sep 2025 05:53PM UTC coverage: 69.782% (+0.01%) from 69.77%
18045385035

push

github

paulmthompson
fix corrupted lambda capture with notification in data transform sub widgets

42952 of 61552 relevant lines covered (69.78%)

1129.6 hits per line

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

42.02
/src/WhiskerToolbox/Media_Widget/Media_Widget.cpp
1
#include "Media_Widget.hpp"
2
#include "ui_Media_Widget.h"
3

4
#include "Collapsible_Widget/Section.hpp"
5
#include "CoreGeometry/ImageSize.hpp"
6
#include "DataManager/DataManager.hpp"
7
#include "DataManager/DigitalTimeSeries/Digital_Interval_Series.hpp"
8
#include "DataManager/Lines/Line_Data.hpp"
9
#include "DataManager/Masks/Mask_Data.hpp"
10
#include "DataManager/Points/Point_Data.hpp"
11
#include "Media_Widget/MediaInterval_Widget/MediaInterval_Widget.hpp"
12
#include "Media_Widget/MediaLine_Widget/MediaLine_Widget.hpp"
13
#include "Media_Widget/MediaMask_Widget/MediaMask_Widget.hpp"
14
#include "Media_Widget/MediaPoint_Widget/MediaPoint_Widget.hpp"
15
#include "Media_Widget/MediaProcessing_Widget/MediaProcessing_Widget.hpp"
16
#include "Media_Widget/MediaTensor_Widget/MediaTensor_Widget.hpp"
17
#include "Media_Widget/MediaText_Widget/MediaText_Widget.hpp"
18
#include "Media_Window/Media_Window.hpp"
19

20
//https://stackoverflow.com/questions/72533139/libtorch-errors-when-used-with-qt-opencv-and-point-cloud-library
21
#undef slots
22
#include "DataManager/Tensors/Tensor_Data.hpp"
23
#define slots Q_SLOTS
24

25
#include <QApplication>
26
#include <QGraphicsView>
27
#include <QResizeEvent>
28
#include <QTimer>
29
#include <QWheelEvent>
30

31
#include <algorithm>
32

33
Media_Widget::Media_Widget(QWidget * parent)
3✔
34
    : QWidget(parent),
35
      ui(new Ui::Media_Widget) {
3✔
36
    ui->setupUi(this);
3✔
37

38
    // Configure splitter behavior
39
    ui->splitter->setStretchFactor(0, 0);// Left panel (scroll area) doesn't stretch
3✔
40
    ui->splitter->setStretchFactor(1, 1);// Right panel (graphics view) stretches
3✔
41

42
    // Set initial sizes: 250px for left panel, rest for canvas (reduced from 350px)
43
    ui->splitter->setSizes({250, 513});
3✔
44

45
    // Set collapsible behavior
46
    ui->splitter->setCollapsible(0, false);// Prevent left panel from collapsing
3✔
47
    ui->splitter->setCollapsible(1, false);// Prevent canvas from collapsing
3✔
48

49
    // Connect splitter moved signal to update canvas size
50
    connect(ui->splitter, &QSplitter::splitterMoved, this, &Media_Widget::_updateCanvasSize);
3✔
51

52
    // Install event filter on graphics view viewport for wheel zoom
53
    if (ui->graphicsView && ui->graphicsView->viewport()) {
3✔
54
        ui->graphicsView->viewport()->installEventFilter(this);
3✔
55
        ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorViewCenter);
3✔
56
        ui->graphicsView->setResizeAnchor(QGraphicsView::AnchorViewCenter);
3✔
57
    }
58

59
    // Create text overlay section
60
    _text_section = new Section(this, "Text Overlays");
3✔
61
    _text_widget = new MediaText_Widget(this);
3✔
62
    _text_section->setContentLayout(*new QVBoxLayout());
3✔
63
    _text_section->layout()->addWidget(_text_widget);
3✔
64
    _text_section->autoSetContentLayout();
3✔
65

66
    // Add text section to the vertical layout in scroll area
67
    // Insert before the feature table widget (at index 0, after the Zoom button)
68
    ui->verticalLayout->insertWidget(1, _text_section);
3✔
69

70
    connect(ui->feature_table_widget, &Feature_Table_Widget::featureSelected, this, &Media_Widget::_featureSelected);
3✔
71

72
    connect(ui->feature_table_widget, &Feature_Table_Widget::addFeature, this, [this](QString const & feature) {
3✔
73
        Media_Widget::_addFeatureToDisplay(feature, true);
×
74
    });
×
75

76
    connect(ui->feature_table_widget, &Feature_Table_Widget::removeFeature, this, [this](QString const & feature) {
3✔
77
        Media_Widget::_addFeatureToDisplay(feature, false);
×
78
    });
×
79

80
    // Ensure the feature table and other widgets are properly sized on startup
81
    QTimer::singleShot(0, this, [this]() {
3✔
82
        int scrollAreaWidth = ui->scrollArea->width();
3✔
83
        ui->feature_table_widget->setFixedWidth(scrollAreaWidth - 10);
3✔
84

85
        // Call the update function to size everything properly
86
        _updateCanvasSize();
3✔
87

88
        // Initialize the stacked widget with proper sizing
89
        ui->stackedWidget->setFixedWidth(scrollAreaWidth - 10);
3✔
90
    });
3✔
91
}
3✔
92

93
Media_Widget::~Media_Widget() {
3✔
94
    // Proactively hide stacked pages while _scene is still alive so any hideEvent
95
    // handlers that interact with _scene do so safely before _scene is destroyed.
96
    if (ui && ui->stackedWidget) {
3✔
97
        for (int i = 0; i < ui->stackedWidget->count(); ++i) {
24✔
98
            QWidget * w = ui->stackedWidget->widget(i);
21✔
99
            if (w && w->isVisible()) {
21✔
100
                w->hide();
2✔
101
            }
102
        }
103
    }
104

105
    // Ensure hover circle is cleared before scene destruction
106
    if (_scene) {
3✔
107
        _scene->setShowHoverCircle(false);
3✔
108
    }
109

110
    delete ui;
3✔
111
}
3✔
112

113
void Media_Widget::updateMedia() {
2✔
114

115
    ui->graphicsView->setScene(_scene.get());
2✔
116
    ui->graphicsView->show();
2✔
117

118
    _updateCanvasSize();
2✔
119
}
2✔
120

121
void Media_Widget::setDataManager(std::shared_ptr<DataManager> data_manager) {
3✔
122
    _data_manager = std::move(data_manager);
3✔
123

124
    // Create the Media_Window now that we have a DataManager
125
    _createMediaWindow();
3✔
126
    _createOptions();
3✔
127

128
    ui->feature_table_widget->setColumns({"Feature", "Enabled", "Type"});
15✔
129
    ui->feature_table_widget->setTypeFilter({DM_DataType::Line, DM_DataType::Mask, DM_DataType::Points, DM_DataType::DigitalInterval, DM_DataType::Tensor, DM_DataType::Video, DM_DataType::Images});
9✔
130
    ui->feature_table_widget->setDataManager(_data_manager);
3✔
131
    ui->feature_table_widget->populateTable();
3✔
132

133
    ui->stackedWidget->addWidget(new MediaPoint_Widget(_data_manager, _scene.get()));
3✔
134
    ui->stackedWidget->addWidget(new MediaLine_Widget(_data_manager, _scene.get()));
3✔
135
    ui->stackedWidget->addWidget(new MediaMask_Widget(_data_manager, _scene.get()));
3✔
136
    ui->stackedWidget->addWidget(new MediaInterval_Widget(_data_manager, _scene.get()));
3✔
137
    ui->stackedWidget->addWidget(new MediaTensor_Widget(_data_manager, _scene.get()));
3✔
138

139
    // Create and store reference to MediaProcessing_Widget
140
    _processing_widget = new MediaProcessing_Widget(_data_manager, _scene.get());
3✔
141
    ui->stackedWidget->addWidget(_processing_widget);
3✔
142

143
    // Connect text widget to scene if both are available
144
    _connectTextWidgetToScene();
3✔
145

146
    // Ensure all widgets in the stacked widget are properly sized
147
    QTimer::singleShot(100, this, [this]() {
3✔
148
        int scrollAreaWidth = ui->scrollArea->width();
×
149
        for (int i = 0; i < ui->stackedWidget->count(); ++i) {
×
150
            QWidget * widget = ui->stackedWidget->widget(i);
×
151
            if (widget) {
×
152
                widget->setFixedWidth(scrollAreaWidth - 10);
×
153
                widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
×
154

155
                // If this is a MediaProcessing_Widget, make sure it fills its container
156
                auto processingWidget = qobject_cast<MediaProcessing_Widget *>(widget);
×
157
                if (processingWidget) {
×
158
                    processingWidget->setMinimumWidth(scrollAreaWidth - 10);
×
159
                    processingWidget->adjustSize();
×
160
                }
161
            }
162
        }
163
        _updateCanvasSize();
×
164
    });
×
165

166
    _data_manager->addObserver([this]() {
3✔
167
        _createOptions();
1✔
168
    });
1✔
169
}
6✔
170

171
void Media_Widget::_createOptions() {
4✔
172

173
    //Setup Media Data
174
    auto media_keys = _data_manager->getKeys<MediaData>();
4✔
175
    for (auto const & media_key: media_keys) {
8✔
176
        auto opts = _scene->getMediaConfig(media_key);
4✔
177
        if (opts.has_value()) continue;
4✔
178

179
        _scene->addMediaDataToScene(media_key);
3✔
180
    }
181

182
    // Setup line data
183
    auto line_keys = _data_manager->getKeys<LineData>();
4✔
184
    for (auto const & line_key: line_keys) {
4✔
185
        auto opts = _scene->getLineConfig(line_key);
×
186
        if (opts.has_value()) continue;
×
187

188
        _scene->addLineDataToScene(line_key);
×
189
    }
190

191
    // Setup mask data
192
    auto mask_keys = _data_manager->getKeys<MaskData>();
4✔
193
    for (auto const & mask_key: mask_keys) {
7✔
194
        auto opts = _scene->getMaskConfig(mask_key);
3✔
195
        if (opts.has_value()) continue;
3✔
196

197
        _scene->addMaskDataToScene(mask_key);
3✔
198
    }
199

200
    // Setup point data
201
    auto point_keys = _data_manager->getKeys<PointData>();
4✔
202
    for (auto const & point_key: point_keys) {
4✔
203
        auto opts = _scene->getPointConfig(point_key);
×
204
        if (opts.has_value()) continue;
×
205

206
        _scene->addPointDataToScene(point_key);
×
207
    }
208

209
    // Setup digital interval data
210
    auto interval_keys = _data_manager->getKeys<DigitalIntervalSeries>();
4✔
211
    for (auto const & interval_key: interval_keys) {
4✔
212
        auto opts = _scene->getIntervalConfig(interval_key);
×
213
        if (opts.has_value()) continue;
×
214

215
        _scene->addDigitalIntervalSeries(interval_key);
×
216
    }
217

218
    // Setup tensor data
219
    auto tensor_keys = _data_manager->getKeys<TensorData>();
4✔
220
    for (auto const & tensor_key: tensor_keys) {
4✔
221
        auto opts = _scene->getTensorConfig(tensor_key);
×
222
        if (opts.has_value()) continue;
×
223

224
        _scene->addTensorDataToScene(tensor_key);
×
225
    }
226
}
8✔
227

228
void Media_Widget::_connectTextWidgetToScene() {
6✔
229
    if (_scene && _text_widget) {
6✔
230
        _scene->setTextWidget(_text_widget);
6✔
231

232
        // Connect text widget signals to update canvas when overlays change
233
        connect(_text_widget, &MediaText_Widget::textOverlayAdded, _scene.get(), &Media_Window::UpdateCanvas);
6✔
234
        connect(_text_widget, &MediaText_Widget::textOverlayRemoved, _scene.get(), &Media_Window::UpdateCanvas);
6✔
235
        connect(_text_widget, &MediaText_Widget::textOverlayUpdated, _scene.get(), &Media_Window::UpdateCanvas);
6✔
236
        connect(_text_widget, &MediaText_Widget::textOverlaysCleared, _scene.get(), &Media_Window::UpdateCanvas);
6✔
237
    }
238
}
6✔
239

240
void Media_Widget::_featureSelected(QString const & feature) {
3✔
241
    auto const type = _data_manager->getType(feature.toStdString());
3✔
242
    auto key = feature.toStdString();
3✔
243

244
    if (type == DM_DataType::Points) {
3✔
245

246
        int const stacked_widget_index = 1;
×
247

248
        ui->stackedWidget->setCurrentIndex(stacked_widget_index);
×
249
        auto point_widget = dynamic_cast<MediaPoint_Widget *>(ui->stackedWidget->widget(stacked_widget_index));
×
250
        point_widget->setActiveKey(key);
×
251

252
    } else if (type == DM_DataType::Line) {
3✔
253

254
        int const stacked_widget_index = 2;
×
255

256
        ui->stackedWidget->setCurrentIndex(stacked_widget_index);
×
257
        auto line_widget = dynamic_cast<MediaLine_Widget *>(ui->stackedWidget->widget(stacked_widget_index));
×
258
        line_widget->setActiveKey(key);
×
259

260
    } else if (type == DM_DataType::Mask) {
3✔
261

262
        int const stacked_widget_index = 3;
3✔
263

264
        ui->stackedWidget->setCurrentIndex(stacked_widget_index);
3✔
265
        auto mask_widget = dynamic_cast<MediaMask_Widget *>(ui->stackedWidget->widget(stacked_widget_index));
3✔
266
        mask_widget->setActiveKey(key);
3✔
267

268

269
    } else if (type == DM_DataType::DigitalInterval) {
×
270
        int const stacked_widget_index = 4;
×
271

272
        ui->stackedWidget->setCurrentIndex(stacked_widget_index);
×
273
        auto interval_widget = dynamic_cast<MediaInterval_Widget *>(ui->stackedWidget->widget(stacked_widget_index));
×
274
        interval_widget->setActiveKey(key);
×
275

276
    } else if (type == DM_DataType::Tensor) {
×
277
        int const stacked_widget_index = 5;
×
278

279
        ui->stackedWidget->setCurrentIndex(stacked_widget_index);
×
280
        auto tensor_widget = dynamic_cast<MediaTensor_Widget *>(ui->stackedWidget->widget(stacked_widget_index));
×
281
        tensor_widget->setActiveKey(key);
×
282
    } else if (type == DM_DataType::Video) {
×
283
        int const stacked_widget_index = 6;
×
284

285
        ui->stackedWidget->setCurrentIndex(stacked_widget_index);
×
286
        auto processing_widget = dynamic_cast<MediaProcessing_Widget *>(ui->stackedWidget->widget(stacked_widget_index));
×
287
        processing_widget->setActiveKey(key);
×
288

289
        // Do NOT set as active media key or update canvas - only show controls for configuration
290
        // The media will only be displayed when it's enabled via the checkbox
291

292
    } else if (type == DM_DataType::Images) {
×
293
        int const stacked_widget_index = 6;
×
294

295
        ui->stackedWidget->setCurrentIndex(stacked_widget_index);
×
296
        auto processing_widget = dynamic_cast<MediaProcessing_Widget *>(ui->stackedWidget->widget(stacked_widget_index));
×
297
        processing_widget->setActiveKey(key);
×
298

299
        // Do NOT set as active media key or update canvas - only show controls for configuration
300
        // The media will only be displayed when it's enabled via the checkbox
301
    } else {
302
        ui->stackedWidget->setCurrentIndex(0);
×
303
        std::cout << "Unsupported feature type" << std::endl;
×
304
    }
305
}
6✔
306

307
void Media_Widget::resizeEvent(QResizeEvent * event) {
2✔
308
    QWidget::resizeEvent(event);
2✔
309
    // When user has zoomed, avoid rescaling scene contents destructively; just adjust scene rect
310
    if (_user_zoom_active) {
2✔
311
        if (_scene) {
×
312
            auto size = ui->graphicsView->size();
×
313
            _scene->setSceneRect(0, 0, size.width(), size.height());
×
314
        }
315
    } else {
316
        _updateCanvasSize();
2✔
317
    }
318
}
2✔
319

320
void Media_Widget::_updateCanvasSize() {
7✔
321
    if (_scene) {
7✔
322
        int width = ui->graphicsView->width();
7✔
323
        int height = ui->graphicsView->height();
7✔
324

325
        _scene->setCanvasSize(
7✔
326
                ImageSize{width, height});
327
        _scene->UpdateCanvas();
7✔
328

329
        // Ensure the view fits the scene properly
330
        ui->graphicsView->setSceneRect(0, 0, width, height);
7✔
331
        if (!_user_zoom_active) {
7✔
332
            ui->graphicsView->resetTransform();
7✔
333
            _current_zoom = 1.0;
7✔
334
        }
335
        // Fit disabled: we manage zoom manually now
336
        // Update left panel sizing
337
        int scrollAreaWidth = ui->scrollArea->width();
7✔
338
        int featureTableWidth = scrollAreaWidth - 10;
7✔
339
        ui->feature_table_widget->setFixedWidth(featureTableWidth);
7✔
340
        ui->stackedWidget->setFixedWidth(featureTableWidth);
7✔
341
        for (int i = 0; i < ui->stackedWidget->count(); ++i) {
56✔
342
            QWidget * widget = ui->stackedWidget->widget(i);
49✔
343
            if (widget) {
49✔
344
                widget->setFixedWidth(featureTableWidth);
49✔
345
            }
346
        }
347
    }
348
}
7✔
349

350
void Media_Widget::_addFeatureToDisplay(QString const & feature, bool enabled) {
×
351
    std::cout << "Feature: " << feature.toStdString() << std::endl;
×
352

353
    auto const feature_key = feature.toStdString();
×
354
    auto const type = _data_manager->getType(feature_key);
×
355

356
    if (type == DM_DataType::Line) {
×
357
        auto opts = _scene->getLineConfig(feature_key);
×
358
        if (!opts.has_value()) {
×
359
            std::cerr << "Table feature key "
360
                      << feature_key
361
                      << " not found in Media_Window Display Options"
×
362
                      << std::endl;
×
363
            return;
×
364
        }
365
        opts.value()->is_visible = enabled;
×
366
    } else if (type == DM_DataType::Mask) {
×
367
        auto opts = _scene->getMaskConfig(feature_key);
×
368
        if (!opts.has_value()) {
×
369
            std::cerr << "Table feature key "
370
                      << feature_key
371
                      << " not found in Media_Window Display Options"
×
372
                      << std::endl;
×
373
            return;
×
374
        }
375
        opts.value()->is_visible = enabled;
×
376
    } else if (type == DM_DataType::Points) {
×
377
        auto opts = _scene->getPointConfig(feature_key);
×
378
        if (!opts.has_value()) {
×
379
            std::cerr << "Table feature key "
380
                      << feature_key
381
                      << " not found in Media_Window Display Options"
×
382
                      << std::endl;
×
383
            return;
×
384
        }
385
        opts.value()->is_visible = enabled;
×
386
    } else if (type == DM_DataType::DigitalInterval) {
×
387
        auto opts = _scene->getIntervalConfig(feature_key);
×
388
        if (!opts.has_value()) {
×
389
            std::cerr << "Table feature key "
390
                      << feature_key
391
                      << " not found in Media_Window Display Options"
×
392
                      << std::endl;
×
393
            return;
×
394
        }
395
        opts.value()->is_visible = enabled;
×
396
    } else if (type == DM_DataType::Tensor) {
×
397
        auto opts = _scene->getTensorConfig(feature_key);
×
398
        if (!opts.has_value()) {
×
399
            std::cerr << "Table feature key "
400
                      << feature_key
401
                      << " not found in Media_Window Display Options"
×
402
                      << std::endl;
×
403
            return;
×
404
        }
405

406
        if (enabled) {
×
407
            std::cout << "Enabling tensor data in scene" << std::endl;
×
408
            opts.value()->is_visible = true;
×
409
        } else {
410
            std::cout << "Disabling tensor data from scene" << std::endl;
×
411
            opts.value()->is_visible = false;
×
412
        }
413
    } else if (type == DM_DataType::Video || type == DM_DataType::Images) {
×
414
        auto opts = _scene->getMediaConfig(feature_key);
×
415
        if (!opts.has_value()) {
×
416
            std::cerr << "Table feature key "
417
                      << feature_key
418
                      << " not found in Media_Window Display Options"
×
419
                      << std::endl;
×
420
            return;
×
421
        }
422
        if (enabled) {
×
423
            std::cout << "Enabling media data in scene" << std::endl;
×
424
            opts.value()->is_visible = true;
×
425

426
            // This ensures new media is loaded from disk
427
            // Before the update
428
            auto current_time = _data_manager->getCurrentTime();
×
429
            LoadFrame(current_time);
×
430

431
        } else {
432
            std::cout << "Disabling media data from scene" << std::endl;
×
433
            opts.value()->is_visible = false;
×
434
        }
435
    } else {
×
436
        std::cout << "Feature type " << convert_data_type_to_string(type) << " not supported" << std::endl;
×
437
    }
438
    _scene->UpdateCanvas();
×
439

440
    if (enabled) {
×
441
        _callback_ids[feature_key].push_back(_data_manager->addCallbackToData(feature_key, [this]() {
×
442
            _scene->UpdateCanvas();
×
443
        }));
×
444
    } else {
445
        for (auto callback_id: _callback_ids[feature_key]) {
×
446
            _data_manager->removeCallbackFromData(feature_key, callback_id);
×
447
        }
448
        _callback_ids[feature_key].clear();
×
449
    }
450
}
×
451

452
void Media_Widget::setFeatureColor(std::string const & feature, std::string const & hex_color) {
×
453
    auto const type = _data_manager->getType(feature);
×
454

455
    if (type == DM_DataType::Line) {
×
456
        auto opts = _scene->getLineConfig(feature);
×
457
        if (opts.has_value()) {
×
458
            opts.value()->hex_color = hex_color;
×
459
        }
460
    } else if (type == DM_DataType::Mask) {
×
461
        auto opts = _scene->getMaskConfig(feature);
×
462
        if (opts.has_value()) {
×
463
            opts.value()->hex_color = hex_color;
×
464
        }
465
    } else if (type == DM_DataType::Points) {
×
466
        auto opts = _scene->getPointConfig(feature);
×
467
        if (opts.has_value()) {
×
468
            opts.value()->hex_color = hex_color;
×
469
        }
470
    } else if (type == DM_DataType::DigitalInterval) {
×
471
        auto opts = _scene->getIntervalConfig(feature);
×
472
        if (opts.has_value()) {
×
473
            opts.value()->hex_color = hex_color;
×
474
        }
475
    } else if (type == DM_DataType::Tensor) {
×
476
        auto opts = _scene->getTensorConfig(feature);
×
477
        if (opts.has_value()) {
×
478
            opts.value()->hex_color = hex_color;
×
479
        }
480
    }
481

482
    _scene->UpdateCanvas();
×
483
}
×
484

485
void Media_Widget::LoadFrame(int frame_id) {
×
486
    if (_scene) {
×
487
        _scene->LoadFrame(frame_id);
×
488
    }
489
    int currentIndex = ui->stackedWidget->currentIndex();
×
490
    if (currentIndex > 0) {
×
491
        auto currentWidget = ui->stackedWidget->currentWidget();
×
492
        auto lineWidget = dynamic_cast<MediaLine_Widget *>(currentWidget);
×
493
        if (lineWidget) {
×
494
            lineWidget->LoadFrame(frame_id);
×
495
        }
496
    }
497
}
×
498

499
// Zoom API implementations
500
void Media_Widget::zoomIn() { _applyZoom(_zoom_step, false); }
×
501
void Media_Widget::zoomOut() { _applyZoom(1.0 / _zoom_step, false); }
×
502
void Media_Widget::resetZoom() {
×
503
    if (!ui->graphicsView) return;
×
504
    ui->graphicsView->resetTransform();
×
505
    _current_zoom = 1.0;
×
506
    _user_zoom_active = false;
×
507
}
508

509
void Media_Widget::_applyZoom(double factor, bool anchor_under_mouse) {
×
510
    if (!ui->graphicsView) return;
×
511
    double new_zoom = _current_zoom * factor;
×
512
    new_zoom = std::clamp(new_zoom, _min_zoom, _max_zoom);
×
513
    factor = new_zoom / _current_zoom;// Adjust factor if clamped
×
514
    if (qFuzzyCompare(factor, 1.0)) return;
×
515
    if (anchor_under_mouse) {
×
516
        ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
×
517
    } else {
518
        ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorViewCenter);
×
519
    }
520
    ui->graphicsView->scale(factor, factor);
×
521
    _current_zoom = new_zoom;
×
522
    _user_zoom_active = (_current_zoom != 1.0);
×
523
}
524

525
bool Media_Widget::eventFilter(QObject * watched, QEvent * event) {
28✔
526
    if (watched == ui->graphicsView->viewport() && event->type() == QEvent::Wheel) {
28✔
527
        auto * wheelEvent = dynamic_cast<QWheelEvent *>(event);
×
528
        double angle = wheelEvent->angleDelta().y();
×
529
        if (angle > 0) {
×
530
            _applyZoom(_zoom_step, true);
×
531
        } else if (angle < 0) {
×
532
            _applyZoom(1.0 / _zoom_step, true);
×
533
        }
534
        wheelEvent->accept();
×
535
        return true;
×
536
    }
537
    return QWidget::eventFilter(watched, event);
28✔
538
}
539

540
void Media_Widget::_createMediaWindow() {
3✔
541
    if (_data_manager) {
3✔
542
        _scene = std::make_unique<Media_Window>(_data_manager, this);
3✔
543

544
        // Set parent widget reference for accessing enabled media keys
545
        _scene->setParentWidget(this);
3✔
546

547
        _connectTextWidgetToScene();
3✔
548
    }
549
}
3✔
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