|
13 | 13 | /// \author David Rohr |
14 | 14 |
|
15 | 15 | #include "GPUDisplayGUI.h" |
16 | | -#include "GPUDisplayGUIWrapper.h" |
| 16 | +#include "GPUDisplayFrontend.h" |
17 | 17 | #include "ui_GPUDisplayGUI.h" |
18 | 18 |
|
| 19 | +#include <QKeyEvent> |
| 20 | +#include <QSignalBlocker> |
| 21 | + |
| 22 | +#include <chrono> |
| 23 | +#include <cmath> |
| 24 | + |
19 | 25 | using namespace o2::gpu; |
20 | 26 |
|
21 | | -GPUDisplayGUI::GPUDisplayGUI(QWidget* parent) : QMainWindow(parent), ui(new Ui::GPUDisplayGUI) |
| 27 | +GPUDisplayGUI::GPUDisplayGUI(GPUDisplayGUIChannel& channel, QWidget* parent) : QMainWindow(parent), mUi(std::make_unique<Ui::GPUDisplayGUI>()), mChannel(channel) |
| 28 | +{ |
| 29 | + mUi->setupUi(this); |
| 30 | + { |
| 31 | + std::lock_guard lock(mChannel.mutex); |
| 32 | + setWindowTitle(QString::fromStdString(mChannel.windowName + " GUI")); |
| 33 | + } |
| 34 | + connect(mUi->lineWidthSlider, &QSlider::valueChanged, this, [this](int32_t value) { |
| 35 | + mUpdate.lineWidth = value * 0.1f; |
| 36 | + mUi->lineWidthValue->setNum(*mUpdate.lineWidth); |
| 37 | + }); |
| 38 | + connect(&mTimer, &QTimer::timeout, this, &GPUDisplayGUI::timerTick); |
| 39 | + mTimer.start(std::chrono::milliseconds(10)); |
| 40 | +} |
| 41 | + |
| 42 | +GPUDisplayGUI::~GPUDisplayGUI() = default; |
| 43 | + |
| 44 | +void GPUDisplayGUI::timerTick() |
| 45 | +{ |
| 46 | + std::unique_lock lock(mChannel.mutex); |
| 47 | + mChannel.guiSleeping = false; |
| 48 | + if (mUpdate.empty()) { // Display processes the update we went to sleep with, wait for the reply (with new changes we would not apply it anyway) |
| 49 | + mChannel.stateUpdated.wait_for(lock, mChannel.replyTimeout, [this] { return !mChannel.displayProcessingCurrentUpdate || mChannel.stop; }); |
| 50 | + } |
| 51 | + if (!mUpdate.empty() && mLastSentId - mLastAppliedId >= mChannel.maxUpdatesAhead) { // Too far ahead of the display, wait for the reply to the last update |
| 52 | + mChannel.stateUpdated.wait_for(lock, mChannel.replyTimeout, [this] { return mChannel.state.appliedUpdate == mLastSentId || mChannel.stop; }); |
| 53 | + } |
| 54 | + if (mChannel.stop) { |
| 55 | + lock.unlock(); |
| 56 | + close(); |
| 57 | + return; |
| 58 | + } |
| 59 | + |
| 60 | + const bool newState = mChannel.state.counter != mState.counter; |
| 61 | + if (newState) { |
| 62 | + mState = mChannel.state; |
| 63 | + if (mState.appliedUpdate == mLastSentId) { |
| 64 | + mLastAppliedId = mLastSentId; |
| 65 | + } |
| 66 | + } |
| 67 | + const bool apply = newState && mUpdate.empty() && mState.appliedUpdate == mLastSentId; // State contains all our updates, and we have no unsent changes |
| 68 | + if (!mUpdate.empty() && mLastSentId - mLastAppliedId < mChannel.maxUpdatesAhead) { |
| 69 | + if (mChannel.update) { // Previous update not yet picked up by the display, merge |
| 70 | + auto& update = *mChannel.update; |
| 71 | + update.keys.insert(update.keys.end(), mUpdate.keys.begin(), mUpdate.keys.end()); |
| 72 | + if (mUpdate.lineWidth) { |
| 73 | + update.lineWidth = mUpdate.lineWidth; |
| 74 | + } |
| 75 | + } else { |
| 76 | + mChannel.update = std::move(mUpdate); |
| 77 | + } |
| 78 | + mChannel.update->id = ++mLastSentId; |
| 79 | + mChannel.guiSleeping = true; |
| 80 | + mUpdate = {}; |
| 81 | + } |
| 82 | + lock.unlock(); |
| 83 | + |
| 84 | + if (apply) { |
| 85 | + applySettings(); |
| 86 | + } |
| 87 | +} |
| 88 | + |
| 89 | +void GPUDisplayGUI::applySettings() |
| 90 | +{ |
| 91 | + const QSignalBlocker blocker(mUi->lineWidthSlider); // Not a user change |
| 92 | + mUi->lineWidthSlider->setValue(std::lround(mState.cfg.cfgL.lineWidth * 10.f)); |
| 93 | + mUi->lineWidthValue->setNum(mState.cfg.cfgL.lineWidth); |
| 94 | +} |
| 95 | + |
| 96 | +void GPUDisplayGUI::bringToFront() |
22 | 97 | { |
23 | | - ui->setupUi(this); |
| 98 | + setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); |
| 99 | + show(); |
| 100 | + raise(); |
| 101 | + activateWindow(); |
24 | 102 | } |
25 | 103 |
|
26 | | -GPUDisplayGUI::~GPUDisplayGUI() |
| 104 | +void GPUDisplayGUI::keyPressEvent(QKeyEvent* event) |
27 | 105 | { |
28 | | - delete ui; |
| 106 | + const int32_t key = translateKey(event); |
| 107 | + if (key < 0) { |
| 108 | + QMainWindow::keyPressEvent(event); |
| 109 | + return; |
| 110 | + } |
| 111 | + mUpdate.keys.emplace_back(key); |
29 | 112 | } |
30 | 113 |
|
31 | | -void GPUDisplayGUI::UpdateTimer() |
| 114 | +int32_t GPUDisplayGUI::translateKey(const QKeyEvent* event) |
32 | 115 | { |
33 | | - mWrapper->UpdateTimer(); |
| 116 | + switch (event->key()) { |
| 117 | + case Qt::Key_Up: |
| 118 | + return GPUDisplayFrontend::KEY_UP; |
| 119 | + case Qt::Key_Down: |
| 120 | + return GPUDisplayFrontend::KEY_DOWN; |
| 121 | + case Qt::Key_Left: |
| 122 | + return GPUDisplayFrontend::KEY_LEFT; |
| 123 | + case Qt::Key_Right: |
| 124 | + return GPUDisplayFrontend::KEY_RIGHT; |
| 125 | + case Qt::Key_PageUp: |
| 126 | + return GPUDisplayFrontend::KEY_PAGEUP; |
| 127 | + case Qt::Key_PageDown: |
| 128 | + return GPUDisplayFrontend::KEY_PAGEDOWN; |
| 129 | + case Qt::Key_Home: |
| 130 | + return GPUDisplayFrontend::KEY_HOME; |
| 131 | + case Qt::Key_End: |
| 132 | + return GPUDisplayFrontend::KEY_END; |
| 133 | + case Qt::Key_Insert: |
| 134 | + return GPUDisplayFrontend::KEY_INSERT; |
| 135 | + case Qt::Key_Escape: |
| 136 | + return GPUDisplayFrontend::KEY_ESCAPE; |
| 137 | + case Qt::Key_Return: |
| 138 | + case Qt::Key_Enter: |
| 139 | + return GPUDisplayFrontend::KEY_ENTER; |
| 140 | + default: |
| 141 | + break; |
| 142 | + } |
| 143 | + if (event->key() >= Qt::Key_F1 && event->key() <= Qt::Key_F12) { |
| 144 | + static_assert(GPUDisplayFrontend::KEY_F12 - GPUDisplayFrontend::KEY_F1 == Qt::Key_F12 - Qt::Key_F1); |
| 145 | + return GPUDisplayFrontend::KEY_F1 + (event->key() - Qt::Key_F1); |
| 146 | + } |
| 147 | + const QString text = event->text(); |
| 148 | + if (text.size() == 1 && text[0].unicode() >= 32 && text[0].unicode() < 127) { // Printable ASCII, with shift applied |
| 149 | + return text[0].unicode(); |
| 150 | + } |
| 151 | + return -1; |
34 | 152 | } |
0 commit comments