1 #include "monitorwindow.h"
2 #include "ui_monitorwindow.h"
3 #include <QGraphicsView>
13 MonitorWindow::MonitorWindow(HidThread
&thread
, QWidget
*parent
) :
15 ui(new Ui::MonitorWindow
),
20 current_layout
= nullptr;
21 connect(&thread
, &HidThread::keyboardName
, this, &MonitorWindow::on_keyboardName
);
22 connect(&thread
, &HidThread::reportMonitorError
, this, &MonitorWindow::on_reportMonitorError
);
23 connect(&thread
, &HidThread::thresholds
, this, &MonitorWindow::on_thresholds
);
24 connect(&thread
, &HidThread::keystate
, this, &MonitorWindow::on_keystate
);
25 this->setContextMenuPolicy(Qt::CustomContextMenu
);
26 connect(this, SIGNAL(customContextMenuRequested(const QPoint
&)),
27 this, SLOT(ShowContextMenu(const QPoint
&)));
30 void MonitorWindow::ShowContextMenu(const QPoint
&pos
)
32 QMenu
contextMenu(tr("Context menu"), this);
33 QAction
action1("Close", this);
34 connect(&action1
, SIGNAL(triggered()), this, SLOT(close()));
35 contextMenu
.addAction(&action1
);
36 contextMenu
.exec(mapToGlobal(pos
));
39 MonitorWindow::~MonitorWindow()
44 void MonitorWindow::setMinimumSizeUnits(unsigned int width_units_times_8
, unsigned int height_units_times_8
)
46 this->setMinimumSize(std::max(ui
->layoutSel
->width() + ui
->layoutSel
->x() * 2,
47 static_cast<int>(width_units_times_8
* MIN_HORIZONTAL_SCALE
/ 8 + 2 * HORIZONTAL_MARGIN
)),
48 ui
->last_label
->geometry().y() + ui
->last_label
->geometry().height() +
49 static_cast<int>(height_units_times_8
* MIN_VERTICAL_SCALE
/ 8 + 2 * VERTICAL_MARGIN
));
52 void MonitorWindow::loadLayout(QString name
)
55 ui
->layoutSel
->clear();
56 for (i
=0;i
<n_keyboards
;i
++)
58 if (name
.compare(QString(keyboards
[i
].kbd_name
))==0)
60 keyboard
= &keyboards
[i
];
61 is_was_key_pressed
= std::vector
<std::vector
<int>>(static_cast<unsigned long>(keyboard
->rows
), std::vector
<int>(static_cast<unsigned long>(keyboard
->cols
), 0));
63 for (j
=0;j
<keyboard
->n_layouts
;j
++)
65 ui
->layoutSel
->addItem(QString(keyboard
->layouts
[j
].lay_name
));
70 ui
->layoutSel
->addItem(QString("Matrix (without showing skipped columns/rows)"));
71 QString name_simp
= name
;
72 if (name
.startsWith("keyboards/")) name_simp
= name
.mid(strlen("keyboards/"));
73 int lastslash
= name_simp
.lastIndexOf("/");
74 if (lastslash
> 0) name_simp
= name_simp
.left(lastslash
);
75 ui
->label_keyboardname
->setText(QString("Keyboard: ") + name_simp
);
76 ui
->layoutSel
->setEnabled(true);
79 on_reportMonitorError("Unknown keyboard (you may need to update the util version)!");
83 keyboard_width_uis_times_8
= 0;
84 keyboard_height_uis_times_8
= 0;
85 for (i
=0;i
<keyboard
->n_layouts
;i
++)
87 const struct lay_def
*layout
= &keyboard
->layouts
[i
];
89 for (j
=0;j
<layout
->n_keys
;j
++)
91 const unsigned int w8
= static_cast<unsigned int>((layout
->keys
[j
].x
+ layout
->keys
[j
].w
)*8 + 0.5);
92 const unsigned int h8
= static_cast<unsigned int>((layout
->keys
[j
].y
+ layout
->keys
[j
].h
)*8 + 0.5);
93 if (w8
> keyboard_width_uis_times_8
) keyboard_width_uis_times_8
= w8
;
94 if (h8
> keyboard_height_uis_times_8
) keyboard_height_uis_times_8
= h8
;
97 setMinimumSizeUnits(keyboard_width_uis_times_8
, keyboard_height_uis_times_8
);
100 void MonitorWindow::displaySquare(int x
, int y
, int w
, int h
, unsigned int col
, unsigned int row
, QPainter
&painter
)
102 QPen
textColor(Qt::black
);
103 painter
.setPen(QPen(Qt::black
));
104 switch (is_was_key_pressed
.at(row
).at(col
))
108 textColor
= QPen(Qt::white
);
109 painter
.setBrush(QBrush(QColor("#008000")));
112 painter
.setBrush(QBrush(QColor("#00FF00")));
115 painter
.setBrush(QBrush(QColor("#FFFFFF")));
118 QRectF
rect(x
, y
, w
, h
);
119 painter
.drawRect(rect
);
120 if (thresholds
.size())
122 uint16_t threshold
= get_threshold(col
, row
);
123 painter
.setPen(textColor
);
124 painter
.drawText(rect
, Qt::AlignCenter
, QString::number(threshold
));
128 void MonitorWindow::updateCurrentLayout()
131 this->current_layout
= nullptr;
132 for (i
=0;i
<keyboard
->n_layouts
;i
++)
134 if (ui
->layoutSel
->currentText().compare(QString(keyboard
->layouts
[i
].lay_name
))==0)
136 this->current_layout
= &keyboard
->layouts
[i
];
142 void MonitorWindow::paintEvent(QPaintEvent
*event
)
145 if (!keyboard
) return;
146 QPainter
painter(this);
147 int xadd
= HORIZONTAL_MARGIN
;
148 int yadd
= ui
->last_label
->geometry().y() + ui
->last_label
->geometry().height() + VERTICAL_MARGIN
;
149 updateCurrentLayout();
150 const struct lay_def
*layout
= this->current_layout
;
153 double scale_x
= (1. * this->width() - 1 - 2 * HORIZONTAL_MARGIN
) * 8 / keyboard_width_uis_times_8
;
154 double scale_y
= (1. * this->height() - 1 - VERTICAL_MARGIN
- yadd
) * 8 / keyboard_height_uis_times_8
;
156 for (j
=0;j
<layout
->n_keys
;j
++)
158 const unsigned int col
= layout
->keys
[j
].col
;
159 const unsigned int row
= layout
->keys
[j
].row
;
160 const int x_
= static_cast<int>(layout
->keys
[j
].x
* 8 + 0.5);
161 const int y_
= static_cast<int>(layout
->keys
[j
].y
* 8 + 0.5);
162 const int w_
= static_cast<int>(layout
->keys
[j
].w
* 8 + 0.5);
163 const int h_
= static_cast<int>(layout
->keys
[j
].h
* 8 + 0.5);
164 const int x__
= static_cast<int>(scale_x
* x_
/ 8 + 0.5);
165 const int y__
= static_cast<int>(scale_y
* y_
/ 8 + 0.5);
166 const int w
= static_cast<int>(scale_x
* (x_
+ w_
) / 8 + 0.5) - x__
;
167 const int h
= static_cast<int>(scale_y
* (y_
+ h_
) / 8 + 0.5) - y__
;
168 const int x
= x__
+ xadd
;
169 const int y
= y__
+ yadd
;
170 displaySquare(x
, y
, w
, h
, col
, row
, painter
);
173 unsigned int col
, row
;
174 double scale_x
= (1. * this->width() - 2 * HORIZONTAL_MARGIN
) / keyboard
->cols
;
175 double scale_y
= (1. * this->height() - VERTICAL_MARGIN
- yadd
) / keyboard
->rows
;
176 for (row
= 0; row
< keyboard
->rows
; row
++)
178 for (col
= 0; col
< keyboard
->cols
; col
++)
180 const int x__
= static_cast<int>(scale_x
* col
+ 0.5);
181 const int y__
= static_cast<int>(scale_y
* row
+ 0.5);
182 const int w
= static_cast<int>(scale_x
* (col
+ 1) + 0.5) - x__
;
183 const int h
= static_cast<int>(scale_y
* (row
+ 1) + 0.5) - y__
;
184 const int x
= x__
+ xadd
;
185 const int y
= y__
+ yadd
;
186 displaySquare(x
, y
, w
, h
, col
, row
, painter
);
192 void MonitorWindow::on_layoutSel_activated(const QString
&arg1
)
195 updateCurrentLayout();
196 if (this->current_layout
)
198 setMinimumSizeUnits(this->keyboard_width_uis_times_8
, this->keyboard_height_uis_times_8
);
200 setMinimumSizeUnits(this->keyboard
->cols
* 8, this->keyboard
->rows
* 8);
205 void MonitorWindow::on_keyboardName(std::string name
)
207 loadLayout(QString::fromStdString(name
));
211 void MonitorWindow::on_thresholds(std::vector
<std::vector
<uint8_t>> thresholds
)
213 this->thresholds
= thresholds
;
217 void MonitorWindow::on_keystate(std::vector
<uint8_t> data
)
219 unsigned int col
, row
;
221 if (!keyboard
) return;
222 unsigned int bytes_per_row
= 1;
223 if (keyboard
->cols
> 16)
226 } else if (keyboard
->cols
> 8)
230 for (col
=0; col
< keyboard
->cols
; col
++)
232 for (row
=0; row
< keyboard
->rows
; row
++)
234 uint8_t pressed
= (data
.at(col
/ 8 + row
* bytes_per_row
) >> (col
% 8)) & 1;
235 int new_is_was_key_pressed
= is_was_key_pressed
.at(row
).at(col
);
236 if (pressed
) new_is_was_key_pressed
|= 3;
237 else new_is_was_key_pressed
&= ~1;
238 if (is_was_key_pressed
.at(row
).at(col
) != new_is_was_key_pressed
) different
= 1;
239 is_was_key_pressed
.at(row
).at(col
) = new_is_was_key_pressed
;
242 if (different
) this->repaint();
245 uint16_t MonitorWindow::get_threshold(unsigned int col
, unsigned int row
)
247 if (thresholds
.at(0).at(0) == 0) return static_cast<uint16_t>((thresholds
.at(0).at(1) | (thresholds
.at(0).at(2) << 8)));
249 unsigned int bytes_per_row
= 1;
250 if (keyboard
->cols
> 16)
253 } else if (keyboard
->cols
> 8)
257 for (i
=0;i
<thresholds
.at(0).at(0); i
++)
259 if ((thresholds
.at(i
).at(3 + col
/ 8 + row
* bytes_per_row
) >> (col
% 8)) & 1)
261 return static_cast<uint16_t>(thresholds
.at(i
).at(1) | (thresholds
.at(i
).at(2) << 8));
267 void MonitorWindow::on_reportMonitorError(std::string error_message
)
269 QMessageBox::critical(this, "Error", error_message
.c_str());
272 void MonitorWindow::on_MonitorWindow_finished(int result
)
275 thread
.closeMonitoredDevice();