Skip to content

Commit fd85ca4

Browse files
committed
Action byte order changed to swap bytes. Added action ANSI
1 parent 1d6287c commit fd85ca4

37 files changed

Lines changed: 602 additions & 164 deletions

omodsim/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ if (NOT Qt6_FOUND)
1818
endif()
1919

2020
# Define target
21-
add_executable(omodsim)
21+
add_executable(omodsim
22+
ansiutils.h
23+
ansimenu.cpp ansimenu.h)
2224

2325
# Define compile definitions
2426
add_compile_definitions(APP_NAME="${PRODUCT_NAME}")

omodsim/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+
}

omodsim/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

omodsim/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

omodsim/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;

omodsim/controls/modbusmessagewidget.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
ModbusMessageWidget::ModbusMessageWidget(QWidget *parent)
1212
: QListWidget(parent)
1313
,_statusClr(Qt::red)
14-
,_byteOrder(ByteOrder::LittleEndian)
14+
,_byteOrder(ByteOrder::Direct)
1515
,_dataDisplayMode(DataDisplayMode::UInt16)
1616
,_showTimestamp(true)
1717
,_mm(nullptr)

omodsim/controls/outputwidget.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ void OutputListModel::updateData(const QModbusDataUnit& data)
191191
const auto mode = _parentWidget->dataDisplayMode();
192192
const auto pointType = _parentWidget->_displayDefinition.PointType;
193193
const auto byteOrder = *_parentWidget->byteOrder();
194+
const auto codepage = _parentWidget->codepage();
194195

195196
for(int i = 0; i < rowCount(); i++)
196197
{
@@ -217,6 +218,10 @@ void OutputListModel::updateData(const QModbusDataUnit& data)
217218
itemData.ValueStr = formatHexValue(pointType, value, byteOrder, itemData.Value);
218219
break;
219220

221+
case DataDisplayMode::Ansi:
222+
itemData.ValueStr = formatAnsiValue(pointType, value, byteOrder, codepage, itemData.Value);
223+
break;
224+
220225
case DataDisplayMode::FloatingPt:
221226
itemData.ValueStr = formatFloatValue(pointType, value, _lastData.value(i+1), byteOrder,
222227
(i%2) || (i+1>=rowCount()), itemData.Value);
@@ -312,7 +317,7 @@ OutputWidget::OutputWidget(QWidget *parent) :
312317
,_displayHexAddreses(false)
313318
,_displayMode(DisplayMode::Data)
314319
,_dataDisplayMode(DataDisplayMode::Hex)
315-
,_byteOrder(ByteOrder::LittleEndian)
320+
,_byteOrder(ByteOrder::Direct)
316321
,_listModel(new OutputListModel(this))
317322
{
318323
ui->setupUi(this);
@@ -747,6 +752,25 @@ void OutputWidget::setByteOrder(ByteOrder order)
747752
_listModel->update();
748753
}
749754

755+
///
756+
/// \brief OutputWidget::codepage
757+
/// \return
758+
///
759+
QString OutputWidget::codepage() const
760+
{
761+
return _codepage;
762+
}
763+
764+
///
765+
/// \brief OutputWidget::setCodepage
766+
/// \param name
767+
///
768+
void OutputWidget::setCodepage(const QString& name)
769+
{
770+
_codepage = name;
771+
_listModel->update();
772+
}
773+
750774
///
751775
/// \brief OutputWidget::on_listView_customContextMenuRequested
752776
/// \param pos

omodsim/controls/outputwidget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ class OutputWidget : public QWidget
8686
const ByteOrder* byteOrder() const;
8787
void setByteOrder(ByteOrder order);
8888

89+
QString codepage() const;
90+
void setCodepage(const QString& name);
91+
8992
bool displayHexAddresses() const;
9093
void setDisplayHexAddresses(bool on);
9194

@@ -146,6 +149,7 @@ private slots:
146149
DisplayMode _displayMode;
147150
DataDisplayMode _dataDisplayMode;
148151
ByteOrder _byteOrder;
152+
QString _codepage;
149153
DisplayDefinition _displayDefinition;
150154
QFile _fileCapture;
151155
AddressDescriptionMap _descriptionMap;

0 commit comments

Comments
 (0)