mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
refactor autotype sequences and entry-point functions
This commit is contained in:
parent
b5cabbeb43
commit
a9479fd662
@ -128,31 +128,16 @@ QStringList AutoType::windowTitles()
|
|||||||
return m_plugin->windowTitles();
|
return m_plugin->windowTitles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, const QString& customSequence, WId window)
|
/**
|
||||||
|
* Core Autotype function that will execute actions
|
||||||
|
*/
|
||||||
|
void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, const QString& sequence, WId window)
|
||||||
{
|
{
|
||||||
if (m_inAutoType || !m_plugin) {
|
// no edit to the sequence beyond this point
|
||||||
|
if (!verifyAutoTypeSyntax(sequence)) {
|
||||||
|
m_inAutoType = false; // TODO: make this automatic
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_inAutoType = true;
|
|
||||||
|
|
||||||
QString sequence;
|
|
||||||
if (customSequence.isEmpty()) {
|
|
||||||
QList<QString> sequences = autoTypeSequences(entry);
|
|
||||||
if(sequences.isEmpty()) {
|
|
||||||
sequence = "";
|
|
||||||
} else {
|
|
||||||
sequence = sequences.first();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sequence = customSequence;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!checkSyntax(sequence)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sequence.replace("{{}", "{LEFTBRACE}");
|
|
||||||
sequence.replace("{}}", "{RIGHTBRACE}");
|
|
||||||
|
|
||||||
QList<AutoTypeAction*> actions;
|
QList<AutoTypeAction*> actions;
|
||||||
ListDeleter<AutoTypeAction*> actionsDeleter(&actions);
|
ListDeleter<AutoTypeAction*> actionsDeleter(&actions);
|
||||||
@ -191,6 +176,30 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
|
|||||||
m_inAutoType = false;
|
m_inAutoType = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single Autotype entry-point function
|
||||||
|
* Perfom autotype sequence in the active window
|
||||||
|
*/
|
||||||
|
void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow)
|
||||||
|
{
|
||||||
|
if (m_inAutoType || !m_plugin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QString> sequences = autoTypeSequences(entry);
|
||||||
|
if(sequences.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_inAutoType = true;
|
||||||
|
|
||||||
|
executeAutoTypeActions(entry, hideWindow, sequences.first());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global Autotype entry-point funcion
|
||||||
|
* Perform global autotype on the active window
|
||||||
|
*/
|
||||||
void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
|
void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
|
||||||
{
|
{
|
||||||
if (m_inAutoType || !m_plugin) {
|
if (m_inAutoType || !m_plugin) {
|
||||||
@ -227,7 +236,7 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
|
|||||||
MessageBox::information(nullptr, tr("Auto-Type - KeePassXC"), message);
|
MessageBox::information(nullptr, tr("Auto-Type - KeePassXC"), message);
|
||||||
} else if ((matchList.size() == 1) && !config()->get("security/autotypeask").toBool()) {
|
} else if ((matchList.size() == 1) && !config()->get("security/autotypeask").toBool()) {
|
||||||
m_inAutoType = false;
|
m_inAutoType = false;
|
||||||
performAutoType(matchList.first().entry, nullptr, matchList.first().sequence);
|
executeAutoTypeActions(matchList.first().entry, nullptr, matchList.first().sequence);
|
||||||
} else {
|
} else {
|
||||||
m_windowFromGlobal = m_plugin->activeWindow();
|
m_windowFromGlobal = m_plugin->activeWindow();
|
||||||
AutoTypeSelectDialog* selectDialog = new AutoTypeSelectDialog();
|
AutoTypeSelectDialog* selectDialog = new AutoTypeSelectDialog();
|
||||||
@ -253,7 +262,7 @@ void AutoType::performAutoTypeFromGlobal(AutoTypeMatch match)
|
|||||||
|
|
||||||
m_inAutoType = false;
|
m_inAutoType = false;
|
||||||
|
|
||||||
performAutoType(match.entry, nullptr, match.sequence, m_windowFromGlobal);
|
executeAutoTypeActions(match.entry, nullptr, match.sequence, m_windowFromGlobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoType::resetInAutoType()
|
void AutoType::resetInAutoType()
|
||||||
@ -283,6 +292,7 @@ void AutoType::unloadPlugin()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AutoType::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
|
bool AutoType::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
|
||||||
{
|
{
|
||||||
Q_ASSERT(key);
|
Q_ASSERT(key);
|
||||||
@ -325,12 +335,19 @@ int AutoType::callEventFilter(void* event)
|
|||||||
return m_plugin->platformEventFilter(event);
|
return m_plugin->platformEventFilter(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AutoType::parseActions(const QString& sequence, const Entry* entry, QList<AutoTypeAction*>& actions)
|
/**
|
||||||
|
* Parse an autotype sequence and resolve its Template/command inside as AutoTypeActions
|
||||||
|
*/
|
||||||
|
bool AutoType::parseActions(const QString& actionSequence, const Entry* entry, QList<AutoTypeAction*>& actions)
|
||||||
{
|
{
|
||||||
QString tmpl;
|
QString tmpl;
|
||||||
bool inTmpl = false;
|
bool inTmpl = false;
|
||||||
m_autoTypeDelay = config()->get("AutoTypeDelay").toInt();
|
m_autoTypeDelay = config()->get("AutoTypeDelay").toInt();
|
||||||
|
|
||||||
|
QString sequence = actionSequence;
|
||||||
|
sequence.replace("{{}", "{LEFTBRACE}");
|
||||||
|
sequence.replace("{}}", "{RIGHTBRACE}");
|
||||||
|
|
||||||
for (const QChar& ch : sequence) {
|
for (const QChar& ch : sequence) {
|
||||||
if (inTmpl) {
|
if (inTmpl) {
|
||||||
if (ch == '{') {
|
if (ch == '{') {
|
||||||
@ -369,6 +386,9 @@ bool AutoType::parseActions(const QString& sequence, const Entry* entry, QList<A
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an autotype Template/command to its AutoTypeAction that will be executed by the plugin executor
|
||||||
|
*/
|
||||||
QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, const Entry* entry)
|
QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, const Entry* entry)
|
||||||
{
|
{
|
||||||
QString tmplName = tmpl;
|
QString tmplName = tmpl;
|
||||||
@ -512,6 +532,9 @@ QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, c
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrive the autotype sequences matches for a given windowTitle
|
||||||
|
*/
|
||||||
QList<QString> AutoType::autoTypeSequences(const Entry* entry, const QString& windowTitle)
|
QList<QString> AutoType::autoTypeSequences(const Entry* entry, const QString& windowTitle)
|
||||||
{
|
{
|
||||||
QList<QString> sequenceList;
|
QList<QString> sequenceList;
|
||||||
@ -564,6 +587,9 @@ QList<QString> AutoType::autoTypeSequences(const Entry* entry, const QString& wi
|
|||||||
return sequenceList;
|
return sequenceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a window title matches a pattern
|
||||||
|
*/
|
||||||
bool AutoType::windowMatches(const QString& windowTitle, const QString& windowPattern)
|
bool AutoType::windowMatches(const QString& windowTitle, const QString& windowPattern)
|
||||||
{
|
{
|
||||||
if (windowPattern.startsWith("//") && windowPattern.endsWith("//") && windowPattern.size() >= 4) {
|
if (windowPattern.startsWith("//") && windowPattern.endsWith("//") && windowPattern.size() >= 4) {
|
||||||
@ -574,11 +600,19 @@ bool AutoType::windowMatches(const QString& windowTitle, const QString& windowPa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a window title matches an entry Title
|
||||||
|
* The entry title should be Spr-compiled by the caller
|
||||||
|
*/
|
||||||
bool AutoType::windowMatchesTitle(const QString& windowTitle, const QString& resolvedTitle)
|
bool AutoType::windowMatchesTitle(const QString& windowTitle, const QString& resolvedTitle)
|
||||||
{
|
{
|
||||||
return !resolvedTitle.isEmpty() && windowTitle.contains(resolvedTitle, Qt::CaseInsensitive);
|
return !resolvedTitle.isEmpty() && windowTitle.contains(resolvedTitle, Qt::CaseInsensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a window title matches an entry URL
|
||||||
|
* The entry URL should be Spr-compiled by the caller
|
||||||
|
*/
|
||||||
bool AutoType::windowMatchesUrl(const QString& windowTitle, const QString& resolvedUrl)
|
bool AutoType::windowMatchesUrl(const QString& windowTitle, const QString& resolvedUrl)
|
||||||
{
|
{
|
||||||
if (!resolvedUrl.isEmpty() && windowTitle.contains(resolvedUrl, Qt::CaseInsensitive)) {
|
if (!resolvedUrl.isEmpty() && windowTitle.contains(resolvedUrl, Qt::CaseInsensitive)) {
|
||||||
@ -593,6 +627,9 @@ bool AutoType::windowMatchesUrl(const QString& windowTitle, const QString& resol
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the overall syntax of an autotype sequence is fine
|
||||||
|
*/
|
||||||
bool AutoType::checkSyntax(const QString& string)
|
bool AutoType::checkSyntax(const QString& string)
|
||||||
{
|
{
|
||||||
QString allowRepetition = "(?:\\s\\d+)?";
|
QString allowRepetition = "(?:\\s\\d+)?";
|
||||||
@ -618,6 +655,9 @@ bool AutoType::checkSyntax(const QString& string)
|
|||||||
return match.hasMatch();
|
return match.hasMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks an autotype sequence for high delay
|
||||||
|
*/
|
||||||
bool AutoType::checkHighDelay(const QString& string)
|
bool AutoType::checkHighDelay(const QString& string)
|
||||||
{
|
{
|
||||||
// 5 digit numbers(10 seconds) are too much
|
// 5 digit numbers(10 seconds) are too much
|
||||||
@ -626,6 +666,9 @@ bool AutoType::checkHighDelay(const QString& string)
|
|||||||
return match.hasMatch();
|
return match.hasMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks an autotype sequence for slow keypress
|
||||||
|
*/
|
||||||
bool AutoType::checkSlowKeypress(const QString& string)
|
bool AutoType::checkSlowKeypress(const QString& string)
|
||||||
{
|
{
|
||||||
// 3 digit numbers(100 milliseconds) are too much
|
// 3 digit numbers(100 milliseconds) are too much
|
||||||
@ -634,6 +677,9 @@ bool AutoType::checkSlowKeypress(const QString& string)
|
|||||||
return match.hasMatch();
|
return match.hasMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks an autotype sequence for high repetition command
|
||||||
|
*/
|
||||||
bool AutoType::checkHighRepetition(const QString& string)
|
bool AutoType::checkHighRepetition(const QString& string)
|
||||||
{
|
{
|
||||||
// 3 digit numbers are too much
|
// 3 digit numbers are too much
|
||||||
@ -642,6 +688,9 @@ bool AutoType::checkHighRepetition(const QString& string)
|
|||||||
return match.hasMatch();
|
return match.hasMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if the syntax of an autotype sequence is correct and doesn't have silly parameters
|
||||||
|
*/
|
||||||
bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
|
bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
|
||||||
{
|
{
|
||||||
if (!AutoType::checkSyntax(sequence)) {
|
if (!AutoType::checkSyntax(sequence)) {
|
||||||
@ -675,12 +724,3 @@ bool AutoType::verifyAutoTypeSyntax(const QString& sequence)
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow, const QString& customSequence, WId window)
|
|
||||||
{
|
|
||||||
auto sequence = entry->effectiveAutoTypeSequence();
|
|
||||||
if (verifyAutoTypeSyntax(sequence)) {
|
|
||||||
executeAutoTypeActions(entry, hideWindow, customSequence, window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -38,10 +38,6 @@ class AutoType : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QStringList windowTitles();
|
QStringList windowTitles();
|
||||||
void executeAutoTypeActions(const Entry* entry,
|
|
||||||
QWidget* hideWindow = nullptr,
|
|
||||||
const QString& customSequence = QString(),
|
|
||||||
WId window = 0);
|
|
||||||
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
|
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
|
||||||
void unregisterGlobalShortcut();
|
void unregisterGlobalShortcut();
|
||||||
int callEventFilter(void* event);
|
int callEventFilter(void* event);
|
||||||
@ -51,9 +47,7 @@ public:
|
|||||||
static bool checkHighDelay(const QString& string);
|
static bool checkHighDelay(const QString& string);
|
||||||
static bool verifyAutoTypeSyntax(const QString& sequence);
|
static bool verifyAutoTypeSyntax(const QString& sequence);
|
||||||
void performAutoType(const Entry* entry,
|
void performAutoType(const Entry* entry,
|
||||||
QWidget* hideWindow = nullptr,
|
QWidget* hideWindow = nullptr);
|
||||||
const QString& customSequence = QString(),
|
|
||||||
WId window = 0);
|
|
||||||
|
|
||||||
inline bool isAvailable()
|
inline bool isAvailable()
|
||||||
{
|
{
|
||||||
@ -79,6 +73,10 @@ private:
|
|||||||
explicit AutoType(QObject* parent = nullptr, bool test = false);
|
explicit AutoType(QObject* parent = nullptr, bool test = false);
|
||||||
~AutoType();
|
~AutoType();
|
||||||
void loadPlugin(const QString& pluginPath);
|
void loadPlugin(const QString& pluginPath);
|
||||||
|
void executeAutoTypeActions(const Entry* entry,
|
||||||
|
QWidget* hideWindow = nullptr,
|
||||||
|
const QString& customSequence = QString(),
|
||||||
|
WId window = 0);
|
||||||
bool parseActions(const QString& sequence, const Entry* entry, QList<AutoTypeAction*>& actions);
|
bool parseActions(const QString& sequence, const Entry* entry, QList<AutoTypeAction*>& actions);
|
||||||
QList<AutoTypeAction*> createActionFromTemplate(const QString& tmpl, const Entry* entry);
|
QList<AutoTypeAction*> createActionFromTemplate(const QString& tmpl, const Entry* entry);
|
||||||
QList<QString> autoTypeSequences(const Entry* entry, const QString& windowTitle = QString());
|
QList<QString> autoTypeSequences(const Entry* entry, const QString& windowTitle = QString());
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
const int Entry::DefaultIconNumber = 0;
|
const int Entry::DefaultIconNumber = 0;
|
||||||
const int Entry::ResolveMaximumDepth = 10;
|
const int Entry::ResolveMaximumDepth = 10;
|
||||||
|
const QString Entry::AutoTypeSequenceUsername = "{USERNAME}{ENTER}";
|
||||||
|
const QString Entry::AutoTypeSequencePassword = "{PASSWORD}{ENTER}";
|
||||||
|
|
||||||
|
|
||||||
Entry::Entry()
|
Entry::Entry()
|
||||||
@ -242,6 +244,15 @@ QString Entry::effectiveAutoTypeSequence() const
|
|||||||
return m_data.defaultAutoTypeSequence;
|
return m_data.defaultAutoTypeSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sequence == Group::RootAutoTypeSequence && (!username().isEmpty() || !password().isEmpty())) {
|
||||||
|
if (username().isEmpty()) {
|
||||||
|
return AutoTypeSequencePassword;
|
||||||
|
} else if (password().isEmpty()) {
|
||||||
|
return AutoTypeSequenceUsername;
|
||||||
|
}
|
||||||
|
return Group::RootAutoTypeSequence;
|
||||||
|
}
|
||||||
|
|
||||||
return sequence;
|
return sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ public:
|
|||||||
int autoTypeObfuscation() const;
|
int autoTypeObfuscation() const;
|
||||||
QString defaultAutoTypeSequence() const;
|
QString defaultAutoTypeSequence() const;
|
||||||
QString effectiveAutoTypeSequence() const;
|
QString effectiveAutoTypeSequence() const;
|
||||||
|
QString effectiveNewAutoTypeSequence() const;
|
||||||
AutoTypeAssociations* autoTypeAssociations();
|
AutoTypeAssociations* autoTypeAssociations();
|
||||||
const AutoTypeAssociations* autoTypeAssociations() const;
|
const AutoTypeAssociations* autoTypeAssociations() const;
|
||||||
QString title() const;
|
QString title() const;
|
||||||
@ -109,6 +110,8 @@ public:
|
|||||||
|
|
||||||
static const int DefaultIconNumber;
|
static const int DefaultIconNumber;
|
||||||
static const int ResolveMaximumDepth;
|
static const int ResolveMaximumDepth;
|
||||||
|
static const QString AutoTypeSequenceUsername;
|
||||||
|
static const QString AutoTypeSequencePassword;
|
||||||
|
|
||||||
void setUuid(const Uuid& uuid);
|
void setUuid(const Uuid& uuid);
|
||||||
void setIcon(int iconNumber);
|
void setIcon(int iconNumber);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
const int Group::DefaultIconNumber = 48;
|
const int Group::DefaultIconNumber = 48;
|
||||||
const int Group::RecycleBinIconNumber = 43;
|
const int Group::RecycleBinIconNumber = 43;
|
||||||
|
const QString Group::RootAutoTypeSequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}";
|
||||||
|
|
||||||
Group::CloneFlags Group::DefaultCloneFlags = static_cast<Group::CloneFlags>(
|
Group::CloneFlags Group::DefaultCloneFlags = static_cast<Group::CloneFlags>(
|
||||||
Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries);
|
Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries);
|
||||||
@ -211,7 +212,7 @@ QString Group::effectiveAutoTypeSequence() const
|
|||||||
} while (group && sequence.isEmpty());
|
} while (group && sequence.isEmpty());
|
||||||
|
|
||||||
if (sequence.isEmpty()) {
|
if (sequence.isEmpty()) {
|
||||||
sequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}";
|
sequence = RootAutoTypeSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sequence;
|
return sequence;
|
||||||
|
@ -88,6 +88,7 @@ public:
|
|||||||
static const int RecycleBinIconNumber;
|
static const int RecycleBinIconNumber;
|
||||||
static CloneFlags DefaultCloneFlags;
|
static CloneFlags DefaultCloneFlags;
|
||||||
static Entry::CloneFlags DefaultEntryCloneFlags;
|
static Entry::CloneFlags DefaultEntryCloneFlags;
|
||||||
|
static const QString RootAutoTypeSequence;
|
||||||
|
|
||||||
Group* findChildByName(const QString& name);
|
Group* findChildByName(const QString& name);
|
||||||
Group* findChildByUuid(const Uuid& uuid);
|
Group* findChildByUuid(const Uuid& uuid);
|
||||||
|
@ -136,7 +136,7 @@ void TestAutoType::testInternal()
|
|||||||
QCOMPARE(m_platform->activeWindowTitle(), QString("Test"));
|
QCOMPARE(m_platform->activeWindowTitle(), QString("Test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestAutoType::testAutoTypeWithoutSequence()
|
void TestAutoType::testSingleAutoType()
|
||||||
{
|
{
|
||||||
m_autoType->performAutoType(m_entry1, nullptr);
|
m_autoType->performAutoType(m_entry1, nullptr);
|
||||||
|
|
||||||
@ -147,17 +147,6 @@ void TestAutoType::testAutoTypeWithoutSequence()
|
|||||||
.arg(m_test->keyToString(Qt::Key_Enter)));
|
.arg(m_test->keyToString(Qt::Key_Enter)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestAutoType::testAutoTypeWithSequence()
|
|
||||||
{
|
|
||||||
m_autoType->performAutoType(m_entry1, nullptr, "{Username}abc{PaSsWoRd}");
|
|
||||||
|
|
||||||
QCOMPARE(m_test->actionCount(), 15);
|
|
||||||
QCOMPARE(m_test->actionChars(),
|
|
||||||
QString("%1abc%2")
|
|
||||||
.arg(m_entry1->username())
|
|
||||||
.arg(m_entry1->password()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestAutoType::testGlobalAutoTypeWithNoMatch()
|
void TestAutoType::testGlobalAutoTypeWithNoMatch()
|
||||||
{
|
{
|
||||||
m_test->setActiveWindowTitle("nomatch");
|
m_test->setActiveWindowTitle("nomatch");
|
||||||
|
@ -38,8 +38,7 @@ private slots:
|
|||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
void testInternal();
|
void testInternal();
|
||||||
void testAutoTypeWithoutSequence();
|
void testSingleAutoType();
|
||||||
void testAutoTypeWithSequence();
|
|
||||||
void testGlobalAutoTypeWithNoMatch();
|
void testGlobalAutoTypeWithNoMatch();
|
||||||
void testGlobalAutoTypeWithOneMatch();
|
void testGlobalAutoTypeWithOneMatch();
|
||||||
void testGlobalAutoTypeTitleMatch();
|
void testGlobalAutoTypeTitleMatch();
|
||||||
|
Loading…
Reference in New Issue
Block a user