Implement global auto-type dialog.

It allows to select an entry when there are multiple entries
that match the window title.
This commit is contained in:
Felix Geyer 2012-07-21 22:17:48 +02:00
parent 34ad5d61f6
commit 20e4643560
7 changed files with 260 additions and 9 deletions

View File

@ -20,6 +20,8 @@ configure_file(config-keepassx.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keepas
set(keepassx_SOURCES
autotype/AutoType.cpp
autotype/AutoTypeAction.cpp
autotype/AutoTypeSelectDialog.cpp
autotype/AutoTypeSelectView.cpp
autotype/ShortcutWidget.cpp
autotype/WindowSelectComboBox.cpp
core/AutoTypeAssociations.cpp
@ -99,6 +101,8 @@ set(keepassx_SOURCES
set(keepassx_MOC
autotype/AutoType.h
autotype/AutoTypeSelectDialog.h
autotype/AutoTypeSelectView.h
autotype/ShortcutWidget.h
autotype/WindowSelectComboBox.h
core/AutoTypeAssociations.h

View File

@ -21,6 +21,7 @@
#include <QtGui/QApplication>
#include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeSelectDialog.h"
#include "core/Database.h"
#include "core/Entry.h"
#include "core/FilePath.h"
@ -88,7 +89,7 @@ QStringList AutoType::windowTitles()
return m_plugin->windowTitles();
}
void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow, const QString& customSequence)
void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow, const QString& customSequence, WId window)
{
if (m_inAutoType || !m_plugin) {
return;
@ -117,10 +118,12 @@ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow, const QS
Tools::wait(500);
WId activeWindow = m_plugin->activeWindow();
if (!window) {
window = m_plugin->activeWindow();
}
Q_FOREACH (AutoTypeAction* action, actions) {
if (m_plugin->activeWindow() != activeWindow) {
if (m_plugin->activeWindow() != window) {
qWarning("Active window changed, interrupting auto-type.");
break;
}
@ -146,13 +149,15 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
m_inAutoType = true;
QList<QPair<Entry*, QString> > entryList;
QList<Entry*> entryList;
QHash<Entry*, QString> sequenceHash;
Q_FOREACH (Database* db, dbList) {
Q_FOREACH (Entry* entry, db->rootGroup()->entriesRecursive()) {
QString sequence = entry->autoTypeSequence(windowTitle);
if (!sequence.isEmpty()) {
entryList << QPair<Entry*, QString>(entry, sequence);
entryList << entry;
sequenceHash.insert(entry, sequence);
}
}
}
@ -162,14 +167,34 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
}
else if (entryList.size() == 1) {
m_inAutoType = false;
performAutoType(entryList.first().first, Q_NULLPTR, entryList.first().second);
performAutoType(entryList.first(), Q_NULLPTR, sequenceHash[entryList.first()]);
}
else {
// TODO: implement
m_inAutoType = false;
m_windowFromGlobal = m_plugin->activeWindow();
AutoTypeSelectDialog* selectDialog = new AutoTypeSelectDialog();
connect(selectDialog, SIGNAL(entryActivated(Entry*,QString)),
SLOT(performAutoTypeFromGlobal(Entry*,QString)));
connect(selectDialog, SIGNAL(rejected()), SLOT(resetInAutoType()));
selectDialog->setEntries(entryList, sequenceHash);
selectDialog->show();
}
}
void AutoType::performAutoTypeFromGlobal(Entry* entry, const QString& sequence)
{
Q_ASSERT(m_inAutoType);
m_inAutoType = false;
performAutoType(entry, Q_NULLPTR, sequence, m_windowFromGlobal);
}
void AutoType::resetInAutoType()
{
Q_ASSERT(m_inAutoType);
m_inAutoType = false;
}
bool AutoType::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
{
Q_ASSERT(key);

View File

@ -20,6 +20,7 @@
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <QtGui/QWidget>
#include "core/Global.h"
@ -37,7 +38,7 @@ class AutoType : public QObject
public:
QStringList windowTitles();
void performAutoType(const Entry* entry, QWidget* hideWindow = Q_NULLPTR,
const QString& customSequence = QString());
const QString& customSequence = QString(), WId window = 0);
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
void unregisterGlobalShortcut();
int callEventFilter(void* event);
@ -54,6 +55,10 @@ public Q_SLOTS:
Q_SIGNALS:
void globalShortcutTriggered();
private Q_SLOTS:
void performAutoTypeFromGlobal(Entry* entry, const QString& sequence);
void resetInAutoType();
private:
explicit AutoType(QObject* parent = Q_NULLPTR);
~AutoType();
@ -67,6 +72,7 @@ private:
QPluginLoader* m_pluginLoader;
AutoTypePlatformInterface* m_plugin;
AutoTypeExecutor* m_executor;
WId m_windowFromGlobal;
static AutoType* m_instance;
Q_DISABLE_COPY(AutoType)

View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
*
* 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 2 or (at your option)
* version 3 of the License.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "AutoTypeSelectDialog.h"
#include <QtGui/QApplication>
#include <QtGui/QDesktopWidget>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QLabel>
#include <QtGui/QVBoxLayout>
#include "autotype/AutoTypeSelectView.h"
#include "core/FilePath.h"
#include "gui/entry/EntryModel.h"
AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent)
: QDialog(parent)
, m_view(new AutoTypeSelectView(this))
, m_entryActivatedEmitted(false)
{
setAttribute(Qt::WA_DeleteOnClose);
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
setWindowTitle(tr("Auto-Type - KeePassX"));
setWindowIcon(filePath()->applicationIcon());
QSize size(400, 250);
resize(size);
// move dialog to the center of the screen
QPoint screenCenter = QApplication::desktop()->screenGeometry(QCursor::pos()).center();
move(screenCenter.x() - (size.width() / 2), screenCenter.y() - (size.height() / 2));
QVBoxLayout* layout = new QVBoxLayout(this);
QLabel* descriptionLabel = new QLabel(tr("Select entry to Auto-Type:"), this);
layout->addWidget(descriptionLabel);
connect(m_view, SIGNAL(activated(QModelIndex)), SLOT(emitEntryActivated(QModelIndex)));
connect(m_view, SIGNAL(clicked(QModelIndex)), SLOT(emitEntryActivated(QModelIndex)));
layout->addWidget(m_view);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, Qt::Horizontal, this);
connect(buttonBox, SIGNAL(rejected()), SLOT(reject()));
layout->addWidget(buttonBox);
}
void AutoTypeSelectDialog::setEntries(const QList<Entry*>& entries, const QHash<Entry*, QString>& sequences)
{
m_sequences = sequences;
m_view->setEntryList(entries);
}
void AutoTypeSelectDialog::emitEntryActivated(const QModelIndex& index)
{
// make sure we don't emit the signal twice when both activated() and clicked() are triggered
if (m_entryActivatedEmitted) {
return;
}
m_entryActivatedEmitted = true;
Entry* entry = m_view->entryFromIndex(index);
accept();
Q_EMIT entryActivated(entry, m_sequences[entry]);
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
*
* 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 2 or (at your option)
* version 3 of the License.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSX_AUTOTYPESELECTDIALOG_H
#define KEEPASSX_AUTOTYPESELECTDIALOG_H
#include <QtCore/QAbstractItemModel>
#include <QtCore/QHash>
#include <QtGui/QDialog>
#include "core/Global.h"
class AutoTypeSelectView;
class Entry;
class AutoTypeSelectDialog : public QDialog
{
Q_OBJECT
public:
explicit AutoTypeSelectDialog(QWidget* parent = Q_NULLPTR);
void setEntries(const QList<Entry*>& entries, const QHash<Entry*, QString>& sequences);
Q_SIGNALS:
void entryActivated(Entry* entry, const QString& sequence);
private Q_SLOTS:
void emitEntryActivated(const QModelIndex& index);
private:
AutoTypeSelectView* const m_view;
QHash<Entry*, QString> m_sequences;
bool m_entryActivatedEmitted;
};
#endif // KEEPASSX_AUTOTYPESELECTDIALOG_H

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
*
* 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 2 or (at your option)
* version 3 of the License.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "AutoTypeSelectView.h"
#include <QtGui/QMouseEvent>
AutoTypeSelectView::AutoTypeSelectView(QWidget* parent)
: EntryView(parent)
{
hideColumn(3);
setMouseTracking(true);
setAllColumnsShowFocus(true);
}
void AutoTypeSelectView::setEntryList(const QList<Entry*>& entries)
{
EntryView::setEntryList(entries);
setCurrentIndex(model()->index(0, 0));
}
void AutoTypeSelectView::mouseMoveEvent(QMouseEvent* event)
{
QModelIndex index = indexAt(event->pos());
if (index.isValid()) {
setCurrentIndex(index);
setCursor(Qt::PointingHandCursor);
}
else {
unsetCursor();
}
EntryView::mouseMoveEvent(event);
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
*
* 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 2 or (at your option)
* version 3 of the License.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSX_AUTOTYPESELECTVIEW_H
#define KEEPASSX_AUTOTYPESELECTVIEW_H
#include "core/Global.h"
#include "gui/entry/EntryView.h"
class Entry;
class AutoTypeSelectView : public EntryView
{
Q_OBJECT
public:
explicit AutoTypeSelectView(QWidget* parent = Q_NULLPTR);
void setEntryList(const QList<Entry*>& entries) Q_DECL_OVERRIDE;
protected:
void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
};
#endif // KEEPASSX_AUTOTYPESELECTVIEW_H