--- /dev/null
+diff --git a/.travis.yml b/.travis.yml
+index fa33cf0..550518a 100644
+--- a/.travis.yml
++++ b/.travis.yml
+@@ -5,16 +5,20 @@ compiler:
+ - gcc
+ - clang
+ language: cpp
++sudo: required
++dist: trusty
+ install:
+ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq update; fi
+- - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake libqt4-dev libgcrypt11-dev zlib1g-dev libxtst-dev; fi
++ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev libxtst-dev xvfb; fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq cmake || brew install cmake; fi
+- - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq qt || brew install qt; fi
++ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq qt5 || brew install qt5; fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq libgcrypt || brew install libgcrypt; fi
+-before_script: mkdir build && pushd build
++before_script:
++ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then CMAKE_ARGS="-DCMAKE_PREFIX_PATH=/usr/local/opt/qt5"; fi
++ - mkdir build && pushd build
+ script:
+- - cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_GUI_TESTS=ON ..
++ - cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_GUI_TESTS=ON $CMAKE_ARGS ..
+ - make
+ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then make test ARGS+="-E testgui --output-on-failure"; fi
+ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then xvfb-run -a --server-args="-screen 0 800x600x24" make test ARGS+="-R testgui --output-on-failure"; fi
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 6df5503..21c46fa 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -21,7 +21,7 @@ endif()
+
+ project(KeePassX)
+
+-cmake_minimum_required(VERSION 2.6.4)
++cmake_minimum_required(VERSION 2.8.12)
+
+ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+
+@@ -31,7 +31,7 @@ include(CheckCXXSourceCompiles)
+
+ option(WITH_TESTS "Enable building of unit tests" ON)
+ option(WITH_GUI_TESTS "Enable building of GUI tests" OFF)
+-option(WITH_CXX11 "Build with the C++ 11 standard" ON)
++option(WITH_DEV_BUILD "Use only for development. Disables/warns about deprecated methods." OFF)
+
+ set(KEEPASSX_VERSION "2.0.2")
+ set(KEEPASSX_VERSION_NUM "2.0.2")
+@@ -61,7 +61,7 @@ macro(add_gcc_compiler_flags FLAGS)
+ add_gcc_compiler_cflags("${FLAGS}")
+ endmacro(add_gcc_compiler_flags)
+
+-add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_NO_STL -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII)
++add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII)
+
+ add_gcc_compiler_flags("-fno-common -fstack-protector --param=ssp-buffer-size=4")
+ add_gcc_compiler_flags("-Wall -Wextra -Wundef -Wpointer-arith -Wno-long-long")
+@@ -100,14 +100,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro")
+ endif()
+
+-if (WITH_CXX11)
+- add_gcc_compiler_cxxflags("-std=c++0x")
+- add_gcc_compiler_cflags("-ansi")
+- if(APPLE)
+- add_gcc_compiler_cxxflags("-stdlib=libc++")
+- endif()
+-else()
+- add_gcc_compiler_flags("-ansi")
++add_gcc_compiler_cxxflags("-std=c++11")
++
++if(APPLE)
++ add_gcc_compiler_cxxflags("-stdlib=libc++")
++endif()
++
++add_gcc_compiler_cflags("-ansi")
++
++if(WITH_DEV_BUILD)
++ add_definitions(-DQT_DEPRECATED_WARNINGS -DGCRYPT_NO_DEPRECATED)
+ endif()
+
+ if(MINGW)
+@@ -146,19 +148,18 @@ if(WITH_TESTS)
+ enable_testing()
+ endif(WITH_TESTS)
+
+-set(QT_REQUIRED_MODULES QtCore QtGui QtTest)
++find_package(Qt5Core 5.2 REQUIRED)
++find_package(Qt5Concurrent 5.2 REQUIRED)
++find_package(Qt5Widgets 5.2 REQUIRED)
++find_package(Qt5Test 5.2 REQUIRED)
++find_package(Qt5LinguistTools 5.2 REQUIRED)
++set(CMAKE_AUTOMOC ON)
+
+-find_package(Qt4 4.6.0 REQUIRED ${QT_REQUIRED_MODULES})
+-include(${QT_USE_FILE})
+ # Debian sets the the build type to None for package builds.
+ # Make sure we don't enable asserts there.
+ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG)
+
+-find_package(Gcrypt REQUIRED)
+-if(NOT (${GCRYPT_VERSION_STRING} VERSION_LESS "1.6.0"))
+- message(STATUS "Gcrypt ${GCRYPT_VERSION_STRING} supports the SALSA20 cipher")
+- set(GCRYPT_HAS_SALSA20 1)
+-endif()
++find_package(Gcrypt 1.6.0 REQUIRED)
+
+ find_package(ZLIB REQUIRED)
+
+@@ -199,10 +200,7 @@ endif()
+
+ include_directories(SYSTEM ${GCRYPT_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
+
+-if(NOT (${CMAKE_VERSION} VERSION_LESS 2.8.3))
+- set(PRINT_SUMMARY ON)
+- include(FeatureSummary)
+-endif()
++include(FeatureSummary)
+
+ add_subdirectory(src)
+ add_subdirectory(share)
+diff --git a/README.md b/README.md
+index 326bd4a..0c18ff3 100644
+--- a/README.md
++++ b/README.md
+@@ -49,20 +49,20 @@ Once downloaded, double click on the file to execute the installer.
+ The following tools must exist within your PATH:
+
+ * make
+-* cmake (>= 2.6.4)
+-* g++ or clang++
++* cmake (>= 2.8.12)
++* g++ (>= 4.7) or clang++ (>= 3.0)
+
+ The following libraries are required:
+
+-* Qt 4 (>= 4.6)
+-* libgcrypt
++* Qt 5 (>= 5.2): qtbase and qttools5
++* libgcrypt (>= 1.6)
+ * zlib
+-* libxtst (optional for auto-type on X11)
++* libxtst, qtx11extras (optional for auto-type on X11)
+
+ On Debian you can install them with:
+
+ ```bash
+-sudo apt-get install build-essential cmake libqt4-dev libgcrypt11-dev zlib1g-dev
++sudo apt-get install build-essential cmake qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev
+ ```
+
+ #### Build Steps
+diff --git a/share/translations/CMakeLists.txt b/share/translations/CMakeLists.txt
+index b1aa878..7380750 100644
+--- a/share/translations/CMakeLists.txt
++++ b/share/translations/CMakeLists.txt
+@@ -17,9 +17,9 @@ file(GLOB TRANSLATION_FILES *.ts)
+ get_filename_component(TRANSLATION_EN_ABS keepassx_en.ts ABSOLUTE)
+ list(REMOVE_ITEM TRANSLATION_FILES keepassx_en.ts)
+ list(REMOVE_ITEM TRANSLATION_FILES ${TRANSLATION_EN_ABS})
+-message(STATUS ${TRANSLATION_FILES})
++message(STATUS "${TRANSLATION_FILES}")
+
+-qt4_add_translation(QM_FILES ${TRANSLATION_FILES})
++qt5_add_translation(QM_FILES ${TRANSLATION_FILES})
+
+ install(FILES ${QM_FILES} DESTINATION ${DATA_INSTALL_DIR}/translations)
+ add_custom_target(translations DEPENDS ${QM_FILES})
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index da8b9ec..da35651 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -54,9 +54,6 @@ set(keepassx_SOURCES
+ core/ListDeleter.h
+ core/Metadata.cpp
+ core/PasswordGenerator.cpp
+- core/qlockfile.cpp
+- core/qsavefile.cpp
+- core/qsavefile_p.h
+ core/SignalMultiplexer.cpp
+ core/TimeDelta.cpp
+ core/TimeInfo.cpp
+@@ -64,8 +61,6 @@ set(keepassx_SOURCES
+ core/Tools.cpp
+ core/Translator.cpp
+ core/Uuid.cpp
+- core/qcommandlineoption.cpp
+- core/qcommandlineparser.cpp
+ crypto/Crypto.cpp
+ crypto/CryptoHash.cpp
+ crypto/Random.cpp
+@@ -133,94 +128,10 @@ set(keepassx_SOURCES
+ streams/SymmetricCipherStream.cpp
+ )
+
+-if(NOT GCRYPT_HAS_SALSA20)
+- set(keepassx_SOURCES
+- ${keepassx_SOURCES}
+- crypto/salsa20/ecrypt-config.h
+- crypto/salsa20/ecrypt-machine.h
+- crypto/salsa20/ecrypt-portable.h
+- crypto/salsa20/ecrypt-sync.h
+- crypto/salsa20/salsa20.c
+- crypto/SymmetricCipherSalsa20.cpp
+- )
+-endif()
+-
+-if(UNIX)
+- set(keepassx_SOURCES
+- ${keepassx_SOURCES}
+- core/qlockfile_unix.cpp
+- )
+-elseif(MINGW)
+- set(keepassx_SOURCES
+- ${keepassx_SOURCES}
+- core/qlockfile_win.cpp
+- )
+-endif()
+-
+ set(keepassx_SOURCES_MAINEXE
+ main.cpp
+ )
+
+-set(keepassx_MOC
+- autotype/AutoType.h
+- autotype/AutoTypeSelectDialog.h
+- autotype/AutoTypeSelectView.h
+- autotype/ShortcutWidget.h
+- autotype/WindowSelectComboBox.h
+- core/AutoTypeAssociations.h
+- core/Config.h
+- core/Database.h
+- core/Entry.h
+- core/EntryAttachments.h
+- core/EntryAttributes.h
+- core/Group.h
+- core/InactivityTimer.h
+- core/Metadata.h
+- core/qsavefile.h
+- gui/AboutDialog.h
+- gui/Application.h
+- gui/ChangeMasterKeyWidget.h
+- gui/Clipboard.h
+- gui/DatabaseOpenWidget.h
+- gui/DatabaseRepairWidget.h
+- gui/DatabaseSettingsWidget.h
+- gui/DatabaseTabWidget.h
+- gui/DatabaseWidget.h
+- gui/DatabaseWidgetStateSync.h
+- gui/DialogyWidget.h
+- gui/DragTabBar.h
+- gui/EditWidget.h
+- gui/EditWidgetIcons.h
+- gui/EditWidgetProperties.h
+- gui/IconModels.h
+- gui/KeePass1OpenWidget.h
+- gui/LineEdit.h
+- gui/MainWindow.h
+- gui/PasswordEdit.h
+- gui/PasswordGeneratorWidget.h
+- gui/PasswordComboBox.h
+- gui/SettingsWidget.h
+- gui/SortFilterHideProxyModel.h
+- gui/UnlockDatabaseWidget.h
+- gui/WelcomeWidget.h
+- gui/entry/AutoTypeAssociationsModel.h
+- gui/entry/EditEntryWidget.h
+- gui/entry/EntryAttachmentsModel.h
+- gui/entry/EntryAttributesModel.h
+- gui/entry/EntryHistoryModel.h
+- gui/entry/EntryModel.h
+- gui/entry/EntryView.h
+- gui/group/EditGroupWidget.h
+- gui/group/GroupModel.h
+- gui/group/GroupView.h
+- keys/CompositeKey_p.h
+- streams/HashedBlockStream.h
+- streams/LayeredStream.h
+- streams/qtiocompressor.h
+- streams/StoreDataStream.h
+- streams/SymmetricCipherStream.h
+-)
+-
+ set(keepassx_FORMS
+ gui/AboutDialog.ui
+ gui/ChangeMasterKeyWidget.ui
+@@ -248,17 +159,18 @@ if(MINGW)
+ ${CMAKE_SOURCE_DIR}/share/windows/icon.rc)
+ endif()
+
+-qt4_wrap_ui(keepassx_SOURCES ${keepassx_FORMS})
+-qt4_wrap_cpp(keepassx_SOURCES ${keepassx_MOC})
++qt5_wrap_ui(keepassx_SOURCES ${keepassx_FORMS})
+
+ add_library(keepassx_core STATIC ${keepassx_SOURCES})
+ set_target_properties(keepassx_core PROPERTIES COMPILE_DEFINITIONS KEEPASSX_BUILDING_CORE)
++target_link_libraries(keepassx_core Qt5::Core Qt5::Concurrent Qt5::Widgets)
+
+ add_executable(${PROGNAME} WIN32 MACOSX_BUNDLE ${keepassx_SOURCES_MAINEXE})
+ target_link_libraries(${PROGNAME}
+ keepassx_core
+- ${QT_QTCORE_LIBRARY}
+- ${QT_QTGUI_LIBRARY}
++ Qt5::Core
++ Qt5::Concurrent
++ Qt5::Widgets
+ ${GCRYPT_LIBRARIES}
+ ${ZLIB_LIBRARIES})
+
+@@ -276,7 +188,7 @@ install(TARGETS ${PROGNAME}
+
+ add_subdirectory(autotype)
+
+-if(APPLE AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8))
++if(APPLE)
+ if(QT_MAC_USE_COCOA AND EXISTS "${QT_LIBRARY_DIR}/Resources/qt_menu.nib")
+ install(DIRECTORY "${QT_LIBRARY_DIR}/Resources/qt_menu.nib"
+ DESTINATION "${DATA_INSTALL_DIR}")
+@@ -294,7 +206,7 @@ if(APPLE AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8))
+ install_qt4_executable(${PROGNAME}.app "qjpeg;qgif;qico;qtaccessiblewidgets")
+ endif()
+
+-if(MINGW AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8))
++if(MINGW )
+ set(CPACK_GENERATOR "ZIP")
+ set(CPACK_STRIP_FILES ON)
+ set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSX_VERSION_NUM}")
+diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp
+index f1b7e3e..15185b2 100644
+--- a/src/autotype/AutoType.cpp
++++ b/src/autotype/AutoType.cpp
+@@ -32,7 +32,7 @@
+ #include "core/Tools.h"
+ #include "gui/MessageBox.h"
+
+-AutoType* AutoType::m_instance = Q_NULLPTR;
++AutoType* AutoType::m_instance = nullptr;
+
+ AutoType::AutoType(QObject* parent, bool test)
+ : QObject(parent)
+@@ -40,8 +40,8 @@ AutoType::AutoType(QObject* parent, bool test)
+ , m_currentGlobalKey(static_cast<Qt::Key>(0))
+ , m_currentGlobalModifiers(0)
+ , m_pluginLoader(new QPluginLoader(this))
+- , m_plugin(Q_NULLPTR)
+- , m_executor(Q_NULLPTR)
++ , m_plugin(nullptr)
++ , m_executor(nullptr)
+ , m_windowFromGlobal(0)
+ {
+ // prevent crash when the plugin has unresolved symbols
+@@ -49,7 +49,7 @@ AutoType::AutoType(QObject* parent, bool test)
+
+ QString pluginName = "keepassx-autotype-";
+ if (!test) {
+- pluginName += Tools::platform();
++ pluginName += QApplication::platformName();
+ }
+ else {
+ pluginName += "test";
+@@ -68,7 +68,7 @@ AutoType::~AutoType()
+ {
+ if (m_executor) {
+ delete m_executor;
+- m_executor = Q_NULLPTR;
++ m_executor = nullptr;
+ }
+ }
+
+@@ -79,7 +79,7 @@ void AutoType::loadPlugin(const QString& pluginPath)
+ QObject* pluginInstance = m_pluginLoader->instance();
+ if (pluginInstance) {
+ m_plugin = qobject_cast<AutoTypePlatformInterface*>(pluginInstance);
+- m_executor = Q_NULLPTR;
++ m_executor = nullptr;
+
+ if (m_plugin) {
+ if (m_plugin->isAvailable()) {
+@@ -202,11 +202,11 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
+ QString message = tr("Couldn't find an entry that matches the window title:");
+ message.append("\n\n");
+ message.append(windowTitle);
+- MessageBox::information(Q_NULLPTR, tr("Auto-Type - KeePassX"), message);
++ MessageBox::information(nullptr, tr("Auto-Type - KeePassX"), message);
+ }
+ else if ((entryList.size() == 1) && !config()->get("security/autotypeask").toBool()) {
+ m_inAutoType = false;
+- performAutoType(entryList.first(), Q_NULLPTR, sequenceHash[entryList.first()]);
++ performAutoType(entryList.first(), nullptr, sequenceHash[entryList.first()]);
+ }
+ else {
+ m_windowFromGlobal = m_plugin->activeWindow();
+@@ -228,7 +228,7 @@ void AutoType::performAutoTypeFromGlobal(Entry* entry, const QString& sequence)
+ m_plugin->raiseWindow(m_windowFromGlobal);
+
+ m_inAutoType = false;
+- performAutoType(entry, Q_NULLPTR, sequence, m_windowFromGlobal);
++ performAutoType(entry, nullptr, sequence, m_windowFromGlobal);
+ }
+
+ void AutoType::resetInAutoType()
+@@ -242,12 +242,12 @@ void AutoType::unloadPlugin()
+ {
+ if (m_executor) {
+ delete m_executor;
+- m_executor = Q_NULLPTR;
++ m_executor = nullptr;
+ }
+
+ if (m_plugin) {
+ m_plugin->unload();
+- m_plugin = Q_NULLPTR;
++ m_plugin = nullptr;
+ }
+ }
+
+diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h
+index f3d626c..d1c8817 100644
+--- a/src/autotype/AutoType.h
++++ b/src/autotype/AutoType.h
+@@ -22,8 +22,6 @@
+ #include <QStringList>
+ #include <QWidget>
+
+-#include "core/Global.h"
+-
+ class AutoTypeAction;
+ class AutoTypeExecutor;
+ class AutoTypePlatformInterface;
+@@ -37,7 +35,7 @@ class AutoType : public QObject
+
+ public:
+ QStringList windowTitles();
+- void performAutoType(const Entry* entry, QWidget* hideWindow = Q_NULLPTR,
++ void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr,
+ const QString& customSequence = QString(), WId window = 0);
+ bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
+ void unregisterGlobalShortcut();
+@@ -62,7 +60,7 @@ private Q_SLOTS:
+ void unloadPlugin();
+
+ private:
+- explicit AutoType(QObject* parent = Q_NULLPTR, bool test = false);
++ explicit AutoType(QObject* parent = nullptr, bool test = false);
+ ~AutoType();
+ void loadPlugin(const QString& pluginPath);
+ bool parseActions(const QString& sequence, const Entry* entry, QList<AutoTypeAction*>& actions);
+diff --git a/src/autotype/AutoTypeAction.h b/src/autotype/AutoTypeAction.h
+index 07e050b..490f0d8 100644
+--- a/src/autotype/AutoTypeAction.h
++++ b/src/autotype/AutoTypeAction.h
+@@ -66,7 +66,7 @@ public:
+ class KEEPASSX_EXPORT AutoTypeClearField : public AutoTypeAction
+ {
+ public:
+- explicit AutoTypeClearField();
++ AutoTypeClearField();
+ AutoTypeAction* clone();
+ void accept(AutoTypeExecutor* executor);
+ };
+diff --git a/src/autotype/AutoTypeSelectDialog.h b/src/autotype/AutoTypeSelectDialog.h
+index 4f455c7..c0dbfe4 100644
+--- a/src/autotype/AutoTypeSelectDialog.h
++++ b/src/autotype/AutoTypeSelectDialog.h
+@@ -22,8 +22,6 @@
+ #include <QDialog>
+ #include <QHash>
+
+-#include "core/Global.h"
+-
+ class AutoTypeSelectView;
+ class Entry;
+
+@@ -32,7 +30,7 @@ class AutoTypeSelectDialog : public QDialog
+ Q_OBJECT
+
+ public:
+- explicit AutoTypeSelectDialog(QWidget* parent = Q_NULLPTR);
++ explicit AutoTypeSelectDialog(QWidget* parent = nullptr);
+ void setEntries(const QList<Entry*>& entries, const QHash<Entry*, QString>& sequences);
+
+ Q_SIGNALS:
+diff --git a/src/autotype/AutoTypeSelectView.h b/src/autotype/AutoTypeSelectView.h
+index bcbb262..749f6a9 100644
+--- a/src/autotype/AutoTypeSelectView.h
++++ b/src/autotype/AutoTypeSelectView.h
+@@ -18,7 +18,6 @@
+ #ifndef KEEPASSX_AUTOTYPESELECTVIEW_H
+ #define KEEPASSX_AUTOTYPESELECTVIEW_H
+
+-#include "core/Global.h"
+ #include "gui/entry/EntryView.h"
+
+ class Entry;
+@@ -28,10 +27,10 @@ class AutoTypeSelectView : public EntryView
+ Q_OBJECT
+
+ public:
+- explicit AutoTypeSelectView(QWidget* parent = Q_NULLPTR);
++ explicit AutoTypeSelectView(QWidget* parent = nullptr);
+
+ protected:
+- void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
++ void mouseMoveEvent(QMouseEvent* event) override;
+
+ private Q_SLOTS:
+ void selectFirstEntry();
+diff --git a/src/autotype/CMakeLists.txt b/src/autotype/CMakeLists.txt
+index a0f7877..707edf9 100644
+--- a/src/autotype/CMakeLists.txt
++++ b/src/autotype/CMakeLists.txt
+@@ -1,12 +1,12 @@
+-if(Q_WS_X11)
++if(UNIX AND NOT APPLE)
+ find_package(X11)
+- if(PRINT_SUMMARY)
+- add_feature_info(libXi X11_Xi_FOUND "The X11 Xi Protocol library is required for auto-type")
+- add_feature_info(libXtest X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type")
+- endif()
++ find_package(Qt5X11Extras 5.2)
++ add_feature_info(libXi X11_Xi_FOUND "The X11 Xi Protocol library is required for auto-type")
++ add_feature_info(libXtest X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type")
++ add_feature_info(Qt5X11Extras Qt5X11Extras_FOUND "The Qt5X11Extras library is required for auto-type")
+
+- if(X11_FOUND AND X11_Xi_FOUND AND X11_XTest_FOUND)
+- add_subdirectory(x11)
++ if(X11_FOUND AND X11_Xi_FOUND AND X11_XTest_FOUND AND Qt5X11Extras_FOUND)
++ add_subdirectory(xcb)
+ endif()
+ endif()
+
+diff --git a/src/autotype/ShortcutWidget.h b/src/autotype/ShortcutWidget.h
+index 5ff306c..60898ab 100644
+--- a/src/autotype/ShortcutWidget.h
++++ b/src/autotype/ShortcutWidget.h
+@@ -20,21 +20,19 @@
+
+ #include <QLineEdit>
+
+-#include "core/Global.h"
+-
+ class ShortcutWidget : public QLineEdit
+ {
+ Q_OBJECT
+
+ public:
+- explicit ShortcutWidget(QWidget* parent = Q_NULLPTR);
++ explicit ShortcutWidget(QWidget* parent = nullptr);
+ Qt::Key key() const;
+ Qt::KeyboardModifiers modifiers() const;
+ void setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
+
+ protected:
+- void keyPressEvent(QKeyEvent* event) Q_DECL_OVERRIDE;
+- void keyReleaseEvent(QKeyEvent* event) Q_DECL_OVERRIDE;
++ void keyPressEvent(QKeyEvent* event) override;
++ void keyReleaseEvent(QKeyEvent* event) override;
+
+ private:
+ void keyEvent(QKeyEvent* event);
+diff --git a/src/autotype/WindowSelectComboBox.h b/src/autotype/WindowSelectComboBox.h
+index 661bc84..244119a 100644
+--- a/src/autotype/WindowSelectComboBox.h
++++ b/src/autotype/WindowSelectComboBox.h
+@@ -20,19 +20,17 @@
+
+ #include <QComboBox>
+
+-#include "core/Global.h"
+-
+ class WindowSelectComboBox : public QComboBox
+ {
+ Q_OBJECT
+
+ public:
+- explicit WindowSelectComboBox(QWidget* parent = Q_NULLPTR);
++ explicit WindowSelectComboBox(QWidget* parent = nullptr);
+ void refreshWindowList();
+
+- void showPopup() Q_DECL_OVERRIDE;
+- QSize sizeHint() const Q_DECL_OVERRIDE;
+- QSize minimumSizeHint() const Q_DECL_OVERRIDE;
++ void showPopup() override;
++ QSize sizeHint() const override;
++ QSize minimumSizeHint() const override;
+ };
+
+ #endif // KEEPASSX_WINDOWSELECTCOMBOBOX_H
+diff --git a/src/autotype/test/AutoTypeTest.cpp b/src/autotype/test/AutoTypeTest.cpp
+index a8bcc71..979af8b 100644
+--- a/src/autotype/test/AutoTypeTest.cpp
++++ b/src/autotype/test/AutoTypeTest.cpp
+@@ -129,5 +129,3 @@ void AutoTypeExecturorTest::execKey(AutoTypeKey* action)
+ {
+ m_platform->addActionKey(action);
+ }
+-
+-Q_EXPORT_PLUGIN2(keepassx-autotype-test, AutoTypePlatformTest)
+diff --git a/src/autotype/test/AutoTypeTest.h b/src/autotype/test/AutoTypeTest.h
+index c791c15..8c6e524 100644
+--- a/src/autotype/test/AutoTypeTest.h
++++ b/src/autotype/test/AutoTypeTest.h
+@@ -23,34 +23,34 @@
+ #include "autotype/AutoTypePlatformPlugin.h"
+ #include "autotype/AutoTypeAction.h"
+ #include "autotype/test/AutoTypeTestInterface.h"
+-#include "core/Global.h"
+
+ class AutoTypePlatformTest : public QObject,
+ public AutoTypePlatformInterface,
+ public AutoTypeTestInterface
+ {
+ Q_OBJECT
++ Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformInterface")
+ Q_INTERFACES(AutoTypePlatformInterface AutoTypeTestInterface)
+
+ public:
+- QString keyToString(Qt::Key key) Q_DECL_OVERRIDE;
++ QString keyToString(Qt::Key key) override;
+
+- bool isAvailable() Q_DECL_OVERRIDE;
+- QStringList windowTitles() Q_DECL_OVERRIDE;
+- WId activeWindow() Q_DECL_OVERRIDE;
+- QString activeWindowTitle() Q_DECL_OVERRIDE;
+- bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE;
+- void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE;
+- int platformEventFilter(void* event) Q_DECL_OVERRIDE;
+- int initialTimeout() Q_DECL_OVERRIDE;
+- bool raiseWindow(WId window) Q_DECL_OVERRIDE;
+- AutoTypeExecutor* createExecutor() Q_DECL_OVERRIDE;
++ bool isAvailable() override;
++ QStringList windowTitles() override;
++ WId activeWindow() override;
++ QString activeWindowTitle() override;
++ bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
++ void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
++ int platformEventFilter(void* event) override;
++ int initialTimeout() override;
++ bool raiseWindow(WId window) override;
++ AutoTypeExecutor* createExecutor() override;
+
+- void setActiveWindowTitle(const QString& title) Q_DECL_OVERRIDE;
++ void setActiveWindowTitle(const QString& title) override;
+
+- QString actionChars() Q_DECL_OVERRIDE;
+- int actionCount() Q_DECL_OVERRIDE;
+- void clearActions() Q_DECL_OVERRIDE;
++ QString actionChars() override;
++ int actionCount() override;
++ void clearActions() override;
+
+ void addActionChar(AutoTypeChar* action);
+ void addActionKey(AutoTypeKey* action);
+@@ -69,8 +69,8 @@ class AutoTypeExecturorTest : public AutoTypeExecutor
+ public:
+ explicit AutoTypeExecturorTest(AutoTypePlatformTest* platform);
+
+- void execChar(AutoTypeChar* action) Q_DECL_OVERRIDE;
+- void execKey(AutoTypeKey* action) Q_DECL_OVERRIDE;
++ void execChar(AutoTypeChar* action) override;
++ void execKey(AutoTypeKey* action) override;
+
+ private:
+ AutoTypePlatformTest* const m_platform;
+diff --git a/src/autotype/test/CMakeLists.txt b/src/autotype/test/CMakeLists.txt
+index 749f7d5..9b3dbd4 100644
+--- a/src/autotype/test/CMakeLists.txt
++++ b/src/autotype/test/CMakeLists.txt
+@@ -2,11 +2,5 @@ set(autotype_test_SOURCES
+ AutoTypeTest.cpp
+ )
+
+-set(autotype_test_MOC
+- AutoTypeTest.h
+-)
+-
+-qt4_wrap_cpp(autotype_test_SOURCES ${autotype_test_MOC})
+-
+ add_library(keepassx-autotype-test MODULE ${autotype_test_SOURCES})
+-target_link_libraries(keepassx-autotype-test testautotype ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
++target_link_libraries(keepassx-autotype-test testautotype Qt5::Core Qt5::Widgets)
+diff --git a/src/autotype/x11/AutoTypeX11.cpp b/src/autotype/x11/AutoTypeX11.cpp
+deleted file mode 100644
+index 6a20a88..0000000
+--- a/src/autotype/x11/AutoTypeX11.cpp
++++ /dev/null
+@@ -1,850 +0,0 @@
+-/*
+- * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
+- * Copyright (C) 2000-2008 Tom Sato <VEF00200@nifty.ne.jp>
+- *
+- * 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 "AutoTypeX11.h"
+-#include "KeySymMap.h"
+-
+-#include <time.h>
+-
+-bool AutoTypePlatformX11::m_catchXErrors = false;
+-bool AutoTypePlatformX11::m_xErrorOccured = false;
+-int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = Q_NULLPTR;
+-
+-AutoTypePlatformX11::AutoTypePlatformX11()
+-{
+- m_dpy = QX11Info::display();
+- m_rootWindow = QX11Info::appRootWindow();
+-
+- m_atomWmState = XInternAtom(m_dpy, "WM_STATE", True);
+- m_atomWmName = XInternAtom(m_dpy, "WM_NAME", True);
+- m_atomNetWmName = XInternAtom(m_dpy, "_NET_WM_NAME", True);
+- m_atomString = XInternAtom(m_dpy, "STRING", True);
+- m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True);
+- m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True);
+-
+- m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
+- m_classBlacklist << "kdesktop" << "kicker"; // KDE 3
+- m_classBlacklist << "Plasma"; // KDE 4
+- m_classBlacklist << "plasmashell"; // KDE 5
+- m_classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4
+-
+- m_currentGlobalKey = static_cast<Qt::Key>(0);
+- m_currentGlobalModifiers = 0;
+-
+- m_keysymTable = Q_NULLPTR;
+- m_xkb = Q_NULLPTR;
+- m_remapKeycode = 0;
+- m_currentRemapKeysym = NoSymbol;
+- m_modifierMask = ControlMask | ShiftMask | Mod1Mask | Mod4Mask;
+-
+- m_loaded = true;
+-
+- updateKeymap();
+-}
+-
+-bool AutoTypePlatformX11::isAvailable()
+-{
+- int ignore;
+-
+- if (!XQueryExtension(m_dpy, "XInputExtension", &ignore, &ignore, &ignore)) {
+- return false;
+- }
+-
+- if (!XQueryExtension(m_dpy, "XTEST", &ignore, &ignore, &ignore)) {
+- return false;
+- }
+-
+- if (!m_xkb) {
+- XkbDescPtr kbd = getKeyboard();
+-
+- if (!kbd) {
+- return false;
+- }
+-
+- XkbFreeKeyboard(kbd, XkbAllComponentsMask, True);
+- }
+-
+- return true;
+-}
+-
+-void AutoTypePlatformX11::unload()
+-{
+- // Restore the KeyboardMapping to its original state.
+- if (m_currentRemapKeysym != NoSymbol) {
+- AddKeysym(NoSymbol);
+- }
+-
+- if (m_keysymTable) {
+- XFree(m_keysymTable);
+- }
+-
+- if (m_xkb) {
+- XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
+- }
+-
+- m_loaded = false;
+-}
+-
+-QStringList AutoTypePlatformX11::windowTitles()
+-{
+- return windowTitlesRecursive(m_rootWindow);
+-}
+-
+-WId AutoTypePlatformX11::activeWindow()
+-{
+- Window window;
+- int revert_to_return;
+- XGetInputFocus(m_dpy, &window, &revert_to_return);
+-
+- int tree;
+- do {
+- if (isTopLevelWindow(window)) {
+- break;
+- }
+-
+- Window root;
+- Window parent;
+- Window* children = Q_NULLPTR;
+- unsigned int numChildren;
+- tree = XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren);
+- window = parent;
+- if (children) {
+- XFree(children);
+- }
+- } while (tree && window);
+-
+- return window;
+-}
+-
+-QString AutoTypePlatformX11::activeWindowTitle()
+-{
+- return windowTitle(activeWindow(), true);
+-}
+-
+-bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
+-{
+- int keycode = XKeysymToKeycode(m_dpy, charToKeySym(key));
+- uint nativeModifiers = qtToNativeModifiers(modifiers);
+-
+- startCatchXErrors();
+- XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
+- XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync,
+- GrabModeAsync);
+- XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync,
+- GrabModeAsync);
+- XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True,
+- GrabModeAsync, GrabModeAsync);
+- stopCatchXErrors();
+-
+- if (!m_xErrorOccured) {
+- m_currentGlobalKey = key;
+- m_currentGlobalModifiers = modifiers;
+- m_currentGlobalKeycode = keycode;
+- m_currentGlobalNativeModifiers = nativeModifiers;
+- return true;
+- }
+- else {
+- unregisterGlobalShortcut(key, modifiers);
+- return false;
+- }
+-}
+-
+-uint AutoTypePlatformX11::qtToNativeModifiers(Qt::KeyboardModifiers modifiers)
+-{
+- uint nativeModifiers = 0;
+-
+- if (modifiers & Qt::ShiftModifier) {
+- nativeModifiers |= ShiftMask;
+- }
+- if (modifiers & Qt::ControlModifier) {
+- nativeModifiers |= ControlMask;
+- }
+- if (modifiers & Qt::AltModifier) {
+- nativeModifiers |= Mod1Mask;
+- }
+- if (modifiers & Qt::MetaModifier) {
+- nativeModifiers |= Mod4Mask;
+- }
+-
+- return nativeModifiers;
+-}
+-
+-void AutoTypePlatformX11::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
+-{
+- KeyCode keycode = XKeysymToKeycode(m_dpy, charToKeySym(key));
+- uint nativeModifiers = qtToNativeModifiers(modifiers);
+-
+- XUngrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow);
+- XUngrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow);
+- XUngrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow);
+- XUngrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow);
+-
+- m_currentGlobalKey = static_cast<Qt::Key>(0);
+- m_currentGlobalModifiers = 0;
+- m_currentGlobalKeycode = 0;
+- m_currentGlobalNativeModifiers = 0;
+-}
+-
+-int AutoTypePlatformX11::platformEventFilter(void* event)
+-{
+- XEvent* xevent = static_cast<XEvent*>(event);
+-
+- if ((xevent->type == KeyPress || xevent->type == KeyRelease)
+- && m_currentGlobalKey
+- && xevent->xkey.keycode == m_currentGlobalKeycode
+- && (xevent->xkey.state & m_modifierMask) == m_currentGlobalNativeModifiers
+- && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized())
+- && m_loaded) {
+- if (xevent->type == KeyPress) {
+- Q_EMIT globalShortcutTriggered();
+- }
+- return 1;
+- }
+- if (xevent->type == MappingNotify && m_loaded) {
+- XRefreshKeyboardMapping(reinterpret_cast<XMappingEvent*>(xevent));
+- updateKeymap();
+- }
+-
+- return -1;
+-}
+-
+-AutoTypeExecutor* AutoTypePlatformX11::createExecutor()
+-{
+- return new AutoTypeExecturorX11(this);
+-}
+-
+-QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
+-{
+- QString title;
+-
+- Atom type;
+- int format;
+- unsigned long nitems;
+- unsigned long after;
+- unsigned char* data = Q_NULLPTR;
+-
+- // the window manager spec says we should read _NET_WM_NAME first, then fall back to WM_NAME
+-
+- int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String,
+- &type, &format, &nitems, &after, &data);
+-
+- if ((retVal == 0) && data) {
+- title = QString::fromUtf8(reinterpret_cast<char*>(data));
+- }
+- else {
+- XTextProperty textProp;
+- retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName);
+- if ((retVal != 0) && textProp.value) {
+- char** textList = Q_NULLPTR;
+- int count;
+-
+- if (textProp.encoding == m_atomUtf8String) {
+- title = QString::fromUtf8(reinterpret_cast<char*>(textProp.value));
+- }
+- else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0)
+- && textList && (count > 0)) {
+- title = QString::fromLocal8Bit(textList[0]);
+- }
+- else if (textProp.encoding == m_atomString) {
+- title = QString::fromLocal8Bit(reinterpret_cast<char*>(textProp.value));
+- }
+-
+- if (textList) {
+- XFreeStringList(textList);
+- }
+- }
+-
+- if (textProp.value) {
+- XFree(textProp.value);
+- }
+- }
+-
+- if (data) {
+- XFree(data);
+- }
+-
+- if (useBlacklist && !title.isEmpty()) {
+- if (window == m_rootWindow) {
+- return QString();
+- }
+-
+- QString className = windowClassName(window);
+- if (m_classBlacklist.contains(className)) {
+- return QString();
+- }
+-
+- QList<Window> keepassxWindows = widgetsToX11Windows(QApplication::topLevelWidgets());
+- if (keepassxWindows.contains(window)) {
+- return QString();
+- }
+- }
+-
+- return title;
+-}
+-
+-QString AutoTypePlatformX11::windowClassName(Window window)
+-{
+- QString className;
+-
+- XClassHint wmClass;
+- wmClass.res_name = Q_NULLPTR;
+- wmClass.res_class = Q_NULLPTR;
+-
+- if (XGetClassHint(m_dpy, window, &wmClass) && wmClass.res_name) {
+- className = QString::fromLocal8Bit(wmClass.res_name);
+- }
+- if (wmClass.res_name) {
+- XFree(wmClass.res_name);
+- }
+- if (wmClass.res_class) {
+- XFree(wmClass.res_class);
+- }
+-
+- return className;
+-}
+-
+-QList<Window> AutoTypePlatformX11::widgetsToX11Windows(const QWidgetList& widgetList)
+-{
+- QList<Window> windows;
+-
+- Q_FOREACH (const QWidget* widget, widgetList) {
+- windows.append(widget->effectiveWinId());
+- }
+-
+- return windows;
+-}
+-
+-QStringList AutoTypePlatformX11::windowTitlesRecursive(Window window)
+-{
+- QStringList titles;
+-
+- if (isTopLevelWindow(window)) {
+- QString title = windowTitle(window, true);
+- if (!title.isEmpty()) {
+- titles.append(title);
+- }
+- }
+-
+- Window root;
+- Window parent;
+- Window* children = Q_NULLPTR;
+- unsigned int numChildren;
+- if (XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren) && children) {
+- for (uint i = 0; i < numChildren; i++) {
+- titles.append(windowTitlesRecursive(children[i]));
+- }
+- }
+- if (children) {
+- XFree(children);
+- }
+-
+- return titles;
+-}
+-
+-bool AutoTypePlatformX11::isTopLevelWindow(Window window)
+-{
+- Atom type = None;
+- int format;
+- unsigned long nitems;
+- unsigned long after;
+- unsigned char* data = Q_NULLPTR;
+- int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 0, False, AnyPropertyType, &type, &format,
+- &nitems, &after, &data);
+- if (data) {
+- XFree(data);
+- }
+-
+- return (retVal == 0) && type;
+-}
+-
+-KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
+-{
+- ushort unicode = ch.unicode();
+-
+- /* first check for Latin-1 characters (1:1 mapping) */
+- if ((unicode >= 0x0020 && unicode <= 0x007e)
+- || (unicode >= 0x00a0 && unicode <= 0x00ff)) {
+- return unicode;
+- }
+-
+- /* mapping table generated from keysymdef.h */
+- const uint* match = qBinaryFind(m_unicodeToKeysymKeys,
+- m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
+- unicode);
+- int index = match - m_unicodeToKeysymKeys;
+- if (index != m_unicodeToKeysymLen) {
+- return m_unicodeToKeysymValues[index];
+- }
+-
+- if (unicode >= 0x0100) {
+- return unicode | 0x01000000;
+- }
+-
+- return NoSymbol;
+-}
+-
+-KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
+-{
+- switch (key) {
+- case Qt::Key_Tab:
+- return XK_Tab;
+- case Qt::Key_Enter:
+- return XK_Return;
+- case Qt::Key_Up:
+- return XK_Up;
+- case Qt::Key_Down:
+- return XK_Down;
+- case Qt::Key_Left:
+- return XK_Left;
+- case Qt::Key_Right:
+- return XK_Right;
+- case Qt::Key_Insert:
+- return XK_Insert;
+- case Qt::Key_Delete:
+- return XK_Delete;
+- case Qt::Key_Home:
+- return XK_Home;
+- case Qt::Key_End:
+- return XK_End;
+- case Qt::Key_PageUp:
+- return XK_Page_Up;
+- case Qt::Key_PageDown:
+- return XK_Page_Down;
+- case Qt::Key_Backspace:
+- return XK_BackSpace;
+- case Qt::Key_Pause:
+- return XK_Break;
+- case Qt::Key_CapsLock:
+- return XK_Caps_Lock;
+- case Qt::Key_Escape:
+- return XK_Escape;
+- case Qt::Key_Help:
+- return XK_Help;
+- case Qt::Key_NumLock:
+- return XK_Num_Lock;
+- case Qt::Key_Print:
+- return XK_Print;
+- case Qt::Key_ScrollLock:
+- return XK_Scroll_Lock;
+- default:
+- if (key >= Qt::Key_F1 && key <= Qt::Key_F16) {
+- return XK_F1 + (key - Qt::Key_F1);
+- }
+- else {
+- return NoSymbol;
+- }
+- }
+-}
+-
+-/*
+- * Update the keyboard and modifier mapping.
+- * We need the KeyboardMapping for AddKeysym.
+- * Modifier mapping is required for clearing the modifiers.
+- */
+-void AutoTypePlatformX11::updateKeymap()
+-{
+- int keycode, inx;
+- int mod_index, mod_key;
+- XModifierKeymap *modifiers;
+-
+- if (m_xkb) {
+- XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
+- }
+- m_xkb = getKeyboard();
+-
+- XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
+- if (m_keysymTable != NULL) XFree(m_keysymTable);
+- m_keysymTable = XGetKeyboardMapping(m_dpy,
+- m_minKeycode, m_maxKeycode - m_minKeycode + 1,
+- &m_keysymPerKeycode);
+-
+- /* determine the keycode to use for remapped keys */
+- inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
+- if (m_remapKeycode == 0 || !isRemapKeycodeValid()) {
+- for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
+- inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
+- if (m_keysymTable[inx] == NoSymbol) {
+- m_remapKeycode = keycode;
+- m_currentRemapKeysym = NoSymbol;
+- break;
+- }
+- }
+- }
+-
+- /* determine the keycode to use for modifiers */
+- modifiers = XGetModifierMapping(m_dpy);
+- for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
+- m_modifier_keycode[mod_index] = 0;
+- for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) {
+- keycode = modifiers->modifiermap[mod_index * modifiers->max_keypermod + mod_key];
+- if (keycode) {
+- m_modifier_keycode[mod_index] = keycode;
+- break;
+- }
+- }
+- }
+- XFreeModifiermap(modifiers);
+-
+- /* Xlib needs some time until the mapping is distributed to
+- all clients */
+- // TODO: we should probably only sleep while in the middle of typing something
+- timespec ts;
+- ts.tv_sec = 0;
+- ts.tv_nsec = 30 * 1000 * 1000;
+- nanosleep(&ts, Q_NULLPTR);
+-}
+-
+-bool AutoTypePlatformX11::isRemapKeycodeValid()
+-{
+- int baseKeycode = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
+- for (int i = 0; i < m_keysymPerKeycode; i++) {
+- if (m_keysymTable[baseKeycode + i] == m_currentRemapKeysym) {
+- return true;
+- }
+- }
+-
+- return false;
+-}
+-
+-void AutoTypePlatformX11::startCatchXErrors()
+-{
+- Q_ASSERT(!m_catchXErrors);
+-
+- m_catchXErrors = true;
+- m_xErrorOccured = false;
+- m_oldXErrorHandler = XSetErrorHandler(x11ErrorHandler);
+-}
+-
+-void AutoTypePlatformX11::stopCatchXErrors()
+-{
+- Q_ASSERT(m_catchXErrors);
+-
+- XSync(m_dpy, False);
+- XSetErrorHandler(m_oldXErrorHandler);
+- m_catchXErrors = false;
+-}
+-
+-int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error)
+-{
+- Q_UNUSED(display)
+- Q_UNUSED(error)
+-
+- if (m_catchXErrors) {
+- m_xErrorOccured = true;
+- }
+-
+- return 1;
+-}
+-
+-XkbDescPtr AutoTypePlatformX11::getKeyboard()
+-{
+- int num_devices;
+- XID keyboard_id = XkbUseCoreKbd;
+- XDeviceInfo* devices = XListInputDevices(m_dpy, &num_devices);
+- if (!devices) {
+- return Q_NULLPTR;
+- }
+-
+- for (int i = 0; i < num_devices; i++) {
+- if (QString(devices[i].name) == "Virtual core XTEST keyboard") {
+- keyboard_id = devices[i].id;
+- break;
+- }
+- }
+-
+- XFreeDeviceList(devices);
+-
+- return XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id);
+-}
+-
+-// --------------------------------------------------------------------------
+-// The following code is taken from xvkbd 3.0 and has been slightly modified.
+-// --------------------------------------------------------------------------
+-
+-/*
+- * Insert a specified keysym on the dedicated position in the keymap
+- * table.
+- */
+-int AutoTypePlatformX11::AddKeysym(KeySym keysym)
+-{
+- if (m_remapKeycode == 0) {
+- return 0;
+- }
+-
+- int inx = (m_remapKeycode- m_minKeycode) * m_keysymPerKeycode;
+- m_keysymTable[inx] = keysym;
+- m_currentRemapKeysym = keysym;
+-
+- XChangeKeyboardMapping(m_dpy, m_remapKeycode, m_keysymPerKeycode, &m_keysymTable[inx], 1);
+- XFlush(m_dpy);
+- updateKeymap();
+-
+- return m_remapKeycode;
+-}
+-
+-/*
+- * Send event to the focused window.
+- * If input focus is specified explicitly, select the window
+- * before send event to the window.
+- */
+-void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type)
+-{
+- XSync(event->display, False);
+- int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
+-
+- event->type = event_type;
+- Bool press;
+- if (event->type == KeyPress) {
+- press = True;
+- }
+- else {
+- press = False;
+- }
+- XTestFakeKeyEvent(event->display, event->keycode, press, 0);
+- XFlush(event->display);
+-
+- XSetErrorHandler(oldHandler);
+-}
+-
+-/*
+- * Send a modifier press/release event for all modifiers
+- * which are set in the mask variable.
+- */
+-void AutoTypePlatformX11::SendModifier(XKeyEvent *event, unsigned int mask, int event_type)
+-{
+- int mod_index;
+- for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
+- if (mask & (1 << mod_index)) {
+- event->keycode = m_modifier_keycode[mod_index];
+- SendEvent(event, event_type);
+- if (event_type == KeyPress)
+- event->state |= (1 << mod_index);
+- else
+- event->state &= (1 << mod_index);
+- }
+- }
+-}
+-
+-/*
+- * Determines the keycode and modifier mask for the given
+- * keysym.
+- */
+-int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask)
+-{
+- int keycode = XKeysymToKeycode(m_dpy, keysym);
+-
+- if (keycode && keysymModifiers(keysym, keycode, mask)) {
+- return keycode;
+- }
+-
+- /* no modifier matches => resort to remapping */
+- keycode = AddKeysym(keysym);
+- if (keycode && keysymModifiers(keysym, keycode, mask)) {
+- return keycode;
+- }
+-
+- *mask = 0;
+- return 0;
+-}
+-
+-bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int *mask)
+-{
+- int shift, mod;
+- unsigned int mods_rtrn;
+-
+- /* determine whether there is a combination of the modifiers
+- (Mod1-Mod5) with or without shift which returns keysym */
+- for (shift = 0; shift < 2; shift ++) {
+- for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod ++) {
+- KeySym keysym_rtrn;
+- *mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod);
+- XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn);
+- if (keysym_rtrn == keysym) {
+- return true;
+- }
+- }
+- }
+-
+- return false;
+-}
+-
+-
+-
+-/*
+- * Send sequence of KeyPressed/KeyReleased events to the focused
+- * window to simulate keyboard. If modifiers (shift, control, etc)
+- * are set ON, many events will be sent.
+- */
+-void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym)
+-{
+- Window cur_focus;
+- int revert_to;
+- XKeyEvent event;
+- int keycode;
+-
+- if (keysym == NoSymbol) {
+- qWarning("No such key: keysym=0x%lX", keysym);
+- return;
+- }
+-
+- XGetInputFocus(m_dpy, &cur_focus, &revert_to);
+-
+- event.display = m_dpy;
+- event.window = cur_focus;
+- event.root = m_rootWindow;
+- event.subwindow = None;
+- event.time = CurrentTime;
+- event.x = 1;
+- event.y = 1;
+- event.x_root = 1;
+- event.y_root = 1;
+- event.same_screen = TRUE;
+-
+- Window root, child;
+- int root_x, root_y, x, y;
+- unsigned int wanted_mask = 0;
+- unsigned int original_mask;
+-
+- XQueryPointer(m_dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &original_mask);
+-
+- /* determine keycode and mask for the given keysym */
+- keycode = GetKeycode(keysym, &wanted_mask);
+- if (keycode < 8 || keycode > 255) {
+- qWarning("Unable to get valid keycode for key: keysym=0x%lX", keysym);
+- return;
+- }
+-
+- event.state = original_mask;
+-
+- // modifiers that need to be pressed but aren't
+- unsigned int press_mask = wanted_mask & ~original_mask;
+-
+- // modifiers that are pressed but maybe shouldn't
+- unsigned int release_check_mask = original_mask & ~wanted_mask;
+-
+- // modifiers we need to release before sending the keycode
+- unsigned int release_mask = 0;
+-
+- // check every release_check_mask individually if it affects the keysym we would generate
+- // if it doesn't we probably don't need to release it
+- for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
+- if (release_check_mask & (1 << mod_index)) {
+- unsigned int mods_rtrn;
+- KeySym keysym_rtrn;
+- XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (1 << mod_index), &mods_rtrn, &keysym_rtrn);
+-
+- if (keysym_rtrn != keysym) {
+- release_mask |= (1 << mod_index);
+- }
+- }
+- }
+-
+- // finally check if the combination of pressed modifiers that we chose to ignore affects the keysym
+- unsigned int mods_rtrn;
+- KeySym keysym_rtrn;
+- XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn);
+- if (keysym_rtrn != keysym) {
+- // oh well, release all the modifiers we don't want
+- release_mask = release_check_mask;
+- }
+-
+- /* release all modifiers */
+- SendModifier(&event, release_mask, KeyRelease);
+-
+- SendModifier(&event, press_mask, KeyPress);
+-
+- /* press and release key */
+- event.keycode = keycode;
+- SendEvent(&event, KeyPress);
+- SendEvent(&event, KeyRelease);
+-
+- /* release the modifiers */
+- SendModifier(&event, press_mask, KeyRelease);
+-
+- /* restore the old keyboard mask */
+- SendModifier(&event, release_mask, KeyPress);
+-}
+-
+-int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
+-{
+- char msg[200];
+-
+- if (event->error_code == BadWindow) {
+- return 0;
+- }
+- XGetErrorText(my_dpy, event->error_code, msg, sizeof(msg) - 1);
+- qWarning("X error trapped: %s, request-code=%d\n", msg, event->request_code);
+- return 0;
+-}
+-
+-
+-AutoTypeExecturorX11::AutoTypeExecturorX11(AutoTypePlatformX11* platform)
+- : m_platform(platform)
+-{
+-}
+-
+-void AutoTypeExecturorX11::execChar(AutoTypeChar* action)
+-{
+- m_platform->SendKeyPressedEvent(m_platform->charToKeySym(action->character));
+-}
+-
+-void AutoTypeExecturorX11::execKey(AutoTypeKey* action)
+-{
+- m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(action->key));
+-}
+-
+-int AutoTypePlatformX11::initialTimeout()
+-{
+- return 500;
+-}
+-
+-bool AutoTypePlatformX11::raiseWindow(WId window)
+-{
+- if (m_atomNetActiveWindow == None) {
+- return false;
+- }
+-
+- XRaiseWindow(m_dpy, window);
+-
+- XEvent event;
+- event.xclient.type = ClientMessage;
+- event.xclient.serial = 0;
+- event.xclient.send_event = True;
+- event.xclient.window = window;
+- event.xclient.message_type = m_atomNetActiveWindow;
+- event.xclient.format = 32;
+- event.xclient.data.l[0] = 1; // FromApplication
+- event.xclient.data.l[1] = QX11Info::appUserTime();
+- QWidget* activeWindow = QApplication::activeWindow();
+- if (activeWindow) {
+- event.xclient.data.l[2] = activeWindow->internalWinId();
+- }
+- else {
+- event.xclient.data.l[2] = 0;
+- }
+- event.xclient.data.l[3] = 0;
+- event.xclient.data.l[4] = 0;
+- XSendEvent(m_dpy, m_rootWindow, False,
+- SubstructureRedirectMask | SubstructureNotifyMask,
+- &event);
+- XFlush(m_dpy);
+-
+- return true;
+-}
+-
+-Q_EXPORT_PLUGIN2(keepassx-autotype-x11, AutoTypePlatformX11)
+diff --git a/src/autotype/x11/AutoTypeX11.h b/src/autotype/x11/AutoTypeX11.h
+deleted file mode 100644
+index 99abb23..0000000
+--- a/src/autotype/x11/AutoTypeX11.h
++++ /dev/null
+@@ -1,134 +0,0 @@
+-/*
+- * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
+- * Copyright (C) 2000-2008 Tom Sato <VEF00200@nifty.ne.jp>
+- *
+- * 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_AUTOTYPEX11_H
+-#define KEEPASSX_AUTOTYPEX11_H
+-
+-#include <QApplication>
+-#include <QSet>
+-#include <QtPlugin>
+-#include <QWidget>
+-#include <QX11Info>
+-
+-#include <X11/Xutil.h>
+-#include <X11/extensions/XTest.h>
+-#include <X11/XKBlib.h>
+-
+-#include "autotype/AutoTypePlatformPlugin.h"
+-#include "autotype/AutoTypeAction.h"
+-#include "core/Global.h"
+-
+-#define N_MOD_INDICES (Mod5MapIndex + 1)
+-
+-class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
+-{
+- Q_OBJECT
+- Q_INTERFACES(AutoTypePlatformInterface)
+-
+-public:
+- AutoTypePlatformX11();
+- bool isAvailable() Q_DECL_OVERRIDE;
+- void unload() Q_DECL_OVERRIDE;
+- QStringList windowTitles() Q_DECL_OVERRIDE;
+- WId activeWindow() Q_DECL_OVERRIDE;
+- QString activeWindowTitle() Q_DECL_OVERRIDE;
+- bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE;
+- void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE;
+- int platformEventFilter(void* event) Q_DECL_OVERRIDE;
+- int initialTimeout() Q_DECL_OVERRIDE;
+- bool raiseWindow(WId window) Q_DECL_OVERRIDE;
+- AutoTypeExecutor* createExecutor() Q_DECL_OVERRIDE;
+-
+- KeySym charToKeySym(const QChar& ch);
+- KeySym keyToKeySym(Qt::Key key);
+-
+- void SendKeyPressedEvent(KeySym keysym);
+-
+-Q_SIGNALS:
+- void globalShortcutTriggered();
+-
+-private:
+- QString windowTitle(Window window, bool useBlacklist);
+- QStringList windowTitlesRecursive(Window window);
+- QString windowClassName(Window window);
+- QList<Window> widgetsToX11Windows(const QWidgetList& widgetList);
+- bool isTopLevelWindow(Window window);
+- uint qtToNativeModifiers(Qt::KeyboardModifiers modifiers);
+- void startCatchXErrors();
+- void stopCatchXErrors();
+- static int x11ErrorHandler(Display* display, XErrorEvent* error);
+-
+- XkbDescPtr getKeyboard();
+- void updateKeymap();
+- bool isRemapKeycodeValid();
+- int AddKeysym(KeySym keysym);
+- void AddModifier(KeySym keysym);
+- void SendEvent(XKeyEvent* event, int event_type);
+- void SendModifier(XKeyEvent *event, unsigned int mask, int event_type);
+- int GetKeycode(KeySym keysym, unsigned int *mask);
+- bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask);
+-
+- static int MyErrorHandler(Display* my_dpy, XErrorEvent* event);
+-
+- Display* m_dpy;
+- Window m_rootWindow;
+- Atom m_atomWmState;
+- Atom m_atomWmName;
+- Atom m_atomNetWmName;
+- Atom m_atomString;
+- Atom m_atomUtf8String;
+- Atom m_atomNetActiveWindow;
+- QSet<QString> m_classBlacklist;
+- Qt::Key m_currentGlobalKey;
+- Qt::KeyboardModifiers m_currentGlobalModifiers;
+- uint m_currentGlobalKeycode;
+- uint m_currentGlobalNativeModifiers;
+- int m_modifierMask;
+- static bool m_catchXErrors;
+- static bool m_xErrorOccured;
+- static int (*m_oldXErrorHandler)(Display*, XErrorEvent*);
+-
+- static const int m_unicodeToKeysymLen;
+- static const uint m_unicodeToKeysymKeys[];
+- static const uint m_unicodeToKeysymValues[];
+-
+- XkbDescPtr m_xkb;
+- KeySym* m_keysymTable;
+- int m_minKeycode;
+- int m_maxKeycode;
+- int m_keysymPerKeycode;
+- /* dedicated keycode for remapped keys */
+- unsigned int m_remapKeycode;
+- KeySym m_currentRemapKeysym;
+- KeyCode m_modifier_keycode[N_MOD_INDICES];
+- bool m_loaded;
+-};
+-
+-class AutoTypeExecturorX11 : public AutoTypeExecutor
+-{
+-public:
+- explicit AutoTypeExecturorX11(AutoTypePlatformX11* platform);
+-
+- void execChar(AutoTypeChar* action) Q_DECL_OVERRIDE;
+- void execKey(AutoTypeKey* action) Q_DECL_OVERRIDE;
+-
+-private:
+- AutoTypePlatformX11* const m_platform;
+-};
+-
+-#endif // KEEPASSX_AUTOTYPEX11_H
+diff --git a/src/autotype/x11/CMakeLists.txt b/src/autotype/x11/CMakeLists.txt
+deleted file mode 100644
+index cc401f7..0000000
+--- a/src/autotype/x11/CMakeLists.txt
++++ /dev/null
+@@ -1,17 +0,0 @@
+-include_directories(SYSTEM ${X11_X11_INCLUDE_PATH})
+-
+-set(autotype_X11_SOURCES
+- AutoTypeX11.cpp
+-)
+-
+-set(autotype_X11_MOC
+- AutoTypeX11.h
+-)
+-
+-qt4_wrap_cpp(autotype_X11_SOURCES ${autotype_X11_MOC})
+-
+-add_library(keepassx-autotype-x11 MODULE ${autotype_X11_SOURCES})
+-target_link_libraries(keepassx-autotype-x11 ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_XTest_LIB})
+-install(TARGETS keepassx-autotype-x11
+- BUNDLE DESTINATION . COMPONENT Runtime
+- LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime)
+diff --git a/src/autotype/x11/KeySymMap.h b/src/autotype/x11/KeySymMap.h
+deleted file mode 100644
+index 55022fe..0000000
+--- a/src/autotype/x11/KeySymMap.h
++++ /dev/null
+@@ -1,169 +0,0 @@
+-/*
+- * Automatically generated by keysymmap.py from parsing keysymdef.h.
+- */
+-
+-const int AutoTypePlatformX11::m_unicodeToKeysymLen = 632;
+-
+-const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {
+- 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
+- 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f,
+- 0x0110, 0x0111, 0x0112, 0x0113, 0x0116, 0x0117, 0x0118, 0x0119,
+- 0x011a, 0x011b, 0x011c, 0x011d, 0x011e, 0x011f, 0x0120, 0x0121,
+- 0x0122, 0x0123, 0x0124, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
+- 0x012a, 0x012b, 0x012e, 0x012f, 0x0130, 0x0131, 0x0134, 0x0135,
+- 0x0136, 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d,
+- 0x013e, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
+- 0x0148, 0x014a, 0x014b, 0x014c, 0x014d, 0x0150, 0x0151, 0x0152,
+- 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015a,
+- 0x015b, 0x015c, 0x015d, 0x015e, 0x015f, 0x0160, 0x0161, 0x0162,
+- 0x0163, 0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, 0x016a,
+- 0x016b, 0x016c, 0x016d, 0x016e, 0x016f, 0x0170, 0x0171, 0x0172,
+- 0x0173, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d, 0x017e,
+- 0x0192, 0x02c7, 0x02d8, 0x02d9, 0x02db, 0x02dd, 0x0385, 0x0386,
+- 0x0388, 0x0389, 0x038a, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391,
+- 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399,
+- 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1,
+- 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa,
+- 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b2,
+- 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba,
+- 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c2,
+- 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca,
+- 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0401, 0x0402, 0x0403, 0x0404,
+- 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c,
+- 0x040e, 0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
+- 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d,
+- 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
+- 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d,
+- 0x042e, 0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435,
+- 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d,
+- 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
+- 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d,
+- 0x044e, 0x044f, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456,
+- 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045e, 0x045f,
+- 0x0490, 0x0491, 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5,
+- 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd,
+- 0x05de, 0x05df, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
+- 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x060c, 0x061b, 0x061f,
+- 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
+- 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, 0x0630,
+- 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638,
+- 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645,
+- 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d,
+- 0x064e, 0x064f, 0x0650, 0x0651, 0x0652, 0x0e01, 0x0e02, 0x0e03,
+- 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b,
+- 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, 0x0e10, 0x0e11, 0x0e12, 0x0e13,
+- 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b,
+- 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, 0x0e20, 0x0e21, 0x0e22, 0x0e23,
+- 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b,
+- 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, 0x0e30, 0x0e31, 0x0e32, 0x0e33,
+- 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0e3f,
+- 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
+- 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e50, 0x0e51,
+- 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59,
+- 0x2002, 0x2003, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, 0x200a,
+- 0x2012, 0x2013, 0x2014, 0x2015, 0x2017, 0x2018, 0x2019, 0x201a,
+- 0x201c, 0x201d, 0x201e, 0x2020, 0x2021, 0x2025, 0x2026, 0x2030,
+- 0x2032, 0x2033, 0x2038, 0x203e, 0x20ac, 0x2105, 0x2116, 0x2117,
+- 0x211e, 0x2122, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158,
+- 0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x2190, 0x2191,
+- 0x2192, 0x2193, 0x21d2, 0x21d4, 0x2202, 0x2207, 0x2218, 0x221a,
+- 0x221d, 0x221e, 0x2227, 0x2228, 0x2229, 0x222a, 0x222b, 0x2234,
+- 0x223c, 0x2243, 0x2260, 0x2261, 0x2264, 0x2265, 0x2282, 0x2283,
+- 0x22a2, 0x22a3, 0x22a4, 0x22a5, 0x2308, 0x230a, 0x2315, 0x2320,
+- 0x2321, 0x2395, 0x239b, 0x239d, 0x239e, 0x23a0, 0x23a1, 0x23a3,
+- 0x23a4, 0x23a6, 0x23a8, 0x23ac, 0x23b7, 0x23ba, 0x23bb, 0x23bc,
+- 0x23bd, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x2424, 0x2500,
+- 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, 0x252c,
+- 0x2534, 0x253c, 0x2592, 0x25c6, 0x25cb, 0x260e, 0x2640, 0x2642,
+- 0x2663, 0x2665, 0x2666, 0x266d, 0x266f, 0x2713, 0x2717, 0x271d,
+- 0x2720, 0x3001, 0x3002, 0x300c, 0x300d, 0x309b, 0x309c, 0x30a1,
+- 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9,
+- 0x30aa, 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7,
+- 0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c3, 0x30c4, 0x30c6,
+- 0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d2,
+- 0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2,
+- 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea,
+- 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f2, 0x30f3, 0x30fb, 0x30fc
+-};
+-
+-const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {
+- 0x03c0, 0x03e0, 0x01c3, 0x01e3, 0x01a1, 0x01b1, 0x01c6, 0x01e6,
+- 0x02c6, 0x02e6, 0x02c5, 0x02e5, 0x01c8, 0x01e8, 0x01cf, 0x01ef,
+- 0x01d0, 0x01f0, 0x03aa, 0x03ba, 0x03cc, 0x03ec, 0x01ca, 0x01ea,
+- 0x01cc, 0x01ec, 0x02d8, 0x02f8, 0x02ab, 0x02bb, 0x02d5, 0x02f5,
+- 0x03ab, 0x03bb, 0x02a6, 0x02b6, 0x02a1, 0x02b1, 0x03a5, 0x03b5,
+- 0x03cf, 0x03ef, 0x03c7, 0x03e7, 0x02a9, 0x02b9, 0x02ac, 0x02bc,
+- 0x03d3, 0x03f3, 0x03a2, 0x01c5, 0x01e5, 0x03a6, 0x03b6, 0x01a5,
+- 0x01b5, 0x01a3, 0x01b3, 0x01d1, 0x01f1, 0x03d1, 0x03f1, 0x01d2,
+- 0x01f2, 0x03bd, 0x03bf, 0x03d2, 0x03f2, 0x01d5, 0x01f5, 0x13bc,
+- 0x13bd, 0x01c0, 0x01e0, 0x03a3, 0x03b3, 0x01d8, 0x01f8, 0x01a6,
+- 0x01b6, 0x02de, 0x02fe, 0x01aa, 0x01ba, 0x01a9, 0x01b9, 0x01de,
+- 0x01fe, 0x01ab, 0x01bb, 0x03ac, 0x03bc, 0x03dd, 0x03fd, 0x03de,
+- 0x03fe, 0x02dd, 0x02fd, 0x01d9, 0x01f9, 0x01db, 0x01fb, 0x03d9,
+- 0x03f9, 0x13be, 0x01ac, 0x01bc, 0x01af, 0x01bf, 0x01ae, 0x01be,
+- 0x08f6, 0x01b7, 0x01a2, 0x01ff, 0x01b2, 0x01bd, 0x07ae, 0x07a1,
+- 0x07a2, 0x07a3, 0x07a4, 0x07a7, 0x07a8, 0x07ab, 0x07b6, 0x07c1,
+- 0x07c2, 0x07c3, 0x07c4, 0x07c5, 0x07c6, 0x07c7, 0x07c8, 0x07c9,
+- 0x07ca, 0x07cb, 0x07cc, 0x07cd, 0x07ce, 0x07cf, 0x07d0, 0x07d1,
+- 0x07d2, 0x07d4, 0x07d5, 0x07d6, 0x07d7, 0x07d8, 0x07d9, 0x07a5,
+- 0x07a9, 0x07b1, 0x07b2, 0x07b3, 0x07b4, 0x07ba, 0x07e1, 0x07e2,
+- 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9, 0x07ea,
+- 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
+- 0x07f2, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8, 0x07f9, 0x07b5,
+- 0x07b9, 0x07b7, 0x07b8, 0x07bb, 0x06b3, 0x06b1, 0x06b2, 0x06b4,
+- 0x06b5, 0x06b6, 0x06b7, 0x06b8, 0x06b9, 0x06ba, 0x06bb, 0x06bc,
+- 0x06be, 0x06bf, 0x06e1, 0x06e2, 0x06f7, 0x06e7, 0x06e4, 0x06e5,
+- 0x06f6, 0x06fa, 0x06e9, 0x06ea, 0x06eb, 0x06ec, 0x06ed, 0x06ee,
+- 0x06ef, 0x06f0, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06e6, 0x06e8,
+- 0x06e3, 0x06fe, 0x06fb, 0x06fd, 0x06ff, 0x06f9, 0x06f8, 0x06fc,
+- 0x06e0, 0x06f1, 0x06c1, 0x06c2, 0x06d7, 0x06c7, 0x06c4, 0x06c5,
+- 0x06d6, 0x06da, 0x06c9, 0x06ca, 0x06cb, 0x06cc, 0x06cd, 0x06ce,
+- 0x06cf, 0x06d0, 0x06d2, 0x06d3, 0x06d4, 0x06d5, 0x06c6, 0x06c8,
+- 0x06c3, 0x06de, 0x06db, 0x06dd, 0x06df, 0x06d9, 0x06d8, 0x06dc,
+- 0x06c0, 0x06d1, 0x06a3, 0x06a1, 0x06a2, 0x06a4, 0x06a5, 0x06a6,
+- 0x06a7, 0x06a8, 0x06a9, 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af,
+- 0x06bd, 0x06ad, 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5,
+- 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced,
+- 0x0cee, 0x0cef, 0x0cf0, 0x0cf1, 0x0cf2, 0x0cf3, 0x0cf4, 0x0cf5,
+- 0x0cf6, 0x0cf7, 0x0cf8, 0x0cf9, 0x0cfa, 0x05ac, 0x05bb, 0x05bf,
+- 0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7, 0x05c8,
+- 0x05c9, 0x05ca, 0x05cb, 0x05cc, 0x05cd, 0x05ce, 0x05cf, 0x05d0,
+- 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8,
+- 0x05d9, 0x05da, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
+- 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x05eb, 0x05ec, 0x05ed,
+- 0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f2, 0x0da1, 0x0da2, 0x0da3,
+- 0x0da4, 0x0da5, 0x0da6, 0x0da7, 0x0da8, 0x0da9, 0x0daa, 0x0dab,
+- 0x0dac, 0x0dad, 0x0dae, 0x0daf, 0x0db0, 0x0db1, 0x0db2, 0x0db3,
+- 0x0db4, 0x0db5, 0x0db6, 0x0db7, 0x0db8, 0x0db9, 0x0dba, 0x0dbb,
+- 0x0dbc, 0x0dbd, 0x0dbe, 0x0dbf, 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3,
+- 0x0dc4, 0x0dc5, 0x0dc6, 0x0dc7, 0x0dc8, 0x0dc9, 0x0dca, 0x0dcb,
+- 0x0dcc, 0x0dcd, 0x0dce, 0x0dcf, 0x0dd0, 0x0dd1, 0x0dd2, 0x0dd3,
+- 0x0dd4, 0x0dd5, 0x0dd6, 0x0dd7, 0x0dd8, 0x0dd9, 0x0dda, 0x0ddf,
+- 0x0de0, 0x0de1, 0x0de2, 0x0de3, 0x0de4, 0x0de5, 0x0de6, 0x0de7,
+- 0x0de8, 0x0de9, 0x0dea, 0x0deb, 0x0dec, 0x0ded, 0x0df0, 0x0df1,
+- 0x0df2, 0x0df3, 0x0df4, 0x0df5, 0x0df6, 0x0df7, 0x0df8, 0x0df9,
+- 0x0aa2, 0x0aa1, 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa6, 0x0aa7, 0x0aa8,
+- 0x0abb, 0x0aaa, 0x0aa9, 0x07af, 0x0cdf, 0x0ad0, 0x0ad1, 0x0afd,
+- 0x0ad2, 0x0ad3, 0x0afe, 0x0af1, 0x0af2, 0x0aaf, 0x0aae, 0x0ad5,
+- 0x0ad6, 0x0ad7, 0x0afc, 0x047e, 0x20ac, 0x0ab8, 0x06b0, 0x0afb,
+- 0x0ad4, 0x0ac9, 0x0ab0, 0x0ab1, 0x0ab2, 0x0ab3, 0x0ab4, 0x0ab5,
+- 0x0ab6, 0x0ab7, 0x0ac3, 0x0ac4, 0x0ac5, 0x0ac6, 0x08fb, 0x08fc,
+- 0x08fd, 0x08fe, 0x08ce, 0x08cd, 0x08ef, 0x08c5, 0x0bca, 0x08d6,
+- 0x08c1, 0x08c2, 0x08de, 0x08df, 0x08dc, 0x08dd, 0x08bf, 0x08c0,
+- 0x08c8, 0x08c9, 0x08bd, 0x08cf, 0x08bc, 0x08be, 0x08da, 0x08db,
+- 0x0bfc, 0x0bdc, 0x0bc2, 0x0bce, 0x0bd3, 0x0bc4, 0x0afa, 0x08a4,
+- 0x08a5, 0x0bcc, 0x08ab, 0x08ac, 0x08ad, 0x08ae, 0x08a7, 0x08a8,
+- 0x08a9, 0x08aa, 0x08af, 0x08b0, 0x08a1, 0x09ef, 0x09f0, 0x09f2,
+- 0x09f3, 0x09e2, 0x09e5, 0x09e9, 0x09e3, 0x09e4, 0x09e8, 0x09f1,
+- 0x09f8, 0x09ec, 0x09eb, 0x09ed, 0x09ea, 0x09f4, 0x09f5, 0x09f7,
+- 0x09f6, 0x09ee, 0x09e1, 0x09e0, 0x0bcf, 0x0af9, 0x0af8, 0x0af7,
+- 0x0aec, 0x0aee, 0x0aed, 0x0af6, 0x0af5, 0x0af3, 0x0af4, 0x0ad9,
+- 0x0af0, 0x04a4, 0x04a1, 0x04a2, 0x04a3, 0x04de, 0x04df, 0x04a7,
+- 0x04b1, 0x04a8, 0x04b2, 0x04a9, 0x04b3, 0x04aa, 0x04b4, 0x04ab,
+- 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc,
+- 0x04bd, 0x04be, 0x04bf, 0x04c0, 0x04c1, 0x04af, 0x04c2, 0x04c3,
+- 0x04c4, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9, 0x04ca, 0x04cb,
+- 0x04cc, 0x04cd, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d2, 0x04d3,
+- 0x04ac, 0x04d4, 0x04ad, 0x04d5, 0x04ae, 0x04d6, 0x04d7, 0x04d8,
+- 0x04d9, 0x04da, 0x04db, 0x04dc, 0x04a6, 0x04dd, 0x04a5, 0x04b0
+-};
+diff --git a/src/autotype/x11/keysymmap.py b/src/autotype/x11/keysymmap.py
+deleted file mode 100755
+index a359710..0000000
+--- a/src/autotype/x11/keysymmap.py
++++ /dev/null
+@@ -1,107 +0,0 @@
+-#!/usr/bin/python3
+-
+-#
+-# Copyright (C) 2013 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/>.
+-#
+-
+-#
+-# Parses keysymdef.h to construct a unicode symbol -> keysym mapping table.
+-#
+-# The lines that are parsed look like this:
+-# #define XK_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */
+-#
+-# This would create a 0x0104 -> 0x01a1 mapping.
+-#
+-
+-import sys
+-import re
+-import collections
+-
+-cols = 8
+-
+-if len(sys.argv) >= 2:
+- keysymdef = sys.argv[1]
+-else:
+- keysymdef = "/usr/include/X11/keysymdef.h"
+-
+-keysymMap = {}
+-
+-f = open(keysymdef, "r")
+-for line in f:
+- match = re.search(r'0x([0-9a-fA-F]+)\s+/\* U\+([0-9a-fA-F]+)', line)
+- if match:
+- keysym = int(match.group(1), 16)
+- unicodeVal = int(match.group(2), 16)
+-
+- # ignore 1:1 mappings
+- if keysym >= 0x0020 and keysym <= 0x007e:
+- continue
+- if keysym >= 0x00a0 and keysym <= 0x00ff:
+- continue
+- # ignore unicode | 0x01000000 mappings
+- if keysym >= 0x1000000:
+- continue
+-
+- keysymMap[unicodeVal] = keysym
+-
+-keysymMap = collections.OrderedDict(sorted(keysymMap.items(), key=lambda t: t[0]))
+-
+-print("""/*
+- * Automatically generated by keysymmap.py from parsing keysymdef.h.
+- */
+-""")
+-
+-print("const int AutoTypePlatformX11::m_unicodeToKeysymLen = " + str(len(keysymMap)) + ";")
+-
+-print()
+-
+-print("const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {")
+-keys = keysymMap.keys()
+-keyLen = len(keys)
+-i = 1
+-for val in keys:
+- hexVal = "{0:#0{1}x}".format(val, 6)
+-
+- if i == keyLen:
+- print(hexVal)
+- elif (i % cols) == 0:
+- print(hexVal + ",")
+- elif ((i - 1) % cols) == 0:
+- print(" " + hexVal + ", ", end="")
+- else:
+- print(hexVal + ", ", end="")
+- i += 1
+-print("};")
+-
+-print()
+-
+-print("const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {")
+-values = keysymMap.values()
+-valuesLen = len(values)
+-i = 1
+-for val in values:
+- hexVal = "{0:#0{1}x}".format(val, 6)
+-
+- if i == valuesLen:
+- print(hexVal)
+- elif (i % cols) == 0:
+- print(hexVal + ",")
+- elif ((i - 1) % cols) == 0:
+- print(" " + hexVal + ", ", end="")
+- else:
+- print(hexVal + ", ", end="")
+- i += 1
+-print("};")
+diff --git a/src/autotype/xcb/AutoTypeXCB.cpp b/src/autotype/xcb/AutoTypeXCB.cpp
+new file mode 100644
+index 0000000..40acaf6
+--- /dev/null
++++ b/src/autotype/xcb/AutoTypeXCB.cpp
+@@ -0,0 +1,870 @@
++/*
++ * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
++ * Copyright (C) 2000-2008 Tom Sato <VEF00200@nifty.ne.jp>
++ *
++ * 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 "AutoTypeXCB.h"
++#include "KeySymMap.h"
++#include "core/Tools.h"
++
++#include <time.h>
++#include <xcb/xcb.h>
++
++bool AutoTypePlatformX11::m_catchXErrors = false;
++bool AutoTypePlatformX11::m_xErrorOccured = false;
++int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = nullptr;
++
++AutoTypePlatformX11::AutoTypePlatformX11()
++{
++ m_dpy = QX11Info::display();
++ m_rootWindow = QX11Info::appRootWindow();
++
++ m_atomWmState = XInternAtom(m_dpy, "WM_STATE", True);
++ m_atomWmName = XInternAtom(m_dpy, "WM_NAME", True);
++ m_atomNetWmName = XInternAtom(m_dpy, "_NET_WM_NAME", True);
++ m_atomString = XInternAtom(m_dpy, "STRING", True);
++ m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True);
++ m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True);
++
++ m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
++ m_classBlacklist << "kdesktop" << "kicker"; // KDE 3
++ m_classBlacklist << "Plasma"; // KDE 4
++ m_classBlacklist << "plasmashell"; // KDE 5
++ m_classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4
++
++ m_currentGlobalKey = static_cast<Qt::Key>(0);
++ m_currentGlobalModifiers = 0;
++
++ m_keysymTable = nullptr;
++ m_xkb = nullptr;
++ m_remapKeycode = 0;
++ m_currentRemapKeysym = NoSymbol;
++ m_modifierMask = ControlMask | ShiftMask | Mod1Mask | Mod4Mask;
++
++ m_loaded = true;
++
++ updateKeymap();
++}
++
++bool AutoTypePlatformX11::isAvailable()
++{
++ int ignore;
++
++ if (!XQueryExtension(m_dpy, "XInputExtension", &ignore, &ignore, &ignore)) {
++ return false;
++ }
++
++ if (!XQueryExtension(m_dpy, "XTEST", &ignore, &ignore, &ignore)) {
++ return false;
++ }
++
++ if (!m_xkb) {
++ XkbDescPtr kbd = getKeyboard();
++
++ if (!kbd) {
++ return false;
++ }
++
++ XkbFreeKeyboard(kbd, XkbAllComponentsMask, True);
++ }
++
++ return true;
++}
++
++void AutoTypePlatformX11::unload()
++{
++ // Restore the KeyboardMapping to its original state.
++ if (m_currentRemapKeysym != NoSymbol) {
++ AddKeysym(NoSymbol);
++ }
++
++ if (m_keysymTable) {
++ XFree(m_keysymTable);
++ }
++
++ if (m_xkb) {
++ XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
++ }
++
++ m_loaded = false;
++}
++
++QStringList AutoTypePlatformX11::windowTitles()
++{
++ return windowTitlesRecursive(m_rootWindow);
++}
++
++WId AutoTypePlatformX11::activeWindow()
++{
++ Window window;
++ int revert_to_return;
++ XGetInputFocus(m_dpy, &window, &revert_to_return);
++
++ int tree;
++ do {
++ if (isTopLevelWindow(window)) {
++ break;
++ }
++
++ Window root;
++ Window parent;
++ Window* children = nullptr;
++ unsigned int numChildren;
++ tree = XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren);
++ window = parent;
++ if (children) {
++ XFree(children);
++ }
++ } while (tree && window);
++
++ return window;
++}
++
++QString AutoTypePlatformX11::activeWindowTitle()
++{
++ return windowTitle(activeWindow(), true);
++}
++
++bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
++{
++ int keycode = XKeysymToKeycode(m_dpy, charToKeySym(key));
++ uint nativeModifiers = qtToNativeModifiers(modifiers);
++
++ startCatchXErrors();
++ XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
++ XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync,
++ GrabModeAsync);
++ XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync,
++ GrabModeAsync);
++ XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True,
++ GrabModeAsync, GrabModeAsync);
++ stopCatchXErrors();
++
++ if (!m_xErrorOccured) {
++ m_currentGlobalKey = key;
++ m_currentGlobalModifiers = modifiers;
++ m_currentGlobalKeycode = keycode;
++ m_currentGlobalNativeModifiers = nativeModifiers;
++ return true;
++ }
++ else {
++ unregisterGlobalShortcut(key, modifiers);
++ return false;
++ }
++}
++
++uint AutoTypePlatformX11::qtToNativeModifiers(Qt::KeyboardModifiers modifiers)
++{
++ uint nativeModifiers = 0;
++
++ if (modifiers & Qt::ShiftModifier) {
++ nativeModifiers |= ShiftMask;
++ }
++ if (modifiers & Qt::ControlModifier) {
++ nativeModifiers |= ControlMask;
++ }
++ if (modifiers & Qt::AltModifier) {
++ nativeModifiers |= Mod1Mask;
++ }
++ if (modifiers & Qt::MetaModifier) {
++ nativeModifiers |= Mod4Mask;
++ }
++
++ return nativeModifiers;
++}
++
++void AutoTypePlatformX11::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
++{
++ KeyCode keycode = XKeysymToKeycode(m_dpy, charToKeySym(key));
++ uint nativeModifiers = qtToNativeModifiers(modifiers);
++
++ XUngrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow);
++ XUngrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow);
++ XUngrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow);
++ XUngrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow);
++
++ m_currentGlobalKey = static_cast<Qt::Key>(0);
++ m_currentGlobalModifiers = 0;
++ m_currentGlobalKeycode = 0;
++ m_currentGlobalNativeModifiers = 0;
++}
++
++int AutoTypePlatformX11::platformEventFilter(void* event)
++{
++ xcb_generic_event_t* genericEvent = static_cast<xcb_generic_event_t*>(event);
++ quint8 type = genericEvent->response_type & 0x7f;
++
++ if (type == XCB_KEY_PRESS || type == XCB_KEY_RELEASE) {
++ xcb_key_press_event_t* keyPressEvent = static_cast<xcb_key_press_event_t*>(event);
++ if (keyPressEvent->detail == m_currentGlobalKeycode
++ && (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers
++ && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized())
++ && m_loaded) {
++ if (type == XCB_KEY_PRESS) {
++ Q_EMIT globalShortcutTriggered();
++ }
++
++ return 1;
++ }
++ }
++ else if (type == XCB_MAPPING_NOTIFY) {
++ xcb_mapping_notify_event_t* mappingNotifyEvent = static_cast<xcb_mapping_notify_event_t*>(event);
++ if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD
++ || mappingNotifyEvent->request == XCB_MAPPING_MODIFIER)
++ {
++ XMappingEvent xMappingEvent;
++ memset(&xMappingEvent, 0, sizeof(xMappingEvent));
++ xMappingEvent.type = MappingNotify;
++ xMappingEvent.display = m_dpy;
++ if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD) {
++ xMappingEvent.request = MappingKeyboard;
++ }
++ else {
++ xMappingEvent.request = MappingModifier;
++ }
++ xMappingEvent.first_keycode = mappingNotifyEvent->first_keycode;
++ xMappingEvent.count = mappingNotifyEvent->count;
++ XRefreshKeyboardMapping(&xMappingEvent);
++ updateKeymap();
++ }
++ }
++
++ return -1;
++}
++
++AutoTypeExecutor* AutoTypePlatformX11::createExecutor()
++{
++ return new AutoTypeExecturorX11(this);
++}
++
++QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
++{
++ QString title;
++
++ Atom type;
++ int format;
++ unsigned long nitems;
++ unsigned long after;
++ unsigned char* data = nullptr;
++
++ // the window manager spec says we should read _NET_WM_NAME first, then fall back to WM_NAME
++
++ int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String,
++ &type, &format, &nitems, &after, &data);
++
++ if ((retVal == 0) && data) {
++ title = QString::fromUtf8(reinterpret_cast<char*>(data));
++ }
++ else {
++ XTextProperty textProp;
++ retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName);
++ if ((retVal != 0) && textProp.value) {
++ char** textList = nullptr;
++ int count;
++
++ if (textProp.encoding == m_atomUtf8String) {
++ title = QString::fromUtf8(reinterpret_cast<char*>(textProp.value));
++ }
++ else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0)
++ && textList && (count > 0)) {
++ title = QString::fromLocal8Bit(textList[0]);
++ }
++ else if (textProp.encoding == m_atomString) {
++ title = QString::fromLocal8Bit(reinterpret_cast<char*>(textProp.value));
++ }
++
++ if (textList) {
++ XFreeStringList(textList);
++ }
++ }
++
++ if (textProp.value) {
++ XFree(textProp.value);
++ }
++ }
++
++ if (data) {
++ XFree(data);
++ }
++
++ if (useBlacklist && !title.isEmpty()) {
++ if (window == m_rootWindow) {
++ return QString();
++ }
++
++ QString className = windowClassName(window);
++ if (m_classBlacklist.contains(className)) {
++ return QString();
++ }
++
++ QList<Window> keepassxWindows = widgetsToX11Windows(QApplication::topLevelWidgets());
++ if (keepassxWindows.contains(window)) {
++ return QString();
++ }
++ }
++
++ return title;
++}
++
++QString AutoTypePlatformX11::windowClassName(Window window)
++{
++ QString className;
++
++ XClassHint wmClass;
++ wmClass.res_name = nullptr;
++ wmClass.res_class = nullptr;
++
++ if (XGetClassHint(m_dpy, window, &wmClass) && wmClass.res_name) {
++ className = QString::fromLocal8Bit(wmClass.res_name);
++ }
++ if (wmClass.res_name) {
++ XFree(wmClass.res_name);
++ }
++ if (wmClass.res_class) {
++ XFree(wmClass.res_class);
++ }
++
++ return className;
++}
++
++QList<Window> AutoTypePlatformX11::widgetsToX11Windows(const QWidgetList& widgetList)
++{
++ QList<Window> windows;
++
++ Q_FOREACH (const QWidget* widget, widgetList) {
++ windows.append(widget->effectiveWinId());
++ }
++
++ return windows;
++}
++
++QStringList AutoTypePlatformX11::windowTitlesRecursive(Window window)
++{
++ QStringList titles;
++
++ if (isTopLevelWindow(window)) {
++ QString title = windowTitle(window, true);
++ if (!title.isEmpty()) {
++ titles.append(title);
++ }
++ }
++
++ Window root;
++ Window parent;
++ Window* children = nullptr;
++ unsigned int numChildren;
++ if (XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren) && children) {
++ for (uint i = 0; i < numChildren; i++) {
++ titles.append(windowTitlesRecursive(children[i]));
++ }
++ }
++ if (children) {
++ XFree(children);
++ }
++
++ return titles;
++}
++
++bool AutoTypePlatformX11::isTopLevelWindow(Window window)
++{
++ Atom type = None;
++ int format;
++ unsigned long nitems;
++ unsigned long after;
++ unsigned char* data = nullptr;
++ int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 0, False, AnyPropertyType, &type, &format,
++ &nitems, &after, &data);
++ if (data) {
++ XFree(data);
++ }
++
++ return (retVal == 0) && type;
++}
++
++KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
++{
++ ushort unicode = ch.unicode();
++
++ /* first check for Latin-1 characters (1:1 mapping) */
++ if ((unicode >= 0x0020 && unicode <= 0x007e)
++ || (unicode >= 0x00a0 && unicode <= 0x00ff)) {
++ return unicode;
++ }
++
++ /* mapping table generated from keysymdef.h */
++ const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys,
++ m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
++ unicode);
++ int index = match - m_unicodeToKeysymKeys;
++ if (index != m_unicodeToKeysymLen) {
++ return m_unicodeToKeysymValues[index];
++ }
++
++ if (unicode >= 0x0100) {
++ return unicode | 0x01000000;
++ }
++
++ return NoSymbol;
++}
++
++KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
++{
++ switch (key) {
++ case Qt::Key_Tab:
++ return XK_Tab;
++ case Qt::Key_Enter:
++ return XK_Return;
++ case Qt::Key_Up:
++ return XK_Up;
++ case Qt::Key_Down:
++ return XK_Down;
++ case Qt::Key_Left:
++ return XK_Left;
++ case Qt::Key_Right:
++ return XK_Right;
++ case Qt::Key_Insert:
++ return XK_Insert;
++ case Qt::Key_Delete:
++ return XK_Delete;
++ case Qt::Key_Home:
++ return XK_Home;
++ case Qt::Key_End:
++ return XK_End;
++ case Qt::Key_PageUp:
++ return XK_Page_Up;
++ case Qt::Key_PageDown:
++ return XK_Page_Down;
++ case Qt::Key_Backspace:
++ return XK_BackSpace;
++ case Qt::Key_Pause:
++ return XK_Break;
++ case Qt::Key_CapsLock:
++ return XK_Caps_Lock;
++ case Qt::Key_Escape:
++ return XK_Escape;
++ case Qt::Key_Help:
++ return XK_Help;
++ case Qt::Key_NumLock:
++ return XK_Num_Lock;
++ case Qt::Key_Print:
++ return XK_Print;
++ case Qt::Key_ScrollLock:
++ return XK_Scroll_Lock;
++ default:
++ if (key >= Qt::Key_F1 && key <= Qt::Key_F16) {
++ return XK_F1 + (key - Qt::Key_F1);
++ }
++ else {
++ return NoSymbol;
++ }
++ }
++}
++
++/*
++ * Update the keyboard and modifier mapping.
++ * We need the KeyboardMapping for AddKeysym.
++ * Modifier mapping is required for clearing the modifiers.
++ */
++void AutoTypePlatformX11::updateKeymap()
++{
++ int keycode, inx;
++ int mod_index, mod_key;
++ XModifierKeymap *modifiers;
++
++ if (m_xkb) {
++ XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
++ }
++ m_xkb = getKeyboard();
++
++ XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
++ if (m_keysymTable != NULL) XFree(m_keysymTable);
++ m_keysymTable = XGetKeyboardMapping(m_dpy,
++ m_minKeycode, m_maxKeycode - m_minKeycode + 1,
++ &m_keysymPerKeycode);
++
++ /* determine the keycode to use for remapped keys */
++ inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
++ if (m_remapKeycode == 0 || !isRemapKeycodeValid()) {
++ for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
++ inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
++ if (m_keysymTable[inx] == NoSymbol) {
++ m_remapKeycode = keycode;
++ m_currentRemapKeysym = NoSymbol;
++ break;
++ }
++ }
++ }
++
++ /* determine the keycode to use for modifiers */
++ modifiers = XGetModifierMapping(m_dpy);
++ for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
++ m_modifier_keycode[mod_index] = 0;
++ for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) {
++ keycode = modifiers->modifiermap[mod_index * modifiers->max_keypermod + mod_key];
++ if (keycode) {
++ m_modifier_keycode[mod_index] = keycode;
++ break;
++ }
++ }
++ }
++ XFreeModifiermap(modifiers);
++
++ /* Xlib needs some time until the mapping is distributed to
++ all clients */
++ // TODO: we should probably only sleep while in the middle of typing something
++ timespec ts;
++ ts.tv_sec = 0;
++ ts.tv_nsec = 30 * 1000 * 1000;
++ nanosleep(&ts, nullptr);
++}
++
++bool AutoTypePlatformX11::isRemapKeycodeValid()
++{
++ int baseKeycode = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
++ for (int i = 0; i < m_keysymPerKeycode; i++) {
++ if (m_keysymTable[baseKeycode + i] == m_currentRemapKeysym) {
++ return true;
++ }
++ }
++
++ return false;
++}
++
++void AutoTypePlatformX11::startCatchXErrors()
++{
++ Q_ASSERT(!m_catchXErrors);
++
++ m_catchXErrors = true;
++ m_xErrorOccured = false;
++ m_oldXErrorHandler = XSetErrorHandler(x11ErrorHandler);
++}
++
++void AutoTypePlatformX11::stopCatchXErrors()
++{
++ Q_ASSERT(m_catchXErrors);
++
++ XSync(m_dpy, False);
++ XSetErrorHandler(m_oldXErrorHandler);
++ m_catchXErrors = false;
++}
++
++int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error)
++{
++ Q_UNUSED(display)
++ Q_UNUSED(error)
++
++ if (m_catchXErrors) {
++ m_xErrorOccured = true;
++ }
++
++ return 1;
++}
++
++XkbDescPtr AutoTypePlatformX11::getKeyboard()
++{
++ int num_devices;
++ XID keyboard_id = XkbUseCoreKbd;
++ XDeviceInfo* devices = XListInputDevices(m_dpy, &num_devices);
++ if (!devices) {
++ return nullptr;
++ }
++
++ for (int i = 0; i < num_devices; i++) {
++ if (QString(devices[i].name) == "Virtual core XTEST keyboard") {
++ keyboard_id = devices[i].id;
++ break;
++ }
++ }
++
++ XFreeDeviceList(devices);
++
++ return XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id);
++}
++
++// --------------------------------------------------------------------------
++// The following code is taken from xvkbd 3.0 and has been slightly modified.
++// --------------------------------------------------------------------------
++
++/*
++ * Insert a specified keysym on the dedicated position in the keymap
++ * table.
++ */
++int AutoTypePlatformX11::AddKeysym(KeySym keysym)
++{
++ if (m_remapKeycode == 0) {
++ return 0;
++ }
++
++ int inx = (m_remapKeycode- m_minKeycode) * m_keysymPerKeycode;
++ m_keysymTable[inx] = keysym;
++ m_currentRemapKeysym = keysym;
++
++ XChangeKeyboardMapping(m_dpy, m_remapKeycode, m_keysymPerKeycode, &m_keysymTable[inx], 1);
++ XFlush(m_dpy);
++ updateKeymap();
++
++ return m_remapKeycode;
++}
++
++/*
++ * Send event to the focused window.
++ * If input focus is specified explicitly, select the window
++ * before send event to the window.
++ */
++void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type)
++{
++ XSync(event->display, False);
++ int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
++
++ event->type = event_type;
++ Bool press;
++ if (event->type == KeyPress) {
++ press = True;
++ }
++ else {
++ press = False;
++ }
++ XTestFakeKeyEvent(event->display, event->keycode, press, 0);
++ XFlush(event->display);
++
++ XSetErrorHandler(oldHandler);
++}
++
++/*
++ * Send a modifier press/release event for all modifiers
++ * which are set in the mask variable.
++ */
++void AutoTypePlatformX11::SendModifier(XKeyEvent *event, unsigned int mask, int event_type)
++{
++ int mod_index;
++ for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
++ if (mask & (1 << mod_index)) {
++ event->keycode = m_modifier_keycode[mod_index];
++ SendEvent(event, event_type);
++ if (event_type == KeyPress)
++ event->state |= (1 << mod_index);
++ else
++ event->state &= (1 << mod_index);
++ }
++ }
++}
++
++/*
++ * Determines the keycode and modifier mask for the given
++ * keysym.
++ */
++int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask)
++{
++ int keycode = XKeysymToKeycode(m_dpy, keysym);
++
++ if (keycode && keysymModifiers(keysym, keycode, mask)) {
++ return keycode;
++ }
++
++ /* no modifier matches => resort to remapping */
++ keycode = AddKeysym(keysym);
++ if (keycode && keysymModifiers(keysym, keycode, mask)) {
++ return keycode;
++ }
++
++ *mask = 0;
++ return 0;
++}
++
++bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int *mask)
++{
++ int shift, mod;
++ unsigned int mods_rtrn;
++
++ /* determine whether there is a combination of the modifiers
++ (Mod1-Mod5) with or without shift which returns keysym */
++ for (shift = 0; shift < 2; shift ++) {
++ for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod ++) {
++ KeySym keysym_rtrn;
++ *mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod);
++ XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn);
++ if (keysym_rtrn == keysym) {
++ return true;
++ }
++ }
++ }
++
++ return false;
++}
++
++
++
++/*
++ * Send sequence of KeyPressed/KeyReleased events to the focused
++ * window to simulate keyboard. If modifiers (shift, control, etc)
++ * are set ON, many events will be sent.
++ */
++void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym)
++{
++ Window cur_focus;
++ int revert_to;
++ XKeyEvent event;
++ int keycode;
++
++ if (keysym == NoSymbol) {
++ qWarning("No such key: keysym=0x%lX", keysym);
++ return;
++ }
++
++ XGetInputFocus(m_dpy, &cur_focus, &revert_to);
++
++ event.display = m_dpy;
++ event.window = cur_focus;
++ event.root = m_rootWindow;
++ event.subwindow = None;
++ event.time = CurrentTime;
++ event.x = 1;
++ event.y = 1;
++ event.x_root = 1;
++ event.y_root = 1;
++ event.same_screen = True;
++
++ Window root, child;
++ int root_x, root_y, x, y;
++ unsigned int wanted_mask = 0;
++ unsigned int original_mask;
++
++ XQueryPointer(m_dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &original_mask);
++
++ /* determine keycode and mask for the given keysym */
++ keycode = GetKeycode(keysym, &wanted_mask);
++ if (keycode < 8 || keycode > 255) {
++ qWarning("Unable to get valid keycode for key: keysym=0x%lX", keysym);
++ return;
++ }
++
++ event.state = original_mask;
++
++ // modifiers that need to be pressed but aren't
++ unsigned int press_mask = wanted_mask & ~original_mask;
++
++ // modifiers that are pressed but maybe shouldn't
++ unsigned int release_check_mask = original_mask & ~wanted_mask;
++
++ // modifiers we need to release before sending the keycode
++ unsigned int release_mask = 0;
++
++ // check every release_check_mask individually if it affects the keysym we would generate
++ // if it doesn't we probably don't need to release it
++ for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
++ if (release_check_mask & (1 << mod_index)) {
++ unsigned int mods_rtrn;
++ KeySym keysym_rtrn;
++ XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (1 << mod_index), &mods_rtrn, &keysym_rtrn);
++
++ if (keysym_rtrn != keysym) {
++ release_mask |= (1 << mod_index);
++ }
++ }
++ }
++
++ // finally check if the combination of pressed modifiers that we chose to ignore affects the keysym
++ unsigned int mods_rtrn;
++ KeySym keysym_rtrn;
++ XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn);
++ if (keysym_rtrn != keysym) {
++ // oh well, release all the modifiers we don't want
++ release_mask = release_check_mask;
++ }
++
++ /* release all modifiers */
++ SendModifier(&event, release_mask, KeyRelease);
++
++ SendModifier(&event, press_mask, KeyPress);
++
++ /* press and release key */
++ event.keycode = keycode;
++ SendEvent(&event, KeyPress);
++ SendEvent(&event, KeyRelease);
++
++ /* release the modifiers */
++ SendModifier(&event, press_mask, KeyRelease);
++
++ /* restore the old keyboard mask */
++ SendModifier(&event, release_mask, KeyPress);
++}
++
++int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
++{
++ char msg[200];
++
++ if (event->error_code == BadWindow) {
++ return 0;
++ }
++ XGetErrorText(my_dpy, event->error_code, msg, sizeof(msg) - 1);
++ qWarning("X error trapped: %s, request-code=%d\n", msg, event->request_code);
++ return 0;
++}
++
++
++AutoTypeExecturorX11::AutoTypeExecturorX11(AutoTypePlatformX11* platform)
++ : m_platform(platform)
++{
++}
++
++void AutoTypeExecturorX11::execChar(AutoTypeChar* action)
++{
++ m_platform->SendKeyPressedEvent(m_platform->charToKeySym(action->character));
++}
++
++void AutoTypeExecturorX11::execKey(AutoTypeKey* action)
++{
++ m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(action->key));
++}
++
++int AutoTypePlatformX11::initialTimeout()
++{
++ return 500;
++}
++
++bool AutoTypePlatformX11::raiseWindow(WId window)
++{
++ if (m_atomNetActiveWindow == None) {
++ return false;
++ }
++
++ XRaiseWindow(m_dpy, window);
++
++ XEvent event;
++ event.xclient.type = ClientMessage;
++ event.xclient.serial = 0;
++ event.xclient.send_event = True;
++ event.xclient.window = window;
++ event.xclient.message_type = m_atomNetActiveWindow;
++ event.xclient.format = 32;
++ event.xclient.data.l[0] = 1; // FromApplication
++ event.xclient.data.l[1] = QX11Info::appUserTime();
++ QWidget* activeWindow = QApplication::activeWindow();
++ if (activeWindow) {
++ event.xclient.data.l[2] = activeWindow->internalWinId();
++ }
++ else {
++ event.xclient.data.l[2] = 0;
++ }
++ event.xclient.data.l[3] = 0;
++ event.xclient.data.l[4] = 0;
++ XSendEvent(m_dpy, m_rootWindow, False,
++ SubstructureRedirectMask | SubstructureNotifyMask,
++ &event);
++ XFlush(m_dpy);
++
++ return true;
++}
+diff --git a/src/autotype/xcb/AutoTypeXCB.h b/src/autotype/xcb/AutoTypeXCB.h
+new file mode 100644
+index 0000000..8adee77
+--- /dev/null
++++ b/src/autotype/xcb/AutoTypeXCB.h
+@@ -0,0 +1,134 @@
++/*
++ * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
++ * Copyright (C) 2000-2008 Tom Sato <VEF00200@nifty.ne.jp>
++ *
++ * 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_AUTOTYPEXCB_H
++#define KEEPASSX_AUTOTYPEXCB_H
++
++#include <QApplication>
++#include <QSet>
++#include <QtPlugin>
++#include <QWidget>
++#include <QX11Info>
++
++#include <X11/Xutil.h>
++#include <X11/extensions/XTest.h>
++#include <X11/XKBlib.h>
++
++#include "autotype/AutoTypePlatformPlugin.h"
++#include "autotype/AutoTypeAction.h"
++
++#define N_MOD_INDICES (Mod5MapIndex + 1)
++
++class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
++{
++ Q_OBJECT
++ Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformX11")
++ Q_INTERFACES(AutoTypePlatformInterface)
++
++public:
++ AutoTypePlatformX11();
++ bool isAvailable() override;
++ void unload() override;
++ QStringList windowTitles() override;
++ WId activeWindow() override;
++ QString activeWindowTitle() override;
++ bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
++ void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
++ int platformEventFilter(void* event) override;
++ int initialTimeout() override;
++ bool raiseWindow(WId window) override;
++ AutoTypeExecutor* createExecutor() override;
++
++ KeySym charToKeySym(const QChar& ch);
++ KeySym keyToKeySym(Qt::Key key);
++
++ void SendKeyPressedEvent(KeySym keysym);
++
++Q_SIGNALS:
++ void globalShortcutTriggered();
++
++private:
++ QString windowTitle(Window window, bool useBlacklist);
++ QStringList windowTitlesRecursive(Window window);
++ QString windowClassName(Window window);
++ QList<Window> widgetsToX11Windows(const QWidgetList& widgetList);
++ bool isTopLevelWindow(Window window);
++ uint qtToNativeModifiers(Qt::KeyboardModifiers modifiers);
++ void startCatchXErrors();
++ void stopCatchXErrors();
++ static int x11ErrorHandler(Display* display, XErrorEvent* error);
++
++ XkbDescPtr getKeyboard();
++ void updateKeymap();
++ bool isRemapKeycodeValid();
++ int AddKeysym(KeySym keysym);
++ void AddModifier(KeySym keysym);
++ void SendEvent(XKeyEvent* event, int event_type);
++ void SendModifier(XKeyEvent *event, unsigned int mask, int event_type);
++ int GetKeycode(KeySym keysym, unsigned int *mask);
++ bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask);
++
++ static int MyErrorHandler(Display* my_dpy, XErrorEvent* event);
++
++ Display* m_dpy;
++ Window m_rootWindow;
++ Atom m_atomWmState;
++ Atom m_atomWmName;
++ Atom m_atomNetWmName;
++ Atom m_atomString;
++ Atom m_atomUtf8String;
++ Atom m_atomNetActiveWindow;
++ QSet<QString> m_classBlacklist;
++ Qt::Key m_currentGlobalKey;
++ Qt::KeyboardModifiers m_currentGlobalModifiers;
++ uint m_currentGlobalKeycode;
++ uint m_currentGlobalNativeModifiers;
++ int m_modifierMask;
++ static bool m_catchXErrors;
++ static bool m_xErrorOccured;
++ static int (*m_oldXErrorHandler)(Display*, XErrorEvent*);
++
++ static const int m_unicodeToKeysymLen;
++ static const uint m_unicodeToKeysymKeys[];
++ static const uint m_unicodeToKeysymValues[];
++
++ XkbDescPtr m_xkb;
++ KeySym* m_keysymTable;
++ int m_minKeycode;
++ int m_maxKeycode;
++ int m_keysymPerKeycode;
++ /* dedicated keycode for remapped keys */
++ unsigned int m_remapKeycode;
++ KeySym m_currentRemapKeysym;
++ KeyCode m_modifier_keycode[N_MOD_INDICES];
++ bool m_loaded;
++};
++
++class AutoTypeExecturorX11 : public AutoTypeExecutor
++{
++public:
++ explicit AutoTypeExecturorX11(AutoTypePlatformX11* platform);
++
++ void execChar(AutoTypeChar* action) override;
++ void execKey(AutoTypeKey* action) override;
++
++private:
++ AutoTypePlatformX11* const m_platform;
++};
++
++#endif // KEEPASSX_AUTOTYPEXCB_H
+diff --git a/src/autotype/xcb/CMakeLists.txt b/src/autotype/xcb/CMakeLists.txt
+new file mode 100644
+index 0000000..3b56b31
+--- /dev/null
++++ b/src/autotype/xcb/CMakeLists.txt
+@@ -0,0 +1,11 @@
++include_directories(SYSTEM ${X11_X11_INCLUDE_PATH})
++
++set(autotype_XCB_SOURCES
++ AutoTypeXCB.cpp
++)
++
++add_library(keepassx-autotype-xcb MODULE ${autotype_XCB_SOURCES})
++target_link_libraries(keepassx-autotype-xcb Qt5::Core Qt5::Widgets Qt5::X11Extras ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_XTest_LIB})
++install(TARGETS keepassx-autotype-xcb
++ BUNDLE DESTINATION . COMPONENT Runtime
++ LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime)
+diff --git a/src/autotype/xcb/KeySymMap.h b/src/autotype/xcb/KeySymMap.h
+new file mode 100644
+index 0000000..55022fe
+--- /dev/null
++++ b/src/autotype/xcb/KeySymMap.h
+@@ -0,0 +1,169 @@
++/*
++ * Automatically generated by keysymmap.py from parsing keysymdef.h.
++ */
++
++const int AutoTypePlatformX11::m_unicodeToKeysymLen = 632;
++
++const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {
++ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
++ 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f,
++ 0x0110, 0x0111, 0x0112, 0x0113, 0x0116, 0x0117, 0x0118, 0x0119,
++ 0x011a, 0x011b, 0x011c, 0x011d, 0x011e, 0x011f, 0x0120, 0x0121,
++ 0x0122, 0x0123, 0x0124, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
++ 0x012a, 0x012b, 0x012e, 0x012f, 0x0130, 0x0131, 0x0134, 0x0135,
++ 0x0136, 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d,
++ 0x013e, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
++ 0x0148, 0x014a, 0x014b, 0x014c, 0x014d, 0x0150, 0x0151, 0x0152,
++ 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015a,
++ 0x015b, 0x015c, 0x015d, 0x015e, 0x015f, 0x0160, 0x0161, 0x0162,
++ 0x0163, 0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, 0x016a,
++ 0x016b, 0x016c, 0x016d, 0x016e, 0x016f, 0x0170, 0x0171, 0x0172,
++ 0x0173, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d, 0x017e,
++ 0x0192, 0x02c7, 0x02d8, 0x02d9, 0x02db, 0x02dd, 0x0385, 0x0386,
++ 0x0388, 0x0389, 0x038a, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391,
++ 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399,
++ 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1,
++ 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa,
++ 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b2,
++ 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba,
++ 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c2,
++ 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca,
++ 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0401, 0x0402, 0x0403, 0x0404,
++ 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c,
++ 0x040e, 0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
++ 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d,
++ 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
++ 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d,
++ 0x042e, 0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435,
++ 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d,
++ 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
++ 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d,
++ 0x044e, 0x044f, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456,
++ 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045e, 0x045f,
++ 0x0490, 0x0491, 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5,
++ 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd,
++ 0x05de, 0x05df, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
++ 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x060c, 0x061b, 0x061f,
++ 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
++ 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, 0x0630,
++ 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638,
++ 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645,
++ 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d,
++ 0x064e, 0x064f, 0x0650, 0x0651, 0x0652, 0x0e01, 0x0e02, 0x0e03,
++ 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b,
++ 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, 0x0e10, 0x0e11, 0x0e12, 0x0e13,
++ 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b,
++ 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, 0x0e20, 0x0e21, 0x0e22, 0x0e23,
++ 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b,
++ 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, 0x0e30, 0x0e31, 0x0e32, 0x0e33,
++ 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0e3f,
++ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
++ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e50, 0x0e51,
++ 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59,
++ 0x2002, 0x2003, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, 0x200a,
++ 0x2012, 0x2013, 0x2014, 0x2015, 0x2017, 0x2018, 0x2019, 0x201a,
++ 0x201c, 0x201d, 0x201e, 0x2020, 0x2021, 0x2025, 0x2026, 0x2030,
++ 0x2032, 0x2033, 0x2038, 0x203e, 0x20ac, 0x2105, 0x2116, 0x2117,
++ 0x211e, 0x2122, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158,
++ 0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x2190, 0x2191,
++ 0x2192, 0x2193, 0x21d2, 0x21d4, 0x2202, 0x2207, 0x2218, 0x221a,
++ 0x221d, 0x221e, 0x2227, 0x2228, 0x2229, 0x222a, 0x222b, 0x2234,
++ 0x223c, 0x2243, 0x2260, 0x2261, 0x2264, 0x2265, 0x2282, 0x2283,
++ 0x22a2, 0x22a3, 0x22a4, 0x22a5, 0x2308, 0x230a, 0x2315, 0x2320,
++ 0x2321, 0x2395, 0x239b, 0x239d, 0x239e, 0x23a0, 0x23a1, 0x23a3,
++ 0x23a4, 0x23a6, 0x23a8, 0x23ac, 0x23b7, 0x23ba, 0x23bb, 0x23bc,
++ 0x23bd, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x2424, 0x2500,
++ 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, 0x252c,
++ 0x2534, 0x253c, 0x2592, 0x25c6, 0x25cb, 0x260e, 0x2640, 0x2642,
++ 0x2663, 0x2665, 0x2666, 0x266d, 0x266f, 0x2713, 0x2717, 0x271d,
++ 0x2720, 0x3001, 0x3002, 0x300c, 0x300d, 0x309b, 0x309c, 0x30a1,
++ 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9,
++ 0x30aa, 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7,
++ 0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c3, 0x30c4, 0x30c6,
++ 0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d2,
++ 0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2,
++ 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea,
++ 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f2, 0x30f3, 0x30fb, 0x30fc
++};
++
++const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {
++ 0x03c0, 0x03e0, 0x01c3, 0x01e3, 0x01a1, 0x01b1, 0x01c6, 0x01e6,
++ 0x02c6, 0x02e6, 0x02c5, 0x02e5, 0x01c8, 0x01e8, 0x01cf, 0x01ef,
++ 0x01d0, 0x01f0, 0x03aa, 0x03ba, 0x03cc, 0x03ec, 0x01ca, 0x01ea,
++ 0x01cc, 0x01ec, 0x02d8, 0x02f8, 0x02ab, 0x02bb, 0x02d5, 0x02f5,
++ 0x03ab, 0x03bb, 0x02a6, 0x02b6, 0x02a1, 0x02b1, 0x03a5, 0x03b5,
++ 0x03cf, 0x03ef, 0x03c7, 0x03e7, 0x02a9, 0x02b9, 0x02ac, 0x02bc,
++ 0x03d3, 0x03f3, 0x03a2, 0x01c5, 0x01e5, 0x03a6, 0x03b6, 0x01a5,
++ 0x01b5, 0x01a3, 0x01b3, 0x01d1, 0x01f1, 0x03d1, 0x03f1, 0x01d2,
++ 0x01f2, 0x03bd, 0x03bf, 0x03d2, 0x03f2, 0x01d5, 0x01f5, 0x13bc,
++ 0x13bd, 0x01c0, 0x01e0, 0x03a3, 0x03b3, 0x01d8, 0x01f8, 0x01a6,
++ 0x01b6, 0x02de, 0x02fe, 0x01aa, 0x01ba, 0x01a9, 0x01b9, 0x01de,
++ 0x01fe, 0x01ab, 0x01bb, 0x03ac, 0x03bc, 0x03dd, 0x03fd, 0x03de,
++ 0x03fe, 0x02dd, 0x02fd, 0x01d9, 0x01f9, 0x01db, 0x01fb, 0x03d9,
++ 0x03f9, 0x13be, 0x01ac, 0x01bc, 0x01af, 0x01bf, 0x01ae, 0x01be,
++ 0x08f6, 0x01b7, 0x01a2, 0x01ff, 0x01b2, 0x01bd, 0x07ae, 0x07a1,
++ 0x07a2, 0x07a3, 0x07a4, 0x07a7, 0x07a8, 0x07ab, 0x07b6, 0x07c1,
++ 0x07c2, 0x07c3, 0x07c4, 0x07c5, 0x07c6, 0x07c7, 0x07c8, 0x07c9,
++ 0x07ca, 0x07cb, 0x07cc, 0x07cd, 0x07ce, 0x07cf, 0x07d0, 0x07d1,
++ 0x07d2, 0x07d4, 0x07d5, 0x07d6, 0x07d7, 0x07d8, 0x07d9, 0x07a5,
++ 0x07a9, 0x07b1, 0x07b2, 0x07b3, 0x07b4, 0x07ba, 0x07e1, 0x07e2,
++ 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9, 0x07ea,
++ 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
++ 0x07f2, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8, 0x07f9, 0x07b5,
++ 0x07b9, 0x07b7, 0x07b8, 0x07bb, 0x06b3, 0x06b1, 0x06b2, 0x06b4,
++ 0x06b5, 0x06b6, 0x06b7, 0x06b8, 0x06b9, 0x06ba, 0x06bb, 0x06bc,
++ 0x06be, 0x06bf, 0x06e1, 0x06e2, 0x06f7, 0x06e7, 0x06e4, 0x06e5,
++ 0x06f6, 0x06fa, 0x06e9, 0x06ea, 0x06eb, 0x06ec, 0x06ed, 0x06ee,
++ 0x06ef, 0x06f0, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06e6, 0x06e8,
++ 0x06e3, 0x06fe, 0x06fb, 0x06fd, 0x06ff, 0x06f9, 0x06f8, 0x06fc,
++ 0x06e0, 0x06f1, 0x06c1, 0x06c2, 0x06d7, 0x06c7, 0x06c4, 0x06c5,
++ 0x06d6, 0x06da, 0x06c9, 0x06ca, 0x06cb, 0x06cc, 0x06cd, 0x06ce,
++ 0x06cf, 0x06d0, 0x06d2, 0x06d3, 0x06d4, 0x06d5, 0x06c6, 0x06c8,
++ 0x06c3, 0x06de, 0x06db, 0x06dd, 0x06df, 0x06d9, 0x06d8, 0x06dc,
++ 0x06c0, 0x06d1, 0x06a3, 0x06a1, 0x06a2, 0x06a4, 0x06a5, 0x06a6,
++ 0x06a7, 0x06a8, 0x06a9, 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af,
++ 0x06bd, 0x06ad, 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5,
++ 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced,
++ 0x0cee, 0x0cef, 0x0cf0, 0x0cf1, 0x0cf2, 0x0cf3, 0x0cf4, 0x0cf5,
++ 0x0cf6, 0x0cf7, 0x0cf8, 0x0cf9, 0x0cfa, 0x05ac, 0x05bb, 0x05bf,
++ 0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7, 0x05c8,
++ 0x05c9, 0x05ca, 0x05cb, 0x05cc, 0x05cd, 0x05ce, 0x05cf, 0x05d0,
++ 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8,
++ 0x05d9, 0x05da, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
++ 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x05eb, 0x05ec, 0x05ed,
++ 0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f2, 0x0da1, 0x0da2, 0x0da3,
++ 0x0da4, 0x0da5, 0x0da6, 0x0da7, 0x0da8, 0x0da9, 0x0daa, 0x0dab,
++ 0x0dac, 0x0dad, 0x0dae, 0x0daf, 0x0db0, 0x0db1, 0x0db2, 0x0db3,
++ 0x0db4, 0x0db5, 0x0db6, 0x0db7, 0x0db8, 0x0db9, 0x0dba, 0x0dbb,
++ 0x0dbc, 0x0dbd, 0x0dbe, 0x0dbf, 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3,
++ 0x0dc4, 0x0dc5, 0x0dc6, 0x0dc7, 0x0dc8, 0x0dc9, 0x0dca, 0x0dcb,
++ 0x0dcc, 0x0dcd, 0x0dce, 0x0dcf, 0x0dd0, 0x0dd1, 0x0dd2, 0x0dd3,
++ 0x0dd4, 0x0dd5, 0x0dd6, 0x0dd7, 0x0dd8, 0x0dd9, 0x0dda, 0x0ddf,
++ 0x0de0, 0x0de1, 0x0de2, 0x0de3, 0x0de4, 0x0de5, 0x0de6, 0x0de7,
++ 0x0de8, 0x0de9, 0x0dea, 0x0deb, 0x0dec, 0x0ded, 0x0df0, 0x0df1,
++ 0x0df2, 0x0df3, 0x0df4, 0x0df5, 0x0df6, 0x0df7, 0x0df8, 0x0df9,
++ 0x0aa2, 0x0aa1, 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa6, 0x0aa7, 0x0aa8,
++ 0x0abb, 0x0aaa, 0x0aa9, 0x07af, 0x0cdf, 0x0ad0, 0x0ad1, 0x0afd,
++ 0x0ad2, 0x0ad3, 0x0afe, 0x0af1, 0x0af2, 0x0aaf, 0x0aae, 0x0ad5,
++ 0x0ad6, 0x0ad7, 0x0afc, 0x047e, 0x20ac, 0x0ab8, 0x06b0, 0x0afb,
++ 0x0ad4, 0x0ac9, 0x0ab0, 0x0ab1, 0x0ab2, 0x0ab3, 0x0ab4, 0x0ab5,
++ 0x0ab6, 0x0ab7, 0x0ac3, 0x0ac4, 0x0ac5, 0x0ac6, 0x08fb, 0x08fc,
++ 0x08fd, 0x08fe, 0x08ce, 0x08cd, 0x08ef, 0x08c5, 0x0bca, 0x08d6,
++ 0x08c1, 0x08c2, 0x08de, 0x08df, 0x08dc, 0x08dd, 0x08bf, 0x08c0,
++ 0x08c8, 0x08c9, 0x08bd, 0x08cf, 0x08bc, 0x08be, 0x08da, 0x08db,
++ 0x0bfc, 0x0bdc, 0x0bc2, 0x0bce, 0x0bd3, 0x0bc4, 0x0afa, 0x08a4,
++ 0x08a5, 0x0bcc, 0x08ab, 0x08ac, 0x08ad, 0x08ae, 0x08a7, 0x08a8,
++ 0x08a9, 0x08aa, 0x08af, 0x08b0, 0x08a1, 0x09ef, 0x09f0, 0x09f2,
++ 0x09f3, 0x09e2, 0x09e5, 0x09e9, 0x09e3, 0x09e4, 0x09e8, 0x09f1,
++ 0x09f8, 0x09ec, 0x09eb, 0x09ed, 0x09ea, 0x09f4, 0x09f5, 0x09f7,
++ 0x09f6, 0x09ee, 0x09e1, 0x09e0, 0x0bcf, 0x0af9, 0x0af8, 0x0af7,
++ 0x0aec, 0x0aee, 0x0aed, 0x0af6, 0x0af5, 0x0af3, 0x0af4, 0x0ad9,
++ 0x0af0, 0x04a4, 0x04a1, 0x04a2, 0x04a3, 0x04de, 0x04df, 0x04a7,
++ 0x04b1, 0x04a8, 0x04b2, 0x04a9, 0x04b3, 0x04aa, 0x04b4, 0x04ab,
++ 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc,
++ 0x04bd, 0x04be, 0x04bf, 0x04c0, 0x04c1, 0x04af, 0x04c2, 0x04c3,
++ 0x04c4, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9, 0x04ca, 0x04cb,
++ 0x04cc, 0x04cd, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d2, 0x04d3,
++ 0x04ac, 0x04d4, 0x04ad, 0x04d5, 0x04ae, 0x04d6, 0x04d7, 0x04d8,
++ 0x04d9, 0x04da, 0x04db, 0x04dc, 0x04a6, 0x04dd, 0x04a5, 0x04b0
++};
+diff --git a/src/autotype/xcb/keysymmap.py b/src/autotype/xcb/keysymmap.py
+new file mode 100755
+index 0000000..a359710
+--- /dev/null
++++ b/src/autotype/xcb/keysymmap.py
+@@ -0,0 +1,107 @@
++#!/usr/bin/python3
++
++#
++# Copyright (C) 2013 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/>.
++#
++
++#
++# Parses keysymdef.h to construct a unicode symbol -> keysym mapping table.
++#
++# The lines that are parsed look like this:
++# #define XK_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */
++#
++# This would create a 0x0104 -> 0x01a1 mapping.
++#
++
++import sys
++import re
++import collections
++
++cols = 8
++
++if len(sys.argv) >= 2:
++ keysymdef = sys.argv[1]
++else:
++ keysymdef = "/usr/include/X11/keysymdef.h"
++
++keysymMap = {}
++
++f = open(keysymdef, "r")
++for line in f:
++ match = re.search(r'0x([0-9a-fA-F]+)\s+/\* U\+([0-9a-fA-F]+)', line)
++ if match:
++ keysym = int(match.group(1), 16)
++ unicodeVal = int(match.group(2), 16)
++
++ # ignore 1:1 mappings
++ if keysym >= 0x0020 and keysym <= 0x007e:
++ continue
++ if keysym >= 0x00a0 and keysym <= 0x00ff:
++ continue
++ # ignore unicode | 0x01000000 mappings
++ if keysym >= 0x1000000:
++ continue
++
++ keysymMap[unicodeVal] = keysym
++
++keysymMap = collections.OrderedDict(sorted(keysymMap.items(), key=lambda t: t[0]))
++
++print("""/*
++ * Automatically generated by keysymmap.py from parsing keysymdef.h.
++ */
++""")
++
++print("const int AutoTypePlatformX11::m_unicodeToKeysymLen = " + str(len(keysymMap)) + ";")
++
++print()
++
++print("const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {")
++keys = keysymMap.keys()
++keyLen = len(keys)
++i = 1
++for val in keys:
++ hexVal = "{0:#0{1}x}".format(val, 6)
++
++ if i == keyLen:
++ print(hexVal)
++ elif (i % cols) == 0:
++ print(hexVal + ",")
++ elif ((i - 1) % cols) == 0:
++ print(" " + hexVal + ", ", end="")
++ else:
++ print(hexVal + ", ", end="")
++ i += 1
++print("};")
++
++print()
++
++print("const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {")
++values = keysymMap.values()
++valuesLen = len(values)
++i = 1
++for val in values:
++ hexVal = "{0:#0{1}x}".format(val, 6)
++
++ if i == valuesLen:
++ print(hexVal)
++ elif (i % cols) == 0:
++ print(hexVal + ",")
++ elif ((i - 1) % cols) == 0:
++ print(" " + hexVal + ", ", end="")
++ else:
++ print(hexVal + ", ", end="")
++ i += 1
++print("};")
+diff --git a/src/config-keepassx.h.cmake b/src/config-keepassx.h.cmake
+index 197c0d3..dc418b6 100644
+--- a/src/config-keepassx.h.cmake
++++ b/src/config-keepassx.h.cmake
+@@ -16,6 +16,4 @@
+ #cmakedefine HAVE_RLIMIT_CORE 1
+ #cmakedefine HAVE_PT_DENY_ATTACH 1
+
+-#cmakedefine GCRYPT_HAS_SALSA20
+-
+ #endif // KEEPASSX_CONFIG_KEEPASSX_H
+diff --git a/src/core/AutoTypeAssociations.h b/src/core/AutoTypeAssociations.h
+index 1b5871b..491a5db 100644
+--- a/src/core/AutoTypeAssociations.h
++++ b/src/core/AutoTypeAssociations.h
+@@ -20,8 +20,6 @@
+
+ #include <QObject>
+
+-#include "core/Global.h"
+-
+ class AutoTypeAssociations : public QObject
+ {
+ Q_OBJECT
+@@ -36,7 +34,7 @@ public:
+ bool operator!=(const AutoTypeAssociations::Association& other) const;
+ };
+
+- explicit AutoTypeAssociations(QObject* parent = Q_NULLPTR);
++ explicit AutoTypeAssociations(QObject* parent = nullptr);
+ void copyDataFrom(const AutoTypeAssociations* other);
+ void add(const AutoTypeAssociations::Association& association);
+ void remove(int index);
+diff --git a/src/core/Config.cpp b/src/core/Config.cpp
+index 046a0fe..5b06c22 100644
+--- a/src/core/Config.cpp
++++ b/src/core/Config.cpp
+@@ -18,12 +18,12 @@
+ #include "Config.h"
+
+ #include <QCoreApplication>
+-#include <QDesktopServices>
+ #include <QDir>
+ #include <QSettings>
++#include <QStandardPaths>
+ #include <QTemporaryFile>
+
+-Config* Config::m_instance(Q_NULLPTR);
++Config* Config::m_instance(nullptr);
+
+ QVariant Config::get(const QString& key)
+ {
+@@ -53,7 +53,7 @@ Config::Config(QObject* parent)
+ QString homePath = QDir::homePath();
+
+ #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
+- // we can't use QDesktopServices on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME
++ // we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME
+ QByteArray env = qgetenv("XDG_CONFIG_HOME");
+ if (env.isEmpty()) {
+ userPath = homePath;
+@@ -70,7 +70,7 @@ Config::Config(QObject* parent)
+
+ userPath += "/keepassx/";
+ #else
+- userPath = QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
++ userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
+ // storageLocation() appends the application name ("/keepassx") to the end
+ userPath += "/";
+ #endif
+diff --git a/src/core/Config.h b/src/core/Config.h
+index ca0f74c..09aa02f 100644
+--- a/src/core/Config.h
++++ b/src/core/Config.h
+@@ -21,8 +21,6 @@
+ #include <QScopedPointer>
+ #include <QVariant>
+
+-#include "core/Global.h"
+-
+ class QSettings;
+
+ class Config : public QObject
+diff --git a/src/core/Database.cpp b/src/core/Database.cpp
+index 098cc06..6f94235 100644
+--- a/src/core/Database.cpp
++++ b/src/core/Database.cpp
+@@ -23,7 +23,6 @@
+
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+-#include "core/Tools.h"
+ #include "crypto/Random.h"
+ #include "format/KeePass2.h"
+
+@@ -105,7 +104,7 @@ Entry* Database::recFindEntry(const Uuid& uuid, Group* group)
+ }
+ }
+
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ Group* Database::resolveGroup(const Uuid& uuid)
+@@ -126,7 +125,7 @@ Group* Database::recFindGroup(const Uuid& uuid, Group* group)
+ }
+ }
+
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QList<DeletedObject> Database::deletedObjects()
+@@ -143,7 +142,7 @@ void Database::addDeletedObject(const DeletedObject& delObj)
+ void Database::addDeletedObject(const Uuid& uuid)
+ {
+ DeletedObject delObj;
+- delObj.deletionTime = Tools::currentDateTimeUtc();
++ delObj.deletionTime = QDateTime::currentDateTimeUtc();
+ delObj.uuid = uuid;
+
+ addDeletedObject(delObj);
+@@ -223,7 +222,7 @@ bool Database::setKey(const CompositeKey& key, const QByteArray& transformSeed,
+ m_data.transformedMasterKey = transformedMasterKey;
+ m_data.hasKey = true;
+ if (updateChangedTime) {
+- m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc());
++ m_metadata->setMasterKeyChanged(QDateTime::currentDateTimeUtc());
+ }
+ Q_EMIT modifiedImmediate();
+
+diff --git a/src/core/Database.h b/src/core/Database.h
+index 97ccad2..6fde3c6 100644
+--- a/src/core/Database.h
++++ b/src/core/Database.h
+@@ -20,6 +20,7 @@
+
+ #include <QDateTime>
+ #include <QHash>
++#include <QObject>
+
+ #include "core/Uuid.h"
+ #include "keys/CompositeKey.h"
+diff --git a/src/core/DatabaseIcons.cpp b/src/core/DatabaseIcons.cpp
+index d6e816f..4e62f79 100644
+--- a/src/core/DatabaseIcons.cpp
++++ b/src/core/DatabaseIcons.cpp
+@@ -19,7 +19,7 @@
+
+ #include "core/FilePath.h"
+
+-DatabaseIcons* DatabaseIcons::m_instance(Q_NULLPTR);
++DatabaseIcons* DatabaseIcons::m_instance(nullptr);
+ const int DatabaseIcons::IconCount(69);
+ const int DatabaseIcons::ExpiredIconIndex(45);
+ const char* const DatabaseIcons::m_indexToName[] = {
+diff --git a/src/core/DatabaseIcons.h b/src/core/DatabaseIcons.h
+index 68d1e0c..a1d9480 100644
+--- a/src/core/DatabaseIcons.h
++++ b/src/core/DatabaseIcons.h
+@@ -23,8 +23,6 @@
+ #include <QPixmapCache>
+ #include <QVector>
+
+-#include "core/Global.h"
+-
+ class DatabaseIcons
+ {
+ public:
+diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp
+index 784b489..2fd52d0 100644
+--- a/src/core/Entry.cpp
++++ b/src/core/Entry.cpp
+@@ -21,7 +21,6 @@
+ #include "core/DatabaseIcons.h"
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+-#include "core/Tools.h"
+
+ const int Entry::DefaultIconNumber = 0;
+
+@@ -29,7 +28,7 @@ Entry::Entry()
+ : m_attributes(new EntryAttributes(this))
+ , m_attachments(new EntryAttachments(this))
+ , m_autoTypeAssociations(new AutoTypeAssociations(this))
+- , m_tmpHistoryItem(Q_NULLPTR)
++ , m_tmpHistoryItem(nullptr)
+ , m_modifiedSinceBegin(false)
+ , m_updateTimeinfo(true)
+ {
+@@ -74,8 +73,8 @@ template <class T> inline bool Entry::set(T& property, const T& value)
+ void Entry::updateTimeinfo()
+ {
+ if (m_updateTimeinfo) {
+- m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc());
+- m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc());
++ m_data.timeInfo.setLastModificationTime(QDateTime::currentDateTimeUtc());
++ m_data.timeInfo.setLastAccessTime(QDateTime::currentDateTimeUtc());
+ }
+ }
+
+@@ -223,7 +222,7 @@ QString Entry::notes() const
+
+ bool Entry::isExpired() const
+ {
+- return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc();
++ return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc();
+ }
+
+ EntryAttributes* Entry::attributes()
+@@ -474,7 +473,7 @@ Entry* Entry::clone(CloneFlags flags) const
+ entry->setUpdateTimeinfo(true);
+
+ if (flags & CloneResetTimeInfo) {
+- QDateTime now = Tools::currentDateTimeUtc();
++ QDateTime now = QDateTime::currentDateTimeUtc();
+ entry->m_data.timeInfo.setCreationTime(now);
+ entry->m_data.timeInfo.setLastModificationTime(now);
+ entry->m_data.timeInfo.setLastAccessTime(now);
+@@ -522,7 +521,7 @@ void Entry::endUpdate()
+ delete m_tmpHistoryItem;
+ }
+
+- m_tmpHistoryItem = Q_NULLPTR;
++ m_tmpHistoryItem = nullptr;
+ }
+
+ void Entry::updateModifiedSinceBegin()
+@@ -568,7 +567,7 @@ void Entry::setGroup(Group* group)
+ QObject::setParent(group);
+
+ if (m_updateTimeinfo) {
+- m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc());
++ m_data.timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc());
+ }
+ }
+
+@@ -583,7 +582,7 @@ const Database* Entry::database() const
+ return m_group->database();
+ }
+ else {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+diff --git a/src/core/Entry.h b/src/core/Entry.h
+index 3044dc8..cd7c7b7 100644
+--- a/src/core/Entry.h
++++ b/src/core/Entry.h
+@@ -29,7 +29,6 @@
+ #include "core/AutoTypeAssociations.h"
+ #include "core/EntryAttachments.h"
+ #include "core/EntryAttributes.h"
+-#include "core/Global.h"
+ #include "core/TimeInfo.h"
+ #include "core/Uuid.h"
+
+diff --git a/src/core/EntryAttachments.h b/src/core/EntryAttachments.h
+index 3446b31..903ca10 100644
+--- a/src/core/EntryAttachments.h
++++ b/src/core/EntryAttachments.h
+@@ -21,14 +21,12 @@
+ #include <QMap>
+ #include <QObject>
+
+-#include "core/Global.h"
+-
+ class EntryAttachments : public QObject
+ {
+ Q_OBJECT
+
+ public:
+- explicit EntryAttachments(QObject* parent = Q_NULLPTR);
++ explicit EntryAttachments(QObject* parent = nullptr);
+ QList<QString> keys() const;
+ bool hasKey(const QString& key) const;
+ QList<QByteArray> values() const;
+diff --git a/src/core/EntryAttributes.h b/src/core/EntryAttributes.h
+index 334eb0a..c6bbf29 100644
+--- a/src/core/EntryAttributes.h
++++ b/src/core/EntryAttributes.h
+@@ -23,14 +23,12 @@
+ #include <QSet>
+ #include <QStringList>
+
+-#include "core/Global.h"
+-
+ class EntryAttributes : public QObject
+ {
+ Q_OBJECT
+
+ public:
+- explicit EntryAttributes(QObject* parent = Q_NULLPTR);
++ explicit EntryAttributes(QObject* parent = nullptr);
+ QList<QString> keys() const;
+ bool hasKey(const QString& key) const;
+ QList<QString> customKeys();
+diff --git a/src/core/EntrySearcher.cpp b/src/core/EntrySearcher.cpp
+index 82a553e..05c4c58 100644
+--- a/src/core/EntrySearcher.cpp
++++ b/src/core/EntrySearcher.cpp
+@@ -19,7 +19,8 @@
+
+ #include "core/Group.h"
+
+-QList<Entry*> EntrySearcher::search(const QString &searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
++QList<Entry*> EntrySearcher::search(const QString& searchTerm, const Group* group,
++ Qt::CaseSensitivity caseSensitivity)
+ {
+ if (!group->resolveSearchingEnabled()) {
+ return QList<Entry*>();
+@@ -28,7 +29,8 @@ QList<Entry*> EntrySearcher::search(const QString &searchTerm, const Group* grou
+ return searchEntries(searchTerm, group, caseSensitivity);
+ }
+
+-QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
++QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Group* group,
++ Qt::CaseSensitivity caseSensitivity)
+ {
+ QList<Entry*> searchResult;
+
+@@ -44,7 +46,8 @@ QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Grou
+ return searchResult;
+ }
+
+-QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity)
++QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry,
++ Qt::CaseSensitivity caseSensitivity)
+ {
+ QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
+ Q_FOREACH (const QString& word, wordList) {
+diff --git a/src/core/EntrySearcher.h b/src/core/EntrySearcher.h
+index 246538c..c7075dc 100644
+--- a/src/core/EntrySearcher.h
++++ b/src/core/EntrySearcher.h
+@@ -28,10 +28,11 @@ class EntrySearcher
+ {
+ public:
+ QList<Entry*> search(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
++
+ private:
+ QList<Entry*> searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
+ QList<Entry*> matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity);
+- bool wordMatch(const QString &word, Entry *entry, Qt::CaseSensitivity caseSensitivity);
++ bool wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity);
+ };
+
+ #endif // KEEPASSX_ENTRYSEARCHER_H
+diff --git a/src/core/FilePath.cpp b/src/core/FilePath.cpp
+index f7c4075..497568a 100644
+--- a/src/core/FilePath.cpp
++++ b/src/core/FilePath.cpp
+@@ -23,7 +23,7 @@
+
+ #include "config-keepassx.h"
+
+-FilePath* FilePath::m_instance(Q_NULLPTR);
++FilePath* FilePath::m_instance(nullptr);
+
+ QString FilePath::dataPath(const QString& name)
+ {
+diff --git a/src/core/FilePath.h b/src/core/FilePath.h
+index 9e98d3e..c37a908 100644
+--- a/src/core/FilePath.h
++++ b/src/core/FilePath.h
+@@ -22,8 +22,6 @@
+ #include <QIcon>
+ #include <QString>
+
+-#include "core/Global.h"
+-
+ class FilePath
+ {
+ public:
+diff --git a/src/core/Global.h b/src/core/Global.h
+index 914c7b4..14281ee 100644
+--- a/src/core/Global.h
++++ b/src/core/Global.h
+@@ -20,104 +20,8 @@
+ #ifndef KEEPASSX_GLOBAL_H
+ #define KEEPASSX_GLOBAL_H
+
+-// mostly copied from qcompilerdetection.h which is part of Qt 5
+-
+ #include <QtGlobal>
+
+-#ifdef Q_CC_CLANG
+-# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
+-# if __has_feature(cxx_strong_enums)
+-# define COMPILER_CLASS_ENUM
+-# endif
+-# if __has_feature(cxx_constexpr)
+-# define COMPILER_CONSTEXPR
+-# endif
+-# if __has_feature(cxx_decltype) /* && __has_feature(cxx_decltype_incomplete_return_types) */
+-# define COMPILER_DECLTYPE
+-# endif
+-# if __has_feature(cxx_override_control)
+-# define COMPILER_EXPLICIT_OVERRIDES
+-# endif
+-# if __has_feature(cxx_nullptr)
+-# define COMPILER_NULLPTR
+-# endif
+-# if __has_feature(cxx_static_assert)
+-# define COMPILER_STATIC_ASSERT
+-# endif
+-# endif
+-#endif // Q_CC_CLANG
+-
+-#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
+-# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
+-# define COMPILER_DECLTYPE
+-# define COMPILER_STATIC_ASSERT
+-# endif
+-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404
+-# define COMPILER_CLASS_ENUM
+-# endif
+-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
+-# define COMPILER_CONSTEXPR
+-# define COMPILER_NULLPTR
+-# endif
+-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407
+-# define COMPILER_EXPLICIT_OVERRIDES
+-# endif
+-# endif
+-#endif
+-
+-/*
+- * C++11 keywords and expressions
+- */
+-#if !defined(Q_NULLPTR)
+-# ifdef COMPILER_NULLPTR
+-# define Q_NULLPTR nullptr
+-# else
+-# define Q_NULLPTR 0
+-# endif
+-#endif
+-
+-#if !defined(Q_DECL_CONSTEXPR)
+-# ifdef COMPILER_CONSTEXPR
+-# define Q_DECL_CONSTEXPR constexpr
+-# else
+-# define Q_DECL_CONSTEXPR
+-# endif
+-#endif
+-
+-#if !defined(Q_DECL_OVERRIDE) && !defined(Q_DECL_FINAL) && !defined(Q_DECL_FINAL_CLASS)
+-# ifdef COMPILER_EXPLICIT_OVERRIDES
+-# define Q_DECL_OVERRIDE override
+-# define Q_DECL_FINAL final
+-# ifdef COMPILER_DECLTYPE
+-# define Q_DECL_FINAL_CLASS final
+-# else
+-# define Q_DECL_FINAL_CLASS
+-# endif
+-# else
+-# define Q_DECL_OVERRIDE
+-# define Q_DECL_FINAL
+-# define Q_DECL_FINAL_CLASS
+-# endif
+-#endif
+-
+-#if !defined(Q_STATIC_ASSERT) && !defined(Q_STATIC_ASSERT_X)
+-#ifdef COMPILER_STATIC_ASSERT
+-#define Q_STATIC_ASSERT(Condition) static_assert(static_cast<bool>(Condition), #Condition)
+-#define Q_STATIC_ASSERT_X(Condition, Message) static_assert(static_cast<bool>(Condition), Message)
+-#else
+-// Intentionally undefined
+-template <bool Test> class QStaticAssertFailure;
+-template <> class QStaticAssertFailure<true> {};
+-
+-#define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B)
+-#define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B
+-#define Q_STATIC_ASSERT(Condition) \
+- enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) = sizeof(QStaticAssertFailure<!!(Condition)>)}
+-#define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
+-#endif // COMPILER_STATIC_ASSERT
+-#endif // !defined(Q_STATIC_ASSERT) && !defined(Q_STATIC_ASSERT_X)
+-
+ #if defined(Q_OS_WIN)
+ # if defined(KEEPASSX_BUILDING_CORE)
+ # define KEEPASSX_EXPORT Q_DECL_EXPORT
+diff --git a/src/core/Group.cpp b/src/core/Group.cpp
+index 371f3e4..2b9e9bc 100644
+--- a/src/core/Group.cpp
++++ b/src/core/Group.cpp
+@@ -20,7 +20,6 @@
+ #include "core/Config.h"
+ #include "core/DatabaseIcons.h"
+ #include "core/Metadata.h"
+-#include "core/Tools.h"
+
+ const int Group::DefaultIconNumber = 48;
+ const int Group::RecycleBinIconNumber = 43;
+@@ -50,7 +49,7 @@ Group::~Group()
+
+ if (m_db && m_parent) {
+ DeletedObject delGroup;
+- delGroup.deletionTime = Tools::currentDateTimeUtc();
++ delGroup.deletionTime = QDateTime::currentDateTimeUtc();
+ delGroup.uuid = m_uuid;
+ m_db->addDeletedObject(delGroup);
+ }
+@@ -84,8 +83,8 @@ template <class P, class V> inline bool Group::set(P& property, const V& value)
+ void Group::updateTimeinfo()
+ {
+ if (m_updateTimeinfo) {
+- m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc());
+- m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc());
++ m_data.timeInfo.setLastModificationTime(QDateTime::currentDateTimeUtc());
++ m_data.timeInfo.setLastAccessTime(QDateTime::currentDateTimeUtc());
+ }
+ }
+
+@@ -203,7 +202,7 @@ Entry* Group::lastTopVisibleEntry() const
+
+ bool Group::isExpired() const
+ {
+- return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc();
++ return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc();
+ }
+
+ void Group::setUuid(const Uuid& uuid)
+@@ -365,7 +364,7 @@ void Group::setParent(Group* parent, int index)
+ }
+
+ if (m_updateTimeinfo) {
+- m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc());
++ m_data.timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc());
+ }
+
+ Q_EMIT modified();
+@@ -385,7 +384,7 @@ void Group::setParent(Database* db)
+
+ cleanupParent();
+
+- m_parent = Q_NULLPTR;
++ m_parent = nullptr;
+ recSetDatabase(db);
+
+ QObject::setParent(db);
+@@ -510,7 +509,7 @@ Group* Group::clone(Entry::CloneFlags entryFlags) const
+
+ clonedGroup->setUpdateTimeinfo(true);
+
+- QDateTime now = Tools::currentDateTimeUtc();
++ QDateTime now = QDateTime::currentDateTimeUtc();
+ clonedGroup->m_data.timeInfo.setCreationTime(now);
+ clonedGroup->m_data.timeInfo.setLastModificationTime(now);
+ clonedGroup->m_data.timeInfo.setLastAccessTime(now);
+diff --git a/src/core/InactivityTimer.h b/src/core/InactivityTimer.h
+index e0a21e0..ba571a5 100644
+--- a/src/core/InactivityTimer.h
++++ b/src/core/InactivityTimer.h
+@@ -21,8 +21,6 @@
+ #include <QMutex>
+ #include <QObject>
+
+-#include "core/Global.h"
+-
+ class QTimer;
+
+ class InactivityTimer : public QObject
+@@ -30,7 +28,7 @@ class InactivityTimer : public QObject
+ Q_OBJECT
+
+ public:
+- explicit InactivityTimer(QObject* parent = Q_NULLPTR);
++ explicit InactivityTimer(QObject* parent = nullptr);
+ void setInactivityTimeout(int inactivityTimeout);
+ void activate();
+ void deactivate();
+diff --git a/src/core/Metadata.cpp b/src/core/Metadata.cpp
+index 0c67bba..a50c6ef 100644
+--- a/src/core/Metadata.cpp
++++ b/src/core/Metadata.cpp
+@@ -42,7 +42,7 @@ Metadata::Metadata(QObject* parent)
+ m_data.protectNotes = false;
+ // m_data.autoEnableVisualHiding = false;
+
+- QDateTime now = Tools::currentDateTimeUtc();
++ QDateTime now = QDateTime::currentDateTimeUtc();
+ m_data.nameChanged = now;
+ m_data.descriptionChanged = now;
+ m_data.defaultUserNameChanged = now;
+@@ -67,7 +67,7 @@ template <class P, class V> bool Metadata::set(P& property, const V& value, QDat
+ if (property != value) {
+ property = value;
+ if (m_updateDatetime) {
+- dateTime = Tools::currentDateTimeUtc();
++ dateTime = QDateTime::currentDateTimeUtc();
+ }
+ Q_EMIT modified();
+ return true;
+diff --git a/src/core/Metadata.h b/src/core/Metadata.h
+index 062e552..c35aed3 100644
+--- a/src/core/Metadata.h
++++ b/src/core/Metadata.h
+@@ -26,7 +26,6 @@
+ #include <QPixmapCache>
+ #include <QPointer>
+
+-#include "core/Global.h"
+ #include "core/Uuid.h"
+
+ class Database;
+@@ -37,7 +36,7 @@ class Metadata : public QObject
+ Q_OBJECT
+
+ public:
+- explicit Metadata(QObject* parent = Q_NULLPTR);
++ explicit Metadata(QObject* parent = nullptr);
+
+ struct MetadataData
+ {
+diff --git a/src/core/PasswordGenerator.h b/src/core/PasswordGenerator.h
+index 6a9d212..cc8196f 100644
+--- a/src/core/PasswordGenerator.h
++++ b/src/core/PasswordGenerator.h
+@@ -22,8 +22,6 @@
+ #include <QString>
+ #include <QVector>
+
+-#include "core/Global.h"
+-
+ typedef QVector<QChar> PasswordGroup;
+
+ class PasswordGenerator
+diff --git a/src/core/SignalMultiplexer.cpp b/src/core/SignalMultiplexer.cpp
+index a70e9ef..ebf38bf 100644
+--- a/src/core/SignalMultiplexer.cpp
++++ b/src/core/SignalMultiplexer.cpp
+@@ -24,7 +24,7 @@ SignalMultiplexer::SignalMultiplexer()
+ SignalMultiplexer::~SignalMultiplexer()
+ {
+ // disconnect all connections
+- setCurrentObject(Q_NULLPTR);
++ setCurrentObject(nullptr);
+ }
+
+ QObject* SignalMultiplexer::currentObject() const
+diff --git a/src/core/SignalMultiplexer.h b/src/core/SignalMultiplexer.h
+index 6d39cd5..b27e1f3 100644
+--- a/src/core/SignalMultiplexer.h
++++ b/src/core/SignalMultiplexer.h
+@@ -21,8 +21,6 @@
+ #include <QObject>
+ #include <QPointer>
+
+-#include "core/Global.h"
+-
+ class SignalMultiplexer
+ {
+ public:
+diff --git a/src/core/TimeInfo.cpp b/src/core/TimeInfo.cpp
+index 2613325..ec6ebde 100644
+--- a/src/core/TimeInfo.cpp
++++ b/src/core/TimeInfo.cpp
+@@ -23,7 +23,7 @@ TimeInfo::TimeInfo()
+ : m_expires(false)
+ , m_usageCount(0)
+ {
+- QDateTime now = Tools::currentDateTimeUtc();
++ QDateTime now = QDateTime::currentDateTimeUtc();
+ m_lastModificationTime = now;
+ m_creationTime = now;
+ m_lastAccessTime = now;
+diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp
+index db3baa8..06eb73d 100644
+--- a/src/core/Tools.cpp
++++ b/src/core/Tools.cpp
+@@ -23,11 +23,7 @@
+ #include <QLocale>
+ #include <QStringList>
+
+-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ #include <QElapsedTimer>
+-#else
+-#include <QTime>
+-#endif
+
+ #ifdef Q_OS_WIN
+ #include <windows.h> // for Sleep(), SetDllDirectoryA() and SetSearchPathMode()
+@@ -122,15 +118,6 @@ bool readAllFromDevice(QIODevice* device, QByteArray& data)
+ }
+ }
+
+-QDateTime currentDateTimeUtc()
+-{
+-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+- return QDateTime::currentDateTimeUtc();
+-#else
+- return QDateTime::currentDateTime().toUTC();
+-#endif
+-}
+-
+ QString imageReaderFilter()
+ {
+ QList<QByteArray> formats = QImageReader::supportedImageFormats();
+@@ -184,7 +171,7 @@ void sleep(int ms)
+ timespec ts;
+ ts.tv_sec = ms / 1000;
+ ts.tv_nsec = (ms % 1000) * 1000 * 1000;
+- nanosleep(&ts, Q_NULLPTR);
++ nanosleep(&ts, nullptr);
+ #endif
+ }
+
+@@ -196,11 +183,7 @@ void wait(int ms)
+ return;
+ }
+
+-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ QElapsedTimer timer;
+-#else
+- QTime timer;
+-#endif
+ timer.start();
+
+ if (ms <= 50) {
+@@ -215,23 +198,10 @@ void wait(int ms)
+ QCoreApplication::processEvents(QEventLoop::AllEvents, timeLeft);
+ sleep(10);
+ }
+- } while (timer.elapsed() < ms);
++ } while (!timer.hasExpired(ms));
+ }
+ }
+
+-QString platform()
+-{
+-#if defined(Q_WS_X11)
+- return "x11";
+-#elif defined(Q_WS_MAC)
+- return "mac";
+-#elif defined(Q_WS_WIN)
+- return "win";
+-#else
+- return QString();
+-#endif
+-}
+-
+ void disableCoreDumps()
+ {
+ // default to true
+diff --git a/src/core/Tools.h b/src/core/Tools.h
+index 68e9dcd..65df1ea 100644
+--- a/src/core/Tools.h
++++ b/src/core/Tools.h
+@@ -18,11 +18,13 @@
+ #ifndef KEEPASSX_TOOLS_H
+ #define KEEPASSX_TOOLS_H
+
++#include "core/Global.h"
++
+ #include <QDateTime>
+ #include <QObject>
+ #include <QString>
+
+-#include "core/Global.h"
++#include <algorithm>
+
+ class QIODevice;
+
+@@ -32,16 +34,27 @@ QString humanReadableFileSize(qint64 bytes);
+ bool hasChild(const QObject* parent, const QObject* child);
+ bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384);
+ bool readAllFromDevice(QIODevice* device, QByteArray& data);
+-QDateTime currentDateTimeUtc();
+ QString imageReaderFilter();
+ bool isHex(const QByteArray& ba);
+ bool isBase64(const QByteArray& ba);
+ void sleep(int ms);
+ void wait(int ms);
+-QString platform();
+ void disableCoreDumps();
+ void setupSearchPaths();
+
++template <typename RandomAccessIterator, typename T>
++RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value)
++{
++ RandomAccessIterator it = std::lower_bound(begin, end, value);
++
++ if ((it == end) || (value < *it)) {
++ return end;
++ }
++ else {
++ return it;
++ }
++}
++
+ } // namespace Tools
+
+ #endif // KEEPASSX_TOOLS_H
+diff --git a/src/core/qcommandlineoption.cpp b/src/core/qcommandlineoption.cpp
+deleted file mode 100644
+index c908807..0000000
+--- a/src/core/qcommandlineoption.cpp
++++ /dev/null
+@@ -1,305 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+-** Copyright (C) 2013 David Faure <faure@kde.org>
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.LGPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU Lesser General Public License version 2.1 requirements
+-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU
+-** General Public License version 3.0 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.GPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU General Public License version 3.0 requirements will be
+-** met: http://www.gnu.org/copyleft/gpl.html.
+-**
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#include "qcommandlineoption.h"
+-
+-#include <QSet>
+-
+-class QCommandLineOptionPrivate : public QSharedData
+-{
+-public:
+- inline QCommandLineOptionPrivate()
+- { }
+-
+- void setNames(const QStringList &nameList);
+-
+- //! The list of names used for this option.
+- QStringList names;
+-
+- //! The documentation name for the value, if one is expected
+- //! Example: "-o <file>" means valueName == "file"
+- QString valueName;
+-
+- //! The description used for this option.
+- QString description;
+-
+- //! The list of default values used for this option.
+- QStringList defaultValues;
+-};
+-
+-/*!
+- \since 5.2
+- \class QCommandLineOption
+- \brief The QCommandLineOption class defines a possible command-line option.
+- \inmodule QtCore
+- \ingroup shared
+- \ingroup tools
+-
+- This class is used to describe an option on the command line. It allows
+- different ways of defining the same option with multiple aliases possible.
+- It is also used to describe how the option is used - it may be a flag (e.g. \c{-v})
+- or take an argument (e.g. \c{-o file}).
+-
+- Examples:
+- \snippet code/src_corelib_tools_qcommandlineoption.cpp 0
+-
+- \sa QCommandLineParser
+-*/
+-
+-/*!
+- Constructs a command line option object with the given arguments.
+-
+- The name of the option is set to \a name.
+- The name can be either short or long. If the name is one character in
+- length, it is considered a short name. Option names must not be empty,
+- must not start with a dash or a slash character, must not contain a \c{=}
+- and cannot be repeated.
+-
+- The description is set to \a description. It is customary to add a "."
+- at the end of the description.
+-
+- In addition, the \a valueName can be set if the option expects a value.
+- The default value for the option is set to \a defaultValue.
+-
+- \sa setDescription(), setValueName(), setDefaultValues()
+-*/
+-QCommandLineOption::QCommandLineOption(const QString &name, const QString &description,
+- const QString &valueName,
+- const QString &defaultValue)
+- : d(new QCommandLineOptionPrivate)
+-{
+- d->setNames(QStringList(name));
+- setValueName(valueName);
+- setDescription(description);
+- setDefaultValue(defaultValue);
+-}
+-
+-/*!
+- Constructs a command line option object with the given arguments.
+-
+- This overload allows to set multiple names for the option, for instance
+- \c{o} and \c{output}.
+-
+- The names of the option are set to \a names.
+- The names can be either short or long. Any name in the list that is one
+- character in length is a short name. Option names must not be empty,
+- must not start with a dash or a slash character, must not contain a \c{=}
+- and cannot be repeated.
+-
+- The description is set to \a description. It is customary to add a "."
+- at the end of the description.
+-
+- In addition, the \a valueName can be set if the option expects a value.
+- The default value for the option is set to \a defaultValue.
+-
+- \sa setDescription(), setValueName(), setDefaultValues()
+-*/
+-QCommandLineOption::QCommandLineOption(const QStringList &names, const QString &description,
+- const QString &valueName,
+- const QString &defaultValue)
+- : d(new QCommandLineOptionPrivate)
+-{
+- d->setNames(names);
+- setValueName(valueName);
+- setDescription(description);
+- setDefaultValue(defaultValue);
+-}
+-
+-/*!
+- Constructs a QCommandLineOption object that is a copy of the QCommandLineOption
+- object \a other.
+-
+- \sa operator=()
+-*/
+-QCommandLineOption::QCommandLineOption(const QCommandLineOption &other)
+- : d(other.d)
+-{
+-}
+-
+-/*!
+- Destroys the command line option object.
+-*/
+-QCommandLineOption::~QCommandLineOption()
+-{
+-}
+-
+-/*!
+- Makes a copy of the \a other object and assigns it to this QCommandLineOption
+- object.
+-*/
+-QCommandLineOption &QCommandLineOption::operator=(const QCommandLineOption &other)
+-{
+- d = other.d;
+- return *this;
+-}
+-
+-/*!
+- Returns the names set for this option.
+- */
+-QStringList QCommandLineOption::names() const
+-{
+- return d->names;
+-}
+-
+-void QCommandLineOptionPrivate::setNames(const QStringList &nameList)
+-{
+- QStringList newNames;
+- if (nameList.isEmpty())
+- qWarning("QCommandLineOption: Options must have at least one name");
+- Q_FOREACH (const QString &name, nameList) {
+- if (name.isEmpty()) {
+- qWarning("QCommandLineOption: Option names cannot be empty");
+- } else {
+- const QChar c = name.at(0);
+- if (c == QLatin1Char('-'))
+- qWarning("QCommandLineOption: Option names cannot start with a '-'");
+- else if (c == QLatin1Char('/'))
+- qWarning("QCommandLineOption: Option names cannot start with a '/'");
+- else if (name.contains(QLatin1Char('=')))
+- qWarning("QCommandLineOption: Option names cannot contain a '='");
+- else
+- newNames.append(name);
+- }
+- }
+- // commit
+- names = newNames;
+-}
+-
+-/*!
+- Sets the name of the expected value, for the documentation, to \a valueName.
+-
+- Options without a value assigned have a boolean-like behavior:
+- either the user specifies --option or they don't.
+-
+- Options with a value assigned need to set a name for the expected value,
+- for the documentation of the option in the help output. An option with names \c{o} and \c{output},
+- and a value name of \c{file} will appear as \c{-o, --output <file>}.
+-
+- Call QCommandLineParser::argument() if you expect the option to be present
+- only once, and QCommandLineParser::arguments() if you expect that option
+- to be present multiple times.
+-
+- \sa valueName()
+- */
+-void QCommandLineOption::setValueName(const QString &valueName)
+-{
+- d->valueName = valueName;
+-}
+-
+-/*!
+- Returns the name of the expected value.
+-
+- If empty, the option doesn't take a value.
+-
+- \sa setValueName()
+- */
+-QString QCommandLineOption::valueName() const
+-{
+- return d->valueName;
+-}
+-
+-/*!
+- Sets the description used for this option to \a description.
+-
+- It is customary to add a "." at the end of the description.
+-
+- The description is used by QCommandLineParser::showHelp().
+-
+- \sa description()
+- */
+-void QCommandLineOption::setDescription(const QString &description)
+-{
+- d->description = description;
+-}
+-
+-/*!
+- Returns the description set for this option.
+-
+- \sa setDescription()
+- */
+-QString QCommandLineOption::description() const
+-{
+- return d->description;
+-}
+-
+-/*!
+- Sets the default value used for this option to \a defaultValue.
+-
+- The default value is used if the user of the application does not specify
+- the option on the command line.
+-
+- If \a defaultValue is empty, the option has no default values.
+-
+- \sa defaultValues() setDefaultValues()
+- */
+-void QCommandLineOption::setDefaultValue(const QString &defaultValue)
+-{
+- QStringList newDefaultValues;
+- if (!defaultValue.isEmpty()) {
+- newDefaultValues << defaultValue;
+- }
+- // commit:
+- d->defaultValues = newDefaultValues;
+-}
+-
+-/*!
+- Sets the list of default values used for this option to \a defaultValues.
+-
+- The default values are used if the user of the application does not specify
+- the option on the command line.
+-
+- \sa defaultValues() setDefaultValue()
+- */
+-void QCommandLineOption::setDefaultValues(const QStringList &defaultValues)
+-{
+- d->defaultValues = defaultValues;
+-}
+-
+-/*!
+- Returns the default values set for this option.
+-
+- \sa setDefaultValues()
+- */
+-QStringList QCommandLineOption::defaultValues() const
+-{
+- return d->defaultValues;
+-}
+diff --git a/src/core/qcommandlineoption.h b/src/core/qcommandlineoption.h
+deleted file mode 100644
+index b97d44c..0000000
+--- a/src/core/qcommandlineoption.h
++++ /dev/null
+@@ -1,81 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.LGPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU Lesser General Public License version 2.1 requirements
+-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU
+-** General Public License version 3.0 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.GPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU General Public License version 3.0 requirements will be
+-** met: http://www.gnu.org/copyleft/gpl.html.
+-**
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#ifndef QCOMMANDLINEOPTION_H
+-#define QCOMMANDLINEOPTION_H
+-
+-#include <QStringList>
+-#include <QSharedData>
+-
+-class QCommandLineOptionPrivate;
+-
+-class QCommandLineOption
+-{
+-public:
+- explicit QCommandLineOption(const QString &name, const QString &description = QString(),
+- const QString &valueName = QString(),
+- const QString &defaultValue = QString());
+- explicit QCommandLineOption(const QStringList &names, const QString &description = QString(),
+- const QString &valueName = QString(),
+- const QString &defaultValue = QString());
+- QCommandLineOption(const QCommandLineOption &other);
+-
+- ~QCommandLineOption();
+-
+- QCommandLineOption &operator=(const QCommandLineOption &other);
+-
+- QStringList names() const;
+-
+- void setValueName(const QString &name);
+- QString valueName() const;
+-
+- void setDescription(const QString &description);
+- QString description() const;
+-
+- void setDefaultValue(const QString &defaultValue);
+- void setDefaultValues(const QStringList &defaultValues);
+- QStringList defaultValues() const;
+-
+-private:
+- QSharedDataPointer<QCommandLineOptionPrivate> d;
+-};
+-
+-#endif // QCOMMANDLINEOPTION_H
+diff --git a/src/core/qcommandlineparser.cpp b/src/core/qcommandlineparser.cpp
+deleted file mode 100644
+index f97d78a..0000000
+--- a/src/core/qcommandlineparser.cpp
++++ /dev/null
+@@ -1,944 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+-** Copyright (C) 2013 David Faure <faure@kde.org>
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.LGPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU Lesser General Public License version 2.1 requirements
+-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU
+-** General Public License version 3.0 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.GPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU General Public License version 3.0 requirements will be
+-** met: http://www.gnu.org/copyleft/gpl.html.
+-**
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#include "qcommandlineparser.h"
+-
+-#include <QCoreApplication>
+-#include <QHash>
+-#include <QVector>
+-#include <stdio.h>
+-#include <stdlib.h>
+-
+-typedef QHash<QString, int> NameHash_t;
+-
+-class QCommandLineParserPrivate
+-{
+-public:
+- inline QCommandLineParserPrivate()
+- : singleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions),
+- builtinVersionOption(false),
+- builtinHelpOption(false),
+- needsParsing(true)
+- { }
+-
+- bool parse(const QStringList &args);
+- void checkParsed(const char *method);
+- QStringList aliases(const QString &name) const;
+- QString helpText() const;
+- bool registerFoundOption(const QString &optionName);
+- bool parseOptionValue(const QString &optionName, const QString &argument,
+- QStringList::const_iterator *argumentIterator,
+- QStringList::const_iterator argsEnd);
+-
+- //! Error text set when parse() returns false
+- QString errorText;
+-
+- //! The command line options used for parsing
+- QList<QCommandLineOption> commandLineOptionList;
+-
+- //! Hash mapping option names to their offsets in commandLineOptionList and optionArgumentList.
+- NameHash_t nameHash;
+-
+- //! Option values found (only for options with a value)
+- QHash<int, QStringList> optionValuesHash;
+-
+- //! Names of options found on the command line.
+- QStringList optionNames;
+-
+- //! Arguments which did not belong to any option.
+- QStringList positionalArgumentList;
+-
+- //! Names of options which were unknown.
+- QStringList unknownOptionNames;
+-
+- //! Application description
+- QString description;
+-
+- //! Documentation for positional arguments
+- struct PositionalArgumentDefinition
+- {
+- QString name;
+- QString description;
+- QString syntax;
+- };
+- QVector<PositionalArgumentDefinition> positionalArgumentDefinitions;
+-
+- //! The parsing mode for "-abc"
+- QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode;
+-
+- //! Whether addVersionOption was called
+- bool builtinVersionOption;
+-
+- //! Whether addHelpOption was called
+- bool builtinHelpOption;
+-
+- //! True if parse() needs to be called
+- bool needsParsing;
+-};
+-
+-QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
+-{
+- const NameHash_t::const_iterator it = nameHash.find(optionName);
+- if (it == nameHash.end()) {
+- qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
+- return QStringList();
+- }
+- return commandLineOptionList.at(*it).names();
+-}
+-
+-/*!
+- \since 5.2
+- \class QCommandLineParser
+- \inmodule QtCore
+- \ingroup tools
+-
+- \brief The QCommandLineParser class provides a means for handling the
+- command line options.
+-
+- QCoreApplication provides the command-line arguments as a simple list of strings.
+- QCommandLineParser provides the ability to define a set of options, parse the
+- command-line arguments, and store which options have actually been used, as
+- well as option values.
+-
+- Any argument that isn't an option (i.e. doesn't start with a \c{-}) is stored
+- as a "positional argument".
+-
+- The parser handles short names, long names, more than one name for the same
+- option, and option values.
+-
+- Options on the command line are recognized as starting with a single or
+- double \c{-} character(s).
+- The option \c{-} (single dash alone) is a special case, often meaning standard
+- input, and not treated as an option. The parser will treat everything after the
+- option \c{--} (double dash) as positional arguments.
+-
+- Short options are single letters. The option \c{v} would be specified by
+- passing \c{-v} on the command line. In the default parsing mode, short options
+- can be written in a compact form, for instance \c{-abc} is equivalent to \c{-a -b -c}.
+- The parsing mode for can be set to ParseAsLongOptions, in which case \c{-abc}
+- will be parsed as the long option \c{abc}.
+-
+- Long options are more than one letter long and cannot be compacted together.
+- The long option \c{verbose} would be passed as \c{--verbose} or \c{-verbose}.
+-
+- Passing values to options can be done using the assignment operator: \c{-v=value}
+- \c{--verbose=value}, or a space: \c{-v value} \c{--verbose value}, i.e. the next
+- argument is used as value (even if it starts with a \c{-}).
+-
+- The parser does not support optional values - if an option is set to
+- require a value, one must be present. If such an option is placed last
+- and has no value, the option will be treated as if it had not been
+- specified.
+-
+- The parser does not automatically support negating or disabling long options
+- by using the format \c{--disable-option} or \c{--no-option}. However, it is
+- possible to handle this case explicitly by making an option with \c{no-option}
+- as one of its names, and handling the option explicitly.
+-
+- Example:
+- \snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
+-
+- Known limitation: the parsing of Qt options inside QCoreApplication and subclasses
+- happens before QCommandLineParser exists, so it can't take it into account. This
+- means any option value that looks like a builtin Qt option, will be treated by
+- QCoreApplication as a builtin Qt option. Example: \c{--profile -reverse} will
+- lead to QGuiApplication seeing the -reverse option set, and removing it from
+- QCoreApplication::arguments() before QCommandLineParser defines the \c{profile}
+- option and parses the command line.
+-
+- \sa QCommandLineOption, QCoreApplication
+-*/
+-
+-/*!
+- Constructs a command line parser object.
+-*/
+-QCommandLineParser::QCommandLineParser()
+- : d(new QCommandLineParserPrivate)
+-{
+-}
+-
+-/*!
+- Destroys the command line parser object.
+-*/
+-QCommandLineParser::~QCommandLineParser()
+-{
+- delete d;
+-}
+-
+-/*!
+- \enum QCommandLineParser::SingleDashWordOptionMode
+-
+- This enum describes the way the parser interprets command-line
+- options that use a single dash followed by multiple letters, as as \c{-abc}.
+-
+- \value ParseAsCompactedShortOptions \c{-abc} is interpreted as \c{-a -b -c},
+- i.e. as three short options that have been compacted on the command-line,
+- if none of the options take a value. If \c{a} takes a value, then it
+- is interpreted as \c{-a bc}, i.e. the short option \c{a} followed by the value \c{bc}.
+- This is typically used in tools that behave like compilers, in order
+- to handle options such as \c{-DDEFINE=VALUE} or \c{-I/include/path}.
+- This is the default parsing mode. New applications are recommended to
+- use this mode.
+-
+- \value ParseAsLongOptions \c{-abc} is interpreted as \c{--abc},
+- i.e. as the long option named \c{abc}. This is how Qt's own tools
+- (uic, rcc...) have always been parsing arguments. This mode should be
+- used for preserving compatibility in applications that were parsing
+- arguments in such a way.
+-
+- \sa setSingleDashWordOptionMode()
+-*/
+-
+-/*!
+- Sets the parsing mode to \a singleDashWordOptionMode.
+- This must be called before process() or parse().
+-*/
+-void QCommandLineParser::setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode)
+-{
+- d->singleDashWordOptionMode = singleDashWordOptionMode;
+-}
+-
+-/*!
+- Adds the option \a option to look for while parsing.
+-
+- Returns \c true if adding the option was successful; otherwise returns \c false.
+-
+- Adding the option fails if there is no name attached to the option, or
+- the option has a name that clashes with an option name added before.
+- */
+-bool QCommandLineParser::addOption(const QCommandLineOption &option)
+-{
+- QStringList optionNames = option.names();
+-
+- if (!optionNames.isEmpty()) {
+- Q_FOREACH (const QString &name, optionNames) {
+- if (d->nameHash.contains(name))
+- return false;
+- }
+-
+- d->commandLineOptionList.append(option);
+-
+- const int offset = d->commandLineOptionList.size() - 1;
+- Q_FOREACH (const QString &name, optionNames)
+- d->nameHash.insert(name, offset);
+-
+- return true;
+- }
+-
+- return false;
+-}
+-
+-/*!
+- Adds the \c{-v} / \c{--version} option, which displays the version string of the application.
+-
+- This option is handled automatically by QCommandLineParser.
+-
+- You can set the actual version string by using QCoreApplication::setApplicationVersion().
+-
+- Returns the option instance, which can be used to call isSet().
+-*/
+-QCommandLineOption QCommandLineParser::addVersionOption()
+-{
+- QCommandLineOption opt(QStringList() << "v" << "version", tr("Displays version information."));
+- addOption(opt);
+- d->builtinVersionOption = true;
+- return opt;
+-}
+-
+-/*!
+- Adds the help option (\c{-h}, \c{--help} and \c{-?} on Windows)
+- This option is handled automatically by QCommandLineParser.
+-
+- Remember to use setApplicationDescription to set the application description,
+- which will be displayed when this option is used.
+-
+- Example:
+- \snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
+-
+- Returns the option instance, which can be used to call isSet().
+-*/
+-QCommandLineOption QCommandLineParser::addHelpOption()
+-{
+- QCommandLineOption opt(QStringList()
+-#ifdef Q_OS_WIN
+- << "?"
+-#endif
+- << "h"
+- << "help", tr("Displays this help."));
+- addOption(opt);
+- d->builtinHelpOption = true;
+- return opt;
+-}
+-
+-/*!
+- Sets the application \a description shown by helpText().
+-*/
+-void QCommandLineParser::setApplicationDescription(const QString &description)
+-{
+- d->description = description;
+-}
+-
+-/*!
+- Returns the application description set in setApplicationDescription().
+-*/
+-QString QCommandLineParser::applicationDescription() const
+-{
+- return d->description;
+-}
+-
+-/*!
+- Defines an additional argument to the application, for the benefit of the help text.
+-
+- The argument \a name and \a description will appear under the \c{Arguments:} section
+- of the help. If \a syntax is specified, it will be appended to the Usage line, otherwise
+- the \a name will be appended.
+-
+- Example:
+- \snippet code/src_corelib_tools_qcommandlineparser.cpp 2
+-
+- \sa addHelpOption(), helpText()
+-*/
+-void QCommandLineParser::addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
+-{
+- QCommandLineParserPrivate::PositionalArgumentDefinition arg;
+- arg.name = name;
+- arg.description = description;
+- arg.syntax = syntax.isEmpty() ? name : syntax;
+- d->positionalArgumentDefinitions.append(arg);
+-}
+-
+-/*!
+- Clears the definitions of additional arguments from the help text.
+-
+- This is only needed for the special case of tools which support multiple commands
+- with different options. Once the actual command has been identified, the options
+- for this command can be defined, and the help text for the command can be adjusted
+- accordingly.
+-
+- Example:
+- \snippet code/src_corelib_tools_qcommandlineparser.cpp 3
+-*/
+-void QCommandLineParser::clearPositionalArguments()
+-{
+- d->positionalArgumentDefinitions.clear();
+-}
+-
+-/*!
+- Parses the command line \a arguments.
+-
+- Most programs don't need to call this, a simple call to process() is enough.
+-
+- parse() is more low-level, and only does the parsing. The application will have to
+- take care of the error handling, using errorText() if parse() returns \c false.
+- This can be useful for instance to show a graphical error message in graphical programs.
+-
+- Calling parse() instead of process() can also be useful in order to ignore unknown
+- options temporarily, because more option definitions will be provided later on
+- (depending on one of the arguments), before calling process().
+-
+- Don't forget that \a arguments must start with the name of the executable (ignored, though).
+-
+- Returns \c false in case of a parse error (unknown option or missing value); returns \c true otherwise.
+-
+- \sa process()
+-*/
+-bool QCommandLineParser::parse(const QStringList &arguments)
+-{
+- return d->parse(arguments);
+-}
+-
+-/*!
+- Returns a translated error text for the user.
+- This should only be called when parse() returns \c false.
+-*/
+-QString QCommandLineParser::errorText() const
+-{
+- if (!d->errorText.isEmpty())
+- return d->errorText;
+- if (d->unknownOptionNames.count() == 1)
+- return tr("Unknown option '%1'.").arg(d->unknownOptionNames.first());
+- if (d->unknownOptionNames.count() > 1)
+- return tr("Unknown options: %1.").arg(d->unknownOptionNames.join(", "));
+- return QString();
+-}
+-
+-/*!
+- Processes the command line \a arguments.
+-
+- In addition to parsing the options (like parse()), this function also handles the builtin
+- options and handles errors.
+-
+- The builtin options are \c{--version} if addVersionOption was called and \c{--help} if addHelpOption was called.
+-
+- When invoking one of these options, or when an error happens (for instance an unknown option was
+- passed), the current process will then stop, using the exit() function.
+-
+- \sa QCoreApplication::arguments(), parse()
+- */
+-void QCommandLineParser::process(const QStringList &arguments)
+-{
+- if (!d->parse(arguments)) {
+- fprintf(stderr, "%s\n", qPrintable(errorText()));
+- ::exit(EXIT_FAILURE);
+- }
+-
+- if (d->builtinVersionOption && isSet("version")) {
+- printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
+- ::exit(EXIT_SUCCESS);
+- }
+-
+- if (d->builtinHelpOption && isSet("help"))
+- showHelp(EXIT_SUCCESS);
+-}
+-
+-/*!
+- \overload
+-
+- The command line is obtained from the QCoreApplication instance \a app.
+- */
+-void QCommandLineParser::process(const QCoreApplication &app)
+-{
+- // QCoreApplication::arguments() is static, but the app instance must exist so we require it as parameter
+- Q_UNUSED(app);
+- process(QCoreApplication::arguments());
+-}
+-
+-void QCommandLineParserPrivate::checkParsed(const char *method)
+-{
+- if (needsParsing)
+- qWarning("QCommandLineParser: call process() or parse() before %s", method);
+-}
+-
+-/*!
+- \internal
+- Looks up the option \a optionName (found on the command line) and register it as found.
+- Returns \c true on success.
+- */
+-bool QCommandLineParserPrivate::registerFoundOption(const QString &optionName)
+-{
+- if (nameHash.contains(optionName)) {
+- optionNames.append(optionName);
+- return true;
+- } else {
+- unknownOptionNames.append(optionName);
+- return false;
+- }
+-}
+-
+-/*!
+- \internal
+- \brief Parse the value for a given option, if it was defined to expect one.
+-
+- The value is taken from the next argument, or after the equal sign in \a argument.
+-
+- \param optionName the short option name
+- \param argument the argument from the command line currently parsed. Only used for -k=value parsing.
+- \param argumentIterator iterator to the currently parsed argument. Incremented if the next argument contains the value.
+- \param argsEnd args.end(), to check if ++argumentIterator goes out of bounds
+- Returns \c true on success.
+- */
+-bool QCommandLineParserPrivate::parseOptionValue(const QString &optionName, const QString &argument,
+- QStringList::const_iterator *argumentIterator, QStringList::const_iterator argsEnd)
+-{
+- const QLatin1Char assignChar('=');
+- const NameHash_t::const_iterator nameHashIt = nameHash.constFind(optionName);
+- if (nameHashIt != nameHash.constEnd()) {
+- const int assignPos = argument.indexOf(assignChar);
+- const NameHash_t::mapped_type optionOffset = *nameHashIt;
+- const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty();
+- if (withValue) {
+- if (assignPos == -1) {
+- ++(*argumentIterator);
+- if (*argumentIterator == argsEnd) {
+- errorText = QCommandLineParser::tr("Missing value after '%1'.").arg(argument);
+- return false;
+- }
+- optionValuesHash[optionOffset].append(*(*argumentIterator));
+- } else {
+- optionValuesHash[optionOffset].append(argument.mid(assignPos + 1));
+- }
+- } else {
+- if (assignPos != -1) {
+- errorText = QCommandLineParser::tr("Unexpected value after '%1'.").arg(argument.left(assignPos));
+- return false;
+- }
+- }
+- }
+- return true;
+-}
+-
+-/*!
+- \internal
+-
+- Parse the list of arguments \a args, and fills in
+- optionNames, optionValuesHash, unknownOptionNames, positionalArguments, and errorText.
+-
+- Any results from a previous parse operation are removed.
+-
+- The parser will not look for further options once it encounters the option
+- \c{--}; this does not include when \c{--} follows an option that requires a value.
+- */
+-bool QCommandLineParserPrivate::parse(const QStringList &args)
+-{
+- needsParsing = false;
+- bool error = false;
+-
+- const QString doubleDashString("--");
+- const QLatin1Char dashChar('-');
+- const QLatin1Char assignChar('=');
+-
+- bool doubleDashFound = false;
+- errorText.clear();
+- positionalArgumentList.clear();
+- optionNames.clear();
+- unknownOptionNames.clear();
+- optionValuesHash.clear();
+-
+- if (args.isEmpty()) {
+- qWarning("QCommandLineParser: argument list cannot be empty, it should contain at least the executable name");
+- return false;
+- }
+-
+- QStringList::const_iterator argumentIterator = args.begin();
+- ++argumentIterator; // skip executable name
+-
+- for (; argumentIterator != args.end() ; ++argumentIterator) {
+- QString argument = *argumentIterator;
+-
+- if (doubleDashFound) {
+- positionalArgumentList.append(argument);
+- } else if (argument.startsWith(doubleDashString)) {
+- if (argument.length() > 2) {
+- QString optionName = argument.mid(2).section(assignChar, 0, 0);
+- if (registerFoundOption(optionName)) {
+- if (!parseOptionValue(optionName, argument, &argumentIterator, args.end()))
+- error = true;
+- } else {
+- error = true;
+- }
+- } else {
+- doubleDashFound = true;
+- }
+- } else if (argument.startsWith(dashChar)) {
+- if (argument.size() == 1) { // single dash ("stdin")
+- positionalArgumentList.append(argument);
+- continue;
+- }
+- switch (singleDashWordOptionMode) {
+- case QCommandLineParser::ParseAsCompactedShortOptions:
+- {
+- QString optionName;
+- bool valueFound = false;
+- for (int pos = 1 ; pos < argument.size(); ++pos) {
+- optionName = argument.mid(pos, 1);
+- if (!registerFoundOption(optionName)) {
+- error = true;
+- } else {
+- const NameHash_t::const_iterator nameHashIt = nameHash.constFind(optionName);
+- Q_ASSERT(nameHashIt != nameHash.constEnd()); // checked by registerFoundOption
+- const NameHash_t::mapped_type optionOffset = *nameHashIt;
+- const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty();
+- if (withValue) {
+- if (pos + 1 < argument.size()) {
+- if (argument.at(pos + 1) == assignChar)
+- ++pos;
+- optionValuesHash[optionOffset].append(argument.mid(pos + 1));
+- valueFound = true;
+- }
+- break;
+- }
+- if (pos + 1 < argument.size() && argument.at(pos + 1) == assignChar)
+- break;
+- }
+- }
+- if (!valueFound && !parseOptionValue(optionName, argument, &argumentIterator, args.end()))
+- error = true;
+- break;
+- }
+- case QCommandLineParser::ParseAsLongOptions:
+- {
+- const QString optionName = argument.mid(1).section(assignChar, 0, 0);
+- if (registerFoundOption(optionName)) {
+- if (!parseOptionValue(optionName, argument, &argumentIterator, args.end()))
+- error = true;
+- } else {
+- error = true;
+- }
+- break;
+- }
+- }
+- } else {
+- positionalArgumentList.append(argument);
+- }
+- if (argumentIterator == args.end())
+- break;
+- }
+- return !error;
+-}
+-
+-/*!
+- Checks whether the option \a name was passed to the application.
+-
+- Returns \c true if the option \a name was set, false otherwise.
+-
+- The name provided can be any long or short name of any option that was
+- added with \c addOption(). All the options names are treated as being
+- equivalent. If the name is not recognized or that option was not present,
+- false is returned.
+-
+- Example:
+- \snippet code/src_corelib_tools_qcommandlineparser.cpp 0
+- */
+-
+-bool QCommandLineParser::isSet(const QString &name) const
+-{
+- d->checkParsed("isSet");
+- if (d->optionNames.contains(name))
+- return true;
+- const QStringList aliases = d->aliases(name);
+- Q_FOREACH (const QString &optionName, d->optionNames) {
+- if (aliases.contains(optionName))
+- return true;
+- }
+- return false;
+-}
+-
+-/*!
+- Returns the option value found for the given option name \a optionName, or
+- an empty string if not found.
+-
+- The name provided can be any long or short name of any option that was
+- added with \c addOption(). All the option names are treated as being
+- equivalent. If the name is not recognized or that option was not present, an
+- empty string is returned.
+-
+- For options found by the parser, the last value found for
+- that option is returned. If the option wasn't specified on the command line,
+- the default value is returned.
+-
+- An empty string is returned if the option does not take a value.
+-
+- \sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
+- */
+-
+-QString QCommandLineParser::value(const QString &optionName) const
+-{
+- d->checkParsed("value");
+- const QStringList valueList = values(optionName);
+-
+- if (!valueList.isEmpty())
+- return valueList.last();
+-
+- return QString();
+-}
+-
+-/*!
+- Returns a list of option values found for the given option name \a
+- optionName, or an empty list if not found.
+-
+- The name provided can be any long or short name of any option that was
+- added with \c addOption(). All the options names are treated as being
+- equivalent. If the name is not recognized or that option was not present, an
+- empty list is returned.
+-
+- For options found by the parser, the list will contain an entry for
+- each time the option was encountered by the parser. If the option wasn't
+- specified on the command line, the default values are returned.
+-
+- An empty list is returned if the option does not take a value.
+-
+- \sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
+- */
+-
+-QStringList QCommandLineParser::values(const QString &optionName) const
+-{
+- d->checkParsed("values");
+- const NameHash_t::const_iterator it = d->nameHash.constFind(optionName);
+- if (it != d->nameHash.constEnd()) {
+- const int optionOffset = *it;
+- QStringList values = d->optionValuesHash.value(optionOffset);
+- if (values.isEmpty())
+- values = d->commandLineOptionList.at(optionOffset).defaultValues();
+- return values;
+- }
+-
+- qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
+- return QStringList();
+-}
+-
+-/*!
+- \overload
+- Checks whether the \a option was passed to the application.
+-
+- Returns \c true if the \a option was set, false otherwise.
+-
+- This is the recommended way to check for options with no values.
+-
+- Example:
+- \snippet code/src_corelib_tools_qcommandlineparser.cpp 1
+-*/
+-bool QCommandLineParser::isSet(const QCommandLineOption &option) const
+-{
+- // option.names() might be empty if the constructor failed
+- return !option.names().isEmpty() && isSet(option.names().first());
+-}
+-
+-/*!
+- \overload
+- Returns the option value found for the given \a option, or
+- an empty string if not found.
+-
+- For options found by the parser, the last value found for
+- that option is returned. If the option wasn't specified on the command line,
+- the default value is returned.
+-
+- An empty string is returned if the option does not take a value.
+-
+- \sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
+-*/
+-QString QCommandLineParser::value(const QCommandLineOption &option) const
+-{
+- return value(option.names().first());
+-}
+-
+-/*!
+- \overload
+- Returns a list of option values found for the given \a option,
+- or an empty list if not found.
+-
+- For options found by the parser, the list will contain an entry for
+- each time the option was encountered by the parser. If the option wasn't
+- specified on the command line, the default values are returned.
+-
+- An empty list is returned if the option does not take a value.
+-
+- \sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
+-*/
+-QStringList QCommandLineParser::values(const QCommandLineOption &option) const
+-{
+- return values(option.names().first());
+-}
+-
+-/*!
+- Returns a list of positional arguments.
+-
+- These are all of the arguments that were not recognized as part of an
+- option.
+- */
+-
+-QStringList QCommandLineParser::positionalArguments() const
+-{
+- d->checkParsed("positionalArguments");
+- return d->positionalArgumentList;
+-}
+-
+-/*!
+- Returns a list of option names that were found.
+-
+- This returns a list of all the recognized option names found by the
+- parser, in the order in which they were found. For any long options
+- that were in the form {--option=value}, the value part will have been
+- dropped.
+-
+- The names in this list do not include the preceding dash characters.
+- Names may appear more than once in this list if they were encountered
+- more than once by the parser.
+-
+- Any entry in the list can be used with \c value() or with
+- \c values() to get any relevant option values.
+- */
+-
+-QStringList QCommandLineParser::optionNames() const
+-{
+- d->checkParsed("optionNames");
+- return d->optionNames;
+-}
+-
+-/*!
+- Returns a list of unknown option names.
+-
+- This list will include both long an short name options that were not
+- recognized. For any long options that were in the form {--option=value},
+- the value part will have been dropped and only the long name is added.
+-
+- The names in this list do not include the preceding dash characters.
+- Names may appear more than once in this list if they were encountered
+- more than once by the parser.
+-
+- \sa optionNames()
+- */
+-
+-QStringList QCommandLineParser::unknownOptionNames() const
+-{
+- d->checkParsed("unknownOptionNames");
+- return d->unknownOptionNames;
+-}
+-
+-/*!
+- Displays the help information, and exits the application.
+- This is automatically triggered by the --help option, but can also
+- be used to display the help when the user is not invoking the
+- application correctly.
+- The exit code is set to \a exitCode. It should be set to 0 if the
+- user requested to see the help, and to any other value in case of
+- an error.
+-
+- \sa helpText()
+-*/
+-void QCommandLineParser::showHelp(int exitCode)
+-{
+- fprintf(stdout, "%s", qPrintable(d->helpText()));
+- ::exit(exitCode);
+-}
+-
+-/*!
+- Returns a string containing the complete help information.
+-
+- \sa showHelp()
+-*/
+-QString QCommandLineParser::helpText() const
+-{
+- return d->helpText();
+-}
+-
+-static QString wrapText(const QString &names, int longestOptionNameString, const QString &description)
+-{
+- const QLatin1Char nl('\n');
+- QString text = QString(" ") + names.leftJustified(longestOptionNameString) + QLatin1Char(' ');
+- const int indent = text.length();
+- int lineStart = 0;
+- int lastBreakable = -1;
+- const int max = 79 - indent;
+- int x = 0;
+- const int len = description.length();
+-
+- for (int i = 0; i < len; ++i) {
+- ++x;
+- const QChar c = description.at(i);
+- if (c.isSpace())
+- lastBreakable = i;
+-
+- int breakAt = -1;
+- int nextLineStart = -1;
+- if (x > max && lastBreakable != -1) {
+- // time to break and we know where
+- breakAt = lastBreakable;
+- nextLineStart = lastBreakable + 1;
+- } else if ((x > max - 1 && lastBreakable == -1) || i == len - 1) {
+- // time to break but found nowhere [-> break here], or end of last line
+- breakAt = i + 1;
+- nextLineStart = breakAt;
+- } else if (c == nl) {
+- // forced break
+- breakAt = i;
+- nextLineStart = i + 1;
+- }
+-
+- if (breakAt != -1) {
+- const int numChars = breakAt - lineStart;
+- //qDebug() << "breakAt=" << description.at(breakAt) << "breakAtSpace=" << breakAtSpace << lineStart << "to" << breakAt << description.mid(lineStart, numChars);
+- if (lineStart > 0)
+- text += QString(indent, QLatin1Char(' '));
+- text += description.mid(lineStart, numChars) + nl;
+- x = 0;
+- lastBreakable = -1;
+- lineStart = nextLineStart;
+- if (lineStart < len && description.at(lineStart).isSpace())
+- ++lineStart; // don't start a line with a space
+- i = lineStart;
+- }
+- }
+-
+- return text;
+-}
+-
+-QString QCommandLineParserPrivate::helpText() const
+-{
+- const QLatin1Char nl('\n');
+- QString text;
+- const QString exeName = QCoreApplication::instance()->arguments().first();
+- QString usage = exeName;
+- if (!commandLineOptionList.isEmpty()) {
+- usage += QLatin1Char(' ');
+- usage += QCommandLineParser::tr("[options]");
+- }
+- Q_FOREACH (const PositionalArgumentDefinition &arg, positionalArgumentDefinitions) {
+- usage += QLatin1Char(' ');
+- usage += arg.syntax;
+- }
+- text += QCommandLineParser::tr("Usage: %1").arg(usage) + nl;
+- if (!description.isEmpty())
+- text += description + nl;
+- text += nl;
+- if (!commandLineOptionList.isEmpty())
+- text += QCommandLineParser::tr("Options:") + nl;
+- QStringList optionNameList;
+- int longestOptionNameString = 0;
+- Q_FOREACH (const QCommandLineOption &option, commandLineOptionList) {
+- QStringList optionNames;
+- Q_FOREACH (const QString &optionName, option.names()) {
+- if (optionName.length() == 1)
+- optionNames.append(QLatin1Char('-') + optionName);
+- else
+- optionNames.append(QString("--") + optionName);
+- }
+- QString optionNamesString = optionNames.join(", ");
+- if (!option.valueName().isEmpty())
+- optionNamesString += QString(" <") + option.valueName() + QLatin1Char('>');
+- optionNameList.append(optionNamesString);
+- longestOptionNameString = qMax(longestOptionNameString, optionNamesString.length());
+- }
+- ++longestOptionNameString;
+- for (int i = 0; i < commandLineOptionList.count(); ++i) {
+- const QCommandLineOption &option = commandLineOptionList.at(i);
+- text += wrapText(optionNameList.at(i), longestOptionNameString, option.description());
+- }
+- if (!positionalArgumentDefinitions.isEmpty()) {
+- if (!commandLineOptionList.isEmpty())
+- text += nl;
+- text += QCommandLineParser::tr("Arguments:") + nl;
+- Q_FOREACH (const PositionalArgumentDefinition &arg, positionalArgumentDefinitions) {
+- text += wrapText(arg.name, longestOptionNameString, arg.description);
+- }
+- }
+- return text;
+-}
+diff --git a/src/core/qcommandlineparser.h b/src/core/qcommandlineparser.h
+deleted file mode 100644
+index eeecf2d..0000000
+--- a/src/core/qcommandlineparser.h
++++ /dev/null
+@@ -1,102 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.LGPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU Lesser General Public License version 2.1 requirements
+-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU
+-** General Public License version 3.0 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.GPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU General Public License version 3.0 requirements will be
+-** met: http://www.gnu.org/copyleft/gpl.html.
+-**
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#ifndef QCOMMANDLINEPARSER_H
+-#define QCOMMANDLINEPARSER_H
+-
+-#include <QStringList>
+-#include <QCoreApplication>
+-
+-#include "qcommandlineoption.h"
+-
+-class QCommandLineParserPrivate;
+-class QCoreApplication;
+-
+-class QCommandLineParser
+-{
+- Q_DECLARE_TR_FUNCTIONS(QCommandLineParser)
+-public:
+- QCommandLineParser();
+- ~QCommandLineParser();
+-
+- enum SingleDashWordOptionMode {
+- ParseAsCompactedShortOptions,
+- ParseAsLongOptions
+- };
+- void setSingleDashWordOptionMode(SingleDashWordOptionMode parsingMode);
+-
+- bool addOption(const QCommandLineOption &commandLineOption);
+-
+- QCommandLineOption addVersionOption();
+- QCommandLineOption addHelpOption();
+- void setApplicationDescription(const QString &description);
+- QString applicationDescription() const;
+- void addPositionalArgument(const QString &name, const QString &description, const QString &syntax = QString());
+- void clearPositionalArguments();
+-
+- void process(const QStringList &arguments);
+- void process(const QCoreApplication &app);
+-
+- bool parse(const QStringList &arguments);
+- QString errorText() const;
+-
+- bool isSet(const QString &name) const;
+- QString value(const QString &name) const;
+- QStringList values(const QString &name) const;
+-
+- bool isSet(const QCommandLineOption &option) const;
+- QString value(const QCommandLineOption &option) const;
+- QStringList values(const QCommandLineOption &option) const;
+-
+- QStringList positionalArguments() const;
+- QStringList optionNames() const;
+- QStringList unknownOptionNames() const;
+-
+- void showHelp(int exitCode = 0);
+- QString helpText() const;
+-
+-private:
+- Q_DISABLE_COPY(QCommandLineParser)
+-
+- QCommandLineParserPrivate * const d;
+-};
+-
+-#endif // QCOMMANDLINEPARSER_H
+diff --git a/src/core/qlockfile.cpp b/src/core/qlockfile.cpp
+deleted file mode 100644
+index 567440c..0000000
+--- a/src/core/qlockfile.cpp
++++ /dev/null
+@@ -1,344 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL21$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 or version 3 as published by the Free
+-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+-** following information to ensure the GNU Lesser General Public License
+-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#include "qlockfile.h"
+-#include "qlockfile_p.h"
+-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+-# include <QElapsedTimer>
+-#else
+-# include <QTime>
+-#endif
+-#include <QDateTime>
+-
+-QT_BEGIN_NAMESPACE
+-
+-/*!
+- \class QLockFile
+- \inmodule QtCore
+- \brief The QLockFile class provides locking between processes using a file.
+- \since 5.1
+-
+- A lock file can be used to prevent multiple processes from accessing concurrently
+- the same resource. For instance, a configuration file on disk, or a socket, a port,
+- a region of shared memory...
+-
+- Serialization is only guaranteed if all processes that access the shared resource
+- use QLockFile, with the same file path.
+-
+- QLockFile supports two use cases:
+- to protect a resource for a short-term operation (e.g. verifying if a configuration
+- file has changed before saving new settings), and for long-lived protection of a
+- resource (e.g. a document opened by a user in an editor) for an indefinite amount of time.
+-
+- When protecting for a short-term operation, it is acceptable to call lock() and wait
+- until any running operation finishes.
+- When protecting a resource over a long time, however, the application should always
+- call setStaleLockTime(0) and then tryLock() with a short timeout, in order to
+- warn the user that the resource is locked.
+-
+- If the process holding the lock crashes, the lock file stays on disk and can prevent
+- any other process from accessing the shared resource, ever. For this reason, QLockFile
+- tries to detect such a "stale" lock file, based on the process ID written into the file,
+- and (in case that process ID got reused meanwhile), on the last modification time of
+- the lock file (30s by default, for the use case of a short-lived operation).
+- If the lock file is found to be stale, it will be deleted.
+-
+- For the use case of protecting a resource over a long time, you should therefore call
+- setStaleLockTime(0), and when tryLock() returns LockFailedError, inform the user
+- that the document is locked, possibly using getLockInfo() for more details.
+-*/
+-
+-/*!
+- \enum QLockFile::LockError
+-
+- This enum describes the result of the last call to lock() or tryLock().
+-
+- \value NoError The lock was acquired successfully.
+- \value LockFailedError The lock could not be acquired because another process holds it.
+- \value PermissionError The lock file could not be created, for lack of permissions
+- in the parent directory.
+- \value UnknownError Another error happened, for instance a full partition
+- prevented writing out the lock file.
+-*/
+-
+-/*!
+- Constructs a new lock file object.
+- The object is created in an unlocked state.
+- When calling lock() or tryLock(), a lock file named \a fileName will be created,
+- if it doesn't already exist.
+-
+- \sa lock(), unlock()
+-*/
+-QLockFile::QLockFile(const QString &fileName)
+- : d_ptr(new QLockFilePrivate(fileName))
+-{
+-}
+-
+-/*!
+- Destroys the lock file object.
+- If the lock was acquired, this will release the lock, by deleting the lock file.
+-*/
+-QLockFile::~QLockFile()
+-{
+- unlock();
+-}
+-
+-/*!
+- Sets \a staleLockTime to be the time in milliseconds after which
+- a lock file is considered stale.
+- The default value is 30000, i.e. 30 seconds.
+- If your application typically keeps the file locked for more than 30 seconds
+- (for instance while saving megabytes of data for 2 minutes), you should set
+- a bigger value using setStaleLockTime().
+-
+- The value of \a staleLockTime is used by lock() and tryLock() in order
+- to determine when an existing lock file is considered stale, i.e. left over
+- by a crashed process. This is useful for the case where the PID got reused
+- meanwhile, so the only way to detect a stale lock file is by the fact that
+- it has been around for a long time.
+-
+- \sa staleLockTime()
+-*/
+-void QLockFile::setStaleLockTime(int staleLockTime)
+-{
+- Q_D(QLockFile);
+- d->staleLockTime = staleLockTime;
+-}
+-
+-/*!
+- Returns the time in milliseconds after which
+- a lock file is considered stale.
+-
+- \sa setStaleLockTime()
+-*/
+-int QLockFile::staleLockTime() const
+-{
+- Q_D(const QLockFile);
+- return d->staleLockTime;
+-}
+-
+-/*!
+- Returns \c true if the lock was acquired by this QLockFile instance,
+- otherwise returns \c false.
+-
+- \sa lock(), unlock(), tryLock()
+-*/
+-bool QLockFile::isLocked() const
+-{
+- Q_D(const QLockFile);
+- return d->isLocked;
+-}
+-
+-/*!
+- Creates the lock file.
+-
+- If another process (or another thread) has created the lock file already,
+- this function will block until that process (or thread) releases it.
+-
+- Calling this function multiple times on the same lock from the same
+- thread without unlocking first is not allowed. This function will
+- \e dead-lock when the file is locked recursively.
+-
+- Returns \c true if the lock was acquired, false if it could not be acquired
+- due to an unrecoverable error, such as no permissions in the parent directory.
+-
+- \sa unlock(), tryLock()
+-*/
+-bool QLockFile::lock()
+-{
+- return tryLock(-1);
+-}
+-
+-/*!
+- Attempts to create the lock file. This function returns \c true if the
+- lock was obtained; otherwise it returns \c false. If another process (or
+- another thread) has created the lock file already, this function will
+- wait for at most \a timeout milliseconds for the lock file to become
+- available.
+-
+- Note: Passing a negative number as the \a timeout is equivalent to
+- calling lock(), i.e. this function will wait forever until the lock
+- file can be locked if \a timeout is negative.
+-
+- If the lock was obtained, it must be released with unlock()
+- before another process (or thread) can successfully lock it.
+-
+- Calling this function multiple times on the same lock from the same
+- thread without unlocking first is not allowed, this function will
+- \e always return false when attempting to lock the file recursively.
+-
+- \sa lock(), unlock()
+-*/
+-bool QLockFile::tryLock(int timeout)
+-{
+- Q_D(QLockFile);
+-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+- QElapsedTimer timer;
+-#else
+- QTime timer;
+-#endif
+- if (timeout > 0)
+- timer.start();
+- int sleepTime = 100;
+- Q_FOREVER {
+- d->lockError = d->tryLock_sys();
+- switch (d->lockError) {
+- case NoError:
+- d->isLocked = true;
+- return true;
+- case PermissionError:
+- case UnknownError:
+- return false;
+- case LockFailedError:
+- if (!d->isLocked && d->isApparentlyStale()) {
+- // Stale lock from another thread/process
+- // Ensure two processes don't remove it at the same time
+- QLockFile rmlock(d->fileName + QLatin1String(".rmlock"));
+- if (rmlock.tryLock()) {
+- if (d->isApparentlyStale() && d->removeStaleLock())
+- continue;
+- }
+- }
+- break;
+- }
+- if (timeout == 0 || (timeout > 0 && (timer.elapsed() > timeout)))
+- return false;
+- QLockFileThread::msleep(sleepTime);
+- if (sleepTime < 5 * 1000)
+- sleepTime *= 2;
+- }
+- // not reached
+- return false;
+-}
+-
+-/*!
+- \fn void QLockFile::unlock()
+- Releases the lock, by deleting the lock file.
+-
+- Calling unlock() without locking the file first, does nothing.
+-
+- \sa lock(), tryLock()
+-*/
+-
+-/*!
+- Retrieves information about the current owner of the lock file.
+-
+- If tryLock() returns \c false, and error() returns LockFailedError,
+- this function can be called to find out more information about the existing
+- lock file:
+- \list
+- \li the PID of the application (returned in \a pid)
+- \li the \a hostname it's running on (useful in case of networked filesystems),
+- \li the name of the application which created it (returned in \a appname),
+- \endlist
+-
+- Note that tryLock() automatically deleted the file if there is no
+- running application with this PID, so LockFailedError can only happen if there is
+- an application with this PID (it could be unrelated though).
+-
+- This can be used to inform users about the existing lock file and give them
+- the choice to delete it. After removing the file using removeStaleLockFile(),
+- the application can call tryLock() again.
+-
+- This function returns \c true if the information could be successfully retrieved, false
+- if the lock file doesn't exist or doesn't contain the expected data.
+- This can happen if the lock file was deleted between the time where tryLock() failed
+- and the call to this function. Simply call tryLock() again if this happens.
+-*/
+-bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const
+-{
+- Q_D(const QLockFile);
+- return d->getLockInfo(pid, hostname, appname);
+-}
+-
+-bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const
+-{
+- QFile reader(fileName);
+- if (!reader.open(QIODevice::ReadOnly))
+- return false;
+-
+- QByteArray pidLine = reader.readLine();
+- pidLine.chop(1);
+- QByteArray appNameLine = reader.readLine();
+- appNameLine.chop(1);
+- QByteArray hostNameLine = reader.readLine();
+- hostNameLine.chop(1);
+- if (pidLine.isEmpty())
+- return false;
+-
+- qint64 thePid = pidLine.toLongLong();
+- if (pid)
+- *pid = thePid;
+- if (appname)
+- *appname = QString::fromUtf8(appNameLine);
+- if (hostname)
+- *hostname = QString::fromUtf8(hostNameLine);
+- return thePid > 0;
+-}
+-
+-/*!
+- Attempts to forcefully remove an existing lock file.
+-
+- Calling this is not recommended when protecting a short-lived operation: QLockFile
+- already takes care of removing lock files after they are older than staleLockTime().
+-
+- This method should only be called when protecting a resource for a long time, i.e.
+- with staleLockTime(0), and after tryLock() returned LockFailedError, and the user
+- agreed on removing the lock file.
+-
+- Returns \c true on success, false if the lock file couldn't be removed. This happens
+- on Windows, when the application owning the lock is still running.
+-*/
+-bool QLockFile::removeStaleLockFile()
+-{
+- Q_D(QLockFile);
+- if (d->isLocked) {
+- qWarning("removeStaleLockFile can only be called when not holding the lock");
+- return false;
+- }
+- return d->removeStaleLock();
+-}
+-
+-/*!
+- Returns the lock file error status.
+-
+- If tryLock() returns \c false, this function can be called to find out
+- the reason why the locking failed.
+-*/
+-QLockFile::LockError QLockFile::error() const
+-{
+- Q_D(const QLockFile);
+- return d->lockError;
+-}
+-
+-QT_END_NAMESPACE
+diff --git a/src/core/qlockfile.h b/src/core/qlockfile.h
+deleted file mode 100644
+index 673026f..0000000
+--- a/src/core/qlockfile.h
++++ /dev/null
+@@ -1,79 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL21$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 or version 3 as published by the Free
+-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+-** following information to ensure the GNU Lesser General Public License
+-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#ifndef QLOCKFILE_H
+-#define QLOCKFILE_H
+-
+-#include <QString>
+-#include <QScopedPointer>
+-
+-QT_BEGIN_NAMESPACE
+-
+-class QLockFilePrivate;
+-
+-class QLockFile
+-{
+-public:
+- QLockFile(const QString &fileName);
+- ~QLockFile();
+-
+- bool lock();
+- bool tryLock(int timeout = 0);
+- void unlock();
+-
+- void setStaleLockTime(int);
+- int staleLockTime() const;
+-
+- bool isLocked() const;
+- bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const;
+- bool removeStaleLockFile();
+-
+- enum LockError {
+- NoError = 0,
+- LockFailedError = 1,
+- PermissionError = 2,
+- UnknownError = 3
+- };
+- LockError error() const;
+-
+-protected:
+- QScopedPointer<QLockFilePrivate> d_ptr;
+-
+-private:
+- Q_DECLARE_PRIVATE(QLockFile)
+- Q_DISABLE_COPY(QLockFile)
+-};
+-
+-QT_END_NAMESPACE
+-
+-#endif // QLOCKFILE_H
+diff --git a/src/core/qlockfile_p.h b/src/core/qlockfile_p.h
+deleted file mode 100644
+index 15fa37b..0000000
+--- a/src/core/qlockfile_p.h
++++ /dev/null
+@@ -1,101 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL21$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 or version 3 as published by the Free
+-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+-** following information to ensure the GNU Lesser General Public License
+-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#ifndef QLOCKFILE_P_H
+-#define QLOCKFILE_P_H
+-
+-//
+-// W A R N I N G
+-// -------------
+-//
+-// This file is not part of the Qt API. It exists purely as an
+-// implementation detail. This header file may change from version to
+-// version without notice, or even be removed.
+-//
+-// We mean it.
+-//
+-
+-#include "qlockfile.h"
+-
+-#include <QFile>
+-#include <QThread>
+-
+-#ifdef Q_OS_WIN
+-#include <qt_windows.h>
+-#endif
+-
+-QT_BEGIN_NAMESPACE
+-
+-class QLockFileThread : public QThread
+-{
+-public:
+- static void msleep(unsigned long msecs) { QThread::msleep(msecs); }
+-};
+-
+-class QLockFilePrivate
+-{
+-public:
+- QLockFilePrivate(const QString &fn)
+- : fileName(fn),
+-#ifdef Q_OS_WIN
+- fileHandle(INVALID_HANDLE_VALUE),
+-#else
+- fileHandle(-1),
+-#endif
+- staleLockTime(30 * 1000), // 30 seconds
+- lockError(QLockFile::NoError),
+- isLocked(false)
+- {
+- }
+- QLockFile::LockError tryLock_sys();
+- bool removeStaleLock();
+- bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const;
+- // Returns \c true if the lock belongs to dead PID, or is old.
+- // The attempt to delete it will tell us if it was really stale or not, though.
+- bool isApparentlyStale() const;
+- static QString processNameByPid(qint64 pid);
+-
+- QString fileName;
+-#ifdef Q_OS_WIN
+- Qt::HANDLE fileHandle;
+-#else
+- int fileHandle;
+-#endif
+- int staleLockTime; // "int milliseconds" is big enough for 24 days
+- QLockFile::LockError lockError;
+- bool isLocked;
+-};
+-
+-QT_END_NAMESPACE
+-
+-#endif /* QLOCKFILE_P_H */
+diff --git a/src/core/qlockfile_unix.cpp b/src/core/qlockfile_unix.cpp
+deleted file mode 100644
+index 5b3add3..0000000
+--- a/src/core/qlockfile_unix.cpp
++++ /dev/null
+@@ -1,244 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+-** Copyright (C) 2015 The Qt Company Ltd.
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL21$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 or version 3 as published by the Free
+-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+-** following information to ensure the GNU Lesser General Public License
+-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#include "qlockfile_p.h"
+-
+-#include <QTemporaryFile>
+-#include <QCoreApplication>
+-#include <QFileInfo>
+-#include <QDebug>
+-#include <QDateTime>
+-
+-#include <sys/file.h> // flock
+-#include <sys/types.h> // kill
+-#include <signal.h> // kill
+-#include <unistd.h> // gethostname
+-
+-#include <errno.h>
+-
+-#if defined(Q_OS_MAC)
+-# include <libproc.h>
+-#elif defined(Q_OS_LINUX)
+-# include <unistd.h>
+-# include <cstdio>
+-#endif
+-
+-QT_BEGIN_NAMESPACE
+-
+-#define EINTR_LOOP(var, cmd) \
+- do { \
+- var = cmd; \
+- } while (var == -1 && errno == EINTR)
+-
+-// don't call QT_OPEN or ::open
+-// call qt_safe_open
+-static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
+-{
+-#ifdef O_CLOEXEC
+- flags |= O_CLOEXEC;
+-#endif
+- int fd;
+- EINTR_LOOP(fd, ::open(pathname, flags, mode));
+-
+- // unknown flags are ignored, so we have no way of verifying if
+- // O_CLOEXEC was accepted
+- if (fd != -1)
+- ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+- return fd;
+-}
+-
+-static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
+-{
+- qint64 ret = 0;
+- EINTR_LOOP(ret, ::write(fd, data, len));
+- return ret;
+-}
+-
+-static QByteArray localHostName() // from QHostInfo::localHostName(), modified to return a QByteArray
+-{
+- QByteArray hostName(512, Qt::Uninitialized);
+- if (gethostname(hostName.data(), hostName.size()) == -1)
+- return QByteArray();
+- hostName.truncate(strlen(hostName.data()));
+- return hostName;
+-}
+-
+-// ### merge into qt_safe_write?
+-static qint64 qt_write_loop(int fd, const char *data, qint64 len)
+-{
+- qint64 pos = 0;
+- while (pos < len) {
+- const qint64 ret = qt_safe_write(fd, data + pos, len - pos);
+- if (ret == -1) // e.g. partition full
+- return pos;
+- pos += ret;
+- }
+- return pos;
+-}
+-
+-static bool setNativeLocks(int fd)
+-{
+-#if defined(LOCK_EX) && defined(LOCK_NB)
+- if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs
+- return false;
+-#endif
+- struct flock flockData;
+- flockData.l_type = F_WRLCK;
+- flockData.l_whence = SEEK_SET;
+- flockData.l_start = 0;
+- flockData.l_len = 0; // 0 = entire file
+- flockData.l_pid = getpid();
+- if (fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems
+- return false;
+- return true;
+-}
+-
+-QLockFile::LockError QLockFilePrivate::tryLock_sys()
+-{
+- // Assemble data, to write in a single call to write
+- // (otherwise we'd have to check every write call)
+- // Use operator% from the fast builder to avoid multiple memory allocations.
+- QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) + '\n'
+- + QCoreApplication::applicationName().toUtf8() + '\n'
+- + localHostName() + '\n';
+-
+- const QByteArray lockFileName = QFile::encodeName(fileName);
+- const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644);
+- if (fd < 0) {
+- switch (errno) {
+- case EEXIST:
+- return QLockFile::LockFailedError;
+- case EACCES:
+- case EROFS:
+- return QLockFile::PermissionError;
+- default:
+- return QLockFile::UnknownError;
+- }
+- }
+- // Ensure nobody else can delete the file while we have it
+- if (!setNativeLocks(fd))
+- qWarning() << "setNativeLocks failed:" << strerror(errno);
+-
+- if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) {
+- close(fd);
+- if (!QFile::remove(fileName))
+- qWarning("QLockFile: Could not remove our own lock file %s.", qPrintable(fileName));
+- return QLockFile::UnknownError; // partition full
+- }
+-
+- // We hold the lock, continue.
+- fileHandle = fd;
+-
+- return QLockFile::NoError;
+-}
+-
+-bool QLockFilePrivate::removeStaleLock()
+-{
+- const QByteArray lockFileName = QFile::encodeName(fileName);
+- const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644);
+- if (fd < 0) // gone already?
+- return false;
+-#ifdef Q_OS_MAC
+- // ugly workaround: ignore setNativeLocks() result on Mac since it's broken there
+- setNativeLocks(fd);
+- bool success = (::unlink(lockFileName) == 0);
+-#else
+- bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0);
+-#endif
+- close(fd);
+- return success;
+-}
+-
+-bool QLockFilePrivate::isApparentlyStale() const
+-{
+- qint64 pid;
+- QString hostname, appname;
+- if (getLockInfo(&pid, &hostname, &appname)) {
+- if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
+- if (::kill(pid, 0) == -1 && errno == ESRCH)
+- return true; // PID doesn't exist anymore
+- const QString processName = processNameByPid(pid);
+- if (!processName.isEmpty()) {
+- QFileInfo fi(appname);
+- if (fi.isSymLink())
+- fi.setFile(fi.symLinkTarget());
+- if (processName.toLower() != fi.fileName().toLower())
+- return true; // PID got reused by a different application.
+- }
+- }
+- }
+- const qint64 age = QFileInfo(fileName).lastModified().secsTo(QDateTime::currentDateTime()) * 1000;
+- return staleLockTime > 0 && age > staleLockTime;
+-}
+-
+-QString QLockFilePrivate::processNameByPid(qint64 pid)
+-{
+-#if defined(Q_OS_MAC)
+- char name[1024];
+- proc_name(pid, name, sizeof(name) / sizeof(char));
+- return QFile::decodeName(name);
+-#elif defined(Q_OS_LINUX)
+- if (!QFile::exists(QString("/proc/version")))
+- return QString();
+- char exePath[64];
+- char buf[PATH_MAX + 1];
+- sprintf(exePath, "/proc/%lld/exe", pid);
+- size_t len = static_cast<size_t>(readlink(exePath, buf, sizeof(buf)));
+- if (len >= sizeof(buf)) {
+- // The pid is gone. Return some invalid process name to fail the test.
+- return QString("/ERROR/");
+- }
+- buf[len] = 0;
+- return QFileInfo(QFile::decodeName(buf)).fileName();
+-#else
+- return QString();
+-#endif
+-}
+-
+-void QLockFile::unlock()
+-{
+- Q_D(QLockFile);
+- if (!d->isLocked)
+- return;
+- close(d->fileHandle);
+- d->fileHandle = -1;
+- if (!QFile::remove(d->fileName)) {
+- qWarning() << "Could not remove our own lock file" << d->fileName << "maybe permissions changed meanwhile?";
+- // This is bad because other users of this lock file will now have to wait for the stale-lock-timeout...
+- }
+- d->lockError = QLockFile::NoError;
+- d->isLocked = false;
+-}
+-
+-QT_END_NAMESPACE
+diff --git a/src/core/qlockfile_win.cpp b/src/core/qlockfile_win.cpp
+deleted file mode 100644
+index 5fc3327..0000000
+--- a/src/core/qlockfile_win.cpp
++++ /dev/null
+@@ -1,227 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+-** Copyright (C) 2015 The Qt Company Ltd.
+-** Contact: http://www.qt.io/licensing/
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL21$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and The Qt Company. For licensing terms
+-** and conditions see http://www.qt.io/terms-conditions. For further
+-** information use the contact form at http://www.qt.io/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 or version 3 as published by the Free
+-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+-** following information to ensure the GNU Lesser General Public License
+-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** As a special exception, The Qt Company gives you certain additional
+-** rights. These rights are described in The Qt Company LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#ifndef _UNICODE
+-#define _UNICODE
+-#endif
+-
+-#ifndef UNICODE
+-#define UNICODE
+-#endif
+-
+-#include "qlockfile_p.h"
+-
+-#include <qt_windows.h>
+-
+-#include <QCoreApplication>
+-#include <QDir>
+-#include <QFileInfo>
+-#include <QDateTime>
+-#include <QDebug>
+-
+-QT_BEGIN_NAMESPACE
+-
+-static inline QByteArray localHostName()
+-{
+- return qgetenv("COMPUTERNAME");
+-}
+-
+-static inline bool fileExists(const wchar_t *fileName)
+-{
+- WIN32_FILE_ATTRIBUTE_DATA data;
+- return GetFileAttributesEx(fileName, GetFileExInfoStandard, &data);
+-}
+-
+-QLockFile::LockError QLockFilePrivate::tryLock_sys()
+-{
+- const ushort* nativePath = QDir::toNativeSeparators(fileName).utf16();
+- // When writing, allow others to read.
+- // When reading, QFile will allow others to read and write, all good.
+- // Adding FILE_SHARE_DELETE would allow forceful deletion of stale files,
+- // but Windows doesn't allow recreating it while this handle is open anyway,
+- // so this would only create confusion (can't lock, but no lock file to read from).
+- const DWORD dwShareMode = FILE_SHARE_READ;
+-#ifndef Q_OS_WINRT
+- SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
+- HANDLE fh = CreateFile((const wchar_t*)nativePath,
+- GENERIC_WRITE,
+- dwShareMode,
+- &securityAtts,
+- CREATE_NEW, // error if already exists
+- FILE_ATTRIBUTE_NORMAL,
+- NULL);
+-#else // !Q_OS_WINRT
+- HANDLE fh = CreateFile2((const wchar_t*)nativePath,
+- GENERIC_WRITE,
+- dwShareMode,
+- CREATE_NEW, // error if already exists
+- NULL);
+-#endif // Q_OS_WINRT
+- if (fh == INVALID_HANDLE_VALUE) {
+- const DWORD lastError = GetLastError();
+- switch (lastError) {
+- case ERROR_SHARING_VIOLATION:
+- case ERROR_ALREADY_EXISTS:
+- case ERROR_FILE_EXISTS:
+- return QLockFile::LockFailedError;
+- case ERROR_ACCESS_DENIED:
+- // readonly file, or file still in use by another process.
+- // Assume the latter if the file exists, since we don't create it readonly.
+- return fileExists((const wchar_t*)nativePath)
+- ? QLockFile::LockFailedError
+- : QLockFile::PermissionError;
+- default:
+- qWarning() << "Got unexpected locking error" << lastError;
+- return QLockFile::UnknownError;
+- }
+- }
+-
+- // We hold the lock, continue.
+- fileHandle = fh;
+- // Assemble data, to write in a single call to write
+- // (otherwise we'd have to check every write call)
+- QByteArray fileData;
+- fileData += QByteArray::number(QCoreApplication::applicationPid());
+- fileData += '\n';
+- fileData += QCoreApplication::applicationName().toUtf8();
+- fileData += '\n';
+- fileData += localHostName();
+- fileData += '\n';
+- DWORD bytesWritten = 0;
+- QLockFile::LockError error = QLockFile::NoError;
+- if (!WriteFile(fh, fileData.constData(), fileData.size(), &bytesWritten, NULL) || !FlushFileBuffers(fh))
+- error = QLockFile::UnknownError; // partition full
+- return error;
+-}
+-
+-bool QLockFilePrivate::removeStaleLock()
+-{
+- // QFile::remove fails on Windows if the other process is still using the file, so it's not stale.
+- return QFile::remove(fileName);
+-}
+-
+-bool QLockFilePrivate::isApparentlyStale() const
+-{
+- qint64 pid;
+- QString hostname, appname;
+-
+- // On WinRT there seems to be no way of obtaining information about other
+- // processes due to sandboxing
+-#ifndef Q_OS_WINRT
+- if (getLockInfo(&pid, &hostname, &appname)) {
+- if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
+- HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
+- if (!procHandle)
+- return true;
+- // We got a handle but check if process is still alive
+- DWORD dwR = ::WaitForSingleObject(procHandle, 0);
+- ::CloseHandle(procHandle);
+- if (dwR == WAIT_TIMEOUT)
+- return true;
+- const QString processName = processNameByPid(pid);
+- if (!processName.isEmpty() && processName != appname)
+- return true; // PID got reused by a different application.
+- }
+- }
+-#else // !Q_OS_WINRT
+- Q_UNUSED(pid);
+- Q_UNUSED(hostname);
+- Q_UNUSED(appname);
+-#endif // Q_OS_WINRT
+- const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
+- return staleLockTime > 0 && age > staleLockTime;
+-}
+-
+-QString QLockFilePrivate::processNameByPid(qint64 pid)
+-{
+-#if !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
+- typedef DWORD (WINAPI *GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD);
+-
+- HMODULE hPsapi = LoadLibraryA("psapi");
+- if (!hPsapi)
+- return QString();
+-
+- GetModuleFileNameExFunc qGetModuleFileNameEx
+- = (GetModuleFileNameExFunc)GetProcAddress(hPsapi, "GetModuleFileNameExW");
+- if (!qGetModuleFileNameEx) {
+- FreeLibrary(hPsapi);
+- return QString();
+- }
+-
+- HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid));
+- if (!hProcess) {
+- FreeLibrary(hPsapi);
+- return QString();
+- }
+- wchar_t buf[MAX_PATH];
+- const DWORD length = qGetModuleFileNameEx(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t));
+- CloseHandle(hProcess);
+- FreeLibrary(hPsapi);
+- if (!length)
+- return QString();
+- QString name = QString::fromWCharArray(buf, length);
+- int i = name.lastIndexOf(QLatin1Char('\\'));
+- if (i >= 0)
+- name.remove(0, i + 1);
+- i = name.lastIndexOf(QLatin1Char('.'));
+- if (i >= 0)
+- name.truncate(i);
+- return name;
+-#else
+- Q_UNUSED(pid);
+- return QString();
+-#endif
+-}
+-
+-void QLockFile::unlock()
+-{
+- Q_D(QLockFile);
+- if (!d->isLocked)
+- return;
+- CloseHandle(d->fileHandle);
+- int attempts = 0;
+- static const int maxAttempts = 500; // 500ms
+- while (!QFile::remove(d->fileName) && ++attempts < maxAttempts) {
+- // Someone is reading the lock file right now (on Windows this prevents deleting it).
+- QLockFileThread::msleep(1);
+- }
+- if (attempts == maxAttempts) {
+- qWarning() << "Could not remove our own lock file" << d->fileName << ". Either other users of the lock file are reading it constantly for 500 ms, or we (no longer) have permissions to delete the file";
+- // This is bad because other users of this lock file will now have to wait for the stale-lock-timeout...
+- }
+- d->lockError = QLockFile::NoError;
+- d->isLocked = false;
+-}
+-
+-QT_END_NAMESPACE
+diff --git a/src/core/qsavefile.cpp b/src/core/qsavefile.cpp
+deleted file mode 100644
+index 287f9e8..0000000
+--- a/src/core/qsavefile.cpp
++++ /dev/null
+@@ -1,452 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+-** Contact: http://www.qt-project.org/
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL$
+-** GNU Lesser General Public License Usage
+-** This file may be used under the terms of the GNU Lesser General Public
+-** License version 2.1 as published by the Free Software Foundation and
+-** appearing in the file LICENSE.LGPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU Lesser
+-** General Public License version 2.1 requirements will be met:
+-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Nokia gives you certain additional
+-** rights. These rights are described in the Nokia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU General
+-** Public License version 3.0 as published by the Free Software Foundation
+-** and appearing in the file LICENSE.GPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU General
+-** Public License version 3.0 requirements will be met:
+-** http://www.gnu.org/copyleft/gpl.html.
+-**
+-** Other Usage
+-** Alternatively, this file may be used in accordance with the terms and
+-** conditions contained in a signed written agreement between you and Nokia.
+-**
+-**
+-**
+-**
+-**
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#include "qsavefile.h"
+-#include "qsavefile_p.h"
+-
+-#include <QAbstractFileEngine>
+-#include <QFileInfo>
+-#include <QTemporaryFile>
+-
+-#ifdef Q_OS_WIN
+-# include <windows.h>
+-#else
+-# include <unistd.h>
+-#endif
+-
+-QSaveFilePrivate::QSaveFilePrivate()
+- : tempFile(0), error(QFile::NoError)
+-{
+-}
+-
+-QSaveFilePrivate::~QSaveFilePrivate()
+-{
+-}
+-
+-/*!
+- \class QSaveFile
+- \brief The QSaveFile class provides an interface for safely writing to files.
+-
+- \ingroup io
+-
+- \reentrant
+-
+- QSaveFile is an I/O device for writing text and binary files, without losing
+- existing data if the writing operation fails.
+-
+- While writing, the contents will be written to a temporary file, and if
+- no error happened, commit() will move it to the final file. This ensures that
+- no data at the final file is lost in case an error happens while writing,
+- and no partially-written file is ever present at the final location. Always
+- use QSaveFile when saving entire documents to disk.
+-
+- QSaveFile automatically detects errors while writing, such as the full partition
+- situation, where write() cannot write all the bytes. It will remember that
+- an error happened, and will discard the temporary file in commit().
+-
+- Much like with QFile, the file is opened with open(). Data is usually read
+- and written using QDataStream or QTextStream, but you can also call the
+- QIODevice-inherited functions read(), readLine(), readAll(), write().
+-
+- Unlike QFile, calling close() is not allowed. commit() replaces it. If commit()
+- was not called and the QSaveFile instance is destroyed, the temporary file is
+- discarded.
+-
+- \sa QTextStream, QDataStream, QFileInfo, QDir, QFile, QTemporaryFile
+-*/
+-
+-/*!
+- \internal
+-*/
+-QSaveFile::QSaveFile()
+- : QIODevice(), d_ptr(new QSaveFilePrivate)
+-{
+-}
+-/*!
+- Constructs a new file object with the given \a parent.
+-*/
+-QSaveFile::QSaveFile(QObject *parent)
+- : QIODevice(parent), d_ptr(new QSaveFilePrivate)
+-{
+-}
+-/*!
+- Constructs a new file object to represent the file with the given \a name.
+-*/
+-QSaveFile::QSaveFile(const QString &name)
+- : QIODevice(0), d_ptr(new QSaveFilePrivate)
+-{
+- Q_D(QSaveFile);
+- d->fileName = name;
+-}
+-/*!
+- Constructs a new file object with the given \a parent to represent the
+- file with the specified \a name.
+-*/
+-QSaveFile::QSaveFile(const QString &name, QObject *parent)
+- : QIODevice(parent), d_ptr(new QSaveFilePrivate)
+-{
+- Q_D(QSaveFile);
+- d->fileName = name;
+-}
+-
+-/*!
+- Destroys the file object, discarding the saved contents unless commit() was called.
+-*/
+-QSaveFile::~QSaveFile()
+-{
+- Q_D(QSaveFile);
+- if (d->tempFile) {
+- d->tempFile->setAutoRemove(true);
+- delete d->tempFile;
+- }
+- QIODevice::close();
+- delete d;
+-}
+-
+-/*!
+- Returns false since temporary files support random access.
+-
+- \sa QIODevice::isSequential()
+-*/
+-bool QSaveFile::isSequential() const
+-{
+- return false;
+-}
+-
+-/*!
+- Returns the file error status.
+-
+- The I/O device status returns an error code. For example, if open()
+- returns false, or a read/write operation returns -1, this function can
+- be called to find out the reason why the operation failed.
+-
+- Unlike QFile which clears the error on the next operation, QSaveFile remembers
+- the error until the file is closed, in order to discard the file contents in close().
+-
+- \sa unsetError()
+-*/
+-
+-QFile::FileError QSaveFile::error() const
+-{
+- return d_func()->error;
+-}
+-
+-/*!
+- Sets the file's error to QFile::NoError.
+-
+- This will make QSaveFile forget that an error happened during saving, so you
+- probably don't want to call this, unless you're really sure that you want to
+- save the file anyway.
+-
+- \sa error()
+-*/
+-void QSaveFile::unsetError()
+-{
+- d_func()->error = QFile::NoError;
+- setErrorString(QString());
+-}
+-
+-/*!
+- Returns the name set by setFileName() or to the QSaveFile
+- constructor.
+-
+- \sa setFileName()
+-*/
+-QString QSaveFile::fileName() const
+-{
+- return d_func()->fileName;
+-}
+-
+-/*!
+- Sets the \a name of the file. The name can have no path, a
+- relative path, or an absolute path.
+-
+- \sa QFile::setFileName(), fileName()
+-*/
+-void QSaveFile::setFileName(const QString &name)
+-{
+- d_func()->fileName = name;
+-}
+-
+-/*!
+- Opens the file using OpenMode \a mode, returning true if successful;
+- otherwise false.
+-
+- Important: the \a mode must be QIODevice::WriteOnly.
+- It may also have additional flags, such as QIODevice::Text and QIODevice::Unbuffered.
+-
+- QIODevice::ReadWrite and QIODevice::Append are not supported at the moment.
+-
+- \sa QIODevice::OpenMode, setFileName()
+-*/
+-bool QSaveFile::open(OpenMode mode)
+-{
+- Q_D(QSaveFile);
+- if (isOpen()) {
+- qWarning("QSaveFile::open: File (%s) already open", qPrintable(fileName()));
+- return false;
+- }
+- unsetError();
+- if ((mode & (ReadOnly | WriteOnly)) == 0) {
+- qWarning("QSaveFile::open: Open mode not specified");
+- return false;
+- }
+- // In the future we could implement Append and ReadWrite by copying from the existing file to the temp file...
+- if ((mode & ReadOnly) || (mode & Append)) {
+- qWarning("QSaveFile::open: Unsupported open mode %d", int(mode));
+- return false;
+- }
+-
+- // check if existing file is writable
+- QFileInfo existingFile(d->fileName);
+- if (existingFile.exists() && !existingFile.isWritable()) {
+- d->error = QFile::WriteError;
+- setErrorString(QSaveFile::tr("Existing file %1 is not writable").arg(d->fileName));
+- return false;
+- }
+- d->tempFile = new QTemporaryFile;
+- d->tempFile->setAutoRemove(false);
+- d->tempFile->setFileTemplate(d->fileName);
+- if (!d->tempFile->open()) {
+- d->error = d->tempFile->error();
+- setErrorString(d->tempFile->errorString());
+- delete d->tempFile;
+- d->tempFile = 0;
+- return false;
+- }
+- QIODevice::open(mode);
+- if (existingFile.exists())
+- d->tempFile->setPermissions(existingFile.permissions());
+- return true;
+-}
+-
+-/*!
+- \reimp
+- Cannot be called.
+- Call commit() instead.
+-*/
+-void QSaveFile::close()
+-{
+- qFatal("QSaveFile::close called");
+-}
+-
+-/*
+- Commits the changes to disk, if all previous writes were successful.
+-
+- It is mandatory to call this at the end of the saving operation, otherwise the file will be
+- discarded.
+-
+- If an error happened during writing, deletes the temporary file and returns false.
+- Otherwise, renames it to the final fileName and returns true on success.
+- Finally, closes the device.
+-
+- \sa cancelWriting()
+-*/
+-bool QSaveFile::commit()
+-{
+- Q_D(QSaveFile);
+- if (!d->tempFile)
+- return false;
+- if (!isOpen()) {
+- qWarning("QSaveFile::commit: File (%s) is not open", qPrintable(fileName()));
+- return false;
+- }
+- flush();
+-#ifdef Q_OS_WIN
+- FlushFileBuffers(reinterpret_cast<HANDLE>(handle()));
+-#elif defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
+- fdatasync(d->tempFile->handle());
+-#else
+- fsync(d->tempFile->handle());
+-#endif
+- QIODevice::close();
+- if (d->error != QFile::NoError) {
+- d->tempFile->remove();
+- unsetError();
+- delete d->tempFile;
+- d->tempFile = 0;
+- return false;
+- }
+- d->tempFile->close();
+-#ifdef Q_OS_WIN
+- // On Windows QAbstractFileEngine::rename() fails if the the target exists,
+- // so we have to rename the target.
+- // Ideally the winapi ReplaceFile() method should be used.
+- QString bakname = d->fileName + "~";
+- QFile::remove(bakname);
+- QFile::rename(d->fileName, bakname);
+-#endif
+- QAbstractFileEngine* fileEngine = d->tempFile->fileEngine();
+- Q_ASSERT(fileEngine);
+- if (!fileEngine->rename(d->fileName)) {
+- d->error = fileEngine->error();
+- setErrorString(fileEngine->errorString());
+- d->tempFile->remove();
+- delete d->tempFile;
+- d->tempFile = 0;
+-#ifdef Q_OS_WIN
+- QFile::rename(bakname, d->fileName);
+-#endif
+- return false;
+- }
+- delete d->tempFile;
+- d->tempFile = 0;
+-#ifdef Q_OS_WIN
+- QFile::remove(bakname);
+-#endif
+- return true;
+-}
+-
+-/*!
+- Sets an error code so that commit() discards the temporary file.
+-
+- Further write operations are possible after calling this method, but none
+- of it will have any effect, the written file will be discarded.
+-
+- \sa commit()
+-*/
+-void QSaveFile::cancelWriting()
+-{
+- if (!isOpen())
+- return;
+- d_func()->error = QFile::WriteError;
+- setErrorString(QSaveFile::tr("Writing canceled by application"));
+-}
+-
+-/*!
+- Returns the size of the file.
+- \sa QFile::size()
+-*/
+-qint64 QSaveFile::size() const
+-{
+- Q_D(const QSaveFile);
+- return d->tempFile ? d->tempFile->size() : qint64(-1);
+-}
+-
+-/*!
+- \reimp
+-*/
+-qint64 QSaveFile::pos() const
+-{
+- Q_D(const QSaveFile);
+- return d->tempFile ? d->tempFile->pos() : qint64(-1);
+-}
+-
+-/*!
+- \reimp
+-*/
+-bool QSaveFile::seek(qint64 offset)
+-{
+- Q_D(QSaveFile);
+- return d->tempFile ? d->tempFile->seek(offset) : false;
+-}
+-
+-/*!
+- \reimp
+-*/
+-bool QSaveFile::atEnd() const
+-{
+- Q_D(const QSaveFile);
+- return d->tempFile ? d->tempFile->atEnd() : true;
+-}
+-
+-/*!
+- Flushes any buffered data to the file. Returns true if successful;
+- otherwise returns false.
+-*/
+-bool QSaveFile::flush()
+-{
+- Q_D(QSaveFile);
+- if (d->tempFile) {
+- if (!d->tempFile->flush()) {
+- d->error = d->tempFile->error();
+- setErrorString(d->tempFile->errorString());
+- return false;
+- }
+- return true;
+- }
+- return false;
+-}
+-
+-/*!
+- Returns the file handle of the temporary file.
+-
+- \sa QFile::handle()
+-*/
+-int QSaveFile::handle() const
+-{
+- Q_D(const QSaveFile);
+- return d->tempFile ? d->tempFile->handle() : -1;
+-}
+-
+-/*!
+- \reimp
+-*/
+-qint64 QSaveFile::readData(char *data, qint64 maxlen)
+-{
+- Q_D(QSaveFile);
+- return d->tempFile ? d->tempFile->read(data, maxlen) : -1;
+-}
+-
+-/*!
+- \reimp
+-*/
+-qint64 QSaveFile::writeData(const char *data, qint64 len)
+-{
+- Q_D(QSaveFile);
+- if (!d->tempFile)
+- return -1;
+- const qint64 written = d->tempFile->write(data, len);
+- if (written != len) {
+- d->error = QFile::WriteError;
+- setErrorString(QSaveFile::tr("Partial write. Partition full?"));
+- }
+- return written;
+-}
+-
+-/*!
+- \reimp
+-*/
+-qint64 QSaveFile::readLineData(char *data, qint64 maxlen)
+-{
+- Q_D(QSaveFile);
+- return d->tempFile ? d->tempFile->readLine(data, maxlen) : -1;
+-}
+diff --git a/src/core/qsavefile.h b/src/core/qsavefile.h
+deleted file mode 100644
+index 84d5a24..0000000
+--- a/src/core/qsavefile.h
++++ /dev/null
+@@ -1,105 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+-** Contact: http://www.qt-project.org/
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL$
+-** GNU Lesser General Public License Usage
+-** This file may be used under the terms of the GNU Lesser General Public
+-** License version 2.1 as published by the Free Software Foundation and
+-** appearing in the file LICENSE.LGPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU Lesser
+-** General Public License version 2.1 requirements will be met:
+-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Nokia gives you certain additional
+-** rights. These rights are described in the Nokia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU General
+-** Public License version 3.0 as published by the Free Software Foundation
+-** and appearing in the file LICENSE.GPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU General
+-** Public License version 3.0 requirements will be met:
+-** http://www.gnu.org/copyleft/gpl.html.
+-**
+-** Other Usage
+-** Alternatively, this file may be used in accordance with the terms and
+-** conditions contained in a signed written agreement between you and Nokia.
+-**
+-**
+-**
+-**
+-**
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#ifndef QSAVEFILE_H
+-#define QSAVEFILE_H
+-
+-#include <QFile>
+-#include <QString>
+-
+-#ifdef open
+-#error qsavefile.h must be included before any header file that defines open
+-#endif
+-
+-class QAbstractFileEngine;
+-class QSaveFilePrivate;
+-
+-class QSaveFile : public QIODevice
+-{
+- Q_OBJECT
+- Q_DECLARE_PRIVATE(QSaveFile)
+-
+-public:
+-
+- QSaveFile();
+- explicit QSaveFile(const QString &name);
+- explicit QSaveFile(QObject *parent);
+- QSaveFile(const QString &name, QObject *parent);
+- ~QSaveFile();
+-
+- QFile::FileError error() const;
+- void unsetError();
+-
+- QString fileName() const;
+- void setFileName(const QString &name);
+-
+- bool isSequential() const;
+-
+- virtual bool open(OpenMode flags);
+- bool commit();
+-
+- void cancelWriting();
+-
+- qint64 size() const;
+- qint64 pos() const;
+- bool seek(qint64 offset);
+- bool atEnd() const;
+- bool flush();
+-
+- bool resize(qint64 sz);
+-
+- int handle() const;
+-
+-protected:
+- qint64 readData(char *data, qint64 maxlen);
+- qint64 writeData(const char *data, qint64 len);
+- qint64 readLineData(char *data, qint64 maxlen);
+-
+-private:
+- virtual void close();
+-
+-private:
+- Q_DISABLE_COPY(QSaveFile)
+-
+- QSaveFilePrivate* const d_ptr;
+-};
+-
+-#endif // QSAVEFILE_H
+diff --git a/src/core/qsavefile_p.h b/src/core/qsavefile_p.h
+deleted file mode 100644
+index 549ecc1..0000000
+--- a/src/core/qsavefile_p.h
++++ /dev/null
+@@ -1,71 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+-** Contact: http://www.qt-project.org/
+-**
+-** This file is part of the QtCore module of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL$
+-** GNU Lesser General Public License Usage
+-** This file may be used under the terms of the GNU Lesser General Public
+-** License version 2.1 as published by the Free Software Foundation and
+-** appearing in the file LICENSE.LGPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU Lesser
+-** General Public License version 2.1 requirements will be met:
+-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Nokia gives you certain additional
+-** rights. These rights are described in the Nokia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU General
+-** Public License version 3.0 as published by the Free Software Foundation
+-** and appearing in the file LICENSE.GPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU General
+-** Public License version 3.0 requirements will be met:
+-** http://www.gnu.org/copyleft/gpl.html.
+-**
+-** Other Usage
+-** Alternatively, this file may be used in accordance with the terms and
+-** conditions contained in a signed written agreement between you and Nokia.
+-**
+-**
+-**
+-**
+-**
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#ifndef QSAVEFILE_P_H
+-#define QSAVEFILE_P_H
+-
+-//
+-// W A R N I N G
+-// -------------
+-//
+-// This file is not part of the Qt API. It exists purely as an
+-// implementation detail. This header file may change from version to
+-// version without notice, or even be removed.
+-//
+-// We mean it.
+-//
+-
+-#include <QTemporaryFile>
+-
+-class QSaveFilePrivate
+-{
+-public:
+- QSaveFilePrivate();
+- ~QSaveFilePrivate();
+-
+- QString fileName;
+- QTemporaryFile *tempFile;
+-
+- QFile::FileError error;
+-};
+-
+-#endif // QSAVEFILE_P_H
+-
+diff --git a/src/crypto/Crypto.cpp b/src/crypto/Crypto.cpp
+index 40ec7ea..1ff6fde 100644
+--- a/src/crypto/Crypto.cpp
++++ b/src/crypto/Crypto.cpp
+@@ -29,43 +29,6 @@ bool Crypto::m_initalized(false);
+ QString Crypto::m_errorStr;
+ QString Crypto::m_backendVersion;
+
+-#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
+-static int gcry_qt_mutex_init(void** p_sys)
+-{
+- *p_sys = new QMutex();
+- return 0;
+-}
+-
+-static int gcry_qt_mutex_destroy(void** p_sys)
+-{
+- delete reinterpret_cast<QMutex*>(*p_sys);
+- return 0;
+-}
+-
+-static int gcry_qt_mutex_lock(void** p_sys)
+-{
+- reinterpret_cast<QMutex*>(*p_sys)->lock();
+- return 0;
+-}
+-
+-static int gcry_qt_mutex_unlock(void** p_sys)
+-{
+- reinterpret_cast<QMutex*>(*p_sys)->unlock();
+- return 0;
+-}
+-
+-static const struct gcry_thread_cbs gcry_threads_qt =
+-{
+- GCRY_THREAD_OPTION_USER,
+- 0,
+- gcry_qt_mutex_init,
+- gcry_qt_mutex_destroy,
+- gcry_qt_mutex_lock,
+- gcry_qt_mutex_unlock,
+- 0, 0, 0, 0, 0, 0, 0, 0
+-};
+-#endif
+-
+ Crypto::Crypto()
+ {
+ }
+@@ -77,10 +40,6 @@ bool Crypto::init()
+ return true;
+ }
+
+- // libgcrypt >= 1.6 doesn't allow custom thread callbacks anymore.
+-#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
+- gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_qt);
+-#endif
+ m_backendVersion = QString::fromLocal8Bit(gcry_check_version(0));
+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+@@ -121,18 +80,18 @@ bool Crypto::backendSelfTest()
+
+ bool Crypto::checkAlgorithms()
+ {
+- if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) {
++ if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) {
+ m_errorStr = "GCRY_CIPHER_AES256 not found.";
+ qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
+ return false;
+ }
+- if (gcry_cipher_algo_info(GCRY_CIPHER_TWOFISH, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) {
++ if (gcry_cipher_algo_info(GCRY_CIPHER_TWOFISH, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) {
+ m_errorStr = "GCRY_CIPHER_TWOFISH not found.";
+ qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
+ return false;
+ }
+ #ifdef GCRYPT_HAS_SALSA20
+- if (gcry_cipher_algo_info(GCRY_CIPHER_SALSA20, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) {
++ if (gcry_cipher_algo_info(GCRY_CIPHER_SALSA20, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) {
+ m_errorStr = "GCRY_CIPHER_SALSA20 not found.";
+ qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
+ return false;
+diff --git a/src/crypto/Crypto.h b/src/crypto/Crypto.h
+index 1726865..0ce2903 100644
+--- a/src/crypto/Crypto.h
++++ b/src/crypto/Crypto.h
+@@ -20,8 +20,6 @@
+
+ #include <QString>
+
+-#include "core/Global.h"
+-
+ class Crypto
+ {
+ public:
+diff --git a/src/crypto/Random.cpp b/src/crypto/Random.cpp
+index 2a375f3..dc0667f 100644
+--- a/src/crypto/Random.cpp
++++ b/src/crypto/Random.cpp
+@@ -19,15 +19,16 @@
+
+ #include <gcrypt.h>
+
++#include "core/Global.h"
+ #include "crypto/Crypto.h"
+
+ class RandomBackendGcrypt : public RandomBackend
+ {
+ public:
+- void randomize(void* data, int len) Q_DECL_OVERRIDE;
++ void randomize(void* data, int len) override;
+ };
+
+-Random* Random::m_instance(Q_NULLPTR);
++Random* Random::m_instance(nullptr);
+
+ void Random::randomize(QByteArray& ba)
+ {
+diff --git a/src/crypto/SymmetricCipher.cpp b/src/crypto/SymmetricCipher.cpp
+index 454548c..12ec264 100644
+--- a/src/crypto/SymmetricCipher.cpp
++++ b/src/crypto/SymmetricCipher.cpp
+@@ -19,7 +19,6 @@
+
+ #include "config-keepassx.h"
+ #include "crypto/SymmetricCipherGcrypt.h"
+-#include "crypto/SymmetricCipherSalsa20.h"
+
+ SymmetricCipher::SymmetricCipher(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
+ SymmetricCipher::Direction direction)
+@@ -61,19 +60,12 @@ SymmetricCipherBackend* SymmetricCipher::createBackend(SymmetricCipher::Algorith
+ switch (algo) {
+ case SymmetricCipher::Aes256:
+ case SymmetricCipher::Twofish:
+-#if defined(GCRYPT_HAS_SALSA20)
+ case SymmetricCipher::Salsa20:
+-#endif
+ return new SymmetricCipherGcrypt(algo, mode, direction);
+
+-#if !defined(GCRYPT_HAS_SALSA20)
+- case SymmetricCipher::Salsa20:
+- return new SymmetricCipherSalsa20(algo, mode, direction);
+-#endif
+-
+ default:
+ Q_ASSERT(false);
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h
+index b8b3eb1..4fc06b7 100644
+--- a/src/crypto/SymmetricCipher.h
++++ b/src/crypto/SymmetricCipher.h
+@@ -22,7 +22,6 @@
+ #include <QScopedPointer>
+ #include <QString>
+
+-#include "core/Global.h"
+ #include "crypto/SymmetricCipherBackend.h"
+
+ class SymmetricCipher
+diff --git a/src/crypto/SymmetricCipherGcrypt.cpp b/src/crypto/SymmetricCipherGcrypt.cpp
+index 5c4fe6a..cd43240 100644
+--- a/src/crypto/SymmetricCipherGcrypt.cpp
++++ b/src/crypto/SymmetricCipherGcrypt.cpp
+@@ -22,7 +22,7 @@
+
+ SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
+ SymmetricCipher::Direction direction)
+- : m_ctx(Q_NULLPTR)
++ : m_ctx(nullptr)
+ , m_algo(gcryptAlgo(algo))
+ , m_mode(gcryptMode(mode))
+ , m_direction(direction)
+@@ -44,10 +44,8 @@ int SymmetricCipherGcrypt::gcryptAlgo(SymmetricCipher::Algorithm algo)
+ case SymmetricCipher::Twofish:
+ return GCRY_CIPHER_TWOFISH;
+
+-#ifdef GCRYPT_HAS_SALSA20
+ case SymmetricCipher::Salsa20:
+ return GCRY_CIPHER_SALSA20;
+-#endif
+
+ default:
+ Q_ASSERT(false);
+@@ -95,7 +93,7 @@ bool SymmetricCipherGcrypt::init()
+ }
+
+ size_t blockSizeT;
+- error = gcry_cipher_algo_info(m_algo, GCRYCTL_GET_BLKLEN, Q_NULLPTR, &blockSizeT);
++ error = gcry_cipher_algo_info(m_algo, GCRYCTL_GET_BLKLEN, nullptr, &blockSizeT);
+ if (error != 0) {
+ setErrorString(error);
+ return false;
+@@ -163,10 +161,10 @@ bool SymmetricCipherGcrypt::processInPlace(QByteArray& data)
+ gcry_error_t error;
+
+ if (m_direction == SymmetricCipher::Decrypt) {
+- error = gcry_cipher_decrypt(m_ctx, data.data(), data.size(), Q_NULLPTR, 0);
++ error = gcry_cipher_decrypt(m_ctx, data.data(), data.size(), nullptr, 0);
+ }
+ else {
+- error = gcry_cipher_encrypt(m_ctx, data.data(), data.size(), Q_NULLPTR, 0);
++ error = gcry_cipher_encrypt(m_ctx, data.data(), data.size(), nullptr, 0);
+ }
+
+ if (error != 0) {
+@@ -188,7 +186,7 @@ bool SymmetricCipherGcrypt::processInPlace(QByteArray& data, quint64 rounds)
+
+ if (m_direction == SymmetricCipher::Decrypt) {
+ for (quint64 i = 0; i != rounds; ++i) {
+- error = gcry_cipher_decrypt(m_ctx, rawData, size, Q_NULLPTR, 0);
++ error = gcry_cipher_decrypt(m_ctx, rawData, size, nullptr, 0);
+
+ if (error != 0) {
+ setErrorString(error);
+@@ -198,7 +196,7 @@ bool SymmetricCipherGcrypt::processInPlace(QByteArray& data, quint64 rounds)
+ }
+ else {
+ for (quint64 i = 0; i != rounds; ++i) {
+- error = gcry_cipher_encrypt(m_ctx, rawData, size, Q_NULLPTR, 0);
++ error = gcry_cipher_encrypt(m_ctx, rawData, size, nullptr, 0);
+
+ if (error != 0) {
+ setErrorString(error);
+diff --git a/src/crypto/salsa20/ecrypt-config.h b/src/crypto/salsa20/ecrypt-config.h
+deleted file mode 100644
+index 0914fbc..0000000
+--- a/src/crypto/salsa20/ecrypt-config.h
++++ /dev/null
+@@ -1,260 +0,0 @@
+-/* ecrypt-config.h */
+-
+-/* *** Normally, it should not be necessary to edit this file. *** */
+-
+-#ifndef ECRYPT_CONFIG
+-#define ECRYPT_CONFIG
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/* Guess the endianness of the target architecture. */
+-
+-#include <QtGlobal>
+-
+-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+-#define ECRYPT_LITTLE_ENDIAN
+-#elif Q_BYTE_ORDER == Q_BIG_ENDIAN
+-#define ECRYPT_BIG_ENDIAN
+-#else
+-#define ECRYPT_UNKNOWN
+-#endif
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/*
+- * Find minimal-width types to store 8-bit, 16-bit, 32-bit, and 64-bit
+- * integers.
+- *
+- * Note: to enable 64-bit types on 32-bit compilers, it might be
+- * necessary to switch from ISO C90 mode to ISO C99 mode (e.g., gcc
+- * -std=c99), or to allow compiler-specific extensions.
+- */
+-
+-#include <limits.h>
+-
+-/* --- check char --- */
+-
+-#if (UCHAR_MAX / 0xFU > 0xFU)
+-#ifndef I8T
+-#define I8T char
+-#define U8C(v) (v##U)
+-
+-#if (UCHAR_MAX == 0xFFU)
+-#define ECRYPT_I8T_IS_BYTE
+-#endif
+-
+-#endif
+-
+-#if (UCHAR_MAX / 0xFFU > 0xFFU)
+-#ifndef I16T
+-#define I16T char
+-#define U16C(v) (v##U)
+-#endif
+-
+-#if (UCHAR_MAX / 0xFFFFU > 0xFFFFU)
+-#ifndef I32T
+-#define I32T char
+-#define U32C(v) (v##U)
+-#endif
+-
+-#if (UCHAR_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU)
+-#ifndef I64T
+-#define I64T char
+-#define U64C(v) (v##U)
+-#define ECRYPT_NATIVE64
+-#endif
+-
+-#endif
+-#endif
+-#endif
+-#endif
+-
+-/* --- check short --- */
+-
+-#if (USHRT_MAX / 0xFU > 0xFU)
+-#ifndef I8T
+-#define I8T short
+-#define U8C(v) (v##U)
+-
+-#if (USHRT_MAX == 0xFFU)
+-#define ECRYPT_I8T_IS_BYTE
+-#endif
+-
+-#endif
+-
+-#if (USHRT_MAX / 0xFFU > 0xFFU)
+-#ifndef I16T
+-#define I16T short
+-#define U16C(v) (v##U)
+-#endif
+-
+-#if (USHRT_MAX / 0xFFFFU > 0xFFFFU)
+-#ifndef I32T
+-#define I32T short
+-#define U32C(v) (v##U)
+-#endif
+-
+-#if (USHRT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU)
+-#ifndef I64T
+-#define I64T short
+-#define U64C(v) (v##U)
+-#define ECRYPT_NATIVE64
+-#endif
+-
+-#endif
+-#endif
+-#endif
+-#endif
+-
+-/* --- check int --- */
+-
+-#if (UINT_MAX / 0xFU > 0xFU)
+-#ifndef I8T
+-#define I8T int
+-#define U8C(v) (v##U)
+-
+-#if (ULONG_MAX == 0xFFU)
+-#define ECRYPT_I8T_IS_BYTE
+-#endif
+-
+-#endif
+-
+-#if (UINT_MAX / 0xFFU > 0xFFU)
+-#ifndef I16T
+-#define I16T int
+-#define U16C(v) (v##U)
+-#endif
+-
+-#if (UINT_MAX / 0xFFFFU > 0xFFFFU)
+-#ifndef I32T
+-#define I32T int
+-#define U32C(v) (v##U)
+-#endif
+-
+-#if (UINT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU)
+-#ifndef I64T
+-#define I64T int
+-#define U64C(v) (v##U)
+-#define ECRYPT_NATIVE64
+-#endif
+-
+-#endif
+-#endif
+-#endif
+-#endif
+-
+-/* --- check long --- */
+-
+-#if (ULONG_MAX / 0xFUL > 0xFUL)
+-#ifndef I8T
+-#define I8T long
+-#define U8C(v) (v##UL)
+-
+-#if (ULONG_MAX == 0xFFUL)
+-#define ECRYPT_I8T_IS_BYTE
+-#endif
+-
+-#endif
+-
+-#if (ULONG_MAX / 0xFFUL > 0xFFUL)
+-#ifndef I16T
+-#define I16T long
+-#define U16C(v) (v##UL)
+-#endif
+-
+-#if (ULONG_MAX / 0xFFFFUL > 0xFFFFUL)
+-#ifndef I32T
+-#define I32T long
+-#define U32C(v) (v##UL)
+-#endif
+-
+-#if (ULONG_MAX / 0xFFFFFFFFUL > 0xFFFFFFFFUL)
+-#ifndef I64T
+-#define I64T long
+-#define U64C(v) (v##UL)
+-#define ECRYPT_NATIVE64
+-#endif
+-
+-#endif
+-#endif
+-#endif
+-#endif
+-
+-/* --- check long long --- */
+-
+-#ifdef ULLONG_MAX
+-
+-#if (ULLONG_MAX / 0xFULL > 0xFULL)
+-#ifndef I8T
+-#define I8T long long
+-#define U8C(v) (v##ULL)
+-
+-#if (ULLONG_MAX == 0xFFULL)
+-#define ECRYPT_I8T_IS_BYTE
+-#endif
+-
+-#endif
+-
+-#if (ULLONG_MAX / 0xFFULL > 0xFFULL)
+-#ifndef I16T
+-#define I16T long long
+-#define U16C(v) (v##ULL)
+-#endif
+-
+-#if (ULLONG_MAX / 0xFFFFULL > 0xFFFFULL)
+-#ifndef I32T
+-#define I32T long long
+-#define U32C(v) (v##ULL)
+-#endif
+-
+-#if (ULLONG_MAX / 0xFFFFFFFFULL > 0xFFFFFFFFULL)
+-#ifndef I64T
+-#define I64T long long
+-#define U64C(v) (v##ULL)
+-#endif
+-
+-#endif
+-#endif
+-#endif
+-#endif
+-
+-#endif
+-
+-/* --- check __int64 --- */
+-
+-#if !defined(__STDC__) && defined(_UI64_MAX)
+-
+-#ifndef I64T
+-#define I64T __int64
+-#define U64C(v) (v##ui64)
+-#endif
+-
+-#endif
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/* find the largest type on this platform (used for alignment) */
+-
+-#if defined(__SSE__) || (defined(_MSC_VER) && (_MSC_VER >= 1300))
+-
+-#include <xmmintrin.h>
+-#define MAXT __m128
+-
+-#elif defined(__MMX__)
+-
+-#include <mmintrin.h>
+-#define MAXT __m64
+-
+-#elif defined(__ALTIVEC__)
+-
+-#define MAXT __vector int
+-
+-#else
+-
+-#define MAXT long
+-
+-#endif
+-
+-/* ------------------------------------------------------------------------- */
+-
+-#endif
+diff --git a/src/crypto/salsa20/ecrypt-machine.h b/src/crypto/salsa20/ecrypt-machine.h
+deleted file mode 100644
+index d006bed..0000000
+--- a/src/crypto/salsa20/ecrypt-machine.h
++++ /dev/null
+@@ -1,49 +0,0 @@
+-/* ecrypt-machine.h */
+-
+-/*
+- * This file is included by 'ecrypt-portable.h'. It allows to override
+- * the default macros for specific platforms. Please carefully check
+- * the machine code generated by your compiler (with optimisations
+- * turned on) before deciding to edit this file.
+- */
+-
+-/* ------------------------------------------------------------------------- */
+-
+-#if (defined(ECRYPT_DEFAULT_ROT) && !defined(ECRYPT_MACHINE_ROT))
+-
+-#define ECRYPT_MACHINE_ROT
+-
+-#if (defined(WIN32) && defined(_MSC_VER))
+-
+-#undef ROTL32
+-#undef ROTR32
+-#undef ROTL64
+-#undef ROTR64
+-
+-#include <stdlib.h>
+-
+-#pragma intrinsic(_lrotl) /* compile rotations "inline" */
+-#pragma intrinsic(_lrotr)
+-
+-#define ROTL32(v, n) _lrotl(v, n)
+-#define ROTR32(v, n) _lrotr(v, n)
+-#define ROTL64(v, n) _rotl64(v, n)
+-#define ROTR64(v, n) _rotr64(v, n)
+-
+-#endif
+-
+-#endif
+-
+-/* ------------------------------------------------------------------------- */
+-
+-#if (defined(ECRYPT_DEFAULT_SWAP) && !defined(ECRYPT_MACHINE_SWAP))
+-
+-#define ECRYPT_MACHINE_SWAP
+-
+-/*
+- * If you want to overwrite the default swap macros, put it here. And so on.
+- */
+-
+-#endif
+-
+-/* ------------------------------------------------------------------------- */
+diff --git a/src/crypto/salsa20/ecrypt-portable.h b/src/crypto/salsa20/ecrypt-portable.h
+deleted file mode 100644
+index 438a464..0000000
+--- a/src/crypto/salsa20/ecrypt-portable.h
++++ /dev/null
+@@ -1,310 +0,0 @@
+-/* ecrypt-portable.h */
+-
+-/*
+- * WARNING: the conversions defined below are implemented as macros,
+- * and should be used carefully. They should NOT be used with
+- * parameters which perform some action. E.g., the following two lines
+- * are not equivalent:
+- *
+- * 1) ++x; y = ROTL32(x, n);
+- * 2) y = ROTL32(++x, n);
+- */
+-
+-/*
+- * *** Please do not edit this file. ***
+- *
+- * The default macros can be overridden for specific architectures by
+- * editing 'ecrypt-machine.h'.
+- */
+-
+-#ifndef ECRYPT_PORTABLE
+-#define ECRYPT_PORTABLE
+-
+-#include "ecrypt-config.h"
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/*
+- * The following types are defined (if available):
+- *
+- * u8: unsigned integer type, at least 8 bits
+- * u16: unsigned integer type, at least 16 bits
+- * u32: unsigned integer type, at least 32 bits
+- * u64: unsigned integer type, at least 64 bits
+- *
+- * s8, s16, s32, s64 -> signed counterparts of u8, u16, u32, u64
+- *
+- * The selection of minimum-width integer types is taken care of by
+- * 'ecrypt-config.h'. Note: to enable 64-bit types on 32-bit
+- * compilers, it might be necessary to switch from ISO C90 mode to ISO
+- * C99 mode (e.g., gcc -std=c99).
+- */
+-
+-#ifdef I8T
+-typedef signed I8T s8;
+-typedef unsigned I8T u8;
+-#endif
+-
+-#ifdef I16T
+-typedef signed I16T s16;
+-typedef unsigned I16T u16;
+-#endif
+-
+-#ifdef I32T
+-typedef signed I32T s32;
+-typedef unsigned I32T u32;
+-#endif
+-
+-#ifdef I64T
+-typedef signed I64T s64;
+-typedef unsigned I64T u64;
+-#endif
+-
+-/*
+- * The following macros are used to obtain exact-width results.
+- */
+-
+-#define U8V(v) ((u8)(v) & U8C(0xFF))
+-#define U16V(v) ((u16)(v) & U16C(0xFFFF))
+-#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
+-#define U64V(v) ((u64)(v) & U64C(0xFFFFFFFFFFFFFFFF))
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/*
+- * The following macros return words with their bits rotated over n
+- * positions to the left/right.
+- */
+-
+-#define ECRYPT_DEFAULT_ROT
+-
+-#define ROTL8(v, n) \
+- (U8V((v) << (n)) | ((v) >> (8 - (n))))
+-
+-#define ROTL16(v, n) \
+- (U16V((v) << (n)) | ((v) >> (16 - (n))))
+-
+-#define ROTL32(v, n) \
+- (U32V((v) << (n)) | ((v) >> (32 - (n))))
+-
+-#define ROTL64(v, n) \
+- (U64V((v) << (n)) | ((v) >> (64 - (n))))
+-
+-#define ROTR8(v, n) ROTL8(v, 8 - (n))
+-#define ROTR16(v, n) ROTL16(v, 16 - (n))
+-#define ROTR32(v, n) ROTL32(v, 32 - (n))
+-#define ROTR64(v, n) ROTL64(v, 64 - (n))
+-
+-#include "ecrypt-machine.h"
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/*
+- * The following macros return a word with bytes in reverse order.
+- */
+-
+-#define ECRYPT_DEFAULT_SWAP
+-
+-#define SWAP16(v) \
+- ROTL16(v, 8)
+-
+-#define SWAP32(v) \
+- ((ROTL32(v, 8) & U32C(0x00FF00FF)) | \
+- (ROTL32(v, 24) & U32C(0xFF00FF00)))
+-
+-#ifdef ECRYPT_NATIVE64
+-#define SWAP64(v) \
+- ((ROTL64(v, 8) & U64C(0x000000FF000000FF)) | \
+- (ROTL64(v, 24) & U64C(0x0000FF000000FF00)) | \
+- (ROTL64(v, 40) & U64C(0x00FF000000FF0000)) | \
+- (ROTL64(v, 56) & U64C(0xFF000000FF000000)))
+-#else
+-#define SWAP64(v) \
+- (((u64)SWAP32(U32V(v)) << 32) | (u64)SWAP32(U32V(v >> 32)))
+-#endif
+-
+-#include "ecrypt-machine.h"
+-
+-#define ECRYPT_DEFAULT_WTOW
+-
+-#ifdef ECRYPT_LITTLE_ENDIAN
+-#define U16TO16_LITTLE(v) (v)
+-#define U32TO32_LITTLE(v) (v)
+-#define U64TO64_LITTLE(v) (v)
+-
+-#define U16TO16_BIG(v) SWAP16(v)
+-#define U32TO32_BIG(v) SWAP32(v)
+-#define U64TO64_BIG(v) SWAP64(v)
+-#endif
+-
+-#ifdef ECRYPT_BIG_ENDIAN
+-#define U16TO16_LITTLE(v) SWAP16(v)
+-#define U32TO32_LITTLE(v) SWAP32(v)
+-#define U64TO64_LITTLE(v) SWAP64(v)
+-
+-#define U16TO16_BIG(v) (v)
+-#define U32TO32_BIG(v) (v)
+-#define U64TO64_BIG(v) (v)
+-#endif
+-
+-#include "ecrypt-machine.h"
+-
+-/*
+- * The following macros load words from an array of bytes with
+- * different types of endianness, and vice versa.
+- */
+-
+-#define ECRYPT_DEFAULT_BTOW
+-
+-#if (!defined(ECRYPT_UNKNOWN) && defined(ECRYPT_I8T_IS_BYTE))
+-
+-#define U8TO16_LITTLE(p) U16TO16_LITTLE(((u16*)(p))[0])
+-#define U8TO32_LITTLE(p) U32TO32_LITTLE(((u32*)(p))[0])
+-#define U8TO64_LITTLE(p) U64TO64_LITTLE(((u64*)(p))[0])
+-
+-#define U8TO16_BIG(p) U16TO16_BIG(((u16*)(p))[0])
+-#define U8TO32_BIG(p) U32TO32_BIG(((u32*)(p))[0])
+-#define U8TO64_BIG(p) U64TO64_BIG(((u64*)(p))[0])
+-
+-#define U16TO8_LITTLE(p, v) (((u16*)(p))[0] = U16TO16_LITTLE(v))
+-#define U32TO8_LITTLE(p, v) (((u32*)(p))[0] = U32TO32_LITTLE(v))
+-#define U64TO8_LITTLE(p, v) (((u64*)(p))[0] = U64TO64_LITTLE(v))
+-
+-#define U16TO8_BIG(p, v) (((u16*)(p))[0] = U16TO16_BIG(v))
+-#define U32TO8_BIG(p, v) (((u32*)(p))[0] = U32TO32_BIG(v))
+-#define U64TO8_BIG(p, v) (((u64*)(p))[0] = U64TO64_BIG(v))
+-
+-#else
+-
+-#define U8TO16_LITTLE(p) \
+- (((u16)((p)[0]) ) | \
+- ((u16)((p)[1]) << 8))
+-
+-#define U8TO32_LITTLE(p) \
+- (((u32)((p)[0]) ) | \
+- ((u32)((p)[1]) << 8) | \
+- ((u32)((p)[2]) << 16) | \
+- ((u32)((p)[3]) << 24))
+-
+-#ifdef ECRYPT_NATIVE64
+-#define U8TO64_LITTLE(p) \
+- (((u64)((p)[0]) ) | \
+- ((u64)((p)[1]) << 8) | \
+- ((u64)((p)[2]) << 16) | \
+- ((u64)((p)[3]) << 24) | \
+- ((u64)((p)[4]) << 32) | \
+- ((u64)((p)[5]) << 40) | \
+- ((u64)((p)[6]) << 48) | \
+- ((u64)((p)[7]) << 56))
+-#else
+-#define U8TO64_LITTLE(p) \
+- ((u64)U8TO32_LITTLE(p) | ((u64)U8TO32_LITTLE((p) + 4) << 32))
+-#endif
+-
+-#define U8TO16_BIG(p) \
+- (((u16)((p)[0]) << 8) | \
+- ((u16)((p)[1]) ))
+-
+-#define U8TO32_BIG(p) \
+- (((u32)((p)[0]) << 24) | \
+- ((u32)((p)[1]) << 16) | \
+- ((u32)((p)[2]) << 8) | \
+- ((u32)((p)[3]) ))
+-
+-#ifdef ECRYPT_NATIVE64
+-#define U8TO64_BIG(p) \
+- (((u64)((p)[0]) << 56) | \
+- ((u64)((p)[1]) << 48) | \
+- ((u64)((p)[2]) << 40) | \
+- ((u64)((p)[3]) << 32) | \
+- ((u64)((p)[4]) << 24) | \
+- ((u64)((p)[5]) << 16) | \
+- ((u64)((p)[6]) << 8) | \
+- ((u64)((p)[7]) ))
+-#else
+-#define U8TO64_BIG(p) \
+- (((u64)U8TO32_BIG(p) << 32) | (u64)U8TO32_BIG((p) + 4))
+-#endif
+-
+-#define U16TO8_LITTLE(p, v) \
+- do { \
+- (p)[0] = U8V((v) ); \
+- (p)[1] = U8V((v) >> 8); \
+- } while (0)
+-
+-#define U32TO8_LITTLE(p, v) \
+- do { \
+- (p)[0] = U8V((v) ); \
+- (p)[1] = U8V((v) >> 8); \
+- (p)[2] = U8V((v) >> 16); \
+- (p)[3] = U8V((v) >> 24); \
+- } while (0)
+-
+-#ifdef ECRYPT_NATIVE64
+-#define U64TO8_LITTLE(p, v) \
+- do { \
+- (p)[0] = U8V((v) ); \
+- (p)[1] = U8V((v) >> 8); \
+- (p)[2] = U8V((v) >> 16); \
+- (p)[3] = U8V((v) >> 24); \
+- (p)[4] = U8V((v) >> 32); \
+- (p)[5] = U8V((v) >> 40); \
+- (p)[6] = U8V((v) >> 48); \
+- (p)[7] = U8V((v) >> 56); \
+- } while (0)
+-#else
+-#define U64TO8_LITTLE(p, v) \
+- do { \
+- U32TO8_LITTLE((p), U32V((v) )); \
+- U32TO8_LITTLE((p) + 4, U32V((v) >> 32)); \
+- } while (0)
+-#endif
+-
+-#define U16TO8_BIG(p, v) \
+- do { \
+- (p)[0] = U8V((v) ); \
+- (p)[1] = U8V((v) >> 8); \
+- } while (0)
+-
+-#define U32TO8_BIG(p, v) \
+- do { \
+- (p)[0] = U8V((v) >> 24); \
+- (p)[1] = U8V((v) >> 16); \
+- (p)[2] = U8V((v) >> 8); \
+- (p)[3] = U8V((v) ); \
+- } while (0)
+-
+-#ifdef ECRYPT_NATIVE64
+-#define U64TO8_BIG(p, v) \
+- do { \
+- (p)[0] = U8V((v) >> 56); \
+- (p)[1] = U8V((v) >> 48); \
+- (p)[2] = U8V((v) >> 40); \
+- (p)[3] = U8V((v) >> 32); \
+- (p)[4] = U8V((v) >> 24); \
+- (p)[5] = U8V((v) >> 16); \
+- (p)[6] = U8V((v) >> 8); \
+- (p)[7] = U8V((v) ); \
+- } while (0)
+-#else
+-#define U64TO8_BIG(p, v) \
+- do { \
+- U32TO8_BIG((p), U32V((v) >> 32)); \
+- U32TO8_BIG((p) + 4, U32V((v) )); \
+- } while (0)
+-#endif
+-
+-#endif
+-
+-#include "ecrypt-machine.h"
+-
+-/* ------------------------------------------------------------------------- */
+-
+-#define AT_LEAST_ONE(n) (((n) < 1) ? 1 : (n))
+-
+-#define ALIGN(t, v, n) \
+- union { t b[n]; MAXT l[AT_LEAST_ONE(n * sizeof(t) / sizeof(MAXT))]; } v
+-
+-/* ------------------------------------------------------------------------- */
+-
+-#endif
+diff --git a/src/crypto/salsa20/ecrypt-sync.h b/src/crypto/salsa20/ecrypt-sync.h
+deleted file mode 100644
+index 245793e..0000000
+--- a/src/crypto/salsa20/ecrypt-sync.h
++++ /dev/null
+@@ -1,287 +0,0 @@
+-/* ecrypt-sync.h */
+-
+-/*
+- * Header file for synchronous stream ciphers without authentication
+- * mechanism.
+- *
+- * *** Please only edit parts marked with "[edit]". ***
+- */
+-
+-#ifndef ECRYPT_SYNC
+-#define ECRYPT_SYNC
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#include "ecrypt-portable.h"
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/* Cipher parameters */
+-
+-/*
+- * The name of your cipher.
+- */
+-#define ECRYPT_NAME "Salsa20" /* [edit] */
+-#define ECRYPT_PROFILE "S!_H."
+-
+-/*
+- * Specify which key and IV sizes are supported by your cipher. A user
+- * should be able to enumerate the supported sizes by running the
+- * following code:
+- *
+- * for (i = 0; ECRYPT_KEYSIZE(i) <= ECRYPT_MAXKEYSIZE; ++i)
+- * {
+- * keysize = ECRYPT_KEYSIZE(i);
+- *
+- * ...
+- * }
+- *
+- * All sizes are in bits.
+- */
+-
+-#define ECRYPT_MAXKEYSIZE 256 /* [edit] */
+-#define ECRYPT_KEYSIZE(i) (128 + (i)*128) /* [edit] */
+-
+-#define ECRYPT_MAXIVSIZE 64 /* [edit] */
+-#define ECRYPT_IVSIZE(i) (64 + (i)*64) /* [edit] */
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/* Data structures */
+-
+-/*
+- * ECRYPT_ctx is the structure containing the representation of the
+- * internal state of your cipher.
+- */
+-
+-typedef struct
+-{
+- u32 input[16]; /* could be compressed */
+- /*
+- * [edit]
+- *
+- * Put here all state variable needed during the encryption process.
+- */
+-} ECRYPT_ctx;
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/* Mandatory functions */
+-
+-/*
+- * Key and message independent initialization. This function will be
+- * called once when the program starts (e.g., to build expanded S-box
+- * tables).
+- */
+-void ECRYPT_init();
+-
+-/*
+- * Key setup. It is the user's responsibility to select the values of
+- * keysize and ivsize from the set of supported values specified
+- * above.
+- */
+-void ECRYPT_keysetup(
+- ECRYPT_ctx* ctx,
+- const u8* key,
+- u32 keysize, /* Key size in bits. */
+- u32 ivsize); /* IV size in bits. */
+-
+-/*
+- * IV setup. After having called ECRYPT_keysetup(), the user is
+- * allowed to call ECRYPT_ivsetup() different times in order to
+- * encrypt/decrypt different messages with the same key but different
+- * IV's.
+- */
+-void ECRYPT_ivsetup(
+- ECRYPT_ctx* ctx,
+- const u8* iv);
+-
+-/*
+- * Encryption/decryption of arbitrary length messages.
+- *
+- * For efficiency reasons, the API provides two types of
+- * encrypt/decrypt functions. The ECRYPT_encrypt_bytes() function
+- * (declared here) encrypts byte strings of arbitrary length, while
+- * the ECRYPT_encrypt_blocks() function (defined later) only accepts
+- * lengths which are multiples of ECRYPT_BLOCKLENGTH.
+- *
+- * The user is allowed to make multiple calls to
+- * ECRYPT_encrypt_blocks() to incrementally encrypt a long message,
+- * but he is NOT allowed to make additional encryption calls once he
+- * has called ECRYPT_encrypt_bytes() (unless he starts a new message
+- * of course). For example, this sequence of calls is acceptable:
+- *
+- * ECRYPT_keysetup();
+- *
+- * ECRYPT_ivsetup();
+- * ECRYPT_encrypt_blocks();
+- * ECRYPT_encrypt_blocks();
+- * ECRYPT_encrypt_bytes();
+- *
+- * ECRYPT_ivsetup();
+- * ECRYPT_encrypt_blocks();
+- * ECRYPT_encrypt_blocks();
+- *
+- * ECRYPT_ivsetup();
+- * ECRYPT_encrypt_bytes();
+- *
+- * The following sequence is not:
+- *
+- * ECRYPT_keysetup();
+- * ECRYPT_ivsetup();
+- * ECRYPT_encrypt_blocks();
+- * ECRYPT_encrypt_bytes();
+- * ECRYPT_encrypt_blocks();
+- */
+-
+-void ECRYPT_encrypt_bytes(
+- ECRYPT_ctx* ctx,
+- const u8* plaintext,
+- u8* ciphertext,
+- u32 msglen); /* Message length in bytes. */
+-
+-void ECRYPT_decrypt_bytes(
+- ECRYPT_ctx* ctx,
+- const u8* ciphertext,
+- u8* plaintext,
+- u32 msglen); /* Message length in bytes. */
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/* Optional features */
+-
+-/*
+- * For testing purposes it can sometimes be useful to have a function
+- * which immediately generates keystream without having to provide it
+- * with a zero plaintext. If your cipher cannot provide this function
+- * (e.g., because it is not strictly a synchronous cipher), please
+- * reset the ECRYPT_GENERATES_KEYSTREAM flag.
+- */
+-
+-#define ECRYPT_GENERATES_KEYSTREAM
+-#ifdef ECRYPT_GENERATES_KEYSTREAM
+-
+-void ECRYPT_keystream_bytes(
+- ECRYPT_ctx* ctx,
+- u8* keystream,
+- u32 length); /* Length of keystream in bytes. */
+-
+-#endif
+-
+-/* ------------------------------------------------------------------------- */
+-
+-/* Optional optimizations */
+-
+-/*
+- * By default, the functions in this section are implemented using
+- * calls to functions declared above. However, you might want to
+- * implement them differently for performance reasons.
+- */
+-
+-/*
+- * All-in-one encryption/decryption of (short) packets.
+- *
+- * The default definitions of these functions can be found in
+- * "ecrypt-sync.c". If you want to implement them differently, please
+- * undef the ECRYPT_USES_DEFAULT_ALL_IN_ONE flag.
+- */
+-#define ECRYPT_USES_DEFAULT_ALL_IN_ONE /* [edit] */
+-
+-void ECRYPT_encrypt_packet(
+- ECRYPT_ctx* ctx,
+- const u8* iv,
+- const u8* plaintext,
+- u8* ciphertext,
+- u32 msglen);
+-
+-void ECRYPT_decrypt_packet(
+- ECRYPT_ctx* ctx,
+- const u8* iv,
+- const u8* ciphertext,
+- u8* plaintext,
+- u32 msglen);
+-
+-/*
+- * Encryption/decryption of blocks.
+- *
+- * By default, these functions are defined as macros. If you want to
+- * provide a different implementation, please undef the
+- * ECRYPT_USES_DEFAULT_BLOCK_MACROS flag and implement the functions
+- * declared below.
+- */
+-
+-#define ECRYPT_BLOCKLENGTH 64 /* [edit] */
+-
+-#define ECRYPT_USES_DEFAULT_BLOCK_MACROS /* [edit] */
+-#ifdef ECRYPT_USES_DEFAULT_BLOCK_MACROS
+-
+-#define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks) \
+- ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, \
+- (blocks) * ECRYPT_BLOCKLENGTH)
+-
+-#define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks) \
+- ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, \
+- (blocks) * ECRYPT_BLOCKLENGTH)
+-
+-#ifdef ECRYPT_GENERATES_KEYSTREAM
+-
+-#define ECRYPT_keystream_blocks(ctx, keystream, blocks) \
+- ECRYPT_keystream_bytes(ctx, keystream, \
+- (blocks) * ECRYPT_BLOCKLENGTH)
+-
+-#endif
+-
+-#else
+-
+-void ECRYPT_encrypt_blocks(
+- ECRYPT_ctx* ctx,
+- const u8* plaintext,
+- u8* ciphertext,
+- u32 blocks); /* Message length in blocks. */
+-
+-void ECRYPT_decrypt_blocks(
+- ECRYPT_ctx* ctx,
+- const u8* ciphertext,
+- u8* plaintext,
+- u32 blocks); /* Message length in blocks. */
+-
+-#ifdef ECRYPT_GENERATES_KEYSTREAM
+-
+-void ECRYPT_keystream_blocks(
+- ECRYPT_ctx* ctx,
+- const u8* keystream,
+- u32 blocks); /* Keystream length in blocks. */
+-
+-#endif
+-
+-#endif
+-
+-/*
+- * If your cipher can be implemented in different ways, you can use
+- * the ECRYPT_VARIANT parameter to allow the user to choose between
+- * them at compile time (e.g., gcc -DECRYPT_VARIANT=3 ...). Please
+- * only use this possibility if you really think it could make a
+- * significant difference and keep the number of variants
+- * (ECRYPT_MAXVARIANT) as small as possible (definitely not more than
+- * 10). Note also that all variants should have exactly the same
+- * external interface (i.e., the same ECRYPT_BLOCKLENGTH, etc.).
+- */
+-#define ECRYPT_MAXVARIANT 1 /* [edit] */
+-
+-#ifndef ECRYPT_VARIANT
+-#define ECRYPT_VARIANT 1
+-#endif
+-
+-#if (ECRYPT_VARIANT > ECRYPT_MAXVARIANT)
+-#error this variant does not exist
+-#endif
+-
+-/* ------------------------------------------------------------------------- */
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif
+diff --git a/src/crypto/salsa20/salsa20.c b/src/crypto/salsa20/salsa20.c
+deleted file mode 100644
+index 74f806c..0000000
+--- a/src/crypto/salsa20/salsa20.c
++++ /dev/null
+@@ -1,133 +0,0 @@
+-/*
+-salsa20-ref.c version 20051118
+-D. J. Bernstein
+-Public domain.
+-*/
+-
+-#include "ecrypt-sync.h"
+-
+-#define ROTATE(v,c) (ROTL32(v,c))
+-#define XOR(v,w) ((v) ^ (w))
+-#define PLUS(v,w) (U32V((v) + (w)))
+-#define PLUSONE(v) (PLUS((v),1))
+-
+-static void salsa20_wordtobyte(u8 output[64],const u32 input[16])
+-{
+- u32 x[16];
+- int i;
+-
+- for (i = 0;i < 16;++i) x[i] = input[i];
+- for (i = 20;i > 0;i -= 2) {
+- x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 0],x[12]), 7));
+- x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[ 4],x[ 0]), 9));
+- x[12] = XOR(x[12],ROTATE(PLUS(x[ 8],x[ 4]),13));
+- x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[12],x[ 8]),18));
+- x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 5],x[ 1]), 7));
+- x[13] = XOR(x[13],ROTATE(PLUS(x[ 9],x[ 5]), 9));
+- x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[13],x[ 9]),13));
+- x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 1],x[13]),18));
+- x[14] = XOR(x[14],ROTATE(PLUS(x[10],x[ 6]), 7));
+- x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[14],x[10]), 9));
+- x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 2],x[14]),13));
+- x[10] = XOR(x[10],ROTATE(PLUS(x[ 6],x[ 2]),18));
+- x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[15],x[11]), 7));
+- x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 3],x[15]), 9));
+- x[11] = XOR(x[11],ROTATE(PLUS(x[ 7],x[ 3]),13));
+- x[15] = XOR(x[15],ROTATE(PLUS(x[11],x[ 7]),18));
+- x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[ 0],x[ 3]), 7));
+- x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[ 1],x[ 0]), 9));
+- x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[ 2],x[ 1]),13));
+- x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[ 3],x[ 2]),18));
+- x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 5],x[ 4]), 7));
+- x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 6],x[ 5]), 9));
+- x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 7],x[ 6]),13));
+- x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 4],x[ 7]),18));
+- x[11] = XOR(x[11],ROTATE(PLUS(x[10],x[ 9]), 7));
+- x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[11],x[10]), 9));
+- x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 8],x[11]),13));
+- x[10] = XOR(x[10],ROTATE(PLUS(x[ 9],x[ 8]),18));
+- x[12] = XOR(x[12],ROTATE(PLUS(x[15],x[14]), 7));
+- x[13] = XOR(x[13],ROTATE(PLUS(x[12],x[15]), 9));
+- x[14] = XOR(x[14],ROTATE(PLUS(x[13],x[12]),13));
+- x[15] = XOR(x[15],ROTATE(PLUS(x[14],x[13]),18));
+- }
+- for (i = 0;i < 16;++i) x[i] = PLUS(x[i],input[i]);
+- for (i = 0;i < 16;++i) U32TO8_LITTLE(output + 4 * i,x[i]);
+-}
+-
+-void ECRYPT_init(void)
+-{
+- return;
+-}
+-
+-static const char sigma[16] = "expand 32-byte k";
+-static const char tau[16] = "expand 16-byte k";
+-
+-void ECRYPT_keysetup(ECRYPT_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
+-{
+- (void)ivbits;
+- const char *constants;
+-
+- x->input[1] = U8TO32_LITTLE(k + 0);
+- x->input[2] = U8TO32_LITTLE(k + 4);
+- x->input[3] = U8TO32_LITTLE(k + 8);
+- x->input[4] = U8TO32_LITTLE(k + 12);
+- if (kbits == 256) { /* recommended */
+- k += 16;
+- constants = sigma;
+- } else { /* kbits == 128 */
+- constants = tau;
+- }
+- x->input[11] = U8TO32_LITTLE(k + 0);
+- x->input[12] = U8TO32_LITTLE(k + 4);
+- x->input[13] = U8TO32_LITTLE(k + 8);
+- x->input[14] = U8TO32_LITTLE(k + 12);
+- x->input[0] = U8TO32_LITTLE(constants + 0);
+- x->input[5] = U8TO32_LITTLE(constants + 4);
+- x->input[10] = U8TO32_LITTLE(constants + 8);
+- x->input[15] = U8TO32_LITTLE(constants + 12);
+-}
+-
+-void ECRYPT_ivsetup(ECRYPT_ctx *x,const u8 *iv)
+-{
+- x->input[6] = U8TO32_LITTLE(iv + 0);
+- x->input[7] = U8TO32_LITTLE(iv + 4);
+- x->input[8] = 0;
+- x->input[9] = 0;
+-}
+-
+-void ECRYPT_encrypt_bytes(ECRYPT_ctx *x,const u8 *m,u8 *c,u32 bytes)
+-{
+- u8 output[64];
+- u32 i;
+-
+- if (!bytes) return;
+- for (;;) {
+- salsa20_wordtobyte(output,x->input);
+- x->input[8] = PLUSONE(x->input[8]);
+- if (!x->input[8]) {
+- x->input[9] = PLUSONE(x->input[9]);
+- /* stopping at 2^70 bytes per nonce is user's responsibility */
+- }
+- if (bytes <= 64) {
+- for (i = 0;i < bytes;++i) c[i] = m[i] ^ output[i];
+- return;
+- }
+- for (i = 0;i < 64;++i) c[i] = m[i] ^ output[i];
+- bytes -= 64;
+- c += 64;
+- m += 64;
+- }
+-}
+-
+-void ECRYPT_decrypt_bytes(ECRYPT_ctx *x,const u8 *c,u8 *m,u32 bytes)
+-{
+- ECRYPT_encrypt_bytes(x,c,m,bytes);
+-}
+-
+-void ECRYPT_keystream_bytes(ECRYPT_ctx *x,u8 *stream,u32 bytes)
+-{
+- u32 i;
+- for (i = 0;i < bytes;++i) stream[i] = 0;
+- ECRYPT_encrypt_bytes(x,stream,stream,bytes);
+-}
+diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp
+index 0e6b4a9..89775b5 100644
+--- a/src/format/KeePass1Reader.cpp
++++ b/src/format/KeePass1Reader.cpp
+@@ -49,9 +49,9 @@ private:
+
+
+ KeePass1Reader::KeePass1Reader()
+- : m_db(Q_NULLPTR)
+- , m_tmpParent(Q_NULLPTR)
+- , m_device(Q_NULLPTR)
++ : m_db(nullptr)
++ , m_tmpParent(nullptr)
++ , m_device(nullptr)
+ , m_encryptionFlags(0)
+ , m_transformRounds(0)
+ , m_error(false)
+@@ -72,16 +72,16 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
+
+ if (keyfileData.isEmpty()) {
+ raiseError(tr("Unable to read keyfile.").append("\n").append(keyfileDevice->errorString()));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ if (!keyfileDevice->seek(0)) {
+ raiseError(tr("Unable to read keyfile.").append("\n").append(keyfileDevice->errorString()));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ if (!newFileKey.load(keyfileDevice)) {
+ raiseError(tr("Unable to read keyfile.").append("\n").append(keyfileDevice->errorString()));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+@@ -96,72 +96,72 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
+ quint32 signature1 = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok);
+ if (!ok || signature1 != KeePass1::SIGNATURE_1) {
+ raiseError(tr("Not a KeePass database."));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ quint32 signature2 = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok);
+ if (!ok || signature2 != KeePass1::SIGNATURE_2) {
+ raiseError(tr("Not a KeePass database."));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ m_encryptionFlags = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok);
+ if (!ok || !(m_encryptionFlags & KeePass1::Rijndael || m_encryptionFlags & KeePass1::Twofish)) {
+ raiseError(tr("Unsupported encryption algorithm."));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ quint32 version = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok);
+ if (!ok || (version & KeePass1::FILE_VERSION_CRITICAL_MASK)
+ != (KeePass1::FILE_VERSION & KeePass1::FILE_VERSION_CRITICAL_MASK)) {
+ raiseError(tr("Unsupported KeePass database version."));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ m_masterSeed = m_device->read(16);
+ if (m_masterSeed.size() != 16) {
+ raiseError("Unable to read master seed");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ m_encryptionIV = m_device->read(16);
+ if (m_encryptionIV.size() != 16) {
+ raiseError("Unable to read encryption IV");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ quint32 numGroups = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok);
+ if (!ok) {
+ raiseError("Invalid number of groups");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ quint32 numEntries = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok);
+ if (!ok) {
+ raiseError("Invalid number of entries");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ m_contentHashHeader = m_device->read(32);
+ if (m_contentHashHeader.size() != 32) {
+ raiseError("Invalid content hash size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ m_transformSeed = m_device->read(32);
+ if (m_transformSeed.size() != 32) {
+ raiseError("Invalid transform seed size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ m_transformRounds = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok);
+ if (!ok) {
+ raiseError("Invalid number of transform rounds");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ if (!m_db->setTransformRounds(m_transformRounds)) {
+ raiseError(tr("Unable to calculate master key"));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ qint64 contentPos = m_device->pos();
+@@ -169,14 +169,14 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
+ QScopedPointer<SymmetricCipherStream> cipherStream(testKeys(password, keyfileData, contentPos));
+
+ if (!cipherStream) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QList<Group*> groups;
+ for (quint32 i = 0; i < numGroups; i++) {
+ Group* group = readGroup(cipherStream.data());
+ if (!group) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ groups.append(group);
+ }
+@@ -185,14 +185,14 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
+ for (quint32 i = 0; i < numEntries; i++) {
+ Entry* entry = readEntry(cipherStream.data());
+ if (!entry) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ entries.append(entry);
+ }
+
+ if (!constructGroupTree(groups)) {
+ raiseError("Unable to construct group tree");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ Q_FOREACH (Entry* entry, entries) {
+@@ -243,7 +243,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
+
+ if (!db->setKey(key)) {
+ raiseError(tr("Unable to calculate master key"));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ return db.take();
+@@ -257,7 +257,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
+ keyFile.reset(new QFile(keyfileName));
+ if (!keyFile->open(QFile::ReadOnly)) {
+ raiseError(keyFile->errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+@@ -272,14 +272,14 @@ Database* KeePass1Reader::readDatabase(const QString& filename, const QString& p
+ QFile dbFile(filename);
+ if (!dbFile.open(QFile::ReadOnly)) {
+ raiseError(dbFile.errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ Database* db = readDatabase(&dbFile, password, keyfileName);
+
+ if (dbFile.error() != QFile::NoError) {
+ raiseError(dbFile.errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ return db;
+@@ -337,7 +337,7 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q
+
+ QByteArray finalKey = key(passwordData, keyfileData);
+ if (finalKey.isEmpty()) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ if (m_encryptionFlags & KeePass1::Rijndael) {
+ cipherStream.reset(new SymmetricCipherStream(m_device, SymmetricCipher::Aes256,
+@@ -350,11 +350,11 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q
+
+ if (!cipherStream->init(finalKey, m_encryptionIV)) {
+ raiseError(cipherStream->errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ if (!cipherStream->open(QIODevice::ReadOnly)) {
+ raiseError(cipherStream->errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ bool success = verifyKey(cipherStream.data());
+@@ -368,7 +368,7 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q
+ }
+ raiseError(msg);
+
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ cipherStream->open(QIODevice::ReadOnly);
+
+@@ -442,19 +442,19 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
+ quint16 fieldType = Endian::readUInt16(cipherStream, KeePass1::BYTEORDER, &ok);
+ if (!ok) {
+ raiseError("Invalid group field type number");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ int fieldSize = static_cast<int>(Endian::readUInt32(cipherStream, KeePass1::BYTEORDER, &ok));
+ if (!ok) {
+ raiseError("Invalid group field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QByteArray fieldData = cipherStream->read(fieldSize);
+ if (fieldData.size() != fieldSize) {
+ raiseError("Read group field data doesn't match size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ switch (fieldType) {
+@@ -464,7 +464,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
+ case 0x0001:
+ if (fieldSize != 4) {
+ raiseError("Incorrect group id field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ groupId = Endian::bytesToUInt32(fieldData, KeePass1::BYTEORDER);
+ groupIdSet = true;
+@@ -476,7 +476,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
+ {
+ if (fieldSize != 5) {
+ raiseError("Incorrect group creation time field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ QDateTime dateTime = dateFromPackedStruct(fieldData);
+ if (dateTime.isValid()) {
+@@ -488,7 +488,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
+ {
+ if (fieldSize != 5) {
+ raiseError("Incorrect group modification time field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ QDateTime dateTime = dateFromPackedStruct(fieldData);
+ if (dateTime.isValid()) {
+@@ -523,7 +523,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
+ {
+ if (fieldSize != 4) {
+ raiseError("Incorrect group icon field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ quint32 iconNumber = Endian::bytesToUInt32(fieldData, KeePass1::BYTEORDER);
+ group->setIcon(iconNumber);
+@@ -533,7 +533,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
+ {
+ if (fieldSize != 2) {
+ raiseError("Incorrect group level field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ groupLevel = Endian::bytesToUInt16(fieldData, KeePass1::BYTEORDER);
+ groupLevelSet = true;
+@@ -548,13 +548,13 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
+ default:
+ // invalid field
+ raiseError("Invalid group field type");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ } while (!reachedEnd);
+
+ if (!groupIdSet || !groupLevelSet) {
+ raiseError("Missing group id or level");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ group->setUuid(Uuid::random());
+@@ -580,19 +580,19 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
+ quint16 fieldType = Endian::readUInt16(cipherStream, KeePass1::BYTEORDER, &ok);
+ if (!ok) {
+ raiseError("Missing entry field type number");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ int fieldSize = static_cast<int>(Endian::readUInt32(cipherStream, KeePass1::BYTEORDER, &ok));
+ if (!ok) {
+ raiseError("Invalid entry field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QByteArray fieldData = cipherStream->read(fieldSize);
+ if (fieldData.size() != fieldSize) {
+ raiseError("Read entry field data doesn't match size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ switch (fieldType) {
+@@ -602,7 +602,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
+ case 0x0001:
+ if (fieldSize != 16) {
+ raiseError("Invalid entry uuid field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ m_entryUuids.insert(fieldData, entry.data());
+ break;
+@@ -610,7 +610,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
+ {
+ if (fieldSize != 4) {
+ raiseError("Invalid entry group id field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ quint32 groupId = Endian::bytesToUInt32(fieldData, KeePass1::BYTEORDER);
+ m_entryGroupIds.insert(entry.data(), groupId);
+@@ -620,7 +620,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
+ {
+ if (fieldSize != 4) {
+ raiseError("Invalid entry icon field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ quint32 iconNumber = Endian::bytesToUInt32(fieldData, KeePass1::BYTEORDER);
+ entry->setIcon(iconNumber);
+@@ -645,7 +645,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
+ {
+ if (fieldSize != 5) {
+ raiseError("Invalid entry creation time field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ QDateTime dateTime = dateFromPackedStruct(fieldData);
+ if (dateTime.isValid()) {
+@@ -657,7 +657,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
+ {
+ if (fieldSize != 5) {
+ raiseError("Invalid entry modification time field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ QDateTime dateTime = dateFromPackedStruct(fieldData);
+ if (dateTime.isValid()) {
+@@ -669,7 +669,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
+ {
+ if (fieldSize != 5) {
+ raiseError("Invalid entry creation time field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ QDateTime dateTime = dateFromPackedStruct(fieldData);
+ if (dateTime.isValid()) {
+@@ -681,7 +681,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
+ {
+ if (fieldSize != 5) {
+ raiseError("Invalid entry expiry time field size");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ QDateTime dateTime = dateFromPackedStruct(fieldData);
+ if (dateTime.isValid()) {
+@@ -704,7 +704,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
+ default:
+ // invalid field
+ raiseError("Invalid entry field type");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ } while (!reachedEnd);
+
+diff --git a/src/format/KeePass2Reader.cpp b/src/format/KeePass2Reader.cpp
+index d1ca9ed..00ebc07 100644
+--- a/src/format/KeePass2Reader.cpp
++++ b/src/format/KeePass2Reader.cpp
+@@ -34,12 +34,12 @@
+ #include "streams/SymmetricCipherStream.h"
+
+ KeePass2Reader::KeePass2Reader()
+- : m_device(Q_NULLPTR)
+- , m_headerStream(Q_NULLPTR)
++ : m_device(nullptr)
++ , m_headerStream(nullptr)
+ , m_error(false)
+ , m_headerEnd(false)
+ , m_saveXml(false)
+- , m_db(Q_NULLPTR)
++ , m_db(nullptr)
+ {
+ }
+
+@@ -67,7 +67,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ quint32 signature1 = Endian::readUInt32(m_headerStream, KeePass2::BYTEORDER, &ok);
+ if (!ok || signature1 != KeePass2::SIGNATURE_1) {
+ raiseError(tr("Not a KeePass database."));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ quint32 signature2 = Endian::readUInt32(m_headerStream, KeePass2::BYTEORDER, &ok);
+@@ -76,11 +76,11 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ "You can import it by clicking on Database > 'Import KeePass 1 database'.\n"
+ "This is a one-way migration. You won't be able to open the imported "
+ "database with the old KeePassX 0.4 version."));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ else if (!ok || signature2 != KeePass2::SIGNATURE_2) {
+ raiseError(tr("Not a KeePass database."));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ quint32 version = Endian::readUInt32(m_headerStream, KeePass2::BYTEORDER, &ok)
+@@ -88,7 +88,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ quint32 maxVersion = KeePass2::FILE_VERSION & KeePass2::FILE_VERSION_CRITICAL_MASK;
+ if (!ok || (version < KeePass2::FILE_VERSION_MIN) || (version > maxVersion)) {
+ raiseError(tr("Unsupported KeePass database version."));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ while (readHeaderField() && !hasError()) {
+@@ -97,7 +97,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ headerStream.close();
+
+ if (hasError()) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ // check if all required headers were present
+@@ -105,12 +105,12 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ || m_streamStartBytes.isEmpty() || m_protectedStreamKey.isEmpty()
+ || m_db->cipher().isNull()) {
+ raiseError("missing database headers");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ if (!m_db->setKey(key, m_transformSeed, false)) {
+ raiseError(tr("Unable to calculate master key"));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ CryptoHash hash(CryptoHash::Sha256);
+@@ -122,24 +122,24 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ SymmetricCipher::Cbc, SymmetricCipher::Decrypt);
+ if (!cipherStream.init(finalKey, m_encryptionIV)) {
+ raiseError(cipherStream.errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ if (!cipherStream.open(QIODevice::ReadOnly)) {
+ raiseError(cipherStream.errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QByteArray realStart = cipherStream.read(32);
+
+ if (realStart != m_streamStartBytes) {
+ raiseError(tr("Wrong key or database file is corrupt."));
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ HashedBlockStream hashedStream(&cipherStream);
+ if (!hashedStream.open(QIODevice::ReadOnly)) {
+ raiseError(hashedStream.errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QIODevice* xmlDevice;
+@@ -153,7 +153,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ ioCompressor->setStreamFormat(QtIOCompressor::GzipFormat);
+ if (!ioCompressor->open(QIODevice::ReadOnly)) {
+ raiseError(ioCompressor->errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ xmlDevice = ioCompressor.data();
+ }
+@@ -161,7 +161,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ KeePass2RandomStream randomStream;
+ if (!randomStream.init(m_protectedStreamKey)) {
+ raiseError(randomStream.errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QScopedPointer<QBuffer> buffer;
+@@ -182,7 +182,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ return db.take();
+ }
+ else {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+@@ -192,7 +192,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
+ QByteArray headerHash = CryptoHash::hash(headerStream.storedData(), CryptoHash::Sha256);
+ if (headerHash != xmlReader.headerHash()) {
+ raiseError("Head doesn't match hash");
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+@@ -204,14 +204,14 @@ Database* KeePass2Reader::readDatabase(const QString& filename, const CompositeK
+ QFile file(filename);
+ if (!file.open(QFile::ReadOnly)) {
+ raiseError(file.errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QScopedPointer<Database> db(readDatabase(&file, key));
+
+ if (file.error() != QFile::NoError) {
+ raiseError(file.errorString());
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ return db.take();
+diff --git a/src/format/KeePass2Repair.cpp b/src/format/KeePass2Repair.cpp
+index f435a7d..81ada2f 100644
+--- a/src/format/KeePass2Repair.cpp
++++ b/src/format/KeePass2Repair.cpp
+@@ -25,13 +25,13 @@
+ #include "format/KeePass2XmlReader.h"
+
+ KeePass2Repair::KeePass2Repair()
+- : m_db(Q_NULLPTR)
++ : m_db(nullptr)
+ {
+ }
+
+ KeePass2Repair::RepairResult KeePass2Repair::repairDatabase(QIODevice* device, const CompositeKey& key)
+ {
+- m_db = Q_NULLPTR;
++ m_db = nullptr;
+ m_errorStr.clear();
+
+ KeePass2Reader reader;
+diff --git a/src/format/KeePass2XmlReader.cpp b/src/format/KeePass2XmlReader.cpp
+index 815cbf9..40087a6 100644
+--- a/src/format/KeePass2XmlReader.cpp
++++ b/src/format/KeePass2XmlReader.cpp
+@@ -31,10 +31,10 @@
+ typedef QPair<QString, QString> StringPair;
+
+ KeePass2XmlReader::KeePass2XmlReader()
+- : m_randomStream(Q_NULLPTR)
+- , m_db(Q_NULLPTR)
+- , m_meta(Q_NULLPTR)
+- , m_tmpParent(Q_NULLPTR)
++ : m_randomStream(nullptr)
++ , m_db(nullptr)
++ , m_meta(nullptr)
++ , m_tmpParent(nullptr)
+ , m_error(false)
+ , m_strictMode(false)
+ {
+@@ -1045,7 +1045,7 @@ QDateTime KeePass2XmlReader::readDateTime()
+ raiseError("Invalid date time value");
+ }
+ else {
+- dt = Tools::currentDateTimeUtc();
++ dt = QDateTime::currentDateTimeUtc();
+ }
+ }
+
+@@ -1146,7 +1146,7 @@ QByteArray KeePass2XmlReader::readCompressedBinary()
+ Group* KeePass2XmlReader::getGroup(const Uuid& uuid)
+ {
+ if (uuid.isNull()) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ if (m_groups.contains(uuid)) {
+@@ -1165,7 +1165,7 @@ Group* KeePass2XmlReader::getGroup(const Uuid& uuid)
+ Entry* KeePass2XmlReader::getEntry(const Uuid& uuid)
+ {
+ if (uuid.isNull()) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ if (m_entries.contains(uuid)) {
+diff --git a/src/format/KeePass2XmlReader.h b/src/format/KeePass2XmlReader.h
+index ca311b0..d2e0e00 100644
+--- a/src/format/KeePass2XmlReader.h
++++ b/src/format/KeePass2XmlReader.h
+@@ -25,7 +25,6 @@
+ #include <QPair>
+ #include <QXmlStreamReader>
+
+-#include "core/Global.h"
+ #include "core/TimeInfo.h"
+ #include "core/Uuid.h"
+
+@@ -42,7 +41,7 @@ class KeePass2XmlReader
+ public:
+ KeePass2XmlReader();
+ Database* readDatabase(QIODevice* device);
+- void readDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = Q_NULLPTR);
++ void readDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = nullptr);
+ Database* readDatabase(const QString& filename);
+ bool hasError();
+ QString errorString();
+diff --git a/src/format/KeePass2XmlWriter.cpp b/src/format/KeePass2XmlWriter.cpp
+index 1eb8dc1..7fd03cc 100644
+--- a/src/format/KeePass2XmlWriter.cpp
++++ b/src/format/KeePass2XmlWriter.cpp
+@@ -25,9 +25,9 @@
+ #include "streams/QtIOCompressor"
+
+ KeePass2XmlWriter::KeePass2XmlWriter()
+- : m_db(Q_NULLPTR)
+- , m_meta(Q_NULLPTR)
+- , m_randomStream(Q_NULLPTR)
++ : m_db(nullptr)
++ , m_meta(nullptr)
++ , m_randomStream(nullptr)
+ , m_error(false)
+ {
+ m_xml.setAutoFormatting(true);
+@@ -58,11 +58,9 @@ void KeePass2XmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2R
+
+ m_xml.writeEndDocument();
+
+-#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
+ if (m_xml.hasError()) {
+ raiseError(device->errorString());
+ }
+-#endif
+ }
+
+ void KeePass2XmlWriter::writeDatabase(const QString& filename, Database* db)
+diff --git a/src/format/KeePass2XmlWriter.h b/src/format/KeePass2XmlWriter.h
+index 48dde6a..23e148d 100644
+--- a/src/format/KeePass2XmlWriter.h
++++ b/src/format/KeePass2XmlWriter.h
+@@ -36,7 +36,7 @@ class KeePass2XmlWriter
+ {
+ public:
+ KeePass2XmlWriter();
+- void writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = Q_NULLPTR,
++ void writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = nullptr,
+ const QByteArray& headerHash = QByteArray());
+ void writeDatabase(const QString& filename, Database* db);
+ bool hasError();
+diff --git a/src/gui/AboutDialog.h b/src/gui/AboutDialog.h
+index 1436aee..08db6c8 100644
+--- a/src/gui/AboutDialog.h
++++ b/src/gui/AboutDialog.h
+@@ -21,8 +21,6 @@
+ #include <QDialog>
+ #include <QScopedPointer>
+
+-#include "core/Global.h"
+-
+ namespace Ui {
+ class AboutDialog;
+ }
+@@ -32,7 +30,7 @@ class AboutDialog : public QDialog
+ Q_OBJECT
+
+ public:
+- explicit AboutDialog(QWidget* parent = Q_NULLPTR);
++ explicit AboutDialog(QWidget* parent = nullptr);
+ ~AboutDialog();
+
+ private:
+diff --git a/src/gui/Application.cpp b/src/gui/Application.cpp
+index ae6931f..70550c5 100644
+--- a/src/gui/Application.cpp
++++ b/src/gui/Application.cpp
+@@ -18,14 +18,38 @@
+
+ #include "Application.h"
+
++#include <QAbstractNativeEventFilter>
+ #include <QFileOpenEvent>
+
+ #include "autotype/AutoType.h"
+
++#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
++class XcbEventFilter : public QAbstractNativeEventFilter
++{
++public:
++ bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override
++ {
++ Q_UNUSED(result)
++
++ if (eventType == QByteArrayLiteral("xcb_generic_event_t")) {
++ int retCode = autoType()->callEventFilter(message);
++ if (retCode == 1) {
++ return true;
++ }
++ }
++
++ return false;
++ }
++};
++#endif
++
+ Application::Application(int& argc, char** argv)
+ : QApplication(argc, argv)
+- , m_mainWindow(Q_NULLPTR)
++ , m_mainWindow(nullptr)
+ {
++#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
++ installNativeEventFilter(new XcbEventFilter());
++#endif
+ }
+
+ void Application::setMainWindow(QWidget* mainWindow)
+@@ -53,19 +77,3 @@ bool Application::event(QEvent* event)
+
+ return QApplication::event(event);
+ }
+-
+-#ifdef Q_WS_X11
+-bool Application::x11EventFilter(XEvent* event)
+-{
+- int retCode = autoType()->callEventFilter(event);
+-
+- if (retCode == 0) {
+- return false;
+- }
+- else if (retCode == 1) {
+- return true;
+- }
+-
+- return QApplication::x11EventFilter(event);
+-}
+-#endif
+diff --git a/src/gui/Application.h b/src/gui/Application.h
+index 2b78998..149b61d 100644
+--- a/src/gui/Application.h
++++ b/src/gui/Application.h
+@@ -21,8 +21,6 @@
+
+ #include <QApplication>
+
+-#include "core/Global.h"
+-
+ class Application : public QApplication
+ {
+ Q_OBJECT
+@@ -31,10 +29,7 @@ public:
+ Application(int& argc, char** argv);
+ void setMainWindow(QWidget* mainWindow);
+
+- bool event(QEvent* event) Q_DECL_OVERRIDE;
+-#ifdef Q_WS_X11
+- bool x11EventFilter(XEvent* event) Q_DECL_OVERRIDE;
+-#endif
++ bool event(QEvent* event) override;
+
+ Q_SIGNALS:
+ void openFile(const QString& filename);
+diff --git a/src/gui/ChangeMasterKeyWidget.h b/src/gui/ChangeMasterKeyWidget.h
+index 46fc3ef..8985ff7 100644
+--- a/src/gui/ChangeMasterKeyWidget.h
++++ b/src/gui/ChangeMasterKeyWidget.h
+@@ -33,7 +33,7 @@ class ChangeMasterKeyWidget : public DialogyWidget
+ Q_OBJECT
+
+ public:
+- explicit ChangeMasterKeyWidget(QWidget* parent = Q_NULLPTR);
++ explicit ChangeMasterKeyWidget(QWidget* parent = nullptr);
+ ~ChangeMasterKeyWidget();
+ void clearForms();
+ CompositeKey newMasterKey();
+diff --git a/src/gui/Clipboard.cpp b/src/gui/Clipboard.cpp
+index 698ca89..bf4db8f 100644
+--- a/src/gui/Clipboard.cpp
++++ b/src/gui/Clipboard.cpp
+@@ -23,7 +23,7 @@
+
+ #include "core/Config.h"
+
+-Clipboard* Clipboard::m_instance(Q_NULLPTR);
++Clipboard* Clipboard::m_instance(nullptr);
+
+ Clipboard::Clipboard(QObject* parent)
+ : QObject(parent)
+diff --git a/src/gui/Clipboard.h b/src/gui/Clipboard.h
+index 8c234a2..dafce70 100644
+--- a/src/gui/Clipboard.h
++++ b/src/gui/Clipboard.h
+@@ -20,8 +20,6 @@
+
+ #include <QObject>
+
+-#include "core/Global.h"
+-
+ class QTimer;
+
+ class Clipboard : public QObject
+@@ -40,7 +38,7 @@ private Q_SLOTS:
+ void clearClipboard();
+
+ private:
+- explicit Clipboard(QObject* parent = Q_NULLPTR);
++ explicit Clipboard(QObject* parent = nullptr);
+
+ static Clipboard* m_instance;
+
+diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp
+index 7e34176..00aae6b 100644
+--- a/src/gui/DatabaseOpenWidget.cpp
++++ b/src/gui/DatabaseOpenWidget.cpp
+@@ -30,7 +30,7 @@
+ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
+ : DialogyWidget(parent)
+ , m_ui(new Ui::DatabaseOpenWidget())
+- , m_db(Q_NULLPTR)
++ , m_db(nullptr)
+ {
+ m_ui->setupUi(this);
+
+diff --git a/src/gui/DatabaseOpenWidget.h b/src/gui/DatabaseOpenWidget.h
+index 9c9a062..ba55e4c 100644
+--- a/src/gui/DatabaseOpenWidget.h
++++ b/src/gui/DatabaseOpenWidget.h
+@@ -35,7 +35,7 @@ class DatabaseOpenWidget : public DialogyWidget
+ Q_OBJECT
+
+ public:
+- explicit DatabaseOpenWidget(QWidget* parent = Q_NULLPTR);
++ explicit DatabaseOpenWidget(QWidget* parent = nullptr);
+ ~DatabaseOpenWidget();
+ void load(const QString& filename);
+ void enterKey(const QString& pw, const QString& keyFile);
+diff --git a/src/gui/DatabaseRepairWidget.h b/src/gui/DatabaseRepairWidget.h
+index 56c5c96..6775d2d 100644
+--- a/src/gui/DatabaseRepairWidget.h
++++ b/src/gui/DatabaseRepairWidget.h
+@@ -25,14 +25,14 @@ class DatabaseRepairWidget : public DatabaseOpenWidget
+ Q_OBJECT
+
+ public:
+- explicit DatabaseRepairWidget(QWidget* parent = Q_NULLPTR);
++ explicit DatabaseRepairWidget(QWidget* parent = nullptr);
+
+ Q_SIGNALS:
+ void success();
+ void error();
+
+ protected:
+- void openDatabase() Q_DECL_OVERRIDE;
++ void openDatabase() override;
+
+ private Q_SLOTS:
+ void processEditFinished(bool result);
+diff --git a/src/gui/DatabaseSettingsWidget.cpp b/src/gui/DatabaseSettingsWidget.cpp
+index 007c44a..d4ca8dd 100644
+--- a/src/gui/DatabaseSettingsWidget.cpp
++++ b/src/gui/DatabaseSettingsWidget.cpp
+@@ -26,7 +26,7 @@
+ DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent)
+ : DialogyWidget(parent)
+ , m_ui(new Ui::DatabaseSettingsWidget())
+- , m_db(Q_NULLPTR)
++ , m_db(nullptr)
+ {
+ m_ui->setupUi(this);
+
+diff --git a/src/gui/DatabaseSettingsWidget.h b/src/gui/DatabaseSettingsWidget.h
+index a7d2832..040e0db 100644
+--- a/src/gui/DatabaseSettingsWidget.h
++++ b/src/gui/DatabaseSettingsWidget.h
+@@ -33,7 +33,7 @@ class DatabaseSettingsWidget : public DialogyWidget
+ Q_OBJECT
+
+ public:
+- explicit DatabaseSettingsWidget(QWidget* parent = Q_NULLPTR);
++ explicit DatabaseSettingsWidget(QWidget* parent = nullptr);
+ ~DatabaseSettingsWidget();
+
+ void load(Database* db);
+diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp
+index 3d03093..69b4f7e 100644
+--- a/src/gui/DatabaseTabWidget.cpp
++++ b/src/gui/DatabaseTabWidget.cpp
+@@ -18,6 +18,8 @@
+ #include "DatabaseTabWidget.h"
+
+ #include <QFileInfo>
++#include <QLockFile>
++#include <QSaveFile>
+ #include <QTabWidget>
+
+ #include "autotype/AutoType.h"
+@@ -25,7 +27,6 @@
+ #include "core/Database.h"
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+-#include "core/qsavefile.h"
+ #include "format/CsvExporter.h"
+ #include "gui/Clipboard.h"
+ #include "gui/DatabaseWidget.h"
+@@ -37,8 +38,8 @@
+ #include "gui/group/GroupView.h"
+
+ DatabaseManagerStruct::DatabaseManagerStruct()
+- : dbWidget(Q_NULLPTR)
+- , lockFile(Q_NULLPTR)
++ : dbWidget(nullptr)
++ , lockFile(nullptr)
+ , saveToFilename(false)
+ , modified(false)
+ , readOnly(false)
+@@ -160,7 +161,7 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw,
+ if (result == QMessageBox::No) {
+ dbStruct.readOnly = true;
+ delete lockFile;
+- lockFile = Q_NULLPTR;
++ lockFile = nullptr;
+ }
+ else {
+ // take over the lock file if possible
+@@ -332,7 +333,7 @@ bool DatabaseTabWidget::saveDatabaseAs(Database* db)
+ }
+ QString fileName = fileDialog()->getSaveFileName(this, tr("Save database as"),
+ oldFileName, tr("KeePass 2 Database").append(" (*.kdbx)"),
+- Q_NULLPTR, 0, "kdbx");
++ nullptr, 0, "kdbx");
+ if (!fileName.isEmpty()) {
+ QFileInfo fileInfo(fileName);
+ QString lockFilePath;
+@@ -453,7 +454,7 @@ void DatabaseTabWidget::exportToCsv()
+
+ QString fileName = fileDialog()->getSaveFileName(this, tr("Export database to CSV file"),
+ QString(), tr("CSV file").append(" (*.csv)"),
+- Q_NULLPTR, 0, "csv");
++ nullptr, 0, "csv");
+ if (fileName.isEmpty()) {
+ return;
+ }
+@@ -558,7 +559,7 @@ Database* DatabaseTabWidget::indexDatabase(int index)
+ }
+ }
+
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ DatabaseManagerStruct DatabaseTabWidget::indexDatabaseManagerStruct(int index)
+@@ -586,7 +587,7 @@ Database* DatabaseTabWidget::databaseFromDatabaseWidget(DatabaseWidget* dbWidget
+ }
+ }
+
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ void DatabaseTabWidget::insertDatabase(Database* db, const DatabaseManagerStruct& dbStruct)
+@@ -611,7 +612,7 @@ DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget()
+ return m_dbList[db].dbWidget;
+ }
+ else {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h
+index c15408d..de4a9ca 100644
+--- a/src/gui/DatabaseTabWidget.h
++++ b/src/gui/DatabaseTabWidget.h
+@@ -21,7 +21,6 @@
+ #include <QHash>
+ #include <QTabWidget>
+
+-#include "core/qlockfile.h"
+ #include "format/KeePass2Writer.h"
+ #include "gui/DatabaseWidget.h"
+
+@@ -29,6 +28,7 @@ class DatabaseWidget;
+ class DatabaseWidgetStateSync;
+ class DatabaseOpenWidget;
+ class QFile;
++class QLockFile;
+
+ struct DatabaseManagerStruct
+ {
+@@ -51,7 +51,7 @@ class DatabaseTabWidget : public QTabWidget
+ Q_OBJECT
+
+ public:
+- explicit DatabaseTabWidget(QWidget* parent = Q_NULLPTR);
++ explicit DatabaseTabWidget(QWidget* parent = nullptr);
+ ~DatabaseTabWidget();
+ void openDatabase(const QString& fileName, const QString& pw = QString(),
+ const QString& keyFile = QString());
+@@ -101,7 +101,7 @@ private:
+ Database* databaseFromDatabaseWidget(DatabaseWidget* dbWidget);
+ void insertDatabase(Database* db, const DatabaseManagerStruct& dbStruct);
+ void updateLastDatabases(const QString& filename);
+- void connectDatabase(Database* newDb, Database* oldDb = Q_NULLPTR);
++ void connectDatabase(Database* newDb, Database* oldDb = nullptr);
+
+ KeePass2Writer m_writer;
+ QHash<Database*, DatabaseManagerStruct> m_dbList;
+diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
+index 8de842f..3bca6fa 100644
+--- a/src/gui/DatabaseWidget.cpp
++++ b/src/gui/DatabaseWidget.cpp
+@@ -52,9 +52,9 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
+ , m_db(db)
+ , m_searchUi(new Ui::SearchWidget())
+ , m_searchWidget(new QWidget())
+- , m_newGroup(Q_NULLPTR)
+- , m_newEntry(Q_NULLPTR)
+- , m_newParent(Q_NULLPTR)
++ , m_newGroup(nullptr)
++ , m_newEntry(nullptr)
++ , m_newParent(nullptr)
+ {
+ m_searchUi->setupUi(m_searchWidget);
+
+@@ -175,7 +175,7 @@ DatabaseWidget::~DatabaseWidget()
+
+ DatabaseWidget::Mode DatabaseWidget::currentMode() const
+ {
+- if (currentWidget() == Q_NULLPTR) {
++ if (currentWidget() == nullptr) {
+ return DatabaseWidget::None;
+ }
+ else if (currentWidget() == m_mainWidget) {
+@@ -554,8 +554,8 @@ void DatabaseWidget::switchToView(bool accepted)
+ delete m_newGroup;
+ }
+
+- m_newGroup = Q_NULLPTR;
+- m_newParent = Q_NULLPTR;
++ m_newGroup = nullptr;
++ m_newParent = nullptr;
+ }
+ else if (m_newEntry) {
+ if (accepted) {
+@@ -567,8 +567,8 @@ void DatabaseWidget::switchToView(bool accepted)
+ delete m_newEntry;
+ }
+
+- m_newEntry = Q_NULLPTR;
+- m_newParent = Q_NULLPTR;
++ m_newEntry = nullptr;
++ m_newParent = nullptr;
+ }
+
+ setCurrentWidget(m_mainWidget);
+@@ -638,9 +638,9 @@ void DatabaseWidget::openDatabase(bool accepted)
+ // We won't need those anymore and KeePass1OpenWidget closes
+ // the file in its dtor.
+ delete m_databaseOpenWidget;
+- m_databaseOpenWidget = Q_NULLPTR;
++ m_databaseOpenWidget = nullptr;
+ delete m_keepass1OpenWidget;
+- m_keepass1OpenWidget = Q_NULLPTR;
++ m_keepass1OpenWidget = nullptr;
+ }
+ else {
+ if (m_databaseOpenWidget->database()) {
+@@ -883,7 +883,7 @@ bool DatabaseWidget::isInSearchMode() const
+ void DatabaseWidget::clearLastGroup(Group* group)
+ {
+ if (group) {
+- m_lastGroup = Q_NULLPTR;
++ m_lastGroup = nullptr;
+ m_searchWidget->hide();
+ }
+ }
+@@ -932,7 +932,7 @@ QStringList DatabaseWidget::customEntryAttributes() const
+
+ bool DatabaseWidget::isGroupSelected() const
+ {
+- return m_groupView->currentGroup() != Q_NULLPTR;
++ return m_groupView->currentGroup() != nullptr;
+ }
+
+ bool DatabaseWidget::currentEntryHasTitle()
+diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h
+index a925606..38a685c 100644
+--- a/src/gui/DatabaseWidget.h
++++ b/src/gui/DatabaseWidget.h
+@@ -21,7 +21,6 @@
+ #include <QScopedPointer>
+ #include <QStackedWidget>
+
+-#include "core/Global.h"
+ #include "core/Uuid.h"
+
+ #include "gui/entry/EntryModel.h"
+@@ -59,7 +58,7 @@ public:
+ LockedMode
+ };
+
+- explicit DatabaseWidget(Database* db, QWidget* parent = Q_NULLPTR);
++ explicit DatabaseWidget(Database* db, QWidget* parent = nullptr);
+ ~DatabaseWidget();
+ Database* database();
+ bool dbHasKey() const;
+@@ -103,7 +102,7 @@ Q_SIGNALS:
+ void entryColumnSizesChanged();
+
+ protected:
+- bool eventFilter(QObject* object, QEvent* event) Q_DECL_OVERRIDE;
++ bool eventFilter(QObject* object, QEvent* event) override;
+
+ public Q_SLOTS:
+ void createEntry();
+diff --git a/src/gui/DatabaseWidgetStateSync.cpp b/src/gui/DatabaseWidgetStateSync.cpp
+index 66b8492..430380c 100644
+--- a/src/gui/DatabaseWidgetStateSync.cpp
++++ b/src/gui/DatabaseWidgetStateSync.cpp
+@@ -22,7 +22,7 @@
+
+ DatabaseWidgetStateSync::DatabaseWidgetStateSync(QObject* parent)
+ : QObject(parent)
+- , m_activeDbWidget(Q_NULLPTR)
++ , m_activeDbWidget(nullptr)
+ , m_blockUpdates(false)
+ {
+ m_splitterSizes = variantToIntList(config()->get("GUI/SplitterState"));
+diff --git a/src/gui/DatabaseWidgetStateSync.h b/src/gui/DatabaseWidgetStateSync.h
+index f6a87cd..a486117 100644
+--- a/src/gui/DatabaseWidgetStateSync.h
++++ b/src/gui/DatabaseWidgetStateSync.h
+@@ -16,8 +16,8 @@
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+-#ifndef KEEPASSX_HEADERVIEWSYNC_H
+-#define KEEPASSX_HEADERVIEWSYNC_H
++#ifndef KEEPASSX_DATABASEWIDGETSTATESYNC_H
++#define KEEPASSX_DATABASEWIDGETSTATESYNC_H
+
+ #include "gui/DatabaseWidget.h"
+
+@@ -26,7 +26,7 @@ class DatabaseWidgetStateSync : public QObject
+ Q_OBJECT
+
+ public:
+- explicit DatabaseWidgetStateSync(QObject* parent = Q_NULLPTR);
++ explicit DatabaseWidgetStateSync(QObject* parent = nullptr);
+ ~DatabaseWidgetStateSync();
+
+ public Q_SLOTS:
+@@ -51,4 +51,4 @@ private:
+ QList<int> m_columnSizesSearch;
+ };
+
+-#endif // KEEPASSX_HEADERVIEWSYNC_H
++#endif // KEEPASSX_DATABASEWIDGETSTATESYNC_H
+diff --git a/src/gui/DialogyWidget.h b/src/gui/DialogyWidget.h
+index 9dd0528..b0915a2 100644
+--- a/src/gui/DialogyWidget.h
++++ b/src/gui/DialogyWidget.h
+@@ -21,17 +21,15 @@
+ #include <QDialogButtonBox>
+ #include <QWidget>
+
+-#include "core/Global.h"
+-
+ class DialogyWidget : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+- explicit DialogyWidget(QWidget* parent = Q_NULLPTR);
++ explicit DialogyWidget(QWidget* parent = nullptr);
+
+ protected:
+- virtual void keyPressEvent(QKeyEvent* e) Q_DECL_OVERRIDE;
++ void keyPressEvent(QKeyEvent* e) override;
+
+ private:
+ bool clickButton(QDialogButtonBox::StandardButton standardButton);
+diff --git a/src/gui/DragTabBar.h b/src/gui/DragTabBar.h
+index 1b6005d..a6117a0 100644
+--- a/src/gui/DragTabBar.h
++++ b/src/gui/DragTabBar.h
+@@ -20,21 +20,19 @@
+
+ #include <QTabBar>
+
+-#include "core/Global.h"
+-
+ class DragTabBar : public QTabBar
+ {
+ Q_OBJECT
+
+ public:
+- explicit DragTabBar(QWidget* parent = Q_NULLPTR);
++ explicit DragTabBar(QWidget* parent = nullptr);
+
+ protected:
+- void dragEnterEvent(QDragEnterEvent* event) Q_DECL_OVERRIDE;
+- void dragMoveEvent(QDragMoveEvent* event) Q_DECL_OVERRIDE;
+- void dragLeaveEvent(QDragLeaveEvent* event) Q_DECL_OVERRIDE;
+- void dropEvent(QDropEvent* event) Q_DECL_OVERRIDE;
+- void tabLayoutChange() Q_DECL_OVERRIDE;
++ void dragEnterEvent(QDragEnterEvent* event) override;
++ void dragMoveEvent(QDragMoveEvent* event) override;
++ void dragLeaveEvent(QDragLeaveEvent* event) override;
++ void dropEvent(QDropEvent* event) override;
++ void tabLayoutChange() override;
+
+ private Q_SLOTS:
+ void dragSwitchTab();
+diff --git a/src/gui/EditWidget.h b/src/gui/EditWidget.h
+index d27abe9..c5f507a 100644
+--- a/src/gui/EditWidget.h
++++ b/src/gui/EditWidget.h
+@@ -33,7 +33,7 @@ class EditWidget : public DialogyWidget
+ Q_OBJECT
+
+ public:
+- explicit EditWidget(QWidget* parent = Q_NULLPTR);
++ explicit EditWidget(QWidget* parent = nullptr);
+ ~EditWidget();
+
+ void add(const QString& labelText, QWidget* widget);
+diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp
+index c408940..3d3565c 100644
+--- a/src/gui/EditWidgetIcons.cpp
++++ b/src/gui/EditWidgetIcons.cpp
+@@ -35,7 +35,7 @@ IconStruct::IconStruct()
+ EditWidgetIcons::EditWidgetIcons(QWidget* parent)
+ : QWidget(parent)
+ , m_ui(new Ui::EditWidgetIcons())
+- , m_database(Q_NULLPTR)
++ , m_database(nullptr)
+ , m_defaultIconModel(new DefaultIconModel(this))
+ , m_customIconModel(new CustomIconModel(this))
+ {
+@@ -85,7 +85,7 @@ IconStruct EditWidgetIcons::save()
+ }
+ }
+
+- m_database = Q_NULLPTR;
++ m_database = nullptr;
+ m_currentUuid = Uuid();
+ return iconStruct;
+ }
+diff --git a/src/gui/EditWidgetIcons.h b/src/gui/EditWidgetIcons.h
+index e18f444..f3f3f11 100644
+--- a/src/gui/EditWidgetIcons.h
++++ b/src/gui/EditWidgetIcons.h
+@@ -20,7 +20,6 @@
+
+ #include <QWidget>
+
+-#include "core/Global.h"
+ #include "core/Uuid.h"
+
+ class Database;
+@@ -44,7 +43,7 @@ class EditWidgetIcons : public QWidget
+ Q_OBJECT
+
+ public:
+- explicit EditWidgetIcons(QWidget* parent = Q_NULLPTR);
++ explicit EditWidgetIcons(QWidget* parent = nullptr);
+ ~EditWidgetIcons();
+
+ IconStruct save();
+diff --git a/src/gui/EditWidgetProperties.h b/src/gui/EditWidgetProperties.h
+index c5d0eb0..4a2c059 100644
+--- a/src/gui/EditWidgetProperties.h
++++ b/src/gui/EditWidgetProperties.h
+@@ -20,7 +20,6 @@
+
+ #include <QWidget>
+
+-#include "core/Global.h"
+ #include "core/TimeInfo.h"
+ #include "core/Uuid.h"
+
+@@ -33,7 +32,7 @@ class EditWidgetProperties : public QWidget
+ Q_OBJECT
+
+ public:
+- explicit EditWidgetProperties(QWidget* parent = Q_NULLPTR);
++ explicit EditWidgetProperties(QWidget* parent = nullptr);
+ ~EditWidgetProperties();
+
+ void setFields(TimeInfo timeInfo, Uuid uuid);
+diff --git a/src/gui/FileDialog.cpp b/src/gui/FileDialog.cpp
+index 8448258..e293db2 100644
+--- a/src/gui/FileDialog.cpp
++++ b/src/gui/FileDialog.cpp
+@@ -19,7 +19,7 @@
+
+ #include "core/Config.h"
+
+-FileDialog* FileDialog::m_instance(Q_NULLPTR);
++FileDialog* FileDialog::m_instance(nullptr);
+
+ QString FileDialog::getOpenFileName(QWidget* parent, const QString& caption, QString dir,
+ const QString& filter, QString* selectedFilter,
+diff --git a/src/gui/FileDialog.h b/src/gui/FileDialog.h
+index 46c6353..9f8fbb5 100644
+--- a/src/gui/FileDialog.h
++++ b/src/gui/FileDialog.h
+@@ -20,17 +20,15 @@
+
+ #include <QFileDialog>
+
+-#include "core/Global.h"
+-
+ class FileDialog
+ {
+ public:
+- QString getOpenFileName(QWidget* parent = Q_NULLPTR, const QString& caption = QString(),
++ QString getOpenFileName(QWidget* parent = nullptr, const QString& caption = QString(),
+ QString dir = QString(), const QString& filter = QString(),
+- QString* selectedFilter = Q_NULLPTR, QFileDialog::Options options = 0);
+- QString getSaveFileName(QWidget* parent = Q_NULLPTR, const QString& caption = QString(),
++ QString* selectedFilter = nullptr, QFileDialog::Options options = 0);
++ QString getSaveFileName(QWidget* parent = nullptr, const QString& caption = QString(),
+ QString dir = QString(), const QString& filter = QString(),
+- QString* selectedFilter = Q_NULLPTR, QFileDialog::Options options = 0,
++ QString* selectedFilter = nullptr, QFileDialog::Options options = 0,
+ const QString& defaultExtension = QString());
+
+ /**
+diff --git a/src/gui/IconModels.h b/src/gui/IconModels.h
+index 8a24707..868ce44 100644
+--- a/src/gui/IconModels.h
++++ b/src/gui/IconModels.h
+@@ -21,7 +21,6 @@
+ #include <QAbstractListModel>
+ #include <QPixmap>
+
+-#include "core/Global.h"
+ #include "core/Uuid.h"
+
+ class DefaultIconModel : public QAbstractListModel
+@@ -29,10 +28,10 @@ class DefaultIconModel : public QAbstractListModel
+ Q_OBJECT
+
+ public:
+- explicit DefaultIconModel(QObject* parent = Q_NULLPTR);
++ explicit DefaultIconModel(QObject* parent = nullptr);
+
+- int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
++ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
++ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+ };
+
+ class CustomIconModel : public QAbstractListModel
+@@ -40,10 +39,10 @@ class CustomIconModel : public QAbstractListModel
+ Q_OBJECT
+
+ public:
+- explicit CustomIconModel(QObject* parent = Q_NULLPTR);
++ explicit CustomIconModel(QObject* parent = nullptr);
+
+- virtual int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
++ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
++ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+ void setIcons(const QHash<Uuid, QPixmap>& icons, const QList<Uuid>& iconsOrder);
+ Uuid uuidFromIndex(const QModelIndex& index) const;
+ QModelIndex indexFromUuid(const Uuid& uuid) const;
+diff --git a/src/gui/KeePass1OpenWidget.h b/src/gui/KeePass1OpenWidget.h
+index a398f9a..203b786 100644
+--- a/src/gui/KeePass1OpenWidget.h
++++ b/src/gui/KeePass1OpenWidget.h
+@@ -25,10 +25,10 @@ class KeePass1OpenWidget : public DatabaseOpenWidget
+ Q_OBJECT
+
+ public:
+- explicit KeePass1OpenWidget(QWidget* parent = Q_NULLPTR);
++ explicit KeePass1OpenWidget(QWidget* parent = nullptr);
+
+ protected:
+- void openDatabase() Q_DECL_OVERRIDE;
++ void openDatabase() override;
+ };
+
+ #endif // KEEPASSX_KEEPASS1OPENWIDGET_H
+diff --git a/src/gui/LineEdit.h b/src/gui/LineEdit.h
+index 2672aae..f5f0584 100644
+--- a/src/gui/LineEdit.h
++++ b/src/gui/LineEdit.h
+@@ -22,8 +22,6 @@
+
+ #include <QLineEdit>
+
+-#include "core/Global.h"
+-
+ class QToolButton;
+
+ class LineEdit : public QLineEdit
+@@ -31,10 +29,10 @@ class LineEdit : public QLineEdit
+ Q_OBJECT
+
+ public:
+- explicit LineEdit(QWidget* parent = Q_NULLPTR);
++ explicit LineEdit(QWidget* parent = nullptr);
+
+ protected:
+- void resizeEvent(QResizeEvent* event) Q_DECL_OVERRIDE;
++ void resizeEvent(QResizeEvent* event) override;
+
+ private Q_SLOTS:
+ void updateCloseButton(const QString& text);
+diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
+index b6dc1df..6245dc7 100644
+--- a/src/gui/MainWindow.cpp
++++ b/src/gui/MainWindow.cpp
+@@ -38,7 +38,7 @@ const QString MainWindow::BaseWindowTitle = "KeePassX";
+
+ MainWindow::MainWindow()
+ : m_ui(new Ui::MainWindow())
+- , m_trayIcon(Q_NULLPTR)
++ , m_trayIcon(nullptr)
+ {
+ m_ui->setupUi(this);
+
+@@ -227,6 +227,7 @@ void MainWindow::updateLastDatabasesMenu()
+ QStringList lastDatabases = config()->get("LastDatabases", QVariant()).toStringList();
+ Q_FOREACH (const QString& database, lastDatabases) {
+ QAction* action = m_ui->menuRecentDatabases->addAction(database);
++ action->setData(database);
+ m_lastDatabasesActions->addAction(action);
+ }
+ m_ui->menuRecentDatabases->addSeparator();
+@@ -257,7 +258,7 @@ void MainWindow::updateCopyAttributesMenu()
+
+ void MainWindow::openRecentDatabase(QAction* action)
+ {
+- openDatabase(action->text());
++ openDatabase(action->data().toString());
+ }
+
+ void MainWindow::clearLastDatabases()
+@@ -450,7 +451,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
+ }
+ }
+
+-void MainWindow::changeEvent(QEvent *event)
++void MainWindow::changeEvent(QEvent* event)
+ {
+ if ((event->type() == QEvent::WindowStateChange) && isMinimized()
+ && isTrayIconEnabled() && m_trayIcon && m_trayIcon->isVisible()
+@@ -521,7 +522,7 @@ void MainWindow::updateTrayIcon()
+ if (m_trayIcon) {
+ m_trayIcon->hide();
+ delete m_trayIcon;
+- m_trayIcon = Q_NULLPTR;
++ m_trayIcon = nullptr;
+ }
+ }
+ }
+@@ -622,7 +623,7 @@ void MainWindow::repairDatabase()
+ if (dialog->exec() == QDialog::Accepted && dbRepairWidget->database()) {
+ QString saveFileName = fileDialog()->getSaveFileName(this, tr("Save repaired database"), QString(),
+ tr("KeePass 2 Database").append(" (*.kdbx)"),
+- Q_NULLPTR, 0, "kdbx");
++ nullptr, 0, "kdbx");
+
+ if (!saveFileName.isEmpty()) {
+ KeePass2Writer writer;
+diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h
+index 5aa39ca..c52cfba 100644
+--- a/src/gui/MainWindow.h
++++ b/src/gui/MainWindow.h
+@@ -44,8 +44,8 @@ public Q_SLOTS:
+ const QString& keyFile = QString());
+
+ protected:
+- void closeEvent(QCloseEvent* event) Q_DECL_OVERRIDE;
+- void changeEvent(QEvent* event) Q_DECL_OVERRIDE;
++ void closeEvent(QCloseEvent* event) override;
++ void changeEvent(QEvent* event) override;
+
+ private Q_SLOTS:
+ void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::None);
+diff --git a/src/gui/MessageBox.h b/src/gui/MessageBox.h
+index abb12c0..1ea4022 100644
+--- a/src/gui/MessageBox.h
++++ b/src/gui/MessageBox.h
+@@ -20,8 +20,6 @@
+
+ #include <QMessageBox>
+
+-#include "core/Global.h"
+-
+ class MessageBox
+ {
+ public:
+diff --git a/src/gui/PasswordComboBox.cpp b/src/gui/PasswordComboBox.cpp
+index f11311a..e121850 100644
+--- a/src/gui/PasswordComboBox.cpp
++++ b/src/gui/PasswordComboBox.cpp
+@@ -24,7 +24,7 @@
+
+ PasswordComboBox::PasswordComboBox(QWidget* parent)
+ : QComboBox(parent)
+- , m_generator(Q_NULLPTR)
++ , m_generator(nullptr)
+ , m_alternatives(10)
+ {
+ setEditable(true);
+@@ -51,7 +51,6 @@ void PasswordComboBox::setEcho(bool echo)
+ #else
+ setStyleSheet("QComboBox { font-family: monospace,Courier; }");
+ #endif
+-
+ }
+ else {
+ // clear items so the combobox indicates that no popup menu is available
+diff --git a/src/gui/PasswordComboBox.h b/src/gui/PasswordComboBox.h
+index 69ce152..7c54e27 100644
+--- a/src/gui/PasswordComboBox.h
++++ b/src/gui/PasswordComboBox.h
+@@ -21,8 +21,6 @@
+
+ #include <QComboBox>
+
+-#include "core/Global.h"
+-
+ class PasswordGenerator;
+
+ class PasswordComboBox : public QComboBox
+@@ -30,7 +28,7 @@ class PasswordComboBox : public QComboBox
+ Q_OBJECT
+
+ public:
+- explicit PasswordComboBox(QWidget* parent = Q_NULLPTR);
++ explicit PasswordComboBox(QWidget* parent = nullptr);
+ ~PasswordComboBox();
+
+ void setGenerator(PasswordGenerator* generator);
+diff --git a/src/gui/PasswordEdit.cpp b/src/gui/PasswordEdit.cpp
+index b68eef6..e5bbf6b 100644
+--- a/src/gui/PasswordEdit.cpp
++++ b/src/gui/PasswordEdit.cpp
+@@ -17,14 +17,12 @@
+
+ #include "PasswordEdit.h"
+
+-#include "core/Global.h"
+-
+ const QColor PasswordEdit::CorrectSoFarColor = QColor(255, 205, 15);
+ const QColor PasswordEdit::ErrorColor = QColor(255, 125, 125);
+
+ PasswordEdit::PasswordEdit(QWidget* parent)
+ : QLineEdit(parent)
+- , m_basePasswordEdit(Q_NULLPTR)
++ , m_basePasswordEdit(nullptr)
+ {
+ }
+
+diff --git a/src/gui/PasswordEdit.h b/src/gui/PasswordEdit.h
+index cfb4a76..7ce4908 100644
+--- a/src/gui/PasswordEdit.h
++++ b/src/gui/PasswordEdit.h
+@@ -20,8 +20,6 @@
+
+ #include <QLineEdit>
+
+-#include "core/Global.h"
+-
+ class PasswordEdit : public QLineEdit
+ {
+ Q_OBJECT
+@@ -30,7 +28,7 @@ public:
+ static const QColor CorrectSoFarColor;
+ static const QColor ErrorColor;
+
+- explicit PasswordEdit(QWidget* parent = Q_NULLPTR);
++ explicit PasswordEdit(QWidget* parent = nullptr);
+ void enableVerifyMode(PasswordEdit* baseEdit);
+
+ public Q_SLOTS:
+diff --git a/src/gui/PasswordGeneratorWidget.h b/src/gui/PasswordGeneratorWidget.h
+index 96f3f60..cfb21bb 100644
+--- a/src/gui/PasswordGeneratorWidget.h
++++ b/src/gui/PasswordGeneratorWidget.h
+@@ -21,7 +21,6 @@
+ #include <QWidget>
+ #include <QComboBox>
+
+-#include "core/Global.h"
+ #include "core/PasswordGenerator.h"
+
+ namespace Ui {
+@@ -35,7 +34,7 @@ class PasswordGeneratorWidget : public QWidget
+ Q_OBJECT
+
+ public:
+- explicit PasswordGeneratorWidget(QWidget* parent = Q_NULLPTR);
++ explicit PasswordGeneratorWidget(QWidget* parent = nullptr);
+ ~PasswordGeneratorWidget();
+ void loadSettings();
+ void reset();
+diff --git a/src/gui/SettingsWidget.h b/src/gui/SettingsWidget.h
+index cefbf6d..3fe621d 100644
+--- a/src/gui/SettingsWidget.h
++++ b/src/gui/SettingsWidget.h
+@@ -30,7 +30,7 @@ class SettingsWidget : public EditWidget
+ Q_OBJECT
+
+ public:
+- explicit SettingsWidget(QWidget* parent = Q_NULLPTR);
++ explicit SettingsWidget(QWidget* parent = nullptr);
+ ~SettingsWidget();
+ void loadSettings();
+
+diff --git a/src/gui/SortFilterHideProxyModel.cpp b/src/gui/SortFilterHideProxyModel.cpp
+index 0902361..0193d95 100644
+--- a/src/gui/SortFilterHideProxyModel.cpp
++++ b/src/gui/SortFilterHideProxyModel.cpp
+@@ -22,6 +22,11 @@ SortFilterHideProxyModel::SortFilterHideProxyModel(QObject* parent)
+ {
+ }
+
++Qt::DropActions SortFilterHideProxyModel::supportedDragActions() const
++{
++ return sourceModel()->supportedDragActions();
++}
++
+ void SortFilterHideProxyModel::hideColumn(int column, bool hide)
+ {
+ m_hiddenColumns.resize(column + 1);
+diff --git a/src/gui/SortFilterHideProxyModel.h b/src/gui/SortFilterHideProxyModel.h
+index a6f1e71..58d9ff7 100644
+--- a/src/gui/SortFilterHideProxyModel.h
++++ b/src/gui/SortFilterHideProxyModel.h
+@@ -21,18 +21,17 @@
+ #include <QBitArray>
+ #include <QSortFilterProxyModel>
+
+-#include "core/Global.h"
+-
+ class SortFilterHideProxyModel : public QSortFilterProxyModel
+ {
+ Q_OBJECT
+
+ public:
+- explicit SortFilterHideProxyModel(QObject* parent = Q_NULLPTR);
++ explicit SortFilterHideProxyModel(QObject* parent = nullptr);
++ Qt::DropActions supportedDragActions() const override;
+ void hideColumn(int column, bool hide);
+
+ protected:
+- bool filterAcceptsColumn(int sourceColumn, const QModelIndex& sourceParent) const Q_DECL_OVERRIDE;
++ bool filterAcceptsColumn(int sourceColumn, const QModelIndex& sourceParent) const override;
+
+ private:
+ QBitArray m_hiddenColumns;
+diff --git a/src/gui/UnlockDatabaseWidget.cpp b/src/gui/UnlockDatabaseWidget.cpp
+index 242b07a..a005d0e 100644
+--- a/src/gui/UnlockDatabaseWidget.cpp
++++ b/src/gui/UnlockDatabaseWidget.cpp
+@@ -34,5 +34,5 @@ void UnlockDatabaseWidget::clearForms()
+ m_ui->checkPassword->setChecked(false);
+ m_ui->checkKeyFile->setChecked(false);
+ m_ui->buttonTogglePassword->setChecked(false);
+- m_db = Q_NULLPTR;
++ m_db = nullptr;
+ }
+diff --git a/src/gui/UnlockDatabaseWidget.h b/src/gui/UnlockDatabaseWidget.h
+index 052578b..adb5efb 100644
+--- a/src/gui/UnlockDatabaseWidget.h
++++ b/src/gui/UnlockDatabaseWidget.h
+@@ -25,7 +25,7 @@ class UnlockDatabaseWidget : public DatabaseOpenWidget
+ Q_OBJECT
+
+ public:
+- explicit UnlockDatabaseWidget(QWidget* parent = Q_NULLPTR);
++ explicit UnlockDatabaseWidget(QWidget* parent = nullptr);
+ void clearForms();
+ };
+
+diff --git a/src/gui/WelcomeWidget.h b/src/gui/WelcomeWidget.h
+index 983aaa0..80a0dde 100644
+--- a/src/gui/WelcomeWidget.h
++++ b/src/gui/WelcomeWidget.h
+@@ -20,8 +20,6 @@
+
+ #include <QWidget>
+
+-#include "core/Global.h"
+-
+ namespace Ui {
+ class WelcomeWidget;
+ }
+@@ -31,7 +29,7 @@ class WelcomeWidget : public QWidget
+ Q_OBJECT
+
+ public:
+- explicit WelcomeWidget(QWidget* parent = Q_NULLPTR);
++ explicit WelcomeWidget(QWidget* parent = nullptr);
+ ~WelcomeWidget();
+
+ private:
+diff --git a/src/gui/entry/AutoTypeAssociationsModel.cpp b/src/gui/entry/AutoTypeAssociationsModel.cpp
+index 6d6dc97..49f6786 100644
+--- a/src/gui/entry/AutoTypeAssociationsModel.cpp
++++ b/src/gui/entry/AutoTypeAssociationsModel.cpp
+@@ -19,7 +19,7 @@
+
+ AutoTypeAssociationsModel::AutoTypeAssociationsModel(QObject* parent)
+ : QAbstractListModel(parent)
+- , m_autoTypeAssociations(Q_NULLPTR)
++ , m_autoTypeAssociations(nullptr)
+ {
+ }
+
+diff --git a/src/gui/entry/AutoTypeAssociationsModel.h b/src/gui/entry/AutoTypeAssociationsModel.h
+index ecb4247..c75168c 100644
+--- a/src/gui/entry/AutoTypeAssociationsModel.h
++++ b/src/gui/entry/AutoTypeAssociationsModel.h
+@@ -29,12 +29,12 @@ class AutoTypeAssociationsModel : public QAbstractListModel
+ Q_OBJECT
+
+ public:
+- explicit AutoTypeAssociationsModel(QObject* parent = Q_NULLPTR);
++ explicit AutoTypeAssociationsModel(QObject* parent = nullptr);
+ void setAutoTypeAssociations(AutoTypeAssociations* autoTypeAssociations);
+- int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+- QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
++ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
++ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
++ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
++ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+
+ public Q_SLOTS:
+ void associationChange(int i);
+diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp
+index 8cad924..00d510c 100644
+--- a/src/gui/entry/EditEntryWidget.cpp
++++ b/src/gui/entry/EditEntryWidget.cpp
+@@ -23,6 +23,7 @@
+
+ #include <QDesktopServices>
+ #include <QStackedLayout>
++#include <QStandardPaths>
+ #include <QMenu>
+ #include <QSortFilterProxyModel>
+ #include <QTemporaryFile>
+@@ -45,7 +46,7 @@
+
+ EditEntryWidget::EditEntryWidget(QWidget* parent)
+ : EditWidget(parent)
+- , m_entry(Q_NULLPTR)
++ , m_entry(nullptr)
+ , m_mainUi(new Ui::EditEntryWidgetMain())
+ , m_advancedUi(new Ui::EditEntryWidgetAdvanced())
+ , m_autoTypeUi(new Ui::EditEntryWidgetAutoType())
+@@ -232,7 +233,7 @@ void EditEntryWidget::useExpiryPreset(QAction* action)
+ {
+ m_mainUi->expireCheck->setChecked(true);
+ TimeDelta delta = action->data().value<TimeDelta>();
+- QDateTime now = Tools::currentDateTimeUtc().toLocalTime();
++ QDateTime now = QDateTime::currentDateTime();
+ QDateTime expiryDateTime = now + delta;
+ m_mainUi->expireDatePicker->setDateTime(expiryDateTime);
+ }
+@@ -477,8 +478,8 @@ void EditEntryWidget::cancel()
+
+ void EditEntryWidget::clear()
+ {
+- m_entry = Q_NULLPTR;
+- m_database = Q_NULLPTR;
++ m_entry = nullptr;
++ m_database = nullptr;
+ m_entryAttributes->clear();
+ m_entryAttachments->clear();
+ m_autoTypeAssoc->clear();
+@@ -590,7 +591,7 @@ void EditEntryWidget::insertAttachment()
+
+ QString defaultDir = config()->get("LastAttachmentDir").toString();
+ if (defaultDir.isEmpty() || !QDir(defaultDir).exists()) {
+- defaultDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
++ defaultDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).value(0);
+ }
+ QString filename = fileDialog()->getOpenFileName(this, tr("Select file"), defaultDir);
+ if (filename.isEmpty() || !QFile::exists(filename)) {
+@@ -624,7 +625,7 @@ void EditEntryWidget::saveCurrentAttachment()
+ QString filename = m_attachmentsModel->keyByIndex(index);
+ QString defaultDirName = config()->get("LastAttachmentDir").toString();
+ if (defaultDirName.isEmpty() || !QDir(defaultDirName).exists()) {
+- defaultDirName = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
++ defaultDirName = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
+ }
+ QDir dir(defaultDirName);
+ QString savePath = fileDialog()->getSaveFileName(this, tr("Save attachment"),
+diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h
+index 03811bf..3c66b2a 100644
+--- a/src/gui/entry/EditEntryWidget.h
++++ b/src/gui/entry/EditEntryWidget.h
+@@ -52,7 +52,7 @@ class EditEntryWidget : public EditWidget
+ Q_OBJECT
+
+ public:
+- explicit EditEntryWidget(QWidget* parent = Q_NULLPTR);
++ explicit EditEntryWidget(QWidget* parent = nullptr);
+ ~EditEntryWidget();
+
+ void loadEntry(Entry* entry, bool create, bool history, const QString& parentName,
+diff --git a/src/gui/entry/EntryAttachmentsModel.cpp b/src/gui/entry/EntryAttachmentsModel.cpp
+index e072d17..39ed69f 100644
+--- a/src/gui/entry/EntryAttachmentsModel.cpp
++++ b/src/gui/entry/EntryAttachmentsModel.cpp
+@@ -20,9 +20,11 @@
+ #include "core/Entry.h"
+ #include "core/Tools.h"
+
++#include <algorithm>
++
+ EntryAttachmentsModel::EntryAttachmentsModel(QObject* parent)
+ : QAbstractListModel(parent)
+- , m_entryAttachments(Q_NULLPTR)
++ , m_entryAttachments(nullptr)
+ {
+ }
+
+@@ -102,7 +104,7 @@ void EntryAttachmentsModel::attachmentAboutToAdd(const QString& key)
+ {
+ QList<QString> rows = m_entryAttachments->keys();
+ rows.append(key);
+- qSort(rows);
++ std::sort(rows.begin(), rows.end());
+ int row = rows.indexOf(key);
+ beginInsertRows(QModelIndex(), row, row);
+ }
+diff --git a/src/gui/entry/EntryAttachmentsModel.h b/src/gui/entry/EntryAttachmentsModel.h
+index 177cde0..c2e238a 100644
+--- a/src/gui/entry/EntryAttachmentsModel.h
++++ b/src/gui/entry/EntryAttachmentsModel.h
+@@ -20,8 +20,6 @@
+
+ #include <QAbstractListModel>
+
+-#include "core/Global.h"
+-
+ class EntryAttachments;
+
+ class EntryAttachmentsModel : public QAbstractListModel
+@@ -29,11 +27,11 @@ class EntryAttachmentsModel : public QAbstractListModel
+ Q_OBJECT
+
+ public:
+- explicit EntryAttachmentsModel(QObject* parent = Q_NULLPTR);
++ explicit EntryAttachmentsModel(QObject* parent = nullptr);
+ void setEntryAttachments(EntryAttachments* entry);
+- int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
++ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
++ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
++ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+ QString keyByIndex(const QModelIndex& index) const;
+
+ private Q_SLOTS:
+diff --git a/src/gui/entry/EntryAttributesModel.cpp b/src/gui/entry/EntryAttributesModel.cpp
+index f73a2d2..297740c 100644
+--- a/src/gui/entry/EntryAttributesModel.cpp
++++ b/src/gui/entry/EntryAttributesModel.cpp
+@@ -20,9 +20,11 @@
+ #include "core/Entry.h"
+ #include "core/Tools.h"
+
++#include <algorithm>
++
+ EntryAttributesModel::EntryAttributesModel(QObject* parent)
+ : QAbstractListModel(parent)
+- , m_entryAttributes(Q_NULLPTR)
++ , m_entryAttributes(nullptr)
+ , m_nextRenameDataChange(false)
+ {
+ }
+@@ -152,7 +154,7 @@ void EntryAttributesModel::attributeAboutToAdd(const QString& key)
+ {
+ QList<QString> rows = m_attributes;
+ rows.append(key);
+- qSort(rows);
++ std::sort(rows.begin(), rows.end());
+ int row = rows.indexOf(key);
+ beginInsertRows(QModelIndex(), row, row);
+ }
+@@ -182,7 +184,7 @@ void EntryAttributesModel::attributeAboutToRename(const QString& oldKey, const Q
+ QList<QString> rows = m_attributes;
+ rows.removeOne(oldKey);
+ rows.append(newKey);
+- qSort(rows);
++ std::sort(rows.begin(), rows.end());
+ int newRow = rows.indexOf(newKey);
+ if (newRow > oldRow) {
+ newRow++;
+diff --git a/src/gui/entry/EntryAttributesModel.h b/src/gui/entry/EntryAttributesModel.h
+index f6ac651..1eec8bf 100644
+--- a/src/gui/entry/EntryAttributesModel.h
++++ b/src/gui/entry/EntryAttributesModel.h
+@@ -20,8 +20,6 @@
+
+ #include <QAbstractListModel>
+
+-#include "core/Global.h"
+-
+ class EntryAttributes;
+
+ class EntryAttributesModel : public QAbstractListModel
+@@ -29,14 +27,14 @@ class EntryAttributesModel : public QAbstractListModel
+ Q_OBJECT
+
+ public:
+- explicit EntryAttributesModel(QObject* parent = Q_NULLPTR);
++ explicit EntryAttributesModel(QObject* parent = nullptr);
+ void setEntryAttributes(EntryAttributes* entryAttributes);
+- int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+- QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+- bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
+- Qt::ItemFlags flags(const QModelIndex& index) const Q_DECL_OVERRIDE;
++ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
++ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
++ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
++ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
++ bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
++ Qt::ItemFlags flags(const QModelIndex& index) const override;
+ QModelIndex indexByKey(const QString& key) const;
+ QString keyByIndex(const QModelIndex& index) const;
+
+diff --git a/src/gui/entry/EntryHistoryModel.h b/src/gui/entry/EntryHistoryModel.h
+index 6c8073a..a7434e0 100644
+--- a/src/gui/entry/EntryHistoryModel.h
++++ b/src/gui/entry/EntryHistoryModel.h
+@@ -20,8 +20,6 @@
+
+ #include <QAbstractTableModel>
+
+-#include "core/Global.h"
+-
+ class Entry;
+
+ class EntryHistoryModel : public QAbstractTableModel
+@@ -29,13 +27,13 @@ class EntryHistoryModel : public QAbstractTableModel
+ Q_OBJECT
+
+ public:
+- explicit EntryHistoryModel(QObject* parent = Q_NULLPTR);
++ explicit EntryHistoryModel(QObject* parent = nullptr);
+
+ Entry* entryFromIndex(const QModelIndex& index) const;
+- int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+- QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
++ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
++ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
++ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
++ QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
+
+ void setEntries(const QList<Entry*>& entries);
+ void clear();
+diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp
+index 084ad72..efb64de 100644
+--- a/src/gui/entry/EntryModel.cpp
++++ b/src/gui/entry/EntryModel.cpp
+@@ -27,9 +27,8 @@
+
+ EntryModel::EntryModel(QObject* parent)
+ : QAbstractTableModel(parent)
+- , m_group(Q_NULLPTR)
++ , m_group(nullptr)
+ {
+- setSupportedDragActions(Qt::MoveAction | Qt::CopyAction);
+ }
+
+ Entry* EntryModel::entryFromIndex(const QModelIndex& index) const
+@@ -72,7 +71,7 @@ void EntryModel::setEntryList(const QList<Entry*>& entries)
+
+ severConnections();
+
+- m_group = Q_NULLPTR;
++ m_group = nullptr;
+ m_allGroups.clear();
+ m_entries = entries;
+ m_orgEntries = entries;
+@@ -191,6 +190,11 @@ Qt::DropActions EntryModel::supportedDropActions() const
+ return 0;
+ }
+
++Qt::DropActions EntryModel::supportedDragActions() const
++{
++ return (Qt::MoveAction | Qt::CopyAction);
++}
++
+ Qt::ItemFlags EntryModel::flags(const QModelIndex& modelIndex) const
+ {
+ if (!modelIndex.isValid()) {
+@@ -211,7 +215,7 @@ QStringList EntryModel::mimeTypes() const
+ QMimeData* EntryModel::mimeData(const QModelIndexList& indexes) const
+ {
+ if (indexes.isEmpty()) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QMimeData* data = new QMimeData();
+@@ -236,7 +240,7 @@ QMimeData* EntryModel::mimeData(const QModelIndexList& indexes) const
+
+ if (seenEntries.isEmpty()) {
+ delete data;
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ else {
+ data->setData(mimeTypes().at(0), encoded);
+@@ -294,11 +298,11 @@ void EntryModel::entryDataChanged(Entry* entry)
+ void EntryModel::severConnections()
+ {
+ if (m_group) {
+- disconnect(m_group, Q_NULLPTR, this, Q_NULLPTR);
++ disconnect(m_group, nullptr, this, nullptr);
+ }
+
+ Q_FOREACH (const Group* group, m_allGroups) {
+- disconnect(group, Q_NULLPTR, this, Q_NULLPTR);
++ disconnect(group, nullptr, this, nullptr);
+ }
+ }
+
+diff --git a/src/gui/entry/EntryModel.h b/src/gui/entry/EntryModel.h
+index 20bcad9..0183c47 100644
+--- a/src/gui/entry/EntryModel.h
++++ b/src/gui/entry/EntryModel.h
+@@ -20,8 +20,6 @@
+
+ #include <QAbstractTableModel>
+
+-#include "core/Global.h"
+-
+ class Entry;
+ class Group;
+
+@@ -38,18 +36,19 @@ public:
+ Url = 3
+ };
+
+- explicit EntryModel(QObject* parent = Q_NULLPTR);
++ explicit EntryModel(QObject* parent = nullptr);
+ Entry* entryFromIndex(const QModelIndex& index) const;
+ QModelIndex indexFromEntry(Entry* entry) const;
+
+- int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+- QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+- Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
+- Qt::ItemFlags flags(const QModelIndex& modelIndex) const Q_DECL_OVERRIDE;
+- QStringList mimeTypes() const Q_DECL_OVERRIDE;
+- QMimeData* mimeData(const QModelIndexList& indexes) const Q_DECL_OVERRIDE;
++ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
++ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
++ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
++ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
++ Qt::DropActions supportedDropActions() const override;
++ Qt::DropActions supportedDragActions() const override;
++ Qt::ItemFlags flags(const QModelIndex& modelIndex) const override;
++ QStringList mimeTypes() const override;
++ QMimeData* mimeData(const QModelIndexList& indexes) const override;
+
+ void setEntryList(const QList<Entry*>& entries);
+
+diff --git a/src/gui/entry/EntryView.cpp b/src/gui/entry/EntryView.cpp
+index cd2c6fb..1c900a5 100644
+--- a/src/gui/entry/EntryView.cpp
++++ b/src/gui/entry/EntryView.cpp
+@@ -32,7 +32,6 @@ EntryView::EntryView(QWidget* parent)
+ m_sortModel->setDynamicSortFilter(true);
+ m_sortModel->setSortLocaleAware(true);
+ m_sortModel->setSortCaseSensitivity(Qt::CaseInsensitive);
+- m_sortModel->setSupportedDragActions(m_model->supportedDragActions());
+ QTreeView::setModel(m_sortModel);
+
+ setUniformRowHeights(true);
+@@ -75,7 +74,7 @@ void EntryView::setEntryList(const QList<Entry*>& entries)
+
+ void EntryView::setFirstEntryActive()
+ {
+- if(m_model->rowCount() > 0) {
++ if (m_model->rowCount() > 0) {
+ QModelIndex index = m_sortModel->mapToSource(m_sortModel->index(0, 0));
+ setCurrentEntry(m_model->entryFromIndex(index));
+ }
+@@ -109,7 +108,7 @@ Entry* EntryView::currentEntry()
+ return m_model->entryFromIndex(m_sortModel->mapToSource(list.first()));
+ }
+ else {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+@@ -130,7 +129,7 @@ Entry* EntryView::entryFromIndex(const QModelIndex& index)
+ return m_model->entryFromIndex(m_sortModel->mapToSource(index));
+ }
+ else {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+diff --git a/src/gui/entry/EntryView.h b/src/gui/entry/EntryView.h
+index c11d041..fb9e356 100644
+--- a/src/gui/entry/EntryView.h
++++ b/src/gui/entry/EntryView.h
+@@ -20,8 +20,6 @@
+
+ #include <QTreeView>
+
+-#include "core/Global.h"
+-
+ #include "gui/entry/EntryModel.h"
+
+ class Entry;
+@@ -34,8 +32,8 @@ class EntryView : public QTreeView
+ Q_OBJECT
+
+ public:
+- explicit EntryView(QWidget* parent = Q_NULLPTR);
+- void setModel(QAbstractItemModel* model) Q_DECL_OVERRIDE;
++ explicit EntryView(QWidget* parent = nullptr);
++ void setModel(QAbstractItemModel* model) override;
+ Entry* currentEntry();
+ void setCurrentEntry(Entry* entry);
+ Entry* entryFromIndex(const QModelIndex& index);
+@@ -52,7 +50,7 @@ Q_SIGNALS:
+ void entrySelectionChanged();
+
+ protected:
+- void keyPressEvent(QKeyEvent* event) Q_DECL_OVERRIDE;
++ void keyPressEvent(QKeyEvent* event) override;
+
+ private Q_SLOTS:
+ void emitEntryActivated(const QModelIndex& index);
+diff --git a/src/gui/group/EditGroupWidget.cpp b/src/gui/group/EditGroupWidget.cpp
+index ebe5cb9..7fdec89 100644
+--- a/src/gui/group/EditGroupWidget.cpp
++++ b/src/gui/group/EditGroupWidget.cpp
+@@ -28,8 +28,8 @@ EditGroupWidget::EditGroupWidget(QWidget* parent)
+ , m_editGroupWidgetMain(new QWidget())
+ , m_editGroupWidgetIcons(new EditWidgetIcons())
+ , m_editWidgetProperties(new EditWidgetProperties())
+- , m_group(Q_NULLPTR)
+- , m_database(Q_NULLPTR)
++ , m_group(nullptr)
++ , m_database(nullptr)
+ {
+ m_mainUi->setupUi(m_editGroupWidgetMain);
+
+@@ -142,8 +142,8 @@ void EditGroupWidget::cancel()
+
+ void EditGroupWidget::clear()
+ {
+- m_group = Q_NULLPTR;
+- m_database = Q_NULLPTR;
++ m_group = nullptr;
++ m_database = nullptr;
+ }
+
+ void EditGroupWidget::addTriStateItems(QComboBox* comboBox, bool inheritDefault)
+diff --git a/src/gui/group/EditGroupWidget.h b/src/gui/group/EditGroupWidget.h
+index c6d91a5..94ad891 100644
+--- a/src/gui/group/EditGroupWidget.h
++++ b/src/gui/group/EditGroupWidget.h
+@@ -37,7 +37,7 @@ class EditGroupWidget : public EditWidget
+ Q_OBJECT
+
+ public:
+- explicit EditGroupWidget(QWidget* parent = Q_NULLPTR);
++ explicit EditGroupWidget(QWidget* parent = nullptr);
+ ~EditGroupWidget();
+
+ void loadGroup(Group* group, bool create, Database* database);
+diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp
+index 1244ad7..fc6d83e 100644
+--- a/src/gui/group/GroupModel.cpp
++++ b/src/gui/group/GroupModel.cpp
+@@ -28,7 +28,7 @@
+
+ GroupModel::GroupModel(Database* db, QObject* parent)
+ : QAbstractItemModel(parent)
+- , m_db(Q_NULLPTR)
++ , m_db(nullptr)
+ {
+ changeDatabase(db);
+ }
+@@ -329,7 +329,7 @@ QStringList GroupModel::mimeTypes() const
+ QMimeData* GroupModel::mimeData(const QModelIndexList& indexes) const
+ {
+ if (indexes.isEmpty()) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QMimeData* data = new QMimeData();
+@@ -354,7 +354,7 @@ QMimeData* GroupModel::mimeData(const QModelIndexList& indexes) const
+
+ if (seenGroups.isEmpty()) {
+ delete data;
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ else {
+ data->setData(mimeTypes().at(0), encoded);
+diff --git a/src/gui/group/GroupModel.h b/src/gui/group/GroupModel.h
+index 752eb2b..0ef0ba9 100644
+--- a/src/gui/group/GroupModel.h
++++ b/src/gui/group/GroupModel.h
+@@ -20,8 +20,6 @@
+
+ #include <QAbstractItemModel>
+
+-#include "core/Global.h"
+-
+ class Database;
+ class Group;
+
+@@ -30,23 +28,23 @@ class GroupModel : public QAbstractItemModel
+ Q_OBJECT
+
+ public:
+- explicit GroupModel(Database* db, QObject* parent = Q_NULLPTR);
++ explicit GroupModel(Database* db, QObject* parent = nullptr);
+ void changeDatabase(Database* newDb);
+ QModelIndex index(Group* group) const;
+ Group* groupFromIndex(const QModelIndex& index) const;
+
+- int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
+- QModelIndex parent(const QModelIndex& index) const Q_DECL_OVERRIDE;
+- QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+- QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+- Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
+- Qt::ItemFlags flags(const QModelIndex& modelIndex) const Q_DECL_OVERRIDE;
++ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
++ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
++ QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
++ QModelIndex parent(const QModelIndex& index) const override;
++ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
++ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
++ Qt::DropActions supportedDropActions() const override;
++ Qt::ItemFlags flags(const QModelIndex& modelIndex) const override;
+ bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column,
+- const QModelIndex& parent) Q_DECL_OVERRIDE;
+- QStringList mimeTypes() const Q_DECL_OVERRIDE;
+- QMimeData* mimeData(const QModelIndexList& indexes) const Q_DECL_OVERRIDE;
++ const QModelIndex& parent) override;
++ QStringList mimeTypes() const override;
++ QMimeData* mimeData(const QModelIndexList& indexes) const override;
+
+ private:
+ QModelIndex parent(Group* group) const;
+diff --git a/src/gui/group/GroupView.cpp b/src/gui/group/GroupView.cpp
+index 3c93662..1f94dc0 100644
+--- a/src/gui/group/GroupView.cpp
++++ b/src/gui/group/GroupView.cpp
+@@ -19,6 +19,7 @@
+
+ #include <QDragMoveEvent>
+ #include <QMetaObject>
++#include <QMimeData>
+
+ #include "core/Database.h"
+ #include "core/Group.h"
+@@ -74,7 +75,7 @@ void GroupView::dragMoveEvent(QDragMoveEvent* event)
+ Group* GroupView::currentGroup()
+ {
+ if (currentIndex() == QModelIndex()) {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ else {
+ return m_model->groupFromIndex(currentIndex());
+diff --git a/src/gui/group/GroupView.h b/src/gui/group/GroupView.h
+index 06bdbaf..69ca828 100644
+--- a/src/gui/group/GroupView.h
++++ b/src/gui/group/GroupView.h
+@@ -20,8 +20,6 @@
+
+ #include <QTreeView>
+
+-#include "core/Global.h"
+-
+ class Database;
+ class Group;
+ class GroupModel;
+@@ -31,9 +29,9 @@ class GroupView : public QTreeView
+ Q_OBJECT
+
+ public:
+- explicit GroupView(Database* db, QWidget* parent = Q_NULLPTR);
++ explicit GroupView(Database* db, QWidget* parent = nullptr);
+ void changeDatabase(Database* newDb);
+- void setModel(QAbstractItemModel* model) Q_DECL_OVERRIDE;
++ void setModel(QAbstractItemModel* model) override;
+ Group* currentGroup();
+ void setCurrentGroup(Group* group);
+ void expandGroup(Group* group, bool expand = true);
+@@ -49,7 +47,7 @@ private Q_SLOTS:
+ void modelReset();
+
+ protected:
+- void dragMoveEvent(QDragMoveEvent* event) Q_DECL_OVERRIDE;
++ void dragMoveEvent(QDragMoveEvent* event) override;
+
+ private:
+ void recInitExpanded(Group* group);
+diff --git a/src/keys/CompositeKey.cpp b/src/keys/CompositeKey.cpp
+index 5bf9cae..d38f466 100644
+--- a/src/keys/CompositeKey.cpp
++++ b/src/keys/CompositeKey.cpp
+@@ -18,8 +18,8 @@
+ #include "CompositeKey.h"
+ #include "CompositeKey_p.h"
+
+-#include <QtConcurrentRun>
+-#include <QTime>
++#include <QtConcurrent>
++#include <QElapsedTimer>
+
+ #include "crypto/CryptoHash.h"
+ #include "crypto/SymmetricCipher.h"
+@@ -94,7 +94,8 @@ QByteArray CompositeKey::transform(const QByteArray& seed, quint64 rounds,
+
+ QByteArray key = rawKey();
+
+- QFuture<QByteArray> future = QtConcurrent::run(transformKeyRaw, key.left(16), seed, rounds, &okLeft, &errorStringLeft);
++ QFuture<QByteArray> future = QtConcurrent::run(transformKeyRaw, key.left(16), seed, rounds,
++ &okLeft, &errorStringLeft);
+ QByteArray result2 = transformKeyRaw(key.right(16), seed, rounds, &okRight, &errorStringRight);
+
+ QByteArray transformed;
+@@ -182,7 +183,7 @@ void TransformKeyBenchmarkThread::run()
+ SymmetricCipher::Encrypt);
+ cipher.init(seed, iv);
+
+- QTime t;
++ QElapsedTimer t;
+ t.start();
+
+ do {
+@@ -191,5 +192,5 @@ void TransformKeyBenchmarkThread::run()
+ return;
+ }
+ m_rounds += 10000;
+- } while (t.elapsed() < m_msec);
++ } while (!t.hasExpired(m_msec));
+ }
+diff --git a/src/keys/FileKey.h b/src/keys/FileKey.h
+index f985433..7a9b1ca 100644
+--- a/src/keys/FileKey.h
++++ b/src/keys/FileKey.h
+@@ -20,7 +20,6 @@
+
+ #include <QXmlStreamReader>
+
+-#include "core/Global.h"
+ #include "keys/Key.h"
+
+ class QIODevice;
+@@ -30,11 +29,11 @@ class FileKey : public Key
+ public:
+ FileKey();
+ bool load(QIODevice* device);
+- bool load(const QString& fileName, QString* errorMsg = Q_NULLPTR);
++ bool load(const QString& fileName, QString* errorMsg = nullptr);
+ QByteArray rawKey() const;
+ FileKey* clone() const;
+ static void create(QIODevice* device);
+- static bool create(const QString& fileName, QString* errorMsg = Q_NULLPTR);
++ static bool create(const QString& fileName, QString* errorMsg = nullptr);
+
+ private:
+ bool loadXml(QIODevice* device);
+diff --git a/src/main.cpp b/src/main.cpp
+index bf558f1..04b70a4 100644
+--- a/src/main.cpp
++++ b/src/main.cpp
+@@ -15,11 +15,11 @@
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
++#include <QCommandLineParser>
+ #include <QFile>
+
+ #include "config-keepassx.h"
+ #include "core/Config.h"
+-#include "core/qcommandlineparser.h"
+ #include "core/Tools.h"
+ #include "core/Translator.h"
+ #include "crypto/Crypto.h"
+@@ -38,7 +38,7 @@ int main(int argc, char** argv)
+ Application::setApplicationName("keepassx");
+ Application::setApplicationVersion(KEEPASSX_VERSION);
+ // don't set organizationName as that changes the return value of
+- // QDesktopServices::storageLocation(QDesktopServices::DataLocation)
++ // QStandardPaths::writableLocation(QDesktopServices::DataLocation)
+
+ QApplication::setQuitOnLastWindowClosed(false);
+
+@@ -47,7 +47,7 @@ int main(int argc, char** argv)
+ "Fatal error while testing the cryptographic functions.");
+ error.append("\n");
+ error.append(Crypto::errorString());
+- MessageBox::critical(Q_NULLPTR, QCoreApplication::translate("Main", "KeePassX - Error"), error);
++ MessageBox::critical(nullptr, QCoreApplication::translate("Main", "KeePassX - Error"), error);
+ return 1;
+ }
+
+diff --git a/src/streams/HashedBlockStream.h b/src/streams/HashedBlockStream.h
+index cae4eb4..93e4af5 100644
+--- a/src/streams/HashedBlockStream.h
++++ b/src/streams/HashedBlockStream.h
+@@ -31,12 +31,12 @@ public:
+ HashedBlockStream(QIODevice* baseDevice, qint32 blockSize);
+ ~HashedBlockStream();
+
+- bool reset() Q_DECL_OVERRIDE;
+- void close() Q_DECL_OVERRIDE;
++ bool reset() override;
++ void close() override;
+
+ protected:
+- qint64 readData(char* data, qint64 maxSize) Q_DECL_OVERRIDE;
+- qint64 writeData(const char* data, qint64 maxSize) Q_DECL_OVERRIDE;
++ qint64 readData(char* data, qint64 maxSize) override;
++ qint64 writeData(const char* data, qint64 maxSize) override;
+
+ private:
+ void init();
+diff --git a/src/streams/LayeredStream.h b/src/streams/LayeredStream.h
+index b243e55..8586b41 100644
+--- a/src/streams/LayeredStream.h
++++ b/src/streams/LayeredStream.h
+@@ -20,8 +20,6 @@
+
+ #include <QIODevice>
+
+-#include "core/Global.h"
+-
+ class LayeredStream : public QIODevice
+ {
+ Q_OBJECT
+@@ -30,12 +28,12 @@ public:
+ explicit LayeredStream(QIODevice* baseDevice);
+ virtual ~LayeredStream();
+
+- bool isSequential() const Q_DECL_OVERRIDE;
+- bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE;
++ bool isSequential() const override;
++ bool open(QIODevice::OpenMode mode) override;
+
+ protected:
+- qint64 readData(char* data, qint64 maxSize) Q_DECL_OVERRIDE;
+- qint64 writeData(const char* data, qint64 maxSize) Q_DECL_OVERRIDE;
++ qint64 readData(char* data, qint64 maxSize) override;
++ qint64 writeData(const char* data, qint64 maxSize) override;
+
+ QIODevice* const m_baseDevice;
+
+diff --git a/src/streams/StoreDataStream.h b/src/streams/StoreDataStream.h
+index 4143438..9f39d6a 100644
+--- a/src/streams/StoreDataStream.h
++++ b/src/streams/StoreDataStream.h
+@@ -26,11 +26,11 @@ class StoreDataStream : public LayeredStream
+
+ public:
+ explicit StoreDataStream(QIODevice* baseDevice);
+- bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE;
++ bool open(QIODevice::OpenMode mode) override;
+ QByteArray storedData() const;
+
+ protected:
+- qint64 readData(char* data, qint64 maxSize) Q_DECL_OVERRIDE;
++ qint64 readData(char* data, qint64 maxSize) override;
+
+ private:
+ QByteArray m_storedData;
+diff --git a/src/streams/SymmetricCipherStream.h b/src/streams/SymmetricCipherStream.h
+index fa44605..b6228e1 100644
+--- a/src/streams/SymmetricCipherStream.h
++++ b/src/streams/SymmetricCipherStream.h
+@@ -33,13 +33,13 @@ public:
+ SymmetricCipher::Mode mode, SymmetricCipher::Direction direction);
+ ~SymmetricCipherStream();
+ bool init(const QByteArray& key, const QByteArray& iv);
+- bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE;
+- bool reset() Q_DECL_OVERRIDE;
+- void close() Q_DECL_OVERRIDE;
++ bool open(QIODevice::OpenMode mode) override;
++ bool reset() override;
++ void close() override;
+
+ protected:
+- qint64 readData(char* data, qint64 maxSize) Q_DECL_OVERRIDE;
+- qint64 writeData(const char* data, qint64 maxSize) Q_DECL_OVERRIDE;
++ qint64 readData(char* data, qint64 maxSize) override;
++ qint64 writeData(const char* data, qint64 maxSize) override;
+
+ private:
+ void resetInternalState();
+diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
+index 2de7094..7ea399f 100644
+--- a/tests/CMakeLists.txt
++++ b/tests/CMakeLists.txt
+@@ -52,10 +52,9 @@ macro(parse_arguments prefix arg_names option_names)
+ endmacro(parse_arguments)
+
+ macro(add_unit_test)
+- parse_arguments(TEST "NAME;SOURCES;MOCS;LIBS" "" ${ARGN})
++ parse_arguments(TEST "NAME;SOURCES;LIBS" "" ${ARGN})
+ set(_test_NAME ${TEST_NAME})
+ set(_srcList ${TEST_SOURCES})
+- qt4_wrap_cpp(_srcList ${TEST_MOCS})
+ add_executable(${_test_NAME} ${_srcList})
+ target_link_libraries(${_test_NAME} ${TEST_LIBS})
+
+@@ -86,85 +85,80 @@ endmacro(add_unit_test)
+
+ set(TEST_LIBRARIES
+ keepassx_core
+- ${QT_QTCORE_LIBRARY}
+- ${QT_QTGUI_LIBRARY}
+- ${QT_QTTEST_LIBRARY}
++ Qt5::Core
++ Qt5::Concurrent
++ Qt5::Widgets
++ Qt5::Test
+ ${GCRYPT_LIBRARIES}
+ ${ZLIB_LIBRARIES}
+ )
+
+ set(testsupport_SOURCES modeltest.cpp FailDevice.cpp)
+-qt4_wrap_cpp(testsupport_SOURCES modeltest.h FailDevice.h)
+ add_library(testsupport STATIC ${testsupport_SOURCES})
++target_link_libraries(testsupport Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test)
+
+-add_unit_test(NAME testgroup SOURCES TestGroup.cpp MOCS TestGroup.h
++add_unit_test(NAME testgroup SOURCES TestGroup.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testkeepass2xmlreader SOURCES TestKeePass2XmlReader.cpp MOCS TestKeePass2XmlReader.h
++add_unit_test(NAME testkeepass2xmlreader SOURCES TestKeePass2XmlReader.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testkeys SOURCES TestKeys.cpp MOCS TestKeys.h
++add_unit_test(NAME testkeys SOURCES TestKeys.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testkeepass2reader SOURCES TestKeePass2Reader.cpp MOCS TestKeePass2Reader.h
++add_unit_test(NAME testkeepass2reader SOURCES TestKeePass2Reader.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testkeepass2writer SOURCES TestKeePass2Writer.cpp MOCS TestKeePass2Writer.h
++add_unit_test(NAME testkeepass2writer SOURCES TestKeePass2Writer.cpp
+ LIBS testsupport ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testgroupmodel SOURCES TestGroupModel.cpp MOCS TestGroupModel.h
++add_unit_test(NAME testgroupmodel SOURCES TestGroupModel.cpp
+ LIBS testsupport ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testentrymodel SOURCES TestEntryModel.cpp MOCS TestEntryModel.h
++add_unit_test(NAME testentrymodel SOURCES TestEntryModel.cpp
+ LIBS testsupport ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testcryptohash SOURCES TestCryptoHash.cpp MOCS TestCryptoHash.h
++add_unit_test(NAME testcryptohash SOURCES TestCryptoHash.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testsymmetriccipher SOURCES TestSymmetricCipher.cpp MOCS TestSymmetricCipher.h
++add_unit_test(NAME testsymmetriccipher SOURCES TestSymmetricCipher.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testhashedblockstream SOURCES TestHashedBlockStream.cpp MOCS TestHashedBlockStream.h
++add_unit_test(NAME testhashedblockstream SOURCES TestHashedBlockStream.cpp
+ LIBS testsupport ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testkeepass2randomstream SOURCES TestKeePass2RandomStream.cpp MOCS TestKeePass2RandomStream.h
++add_unit_test(NAME testkeepass2randomstream SOURCES TestKeePass2RandomStream.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testmodified SOURCES TestModified.cpp MOCS TestModified.h
++add_unit_test(NAME testmodified SOURCES TestModified.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testdeletedobjects SOURCES TestDeletedObjects.cpp MOCS TestDeletedObjects.h
++add_unit_test(NAME testdeletedobjects SOURCES TestDeletedObjects.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testkeepass1reader SOURCES TestKeePass1Reader.cpp MOCS TestKeePass1Reader.h
++add_unit_test(NAME testkeepass1reader SOURCES TestKeePass1Reader.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testqsavefile SOURCES TestQSaveFile.cpp MOCS TestQSaveFile.h
++add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp MOCS TestWildcardMatcher.h
+- LIBS ${TEST_LIBRARIES})
+-
+-add_unit_test(NAME testautotype SOURCES TestAutoType.cpp MOCS TestAutoType.h
++add_unit_test(NAME testautotype SOURCES TestAutoType.cpp
+ LIBS ${TEST_LIBRARIES})
+ set_target_properties(testautotype PROPERTIES ENABLE_EXPORTS ON)
+
+-add_unit_test(NAME testentry SOURCES TestEntry.cpp MOCS TestEntry.h
+- LIBS ${TEST_LIBRARIES})
+-
+-add_unit_test(NAME testqcommandlineparser SOURCES TestQCommandLineParser.cpp MOCS TestQCommandLineParser.h
++add_unit_test(NAME testentry SOURCES TestEntry.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testrandom SOURCES TestRandom.cpp MOCS TestRandom.h
++add_unit_test(NAME testrandom SOURCES TestRandom.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testentrysearcher SOURCES TestEntrySearcher.cpp MOCS TestEntrySearcher.h
++add_unit_test(NAME testentrysearcher SOURCES TestEntrySearcher.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testexporter SOURCES TestExporter.cpp MOCS TestExporter.h
++add_unit_test(NAME testexporter SOURCES TestExporter.cpp
+ LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testcsvexporter SOURCES TestCsvExporter.cpp MOCS TestCsvExporter.h
++add_unit_test(NAME testcsvexporter SOURCES TestCsvExporter.cpp
+ LIBS ${TEST_LIBRARIES})
+
+ if(WITH_GUI_TESTS)
+diff --git a/tests/FailDevice.h b/tests/FailDevice.h
+index f812593..194d617 100644
+--- a/tests/FailDevice.h
++++ b/tests/FailDevice.h
+@@ -20,19 +20,17 @@
+
+ #include <QBuffer>
+
+-#include "core/Global.h"
+-
+ class FailDevice : public QBuffer
+ {
+ Q_OBJECT
+
+ public:
+- explicit FailDevice(int failAfter, QObject* parent = Q_NULLPTR);
+- bool open(QIODevice::OpenMode openMode) Q_DECL_OVERRIDE;
++ explicit FailDevice(int failAfter, QObject* parent = nullptr);
++ bool open(QIODevice::OpenMode openMode) override;
+
+ protected:
+- qint64 readData(char* data, qint64 len) Q_DECL_OVERRIDE;
+- qint64 writeData(const char* data, qint64 len) Q_DECL_OVERRIDE;
++ qint64 readData(char* data, qint64 len) override;
++ qint64 writeData(const char* data, qint64 len) override;
+
+ private:
+ int m_failAfter;
+diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp
+index 8968348..cbd927f 100644
+--- a/tests/TestAutoType.cpp
++++ b/tests/TestAutoType.cpp
+@@ -20,7 +20,6 @@
+ #include <QPluginLoader>
+ #include <QTest>
+
+-#include "tests.h"
+ #include "core/Config.h"
+ #include "core/FilePath.h"
+ #include "core/Entry.h"
+@@ -108,7 +107,7 @@ void TestAutoType::testInternal()
+
+ void TestAutoType::testAutoTypeWithoutSequence()
+ {
+- m_autoType->performAutoType(m_entry1, Q_NULLPTR);
++ m_autoType->performAutoType(m_entry1, nullptr);
+
+ QCOMPARE(m_test->actionCount(), 14);
+ QCOMPARE(m_test->actionChars(),
+@@ -119,7 +118,7 @@ void TestAutoType::testAutoTypeWithoutSequence()
+
+ void TestAutoType::testAutoTypeWithSequence()
+ {
+- m_autoType->performAutoType(m_entry1, Q_NULLPTR, "{Username}abc{PaSsWoRd}");
++ m_autoType->performAutoType(m_entry1, nullptr, "{Username}abc{PaSsWoRd}");
+
+ QCOMPARE(m_test->actionCount(), 15);
+ QCOMPARE(m_test->actionChars(),
+diff --git a/tests/TestCryptoHash.cpp b/tests/TestCryptoHash.cpp
+index 4002aea..c166f55 100644
+--- a/tests/TestCryptoHash.cpp
++++ b/tests/TestCryptoHash.cpp
+@@ -19,7 +19,6 @@
+
+ #include <QTest>
+
+-#include "tests.h"
+ #include "crypto/Crypto.h"
+ #include "crypto/CryptoHash.h"
+
+diff --git a/tests/TestCsvExporter.cpp b/tests/TestCsvExporter.cpp
+index 5965e60..1fa6634 100644
+--- a/tests/TestCsvExporter.cpp
++++ b/tests/TestCsvExporter.cpp
+@@ -21,8 +21,6 @@
+ #include <QBuffer>
+ #include <QTest>
+
+-#include "tests.h"
+-
+ #include "core/Database.h"
+ #include "core/Entry.h"
+ #include "core/Group.h"
+@@ -53,7 +51,7 @@ void TestCsvExporter::cleanUp()
+ void TestCsvExporter::testExport()
+ {
+ Group* groupRoot = m_db->rootGroup();
+- Group* group= new Group();
++ Group* group = new Group();
+ group->setName("Test Group Name");
+ group->setParent(groupRoot);
+ Entry* entry = new Entry();
+@@ -85,10 +83,10 @@ void TestCsvExporter::testEmptyDatabase()
+ void TestCsvExporter::testNestedGroups()
+ {
+ Group* groupRoot = m_db->rootGroup();
+- Group* group= new Group();
++ Group* group = new Group();
+ group->setName("Test Group Name");
+ group->setParent(groupRoot);
+- Group* childGroup= new Group();
++ Group* childGroup = new Group();
+ childGroup->setName("Test Sub Group Name");
+ childGroup->setParent(group);
+ Entry* entry = new Entry();
+diff --git a/tests/TestCsvExporter.h b/tests/TestCsvExporter.h
+index a71c936..c8cc4dc 100644
+--- a/tests/TestCsvExporter.h
++++ b/tests/TestCsvExporter.h
+@@ -42,7 +42,6 @@ private Q_SLOTS:
+ private:
+ Database* m_db;
+ CsvExporter* m_csvExporter;
+-
+ };
+
+ #endif // KEEPASSX_TESTCSVEXPORTER_H
+diff --git a/tests/TestDeletedObjects.cpp b/tests/TestDeletedObjects.cpp
+index cf9e3d1..5af0178 100644
+--- a/tests/TestDeletedObjects.cpp
++++ b/tests/TestDeletedObjects.cpp
+@@ -19,7 +19,6 @@
+
+ #include <QTest>
+
+-#include "tests.h"
+ #include "core/Database.h"
+ #include "core/Group.h"
+ #include "crypto/Crypto.h"
+diff --git a/tests/TestEntry.cpp b/tests/TestEntry.cpp
+index f918b6c..1eaca32 100644
+--- a/tests/TestEntry.cpp
++++ b/tests/TestEntry.cpp
+@@ -19,7 +19,6 @@
+
+ #include <QTest>
+
+-#include "tests.h"
+ #include "core/Entry.h"
+ #include "crypto/Crypto.h"
+
+diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp
+index b323a73..3f956d7 100644
+--- a/tests/TestEntryModel.cpp
++++ b/tests/TestEntryModel.cpp
+@@ -21,7 +21,6 @@
+ #include <QTest>
+
+ #include "modeltest.h"
+-#include "tests.h"
+ #include "core/DatabaseIcons.h"
+ #include "core/Entry.h"
+ #include "core/Group.h"
+diff --git a/tests/TestEntrySearcher.cpp b/tests/TestEntrySearcher.cpp
+index 9f7ca13..6b951c7 100644
+--- a/tests/TestEntrySearcher.cpp
++++ b/tests/TestEntrySearcher.cpp
+@@ -19,8 +19,6 @@
+
+ #include <QTest>
+
+-#include "tests.h"
+-
+ QTEST_GUILESS_MAIN(TestEntrySearcher)
+
+ void TestEntrySearcher::initTestCase()
+diff --git a/tests/TestExporter.cpp b/tests/TestExporter.cpp
+index 76a6f75..656b76c 100644
+--- a/tests/TestExporter.cpp
++++ b/tests/TestExporter.cpp
+@@ -20,7 +20,6 @@
+
+ #include <QTest>
+
+-#include "tests.h"
+ #include "core/ToDbExporter.h"
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+@@ -77,6 +76,3 @@ void TestExporter::testToDbExporter()
+ delete dbOrg;
+ delete dbExp;
+ }
+-
+-
+-
+diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp
+index 507cf15..13ce82e 100644
+--- a/tests/TestGroup.cpp
++++ b/tests/TestGroup.cpp
+@@ -21,7 +21,6 @@
+ #include <QSignalSpy>
+ #include <QTest>
+
+-#include "tests.h"
+ #include "core/Database.h"
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+diff --git a/tests/TestGroupModel.cpp b/tests/TestGroupModel.cpp
+index 32a4b8e..3608cc4 100644
+--- a/tests/TestGroupModel.cpp
++++ b/tests/TestGroupModel.cpp
+@@ -21,7 +21,6 @@
+ #include <QTest>
+
+ #include "modeltest.h"
+-#include "tests.h"
+ #include "core/Database.h"
+ #include "core/Group.h"
+ #include "crypto/Crypto.h"
+diff --git a/tests/TestHashedBlockStream.cpp b/tests/TestHashedBlockStream.cpp
+index d5a0cea..b78a46b 100644
+--- a/tests/TestHashedBlockStream.cpp
++++ b/tests/TestHashedBlockStream.cpp
+@@ -20,7 +20,6 @@
+ #include <QBuffer>
+ #include <QTest>
+
+-#include "tests.h"
+ #include "FailDevice.h"
+ #include "crypto/Crypto.h"
+ #include "streams/HashedBlockStream.h"
+diff --git a/tests/TestKeePass1Reader.cpp b/tests/TestKeePass1Reader.cpp
+index d9dff9e..f60846d 100644
+--- a/tests/TestKeePass1Reader.cpp
++++ b/tests/TestKeePass1Reader.cpp
+@@ -21,7 +21,6 @@
+ #include <QTest>
+
+ #include "config-keepassx-tests.h"
+-#include "tests.h"
+ #include "core/Database.h"
+ #include "core/Entry.h"
+ #include "core/Group.h"
+diff --git a/tests/TestKeePass2RandomStream.cpp b/tests/TestKeePass2RandomStream.cpp
+index cb88133..03dfbe5 100644
+--- a/tests/TestKeePass2RandomStream.cpp
++++ b/tests/TestKeePass2RandomStream.cpp
+@@ -19,7 +19,6 @@
+
+ #include <QTest>
+
+-#include "tests.h"
+ #include "crypto/Crypto.h"
+ #include "crypto/CryptoHash.h"
+ #include "crypto/SymmetricCipher.h"
+diff --git a/tests/TestKeePass2Reader.cpp b/tests/TestKeePass2Reader.cpp
+index d6cb70c..22973ee 100644
+--- a/tests/TestKeePass2Reader.cpp
++++ b/tests/TestKeePass2Reader.cpp
+@@ -20,7 +20,6 @@
+ #include <QTest>
+
+ #include "config-keepassx-tests.h"
+-#include "tests.h"
+ #include "core/Database.h"
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+diff --git a/tests/TestKeePass2Writer.cpp b/tests/TestKeePass2Writer.cpp
+index c872794..60b7b90 100644
+--- a/tests/TestKeePass2Writer.cpp
++++ b/tests/TestKeePass2Writer.cpp
+@@ -21,7 +21,6 @@
+ #include <QTest>
+
+ #include "config-keepassx-tests.h"
+-#include "tests.h"
+ #include "FailDevice.h"
+ #include "core/Database.h"
+ #include "core/Group.h"
+diff --git a/tests/TestKeePass2XmlReader.cpp b/tests/TestKeePass2XmlReader.cpp
+index dd81327..f04c548 100644
+--- a/tests/TestKeePass2XmlReader.cpp
++++ b/tests/TestKeePass2XmlReader.cpp
+@@ -21,7 +21,6 @@
+ #include <QFile>
+ #include <QTest>
+
+-#include "tests.h"
+ #include "core/Database.h"
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+@@ -112,12 +111,12 @@ void TestKeePass2XmlReader::testMetadata()
+ QCOMPARE(m_db->metadata()->protectUrl(), true);
+ QCOMPARE(m_db->metadata()->protectNotes(), false);
+ QCOMPARE(m_db->metadata()->recycleBinEnabled(), true);
+- QVERIFY(m_db->metadata()->recycleBin() != Q_NULLPTR);
++ QVERIFY(m_db->metadata()->recycleBin() != nullptr);
+ QCOMPARE(m_db->metadata()->recycleBin()->name(), QString("Recycle Bin"));
+ QCOMPARE(m_db->metadata()->recycleBinChanged(), genDT(2010, 8, 25, 16, 12, 57));
+- QVERIFY(m_db->metadata()->entryTemplatesGroup() == Q_NULLPTR);
++ QVERIFY(m_db->metadata()->entryTemplatesGroup() == nullptr);
+ QCOMPARE(m_db->metadata()->entryTemplatesGroupChanged(), genDT(2010, 8, 8, 17, 24, 19));
+- QVERIFY(m_db->metadata()->lastSelectedGroup() != Q_NULLPTR);
++ QVERIFY(m_db->metadata()->lastSelectedGroup() != nullptr);
+ QCOMPARE(m_db->metadata()->lastSelectedGroup()->name(), QString("NewDatabase"));
+ QVERIFY(m_db->metadata()->lastTopVisibleGroup() == m_db->metadata()->lastSelectedGroup());
+ QCOMPARE(m_db->metadata()->historyMaxItems(), -1);
+diff --git a/tests/TestKeys.cpp b/tests/TestKeys.cpp
+index b661775..6c1953f 100644
+--- a/tests/TestKeys.cpp
++++ b/tests/TestKeys.cpp
+@@ -21,7 +21,6 @@
+ #include <QTest>
+
+ #include "config-keepassx-tests.h"
+-#include "tests.h"
+ #include "core/Database.h"
+ #include "core/Metadata.h"
+ #include "crypto/Crypto.h"
+@@ -177,7 +176,7 @@ void TestKeys::benchmarkTransformKey()
+ QByteArray env = qgetenv("BENCHMARK");
+
+ if (env.isEmpty() || env == "0" || env == "no") {
+- QSKIP("Benchmark skipped. Set env variable BENCHMARK=1 to enable.", SkipAll);
++ QSKIP("Benchmark skipped. Set env variable BENCHMARK=1 to enable.");
+ }
+
+ PasswordKey pwKey;
+diff --git a/tests/TestModified.cpp b/tests/TestModified.cpp
+index e275e83..70a4a48 100644
+--- a/tests/TestModified.cpp
++++ b/tests/TestModified.cpp
+@@ -20,7 +20,6 @@
+ #include <QSignalSpy>
+ #include <QTest>
+
+-#include "tests.h"
+ #include "core/Database.h"
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+@@ -237,7 +236,7 @@ void TestModified::testEntrySets()
+ entry->setExpires(entry->timeInfo().expires());
+ QCOMPARE(spyModified.count(), spyCount);
+
+- entry->setExpiryTime(Tools::currentDateTimeUtc().addYears(1));
++ entry->setExpiryTime(QDateTime::currentDateTimeUtc().addYears(1));
+ QCOMPARE(spyModified.count(), ++spyCount);
+ entry->setExpiryTime(entry->timeInfo().expiryTime());
+ QCOMPARE(spyModified.count(), spyCount);
+diff --git a/tests/TestQCommandLineParser.cpp b/tests/TestQCommandLineParser.cpp
+deleted file mode 100644
+index 4e2c635..0000000
+--- a/tests/TestQCommandLineParser.cpp
++++ /dev/null
+@@ -1,416 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 David Faure <faure@kde.org>
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the test suite of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.LGPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU Lesser General Public License version 2.1 requirements
+-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU
+-** General Public License version 3.0 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.GPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU General Public License version 3.0 requirements will be
+-** met: http://www.gnu.org/copyleft/gpl.html.
+-**
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#include "TestQCommandLineParser.h"
+-
+-#include <QtTest>
+-
+-#include "tests.h"
+-#include "core/qcommandlineparser.h"
+-
+-QTEST_GUILESS_MAIN(TestQCommandLineParser)
+-
+-Q_DECLARE_METATYPE(char**)
+-
+-static char *empty_argv[] = { 0 };
+-static int empty_argc = 1;
+-
+-void TestQCommandLineParser::initTestCase()
+-{
+- Q_ASSERT(!empty_argv[0]);
+- empty_argv[0] = const_cast<char*>("TestQCommandLineParser");
+-}
+-
+-Q_DECLARE_METATYPE(QCommandLineParser::SingleDashWordOptionMode)
+-
+-void TestQCommandLineParser::parsingModes_data()
+-{
+- QTest::addColumn<QCommandLineParser::SingleDashWordOptionMode>("parsingMode");
+-
+- QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions;
+- QTest::newRow("implicitlylong") << QCommandLineParser::ParseAsLongOptions;
+-}
+-
+-void TestQCommandLineParser::testInvalidOptions()
+-{
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- QTest::ignoreMessage(QtWarningMsg, "QCommandLineOption: Option names cannot start with a '-'");
+- parser.addOption(QCommandLineOption("-v", "Displays version information."));
+-}
+-
+-void TestQCommandLineParser::testPositionalArguments()
+-{
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "file.txt"));
+- QCOMPARE(parser.positionalArguments(), QStringList() << "file.txt");
+-}
+-
+-void TestQCommandLineParser::testBooleanOption_data()
+-{
+- QTest::addColumn<QStringList>("args");
+- QTest::addColumn<QStringList>("expectedOptionNames");
+- QTest::addColumn<bool>("expectedIsSet");
+-
+- QTest::newRow("set") << (QStringList() << "TestQCommandLineParser" << "-b") << (QStringList() << "b") << true;
+- QTest::newRow("unset") << (QStringList() << "TestQCommandLineParser") << QStringList() << false;
+-}
+-
+-void TestQCommandLineParser::testBooleanOption()
+-{
+- QFETCH(QStringList, args);
+- QFETCH(QStringList, expectedOptionNames);
+- QFETCH(bool, expectedIsSet);
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- QVERIFY(parser.addOption(QCommandLineOption("b", "a boolean option")));
+- QVERIFY(parser.parse(args));
+- QCOMPARE(parser.optionNames(), expectedOptionNames);
+- QCOMPARE(parser.isSet("b"), expectedIsSet);
+- QCOMPARE(parser.values("b"), QStringList());
+- QCOMPARE(parser.positionalArguments(), QStringList());
+- // Should warn on typos
+- QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: option not defined: \"c\"");
+- QVERIFY(!parser.isSet("c"));
+-}
+-
+-void TestQCommandLineParser::testMultipleNames_data()
+-{
+- QTest::addColumn<QStringList>("args");
+- QTest::addColumn<QStringList>("expectedOptionNames");
+-
+- QTest::newRow("short") << (QStringList() << "TestQCommandLineParser" << "-v") << (QStringList() << "v");
+- QTest::newRow("long") << (QStringList() << "TestQCommandLineParser" << "--version") << (QStringList() << "version");
+- QTest::newRow("not_set") << (QStringList() << "TestQCommandLineParser") << QStringList();
+-}
+-
+-void TestQCommandLineParser::testMultipleNames()
+-{
+- QFETCH(QStringList, args);
+- QFETCH(QStringList, expectedOptionNames);
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineOption option(QStringList() << "v" << "version", "Show version information");
+- QCOMPARE(option.names(), QStringList() << "v" << "version");
+- QCommandLineParser parser;
+- QVERIFY(parser.addOption(option));
+- QVERIFY(parser.parse(args));
+- QCOMPARE(parser.optionNames(), expectedOptionNames);
+- const bool expectedIsSet = !expectedOptionNames.isEmpty();
+- QCOMPARE(parser.isSet("v"), expectedIsSet);
+- QCOMPARE(parser.isSet("version"), expectedIsSet);
+-}
+-
+-void TestQCommandLineParser::testSingleValueOption_data()
+-{
+- QTest::addColumn<QStringList>("args");
+- QTest::addColumn<QStringList>("defaults");
+- QTest::addColumn<bool>("expectedIsSet");
+-
+- QTest::newRow("short") << (QStringList() << "tst" << "-s" << "oxygen") << QStringList() << true;
+- QTest::newRow("long") << (QStringList() << "tst" << "--style" << "oxygen") << QStringList() << true;
+- QTest::newRow("longequal") << (QStringList() << "tst" << "--style=oxygen") << QStringList() << true;
+- QTest::newRow("default") << (QStringList() << "tst") << (QStringList() << "oxygen") << false;
+-}
+-
+-void TestQCommandLineParser::testSingleValueOption()
+-{
+- QFETCH(QStringList, args);
+- QFETCH(QStringList, defaults);
+- QFETCH(bool, expectedIsSet);
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- QCommandLineOption option(QStringList() << "s" << "style", "style name", "styleName");
+- option.setDefaultValues(defaults);
+- QVERIFY(parser.addOption(option));
+- for (int mode = 0; mode < 2; ++mode) {
+- parser.setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode(mode));
+- QVERIFY(parser.parse(args));
+- QCOMPARE(parser.isSet("s"), expectedIsSet);
+- QCOMPARE(parser.isSet("style"), expectedIsSet);
+- QCOMPARE(parser.isSet(option), expectedIsSet);
+- QCOMPARE(parser.value("s"), QString("oxygen"));
+- QCOMPARE(parser.value("style"), QString("oxygen"));
+- QCOMPARE(parser.values("s"), QStringList() << "oxygen");
+- QCOMPARE(parser.values("style"), QStringList() << "oxygen");
+- QCOMPARE(parser.values(option), QStringList() << "oxygen");
+- QCOMPARE(parser.positionalArguments(), QStringList());
+- }
+- // Should warn on typos
+- QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: option not defined: \"c\"");
+- QVERIFY(parser.values("c").isEmpty());
+-}
+-
+-void TestQCommandLineParser::testValueNotSet()
+-{
+- QCoreApplication app(empty_argc, empty_argv);
+- // Not set, no default value
+- QCommandLineParser parser;
+- QCommandLineOption option(QStringList() << "s" << "style", "style name");
+- option.setValueName("styleName");
+- QVERIFY(parser.addOption(option));
+- QVERIFY(parser.parse(QStringList() << "tst"));
+- QCOMPARE(parser.optionNames(), QStringList());
+- QVERIFY(!parser.isSet("s"));
+- QVERIFY(!parser.isSet("style"));
+- QCOMPARE(parser.value("s"), QString());
+- QCOMPARE(parser.value("style"), QString());
+- QCOMPARE(parser.values("s"), QStringList());
+- QCOMPARE(parser.values("style"), QStringList());
+-}
+-
+-void TestQCommandLineParser::testMultipleValuesOption()
+-{
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineOption option("param", "Pass parameter to the backend.");
+- option.setValueName("key=value");
+- QCommandLineParser parser;
+- QVERIFY(parser.addOption(option));
+- {
+- QVERIFY(parser.parse(QStringList() << "tst" << "--param" << "key1=value1"));
+- QVERIFY(parser.isSet("param"));
+- QCOMPARE(parser.values("param"), QStringList() << "key1=value1");
+- QCOMPARE(parser.value("param"), QString("key1=value1"));
+- }
+- {
+- QVERIFY(parser.parse(QStringList() << "tst" << "--param" << "key1=value1" << "--param" << "key2=value2"));
+- QVERIFY(parser.isSet("param"));
+- QCOMPARE(parser.values("param"), QStringList() << "key1=value1" << "key2=value2");
+- QCOMPARE(parser.value("param"), QString("key2=value2"));
+- }
+-
+- QString expected =
+- "Usage: TestQCommandLineParser [options]\n"
+- "\n"
+- "Options:\n"
+- " --param <key=value> Pass parameter to the backend.\n";
+-
+- const QString exeName = QCoreApplication::instance()->arguments().first(); // e.g. debug\tst_qcommandlineparser.exe on Windows
+- expected.replace("TestQCommandLineParser", exeName);
+- QCOMPARE(parser.helpText(), expected);
+-}
+-
+-void TestQCommandLineParser::testUnknownOptionErrorHandling_data()
+-{
+- QTest::addColumn<QCommandLineParser::SingleDashWordOptionMode>("parsingMode");
+- QTest::addColumn<QStringList>("args");
+- QTest::addColumn<QStringList>("expectedUnknownOptionNames");
+- QTest::addColumn<QString>("expectedErrorText");
+-
+- const QStringList args_hello = QStringList() << "TestQCommandLineParser" << "--hello";
+- const QString error_hello("Unknown option 'hello'.");
+- QTest::newRow("unknown_name_collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << args_hello << QStringList("hello") << error_hello;
+- QTest::newRow("unknown_name_long") << QCommandLineParser::ParseAsLongOptions << args_hello << QStringList("hello") << error_hello;
+-
+- const QStringList args_value = QStringList() << "TestQCommandLineParser" << "-b=1";
+- QTest::newRow("bool_with_value_collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << args_value << QStringList() << QString("Unexpected value after '-b'.");
+- QTest::newRow("bool_with_value_long") << QCommandLineParser::ParseAsLongOptions << args_value << QStringList() << QString("Unexpected value after '-b'.");
+-
+- const QStringList args_dash_long = QStringList() << "TestQCommandLineParser" << "-bool";
+- const QString error_bool("Unknown options: o, o, l.");
+- QTest::newRow("unknown_name_long_collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << args_dash_long << (QStringList() << "o" << "o" << "l") << error_bool;
+-}
+-
+-void TestQCommandLineParser::testUnknownOptionErrorHandling()
+-{
+- QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode);
+- QFETCH(QStringList, args);
+- QFETCH(QStringList, expectedUnknownOptionNames);
+- QFETCH(QString, expectedErrorText);
+-
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- parser.setSingleDashWordOptionMode(parsingMode);
+- QVERIFY(parser.addOption(QCommandLineOption(QStringList() << "b" << "bool", "a boolean option")));
+- QCOMPARE(parser.parse(args), expectedErrorText.isEmpty());
+- QCOMPARE(parser.unknownOptionNames(), expectedUnknownOptionNames);
+- QCOMPARE(parser.errorText(), expectedErrorText);
+-}
+-
+-void TestQCommandLineParser::testDoubleDash_data()
+-{
+- parsingModes_data();
+-}
+-
+-void TestQCommandLineParser::testDoubleDash()
+-{
+- QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode);
+-
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- parser.addOption(QCommandLineOption(QStringList() << "o" << "output", "Output file", "filename"));
+- parser.setSingleDashWordOptionMode(parsingMode);
+- QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "--output" << "foo"));
+- QCOMPARE(parser.value("output"), QString("foo"));
+- QCOMPARE(parser.positionalArguments(), QStringList());
+- QCOMPARE(parser.unknownOptionNames(), QStringList());
+- QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "--" << "--output" << "bar" << "-b" << "bleh"));
+- QCOMPARE(parser.value("output"), QString());
+- QCOMPARE(parser.positionalArguments(), QStringList() << "--output" << "bar" << "-b" << "bleh");
+- QCOMPARE(parser.unknownOptionNames(), QStringList());
+-}
+-
+-void TestQCommandLineParser::testDefaultValue()
+-{
+- QCommandLineOption opt("name", "desc",
+- "valueName", "default");
+- QCOMPARE(opt.defaultValues(), QStringList("default"));
+- opt.setDefaultValue("");
+- QCOMPARE(opt.defaultValues(), QStringList());
+- opt.setDefaultValue("default");
+- QCOMPARE(opt.defaultValues(), QStringList("default"));
+-}
+-
+-void TestQCommandLineParser::testProcessNotCalled()
+-{
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- QVERIFY(parser.addOption(QCommandLineOption("b", "a boolean option")));
+- QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: call process() or parse() before isSet");
+- QVERIFY(!parser.isSet("b"));
+- QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: call process() or parse() before values");
+- QCOMPARE(parser.values("b"), QStringList());
+-}
+-
+-void TestQCommandLineParser::testEmptyArgsList()
+-{
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: argument list cannot be empty, it should contain at least the executable name");
+- QVERIFY(!parser.parse(QStringList())); // invalid call, argv[0] is missing
+-}
+-
+-void TestQCommandLineParser::testMissingOptionValue()
+-{
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- parser.addOption(QCommandLineOption("option", "An option", "value"));
+- QVERIFY(!parser.parse(QStringList() << "argv0" << "--option")); // the user forgot to pass a value for --option
+- QCOMPARE(parser.value("option"), QString());
+- QCOMPARE(parser.errorText(), QString("Missing value after '--option'."));
+-}
+-
+-void TestQCommandLineParser::testStdinArgument_data()
+-{
+- parsingModes_data();
+-}
+-
+-void TestQCommandLineParser::testStdinArgument()
+-{
+- QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode);
+-
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- parser.setSingleDashWordOptionMode(parsingMode);
+- parser.addOption(QCommandLineOption(QStringList() << "i" << "input", "Input file.", "filename"));
+- parser.addOption(QCommandLineOption("b", "Boolean option."));
+- QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "--input" << "-"));
+- QCOMPARE(parser.value("input"), QString("-"));
+- QCOMPARE(parser.positionalArguments(), QStringList());
+- QCOMPARE(parser.unknownOptionNames(), QStringList());
+-
+- QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "--input" << "-" << "-b" << "arg"));
+- QCOMPARE(parser.value("input"), QString("-"));
+- QVERIFY(parser.isSet("b"));
+- QCOMPARE(parser.positionalArguments(), QStringList() << "arg");
+- QCOMPARE(parser.unknownOptionNames(), QStringList());
+-
+- QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "-"));
+- QCOMPARE(parser.value("input"), QString());
+- QVERIFY(!parser.isSet("b"));
+- QCOMPARE(parser.positionalArguments(), QStringList() << "-");
+- QCOMPARE(parser.unknownOptionNames(), QStringList());
+-}
+-
+-void TestQCommandLineParser::testSingleDashWordOptionModes_data()
+-{
+- QTest::addColumn<QCommandLineParser::SingleDashWordOptionMode>("parsingMode");
+- QTest::addColumn<QStringList>("commandLine");
+- QTest::addColumn<QStringList>("expectedOptionNames");
+- QTest::addColumn<QStringList>("expectedOptionValues");
+-
+- QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-abc" << "val")
+- << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val");
+- QTest::newRow("collapsed_with_equalsign_value") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-abc=val")
+- << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val");
+- QTest::newRow("collapsed_explicit_longoption") << QCommandLineParser::ParseAsCompactedShortOptions << QStringList("--nn")
+- << QStringList("nn") << QStringList();
+- QTest::newRow("collapsed_longoption_value") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "--abc" << "val")
+- << QStringList("abc") << QStringList("val");
+- QTest::newRow("compiler") << QCommandLineParser::ParseAsCompactedShortOptions << QStringList("-cab")
+- << QStringList("c") << QStringList("ab");
+- QTest::newRow("compiler_with_space") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-c" << "val")
+- << QStringList("c") << QStringList("val");
+-
+- QTest::newRow("implicitlylong") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-abc" << "val")
+- << QStringList("abc") << QStringList("val");
+- QTest::newRow("implicitlylong_equal") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-abc=val")
+- << QStringList("abc") << QStringList("val");
+- QTest::newRow("implicitlylong_longoption") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "--nn")
+- << QStringList("nn") << QStringList();
+- QTest::newRow("implicitlylong_longoption_value") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "--abc" << "val")
+- << QStringList("abc") << QStringList("val");
+- QTest::newRow("implicitlylong_with_space") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-c" << "val")
+- << QStringList("c") << QStringList("val");
+-}
+-
+-void TestQCommandLineParser::testSingleDashWordOptionModes()
+-{
+- QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode);
+- QFETCH(QStringList, commandLine);
+- QFETCH(QStringList, expectedOptionNames);
+- QFETCH(QStringList, expectedOptionValues);
+-
+- commandLine.prepend("TestQCommandLineParser");
+-
+- QCoreApplication app(empty_argc, empty_argv);
+- QCommandLineParser parser;
+- parser.setSingleDashWordOptionMode(parsingMode);
+- parser.addOption(QCommandLineOption("a", "a option."));
+- parser.addOption(QCommandLineOption("b", "b option."));
+- parser.addOption(QCommandLineOption(QStringList() << "c" << "abc", "c option.", "value"));
+- parser.addOption(QCommandLineOption("nn", "nn option."));
+- QVERIFY(parser.parse(commandLine));
+- QCOMPARE(parser.optionNames(), expectedOptionNames);
+- for (int i = 0; i < expectedOptionValues.count(); ++i)
+- QCOMPARE(parser.value(parser.optionNames().at(i)), expectedOptionValues.at(i));
+- QCOMPARE(parser.unknownOptionNames(), QStringList());
+-}
+diff --git a/tests/TestQCommandLineParser.h b/tests/TestQCommandLineParser.h
+deleted file mode 100644
+index 46214cd..0000000
+--- a/tests/TestQCommandLineParser.h
++++ /dev/null
+@@ -1,82 +0,0 @@
+-/****************************************************************************
+-**
+-** Copyright (C) 2013 David Faure <faure@kde.org>
+-** Contact: http://www.qt-project.org/legal
+-**
+-** This file is part of the test suite of the Qt Toolkit.
+-**
+-** $QT_BEGIN_LICENSE:LGPL$
+-** Commercial License Usage
+-** Licensees holding valid commercial Qt licenses may use this file in
+-** accordance with the commercial license agreement provided with the
+-** Software or, alternatively, in accordance with the terms contained in
+-** a written agreement between you and Digia. For licensing terms and
+-** conditions see http://qt.digia.com/licensing. For further information
+-** use the contact form at http://qt.digia.com/contact-us.
+-**
+-** GNU Lesser General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU Lesser
+-** General Public License version 2.1 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.LGPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU Lesser General Public License version 2.1 requirements
+-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+-**
+-** In addition, as a special exception, Digia gives you certain additional
+-** rights. These rights are described in the Digia Qt LGPL Exception
+-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+-**
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU
+-** General Public License version 3.0 as published by the Free Software
+-** Foundation and appearing in the file LICENSE.GPL included in the
+-** packaging of this file. Please review the following information to
+-** ensure the GNU General Public License version 3.0 requirements will be
+-** met: http://www.gnu.org/copyleft/gpl.html.
+-**
+-**
+-** $QT_END_LICENSE$
+-**
+-****************************************************************************/
+-
+-#ifndef KEEPASSX_TESTQCOMMANDLINEPARSER_H
+-#define KEEPASSX_TESTQCOMMANDLINEPARSER_H
+-
+-#include <QObject>
+-
+-class TestQCommandLineParser : public QObject
+-{
+- Q_OBJECT
+-
+-public Q_SLOTS:
+- void initTestCase();
+-
+-private Q_SLOTS:
+- void parsingModes_data();
+-
+- // In-process tests
+- void testInvalidOptions();
+- void testPositionalArguments();
+- void testBooleanOption_data();
+- void testBooleanOption();
+- void testMultipleNames_data();
+- void testMultipleNames();
+- void testSingleValueOption_data();
+- void testSingleValueOption();
+- void testValueNotSet();
+- void testMultipleValuesOption();
+- void testUnknownOptionErrorHandling_data();
+- void testUnknownOptionErrorHandling();
+- void testDoubleDash_data();
+- void testDoubleDash();
+- void testDefaultValue();
+- void testProcessNotCalled();
+- void testEmptyArgsList();
+- void testMissingOptionValue();
+- void testStdinArgument_data();
+- void testStdinArgument();
+- void testSingleDashWordOptionModes_data();
+- void testSingleDashWordOptionModes();
+-};
+-
+-#endif // KEEPASSX_TESTQCOMMANDLINEPARSER_H
+diff --git a/tests/TestQSaveFile.cpp b/tests/TestQSaveFile.cpp
+deleted file mode 100644
+index 443db52..0000000
+--- a/tests/TestQSaveFile.cpp
++++ /dev/null
+@@ -1,204 +0,0 @@
+-/*
+- * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
+- * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+- *
+- * 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 "TestQSaveFile.h"
+-
+-#include <QtTest>
+-
+-#include <unistd.h>
+-
+-#if defined(Q_OS_WIN)
+-# include <windows.h>
+-#endif
+-
+-#include "tests.h"
+-#include "core/qsavefile.h"
+-
+-QTEST_GUILESS_MAIN(TestQSaveFile)
+-
+-class DirCleanup
+-{
+-public:
+- DirCleanup(const QString& dir, const QString& filePrefix) : m_dir(dir), m_filePrefix(filePrefix) {}
+- ~DirCleanup() {
+- QDir dir(m_dir);
+- QStringList files = dir.entryList(QStringList() << (m_filePrefix + "*"), QDir::Files);
+- Q_FOREACH (const QString& file, files) {
+- QFile::remove(m_dir + "/" + file);
+- }
+-
+- QDir().rmdir(m_dir);
+- }
+-
+-private:
+- QString m_dir;
+- QString m_filePrefix;
+-};
+-
+-void TestQSaveFile::transactionalWrite()
+-{
+- const QString dir = tmpDir();
+- QVERIFY(!dir.isEmpty());
+- const QString targetFile = dir + QString::fromLatin1("/outfile");
+- DirCleanup dirCleanup(dir, "outfile");
+- QFile::remove(targetFile);
+- QSaveFile file(targetFile);
+- QVERIFY(file.open(QIODevice::WriteOnly));
+- QVERIFY(file.isOpen());
+- QCOMPARE(file.fileName(), targetFile);
+- QVERIFY(!QFile::exists(targetFile));
+-
+- QTextStream ts(&file);
+- ts << "This is test data one.\n";
+- ts.flush();
+- QCOMPARE(file.error(), QFile::NoError);
+- QVERIFY(!QFile::exists(targetFile));
+-
+- QVERIFY(file.commit());
+- QVERIFY(QFile::exists(targetFile));
+- QCOMPARE(file.fileName(), targetFile);
+-
+- // Check that we can reuse a QSaveFile object
+- // (and test the case of an existing target file)
+- QVERIFY(file.open(QIODevice::WriteOnly));
+- QCOMPARE(file.write("Hello"), 5LL);
+- QVERIFY(file.commit());
+-
+- QFile reader(targetFile);
+- QVERIFY(reader.open(QIODevice::ReadOnly));
+- QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Hello"));
+- reader.close();
+-
+- QVERIFY(QFile::remove(targetFile));
+-}
+-
+-void TestQSaveFile::autoFlush()
+-{
+- const QString dir = tmpDir();
+- QVERIFY(!dir.isEmpty());
+- const QString targetFile = dir + QString::fromLatin1("/outfile");
+- DirCleanup dirCleanup(dir, "outfile");
+- QFile::remove(targetFile);
+- QSaveFile file(targetFile);
+- QVERIFY(file.open(QIODevice::WriteOnly));
+-
+- QTextStream ts(&file);
+- ts << "Auto-flush.";
+- // no flush
+- QVERIFY(file.commit()); // close will emit aboutToClose, which will flush the stream
+- QFile reader(targetFile);
+- QVERIFY(reader.open(QIODevice::ReadOnly));
+- QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Auto-flush."));
+- reader.close();
+-
+- QVERIFY(QFile::remove(targetFile));
+-}
+-
+-void TestQSaveFile::transactionalWriteNoPermissions()
+-{
+-#ifdef Q_OS_UNIX
+- if (::geteuid() == 0) {
+- QSKIP("not valid running this test as root", SkipAll);
+- }
+-
+- // You can write into /dev/zero, but you can't create a /dev/zero.XXXXXX temp file.
+- QSaveFile file("/dev/zero");
+- if (!QDir("/dev").exists()) {
+- QSKIP("/dev doesn't exist on this system", SkipAll);
+- }
+-
+- QVERIFY(!file.open(QIODevice::WriteOnly));
+- QCOMPARE(static_cast<int>(file.error()), static_cast<int>(QFile::OpenError));
+- QVERIFY(!file.commit());
+-#endif
+-}
+-
+-void TestQSaveFile::transactionalWriteCanceled()
+-{
+- const QString dir = tmpDir();
+- QVERIFY(!dir.isEmpty());
+- const QString targetFile = dir + QString::fromLatin1("/outfile");
+- DirCleanup dirCleanup(dir, "outfile");
+- QFile::remove(targetFile);
+- QSaveFile file(targetFile);
+- QVERIFY(file.open(QIODevice::WriteOnly));
+-
+- QTextStream ts(&file);
+- ts << "This writing operation will soon be canceled.\n";
+- ts.flush();
+- QCOMPARE(file.error(), QFile::NoError);
+- QVERIFY(!QFile::exists(targetFile));
+-
+- // We change our mind, let's abort writing
+- file.cancelWriting();
+-
+- QVERIFY(!file.commit());
+-
+- QVERIFY(!QFile::exists(targetFile)); // temp file was discarded
+- QCOMPARE(file.fileName(), targetFile);
+-}
+-
+-void TestQSaveFile::transactionalWriteErrorRenaming()
+-{
+-#ifndef Q_OS_WIN
+- if (::geteuid() == 0) {
+- QSKIP("not valid running this test as root", SkipAll);
+- }
+- const QString dir = tmpDir();
+- QVERIFY(!dir.isEmpty());
+- const QString targetFile = dir + QString::fromLatin1("/outfile");
+- DirCleanup dirCleanup(dir, "outfile");
+- QSaveFile file(targetFile);
+- QVERIFY(file.open(QIODevice::WriteOnly));
+- QCOMPARE(file.write("Hello"), qint64(5));
+- QVERIFY(!QFile::exists(targetFile));
+-
+-#ifdef Q_OS_UNIX
+- QFile dirAsFile(dir); // yay, I have to use QFile to change a dir's permissions...
+- QVERIFY(dirAsFile.setPermissions(QFile::Permissions(0))); // no permissions
+-#else
+- QVERIFY(file.setPermissions(QFile::ReadOwner));
+-#endif
+-
+- QVERIFY(!file.commit());
+- QVERIFY(!QFile::exists(targetFile)); // renaming failed
+- QCOMPARE(file.error(), QFile::RenameError);
+-
+- // Restore permissions so that the cleanup can happen
+-#ifdef Q_OS_UNIX
+- QVERIFY(dirAsFile.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)));
+-#else
+- QVERIFY(file.setPermissions(QFile::ReadOwner | QFile::WriteOwner));
+-#endif
+-#endif // !Q_OS_WIN
+-}
+-
+-QString TestQSaveFile::tmpDir()
+-{
+- QTemporaryFile* tmpFile = new QTemporaryFile(QDir::tempPath() + "/qttest_temp.XXXXXX");
+- if (!tmpFile->open()) {
+- return QString();
+- }
+- QString dirName = tmpFile->fileName();
+- delete tmpFile;
+- if (!QDir().mkdir(dirName)) {
+- return QString();
+- }
+-
+- return dirName;
+-}
+diff --git a/tests/TestQSaveFile.h b/tests/TestQSaveFile.h
+deleted file mode 100644
+index 8e1caf0..0000000
+--- a/tests/TestQSaveFile.h
++++ /dev/null
+@@ -1,39 +0,0 @@
+-/*
+- * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
+- * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
+- *
+- * 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_TESTQSAVEFILE_H
+-#define KEEPASSX_TESTQSAVEFILE_H
+-
+-#include <QObject>
+-
+-class TestQSaveFile : public QObject
+-{
+- Q_OBJECT
+-
+-private Q_SLOTS:
+- void transactionalWrite();
+- void autoFlush();
+- void transactionalWriteNoPermissions();
+- void transactionalWriteCanceled();
+- void transactionalWriteErrorRenaming();
+-
+-private:
+- QString tmpDir();
+-};
+-
+-#endif // KEEPASSX_TESTQSAVEFILE_H
+diff --git a/tests/TestRandom.cpp b/tests/TestRandom.cpp
+index 40ab702..6c5b1f7 100644
+--- a/tests/TestRandom.cpp
++++ b/tests/TestRandom.cpp
+@@ -17,8 +17,8 @@
+
+ #include "TestRandom.h"
+
+-#include "tests.h"
+ #include "core/Endian.h"
++#include "core/Global.h"
+
+ #include <QTest>
+
+diff --git a/tests/TestRandom.h b/tests/TestRandom.h
+index a308f36..c879f94 100644
+--- a/tests/TestRandom.h
++++ b/tests/TestRandom.h
+@@ -18,7 +18,6 @@
+ #ifndef KEEPASSX_TESTRANDOM_H
+ #define KEEPASSX_TESTRANDOM_H
+
+-#include "core/Global.h"
+ #include "crypto/Random.h"
+
+ #include <QObject>
+@@ -27,7 +26,7 @@ class RandomBackendTest : public RandomBackend
+ {
+ public:
+ RandomBackendTest();
+- void randomize(void* data, int len) Q_DECL_OVERRIDE;
++ void randomize(void* data, int len) override;
+ void setNextBytes(const QByteArray& nextBytes);
+
+ private:
+diff --git a/tests/TestSymmetricCipher.cpp b/tests/TestSymmetricCipher.cpp
+index 578d250..698ecb2 100644
+--- a/tests/TestSymmetricCipher.cpp
++++ b/tests/TestSymmetricCipher.cpp
+@@ -20,7 +20,6 @@
+ #include <QBuffer>
+ #include <QTest>
+
+-#include "tests.h"
+ #include "crypto/Crypto.h"
+ #include "crypto/SymmetricCipher.h"
+ #include "streams/SymmetricCipherStream.h"
+diff --git a/tests/TestWildcardMatcher.cpp b/tests/TestWildcardMatcher.cpp
+index dc9991d..dffe1c8 100644
+--- a/tests/TestWildcardMatcher.cpp
++++ b/tests/TestWildcardMatcher.cpp
+@@ -19,7 +19,6 @@
+
+ #include <QTest>
+
+-#include "tests.h"
+ #include "autotype/WildcardMatcher.h"
+
+ QTEST_GUILESS_MAIN(TestWildcardMatcher)
+diff --git a/tests/gui/CMakeLists.txt b/tests/gui/CMakeLists.txt
+index 91fcd69..a1ca914 100644
+--- a/tests/gui/CMakeLists.txt
++++ b/tests/gui/CMakeLists.txt
+@@ -13,6 +13,6 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+-add_unit_test(NAME testgui SOURCES TestGui.cpp MOCS TestGui.h LIBS ${TEST_LIBRARIES})
++add_unit_test(NAME testgui SOURCES TestGui.cpp LIBS ${TEST_LIBRARIES})
+
+-add_unit_test(NAME testguipixmaps SOURCES TestGuiPixmaps.cpp MOCS TestGuiPixmaps.h LIBS ${TEST_LIBRARIES})
++add_unit_test(NAME testguipixmaps SOURCES TestGuiPixmaps.cpp LIBS ${TEST_LIBRARIES})
+diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp
+index 6aa49b8..1585c8a 100644
+--- a/tests/gui/TestGui.cpp
++++ b/tests/gui/TestGui.cpp
+@@ -21,6 +21,7 @@
+ #include <QApplication>
+ #include <QDialogButtonBox>
+ #include <QLineEdit>
++#include <QMimeData>
+ #include <QPushButton>
+ #include <QSpinBox>
+ #include <QTemporaryFile>
+@@ -29,7 +30,6 @@
+ #include <QToolButton>
+
+ #include "config-keepassx-tests.h"
+-#include "tests.h"
+ #include "core/Config.h"
+ #include "core/Database.h"
+ #include "core/Entry.h"
+@@ -56,6 +56,7 @@ void TestGui::initTestCase()
+ m_mainWindow = new MainWindow();
+ m_tabWidget = m_mainWindow->findChild<DatabaseTabWidget*>("tabWidget");
+ m_mainWindow->show();
++ m_mainWindow->activateWindow();
+ Tools::wait(50);
+
+ QByteArray tmpData;
+@@ -184,7 +185,7 @@ void TestGui::testSearch()
+ QLineEdit* searchEdit = m_dbWidget->findChild<QLineEdit*>("searchEdit");
+ QToolButton* clearSearch = m_dbWidget->findChild<QToolButton*>("clearButton");
+
+- QVERIFY(!searchEdit->hasFocus());
++ QVERIFY(!searchEdit->isVisible());
+
+ // Enter search
+ QTest::mouseClick(searchActionWidget, Qt::LeftButton);
+@@ -439,8 +440,8 @@ void TestGui::testDatabaseLocking()
+
+ triggerAction("actionLockDatabases");
+
+- QCOMPARE(m_tabWidget->tabText(0), QString("Save [locked]"));
+- QCOMPARE(m_tabWidget->tabText(1), QString("basic [New database]*"));
++ QCOMPARE(m_tabWidget->tabText(0).remove('&'), QString("Save [locked]"));
++ QCOMPARE(m_tabWidget->tabText(1).remove('&'), QString("basic [New database]*"));
+
+ QWidget* dbWidget = m_tabWidget->currentDatabaseWidget();
+ QWidget* unlockDatabaseWidget = dbWidget->findChild<QWidget*>("unlockDatabaseWidget");
+@@ -450,7 +451,7 @@ void TestGui::testDatabaseLocking()
+ QTest::keyClicks(editPassword, "masterpw");
+ QTest::keyClick(editPassword, Qt::Key_Enter);
+
+- QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("basic [New database]*"));
++ QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()).remove('&'), QString("basic [New database]*"));
+ }
+
+ void TestGui::cleanupTestCase()
+diff --git a/tests/gui/TestGuiPixmaps.cpp b/tests/gui/TestGuiPixmaps.cpp
+index 87e3f24..3637494 100644
+--- a/tests/gui/TestGuiPixmaps.cpp
++++ b/tests/gui/TestGuiPixmaps.cpp
+@@ -19,7 +19,6 @@
+
+ #include <QTest>
+
+-#include "tests.h"
+ #include "core/Database.h"
+ #include "core/DatabaseIcons.h"
+ #include "core/Entry.h"
+diff --git a/tests/modeltest.cpp b/tests/modeltest.cpp
+index 19f02d9..360a7be 100644
+--- a/tests/modeltest.cpp
++++ b/tests/modeltest.cpp
+@@ -1,50 +1,40 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+-** Contact: http://www.qt-project.org/
++** Copyright (C) 2015 The Qt Company Ltd.
++** Contact: http://www.qt.io/licensing/
+ **
+ ** This file is part of the test suite of the Qt Toolkit.
+ **
+-** $QT_BEGIN_LICENSE:LGPL$
++** $QT_BEGIN_LICENSE:LGPL21$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see http://www.qt.io/terms-conditions. For further
++** information use the contact form at http://www.qt.io/contact-us.
++**
+ ** GNU Lesser General Public License Usage
+-** This file may be used under the terms of the GNU Lesser General Public
+-** License version 2.1 as published by the Free Software Foundation and
+-** appearing in the file LICENSE.LGPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU Lesser
+-** General Public License version 2.1 requirements will be met:
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 or version 3 as published by the Free
++** Software Foundation and appearing in the file LICENSE.LGPLv21 and
++** LICENSE.LGPLv3 included in the packaging of this file. Please review the
++** following information to ensure the GNU Lesser General Public License
++** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+-** In addition, as a special exception, Nokia gives you certain additional
+-** rights. These rights are described in the Nokia Qt LGPL Exception
++** As a special exception, The Qt Company gives you certain additional
++** rights. These rights are described in The Qt Company LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU General
+-** Public License version 3.0 as published by the Free Software Foundation
+-** and appearing in the file LICENSE.GPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU General
+-** Public License version 3.0 requirements will be met:
+-** http://www.gnu.org/copyleft/gpl.html.
+-**
+-** Other Usage
+-** Alternatively, this file may be used in accordance with the terms and
+-** conditions contained in a signed written agreement between you and Nokia.
+-**
+-**
+-**
+-**
+-**
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+-
+ #include "modeltest.h"
+
+-#include <QDebug>
+-#include <QTest>
+-
+-Q_DECLARE_METATYPE ( QModelIndex )
++#include <QtCore>
++#include <QtTest>
+
+ /*!
+ Connect to all of the models signals. Whenever anything happens recheck everything.
+@@ -54,50 +44,52 @@ ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject (
+ if (!model)
+ qFatal("%s: model must not be null", Q_FUNC_INFO);
+
+- connect ( model, SIGNAL ( columnsAboutToBeInserted ( const QModelIndex &, int, int ) ),
+- this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( columnsAboutToBeRemoved ( const QModelIndex &, int, int ) ),
+- this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( columnsInserted ( const QModelIndex &, int, int ) ),
+- this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( columnsRemoved ( const QModelIndex &, int, int ) ),
+- this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ),
+- this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ),
+- this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( layoutAboutToBeChanged () ), this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( layoutChanged () ), this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( modelReset () ), this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ),
+- this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ),
+- this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ),
+- this, SLOT ( runAllTests() ) );
+- connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ),
+- this, SLOT ( runAllTests() ) );
+-
+- // Special checks for inserting/removing
+- connect ( model, SIGNAL ( layoutAboutToBeChanged() ),
+- this, SLOT ( layoutAboutToBeChanged() ) );
+- connect ( model, SIGNAL ( layoutChanged() ),
+- this, SLOT ( layoutChanged() ) );
+-
+- connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ),
+- this, SLOT ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ) );
+- connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ),
+- this, SLOT ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ) );
+- connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ),
+- this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) );
+- connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ),
+- this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) );
+-
+- connect ( model, SIGNAL (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
+- this, SLOT (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) );
+- connect ( model, SIGNAL (rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+- this, SLOT (rowsMoved(QModelIndex,int,int,QModelIndex,int)) );
+-
++ connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
++ this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
++ this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
++ this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
++ this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
++ this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
++ this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
++ this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
++ this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
++ this, SLOT(runAllTests()) );
++ connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
++ this, SLOT(runAllTests()) );
++
++ // Special checks for changes
++ connect(model, SIGNAL(layoutAboutToBeChanged()),
++ this, SLOT(layoutAboutToBeChanged()) );
++ connect(model, SIGNAL(layoutChanged()),
++ this, SLOT(layoutChanged()) );
++
++ connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
++ this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)) );
++ connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
++ this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)) );
++ connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
++ this, SLOT(rowsInserted(QModelIndex,int,int)) );
++ connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
++ this, SLOT(rowsRemoved(QModelIndex,int,int)) );
++ connect(model, SIGNAL (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
++ this, SLOT (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) );
++ connect(model, SIGNAL (rowsMoved(QModelIndex,int,int,QModelIndex,int)),
++ this, SLOT (rowsMoved(QModelIndex,int,int,QModelIndex,int)) );
++ connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
++ this, SLOT(dataChanged(QModelIndex,QModelIndex)) );
++ connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
++ this, SLOT(headerDataChanged(Qt::Orientation,int,int)) );
+
+ runAllTests();
+ }
+@@ -257,7 +249,7 @@ void ModelTest::index()
+ void ModelTest::parent()
+ {
+ // qDebug() << "p";
+- // Make sure the model wont crash and will return an invalid QModelIndex
++ // Make sure the model won't crash and will return an invalid QModelIndex
+ // when asked for the parent of an invalid index.
+ QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() );
+
+@@ -339,6 +331,8 @@ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
+ //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
+ // << "columns:" << columns << "parent column:" << parent.column();
+
++ const QModelIndex topLeftChild = model->index( 0, 0, parent );
++
+ QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) );
+ for ( int r = 0; r < rows; ++r ) {
+ if ( model->canFetchMore ( parent ) ) {
+@@ -362,6 +356,15 @@ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
+ QModelIndex b = model->index ( r, c, parent );
+ QVERIFY( a == b );
+
++ {
++ const QModelIndex sibling = model->sibling( r, c, topLeftChild );
++ QVERIFY( index == sibling );
++ }
++ {
++ const QModelIndex sibling = topLeftChild.sibling( r, c );
++ QVERIFY( index == sibling );
++ }
++
+ // Some basic checking on the index that is returned
+ QVERIFY( index.model() == model );
+ QCOMPARE( index.row(), r );
+@@ -474,9 +477,9 @@ void ModelTest::data()
+
+ \sa rowsInserted()
+ */
+-void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end )
++void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */)
+ {
+- Q_UNUSED(end);
++// Q_UNUSED(end);
+ // qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString()
+ // << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) );
+ // qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) );
+@@ -565,6 +568,30 @@ void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end )
+ QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) );
+ }
+
++void ModelTest::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
++{
++ QVERIFY(topLeft.isValid());
++ QVERIFY(bottomRight.isValid());
++ QModelIndex commonParent = bottomRight.parent();
++ QVERIFY(topLeft.parent() == commonParent);
++ QVERIFY(topLeft.row() <= bottomRight.row());
++ QVERIFY(topLeft.column() <= bottomRight.column());
++ int rowCount = model->rowCount(commonParent);
++ int columnCount = model->columnCount(commonParent);
++ QVERIFY(bottomRight.row() < rowCount);
++ QVERIFY(bottomRight.column() < columnCount);
++}
++
++void ModelTest::headerDataChanged(Qt::Orientation orientation, int start, int end)
++{
++ QVERIFY(start >= 0);
++ QVERIFY(end >= 0);
++ QVERIFY(start <= end);
++ int itemCount = orientation == Qt::Vertical ? model->rowCount() : model->columnCount();
++ QVERIFY(start < itemCount);
++ QVERIFY(end < itemCount);
++}
++
+ void ModelTest::rowsAboutToBeMoved( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow )
+ {
+ Changing cs;
+@@ -589,8 +616,8 @@ void ModelTest::rowsMoved( const QModelIndex &srcParent, int start, int end, con
+ QVERIFY ( cd.oldSize == model->rowCount ( destParent ) );
+
+ // TODO: Find out what I can assert here about last and next.
+- // QVERIFY ( cd.last == model->data ( model->index ( destinationRow - 1, 0, cd.parent ) ) );
+- // QVERIFY ( cd.next == model->data ( model->index ( destinationRow + (end - start + 1), 0, cd.parent ) ) );
++ // Q_ASSERT ( cd.last == model->data ( model->index ( destinationRow - 1, 0, cd.parent ) ) );
++ // Q_ASSERT ( cd.next == model->data ( model->index ( destinationRow + (end - start + 1), 0, cd.parent ) ) );
+ }
+ else {
+ QVERIFY ( cd.oldSize + ( end - start + 1 ) == model->rowCount ( destParent ) );
+@@ -602,12 +629,12 @@ void ModelTest::rowsMoved( const QModelIndex &srcParent, int start, int end, con
+ Changing cs = remove.pop();
+ QVERIFY ( cs.parent == srcParent );
+ if (srcParent == destParent) {
+- QVERIFY ( cs.oldSize == model->rowCount ( srcParent ) );
++ QVERIFY ( cs.oldSize == model->rowCount ( srcParent ) );
+ }
+ else {
+- QVERIFY ( cs.oldSize - ( end - start + 1 ) == model->rowCount ( srcParent ) );
++ QVERIFY ( cs.oldSize - ( end - start + 1 ) == model->rowCount ( srcParent ) );
+
+- QVERIFY ( cs.last == model->data ( model->index ( start - 1, 0, srcParent ) ) );
+- QVERIFY ( cs.next == model->data ( model->index ( start, 0, srcParent ) ) );
++ QVERIFY ( cs.last == model->data ( model->index ( start - 1, 0, srcParent ) ) );
++ QVERIFY ( cs.next == model->data ( model->index ( start, 0, srcParent ) ) );
+ }
+ }
+diff --git a/tests/modeltest.h b/tests/modeltest.h
+index 9eb343d..3dcf18c 100644
+--- a/tests/modeltest.h
++++ b/tests/modeltest.h
+@@ -1,40 +1,32 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+-** All rights reserved.
+-** Contact: Nokia Corporation (qt-info@nokia.com)
++** Copyright (C) 2015 The Qt Company Ltd.
++** Contact: http://www.qt.io/licensing/
+ **
+ ** This file is part of the test suite of the Qt Toolkit.
+ **
+-** $QT_BEGIN_LICENSE:LGPL$
++** $QT_BEGIN_LICENSE:LGPL21$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see http://www.qt.io/terms-conditions. For further
++** information use the contact form at http://www.qt.io/contact-us.
++**
+ ** GNU Lesser General Public License Usage
+-** This file may be used under the terms of the GNU Lesser General Public
+-** License version 2.1 as published by the Free Software Foundation and
+-** appearing in the file LICENSE.LGPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU Lesser
+-** General Public License version 2.1 requirements will be met:
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 or version 3 as published by the Free
++** Software Foundation and appearing in the file LICENSE.LGPLv21 and
++** LICENSE.LGPLv3 included in the packaging of this file. Please review the
++** following information to ensure the GNU Lesser General Public License
++** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+-** In addition, as a special exception, Nokia gives you certain additional
+-** rights. These rights are described in the Nokia Qt LGPL Exception
++** As a special exception, The Qt Company gives you certain additional
++** rights. These rights are described in The Qt Company LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+-** GNU General Public License Usage
+-** Alternatively, this file may be used under the terms of the GNU General
+-** Public License version 3.0 as published by the Free Software Foundation
+-** and appearing in the file LICENSE.GPL included in the packaging of this
+-** file. Please review the following information to ensure the GNU General
+-** Public License version 3.0 requirements will be met:
+-** http://www.gnu.org/copyleft/gpl.html.
+-**
+-** Other Usage
+-** Alternatively, this file may be used in accordance with the terms and
+-** conditions contained in a signed written agreement between you and Nokia.
+-**
+-**
+-**
+-**
+-**
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+@@ -43,8 +35,8 @@
+ #ifndef MODELTEST_H
+ #define MODELTEST_H
+
+-#include <QAbstractItemModel>
+ #include <QObject>
++#include <QAbstractItemModel>
+ #include <QStack>
+
+ class ModelTest : public QObject
+@@ -73,7 +65,8 @@ protected Q_SLOTS:
+ void rowsRemoved( const QModelIndex & parent, int start, int end );
+ void rowsAboutToBeMoved ( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow );
+ void rowsMoved ( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow );
+-
++ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
++ void headerDataChanged(Qt::Orientation orientation, int start, int end);
+
+ private:
+ void checkChildren( const QModelIndex &parent, int currentDepth = 0 );
+diff --git a/tests/tests.h b/tests/tests.h
+deleted file mode 100644
+index e719a0b..0000000
+--- a/tests/tests.h
++++ /dev/null
+@@ -1,72 +0,0 @@
+-/*
+- * Copyright (C) 2011 Felix Geyer <debfx@fobos.de>
+- * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+- *
+- * 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_TESTS_H
+-#define KEEPASSX_TESTS_H
+-
+-#include <QTest>
+-
+-// backport QTEST_GUILESS_MAIN, QTRY_VERIFY and QTRY_COMPARE from Qt 5
+-
+-#ifndef QTEST_GUILESS_MAIN
+-#define QTEST_GUILESS_MAIN(TestObject) \
+-int main(int argc, char* argv[]) \
+-{ \
+- QCoreApplication app(argc, argv); \
+- TestObject tc; \
+- return QTest::qExec(&tc, argc, argv); \
+-}
+-#endif // QTEST_GUILESS_MAIN
+-
+-
+-#ifndef QTRY_VERIFY
+-#define KEEPASSX_VERIFY_WITH_TIMEOUT(__expr, __timeout) \
+-do { \
+- const int __step = 50; \
+- const int __timeoutValue = __timeout; \
+- if (!(__expr)) { \
+- QTest::qWait(0); \
+- } \
+- for (int __i = 0; __i < __timeoutValue && !(__expr); __i+=__step) { \
+- QTest::qWait(__step); \
+- } \
+- QVERIFY(__expr); \
+-} while (0)
+-
+-#define QTRY_VERIFY(__expr) KEEPASSX_VERIFY_WITH_TIMEOUT(__expr, 5000)
+-#endif // QTRY_VERIFY
+-
+-
+-#ifndef QTRY_COMPARE
+-#define KEEPASSX_COMPARE_WITH_TIMEOUT(__expr, __expected, __timeout) \
+-do { \
+- const int __step = 50; \
+- const int __timeoutValue = __timeout; \
+- if ((__expr) != (__expected)) { \
+- QTest::qWait(0); \
+- } \
+- for (int __i = 0; __i < __timeoutValue && ((__expr) != (__expected)); __i+=__step) { \
+- QTest::qWait(__step); \
+- } \
+- QCOMPARE(__expr, __expected); \
+-} while (0)
+-
+-#define QTRY_COMPARE(__expr, __expected) KEEPASSX_COMPARE_WITH_TIMEOUT(__expr, __expected, 5000)
+-#endif // QTRY_COMPARE
+-
+-#endif // KEEPASSX_TESTS_H
+diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
+index c4aa5fa..7988467 100644
+--- a/utils/CMakeLists.txt
++++ b/utils/CMakeLists.txt
+@@ -18,7 +18,8 @@ include_directories(../src)
+ add_executable(kdbx-extract kdbx-extract.cpp)
+ target_link_libraries(kdbx-extract
+ keepassx_core
+- ${QT_QTCORE_LIBRARY}
+- ${QT_QTGUI_LIBRARY}
++ Qt5::Core
++ Qt5::Concurrent
++ Qt5::Widgets
+ ${GCRYPT_LIBRARIES}
+ ${ZLIB_LIBRARIES})