Commit 615dfe83 authored by Ingo Klöcker's avatar Ingo Klöcker
Browse files

Focus first child widget when switching the main view

This change adds a simple interface to allow passing input focus to a
suitable child widget of the different main views. The interface is
implemented by all main views.

The welcome view passes the focus to the label with the welcome message.
The certificate view passes the focus to the search bar.
The pad view passes the focus to the text edit, so that the user can
immediately paste or start typing.
The smart card view passes the focus to the first enabled child widget.

In particular, passing the focus to a child widget of the activated main
view removes the focus from the tool bar buttons that may have been used
to switch the main view.

GnuPG-bug-id: 6026
parent 856652e7
......@@ -363,6 +363,7 @@ set(_kleopatra_SRCS
dialogs/weboftrustdialog.h
dialogs/weboftrustwidget.cpp
dialogs/weboftrustwidget.h
interfaces/focusfirstchild.h
newcertificatewizard/advancedsettingsdialog.cpp
newcertificatewizard/advancedsettingsdialog_p.h
newcertificatewizard/enterdetailspage.cpp
......
/* -*- mode: c++; c-basic-offset:4 -*-
interfaces/focusfirstchild.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <Qt>
namespace Kleo
{
class FocusFirstChild
{
public:
virtual ~FocusFirstChild() = default;
virtual void focusFirstChild(Qt::FocusReason reason = Qt::OtherFocusReason) = 0;
};
}
......@@ -12,6 +12,8 @@
#include "aboutdata.h"
#include "settings.h"
#include <interfaces/focusfirstchild.h>
#include "view/padwidget.h"
#include "view/searchbar.h"
#include "view/tabwidget.h"
......@@ -113,7 +115,7 @@ static const std::vector<QString> mainViewActionNames = {
QStringLiteral("pad_view")
};
class CertificateView : public QWidget
class CertificateView : public QWidget, public FocusFirstChild
{
Q_OBJECT
public:
......@@ -133,6 +135,11 @@ public:
return ui.tabWidget;
}
void focusFirstChild(Qt::FocusReason reason) override
{
ui.searchBar->lineEdit()->setFocus(reason);
}
private:
struct UI {
TabWidget *tabWidget = nullptr;
......@@ -306,6 +313,9 @@ public:
}
}
ui.stackWidget->setCurrentWidget(widget);
if (auto ffci = dynamic_cast<Kleo::FocusFirstChild *>(widget)) {
ffci->focusFirstChild(Qt::TabFocusReason);
}
}
void showCertificateView()
......
......@@ -72,6 +72,8 @@ static GpgME::Protocol getProtocol(const std::shared_ptr<const Kleo::Crypto::Tas
class PadWidget::Private
{
friend class ::Kleo::PadWidget;
public:
Private(PadWidget *qq):
q(qq),
......@@ -534,3 +536,8 @@ PadWidget::PadWidget(QWidget *parent):
d(new Private(this))
{
}
void PadWidget::focusFirstChild(Qt::FocusReason reason)
{
d->mEdit->setFocus(reason);
}
......@@ -9,19 +9,24 @@
#pragma once
#include <interfaces/focusfirstchild.h>
#include <QWidget>
#include <memory>
namespace Kleo
{
/** The padwidget provides a general I/O area inside of kleopatra
* and can be used as an alternative view to the tabwidget. */
class PadWidget: public QWidget
class PadWidget: public QWidget, public FocusFirstChild
{
Q_OBJECT
public:
explicit PadWidget(QWidget *parent = Q_NULLPTR);
void focusFirstChild(Qt::FocusReason reason = Qt::OtherFocusReason) override;
private:
class Private;
std::shared_ptr<Private> d;
......
......@@ -76,6 +76,8 @@ public:
class SmartCardWidget::Private
{
friend class ::Kleo::SmartCardWidget;
public:
Private(SmartCardWidget *qq);
......@@ -193,6 +195,29 @@ SmartCardWidget::SmartCardWidget(QWidget *parent)
Kleo::SmartCardWidget::~SmartCardWidget() = default;
QWidget *getFirstEnabledFocusWidget(QWidget *parent)
{
for (auto w = parent->nextInFocusChain(); w != parent; w = w->nextInFocusChain()) {
if (w->isEnabled() && (w->focusPolicy() != Qt::NoFocus)) {
return w;
}
}
return nullptr;
}
void SmartCardWidget::focusFirstChild(Qt::FocusReason reason)
{
if (d->mStack->currentWidget() == d->mPlaceHolderWidget) {
if (auto w = getFirstEnabledFocusWidget(d->mPlaceHolderWidget)) {
w->setFocus(reason);
}
} else if (auto cardWidget = d->mTabWidget->currentWidget()) {
if (auto w = getFirstEnabledFocusWidget(cardWidget)) {
w->setFocus(reason);
}
}
}
void SmartCardWidget::reload()
{
ReaderStatus::mutableInstance()->updateStatus();
......
......@@ -8,6 +8,8 @@
*/
#pragma once
#include <interfaces/focusfirstchild.h>
#include <QWidget>
#include <memory>
......@@ -16,13 +18,15 @@ namespace Kleo
{
/* SmartCardWidget a generic widget to interact with smartcards */
class SmartCardWidget: public QWidget
class SmartCardWidget: public QWidget, public FocusFirstChild
{
Q_OBJECT
public:
explicit SmartCardWidget(QWidget *parent = nullptr);
~SmartCardWidget() override;
void focusFirstChild(Qt::FocusReason reason = Qt::OtherFocusReason) override;
public Q_SLOTS:
void reload();
......
/* view/smartcardwidget.h
/* view/welcomewidget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
......@@ -7,6 +7,8 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "welcomewidget.h"
#include <version-kleopatra.h>
......@@ -147,3 +149,8 @@ WelcomeWidget::WelcomeWidget (QWidget *parent): QWidget(parent),
d(new Private(this))
{
}
void WelcomeWidget::focusFirstChild(Qt::FocusReason reason)
{
d->mLabel->setFocus(reason);
}
#pragma once
/* view/welcomewidget.h
This file is part of Kleopatra, the KDE keymanager
......@@ -7,19 +6,25 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <interfaces/focusfirstchild.h>
#include <QWidget>
#include <memory>
namespace Kleo
{
/* Helper Widget that can be shown if a user has no keys */
class WelcomeWidget: public QWidget
class WelcomeWidget: public QWidget, public FocusFirstChild
{
Q_OBJECT
public:
explicit WelcomeWidget(QWidget *parent = nullptr);
void focusFirstChild(Qt::FocusReason reason = Qt::OtherFocusReason) override;
private:
class Private;
std::shared_ptr<Private> d;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment