diff --git a/Linphone/core/App.cpp b/Linphone/core/App.cpp index 24ce4fe68..cb70a71f9 100644 --- a/Linphone/core/App.cpp +++ b/Linphone/core/App.cpp @@ -100,6 +100,7 @@ #include "tool/Utils.hpp" #include "tool/accessibility/AccessibilityHelper.hpp" #include "tool/accessibility/FocusHelper.hpp" +#include "tool/accessibility/KeyboardShortcuts.hpp" #include "tool/native/DesktopTools.hpp" #include "tool/providers/AvatarProvider.hpp" #include "tool/providers/EmojiProvider.hpp" @@ -643,6 +644,10 @@ void App::initCore() { tr("info_popup_configuration_failed_message").arg(message), false); }); } + + //--------------------------------------------------------------------------------------------- + lDebug() << log().arg("Creating KeyboardShortcuts"); + KeyboardShortcuts::create(getMainWindow()); } }, Qt::QueuedConnection); diff --git a/Linphone/core/call/CallList.cpp b/Linphone/core/call/CallList.cpp index 60ca474f6..a3bd81233 100644 --- a/Linphone/core/call/CallList.cpp +++ b/Linphone/core/call/CallList.cpp @@ -188,6 +188,15 @@ QSharedPointer CallList::getNextCall() { return nullptr; } +QSharedPointer CallList::getFirstIncommingPendingCall() { + auto callList = getSharedList(); + auto it = std::find_if(callList.begin(), callList.end(), [](const QSharedPointer call) { + return call->getState() == LinphoneEnums::CallState::IncomingReceived; + }); + if (it == callList.end()) return nullptr; + return *it; +} + void CallList::onStateChanged() { auto call = dynamic_cast(sender()); switch (call->getState()) { diff --git a/Linphone/core/call/CallList.hpp b/Linphone/core/call/CallList.hpp index 02be9408d..1b2e22e7e 100644 --- a/Linphone/core/call/CallList.hpp +++ b/Linphone/core/call/CallList.hpp @@ -55,6 +55,8 @@ public: // At the moment, it select the last call in the list. QSharedPointer getNextCall(); + QSharedPointer getFirstIncommingPendingCall(); + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; signals: void lUpdate(); diff --git a/Linphone/tool/CMakeLists.txt b/Linphone/tool/CMakeLists.txt index 8a9f58ca9..aafe1a72b 100644 --- a/Linphone/tool/CMakeLists.txt +++ b/Linphone/tool/CMakeLists.txt @@ -28,8 +28,9 @@ list(APPEND _LINPHONEAPP_SOURCES tool/ui/DashRectangle.cpp - tool/accessibility/FocusHelper.cpp tool/accessibility/AccessibilityHelper.cpp + tool/accessibility/KeyboardShortcuts.cpp + tool/accessibility/FocusHelper.cpp ) diff --git a/Linphone/tool/accessibility/KeyboardShortcuts.cpp b/Linphone/tool/accessibility/KeyboardShortcuts.cpp new file mode 100644 index 000000000..5e509c611 --- /dev/null +++ b/Linphone/tool/accessibility/KeyboardShortcuts.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2010-2025 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "KeyboardShortcuts.hpp" +#include "core/App.hpp" +#include "core/call/CallList.hpp" +#include "tool/Utils.hpp" +#include +#include + +DEFINE_ABSTRACT_OBJECT(KeyboardShortcuts) + +std::shared_ptr KeyboardShortcuts::gKeyboardShortcuts; + +KeyboardShortcuts::KeyboardShortcuts(QQuickWindow *window) { + mustBeInMainThread(getClassName()); + + mWindow = window; + + // Define shortcuts + mAcceptCallShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_A), mWindow); + mDeclineCallShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_D), mWindow); + + // Make some shortcut active for the whole app + mAcceptCallShortcut->setContext(Qt::ApplicationShortcut); + mDeclineCallShortcut->setContext(Qt::ApplicationShortcut); + + // Link shortcuts to action + QObject::connect(mAcceptCallShortcut, &QShortcut::activated, this, &KeyboardShortcuts::onAcceptCallShortcut); + QObject::connect(mDeclineCallShortcut, &QShortcut::activated, this, &KeyboardShortcuts::onDeclineCallShortcut); +} + +KeyboardShortcuts::~KeyboardShortcuts() { +} + +std::shared_ptr KeyboardShortcuts::create(QQuickWindow *window) { + if (gKeyboardShortcuts) return gKeyboardShortcuts; + auto model = std::make_shared(window); + gKeyboardShortcuts = model; + return model; +} + +std::shared_ptr KeyboardShortcuts::getInstance() { + return gKeyboardShortcuts; +} + +// ----------------------------------------------------------------------------- +// Actions callable with the shortcuts +// ----------------------------------------------------------------------------- + +void KeyboardShortcuts::onAcceptCallShortcut() { + // Retrieve the first pending call of the call list + auto callList = App::getInstance()->getCallList(); + auto currentPendingCall = callList->getFirstIncommingPendingCall(); + if (!currentPendingCall.isNull()) { + lDebug() << "Accept call with shortcut :" << currentPendingCall; + auto gui = new CallGui(currentPendingCall); + Utils::openCallsWindow(gui); + currentPendingCall->lAccept(false); + } +} + +void KeyboardShortcuts::onDeclineCallShortcut() { + // Retrieve the first pending call of the call list + auto callList = App::getInstance()->getCallList(); + auto currentPendingCall = callList->getFirstIncommingPendingCall(); + if (!currentPendingCall.isNull()) { + lDebug() << "Dcline call with shortcut :" << currentPendingCall; + currentPendingCall->lDecline(); + } +} \ No newline at end of file diff --git a/Linphone/tool/accessibility/KeyboardShortcuts.hpp b/Linphone/tool/accessibility/KeyboardShortcuts.hpp new file mode 100644 index 000000000..da91d0054 --- /dev/null +++ b/Linphone/tool/accessibility/KeyboardShortcuts.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010-2025 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "tool/AbstractObject.hpp" +#include +#include +#include +#include +#include + +#ifndef KEYBOARD_SHORTCUTS_H_ +#define KEYBOARD_SHORTCUTS_H_ + +class KeyboardShortcuts : public QObject, public AbstractObject { + Q_OBJECT + +public: + KeyboardShortcuts(QQuickWindow *window); + ~KeyboardShortcuts(); + static std::shared_ptr create(QQuickWindow *window); + static std::shared_ptr getInstance(); + +private: + static std::shared_ptr gKeyboardShortcuts; + + // Window where to put the shortcuts + QQuickWindow *mWindow = nullptr; + + // The shortcuts + QShortcut *mAcceptCallShortcut; + QShortcut *mDeclineCallShortcut; + + // Actions callable with the shortcuts + static void onAcceptCallShortcut(); + static void onDeclineCallShortcut(); + + DECLARE_ABSTRACT_OBJECT +}; + +#endif // KEYBOARD_SHORTCUTS_H_ \ No newline at end of file diff --git a/Linphone/view/Control/Tool/Helper/utils.js b/Linphone/view/Control/Tool/Helper/utils.js index bf5a4066d..31cb2a088 100644 --- a/Linphone/view/Control/Tool/Helper/utils.js +++ b/Linphone/view/Control/Tool/Helper/utils.js @@ -143,11 +143,8 @@ function getTopParent (object, useFakeParent) { // Check that an item is descendant of another one function isDescendant(child, parent) { - console.debug("---") - console.debug(child) var current = child.parent while (current) { - console.debug(current) if (current === parent) return true current = current.parent @@ -177,7 +174,6 @@ function getLastFocussableItemInItem(item) { current = next; next = current.nextItemInFocusChain(); } while(isDescendant(next, item) && next.visible) - console.log("find last content", current) return current; }