Skip to content

Commit 07be6f2

Browse files
committed
Merge remote-tracking branch 'origin/dev'
2 parents a739668 + 675fefd commit 07be6f2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+4120
-1032
lines changed

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
# Open ModScan
22
Open ModScan is a free implimentation of modbus master (client) utility for modbus-tcp and modbus-rtu protocols.
33

4-
![image](https://github.com/user-attachments/assets/71563b34-3d85-404b-9d36-03ad5da76684)
4+
![image](https://github.com/user-attachments/assets/aaa2b5c8-9f47-4e17-803d-2af7d24fb0c7)
55

66

7-
![image](https://github.com/user-attachments/assets/1a7f45f9-66a8-4591-975f-4ea3b623ac31)
8-
7+
![image](https://github.com/user-attachments/assets/2bfe852f-1cc2-433d-8917-70815228a1c3)
98

109

1110
## Features
@@ -29,13 +28,13 @@ Registers
2928

3029
## Modbus Logging
3130

32-
![image](https://github.com/user-attachments/assets/1cc38a65-7631-4122-b975-6a01781131e4)
31+
![image](https://github.com/user-attachments/assets/8d24e149-e6db-47e1-a3d2-b2d5ed207ed4)
3332

3433

3534
## Extended Featues
3635
- Modbus Address Scan
3736

38-
![image](https://github.com/user-attachments/assets/dfbe062f-d696-4e38-a75f-d5d53182df58)
37+
![image](https://github.com/user-attachments/assets/798ed74a-c5fc-413f-a173-e223c9c7d3f3)
3938

4039
- Modbus Scanner (supports both Modbus RTU and Modbus TCP scanning)
4140

omodscan/ansimenu.cpp

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#include <QTimer>
2+
#include <QApplication>
3+
#include <QMouseEvent>
4+
#include "ansimenu.h"
5+
6+
///
7+
/// \brief AnsiMenu::AnsiMenu
8+
///
9+
AnsiMenu::AnsiMenu(QWidget *parent)
10+
: QMenu(parent)
11+
{
12+
_actionArabic = new QAction(tr("Arabic"), parent);
13+
_actionBaltic = new QAction(tr("Baltic"), parent);
14+
_actionCeltic = new QAction(tr("Celtic"), parent);
15+
_actionCyrillic = new QAction(tr("Cyrillic"), parent);
16+
_actionCentralEuropean = new QAction(tr("Central European"), parent);
17+
_actionChinese = new QAction(tr("Chinese"), parent);
18+
_actionEasternEuropean = new QAction(tr("Eastern European"), parent);
19+
_actionGreek = new QAction(tr("Greek"), parent);
20+
_actionHebrew = new QAction(tr("Hebrew"), parent);
21+
_actionJapanese = new QAction(tr("Japanese"), parent);
22+
_actionKorean = new QAction(tr("Korean"), parent);
23+
_actionThai = new QAction(tr("Thai"), parent);
24+
_actionTurkish = new QAction(tr("Turkish"), parent);
25+
_actionWesternEuropean = new QAction(tr("Western European"), parent);
26+
_actionVietnamese = new QAction(tr("Vietnamese"), parent);
27+
28+
createSubMenu(_actionArabic, { "ISO 8859-6", "Windows-1256" });
29+
createSubMenu(_actionBaltic, { "ISO 8859-4", "ISO 8859-13", "Windows-1257" });
30+
createSubMenu(_actionCeltic, { "ISO 8859-14" });
31+
createSubMenu(_actionCyrillic, { "ISO 8859-5", "KOI8-R", "KOI8-U", "Windows-1251" });
32+
createSubMenu(_actionCentralEuropean, { "Windows-1250" });
33+
createSubMenu(_actionChinese, { "Big5" });
34+
createSubMenu(_actionEasternEuropean, { "ISO 8859-2" });
35+
createSubMenu(_actionGreek, { "ISO 8859-7", "Windows-1253" });
36+
createSubMenu(_actionHebrew, { "ISO 8859-8", "Windows-1255" });
37+
createSubMenu(_actionJapanese, { "Shift-JIS" });
38+
createSubMenu(_actionKorean, { "EUC-KR" });
39+
createSubMenu(_actionThai, { "TIS-620" });
40+
createSubMenu(_actionTurkish, { "ISO 8859-3", "ISO 8859-9", "Windows-1254" });
41+
createSubMenu(_actionWesternEuropean, { "ISO 8859-1", "ISO 8859-15", "Windows-1252" });
42+
createSubMenu(_actionVietnamese, { "Windows-1258" });
43+
}
44+
45+
///
46+
/// \brief AnsiMenu::changeEvent
47+
/// \param event
48+
///
49+
void AnsiMenu::changeEvent(QEvent* event)
50+
{
51+
if (event->type() == QEvent::LanguageChange)
52+
{
53+
_actionArabic->setText(tr("Arabic"));
54+
_actionBaltic->setText(tr("Baltic"));
55+
_actionCeltic->setText(tr("Celtic"));
56+
_actionCyrillic->setText(tr("Cyrillic"));
57+
_actionCentralEuropean->setText(tr("Central European"));
58+
_actionChinese->setText(tr("Chinese"));
59+
_actionEasternEuropean->setText(tr("Eastern European"));
60+
_actionGreek->setText(tr("Greek"));
61+
_actionHebrew->setText(tr("Hebrew"));
62+
_actionJapanese->setText(tr("Japanese"));
63+
_actionKorean->setText(tr("Korean"));
64+
_actionThai->setText(tr("Thai"));
65+
_actionTurkish->setText(tr("Turkish"));
66+
_actionWesternEuropean->setText(tr("Western European"));
67+
_actionVietnamese->setText(tr("Vietnamese"));
68+
}
69+
70+
QMenu::changeEvent(event);
71+
}
72+
73+
///
74+
/// \brief AnsiMenu::mouseReleaseEvent
75+
/// \param event
76+
///
77+
void AnsiMenu::mouseReleaseEvent(QMouseEvent* event)
78+
{
79+
if (event->button() == Qt::LeftButton)
80+
{
81+
menuAction()->trigger();
82+
closeMenu();
83+
}
84+
85+
QMenu::mouseReleaseEvent(event);
86+
}
87+
88+
///
89+
/// \brief AnsiMenu::closeMenu
90+
///
91+
void AnsiMenu::closeMenu()
92+
{
93+
for (auto&& widget : QApplication::topLevelWidgets())
94+
{
95+
auto menu = qobject_cast<QMenu*>(widget);
96+
if (menu && menu->isVisible() && menu != this)
97+
menu->close();
98+
}
99+
}
100+
101+
///
102+
/// \brief AnsiMenu::createSubMenu
103+
/// \param a
104+
/// \param encodings
105+
///
106+
void AnsiMenu::createSubMenu(QAction* a, const QStringList& encodings)
107+
{
108+
auto menu = new QMenu(this);
109+
for(auto&& e : encodings)
110+
{
111+
auto action = new QAction(e, a);
112+
action->setCheckable(true);
113+
114+
menu->addAction(action);
115+
connect(action, &QAction::triggered, this, [this, action, a](){
116+
resetState();
117+
a->setChecked(true);
118+
action->setChecked(true);
119+
emit codepageSelected(action->text());
120+
menuAction()->trigger();
121+
});
122+
}
123+
124+
a->setCheckable(true);
125+
a->setMenu(menu);
126+
127+
addAction(a);
128+
}
129+
130+
///
131+
/// \brief AnsiMenu::selectCodepage
132+
/// \param name
133+
///
134+
void AnsiMenu::selectCodepage(const QString& name)
135+
{
136+
for(auto&& a : actions())
137+
{
138+
a->setChecked(false);
139+
for(auto&& ma : a->menu()->actions())
140+
{
141+
if(ma->text() == name)
142+
{
143+
a->setChecked(true);
144+
ma->setChecked(true);
145+
}
146+
}
147+
}
148+
}
149+
150+
///
151+
/// \brief AnsiMenu::resetState
152+
///
153+
void AnsiMenu::resetState()
154+
{
155+
for(auto&& a : actions())
156+
{
157+
a->setChecked(false);
158+
for(auto&& ma : a->menu()->actions())
159+
ma->setChecked(false);
160+
}
161+
}

omodscan/ansimenu.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifndef ANSIMENU_H
2+
#define ANSIMENU_H
3+
4+
#include <QMenu>
5+
6+
///
7+
/// \brief The AnsiMenu class
8+
///
9+
class AnsiMenu : public QMenu
10+
{
11+
Q_OBJECT
12+
13+
public:
14+
explicit AnsiMenu(QWidget *parent = nullptr);
15+
16+
void selectCodepage(const QString& name);
17+
18+
signals:
19+
void codepageSelected(const QString& name);
20+
21+
protected:
22+
void changeEvent(QEvent* event) override;
23+
void mouseReleaseEvent(QMouseEvent* event) override;
24+
25+
private:
26+
void closeMenu();
27+
void resetState();
28+
void createSubMenu(QAction* a, const QStringList& encodings);
29+
30+
private:
31+
QAction* _actionArabic;
32+
QAction* _actionBaltic;
33+
QAction* _actionCeltic;
34+
QAction* _actionCyrillic;
35+
QAction* _actionCentralEuropean;
36+
QAction* _actionChinese;
37+
QAction* _actionEasternEuropean;
38+
QAction* _actionGreek;
39+
QAction* _actionHebrew;
40+
QAction* _actionJapanese;
41+
QAction* _actionKorean;
42+
QAction* _actionThai;
43+
QAction* _actionTurkish;
44+
QAction* _actionWesternEuropean;
45+
QAction* _actionVietnamese;
46+
};
47+
48+
#endif // ANSIMENU_H

omodscan/ansiutils.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#ifndef ANSIUTILS_H
2+
#define ANSIUTILS_H
3+
4+
#include <QLocale>
5+
#include <QByteArray>
6+
#include <QTextCodec>
7+
#include <QDebug>
8+
#include "numericutils.h"
9+
10+
///
11+
/// \brief uint16ToAnsi
12+
/// \param value
13+
/// \param order
14+
/// \return
15+
///
16+
inline QByteArray uint16ToAnsi(quint16 value, ByteOrder order = ByteOrder::Direct)
17+
{
18+
quint8 lo, hi;
19+
breakUInt16(value, lo, hi, order);
20+
21+
QByteArray result;
22+
result.append(hi);
23+
result.append(lo);
24+
25+
return result;
26+
}
27+
28+
///
29+
/// \brief uint16FromAnsi
30+
/// \param Ansi
31+
/// \param order
32+
/// \return
33+
///
34+
inline quint16 uint16FromAnsi(const QByteArray& ansi, ByteOrder order = ByteOrder::Direct)
35+
{
36+
if(ansi.length() == 2)
37+
return makeUInt16((quint8)ansi[1], (quint8)ansi[0], order);
38+
else
39+
return 0;
40+
}
41+
42+
///
43+
/// \brief printableAnsi
44+
/// \param ansi
45+
/// \param codepage
46+
/// \param sep
47+
/// \return
48+
///
49+
inline QString printableAnsi(const QByteArray& ansi, const QString& codepage, const QChar& sep = QChar())
50+
{
51+
QByteArray result;
52+
for(auto&& c : ansi)
53+
{
54+
const quint8 b = c;
55+
if(b >= 32)
56+
result.append(b);
57+
else
58+
result.append('?');
59+
60+
if(sep.isPrint())
61+
result.append(sep.toLatin1());
62+
}
63+
64+
auto codec = QTextCodec::codecForName(codepage.toUtf8());
65+
return codec ? codec->toUnicode(result) : QString::fromLocal8Bit(result);
66+
}
67+
68+
#endif // ANSIUTILS_H

omodscan/byteorderutils.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@
1010
/// \param order
1111
/// \return
1212
///
13-
inline quint16 toByteOrderValue(quint16 value, ByteOrder order)
13+
template<typename T>
14+
inline T toByteOrderValue(T value, ByteOrder order)
1415
{
1516
switch(order)
1617
{
17-
case ByteOrder::BigEndian:
18-
return qToBigEndian<quint16>(value);
18+
case ByteOrder::Direct:
19+
return qToBigEndian<T>(value);
1920

20-
case ByteOrder::LittleEndian:
21-
return qToLittleEndian<quint16>(value);
21+
case ByteOrder::Swapped:
22+
return qToLittleEndian<T>(value);
2223
}
2324

2425
return value;

omodscan/controls/addressbasecombobox.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ void AddressBaseComboBox::changeEvent(QEvent* event)
2626
{
2727
switch(itemData(i).value<AddressBase>())
2828
{
29-
case AddressBase::Base0:
30-
setItemText(i, tr("0-based"));
29+
case AddressBase::Base0:
30+
setItemText(i, tr("0-based"));
3131
break;
3232

33-
case AddressBase::Base1:
34-
setItemText(i, tr("1-based"));
33+
case AddressBase::Base1:
34+
setItemText(i, tr("1-based"));
3535
break;
3636
}
3737
}

omodscan/controls/byteordercombobox.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <QEvent>
12
#include "byteordercombobox.h"
23

34
///
@@ -7,12 +8,27 @@
78
ByteOrderComboBox::ByteOrderComboBox(QWidget *parent)
89
:QComboBox(parent)
910
{
10-
addItem("Little-Endian", QVariant::fromValue(ByteOrder::LittleEndian));
11-
addItem("Big-Endian", QVariant::fromValue(ByteOrder::BigEndian));
11+
addItem(tr("Direct"), QVariant::fromValue(ByteOrder::Direct));
12+
addItem(tr("Swapped"), QVariant::fromValue(ByteOrder::Swapped));
1213

1314
connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ByteOrderComboBox::on_currentIndexChanged);
1415
}
1516

17+
///
18+
/// \brief ByteOrderComboBox::changeEvent
19+
/// \param event
20+
///
21+
void ByteOrderComboBox::changeEvent(QEvent* event)
22+
{
23+
if (event->type() == QEvent::LanguageChange)
24+
{
25+
setItemText(0, tr("Direct"));
26+
setItemText(1, tr("Swapped"));
27+
}
28+
29+
QComboBox::changeEvent(event);
30+
}
31+
1632
///
1733
/// \brief ByteOrderComboBox::currentByteOrder
1834
/// \return

omodscan/controls/byteordercombobox.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class ByteOrderComboBox : public QComboBox
1919
signals:
2020
void byteOrderChanged(ByteOrder order);
2121

22+
protected:
23+
void changeEvent(QEvent* event) override;
24+
2225
private slots:
2326
void on_currentIndexChanged(int);
2427
};

0 commit comments

Comments
 (0)