Shows how to create an active runner with Qt's key event handler.
#include "qt_key_event_runner.h"
#include <adtfstreaming3/graph_element_editors.h>
#include <QApplication>
#include <QWindow>
#include <QKeyEvent>
#include <QMainWindow>
#include <string>
using namespace adtf::ucom;
using namespace adtf::streaming;
std::vector<std::pair<Qt::Key, std::string>> s_oQtKeys{{Qt::Key_Escape, "Escape"},
{Qt::Key_Tab, "Tab"},
{Qt::Key_Backtab, "Backtab"},
{Qt::Key_Backspace, "Backspace"},
{Qt::Key_Return, "Return"},
{Qt::Key_Enter, "Enter"},
{Qt::Key_Insert, "Insert"},
{Qt::Key_Delete, "Delete"},
{Qt::Key_Pause, "Pause"},
{Qt::Key_Print, "Print"},
{Qt::Key_SysReq, "SysReq"},
{Qt::Key_Clear, "Clear"},
{Qt::Key_Home, "Home"},
{Qt::Key_End, "End"},
{Qt::Key_Left, "Left"},
{Qt::Key_Up, "Up"},
{Qt::Key_Right, "Right"},
{Qt::Key_Down, "Down"},
{Qt::Key_PageUp, "PageUp"},
{Qt::Key_PageDown, "PageDown"},
{Qt::Key_Shift, "Shift"},
{Qt::Key_Control, "Control"},
{Qt::Key_Meta, "Meta"},
{Qt::Key_Alt, "Alt"},
{Qt::Key_CapsLock, "CapsLock"},
{Qt::Key_NumLock, "NumLock"},
{Qt::Key_ScrollLock, "ScrollLock"},
{Qt::Key_F1, "F1"},
{Qt::Key_F2, "F2"},
{Qt::Key_F3, "F3"},
{Qt::Key_F4, "F4"},
{Qt::Key_F5, "F5"},
{Qt::Key_F6, "F6"},
{Qt::Key_F7, "F7"},
{Qt::Key_F8, "F8"},
{Qt::Key_F9, "F9"},
{Qt::Key_F10, "F10"},
{Qt::Key_F11, "F11"},
{Qt::Key_F12, "F12"},
{Qt::Key_F13, "F13"},
{Qt::Key_F14, "F14"},
{Qt::Key_F15, "F15"},
{Qt::Key_F16, "F16"},
{Qt::Key_F17, "F17"},
{Qt::Key_F18, "F18"},
{Qt::Key_F19, "F19"},
{Qt::Key_F20, "F20"},
{Qt::Key_F21, "F21"},
{Qt::Key_F22, "F22"},
{Qt::Key_F23, "F23"},
{Qt::Key_F24, "F24"},
{Qt::Key_F25, "F25"},
{Qt::Key_F26, "F26"},
{Qt::Key_F27, "F27"},
{Qt::Key_F28, "F28"},
{Qt::Key_F29, "F29"},
{Qt::Key_F30, "F30"},
{Qt::Key_F31, "F31"},
{Qt::Key_F32, "F32"},
{Qt::Key_F33, "F33"},
{Qt::Key_F34, "F34"},
{Qt::Key_F35, "F35"},
{Qt::Key_Super_L, "Super_L"},
{Qt::Key_Super_R, "Super_R"},
{Qt::Key_Menu, "Menu"},
{Qt::Key_Hyper_L, "Hyper_L"},
{Qt::Key_Hyper_R, "Hyper_R"},
{Qt::Key_Help, "Help"},
{Qt::Key_Direction_L, "Direction_L"},
{Qt::Key_Direction_R, "Direction_R"},
{Qt::Key_Space, "Space"},
{Qt::Key_Exclam, "Exclam"},
{Qt::Key_QuoteDbl, "QuoteDbl"},
{Qt::Key_NumberSign, "NumberSign"},
{Qt::Key_Dollar, "Dollar"},
{Qt::Key_Percent, "Percent"},
{Qt::Key_Ampersand, "Ampersand"},
{Qt::Key_Apostrophe, "Apostrophe"},
{Qt::Key_ParenLeft, "ParenLeft"},
{Qt::Key_ParenRight, "ParenRight"},
{Qt::Key_Asterisk, "Asterisk"},
{Qt::Key_Plus, "Plus"},
{Qt::Key_Comma, "Comma"},
{Qt::Key_Minus, "Minus"},
{Qt::Key_Period, "Period"},
{Qt::Key_Slash, "Slash"},
{Qt::Key_0, "0"},
{Qt::Key_1, "1"},
{Qt::Key_2, "2"},
{Qt::Key_3, "3"},
{Qt::Key_4, "4"},
{Qt::Key_5, "5"},
{Qt::Key_6, "6"},
{Qt::Key_7, "7"},
{Qt::Key_8, "8"},
{Qt::Key_9, "9"},
{Qt::Key_Colon, "Colon"},
{Qt::Key_Semicolon, "Semicolon"},
{Qt::Key_Less, "Less"},
{Qt::Key_Equal, "Equal"},
{Qt::Key_Greater, "Greater"},
{Qt::Key_Question, "Question"},
{Qt::Key_At, "At"},
{Qt::Key_A, "A"},
{Qt::Key_B, "B"},
{Qt::Key_C, "C"},
{Qt::Key_D, "D"},
{Qt::Key_E, "E"},
{Qt::Key_F, "F"},
{Qt::Key_G, "G"},
{Qt::Key_H, "H"},
{Qt::Key_I, "I"},
{Qt::Key_J, "J"},
{Qt::Key_K, "K"},
{Qt::Key_L, "L"},
{Qt::Key_M, "M"},
{Qt::Key_N, "N"},
{Qt::Key_O, "O"},
{Qt::Key_P, "P"},
{Qt::Key_Q, "Q"},
{Qt::Key_R, "R"},
{Qt::Key_S, "S"},
{Qt::Key_T, "T"},
{Qt::Key_U, "U"},
{Qt::Key_V, "V"},
{Qt::Key_W, "W"},
{Qt::Key_X, "X"},
{Qt::Key_Y, "Y"},
{Qt::Key_Z, "Z"},
{Qt::Key_BracketLeft, "BracketLeft"},
{Qt::Key_Backslash, "Backslash"},
{Qt::Key_BracketRight, "BracketRight"},
{Qt::Key_AsciiCircum, "AsciiCircum"},
{Qt::Key_Underscore, "Underscore"},
{Qt::Key_QuoteLeft, "QuoteLeft"},
{Qt::Key_BraceLeft, "BraceLeft"},
{Qt::Key_Bar, "Bar"},
{Qt::Key_BraceRight, "BraceRight"},
{Qt::Key_AsciiTilde, "AsciiTilde"}};
cQtKeyEventRunner::cQtKeyEventRunner()
{
adtf::streaming::set_description(
*this, "Use this active runner to send a trigger to Runner by pressing a defined keyboard shortcut.");
m_eKey.SetValueList(s_oQtKeys);
m_eKey.SetDescription("Key to choose for shortcut combination.");
RegisterPropertyVariable("key", m_eKey);
m_bCtrl.SetDescription("If enabled - 'CTRL' key will be set for shortcut combination.");
RegisterPropertyVariable("ctrl", m_bCtrl);
m_bAlt.SetDescription("If enabled - 'ALT' key will be set for shortcut combination.");
RegisterPropertyVariable("alt", m_bAlt);
m_bShift.SetDescription("If enabled - 'SHIFT' key will be set for shortcut combination.");
RegisterPropertyVariable("shift", m_bShift);
adtf::streaming::set_help_link(*this, "$(ADTF_QT5_DIR)/doc/html/page_qt5_key_event_runner.html");
}
cQtKeyEventRunner::~cQtKeyEventRunner() = default;
tResult cQtKeyEventRunner::Activate()
{
auto oAllWindows = qApp->topLevelWidgets();
m_pMainWindow = nullptr;
for (const auto pWindow : oAllWindows)
{
if (auto pMainWindow = qobject_cast<QMainWindow*>(pWindow))
{
m_pMainWindow = pMainWindow;
break;
}
}
if (!m_pMainWindow)
{
RETURN_ERROR_DESC(ERR_NOT_FOUND, "Unable to find main window.");
}
m_pMainWindow->installEventFilter(this);
RETURN_NOERROR;
}
tResult cQtKeyEventRunner::Deactivate()
{
if (m_pMainWindow)
{
m_pMainWindow->removeEventFilter(this);
m_pMainWindow = nullptr;
}
RETURN_NOERROR;
}
bool cQtKeyEventRunner::IsActivated() const
{
return m_pMainWindow != nullptr;
}
bool cQtKeyEventRunner::eventFilter(QObject* pObject, QEvent* pEvent)
{
if (pObject == m_pMainWindow && pEvent->type() == QEvent::KeyPress)
{
QKeyEvent* pKeyEvent = static_cast<QKeyEvent*>(pEvent);
if (pKeyEvent->key() == m_eKey && (!m_bCtrl || pKeyEvent->modifiers() & Qt::ControlModifier) &&
(!m_bAlt || pKeyEvent->modifiers() & Qt::AltModifier) &&
(!m_bShift || pKeyEvent->modifiers() & Qt::ShiftModifier))
{
Trigger();
}
}
return false;
}
ADTF_PLUGIN("Qt5 Key Event Runner Plugin", cQtKeyEventRunner)
Helper namespace for extension of adtf_string_forward interfaces.
Definition qt_string_intf.h:11
#include <adtftesting/adtf_testing.h>
#include <adtfsystemsdk/testing/test_system.h>
#include <adtffiltersdk/adtf_filtersdk.h>
#include <QApplication>
#include <QWidget>
#include <QTreeWidget>
#include <QtTest/QTest>
using namespace adtf::ucom;
using namespace adtf::streaming;
using namespace adtf::filter;
using namespace adtf::filter::testing;
using namespace adtf::mediadescription;
struct cMyTestSystem : adtf::system::testing::cSessionTestSystem
{
cMyTestSystem()
{
SetEnvironmentFile(TEST_ENVIRONMENT_FILE);
adtf::services::create_empty_session();
CreateService(CID_ADTF_REFERENCE_CLOCK, "clock");
SetRunLevel(adtf::base::tADTFRunLevel::RL_System);
}
};
QWindow* find_main_window()
{
auto oAllWindows = qApp->allWindows();
if (oAllWindows.empty())
{
THROW_ERROR_DESC(ERR_NOT_FOUND, "Unable to find main window");
}
return oAllWindows.first();
}
TEST_CASE_METHOD(cMyTestSystem, "Test Trigger Generation", "[req:ACORE-10085]")
{
auto fnTest = []
{
cFilterGraph oGraph;
object_ptr<IActiveRunner> pRunner;
object_ptr<IFilter> pFilter;
std::optional<cOutputRecorder> oRecorder;
auto fnInit = [&]() -> tResult
{
RETURN_IF_FAILED(add_graph_object(oGraph, "qt_key_event_runner.streaming.adtf.cid", "key_event_runner",
{{"key", adtf::util::cString::FromType(Qt::Key_I)}}, 0, pRunner));
RETURN_IF_FAILED(
add_graph_object(oGraph, "demo_time_trigger.filter.adtf.cid", "generator", {}, 0, pFilter));
THROW_IF_FAILED(oGraph.SetState(IFilter::tFilterState::State_Constructed));
RETURN_IF_FAILED(oGraph.AddConnection("connection1", "key_event_runner", "", "generator",
"data_generator_function", 0, true));
RETURN_IF_THROWS(oRecorder.emplace(pFilter, "out"));
THROW_IF_FAILED(oGraph.SetState(IFilter::tFilterState::State_Initialized));
RETURN_IF_FAILED(oGraph.SetState(IFilterGraph::tFilterState::State_Ready));
RETURN_IF_FAILED(_runtime->SetRunLevel(tADTFRunLevel::RL_FilterGraph));
RETURN_IF_FAILED(oGraph.SetState(IFilterGraph::tFilterState::State_Running));
RETURN_IF_FAILED(_runtime->SetRunLevel(tADTFRunLevel::RL_Running));
RETURN_NOERROR;
};
auto pMainWindow = find_main_window();
QTest::keyClick(pMainWindow, Qt::Key_I);
if (oRecorder->GetCurrentOutput().GetSamples().size() != 1)
{
THROW_ERROR_DESC(ERR_NOT_FOUND, "no trigger executed");
}
QTest::keyClick(pMainWindow, Qt::Key_U);
if (!oRecorder->GetCurrentOutput().GetSamples().empty())
{
THROW_ERROR_DESC(ERR_NOT_FOUND, "trigger should only be executed when 'i' is pressed");
}
QTest::keyClick(pMainWindow, Qt::Key_I);
if (oRecorder->GetCurrentOutput().GetSamples().size() != 1)
{
THROW_ERROR_DESC(ERR_NOT_FOUND, "no trigger executed");
}
};
REQUIRE_NOTHROW(ExecTest(tADTFRunLevel::RL_Session, std::move(fnTest)));
}
Namespace for all provided testing functionality helper.
Definition qt_test_tools.h:26
tResult execute_in_gui_thread(std::function< tResult()> fnFunction, std::chrono::milliseconds tmTimeout=std::chrono::milliseconds{0})
#define CID_ADTF_XSYSTEM
Definition qtxsystem_intf.h:21