#include "navigationmodemgr.h" #include #include #include #include #include #include #include #include #include "navigationmode.h" using namespace vnotex; QWidget *NavigationModeMgr::s_widget = nullptr; NavigationModeMgr::NavigationModeMgr() : QObject(nullptr) { Q_ASSERT(s_widget); const auto &coreConfig = ConfigMgr::getInst().getCoreConfig(); auto keys = coreConfig.getShortcut(CoreConfig::Shortcut::NavigationMode); auto shortcut = WidgetUtils::createShortcut(keys, s_widget, Qt::ApplicationShortcut); if (!shortcut) { qWarning() << "failed to create shortcut for NavigationMode" << keys; return; } connect(shortcut, &QShortcut::activated, this, &NavigationModeMgr::triggerNavigationMode); } NavigationModeMgr::~NavigationModeMgr() { } NavigationModeMgr &NavigationModeMgr::getInst() { static NavigationModeMgr mgr; return mgr; } void NavigationModeMgr::registerNavigationTarget(NavigationMode *p_target) { auto key = getNextMajorKey(); if (!key.isNull()) { p_target->registerNavigation(key); m_targets.push_back(Target(p_target, true)); } else { qWarning() << "failed to register navigation target for no major key available" << p_target; } } QChar NavigationModeMgr::getNextMajorKey() { QChar ret = m_nextMajorKey; if (m_nextMajorKey == 'z') { m_nextMajorKey = QChar(); } else if (!m_nextMajorKey.isNull()) { m_nextMajorKey = QChar(m_nextMajorKey.toLatin1() + 1); } return ret; } void NavigationModeMgr::triggerNavigationMode() { if (m_targets.isEmpty()) { qInfo() << "no navigation target"; return; } m_activated = true; qApp->installEventFilter(this); for (auto &target : m_targets) { target.m_available = true; target.m_target->showNavigation(); } } void NavigationModeMgr::init(QWidget *p_widget) { s_widget = p_widget; } void NavigationModeMgr::exitNavigationMode() { m_activated = false; qApp->removeEventFilter(this); for (auto &target : m_targets) { target.m_available = true; target.m_target->hideNavigation(); } } bool NavigationModeMgr::eventFilter(QObject *p_obj, QEvent *p_event) { if (m_activated) { switch (p_event->type()) { case QEvent::KeyPress: { bool ret = handleKeyPress(static_cast(p_event)); if (ret) { return true; } break; } case QEvent::MouseButtonPress: exitNavigationMode(); break; default: break; } } return QObject::eventFilter(p_obj, p_event); } bool NavigationModeMgr::handleKeyPress(QKeyEvent *p_event) { int key = p_event->key(); auto modifiers = p_event->modifiers(); if (WidgetUtils::isMetaKey(key)) { return false; } bool hasConsumed = false; bool pending = false; for (auto &target : m_targets) { if (hasConsumed) { target.m_available = false; target.m_target->hideNavigation(); continue; } if (target.m_available) { auto sta = target.m_target->handleKeyNavigation(key); if (sta.m_isKeyConsumed) { hasConsumed = true; if (!sta.m_isTargetHit) { // Consumed but not hit. Need more keys. pending = true; } } else { // Do not ask this target any more. target.m_available = false; target.m_target->hideNavigation(); } } } if (!pending) { exitNavigationMode(); } return true; }