Commit 9eeb270f authored by Stefano Crocco's avatar Stefano Crocco

Add a Wallet submenu to the Tools menu

The menu contains the same actions as the popup menu you get when
clicking on the wallet icon. This makes the actions easier to discover
and allows to access them using only the keyboard. Besides, it allows to
assign shortcuts to them.
parent 1edc789e
......@@ -102,9 +102,6 @@ WebEnginePage::WebEnginePage(WebEnginePart *part, QWidget *parent)
WebEnginePartDownloadManager::instance()->addPage(this);
m_wallet = new WebEngineWallet(this, parent ? parent->window()->winId() : 0);
if (m_wallet) {
connect(this, &QWebEnginePage::loadFinished, m_wallet, [this](bool ok){if (ok){m_wallet->detectAndFillPageForms(this);}});
}
}
WebEnginePage::~WebEnginePage()
......
......@@ -315,6 +315,8 @@ void WebEnginePart::initActions()
&WebEnginePart::slotShowSearchBar, actionCollection());
action->setWhatsThis(i18nc("find action \"whats this\" text", "<h3>Find text</h3>"
"Shows a dialog that allows you to find text on the displayed page."));
createWalletActions();
}
void WebEnginePart::updateActions()
......@@ -380,6 +382,7 @@ void WebEnginePart::setWallet(WebEngineWallet* wallet)
disconnect(m_wallet, &WebEngineWallet::walletClosed, this, &WebEnginePart::resetWallet);
disconnect(m_wallet, &WebEngineWallet::formDetectionDone, this, &WebEnginePart::walletFinishedFormDetection);
disconnect(m_wallet, &WebEngineWallet::saveFormDataCompleted, this, &WebEnginePart::slotWalletSavedForms);
disconnect(m_wallet, &WebEngineWallet::walletOpened, this, &WebEnginePart::updateWalletActions);
}
m_wallet = wallet;
if (m_wallet) {
......@@ -390,6 +393,7 @@ void WebEnginePart::setWallet(WebEngineWallet* wallet)
connect(m_wallet, &WebEngineWallet::walletClosed, this, &WebEnginePart::resetWallet);
connect(m_wallet, &WebEngineWallet::formDetectionDone, this, &WebEnginePart::walletFinishedFormDetection);
connect(m_wallet, &WebEngineWallet::saveFormDataCompleted, this, &WebEnginePart::slotWalletSavedForms);
connect(m_wallet, &WebEngineWallet::walletOpened, this, &WebEnginePart::updateWalletActions);
}
}
......@@ -533,6 +537,10 @@ void WebEnginePart::slotLoadFinished (bool ok)
slotUrlChanged(url);
}
if (m_wallet) {
m_wallet->detectAndFillPageForms(page());
}
bool pending = false;
// QWebFrame* frame = (page() ? page()->currentFrame() : 0);
// if (ok &&
......@@ -804,41 +812,32 @@ void WebEnginePart::deleteStatusBarWalletLabel()
void WebEnginePart::resetWallet()
{
deleteStatusBarWalletLabel();
m_walletData = {false, false, false};
updateWalletData({false, false, false});
updateWalletActions();
}
void WebEnginePart::slotShowWalletMenu()
{
QMenu *menu = new QMenu(nullptr);
bool hasCustomForms = m_wallet && m_wallet->hasCustomizedCacheableForms(url());
if (m_wallet) {
if (m_walletData.hasCachedData) {
menu->addAction(i18nc("Fill the forms with data from KWallet", "&Fill forms now"), [this]{if(page() && m_wallet){m_wallet->detectAndFillPageForms(page());}});
auto addAction = [this, menu](const QString &name) {
QAction *a = actionCollection()->action(name);
if (a->isEnabled()) {
menu->addAction(a);
}
if (m_walletData.hasAutoFillableForms || hasCustomForms) {
menu->addAction(i18n("Memorize passwords in this page &now"), [this]{if (page() && m_wallet){m_wallet->savePageDataNow(page());}});
}
}
if (m_wallet && (m_walletData.hasForms ||hasCustomForms)) {
menu->addSeparator();
if (m_walletData.hasForms) {
menu->addAction(i18n("&Customize fields to memorize for this page..."), this, [this](){if (m_wallet){m_wallet->customizeFieldsToCache(page(), view());}});
}
if (hasCustomForms) {
menu->addAction(i18n("Remove customized memorization settings for this page"), m_wallet, [this](){m_wallet->removeCustomizationForPage(url());});
}
}
};
addAction("walletFillFormsNow");
addAction("walletCacheFormsNow");
addAction("walletCustomizeFields");
addAction("walletRemoveCustomization");
menu->addSeparator();
if (m_webView && WebEngineSettings::self()->isNonPasswordStorableSite(m_webView->url().host())) {
menu->addAction(i18n("&Allow password caching for this site"), this, &WebEnginePart::slotDeleteNonPasswordStorableSite);
}
if (m_walletData.hasCachedData) {
menu->addAction(i18n("Remove all memorized passwords for this site"), this, &WebEnginePart::slotRemoveCachedPasswords);
}
addAction("walletDisablePasswordCaching");
addAction("walletRemoveCachedData");
menu->addSeparator();
menu->addAction(i18nc("Launch the wallet manager from the popup menu", "Launch wallet manager"), this, [this]{slotLaunchWalletManager();});
menu->addAction(i18n("&Close Wallet"), this, &WebEnginePart::resetWallet);
addAction("walletShowManager");
addAction("walletCloseWallet");
KAcceleratorManager::manage(menu);
menu->popup(QCursor::pos());
......@@ -851,19 +850,29 @@ void WebEnginePart::slotLaunchWalletManager()
job->start();
}
void WebEnginePart::slotDeleteNonPasswordStorableSite()
void WebEnginePart::togglePasswordStorableState(bool on)
{
if (m_webView)
WebEngineSettings::self()->removeNonPasswordStorableSite(m_webView->url().host());
if (!m_webView) {
return;
}
QString host = m_webView->url().host();
if (on) {
WebEngineSettings::self()->removeNonPasswordStorableSite(host);
} else {
WebEngineSettings::self()->addNonPasswordStorableSite(host);
}
updateWalletActions();
updateWalletStatusBarIcon();
}
void WebEnginePart::slotRemoveCachedPasswords()
{
if (!page() || !page()->wallet())
if (!page() || !page()->wallet()) {
return;
}
page()->wallet()->removeFormData(page());
m_walletData.hasCachedData = false;
updateWalletData(WalletData::HasCachedData, false);
}
void WebEnginePart::slotSetTextEncoding(QTextCodec * codec)
......@@ -992,7 +1001,7 @@ void WebEnginePart::slotSaveFormDataDone()
lay->removeWidget(m_passwordBar);
}
void WebEnginePart::addWalletStatusBarIcon ()
void WebEnginePart::updateWalletStatusBarIcon ()
{
if (m_walletData.hasForms) {
if (m_statusBarWalletLabel) {
......@@ -1014,8 +1023,7 @@ void WebEnginePart::addWalletStatusBarIcon ()
void WebEnginePart::slotFillFormRequestCompleted (bool ok)
{
m_walletData.hasCachedData = ok;
addWalletStatusBarIcon();
updateWalletData(WalletData::HasCachedData, ok);
}
void WebEnginePart::exitFullScreen()
......@@ -1026,15 +1034,101 @@ void WebEnginePart::exitFullScreen()
void WebEnginePart::walletFinishedFormDetection(const QUrl& url, bool found, bool autoFillableFound)
{
if (page() && page()->url() == url) {
m_walletData.hasForms = found;
m_walletData.hasAutoFillableForms = autoFillableFound;
updateWalletData({found, autoFillableFound});
updateWalletActions();
updateWalletStatusBarIcon();
}
}
void WebEnginePart::slotWalletSavedForms(const QUrl& url, bool success)
{
if (success && url == this->url()) {
m_walletData.hasCachedData = true;
addWalletStatusBarIcon();
updateWalletData(WalletData::HasCachedData, true);
}
}
void WebEnginePart::createWalletActions()
{
QAction *a = new QAction(i18nc("Fill the forms with data from KWallet", "&Fill forms now"), this);
a->setShortcut(QKeySequence("Ctrl+Shift+V"));
actionCollection()->addAction("walletFillFormsNow", a);
connect(a, &QAction::triggered, this, [this]{if(page() && m_wallet){m_wallet->detectAndFillPageForms(page());}});
a = new QAction(i18n("&Memorize passwords in this page now"), this);
actionCollection()->addAction("walletCacheFormsNow", a);
connect(a, &QAction::triggered, this, [this]{if (page() && m_wallet){m_wallet->savePageDataNow(page());}});
a = new QAction(i18n("&Customize fields to memorize for this page..."), this);
actionCollection()->addAction("walletCustomizeFields", a);
connect(a, &QAction::triggered, this, [this](){if (m_wallet){m_wallet->customizeFieldsToCache(page(), view());}});
a = new QAction(i18n("Remove customized memorization settings for this page"), this);
actionCollection()->addAction("walletRemoveCustomization", a);
connect(a, &QAction::triggered, this, [this](){m_wallet->removeCustomizationForPage(url());});
KToggleAction *ta = new KToggleAction (i18n("&Allow password caching for this site"), this);
actionCollection()->addAction("walletDisablePasswordCaching", ta);
connect(ta, &QAction::triggered, this, &WebEnginePart::togglePasswordStorableState);
a = new QAction(i18n("Remove all memorized passwords for this site"), this);
actionCollection()->addAction("walletRemoveCachedData", a);
connect(a, &QAction::triggered, this, &WebEnginePart::slotRemoveCachedPasswords);
a = new QAction(i18n("&Launch wallet manager"), this);
actionCollection()->addAction("walletShowManager", a);
connect(a, &QAction::triggered, this, &WebEnginePart::slotLaunchWalletManager);
a = new QAction(i18n("&Close Wallet"), this);
actionCollection()->addAction("walletCloseWallet", a);
connect(a, &QAction::triggered, this, &WebEnginePart::resetWallet);
updateWalletActions();
}
void WebEnginePart::updateWalletActions()
{
bool enableCaching = m_webView && !WebEngineSettings::self()->isNonPasswordStorableSite(m_webView->url().host());
bool hasCustomForms = m_wallet && m_wallet->hasCustomizedCacheableForms(url());
actionCollection()->action("walletFillFormsNow")->setEnabled(enableCaching && m_wallet && m_walletData.hasCachedData);
actionCollection()->action("walletCacheFormsNow")->setEnabled(enableCaching && m_wallet && (m_walletData.hasAutoFillableForms || hasCustomForms));
actionCollection()->action("walletCustomizeFields")->setEnabled(enableCaching && m_walletData.hasForms);
actionCollection()->action("walletRemoveCustomization")->setEnabled(hasCustomForms);
QAction *a = actionCollection()->action("walletDisablePasswordCaching");
a->setChecked(enableCaching);
a->setEnabled(m_walletData.hasForms);
actionCollection()->action("walletRemoveCachedData")->setEnabled(m_walletData.hasCachedData);
actionCollection()->action("walletCloseWallet")->setEnabled(m_wallet && m_wallet->isOpen());
}
void WebEnginePart::updateWalletData(WebEnginePart::WalletData::Member which, bool status)
{
switch (which) {
case WalletData::HasForms:
m_walletData.hasForms = status;
break;
case WalletData::HasAutofillableForms:
m_walletData.hasAutoFillableForms = status;
break;
case WalletData::HasCachedData:
m_walletData.hasCachedData = status;
break;
}
updateWalletActions();
updateWalletStatusBarIcon();
}
void WebEnginePart::updateWalletData(std::initializer_list<bool> data)
{
Q_ASSERT(data.size() > 0 && data.size() < 4);
int size = data.size();
auto it = data.begin();
m_walletData.hasForms = it[0];
if (size > 1) {
m_walletData.hasAutoFillableForms = it[1];
}
if (size > 2) {
m_walletData.hasAutoFillableForms = it[2];
}
updateWalletActions();
updateWalletStatusBarIcon();
}
......@@ -139,7 +139,7 @@ private Q_SLOTS:
void resetWallet();
void slotShowWalletMenu();
void slotLaunchWalletManager();
void slotDeleteNonPasswordStorableSite();
void togglePasswordStorableState(bool on);
void slotRemoveCachedPasswords();
void slotSetTextEncoding(QTextCodec*);
void slotSetStatusBarText(const QString& text);
......@@ -152,8 +152,9 @@ private Q_SLOTS:
void slotFeaturePermissionGranted(QWebEnginePage::Feature);
void slotFeaturePermissionDenied(QWebEnginePage::Feature);
void addWalletStatusBarIcon();
void updateWalletStatusBarIcon();
void walletFinishedFormDetection(const QUrl &url, bool found, bool autoFillableFound);
void updateWalletActions();
private:
WebEnginePage* page();
......@@ -161,18 +162,24 @@ private:
static void initWebEngineUrlSchemes();
void deleteStatusBarWalletLabel();
struct WalletData{
enum Member{HasForms, HasAutofillableForms, HasCachedData};
bool hasForms;
bool hasAutoFillableForms;
bool hasCachedData;
};
//Always use the following functions to change the values of m_walletData, as they automatically update the UI
void updateWalletData(WalletData::Member which, bool status);
void updateWalletData(std::initializer_list<bool> data);
void attemptInstallKIOSchemeHandler(const QUrl &url);
void initActions();
void createWalletActions();
void updateActions();
bool m_emitOpenUrlNotify;
struct WalletData{
bool hasForms;
bool hasAutoFillableForms;
bool hasCachedData;
};
WalletData m_walletData;
bool m_doLoadFinishedActions;
KUrlLabel* m_statusBarWalletLabel;
......
<!DOCTYPE gui SYSTEM "kpartgui.dtd">
<gui name="webenginepart" version="8">
<gui name="webenginepart" version="9">
<MenuBar>
<Menu name="file">
<text>&amp;File</text>
......@@ -26,6 +26,23 @@
<Action name="viewDocumentSource" />
<ActionList name="debugScriptList" />
</Menu>
<Menu name="tools">
<text>&amp;Tools</text>
<Menu name="wallet" icon="wallet-open">
<text>&amp;Credential management</text>
<Action name="walletFillFormsNow" enabled="false"/>
<Action name="walletCacheFormsNow"/>
<Separator />
<Action name="walletCustomizeFields"/>
<Action name="walletRemoveCustomization"/>
<Separator />
<Action name="walletDisablePasswordCaching"/>
<Action name="walletRemoveCachedData"/>
<Separator />
<Action name="walletShowManager"/>
<Action name="walletCloseWallet"/>
</Menu>
</Menu>
</MenuBar>
<ToolBar name="htmlToolBar" iconText="icononly" iconSize="22" hidden="true"><text>HTML Toolbar</text>
<Action name="zoomIn" />
......
......@@ -131,6 +131,11 @@ WebEngineWallet::~WebEngineWallet()
delete d;
}
bool WebEngineWallet::isOpen() const
{
return d->wallet && d->wallet->isOpen();
}
void WebEngineWallet::detectAndFillPageForms(WebEnginePage *page)
{
QUrl url = page->url();
......
......@@ -188,6 +188,12 @@ public:
*/
~WebEngineWallet() override;
/**
* @brief Whether the wallet is open or not
* @return @b true if the wallet is open and @b false otherwise
*/
bool isOpen() const;
/**
* @brief Attempts to save the form data from @p page and its children frames.
*
......@@ -366,6 +372,11 @@ Q_SIGNALS:
*/
void walletClosed();
/**
* @brief Signal emitted when the wallet is opened
*/
void walletOpened();
protected:
/**
* @brief Returns a list of forms for @p url that are waiting to be filled.
......
......@@ -321,6 +321,8 @@ void WebEngineWallet::WebEngineWalletPrivate::_k_openWalletDone(bool ok)
wallet->createFolder(KWallet::Wallet::FormDataFolder())) &&
wallet->setFolder(KWallet::Wallet::FormDataFolder())) {
emit q->walletOpened();
// Do pending fill requests...
if (!pendingFillRequests.isEmpty()) {
QMutableHashIterator<QUrl, FormsData> requestIt(pendingFillRequests);
......
Markdown is supported
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