add support for per TGID RID permission lists; add call router support to check for source RID permission to TGID;
parent
f8ee0aab51
commit
619cb548df
@ -0,0 +1,301 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Talkgroup Editor
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file TGEditRIDListWnd.h
|
||||||
|
* @ingroup tged
|
||||||
|
*/
|
||||||
|
#if !defined(__TG_EDIT_RID_LIST_WND_H__)
|
||||||
|
#define __TG_EDIT_RID_LIST_WND_H__
|
||||||
|
|
||||||
|
#include "common/Log.h"
|
||||||
|
|
||||||
|
#include "tged/CloseWndBase.h"
|
||||||
|
#include "tged/TGEdMain.h"
|
||||||
|
|
||||||
|
#include <final/final.h>
|
||||||
|
using namespace finalcut;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Class Declaration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This class implements the line edit control for radio IDs.
|
||||||
|
* @ingroup tged
|
||||||
|
*/
|
||||||
|
class HOST_SW_API RIDLineEdit final : public FLineEdit {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initializes a new instance of the RIDLineEdit class.
|
||||||
|
* @param widget
|
||||||
|
*/
|
||||||
|
explicit RIDLineEdit(FWidget* widget = nullptr) : FLineEdit{widget}
|
||||||
|
{
|
||||||
|
setInputFilter("[[:digit:]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Event Handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Event that occurs on keyboard key press.
|
||||||
|
* @param e Keyboard Event.
|
||||||
|
*/
|
||||||
|
void onKeyPress(finalcut::FKeyEvent* e) override
|
||||||
|
{
|
||||||
|
const auto key = e->key();
|
||||||
|
if (key == FKey::Up) {
|
||||||
|
emitCallback("up-pressed");
|
||||||
|
e->accept();
|
||||||
|
return;
|
||||||
|
} else if (key == FKey::Down) {
|
||||||
|
emitCallback("down-pressed");
|
||||||
|
e->accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == FKey::Insert) {
|
||||||
|
emitCallback("insert-pressed");
|
||||||
|
e->accept();
|
||||||
|
return;
|
||||||
|
} else if (key == FKey::Return) {
|
||||||
|
emitCallback("return-pressed");
|
||||||
|
e->accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FLineEdit::onKeyPress(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This class implements the talkgroup radio ID list editor window.
|
||||||
|
* @ingroup tged
|
||||||
|
*/
|
||||||
|
class HOST_SW_API TGEditRIDListWnd final : public CloseWndBase {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initializes a new instance of the TGEditWnd class.
|
||||||
|
* @param rule
|
||||||
|
* @param peerList
|
||||||
|
* @param title
|
||||||
|
* @param widget
|
||||||
|
*/
|
||||||
|
explicit TGEditRIDListWnd(lookups::TalkgroupRuleGroupVoice rule, std::vector<uint32_t> ridList,
|
||||||
|
std::string title = "Radio ID List", FWidget *widget = nullptr) : CloseWndBase{widget}
|
||||||
|
{
|
||||||
|
m_rule = rule;
|
||||||
|
this->ridList = ridList;
|
||||||
|
m_title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief List of radio IDs.
|
||||||
|
*/
|
||||||
|
std::vector<uint32_t> ridList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_skipSaving;
|
||||||
|
std::string m_title;
|
||||||
|
|
||||||
|
lookups::TalkgroupRuleGroupVoice m_rule;
|
||||||
|
|
||||||
|
FListBox m_listBox{this};
|
||||||
|
|
||||||
|
FButton m_add{"&Add", this};
|
||||||
|
FButton m_delete{"&Delete", this};
|
||||||
|
|
||||||
|
FLabel m_entryLabel{"Radio ID: ", this};
|
||||||
|
RIDLineEdit m_entry{this};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the window layout.
|
||||||
|
*/
|
||||||
|
void initLayout() override
|
||||||
|
{
|
||||||
|
FDialog::setText(m_title);
|
||||||
|
FDialog::setSize(FSize{40, 21});
|
||||||
|
|
||||||
|
m_enableSetButton = false;
|
||||||
|
CloseWndBase::initLayout();
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes window controls.
|
||||||
|
*/
|
||||||
|
void initControls() override
|
||||||
|
{
|
||||||
|
m_closeButton.setText("&OK");
|
||||||
|
|
||||||
|
m_add.setGeometry(FPoint(2, int(getHeight() - 4)), FSize(9, 1));
|
||||||
|
m_add.setBackgroundColor(FColor::DarkGreen);
|
||||||
|
m_add.setFocusBackgroundColor(FColor::DarkGreen);
|
||||||
|
m_add.addCallback("clicked", [&]() { addEntry(); });
|
||||||
|
|
||||||
|
m_delete.setGeometry(FPoint(13, int(getHeight() - 4)), FSize(10, 1));
|
||||||
|
m_delete.setBackgroundColor(FColor::DarkRed);
|
||||||
|
m_delete.setFocusBackgroundColor(FColor::DarkRed);
|
||||||
|
m_delete.addCallback("clicked", [&]() { deleteEntry(); });
|
||||||
|
|
||||||
|
m_entryLabel.setGeometry(FPoint(2, int(getHeight() - 6)), FSize(10, 1));
|
||||||
|
m_entry.setGeometry(FPoint(12, int(getHeight() - 6)), FSize(11, 1));
|
||||||
|
m_entry.setShadow(false);
|
||||||
|
m_entry.addCallback("up-pressed", [&]() {
|
||||||
|
uint32_t tgId = ::atoi(m_entry.getText().c_str());
|
||||||
|
tgId++;
|
||||||
|
if (tgId > 16777217U) {
|
||||||
|
tgId = 16777217U;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_entry.setText(std::to_string(tgId));
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
m_entry.addCallback("down-pressed", [&]() {
|
||||||
|
uint32_t tgId = ::atoi(m_entry.getText().c_str());
|
||||||
|
tgId--;
|
||||||
|
if (tgId < 1U) {
|
||||||
|
tgId = 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_entry.setText(std::to_string(tgId));
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
m_entry.addCallback("insert-pressed", [&]() { addEntry(); });
|
||||||
|
m_entry.addCallback("return-pressed", [&]() {
|
||||||
|
size_t curItem = m_listBox.currentItem();
|
||||||
|
auto item = m_listBox.getItem(curItem);
|
||||||
|
LogMessage(LOG_HOST, "Updating %s radio ID %s to %s for TG %s (%u)", m_title.c_str(), item.getText().c_str(), m_entry.getText().c_str(),
|
||||||
|
m_rule.name().c_str(), m_rule.source().tgId());
|
||||||
|
item.setText(m_entry.getText());
|
||||||
|
|
||||||
|
m_listBox.remove(curItem);
|
||||||
|
m_listBox.insert(item);
|
||||||
|
|
||||||
|
//setFocusWidget(&m_listBox);
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_listBox.setGeometry(FPoint{1, 1}, FSize{getWidth() - 1, getHeight() - 7});
|
||||||
|
m_listBox.setMultiSelection(false);
|
||||||
|
m_listBox.addCallback("row-selected", [&]() {
|
||||||
|
size_t curItem = m_listBox.currentItem();
|
||||||
|
auto item = m_listBox.getItem(curItem);
|
||||||
|
m_entry.setText(item.getText().c_str());
|
||||||
|
|
||||||
|
setFocusWidget(&m_listBox);
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
|
||||||
|
CloseWndBase::initControls();
|
||||||
|
|
||||||
|
setFocusWidget(&m_listBox);
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Populates the radio list.
|
||||||
|
*/
|
||||||
|
void loadList()
|
||||||
|
{
|
||||||
|
m_listBox.clear();
|
||||||
|
for (auto entry : ridList) {
|
||||||
|
m_listBox.insert(std::to_string(entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
void addEntry()
|
||||||
|
{
|
||||||
|
if (m_entry.getText() == "") {
|
||||||
|
m_listBox.insert(std::to_string(0U));
|
||||||
|
} else {
|
||||||
|
m_listBox.insert(m_entry.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
//setFocusWidget(&m_listBox);
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
void deleteEntry()
|
||||||
|
{
|
||||||
|
m_entry.setText("");
|
||||||
|
|
||||||
|
size_t curItem = m_listBox.currentItem();
|
||||||
|
auto item = m_listBox.getItem(curItem);
|
||||||
|
LogMessage(LOG_HOST, "Removing %s radio ID %s from TG %s (%u)", m_title.c_str(), item.getText().c_str(),
|
||||||
|
m_rule.name().c_str(), m_rule.source().tgId());
|
||||||
|
m_listBox.remove(curItem);
|
||||||
|
|
||||||
|
//setFocusWidget(&m_listBox);
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Event Handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Event that occurs on keyboard key press.
|
||||||
|
* @param e Keyboard Event.
|
||||||
|
*/
|
||||||
|
void onKeyPress(finalcut::FKeyEvent* e) override
|
||||||
|
{
|
||||||
|
const auto key = e->key();
|
||||||
|
if (key == FKey::Insert) {
|
||||||
|
addEntry();
|
||||||
|
redraw();
|
||||||
|
} else if (key == FKey::Del_char) {
|
||||||
|
deleteEntry();
|
||||||
|
redraw();
|
||||||
|
} else if (key == FKey::Enter || key == FKey::Return) {
|
||||||
|
this->close();
|
||||||
|
} else if (key == FKey::Escape) {
|
||||||
|
m_skipSaving = true;
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Event that occurs when the window is closed.
|
||||||
|
* @param e Close event.
|
||||||
|
*/
|
||||||
|
void onClose(FCloseEvent* e) override
|
||||||
|
{
|
||||||
|
if (m_skipSaving) {
|
||||||
|
m_skipSaving = false;
|
||||||
|
CloseWndBase::onClose(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ridList.clear();
|
||||||
|
for (uint32_t i = 0U; i < m_listBox.getCount(); i++) {
|
||||||
|
auto item = m_listBox.getItem(i + 1U);
|
||||||
|
if (item.getText() != "") {
|
||||||
|
uint32_t peerId = ::atoi(item.getText().c_str());
|
||||||
|
LogMessage(LOG_HOST, "%s radio ID %s for TG %s (%u)", m_title.c_str(), item.getText().c_str(),
|
||||||
|
m_rule.name().c_str(), m_rule.source().tgId());
|
||||||
|
ridList.push_back(peerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseWndBase::onClose(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __TG_EDIT_RID_LIST_WND_H__
|
||||||
Loading…
Reference in new issue