diff --git a/CHANGELOG.md b/CHANGELOG.md index c201bee41..ff7e1b018 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -897,7 +897,7 @@ - Compare window title to entry URLs #556 - Implemented inline error messages #162 - Ignore group expansion and other minor changes when making database "dirty" #464 -- Updated license and copyright information on souce files #632 +- Updated license and copyright information on source files #632 - Added contributors list to about dialog #629 ## 2.1.4 (2017-04-09) diff --git a/README.md b/README.md index 0142a698b..4bffba69c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # KeePassXC +[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/6326/badge)](https://bestpractices.coreinfrastructure.org/projects/6326) [![TeamCity Build Status](https://ci.keepassxc.org/app/rest/builds/buildType:\(project:KeepassXC\)/statusIcon)](https://ci.keepassxc.org/?guest=1) [![codecov](https://codecov.io/gh/keepassxreboot/keepassxc/branch/develop/graph/badge.svg)](https://codecov.io/gh/keepassxreboot/keepassxc) [![GitHub release](https://img.shields.io/github/release/keepassxreboot/keepassxc)](https://github.com/keepassxreboot/keepassxc/releases/) diff --git a/cmake/KPXCMacDeployHelpers.cmake b/cmake/KPXCMacDeployHelpers.cmake index d22051d32..f86067cbc 100644 --- a/cmake/KPXCMacDeployHelpers.cmake +++ b/cmake/KPXCMacDeployHelpers.cmake @@ -1,5 +1,5 @@ # Running macdeployqt on a POST_BUILD copied binaries is pointless when using CPack because -# the copied binaries will be overriden by the corresponding install(TARGETS) commands. +# the copied binaries will be overridden by the corresponding install(TARGETS) commands. # That's why we run macdeployqt using install(CODE) on the already installed binaries. # The precondition is that all install(TARGETS) calls have to be called before this function is # called. diff --git a/docs/topics/AutoType.adoc b/docs/topics/AutoType.adoc index 836d2c7d1..04c5e7b96 100644 --- a/docs/topics/AutoType.adoc +++ b/docs/topics/AutoType.adoc @@ -1,4 +1,4 @@ -= KeePassXC - Auto-Type += KeePassXC – Auto-Type :imagesdir: ../images // tag::content[] diff --git a/docs/topics/BrowserPlugin.adoc b/docs/topics/BrowserPlugin.adoc index 9435a1c9c..f36767492 100644 --- a/docs/topics/BrowserPlugin.adoc +++ b/docs/topics/BrowserPlugin.adoc @@ -1,4 +1,4 @@ -= KeePassXC - Browser Plugin += KeePassXC – Browser Plugin include::.sharedheader[] :imagesdir: ../images diff --git a/docs/topics/DatabaseOperations.adoc b/docs/topics/DatabaseOperations.adoc index aa5b4aec3..b3098fc9a 100644 --- a/docs/topics/DatabaseOperations.adoc +++ b/docs/topics/DatabaseOperations.adoc @@ -1,4 +1,4 @@ -= KeePassXC - Database Operations += KeePassXC – Database Operations include::.sharedheader[] :imagesdir: ../images @@ -11,22 +11,22 @@ To create a database, perform the following steps: 1. Open your KeePassXC application. Click the create new database button *(A)*: + -.Create database - Welcome screen +.Create database – Welcome screen image::welcome_screen.png[] 2. The database creation wizard appears. Enter the desired database name and a short description (optional): + -.Create database - General information +.Create database – General information image::new_db_wizard_1.png[,80%] 3. Click Continue. The Encryption Settings screen appears, we don't recommend making any changes besides increasing or decreasing the decryption time using the slider. Setting the Decryption Time slider at higher values means that the database will have higher level of protection but the time taken by the database to open will increase. + -.Create database - Encryption settings +.Create database – Encryption settings image::new_db_wizard_2.png[,80%] 4. Click the Continue button. The Database Credentials screen appears, enter your desired database password. We recommend using a long, randomized password. + -.Create database - Database credentials +.Create database – Database credentials image::new_db_wizard_3.png[,80%] + *(A)* Open the password generator + @@ -362,7 +362,7 @@ The following key derivation functions are supported: * AES-KDF (KDBX 4 and KDBX 3.1): This key derivation function is based on iterating AES. Users can change the number of iterations. The more iterations, the harder are dictionary and guessing attacks, but also database loading/saving takes more time (linearly). KDBX 3.1 only supports AES-KDF; any other key derivation function, like for instance Argon2, requires KDBX 4. - * Argon2 (KDBX 4 - recommended): KDBX 4, the Argon2 key derivation function can be used for transforming the composite master key (as protection against dictionary attacks). The main advantage of Argon2 over AES-KDF is that it provides a better resistance against GPU/ASIC attacks (due to being a memory-hard function). The number of iterations scales linearly with the required time. By increasing the memory parameter, GPU/ASIC attacks become harder and the required time increases. The parallelism parameter can be used to specify how many threads should be used. We recommend using Argon2id to prevent against timing-based attacks. Argon2d offers maximum compatibility with other KeePass-based apps, the default settings provide sufficient protection against any known attacks. + * Argon2 (KDBX 4 – recommended): KDBX 4, the Argon2 key derivation function can be used for transforming the composite master key (as protection against dictionary attacks). The main advantage of Argon2 over AES-KDF is that it provides a better resistance against GPU/ASIC attacks (due to being a memory-hard function). The number of iterations scales linearly with the required time. By increasing the memory parameter, GPU/ASIC attacks become harder and the required time increases. The parallelism parameter can be used to specify how many threads should be used. We recommend using Argon2id to prevent against timing-based attacks. Argon2d offers maximum compatibility with other KeePass-based apps, the default settings provide sufficient protection against any known attacks. == Database Maintenance KeePassXC offers some maintenance features that can be applied to clean up your database. Navigate to _Database_ -> _Database settings_ then click on _Maintenance_ on the left hand panel. The following screen appears. On this screen you can delete multiple icons at once and purge any unused icons in your database. @@ -395,9 +395,9 @@ The database file that you create might contain highly sensitive data and must b Make sure that you or someone else does not accidentally delete the database file. Deletion of the database file will result in the total loss of all your information (including all your passwords!) and a lot of inconvenience to manually retrieve your logins for various web applications. Do not share the credentials to access your database file with anyone unless you absolutely trust them (spouse, child, etc.). -TIP: You can safely store your database file in the cloud (e.g., OneDrive, Dropbox, Google Drive, Nextcloud, Syncthing, etc). The database file is always fully encrypted; unencrypted data is never written to disk and is never accessible to your cloud storage provider. We recommend using a storage service that keeps automatic backups (version history) of your database file in the event of corruption or accidental deletion. +TIP: You can safely store your database file in the cloud (OneDrive, Dropbox, Google Drive, Nextcloud, Syncthing, etc.). The database file is always fully encrypted; unencrypted data is never written to disk and is never accessible to your cloud storage provider. We recommend using a storage service that keeps automatic backups (version history) of your database file in the event of corruption or accidental deletion. -== Backing up a Database File +== Backing up a Database File It is a good practice to create copies of your database file and store the copies of your database on a different computer, smart phone, or cloud storage space such a Google Drive or Microsoft OneDrive. Backups can be created automatically by selecting the _Backup database file before saving_ option in the application settings. Additionally, you can create a backup on-demand using the _Database_ -> _Save Database Backup..._ menu feature. .Saving a database backup diff --git a/docs/topics/DownloadInstall.adoc b/docs/topics/DownloadInstall.adoc index e96c885de..f5a967ec5 100644 --- a/docs/topics/DownloadInstall.adoc +++ b/docs/topics/DownloadInstall.adoc @@ -1,4 +1,4 @@ -= KeePassXC - Download and Install += KeePassXC – Download and Install include::.sharedheader[] :imagesdir: ../images @@ -8,9 +8,9 @@ KeePassXC is available for download for the following operating systems and plat * Microsoft Windows ** Portable and MSI Installer (64-bit and 32-bit) -* Linux - Official Cross-Distribution Packages +* Linux – Official Cross-Distribution Packages ** AppImage and Snap Package -* Linux - Distribution-Specific Packages +* Linux – Distribution-Specific Packages ** Ubuntu, Debian, Arch Linux, Gentoo, Fedora, CentOS, and OpenSUSE * macOS ** DMG Installer, Homebrew Cask @@ -45,9 +45,9 @@ image::install_wizard_2.png[,80%] The following options can be set when running the MSI in an unattended installation: -* *LAUNCHAPPONEXIT* - Launch KeePassXC after install (default ON) -* *AUTOSTARTPROGRAM* - KeePassXC will auto-start on login (default ON) -* *INSTALLDESKTOPSHORTCUT* - A desktop icon will be installed (default OFF) +* *LAUNCHAPPONEXIT* – Launch KeePassXC after install (default ON) +* *AUTOSTARTPROGRAM* – KeePassXC will auto-start on login (default ON) +* *INSTALLDESKTOPSHORTCUT* – A desktop icon will be installed (default OFF) Example: `msiexec.exe /q /i KeePassXC-Y.Y.Y-WinZZ.msi AUTOSTARTPROGRAM=0` @@ -69,4 +69,4 @@ image::macos_install.png[,80%] // end::content[] // tag::advanced[] -// end::advanced[] \ No newline at end of file +// end::advanced[] diff --git a/docs/topics/ImportExport.adoc b/docs/topics/ImportExport.adoc index 657a182ad..974b00474 100644 --- a/docs/topics/ImportExport.adoc +++ b/docs/topics/ImportExport.adoc @@ -1,4 +1,4 @@ -= KeePassXC - Import/Export Operations += KeePassXC – Import/Export Operations include::.sharedheader[] :imagesdir: ../images diff --git a/docs/topics/KeeShare.adoc b/docs/topics/KeeShare.adoc index 6735378d4..75769bdb4 100644 --- a/docs/topics/KeeShare.adoc +++ b/docs/topics/KeeShare.adoc @@ -1,4 +1,4 @@ -= KeePassXC - KeeShare += KeePassXC – KeeShare include::.sharedheader[] :imagesdir: ../images @@ -24,10 +24,10 @@ NOTE: KeeShare does not synchronize group structure after the initial share is c 1. Open the edit sheet on a group you want to share. 2. Select the KeeShare category on the left toolbar. 3. Choose a sharing type: - a. *Inactive* - Disable sharing this group - b. *Import* - Read-only import of entries, merge changes - c. *Export* - Write-only export of entries, no merge - d. *Synchronize* - Read/Write entries from the share, merge changes + a. *Inactive* – Disable sharing this group + b. *Import* – Read-only import of entries, merge changes + c. *Export* – Write-only export of entries, no merge + d. *Synchronize* – Read/Write entries from the share, merge changes 4. Choose a path to store the shared credentials to. 5. The password to use for this share container. diff --git a/docs/topics/KeyboardShortcuts.adoc b/docs/topics/KeyboardShortcuts.adoc index b027ba1fc..8d8ab6ca0 100644 --- a/docs/topics/KeyboardShortcuts.adoc +++ b/docs/topics/KeyboardShortcuts.adoc @@ -1,4 +1,4 @@ -= KeePassXC - Keyboard Shortcuts += KeePassXC – Keyboard Shortcuts include::.sharedheader[] :imagesdir: ../images @@ -9,12 +9,15 @@ NOTE: On macOS please substitute `Ctrl` with `Cmd` (aka `⌘`). |=== |Action | Keyboard Shortcut +|Settings | Ctrl + , |Open Database | Ctrl + O |Save Database | Ctrl + S |Save Database As | Ctrl + Shift + S |New Database | Ctrl + Shift + N |Close Database | Ctrl + W ; Ctrl + F4 |Lock All Databases | Ctrl + L +|Database Settings | Ctrl + Shift + , +|Database Reports | Ctrl + Shift + R |Quit | Ctrl + Q |New Entry | Ctrl + N |Edit Entry | Enter ; Ctrl + E diff --git a/docs/topics/PasswordGenerator.adoc b/docs/topics/PasswordGenerator.adoc index 2d8310b83..a1f1915e9 100644 --- a/docs/topics/PasswordGenerator.adoc +++ b/docs/topics/PasswordGenerator.adoc @@ -1,4 +1,4 @@ -= KeePassXC - Password Generator += KeePassXC – Password Generator include::.sharedheader[] :imagesdir: ../images diff --git a/docs/topics/Reference.adoc b/docs/topics/Reference.adoc index fb9545ed2..4171ed9a5 100644 --- a/docs/topics/Reference.adoc +++ b/docs/topics/Reference.adoc @@ -1,4 +1,4 @@ -= KeePassXC - Reference += KeePassXC – Reference include::.sharedheader[] :imagesdir: ../images @@ -53,13 +53,13 @@ A reference to another entry's field is possible using the shorthand syntax: `<FIELD>` and `<SEARCH_IN>` can be one of following: -* T - Title -* U - Username -* P - Password -* A - URL -* N - Notes -* I - UUID (found on entry properties page) -* O - Custom Attribute _(SEARCH_IN only)_ +* T – Title +* U – Username +* P – Password +* A – URL +* N – Notes +* I – UUID (found on entry properties page) +* O – Custom Attribute _(SEARCH_IN only)_ Examples: + `{REF:U@I:033054D445C648C59092CC1D661B1B71}` + diff --git a/docs/topics/SSHAgent.adoc b/docs/topics/SSHAgent.adoc index e47ffa506..5539e0e67 100644 --- a/docs/topics/SSHAgent.adoc +++ b/docs/topics/SSHAgent.adoc @@ -1,4 +1,4 @@ -= KeePassXC - SSH Agent integration += KeePassXC – SSH Agent integration include::.sharedheader[] :imagesdir: ../images diff --git a/docs/topics/UserInterface.adoc b/docs/topics/UserInterface.adoc index c61dc85a8..dc7908e56 100644 --- a/docs/topics/UserInterface.adoc +++ b/docs/topics/UserInterface.adoc @@ -1,22 +1,22 @@ -= KeePassXC - Database Operations += KeePassXC – Database Operations include::.sharedheader[] :imagesdir: ../images // tag::content[] == Interface Overview === Application Layout -The KeePassXC interface is designed for simplicity and easy access to your information. The main database view is split into three main partitions detailed below. You can open multiple databases at the same time, they will appear in tabs. +The KeePassXC interface is designed for simplicity and easy access to your information. The main database view is split into four main partitions detailed below. You can open multiple databases at the same time, they will appear in tabs. .Main database interface image::main_interface.png[] -*(A) Groups* - Organize your entries into discrete groups to bring order to all of your sensitive information. Groups can be nested under each other to create a hierarchy. Settings from parent groups get applied to their children. You can hide this panel on the View menu. +*(A) Groups* – Organize your entries into discrete groups to bring order to all of your sensitive information. Groups can be nested under each other to create a hierarchy. Settings from parent groups get applied to their children. You can hide this panel on the View menu. -*(B) Tags* - Dynamic groups of entries that can be quickly displayed with one click. Any number of custom tags can be added when editing an entry. This panel also includes useful pre-defined searches, such as finding expired and weak passwords. +*(B) Tags* – Dynamic groups of entries that can be quickly displayed with one click. Any number of custom tags can be added when editing an entry. This panel also includes useful pre-defined searches, such as finding expired and weak passwords. -*\(C) Entries* - Entries contain all the information you want to store for a website or application you are storing in KeePassXC. This view shows all the entries in the selected group. Each column can be resized, reordered, and shown or hidden based on your preference. Right-click the header row to see all available options. +*\(C) Entries* – Entries contain all the information you want to store for a website or application you are storing in KeePassXC. This view shows all the entries in the selected group. Each column can be resized, reordered, and shown or hidden based on your preference. Right-click the header row to see all available options. -*(D) Preview* - Shows a preview of the selected group or entry. You can temporarily hide this preview using the close button on the right hand side or completely disabled in the application settings. +*(D) Preview* – Shows a preview of the selected group or entry. You can temporarily hide this preview using the close button on the right hand side or completely disabled in the application settings. TIP: You can enable double-click copying of entry username and password in the Application Security Settings. This is turned off by default starting with version 2.7.0. @@ -26,10 +26,10 @@ The toolbar provides a quick way to perform common tasks with your database. Som .Toolbar overview image::toolbar.png[] -*(A) Database* - Open Database, Save Database, Lock Database + -*(B) Entries* - Create Entry, Edit Entry, Delete Selected Entries + -*\(C) Entry Data* - Copy Username, Copy Password, Copy URL, Perform Auto-Type + -*(D) Tools* - Password Generator, Application Settings + +*(A) Database* – Open Database, Save Database, Lock Database + +*(B) Entries* – Create Entry, Edit Entry, Delete Selected Entries + +*\(C) Entry Data* – Copy Username, Copy Password, Copy URL, Perform Auto-Type + +*(D) Tools* – Password Generator, Application Settings + *(E) Search* === Application Settings @@ -59,7 +59,7 @@ You can use the following command line options to tailor the application to your ---- Usage: keepassxc.exe [options] [filename(s)] -KeePassXC - cross-platform password manager +KeePassXC – cross-platform password manager Options: -?, -h, --help Displays help on commandline options. diff --git a/docs/topics/Welcome.adoc b/docs/topics/Welcome.adoc index 4eb168e6c..ec44b6e53 100644 --- a/docs/topics/Welcome.adoc +++ b/docs/topics/Welcome.adoc @@ -1,4 +1,4 @@ -= KeePassXC - Welcome += KeePassXC – Welcome include::.sharedheader[] :imagesdir: ../images @@ -9,7 +9,7 @@ KeePassXC is a modern, secure, and open-source password manager that stores and KeePassXC is for people with extremely high demands of secure personal data management. It saves many different types of information, such as usernames, passwords, URLs, attachments, and notes in an offline, encrypted file that can be stored in any location, including private and public cloud solutions. For easy identification and management, user-defined titles and icons can be specified for entries. In addition, entries are sorted in customizable groups. An integrated search function allows you to use advanced patterns to easily find any entry in your database. A customizable, fast, and easy-to-use password generator utility allows you to create passwords with any combination of characters or easy to remember passphrases. === Overview -You can store an unlimited number of passwords and information in a KeePassXC database. Every piece of information you store in your database is encrypted at all times within the `kdbx` file. When you are accessing your database from within KeePassXC, your information in decrypted and stored in your computer's memory. KeePassXC places controls over the access to this data so other applications cannot read it (unless they have administrative rights). The interface is designed to let you quickly access your passwords, search for the right entry, perform Auto-Type or copy/paste operations, make and save changes, and then get out of your way. +You can store an unlimited number of passwords and information in a KeePassXC database. Every piece of information you store in your database is encrypted at all times within the `kdbx` file. When you are accessing your database from within KeePassXC, your information is decrypted and stored in your computer's memory. KeePassXC places controls over the access to this data so other applications cannot read it (unless they have administrative rights). The interface is designed to let you quickly access your passwords, search for the right entry, perform Auto-Type or copy/paste operations, make and save changes, and then get out of your way. KeePassXC ships with light and dark themes specifically designed to meet accessibility standards. In most cases, the appropriate theme for your system will be determined automatically, but you can always set a specific theme in the application settings. @@ -45,4 +45,4 @@ KeePassXC has numerous features for novice and power users alike. This guide wil ** Additional encryption choices: Twofish and ChaCha20 // end::content[] // tag::advanced[] -// end::advanced[] \ No newline at end of file +// end::advanced[] diff --git a/release-tool b/release-tool index 920edba06..0f43ec632 100755 --- a/release-tool +++ b/release-tool @@ -1411,8 +1411,8 @@ i18n() { if ! command -v $LUPDATE > /dev/null; then LUPDATE=lupdate fi - $LUPDATE -no-ui-lines -disable-heuristic similartext -locations none -no-obsolete src \ - -ts share/translations/keepassxc_en.ts $@ + $LUPDATE -no-ui-lines -disable-heuristic similartext -locations none -extensions c,cpp,h,js,mm,qrc,ui \ + -no-obsolete src -ts share/translations/keepassxc_en.ts $@ return 0 fi diff --git a/release-tool.ps1 b/release-tool.ps1 index 76bb15790..1864258c4 100644 --- a/release-tool.ps1 +++ b/release-tool.ps1 @@ -284,7 +284,7 @@ if ($Merge) { # Update translation files Write-Host "Updating source translation file..." Invoke-Cmd "lupdate" "-no-ui-lines -disable-heuristic similartext -locations none", ` - "-no-obsolete ./src -ts share/translations/keepassxc_en.ts" + "-extensions c,cpp,h,js,mm,qrc,ui -no-obsolete ./src -ts share/translations/keepassxc_en.ts" Write-Host "Pulling updated translations from Transifex..." Invoke-Cmd "tx" "pull -af --minimum-perc=60 --parallel -r keepassxc.share-translations-keepassxc-en-ts--develop" diff --git a/share/linux/org.keepassxc.KeePassXC.appdata.xml b/share/linux/org.keepassxc.KeePassXC.appdata.xml index c899a6601..e51d6acac 100644 --- a/share/linux/org.keepassxc.KeePassXC.appdata.xml +++ b/share/linux/org.keepassxc.KeePassXC.appdata.xml @@ -941,7 +941,7 @@
  • Compare window title to entry URLs [#556]
  • Implemented inline error messages [#162]
  • Ignore group expansion and other minor changes when making database "dirty" [#464]
  • -
  • Updated license and copyright information on souce files [#632]
  • +
  • Updated license and copyright information on source files [#632]
  • Added contributors list to about dialog [#629]
  • diff --git a/share/linux/org.keepassxc.KeePassXC.desktop.in b/share/linux/org.keepassxc.KeePassXC.desktop.in index eef24fe7f..bf633727a 100644 --- a/share/linux/org.keepassxc.KeePassXC.desktop.in +++ b/share/linux/org.keepassxc.KeePassXC.desktop.in @@ -42,6 +42,8 @@ StartupWMClass=keepassxc StartupNotify=true Terminal=false Type=Application -Version=1.0 +Version=1.5 Categories=Utility;Security;Qt; MimeType=application/x-keepass2; +SingleMainWindow=true +X-GNOME-SingleWindow=true diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index a526851ec..927492641 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -892,52 +892,6 @@ Do you want to delete the entry? - - Converting attributes to custom data… - - - - Abort - - - - KeePassXC: Converted KeePassHTTP attributes - - - - Successfully converted attributes from %1 entry(s). -Moved %2 keys to custom data. - - - - Successfully moved %n keys to custom data. - - - - - - - KeePassXC: No entry with KeePassHTTP attributes found! - - - - The active database does not contain an entry with KeePassHTTP attributes. - - - - Don't show this warning again - - - - KeePassXC: Legacy browser integration settings detected - - - - Your KeePassXC-Browser settings need to be moved into the database settings. -This is necessary to maintain your current browser connections. -Would you like to migrate your existing settings now? - - BrowserSettingsWidget @@ -1597,6 +1551,10 @@ If you do not have a key file, please leave the field empty. <p>Click for more information…</p> + + authenticate to access the database + + DatabaseSettingWidgetMetaData @@ -1642,14 +1600,6 @@ If you do not have a key file, please leave the field empty. KeePassXC-Browser settings - - Convert KeePassHTTP data - - - - Convert legacy KeePassHTTP attributes to KeePassXC-Browser compatible custom data - - Refresh database root group ID @@ -1759,15 +1709,6 @@ Permissions to access entries will be revoked. The active database does not contain an entry with permissions. - - Move KeePassHTTP attributes to custom data - - - - Do you really want to convert all legacy browser integration data to the latest standard? -This is necessary to maintain compatibility with the browser plugin. - - Refresh database ID @@ -3084,10 +3025,6 @@ Would you like to correct it? EditGroupWidgetBrowser - - Edit Group - - These settings affect to the group's behaviour with the browser extension. @@ -5200,10 +5137,6 @@ Are you sure you want to continue with this file? Copy title to clipboard - - &URL - - Copy URL to clipboard @@ -5458,6 +5391,10 @@ We recommend you use the AppImage available on our downloads page. XML File… + + Copy &URL + + ManageDatabase @@ -5827,6 +5764,10 @@ We recommend you use the AppImage available on our downloads page. Unexpected EOF when writing private key + + AES-256/GCM is currently not supported + + PasswordEditWidget @@ -7924,6 +7865,10 @@ Kernel: %3 %4 This options is deprecated, use --set-key-file instead. + + KeePassXC is not running. No open database to lock + + Password is %1 old diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b0bd3e0ab..3a589842d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -532,5 +532,5 @@ if(WIN32) endif() # The install commands in this subdirectory will be executed after all the install commands in the -# current scope are ran. It is required for correct functtioning of macdeployqt. +# current scope are ran. It is required for correct functioning of macdeployqt. add_subdirectory(post_install) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 750053955..c39a13201 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -225,7 +225,7 @@ void AutoType::createTestInstance() QStringList AutoType::windowTitles() { if (!m_plugin) { - return QStringList(); + return {}; } return m_plugin->windowTitles(); @@ -356,7 +356,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, /** * Single Autotype entry-point function - * Look up the Auto-Type sequence for the given entry then perfom Auto-Type in the active window + * Look up the Auto-Type sequence for the given entry then perform Auto-Type in the active window */ void AutoType::performAutoType(const Entry* entry) { @@ -372,7 +372,7 @@ void AutoType::performAutoType(const Entry* entry) /** * Extra Autotype entry-point function - * Perfom Auto-Type of the directly specified sequence in the active window + * Perform Auto-Type of the directly specified sequence in the active window */ void AutoType::performAutoTypeWithSequence(const Entry* entry, const QString& sequence) { diff --git a/src/autotype/AutoTypeAction.h b/src/autotype/AutoTypeAction.h index 082d0aea7..f68917f8f 100644 --- a/src/autotype/AutoTypeAction.h +++ b/src/autotype/AutoTypeAction.h @@ -38,17 +38,17 @@ public: static Result Ok() { - return Result(true, false, QString()); + return {true, false, QString()}; } static Result Retry(const QString& error) { - return Result(false, true, error); + return {false, true, error}; } static Result Failed(const QString& error) { - return Result(false, false, error); + return {false, false, error}; } bool isOk() const diff --git a/src/autotype/AutoTypePlatformPlugin.h b/src/autotype/AutoTypePlatformPlugin.h index 7154dcdd7..1e1e7b846 100644 --- a/src/autotype/AutoTypePlatformPlugin.h +++ b/src/autotype/AutoTypePlatformPlugin.h @@ -25,9 +25,7 @@ class AutoTypePlatformInterface { public: - virtual ~AutoTypePlatformInterface() - { - } + virtual ~AutoTypePlatformInterface() = default; virtual bool isAvailable() = 0; virtual QStringList windowTitles() = 0; virtual WId activeWindow() = 0; diff --git a/src/autotype/AutoTypeSelectDialog.cpp b/src/autotype/AutoTypeSelectDialog.cpp index 38c1ac58c..5e5d20c3a 100644 --- a/src/autotype/AutoTypeSelectDialog.cpp +++ b/src/autotype/AutoTypeSelectDialog.cpp @@ -92,9 +92,7 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) } // Required for QScopedPointer -AutoTypeSelectDialog::~AutoTypeSelectDialog() -{ -} +AutoTypeSelectDialog::~AutoTypeSelectDialog() = default; void AutoTypeSelectDialog::setMatches(const QList& matches, const QList>& dbs, @@ -326,7 +324,7 @@ void AutoTypeSelectDialog::buildActionMenu() submitAutoTypeMatch(match); }); -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) || defined(Q_OS_MAC) auto typeVirtualAction = new QAction(icons()->icon("auto-type"), tr("Use Virtual Keyboard")); m_actionMenu->insertAction(copyUsernameAction, typeVirtualAction); typeVirtualAction->setShortcut(Qt::CTRL + Qt::Key_4); @@ -342,7 +340,7 @@ void AutoTypeSelectDialog::buildActionMenu() typeUsernameAction->setShortcutVisibleInContextMenu(true); typePasswordAction->setShortcutVisibleInContextMenu(true); typeTotpAction->setShortcutVisibleInContextMenu(true); -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) || defined(Q_OS_MAC) typeVirtualAction->setShortcutVisibleInContextMenu(true); #endif #endif diff --git a/src/autotype/mac/AutoTypeMac.cpp b/src/autotype/mac/AutoTypeMac.cpp index eb6e4f774..f3f5c6594 100644 --- a/src/autotype/mac/AutoTypeMac.cpp +++ b/src/autotype/mac/AutoTypeMac.cpp @@ -250,6 +250,10 @@ AutoTypeAction::Result AutoTypeExecutorMac::execType(const AutoTypeKey* action) int ch = action->character.toUpper().toLatin1(); m_platform->sendKey(static_cast(ch), true, action->modifiers); m_platform->sendKey(static_cast(ch), false, action->modifiers); + } else if (mode == Mode::VIRTUAL) { + int ch = action->character.toLatin1(); + m_platform->sendKey(static_cast(ch), true, action->modifiers); + m_platform->sendKey(static_cast(ch), false, action->modifiers); } else { m_platform->sendChar(action->character, true); m_platform->sendChar(action->character, false); diff --git a/src/autotype/test/AutoTypeTest.cpp b/src/autotype/test/AutoTypeTest.cpp index 69c71a53c..641b9502a 100644 --- a/src/autotype/test/AutoTypeTest.cpp +++ b/src/autotype/test/AutoTypeTest.cpp @@ -29,7 +29,7 @@ QString AutoTypePlatformTest::keyToString(Qt::Key key) QStringList AutoTypePlatformTest::windowTitles() { - return QStringList(); + return {}; } WId AutoTypePlatformTest::activeWindow() diff --git a/src/autotype/test/AutoTypeTestInterface.h b/src/autotype/test/AutoTypeTestInterface.h index 7681f2ecb..8b1b7f9ad 100644 --- a/src/autotype/test/AutoTypeTestInterface.h +++ b/src/autotype/test/AutoTypeTestInterface.h @@ -23,9 +23,7 @@ class AutoTypeTestInterface { public: - virtual ~AutoTypeTestInterface() - { - } + virtual ~AutoTypeTestInterface() = default; virtual void setActiveWindowTitle(const QString& title) = 0; virtual QString actionChars() = 0; diff --git a/src/autotype/xcb/AutoTypeXCB.cpp b/src/autotype/xcb/AutoTypeXCB.cpp index f2b967656..047ef3a95 100644 --- a/src/autotype/xcb/AutoTypeXCB.cpp +++ b/src/autotype/xcb/AutoTypeXCB.cpp @@ -184,17 +184,17 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist) if (useBlacklist && !title.isEmpty()) { if (window == m_rootWindow) { - return QString(); + return {}; } QString className = windowClassName(window); if (m_classBlacklist.contains(className)) { - return QString(); + return {}; } QList keepassxWindows = widgetsToX11Windows(QApplication::topLevelWidgets()); if (keepassxWindows.contains(window)) { - return QString(); + return {}; } } diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index 2953cf582..f054f75b9 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -1,6 +1,7 @@ /* - * Copyright (C) 2013 Francois Ferrand * Copyright (C) 2022 KeePassXC Team + * Copyright (C) 2017 Sami Vänttinen + * Copyright (C) 2013 Francois Ferrand * * 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 @@ -781,79 +782,6 @@ BrowserService::searchEntries(const QString& siteUrl, const QString& formUrl, co return entries; } -void BrowserService::convertAttributesToCustomData(QSharedPointer db) -{ - if (!db) { - return; - } - - QList entries = db->rootGroup()->entriesRecursive(); - QProgressDialog progress(tr("Converting attributes to custom data…"), tr("Abort"), 0, entries.count()); - progress.setWindowModality(Qt::WindowModal); - - int counter = 0; - int keyCounter = 0; - for (auto* entry : entries) { - if (progress.wasCanceled()) { - return; - } - - if (moveSettingsToCustomData(entry, KEEPASSHTTP_NAME)) { - ++counter; - } - - if (moveSettingsToCustomData(entry, KEEPASSXCBROWSER_OLD_NAME)) { - ++counter; - } - - if (moveSettingsToCustomData(entry, KEEPASSXCBROWSER_NAME)) { - ++counter; - } - - if (entry->title() == KEEPASSHTTP_NAME || entry->title().contains(KEEPASSXCBROWSER_NAME, Qt::CaseInsensitive)) { - keyCounter += moveKeysToCustomData(entry, db); - db->recycleEntry(entry); - } - - progress.setValue(progress.value() + 1); - } - progress.reset(); - - if (counter > 0) { - MessageBox::information(nullptr, - tr("KeePassXC: Converted KeePassHTTP attributes"), - tr("Successfully converted attributes from %1 entry(s).\n" - "Moved %2 keys to custom data.", - "") - .arg(counter) - .arg(keyCounter), - MessageBox::Ok); - } else if (counter == 0 && keyCounter > 0) { - MessageBox::information(nullptr, - tr("KeePassXC: Converted KeePassHTTP attributes"), - tr("Successfully moved %n keys to custom data.", "", keyCounter), - MessageBox::Ok); - } else { - MessageBox::information(nullptr, - tr("KeePassXC: No entry with KeePassHTTP attributes found!"), - tr("The active database does not contain an entry with KeePassHTTP attributes."), - MessageBox::Ok); - } - - // Rename password groupName - Group* rootGroup = db->rootGroup(); - if (!rootGroup) { - return; - } - - for (auto* g : rootGroup->groupsRecursive(true)) { - if (g->name() == KEEPASSHTTP_GROUP_NAME) { - g->setName(KEEPASSXCBROWSER_GROUP_NAME); - break; - } - } -} - void BrowserService::requestGlobalAutoType(const QString& search) { emit osUtils->globalShortcutTriggered("autotype", search); @@ -1264,84 +1192,6 @@ QSharedPointer BrowserService::selectedDatabase() return getDatabase(); } -bool BrowserService::moveSettingsToCustomData(Entry* entry, const QString& name) -{ - if (entry->attributes()->contains(name)) { - QString attr = entry->attributes()->value(name); - entry->beginUpdate(); - if (!attr.isEmpty()) { - entry->customData()->set(KEEPASSXCBROWSER_NAME, attr); - } - entry->attributes()->remove(name); - entry->endUpdate(); - return true; - } - return false; -} - -int BrowserService::moveKeysToCustomData(Entry* entry, QSharedPointer db) -{ - int keyCounter = 0; - for (const auto& key : entry->attributes()->keys()) { - if (key.contains(CustomData::BrowserLegacyKeyPrefix)) { - QString publicKey = key; - publicKey.remove(CustomData::BrowserLegacyKeyPrefix); - - // Add key to database custom data - if (db && !db->metadata()->customData()->contains(CustomData::BrowserKeyPrefix + publicKey)) { - db->metadata()->customData()->set(CustomData::BrowserKeyPrefix + publicKey, - entry->attributes()->value(key)); - ++keyCounter; - } - } - } - - return keyCounter; -} - -bool BrowserService::checkLegacySettings(QSharedPointer db) -{ - if (!db || !browserSettings()->isEnabled() || browserSettings()->noMigrationPrompt()) { - return false; - } - - bool legacySettingsFound = false; - QList entries = db->rootGroup()->entriesRecursive(); - for (const auto& e : entries) { - if (e->isRecycled()) { - continue; - } - - if ((e->attributes()->contains(KEEPASSHTTP_NAME) || e->attributes()->contains(KEEPASSXCBROWSER_NAME)) - || (e->title() == KEEPASSHTTP_NAME || e->title().contains(KEEPASSXCBROWSER_NAME, Qt::CaseInsensitive))) { - legacySettingsFound = true; - break; - } - } - - if (!legacySettingsFound) { - return false; - } - - auto* checkbox = new QCheckBox(tr("Don't show this warning again")); - QObject::connect(checkbox, &QCheckBox::stateChanged, [&](int state) { - browserSettings()->setNoMigrationPrompt(static_cast(state) == Qt::CheckState::Checked); - }); - - auto dialogResult = - MessageBox::warning(nullptr, - tr("KeePassXC: Legacy browser integration settings detected"), - tr("Your KeePassXC-Browser settings need to be moved into the database settings.\n" - "This is necessary to maintain your current browser connections.\n" - "Would you like to migrate your existing settings now?"), - MessageBox::Yes | MessageBox::No, - MessageBox::NoButton, - MessageBox::Raise, - checkbox); - - return dialogResult == MessageBox::Yes; -} - QStringList BrowserService::getEntryURLs(const Entry* entry) { QStringList urlList; @@ -1440,11 +1290,6 @@ void BrowserService::databaseUnlocked(DatabaseWidget* dbWidget) QJsonObject msg; msg["action"] = QString("database-unlocked"); m_browserHost->broadcastClientMessage(msg); - - auto db = dbWidget->database(); - if (checkLegacySettings(db)) { - convertAttributesToCustomData(db); - } } } diff --git a/src/browser/BrowserService.h b/src/browser/BrowserService.h index b9e153248..c9fc83b75 100644 --- a/src/browser/BrowserService.h +++ b/src/browser/BrowserService.h @@ -1,6 +1,7 @@ /* - * Copyright (C) 2013 Francois Ferrand * Copyright (C) 2022 KeePassXC Team + * Copyright (C) 2017 Sami Vänttinen + * Copyright (C) 2013 Francois Ferrand * * 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 @@ -88,7 +89,6 @@ public: const StringPairList& keyList, const bool httpAuth = false); void requestGlobalAutoType(const QString& search); - static void convertAttributesToCustomData(QSharedPointer db); static const QString KEEPASSXCBROWSER_NAME; static const QString KEEPASSXCBROWSER_OLD_NAME; @@ -157,16 +157,11 @@ private: QSharedPointer selectedDatabase(); QString getDatabaseRootUuid(); QString getDatabaseRecycleBinUuid(); - bool checkLegacySettings(QSharedPointer db); QStringList getEntryURLs(const Entry* entry); void hideWindow() const; void raiseWindow(const bool force = false); - void updateWindowState(); - static bool moveSettingsToCustomData(Entry* entry, const QString& name); - static int moveKeysToCustomData(Entry* entry, QSharedPointer db); - QPointer m_browserHost; QHash> m_browserClients; diff --git a/src/browser/NativeMessageInstaller.cpp b/src/browser/NativeMessageInstaller.cpp index f4876f4e8..2d5054ec9 100644 --- a/src/browser/NativeMessageInstaller.cpp +++ b/src/browser/NativeMessageInstaller.cpp @@ -225,7 +225,7 @@ QString NativeMessageInstaller::getNativeMessagePath(SupportedBrowsers browser) } else { basePath = QDir::homePath() + "/.config"; } -#elif defined(Q_OS_LINUX) +#elif defined(Q_OS_LINUX) || (defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)) if (browser == SupportedBrowsers::TOR_BROWSER) { basePath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); } else if (browser == SupportedBrowsers::FIREFOX) { diff --git a/src/cli/AddGroup.cpp b/src/cli/AddGroup.cpp index d323ecff8..762afa80f 100644 --- a/src/cli/AddGroup.cpp +++ b/src/cli/AddGroup.cpp @@ -29,9 +29,7 @@ AddGroup::AddGroup() positionalArguments.append({QString("group"), QObject::tr("Path of the group to add."), QString("")}); } -AddGroup::~AddGroup() -{ -} +AddGroup::~AddGroup() = default; int AddGroup::executeWithDatabase(QSharedPointer database, QSharedPointer parser) { diff --git a/src/cli/Command.cpp b/src/cli/Command.cpp index 4bba8fff9..f138fb5c8 100644 --- a/src/cli/Command.cpp +++ b/src/cli/Command.cpp @@ -103,9 +103,7 @@ Command::Command() options.append(Command::QuietOption); } -Command::~Command() -{ -} +Command::~Command() = default; QString Command::getDescriptionLine() { diff --git a/src/cli/DatabaseCreate.cpp b/src/cli/DatabaseCreate.cpp index 10b424825..c2444645b 100644 --- a/src/cli/DatabaseCreate.cpp +++ b/src/cli/DatabaseCreate.cpp @@ -149,7 +149,7 @@ QSharedPointer DatabaseCreate::initializeDatabaseFromOptions(const QSh * If a key file is specified but it can't be loaded, the function will * fail. * - * If the database is being saved in a non existant directory, the + * If the database is being saved in a non existent directory, the * function will fail. * * @return EXIT_SUCCESS on success, or EXIT_FAILURE on failure diff --git a/src/cli/Generate.cpp b/src/cli/Generate.cpp index 980e9fa14..1f6ceff5d 100644 --- a/src/cli/Generate.cpp +++ b/src/cli/Generate.cpp @@ -93,7 +93,7 @@ QSharedPointer Generate::createGenerator(QSharedPointersetLength(PasswordGenerator::DefaultLength); } else if (passwordLength.toInt() <= 0) { err << QObject::tr("Invalid password length %1").arg(passwordLength) << endl; - return QSharedPointer(nullptr); + return {}; } else { passwordGenerator->setLength(passwordLength.toInt()); } @@ -139,7 +139,7 @@ QSharedPointer Generate::createGenerator(QSharedPointerisValid()) { err << QObject::tr("Invalid password generator after applying all options") << endl; - return QSharedPointer(nullptr); + return {}; } return passwordGenerator; diff --git a/src/cli/Import.cpp b/src/cli/Import.cpp index cc74df767..a9d7a5a2f 100644 --- a/src/cli/Import.cpp +++ b/src/cli/Import.cpp @@ -28,7 +28,7 @@ * A password can be specified to encrypt the database. * If none is specified the function will fail. * - * If the database is being saved in a non existant directory, the + * If the database is being saved in a non existent directory, the * function will fail. * * @return EXIT_SUCCESS on success, or EXIT_FAILURE on failure diff --git a/src/cli/Move.cpp b/src/cli/Move.cpp index a9ee78614..8cdf96eb9 100644 --- a/src/cli/Move.cpp +++ b/src/cli/Move.cpp @@ -30,9 +30,7 @@ Move::Move() positionalArguments.append({QString("group"), QObject::tr("Path of the destination group."), QString("")}); } -Move::~Move() -{ -} +Move::~Move() = default; int Move::executeWithDatabase(QSharedPointer database, QSharedPointer parser) { diff --git a/src/cli/RemoveGroup.cpp b/src/cli/RemoveGroup.cpp index 6455af496..15bb01c29 100644 --- a/src/cli/RemoveGroup.cpp +++ b/src/cli/RemoveGroup.cpp @@ -30,9 +30,7 @@ RemoveGroup::RemoveGroup() positionalArguments.append({QString("group"), QObject::tr("Path of the group to remove."), QString("")}); } -RemoveGroup::~RemoveGroup() -{ -} +RemoveGroup::~RemoveGroup() = default; int RemoveGroup::executeWithDatabase(QSharedPointer database, QSharedPointer parser) { diff --git a/src/cli/Utils.cpp b/src/cli/Utils.cpp index d8134de26..bca837db8 100644 --- a/src/cli/Utils.cpp +++ b/src/cli/Utils.cpp @@ -384,7 +384,7 @@ namespace Utils if (fieldName == TagsFieldName) { return entry->tags(); } - return QString(""); + return ""; } QStringList findAttributes(const EntryAttributes& attributes, const QString& name) @@ -413,7 +413,7 @@ namespace Utils * * @param path Path to the key file to be loaded * @param fileKey Resulting fileKey - * @return true if the key file was loaded succesfully + * @return true if the key file was loaded successfully */ bool loadFileKey(const QString& path, QSharedPointer& fileKey) { diff --git a/src/core/AsyncTask.h b/src/core/AsyncTask.h index 581865419..244d0ff92 100644 --- a/src/core/AsyncTask.h +++ b/src/core/AsyncTask.h @@ -64,7 +64,7 @@ namespace AsyncTask * * @param task std::function object to run * @param context QObject responsible for calling this function - * @param callback std::function object to run after the task completess + * @param callback std::function object to run after the task completes */ template void runThenCallback(FunctionObject task, QObject* context, FunctionObject2 callback) diff --git a/src/core/Base32.cpp b/src/core/Base32.cpp index 05841121a..d0a148eec 100644 --- a/src/core/Base32.cpp +++ b/src/core/Base32.cpp @@ -50,7 +50,7 @@ QVariant Base32::decode(const QByteArray& encodedData) } if (encodedData.size() % 8 != 0) { - return QVariant(); + return {}; } int nPads = 0; @@ -119,7 +119,7 @@ QVariant Base32::decode(const QByteArray& encodedData) continue; } else { // illegal character - return QVariant(); + return {}; } } } @@ -145,7 +145,7 @@ QVariant Base32::decode(const QByteArray& encodedData) QByteArray Base32::encode(const QByteArray& data) { if (data.size() < 1) { - return QByteArray(); + return {}; } const int nBits = data.size() * 8; diff --git a/src/core/Clock.cpp b/src/core/Clock.cpp index 5704d4bff..fcab4d2ae 100644 --- a/src/core/Clock.cpp +++ b/src/core/Clock.cpp @@ -50,12 +50,12 @@ QDateTime Clock::serialized(const QDateTime& dateTime) QDateTime Clock::datetimeUtc(int year, int month, int day, int hour, int min, int second) { - return QDateTime(QDate(year, month, day), QTime(hour, min, second), Qt::UTC); + return {QDate(year, month, day), QTime(hour, min, second), Qt::UTC}; } QDateTime Clock::datetime(int year, int month, int day, int hour, int min, int second) { - return QDateTime(QDate(year, month, day), QTime(hour, min, second), Qt::LocalTime); + return {QDate(year, month, day), QTime(hour, min, second), Qt::LocalTime}; } QDateTime Clock::datetimeUtc(qint64 msecSinceEpoch) @@ -78,13 +78,9 @@ QDateTime Clock::parse(const QString& text, const QString& format) return QDateTime::fromString(text, format); } -Clock::~Clock() -{ -} +Clock::~Clock() = default; -Clock::Clock() -{ -} +Clock::Clock() = default; QDateTime Clock::currentDateTimeUtcImpl() const { diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 44896bc1c..5811b2e25 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -454,9 +454,7 @@ Config::Config(QObject* parent) init(configFiles.first, configFiles.second); } -Config::~Config() -{ -} +Config::~Config() = default; void Config::init(const QString& configFileName, const QString& localConfigFileName) { diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 508cbe51c..5ba2ab367 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -275,8 +275,8 @@ bool Database::saveAs(const QString& filePath, SaveAction action, const QString& bool isNewFile = !QFile::exists(realFilePath); bool ok = AsyncTask::runAndWaitForFuture([&] { return performSave(realFilePath, action, backupFilePath, error); }); if (ok) { - markAsClean(); setFilePath(filePath); + markAsClean(); if (isNewFile) { QFile::setPermissions(realFilePath, QFile::ReadUser | QFile::WriteUser); } @@ -346,7 +346,7 @@ bool Database::performSave(const QString& filePath, SaveAction action, const QSt tempFile.setAutoRemove(false); QFile::setPermissions(filePath, perms); #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - // Retain orginal creation time + // Retain original creation time tempFile.setFileTime(createTime, QFile::FileBirthTime); #endif return true; diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 48fd6a769..251e18631 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -1236,7 +1236,7 @@ QString Entry::referenceFieldValue(EntryReferenceType referenceType) const default: break; } - return QString(); + return {}; } void Entry::moveUp() @@ -1353,7 +1353,7 @@ QString Entry::resolvePlaceholder(const QString& placeholder) const QString Entry::resolveUrlPlaceholder(const QString& str, Entry::PlaceholderType placeholderType) const { if (str.isEmpty()) { - return QString(); + return {}; } const QUrl qurl(str); @@ -1384,7 +1384,7 @@ QString Entry::resolveUrlPlaceholder(const QString& str, Entry::PlaceholderType } } - return QString(); + return {}; } Entry::PlaceholderType Entry::placeholderType(const QString& placeholder) const @@ -1456,7 +1456,7 @@ QString Entry::resolveUrl(const QString& url) const } // No URL in this command - return QString(""); + return {}; } if (!newUrl.isEmpty() && !newUrl.contains("://")) { diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 273ada2cb..f9aa9d142 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -166,7 +166,7 @@ QString Group::effectiveAutoTypeSequence() const const Group* group = this; do { if (group->autoTypeEnabled() == Group::Disable) { - return QString(); + return {}; } sequence = group->defaultAutoTypeSequence(); diff --git a/src/core/Group.h b/src/core/Group.h index 4d1ddfd83..4e7f7cb0c 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -43,7 +43,7 @@ public: KeepLocal, // merge history forcing local as top regardless of age KeepRemote, // merge history forcing remote as top regardless of age KeepNewer, // merge history - Synchronize, // merge history keeping most recent as top entry and appling deletions + Synchronize, // merge history keeping most recent as top entry and applying deletions }; enum CloneFlag diff --git a/src/core/PassphraseGenerator.cpp b/src/core/PassphraseGenerator.cpp index ef1d867e2..79227817e 100644 --- a/src/core/PassphraseGenerator.cpp +++ b/src/core/PassphraseGenerator.cpp @@ -116,7 +116,7 @@ QString PassphraseGenerator::generatePassphrase() const // In case there was an error loading the wordlist if (m_wordlist.length() == 0) { - return QString(); + return {}; } QStringList words; diff --git a/src/core/SignalMultiplexer.cpp b/src/core/SignalMultiplexer.cpp index d1ed89e30..99f7fab15 100644 --- a/src/core/SignalMultiplexer.cpp +++ b/src/core/SignalMultiplexer.cpp @@ -19,9 +19,7 @@ #include "core/Global.h" -SignalMultiplexer::SignalMultiplexer() -{ -} +SignalMultiplexer::SignalMultiplexer() = default; SignalMultiplexer::~SignalMultiplexer() { diff --git a/src/core/TimeDelta.cpp b/src/core/TimeDelta.cpp index 0037396f6..94cea03c8 100644 --- a/src/core/TimeDelta.cpp +++ b/src/core/TimeDelta.cpp @@ -29,22 +29,22 @@ QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta) TimeDelta TimeDelta::fromHours(int hours) { - return TimeDelta(hours, 0, 0, 0); + return {hours, 0, 0, 0}; } TimeDelta TimeDelta::fromDays(int days) { - return TimeDelta(0, days, 0, 0); + return {0, days, 0, 0}; } TimeDelta TimeDelta::fromMonths(int months) { - return TimeDelta(0, 0, months, 0); + return {0, 0, months, 0}; } TimeDelta TimeDelta::fromYears(int years) { - return TimeDelta(0, 0, 0, years); + return {0, 0, 0, years}; } TimeDelta::TimeDelta() diff --git a/src/crypto/CryptoHash.cpp b/src/crypto/CryptoHash.cpp index 5177bb86f..a1dc6595e 100644 --- a/src/crypto/CryptoHash.cpp +++ b/src/crypto/CryptoHash.cpp @@ -106,7 +106,7 @@ QByteArray CryptoHash::result() const } else if (d->hashFunction) { result = d->hashFunction->final(); } - return QByteArray(reinterpret_cast(result.data()), result.size()); + return {reinterpret_cast(result.data()), int(result.size())}; } QByteArray CryptoHash::hash(const QByteArray& data, Algorithm algo) diff --git a/src/crypto/SymmetricCipher.cpp b/src/crypto/SymmetricCipher.cpp index 4d3a7bdfe..1ed05bb33 100644 --- a/src/crypto/SymmetricCipher.cpp +++ b/src/crypto/SymmetricCipher.cpp @@ -267,3 +267,22 @@ int SymmetricCipher::blockSize(Mode mode) return 0; } } + +int SymmetricCipher::ivSize(Mode mode) +{ + switch (mode) { + case Aes128_CBC: + case Aes256_CBC: + case Aes128_CTR: + case Aes256_CTR: + case Twofish_CBC: + return 16; + case Aes256_GCM: + return 12; + case Salsa20: + case ChaCha20: + return 8; + default: + return 0; + } +} diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h index 83b54658f..e18f623f3 100644 --- a/src/crypto/SymmetricCipher.h +++ b/src/crypto/SymmetricCipher.h @@ -70,6 +70,7 @@ public: static int defaultIvSize(Mode mode); static int keySize(Mode mode); static int blockSize(Mode mode); + static int ivSize(Mode mode); private: static QString modeToString(const Mode mode); diff --git a/src/format/KdbxXmlReader.cpp b/src/format/KdbxXmlReader.cpp index e66e12174..eb7fa4158 100644 --- a/src/format/KdbxXmlReader.cpp +++ b/src/format/KdbxXmlReader.cpp @@ -183,7 +183,7 @@ QString KdbxXmlReader::errorString() const .arg(m_xml.lineNumber()) .arg(m_xml.columnNumber()); } - return QString(); + return {}; } bool KdbxXmlReader::isTrueValue(const QStringRef& value) @@ -1117,13 +1117,13 @@ QUuid KdbxXmlReader::readUuid() { QByteArray uuidBin = readBinary(); if (uuidBin.isEmpty()) { - return QUuid(); + return {}; } if (uuidBin.length() != UUID_LENGTH) { if (m_strictMode) { raiseError(tr("Invalid uuid value")); } - return QUuid(); + return {}; } return QUuid::fromRfc4122(uuidBin); } diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp index 993939a44..144e1b473 100644 --- a/src/format/KeePass1Reader.cpp +++ b/src/format/KeePass1Reader.cpp @@ -391,7 +391,7 @@ QByteArray KeePass1Reader::key(const QByteArray& password, const QByteArray& key if (!result) { raiseError(tr("Key transformation failed")); - return QByteArray(); + return {}; } CryptoHash hash(CryptoHash::Sha256); @@ -927,7 +927,7 @@ QDateTime KeePass1Reader::dateFromPackedStruct(const QByteArray& data) // check for the special "never" datetime if (dateTime == QDateTime(QDate(2999, 12, 28), QTime(23, 59, 59), Qt::UTC)) { - return QDateTime(); + return {}; } else { return dateTime; } @@ -943,13 +943,13 @@ bool KeePass1Reader::isMetaStream(const Entry* entry) QByteArray KeePass1Reader::readKeyfile(QIODevice* device) { if (device->size() == 0) { - return QByteArray(); + return {}; } if (device->size() == 32) { QByteArray data = device->read(32); if (data.size() != 32) { - return QByteArray(); + return {}; } return data; @@ -959,7 +959,7 @@ QByteArray KeePass1Reader::readKeyfile(QIODevice* device) QByteArray data = device->read(64); if (data.size() != 64) { - return QByteArray(); + return {}; } if (Tools::isHex(data)) { @@ -974,7 +974,7 @@ QByteArray KeePass1Reader::readKeyfile(QIODevice* device) do { if (!Tools::readFromDevice(device, buffer)) { - return QByteArray(); + return {}; } cryptoHash.addData(buffer); } while (!buffer.isEmpty()); diff --git a/src/format/KeePass2RandomStream.cpp b/src/format/KeePass2RandomStream.cpp index 509e32513..da6df20ad 100644 --- a/src/format/KeePass2RandomStream.cpp +++ b/src/format/KeePass2RandomStream.cpp @@ -50,7 +50,7 @@ QByteArray KeePass2RandomStream::randomBytes(int size, bool* ok) if (m_buffer.size() == m_offset) { if (!loadBlock()) { *ok = false; - return QByteArray(); + return {}; } } @@ -71,7 +71,7 @@ QByteArray KeePass2RandomStream::process(const QByteArray& data, bool* ok) QByteArray randomData = randomBytes(data.size(), &randomBytesOk); if (!randomBytesOk) { *ok = false; - return QByteArray(); + return {}; } QByteArray result; diff --git a/src/format/KeePass2Writer.cpp b/src/format/KeePass2Writer.cpp index 4cf0d4ad6..76e8cacc3 100644 --- a/src/format/KeePass2Writer.cpp +++ b/src/format/KeePass2Writer.cpp @@ -184,7 +184,7 @@ void KeePass2Writer::raiseError(const QString& errorMessage) */ QSharedPointer KeePass2Writer::writer() const { - return QSharedPointer(); + return {}; } /** diff --git a/src/format/OpData01.cpp b/src/format/OpData01.cpp index 3ded0288c..a51ff8fdb 100644 --- a/src/format/OpData01.cpp +++ b/src/format/OpData01.cpp @@ -27,9 +27,7 @@ OpData01::OpData01(QObject* parent) { } -OpData01::~OpData01() -{ -} +OpData01::~OpData01() = default; bool OpData01::decodeBase64(QString const& b64String, const QByteArray& key, const QByteArray& hmacKey) { diff --git a/src/format/OpVaultReader.cpp b/src/format/OpVaultReader.cpp index 201354bce..44f0d85ec 100644 --- a/src/format/OpVaultReader.cpp +++ b/src/format/OpVaultReader.cpp @@ -35,9 +35,7 @@ OpVaultReader::OpVaultReader(QObject* parent) { } -OpVaultReader::~OpVaultReader() -{ -} +OpVaultReader::~OpVaultReader() = default; Database* OpVaultReader::readDatabase(QDir& opdataDir, const QString& password) { @@ -301,11 +299,11 @@ QJsonObject OpVaultReader::readAndAssertJsonFile(QFile& file, const QString& str auto absFilePath = fileInfo.absoluteFilePath(); if (!fileInfo.exists()) { qCritical() << QString("File \"%1\" must exist").arg(absFilePath); - return QJsonObject(); + return {}; } if (!fileInfo.isReadable()) { qCritical() << QString("File \"%1\" must be readable").arg(absFilePath); - return QJsonObject(); + return {}; } if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -331,7 +329,7 @@ QJsonObject OpVaultReader::readAndAssertJsonFile(QFile& file, const QString& str QJsonDocument jDoc = QJsonDocument::fromJson(filePayload, error); if (!jDoc.isObject()) { qCritical() << "Expected " << filePayload << "to be a JSON Object"; - return QJsonObject(); + return {}; } return jDoc.object(); } diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index 00d12c65e..e48fa8c49 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -327,9 +327,7 @@ AboutDialog::AboutDialog(QWidget* parent) m_ui->buttonBox->button(QDialogButtonBox::Close)->setDefault(true); } -AboutDialog::~AboutDialog() -{ -} +AboutDialog::~AboutDialog() = default; void AboutDialog::copyToClipboard() { diff --git a/src/gui/ApplicationSettingsWidget.cpp b/src/gui/ApplicationSettingsWidget.cpp index 7972e8e0c..901afeab9 100644 --- a/src/gui/ApplicationSettingsWidget.cpp +++ b/src/gui/ApplicationSettingsWidget.cpp @@ -175,9 +175,7 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent) m_secUi->quickUnlockCheckBox->setVisible(showQuickUnlock); } -ApplicationSettingsWidget::~ApplicationSettingsWidget() -{ -} +ApplicationSettingsWidget::~ApplicationSettingsWidget() = default; void ApplicationSettingsWidget::addSettingsPage(ISettingsPage* page) { diff --git a/src/gui/ApplicationSettingsWidget.h b/src/gui/ApplicationSettingsWidget.h index e7acb37b7..5c6572173 100644 --- a/src/gui/ApplicationSettingsWidget.h +++ b/src/gui/ApplicationSettingsWidget.h @@ -30,9 +30,7 @@ namespace Ui class ISettingsPage { public: - virtual ~ISettingsPage() - { - } + virtual ~ISettingsPage() = default; virtual QString name() = 0; virtual QIcon icon() = 0; virtual QWidget* createWidget() = 0; diff --git a/src/gui/CategoryListWidget.cpp b/src/gui/CategoryListWidget.cpp index 8da7431b5..cae806f62 100644 --- a/src/gui/CategoryListWidget.cpp +++ b/src/gui/CategoryListWidget.cpp @@ -43,9 +43,7 @@ CategoryListWidget::CategoryListWidget(QWidget* parent) // clang-format on } -CategoryListWidget::~CategoryListWidget() -{ -} +CategoryListWidget::~CategoryListWidget() = default; QSize CategoryListWidget::sizeHint() const { @@ -64,8 +62,8 @@ QSize CategoryListWidget::sizeHint() const QSize CategoryListWidget::minimumSizeHint() const { - return QSize(m_itemDelegate->minWidth() + m_ui->categoryList->frameWidth() * 2, - m_ui->categoryList->sizeHintForRow(0) * 2); + return {m_itemDelegate->minWidth() + m_ui->categoryList->frameWidth() * 2, + m_ui->categoryList->sizeHintForRow(0) * 2}; } int CategoryListWidget::addCategory(const QString& labelText, const QIcon& icon) diff --git a/src/gui/Clipboard.cpp b/src/gui/Clipboard.cpp index 2def33c81..c5ee9c6a0 100644 --- a/src/gui/Clipboard.cpp +++ b/src/gui/Clipboard.cpp @@ -52,24 +52,19 @@ void Clipboard::setText(const QString& text, bool clear) } auto* mime = new QMimeData; -#ifdef Q_OS_MACOS mime->setText(text); +#if defined(Q_OS_MACOS) mime->setData("application/x-nspasteboard-concealed-type", text.toUtf8()); - clipboard->setMimeData(mime, QClipboard::Clipboard); -#else - mime->setText(text); -#ifdef Q_OS_LINUX +#elif defined(Q_OS_UNIX) mime->setData("x-kde-passwordManagerHint", QByteArrayLiteral("secret")); -#endif -#ifdef Q_OS_WIN +#elif defined(Q_OS_WIN) mime->setData("ExcludeClipboardContentFromMonitorProcessing", QByteArrayLiteral("1")); #endif - clipboard->setMimeData(mime, QClipboard::Clipboard); if (clipboard->supportsSelection()) { clipboard->setMimeData(mime, QClipboard::Selection); } -#endif + clipboard->setMimeData(mime, QClipboard::Clipboard); if (clear) { m_lastCopied = text; diff --git a/src/gui/CloneDialog.cpp b/src/gui/CloneDialog.cpp index 8ce368a60..0ce2c5f2e 100644 --- a/src/gui/CloneDialog.cpp +++ b/src/gui/CloneDialog.cpp @@ -61,6 +61,4 @@ void CloneDialog::cloneEntry() close(); } -CloneDialog::~CloneDialog() -{ -} +CloneDialog::~CloneDialog() = default; diff --git a/src/gui/DatabaseOpenDialog.cpp b/src/gui/DatabaseOpenDialog.cpp index e1b9391d0..3eef249f1 100644 --- a/src/gui/DatabaseOpenDialog.cpp +++ b/src/gui/DatabaseOpenDialog.cpp @@ -68,13 +68,13 @@ DatabaseOpenDialog::DatabaseOpenDialog(QWidget* parent) auto* shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageUp, this); shortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(-1); }); - shortcut = new QShortcut(dbTabModifier + Qt::Key_Tab, this); + shortcut = new QShortcut(dbTabModifier + Qt::SHIFT + Qt::Key_Tab, this); shortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(-1); }); shortcut = new QShortcut(Qt::CTRL + Qt::Key_PageDown, this); shortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(1); }); - shortcut = new QShortcut(dbTabModifier + Qt::SHIFT + Qt::Key_Tab, this); + shortcut = new QShortcut(dbTabModifier + Qt::Key_Tab, this); shortcut->setContext(Qt::WidgetWithChildrenShortcut); connect(shortcut, &QShortcut::activated, this, [this]() { selectTabOffset(1); }); } diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index aff418627..882d8d057 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -141,9 +141,7 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) connect(m_ui->resetQuickUnlockButton, &QPushButton::pressed, this, [this] { resetQuickUnlock(); }); } -DatabaseOpenWidget::~DatabaseOpenWidget() -{ -} +DatabaseOpenWidget::~DatabaseOpenWidget() = default; void DatabaseOpenWidget::showEvent(QShowEvent* event) { @@ -538,9 +536,6 @@ bool DatabaseOpenWidget::isOnQuickUnlockScreen() */ void DatabaseOpenWidget::resetQuickUnlock() { - if (!isQuickUnlockAvailable()) { - return; - } #if defined(Q_CC_MSVC) getWindowsHello()->reset(m_filename); #elif defined(Q_OS_MACOS) diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 8d95aaef1..d4e50116f 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -68,9 +68,7 @@ DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) connect(&m_lockDelayTimer, &QTimer::timeout, this, [this] { lockDatabases(); }); } -DatabaseTabWidget::~DatabaseTabWidget() -{ -} +DatabaseTabWidget::~DatabaseTabWidget() = default; void DatabaseTabWidget::toggleTabbar() { @@ -244,6 +242,7 @@ void DatabaseTabWidget::addDatabaseTab(DatabaseWidget* dbWidget, bool inBackgrou SLOT(updateTabName())); connect(dbWidget, SIGNAL(databaseModified()), SLOT(updateTabName())); connect(dbWidget, SIGNAL(databaseSaved()), SLOT(updateTabName())); + connect(dbWidget, SIGNAL(databaseSaved()), SLOT(updateLastDatabases())); connect(dbWidget, SIGNAL(databaseUnlocked()), SLOT(updateTabName())); connect(dbWidget, SIGNAL(databaseUnlocked()), SLOT(emitDatabaseLockChanged())); connect(dbWidget, SIGNAL(databaseLocked()), SLOT(updateTabName())); @@ -331,7 +330,7 @@ void DatabaseTabWidget::importOpVaultDatabase() * Attempt to close the current database and remove its tab afterwards. * * @param index index of the database tab to close - * @return true if database was closed successully + * @return true if database was closed successfully */ bool DatabaseTabWidget::closeCurrentDatabaseTab() { @@ -342,7 +341,7 @@ bool DatabaseTabWidget::closeCurrentDatabaseTab() * Attempt to close the database tab that sent the close request. * * @param index index of the database tab to close - * @return true if database was closed successully + * @return true if database was closed successfully */ bool DatabaseTabWidget::closeDatabaseTabFromSender() { @@ -353,7 +352,7 @@ bool DatabaseTabWidget::closeDatabaseTabFromSender() * Attempt to close a database and remove its tab afterwards. * * @param index index of the database tab to close - * @return true if database was closed successully + * @return true if database was closed successfully */ bool DatabaseTabWidget::closeDatabaseTab(int index) { @@ -364,7 +363,7 @@ bool DatabaseTabWidget::closeDatabaseTab(int index) * Attempt to close a database and remove its tab afterwards. * * @param dbWidget \link DatabaseWidget to close - * @return true if database was closed successully + * @return true if database was closed successfully */ bool DatabaseTabWidget::closeDatabaseTab(DatabaseWidget* dbWidget) { @@ -829,6 +828,18 @@ void DatabaseTabWidget::updateLastDatabases(const QString& filename) } } +void DatabaseTabWidget::updateLastDatabases() +{ + auto dbWidget = currentDatabaseWidget(); + + if (dbWidget) { + auto filePath = dbWidget->database()->filePath(); + if (!filePath.isEmpty()) { + updateLastDatabases(filePath); + } + } +} + void DatabaseTabWidget::emitActiveDatabaseChanged() { emit activeDatabaseChanged(currentDatabaseWidget()); diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 38a1822bf..3a6791a80 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -105,6 +105,7 @@ private slots: void emitDatabaseLockChanged(); void handleDatabaseUnlockDialogFinished(bool accepted, DatabaseWidget* dbWidget); void handleExportError(const QString& reason); + void updateLastDatabases(); private: QSharedPointer execNewDatabaseWizard(); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 76191fd2b..882a87f49 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -1837,7 +1837,7 @@ QStringList DatabaseWidget::customEntryAttributes() const { Entry* entry = m_entryView->currentEntry(); if (!entry) { - return QStringList(); + return {}; } return entry->attributes()->customKeys(); diff --git a/src/gui/DatabaseWidgetStateSync.cpp b/src/gui/DatabaseWidgetStateSync.cpp index 9cc22254f..7264c23df 100644 --- a/src/gui/DatabaseWidgetStateSync.cpp +++ b/src/gui/DatabaseWidgetStateSync.cpp @@ -36,9 +36,7 @@ DatabaseWidgetStateSync::DatabaseWidgetStateSync(QObject* parent) connect(qApp, &QCoreApplication::aboutToQuit, this, &DatabaseWidgetStateSync::sync); } -DatabaseWidgetStateSync::~DatabaseWidgetStateSync() -{ -} +DatabaseWidgetStateSync::~DatabaseWidgetStateSync() = default; /** * Sync state with persistent storage. diff --git a/src/gui/EditWidget.cpp b/src/gui/EditWidget.cpp index 92e221607..719656744 100644 --- a/src/gui/EditWidget.cpp +++ b/src/gui/EditWidget.cpp @@ -45,9 +45,7 @@ EditWidget::EditWidget(QWidget* parent) connect(m_ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), SLOT(buttonClicked(QAbstractButton*))); } -EditWidget::~EditWidget() -{ -} +EditWidget::~EditWidget() = default; void EditWidget::addPage(const QString& labelText, const QIcon& icon, QWidget* widget) { diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index 25542730c..e57e23c94 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -86,9 +86,7 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent) #endif } -EditWidgetIcons::~EditWidgetIcons() -{ -} +EditWidgetIcons::~EditWidgetIcons() = default; IconStruct EditWidgetIcons::state() { diff --git a/src/gui/EditWidgetProperties.cpp b/src/gui/EditWidgetProperties.cpp index 3e26352d3..4aea1510c 100644 --- a/src/gui/EditWidgetProperties.cpp +++ b/src/gui/EditWidgetProperties.cpp @@ -41,9 +41,7 @@ EditWidgetProperties::EditWidgetProperties(QWidget* parent) connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedPluginData())); } -EditWidgetProperties::~EditWidgetProperties() -{ -} +EditWidgetProperties::~EditWidgetProperties() = default; void EditWidgetProperties::setFields(const TimeInfo& timeInfo, const QUuid& uuid) { diff --git a/src/gui/EntryPreviewWidget.cpp b/src/gui/EntryPreviewWidget.cpp index d864560dd..a3eda3f37 100644 --- a/src/gui/EntryPreviewWidget.cpp +++ b/src/gui/EntryPreviewWidget.cpp @@ -107,9 +107,7 @@ EntryPreviewWidget::EntryPreviewWidget(QWidget* parent) #endif } -EntryPreviewWidget::~EntryPreviewWidget() -{ -} +EntryPreviewWidget::~EntryPreviewWidget() = default; void EntryPreviewWidget::clear() { diff --git a/src/gui/FileDialog.cpp b/src/gui/FileDialog.cpp index 0d46898fb..84b19e260 100644 --- a/src/gui/FileDialog.cpp +++ b/src/gui/FileDialog.cpp @@ -21,9 +21,7 @@ FileDialog* FileDialog::m_instance(nullptr); -FileDialog::FileDialog() -{ -} +FileDialog::FileDialog() = default; QString FileDialog::getOpenFileName(QWidget* parent, const QString& caption, diff --git a/src/gui/Font.h b/src/gui/Font.h index d53f0c407..878dbb53d 100644 --- a/src/gui/Font.h +++ b/src/gui/Font.h @@ -27,9 +27,7 @@ public: static QFont fixedFont(); private: - Font() - { - } + Font() = default; }; #endif // KEEPASSX_FONT_H diff --git a/src/gui/HtmlExporter.cpp b/src/gui/HtmlExporter.cpp index 70249ed26..654909463 100644 --- a/src/gui/HtmlExporter.cpp +++ b/src/gui/HtmlExporter.cpp @@ -85,15 +85,6 @@ namespace item.append(""); } - const auto& n = entry.notes(); - if (!n.isEmpty()) { - item.append(""); - item.append(QObject::tr("Notes")); - item.append(""); - item.append(entry.notes().toHtmlEscaped().replace("\n", "
    ")); - item.append(""); - } - // Now add the attributes (if there are any) const auto* const attr = entry.attributes(); if (attr && !attr->customKeys().isEmpty()) { @@ -105,6 +96,15 @@ namespace item.append(""); } } + + const auto& n = entry.notes(); + if (!n.isEmpty()) { + item.append(""); + item.append(QObject::tr("Notes")); + item.append(""); + item.append(entry.notes().toHtmlEscaped().replace("\n", "
    ")); + item.append(""); + } return item; } } // namespace @@ -150,15 +150,18 @@ bool HtmlExporter::exportDatabase(QIODevice* device, "h3 " "{ margin-left: 2em; }" "table " - "{ margin-left: 4em; } " + "{ margin-left: 1em; } " + "caption " + "{ text-align: left; font-weight: bold; font-size: 150%; border-bottom: .15em solid " + "#4ca; margin-bottom: .5em;} " "th, td " "{ text-align: left; vertical-align: top; padding: 1px; }" "th " - "{ min-width: 5em; width: 20%; } " + "{ min-width: 7em; width: 15%; } " ".username, .password, .url, .attr " "{ font-size: larger; font-family: monospace; } " ".notes " - "{ font-size: medium; } " + "{ font-size: small; } " "" "\n" "" @@ -231,7 +234,7 @@ bool HtmlExporter::writeGroup(QIODevice& device, const Group& group, QString pat } // Begin the table for the entries in this group - auto table = QString(""); + auto table = QString("
    "); auto entries = group.entries(); if (sorted) { @@ -252,10 +255,11 @@ bool HtmlExporter::writeGroup(QIODevice& device, const Group& group, QString pat // icon and entry title ... table += ""; table += ""; - table += ""; + auto caption = ""; // ... then the right side with the data fields - table += ""; + table += + ""; table += ""; } diff --git a/src/gui/IconModels.cpp b/src/gui/IconModels.cpp index ab435aedc..1d1eefb42 100644 --- a/src/gui/IconModels.cpp +++ b/src/gui/IconModels.cpp @@ -38,7 +38,7 @@ int DefaultIconModel::rowCount(const QModelIndex& parent) const QVariant DefaultIconModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) { - return QVariant(); + return {}; } Q_ASSERT(index.row() < databaseIcons()->count()); @@ -47,7 +47,7 @@ QVariant DefaultIconModel::data(const QModelIndex& index, int role) const return databaseIcons()->icon(index.row(), IconSize::Medium); } - return QVariant(); + return {}; } CustomIconModel::CustomIconModel(QObject* parent) @@ -78,7 +78,7 @@ int CustomIconModel::rowCount(const QModelIndex& parent) const QVariant CustomIconModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) { - return QVariant(); + return {}; } if (role == Qt::DecorationRole) { @@ -86,7 +86,7 @@ QVariant CustomIconModel::data(const QModelIndex& index, int role) const return m_icons.value(uuid); } - return QVariant(); + return {}; } QUuid CustomIconModel::uuidFromIndex(const QModelIndex& index) const diff --git a/src/gui/Icons.cpp b/src/gui/Icons.cpp index b16c40f80..2083444d7 100644 --- a/src/gui/Icons.cpp +++ b/src/gui/Icons.cpp @@ -48,16 +48,14 @@ private: Icons* Icons::m_instance(nullptr); -Icons::Icons() -{ -} +Icons::Icons() = default; QString Icons::applicationIconName() { #ifdef KEEPASSXC_DIST_FLATPAK - return QString("org.keepassxc.KeePassXC"); + return "org.keepassxc.KeePassXC"; #else - return QString("keepassxc"); + return "keepassxc"; #endif } diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 6e0207d66..cba20a9a6 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -128,6 +128,7 @@ MainWindow::MainWindow() m_entryContextMenu->setSeparatorsCollapsible(true); m_entryContextMenu->addAction(m_ui->actionEntryCopyUsername); m_entryContextMenu->addAction(m_ui->actionEntryCopyPassword); + m_entryContextMenu->addAction(m_ui->actionEntryCopyURL); m_entryContextMenu->addAction(m_ui->menuEntryCopyAttribute->menuAction()); m_entryContextMenu->addAction(m_ui->menuEntryTotp->menuAction()); m_entryContextMenu->addAction(m_ui->menuTags->menuAction()); @@ -268,6 +269,9 @@ MainWindow::MainWindow() setShortcut(m_ui->actionDatabaseSave, QKeySequence::Save, Qt::CTRL + Qt::Key_S); setShortcut(m_ui->actionDatabaseSaveAs, QKeySequence::SaveAs, Qt::CTRL + Qt::SHIFT + Qt::Key_S); setShortcut(m_ui->actionDatabaseClose, QKeySequence::Close, Qt::CTRL + Qt::Key_W); + m_ui->actionDatabaseSettings->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Comma); + m_ui->actionReports->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_R); + setShortcut(m_ui->actionSettings, QKeySequence::Preferences, Qt::CTRL + Qt::Key_Comma); m_ui->actionLockDatabase->setShortcut(Qt::CTRL + Qt::Key_L); m_ui->actionLockAllDatabases->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_L); setShortcut(m_ui->actionQuit, QKeySequence::Quit, Qt::CTRL + Qt::Key_Q); @@ -745,7 +749,7 @@ void MainWindow::appExit() /** * Returns if application was built with hardware key support. - * Intented to be used by 3rd-party applications using DBus. + * Intended to be used by 3rd-party applications using DBus. * * @return True if built with hardware key support, false otherwise */ @@ -761,7 +765,7 @@ bool MainWindow::isHardwareKeySupported() /** * Refreshes list of hardware keys known. * Triggers the DatabaseOpenWidget to automatically select the key last used for a database if found. - * Intented to be used by 3rd-party applications using DBus. + * Intended to be used by 3rd-party applications using DBus. * * @return True if any key was found, false otherwise or if application lacks hardware key support */ diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index 60b9d1b80..bbc06c180 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -216,7 +216,7 @@ 00800 - 25 + 22 @@ -247,11 +247,6 @@ - - - &Quit - - @@ -306,7 +301,6 @@ Copy Att&ribute - @@ -338,6 +332,7 @@ + @@ -818,7 +813,7 @@ false - &URL + Copy &URL Copy URL to clipboard @@ -895,7 +890,7 @@ Copy &TOTP - + Copy Password and TOTP diff --git a/src/gui/PasswordWidget.cpp b/src/gui/PasswordWidget.cpp index f5e97ba08..e1fc20c6b 100644 --- a/src/gui/PasswordWidget.cpp +++ b/src/gui/PasswordWidget.cpp @@ -54,7 +54,7 @@ PasswordWidget::PasswordWidget(QWidget* parent) // use a monospace font for the password field QFont passwordFont = Font::fixedFont(); passwordFont.setLetterSpacing(QFont::PercentageSpacing, 110); - setFont(passwordFont); + m_ui->passwordEdit->setFont(passwordFont); // Prevent conflicts with global Mac shortcuts (force Control on all platforms) #ifdef Q_OS_MAC @@ -143,19 +143,19 @@ void PasswordWidget::setReadOnly(bool state) m_ui->passwordEdit->setReadOnly(state); } -void PasswordWidget::setRepeatPartner(PasswordWidget* repeatEdit) +void PasswordWidget::setRepeatPartner(PasswordWidget* repeatPartner) { - m_repeatPasswordEdit = repeatEdit; - m_repeatPasswordEdit->setParentPasswordEdit(this); + m_repeatPasswordWidget = repeatPartner; + m_repeatPasswordWidget->setParentPasswordEdit(this); connect( - m_ui->passwordEdit, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(autocompletePassword(QString))); - connect(m_ui->passwordEdit, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(updateRepeatStatus())); + m_ui->passwordEdit, SIGNAL(textChanged(QString)), m_repeatPasswordWidget, SLOT(autocompletePassword(QString))); + connect(m_ui->passwordEdit, SIGNAL(textChanged(QString)), m_repeatPasswordWidget, SLOT(updateRepeatStatus())); } void PasswordWidget::setParentPasswordEdit(PasswordWidget* parent) { - m_parentPasswordEdit = parent; + m_parentPasswordWidget = parent; // Hide actions m_toggleVisibleAction->setVisible(false); m_passwordGeneratorAction->setVisible(false); @@ -176,13 +176,13 @@ void PasswordWidget::setShowPassword(bool show) m_toggleVisibleAction->setIcon(icons()->onOffIcon("password-show", show)); m_toggleVisibleAction->setChecked(show); - if (m_repeatPasswordEdit) { - m_repeatPasswordEdit->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); + if (m_repeatPasswordWidget) { + m_repeatPasswordWidget->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); if (!config()->get(Config::Security_PasswordsRepeatVisible).toBool()) { - m_repeatPasswordEdit->setEnabled(!show); - m_repeatPasswordEdit->setText(text()); + m_repeatPasswordWidget->setEnabled(!show); + m_repeatPasswordWidget->setText(text()); } else { - m_repeatPasswordEdit->setEnabled(true); + m_repeatPasswordWidget->setEnabled(true); } } } @@ -199,19 +199,19 @@ void PasswordWidget::popupPasswordGenerator() generator->setPasswordLength(text().length()); connect(generator, SIGNAL(appliedPassword(QString)), SLOT(setText(QString))); - if (m_repeatPasswordEdit) { - connect(generator, SIGNAL(appliedPassword(QString)), m_repeatPasswordEdit, SLOT(setText(QString))); + if (m_repeatPasswordWidget) { + connect(generator, SIGNAL(appliedPassword(QString)), m_repeatPasswordWidget, SLOT(setText(QString))); } } void PasswordWidget::updateRepeatStatus() { static const auto stylesheetTemplate = QStringLiteral("QLineEdit { background: %1; }"); - if (!m_parentPasswordEdit) { + if (!m_parentPasswordWidget) { return; } - const auto otherPassword = m_parentPasswordEdit->text(); + const auto otherPassword = m_parentPasswordWidget->text(); const auto password = text(); if (otherPassword != password) { bool isCorrect = false; @@ -251,7 +251,7 @@ bool PasswordWidget::event(QEvent* event) void PasswordWidget::checkCapslockState() { - if (m_parentPasswordEdit) { + if (m_parentPasswordWidget) { return; } diff --git a/src/gui/PasswordWidget.h b/src/gui/PasswordWidget.h index f844d7737..0014b696f 100644 --- a/src/gui/PasswordWidget.h +++ b/src/gui/PasswordWidget.h @@ -37,7 +37,7 @@ public: explicit PasswordWidget(QWidget* parent = nullptr); ~PasswordWidget() override; void enablePasswordGenerator(); - void setRepeatPartner(PasswordWidget* repeatEdit); + void setRepeatPartner(PasswordWidget* repeatPartner); void setQualityVisible(bool state); bool isPasswordVisible() const; @@ -76,8 +76,8 @@ private: QPointer m_toggleVisibleAction; QPointer m_passwordGeneratorAction; QPointer m_capslockAction; - QPointer m_repeatPasswordEdit; - QPointer m_parentPasswordEdit; + QPointer m_repeatPasswordWidget; + QPointer m_parentPasswordWidget; bool m_capslockState = false; }; diff --git a/src/gui/SearchWidget.cpp b/src/gui/SearchWidget.cpp index 8a04ec14f..765855cf8 100644 --- a/src/gui/SearchWidget.cpp +++ b/src/gui/SearchWidget.cpp @@ -81,9 +81,7 @@ SearchWidget::SearchWidget(QWidget* parent) } } -SearchWidget::~SearchWidget() -{ -} +SearchWidget::~SearchWidget() = default; bool SearchWidget::eventFilter(QObject* obj, QEvent* event) { diff --git a/src/gui/TotpDialog.cpp b/src/gui/TotpDialog.cpp index e856f5d6a..83d8a6973 100644 --- a/src/gui/TotpDialog.cpp +++ b/src/gui/TotpDialog.cpp @@ -53,9 +53,7 @@ TotpDialog::TotpDialog(QWidget* parent, Entry* entry) connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(copyToClipboard())); } -TotpDialog::~TotpDialog() -{ -} +TotpDialog::~TotpDialog() = default; void TotpDialog::copyToClipboard() { diff --git a/src/gui/TotpSetupDialog.cpp b/src/gui/TotpSetupDialog.cpp index 1d403a17c..ed84218c5 100644 --- a/src/gui/TotpSetupDialog.cpp +++ b/src/gui/TotpSetupDialog.cpp @@ -38,9 +38,7 @@ TotpSetupDialog::TotpSetupDialog(QWidget* parent, Entry* entry) init(); } -TotpSetupDialog::~TotpSetupDialog() -{ -} +TotpSetupDialog::~TotpSetupDialog() = default; void TotpSetupDialog::saveSettings() { diff --git a/src/gui/WelcomeWidget.cpp b/src/gui/WelcomeWidget.cpp index bb5b99ee2..916719c9d 100644 --- a/src/gui/WelcomeWidget.cpp +++ b/src/gui/WelcomeWidget.cpp @@ -51,9 +51,7 @@ WelcomeWidget::WelcomeWidget(QWidget* parent) SLOT(openDatabaseFromFile(QListWidgetItem*))); } -WelcomeWidget::~WelcomeWidget() -{ -} +WelcomeWidget::~WelcomeWidget() = default; void WelcomeWidget::openDatabaseFromFile(QListWidgetItem* item) { diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp index b7cb7075c..6781974f5 100644 --- a/src/gui/csvImport/CsvImportWidget.cpp +++ b/src/gui/csvImport/CsvImportWidget.cpp @@ -88,9 +88,7 @@ void CsvImportWidget::skippedChanged(int rows) updateTableview(); } -CsvImportWidget::~CsvImportWidget() -{ -} +CsvImportWidget::~CsvImportWidget() = default; void CsvImportWidget::configParser() { diff --git a/src/gui/csvImport/CsvImportWizard.cpp b/src/gui/csvImport/CsvImportWizard.cpp index 4595c06d9..d0856023e 100644 --- a/src/gui/csvImport/CsvImportWizard.cpp +++ b/src/gui/csvImport/CsvImportWizard.cpp @@ -29,9 +29,7 @@ CsvImportWizard::CsvImportWizard(QWidget* parent) connect(m_parse, SIGNAL(editFinished(bool)), this, SLOT(parseFinished(bool))); } -CsvImportWizard::~CsvImportWizard() -{ -} +CsvImportWizard::~CsvImportWizard() = default; void CsvImportWizard::load(const QString& filename, Database* database) { diff --git a/src/gui/csvImport/CsvParserModel.cpp b/src/gui/csvImport/CsvParserModel.cpp index 77abb5931..45675d0c4 100644 --- a/src/gui/csvImport/CsvParserModel.cpp +++ b/src/gui/csvImport/CsvParserModel.cpp @@ -26,9 +26,7 @@ CsvParserModel::CsvParserModel(QObject* parent) { } -CsvParserModel::~CsvParserModel() -{ -} +CsvParserModel::~CsvParserModel() = default; void CsvParserModel::setFilename(const QString& filename) { @@ -119,12 +117,12 @@ int CsvParserModel::columnCount(const QModelIndex& parent) const QVariant CsvParserModel::data(const QModelIndex& index, int role) const { if ((index.column() >= m_columnHeader.size()) || (index.row() + m_skipped >= rowCount()) || !index.isValid()) { - return QVariant(); + return {}; } if (role == Qt::DisplayRole) { return m_table.at(index.row() + m_skipped).at(m_columnMap[index.column()]); } - return QVariant(); + return {}; } QVariant CsvParserModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -132,15 +130,15 @@ QVariant CsvParserModel::headerData(int section, Qt::Orientation orientation, in if (role == Qt::DisplayRole) { if (orientation == Qt::Horizontal) { if ((section < 0) || (section >= m_columnHeader.size())) { - return QVariant(); + return {}; } return m_columnHeader.at(section); } else if (orientation == Qt::Vertical) { if (section + m_skipped >= rowCount()) { - return QVariant(); + return {}; } return QString::number(section + 1); } } - return QVariant(); + return {}; } diff --git a/src/gui/databasekey/KeyComponentWidget.cpp b/src/gui/databasekey/KeyComponentWidget.cpp index e0cdc0f8a..f49c10e1e 100644 --- a/src/gui/databasekey/KeyComponentWidget.cpp +++ b/src/gui/databasekey/KeyComponentWidget.cpp @@ -43,9 +43,7 @@ KeyComponentWidget::KeyComponentWidget(QWidget* parent) m_ui->stackedWidget->blockSignals(prev); } -KeyComponentWidget::~KeyComponentWidget() -{ -} +KeyComponentWidget::~KeyComponentWidget() = default; void KeyComponentWidget::setComponentAdded(bool added) { diff --git a/src/gui/databasekey/KeyFileEditWidget.cpp b/src/gui/databasekey/KeyFileEditWidget.cpp index dc38d05d7..dfaef273c 100644 --- a/src/gui/databasekey/KeyFileEditWidget.cpp +++ b/src/gui/databasekey/KeyFileEditWidget.cpp @@ -33,9 +33,7 @@ KeyFileEditWidget::KeyFileEditWidget(DatabaseSettingsWidget* parent) initComponent(); } -KeyFileEditWidget::~KeyFileEditWidget() -{ -} +KeyFileEditWidget::~KeyFileEditWidget() = default; bool KeyFileEditWidget::addToCompositeKey(QSharedPointer key) { diff --git a/src/gui/databasekey/PasswordEditWidget.cpp b/src/gui/databasekey/PasswordEditWidget.cpp index 5ed6b6328..b6d2b3ec7 100644 --- a/src/gui/databasekey/PasswordEditWidget.cpp +++ b/src/gui/databasekey/PasswordEditWidget.cpp @@ -29,9 +29,7 @@ PasswordEditWidget::PasswordEditWidget(QWidget* parent) initComponent(); } -PasswordEditWidget::~PasswordEditWidget() -{ -} +PasswordEditWidget::~PasswordEditWidget() = default; bool PasswordEditWidget::addToCompositeKey(QSharedPointer key) { diff --git a/src/gui/databasekey/YubiKeyEditWidget.cpp b/src/gui/databasekey/YubiKeyEditWidget.cpp index 2e6cf4ff3..a8c4e7843 100644 --- a/src/gui/databasekey/YubiKeyEditWidget.cpp +++ b/src/gui/databasekey/YubiKeyEditWidget.cpp @@ -33,9 +33,7 @@ YubiKeyEditWidget::YubiKeyEditWidget(QWidget* parent) connect(YubiKey::instance(), SIGNAL(detectComplete(bool)), SLOT(hardwareKeyResponse(bool)), Qt::QueuedConnection); } -YubiKeyEditWidget::~YubiKeyEditWidget() -{ -} +YubiKeyEditWidget::~YubiKeyEditWidget() = default; bool YubiKeyEditWidget::addToCompositeKey(QSharedPointer key) { diff --git a/src/gui/dbsettings/DatabaseSettingsDialog.cpp b/src/gui/dbsettings/DatabaseSettingsDialog.cpp index 6d96dd769..8bbf7fd6d 100644 --- a/src/gui/dbsettings/DatabaseSettingsDialog.cpp +++ b/src/gui/dbsettings/DatabaseSettingsDialog.cpp @@ -122,9 +122,7 @@ DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent) pageChanged(); } -DatabaseSettingsDialog::~DatabaseSettingsDialog() -{ -} +DatabaseSettingsDialog::~DatabaseSettingsDialog() = default; void DatabaseSettingsDialog::load(const QSharedPointer& db) { diff --git a/src/gui/dbsettings/DatabaseSettingsDialog.h b/src/gui/dbsettings/DatabaseSettingsDialog.h index 512c47a1a..7607f9f78 100644 --- a/src/gui/dbsettings/DatabaseSettingsDialog.h +++ b/src/gui/dbsettings/DatabaseSettingsDialog.h @@ -41,9 +41,7 @@ namespace Ui class IDatabaseSettingsPage { public: - virtual ~IDatabaseSettingsPage() - { - } + virtual ~IDatabaseSettingsPage() = default; virtual QString name() = 0; virtual QIcon icon() = 0; virtual QWidget* createWidget() = 0; diff --git a/src/gui/dbsettings/DatabaseSettingsWidget.cpp b/src/gui/dbsettings/DatabaseSettingsWidget.cpp index b2536f203..5c300f868 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidget.cpp +++ b/src/gui/dbsettings/DatabaseSettingsWidget.cpp @@ -23,9 +23,7 @@ DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) { } -DatabaseSettingsWidget::~DatabaseSettingsWidget() -{ -} +DatabaseSettingsWidget::~DatabaseSettingsWidget() = default; /** * Load the database to be configured by this page and initialize the page. diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp index aa91fa451..cbfdb0dcb 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp +++ b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 KeePassXC Team + * Copyright (C) 2022 KeePassXC Team * Copyright (C) 2018 Sami Vänttinen * * This program is free software: you can redistribute it and/or modify @@ -48,8 +48,6 @@ DatabaseSettingsWidgetBrowser::DatabaseSettingsWidgetBrowser(QWidget* parent) // clang-format on connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedKey())); - connect(m_ui->convertToCustomData, SIGNAL(clicked()), this, SLOT(convertAttributesToCustomData())); - connect(m_ui->convertToCustomData, SIGNAL(clicked()), this, SLOT(updateSharedKeyList())); connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SLOT(removeSharedEncryptionKeys())); connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SLOT(updateSharedKeyList())); connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SLOT(removeStoredPermissions())); @@ -141,7 +139,6 @@ void DatabaseSettingsWidgetBrowser::updateModel() void DatabaseSettingsWidgetBrowser::settingsWarning() { if (!browserSettings()->isEnabled()) { - m_ui->convertToCustomData->setEnabled(false); m_ui->removeSharedEncryptionKeys->setEnabled(false); m_ui->removeStoredPermissions->setEnabled(false); m_ui->customDataTable->setEnabled(false); @@ -150,7 +147,6 @@ void DatabaseSettingsWidgetBrowser::settingsWarning() m_ui->warningWidget->setCloseButtonVisible(false); m_ui->warningWidget->setAutoHideTimeout(-1); } else { - m_ui->convertToCustomData->setEnabled(true); m_ui->removeSharedEncryptionKeys->setEnabled(true); m_ui->removeStoredPermissions->setEnabled(true); m_ui->customDataTable->setEnabled(true); @@ -242,22 +238,6 @@ void DatabaseSettingsWidgetBrowser::removeStoredPermissions() } } -void DatabaseSettingsWidgetBrowser::convertAttributesToCustomData() -{ - if (MessageBox::Yes - != MessageBox::question( - this, - tr("Move KeePassHTTP attributes to custom data"), - tr("Do you really want to convert all legacy browser integration data to the latest standard?\n" - "This is necessary to maintain compatibility with the browser plugin."), - MessageBox::Yes | MessageBox::Cancel, - MessageBox::Cancel)) { - return; - } - - BrowserService::convertAttributesToCustomData(m_db); -} - void DatabaseSettingsWidgetBrowser::refreshDatabaseID() { if (MessageBox::Yes diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h index 9beb40466..149cd3a6a 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h +++ b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 KeePassXC Team + * Copyright (C) 2022 KeePassXC Team * Copyright (C) 2018 Sami Vänttinen * * This program is free software: you can redistribute it and/or modify @@ -59,7 +59,6 @@ private slots: void updateSharedKeyList(); void removeSharedEncryptionKeys(); void removeStoredPermissions(); - void convertAttributesToCustomData(); void refreshDatabaseID(); void editIndex(const QModelIndex& index); void editFinished(QStandardItem* item); diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.ui b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.ui index 7d6dc00d2..a62d0d786 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.ui +++ b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.ui @@ -51,35 +51,6 @@ KeePassXC-Browser settings - - - - - 0 - 0 - - - - Convert KeePassHTTP data - - - Convert legacy KeePassHTTP attributes to KeePassXC-Browser compatible custom data - - - - - - - - 0 - 0 - - - - Refresh database root group ID - - - @@ -106,6 +77,19 @@ + + + + + 0 + 0 + + + + Refresh database root group ID + + + @@ -186,7 +170,6 @@ removeSharedEncryptionKeys removeStoredPermissions - convertToCustomData refreshDatabaseID customDataTable removeCustomDataButton diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp index 2dae5cbb5..41b4eea6d 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp +++ b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp @@ -71,9 +71,7 @@ DatabaseSettingsWidgetDatabaseKey::DatabaseSettingsWidgetDatabaseKey(QWidget* pa setLayout(vbox); } -DatabaseSettingsWidgetDatabaseKey::~DatabaseSettingsWidgetDatabaseKey() -{ -} +DatabaseSettingsWidgetDatabaseKey::~DatabaseSettingsWidgetDatabaseKey() = default; void DatabaseSettingsWidgetDatabaseKey::load(QSharedPointer db) { diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp index be13cd188..3a3495dfc 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp +++ b/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp @@ -70,9 +70,7 @@ DatabaseSettingsWidgetEncryption::DatabaseSettingsWidgetEncryption(QWidget* pare connect(m_ui->parallelismSpinBox, SIGNAL(valueChanged(int)), SLOT(markDirty())); } -DatabaseSettingsWidgetEncryption::~DatabaseSettingsWidgetEncryption() -{ -} +DatabaseSettingsWidgetEncryption::~DatabaseSettingsWidgetEncryption() = default; #define IS_ARGON2(uuid) (uuid == KeePass2::KDF_ARGON2D || uuid == KeePass2::KDF_ARGON2ID) #define IS_AES_KDF(uuid) (uuid == KeePass2::KDF_AES_KDBX3 || uuid == KeePass2::KDF_AES_KDBX4) diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp index 6bc21aec5..ac883ac7a 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp +++ b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp @@ -33,9 +33,7 @@ DatabaseSettingsWidgetGeneral::DatabaseSettingsWidgetGeneral(QWidget* parent) connect(m_ui->historyMaxSizeCheckBox, SIGNAL(toggled(bool)), m_ui->historyMaxSizeSpinBox, SLOT(setEnabled(bool))); } -DatabaseSettingsWidgetGeneral::~DatabaseSettingsWidgetGeneral() -{ -} +DatabaseSettingsWidgetGeneral::~DatabaseSettingsWidgetGeneral() = default; void DatabaseSettingsWidgetGeneral::initialize() { diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.cpp index 09650c6b0..fea6bc2a3 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.cpp +++ b/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.cpp @@ -42,9 +42,7 @@ DatabaseSettingsWidgetMaintenance::DatabaseSettingsWidgetMaintenance(QWidget* pa SLOT(selectionChanged())); } -DatabaseSettingsWidgetMaintenance::~DatabaseSettingsWidgetMaintenance() -{ -} +DatabaseSettingsWidgetMaintenance::~DatabaseSettingsWidgetMaintenance() = default; void DatabaseSettingsWidgetMaintenance::populateIcons(QSharedPointer db) { diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.cpp index 0a1dccb5f..32879a75b 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.cpp +++ b/src/gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.cpp @@ -28,9 +28,7 @@ DatabaseSettingWidgetMetaData::DatabaseSettingWidgetMetaData(QWidget* parent) m_ui->setupUi(this); } -DatabaseSettingWidgetMetaData::~DatabaseSettingWidgetMetaData() -{ -} +DatabaseSettingWidgetMetaData::~DatabaseSettingWidgetMetaData() = default; void DatabaseSettingWidgetMetaData::initialize() { diff --git a/src/gui/entry/AutoTypeAssociationsModel.cpp b/src/gui/entry/AutoTypeAssociationsModel.cpp index 6e7b08bc0..03eedae25 100644 --- a/src/gui/entry/AutoTypeAssociationsModel.cpp +++ b/src/gui/entry/AutoTypeAssociationsModel.cpp @@ -79,14 +79,14 @@ QVariant AutoTypeAssociationsModel::headerData(int section, Qt::Orientation orie return tr("Sequence"); } } else { - return QVariant(); + return {}; } } QVariant AutoTypeAssociationsModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) { - return QVariant(); + return {}; } if (role == Qt::DisplayRole) { @@ -108,7 +108,7 @@ QVariant AutoTypeAssociationsModel::data(const QModelIndex& index, int role) con return sequence; } } else { - return QVariant(); + return {}; } } diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index b03d469e5..be7fd1467 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -135,9 +135,7 @@ EditEntryWidget::EditEntryWidget(QWidget* parent) m_mainUi->passwordEdit->setQualityVisible(true); } -EditEntryWidget::~EditEntryWidget() -{ -} +EditEntryWidget::~EditEntryWidget() = default; void EditEntryWidget::setupMain() { @@ -234,8 +232,7 @@ void EditEntryWidget::setupAutoType() // clang-format off connect(m_autoTypeUi->enableButton, SIGNAL(toggled(bool)), SLOT(updateAutoTypeEnabled())); - connect(m_autoTypeUi->customSequenceButton, SIGNAL(toggled(bool)), - m_autoTypeUi->sequenceEdit, SLOT(setEnabled(bool))); + connect(m_autoTypeUi->customSequenceButton, &QRadioButton::toggled, this, &EditEntryWidget::updateAutoTypeEnabled); connect(m_autoTypeUi->openHelpButton, SIGNAL(clicked()), SLOT(openAutotypeHelp())); connect(m_autoTypeUi->customWindowSequenceButton, SIGNAL(toggled(bool)), m_autoTypeUi->windowSequenceEdit, SLOT(setEnabled(bool))); diff --git a/src/gui/entry/EntryAttachmentsModel.cpp b/src/gui/entry/EntryAttachmentsModel.cpp index c5d0ff073..d66e912ab 100644 --- a/src/gui/entry/EntryAttachmentsModel.cpp +++ b/src/gui/entry/EntryAttachmentsModel.cpp @@ -79,7 +79,7 @@ QVariant EntryAttachmentsModel::headerData(int section, Qt::Orientation orientat QVariant EntryAttachmentsModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) { - return QVariant(); + return {}; } if (role == Qt::DisplayRole || role == Qt::EditRole) { @@ -96,7 +96,7 @@ QVariant EntryAttachmentsModel::data(const QModelIndex& index, int role) const } } - return QVariant(); + return {}; } bool EntryAttachmentsModel::setData(const QModelIndex& index, const QVariant& value, int role) @@ -124,7 +124,7 @@ Qt::ItemFlags EntryAttachmentsModel::flags(const QModelIndex& index) const QString EntryAttachmentsModel::keyByIndex(const QModelIndex& index) const { if (!index.isValid()) { - return QString(); + return {}; } return m_entryAttachments->keys().at(index.row()); diff --git a/src/gui/entry/EntryAttachmentsWidget.cpp b/src/gui/entry/EntryAttachmentsWidget.cpp index 796b84fb7..d514804f8 100644 --- a/src/gui/entry/EntryAttachmentsWidget.cpp +++ b/src/gui/entry/EntryAttachmentsWidget.cpp @@ -75,9 +75,7 @@ EntryAttachmentsWidget::EntryAttachmentsWidget(QWidget* parent) updateButtonsEnabled(); } -EntryAttachmentsWidget::~EntryAttachmentsWidget() -{ -} +EntryAttachmentsWidget::~EntryAttachmentsWidget() = default; const EntryAttachments* EntryAttachmentsWidget::attachments() const { @@ -313,6 +311,7 @@ void EntryAttachmentsWidget::updateButtonsVisible() { m_ui->addAttachmentButton->setVisible(m_buttonsVisible && !m_readOnly); m_ui->removeAttachmentButton->setVisible(m_buttonsVisible && !m_readOnly); + m_ui->renameAttachmentButton->setVisible(m_buttonsVisible && !m_readOnly); } bool EntryAttachmentsWidget::insertAttachments(const QStringList& filenames, QString& errorMessage) diff --git a/src/gui/entry/EntryAttributesModel.cpp b/src/gui/entry/EntryAttributesModel.cpp index 90ef21bb3..9ce9ed251 100644 --- a/src/gui/entry/EntryAttributesModel.cpp +++ b/src/gui/entry/EntryAttributesModel.cpp @@ -80,14 +80,14 @@ QVariant EntryAttributesModel::headerData(int section, Qt::Orientation orientati if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole) && (section == 0)) { return tr("Name"); } else { - return QVariant(); + return {}; } } QVariant EntryAttributesModel::data(const QModelIndex& index, int role) const { if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::EditRole)) { - return QVariant(); + return {}; } return m_attributes.at(index.row()); @@ -124,7 +124,7 @@ QModelIndex EntryAttributesModel::indexByKey(const QString& key) const int row = m_attributes.indexOf(key); if (row == -1) { - return QModelIndex(); + return {}; } else { return index(row, 0); } @@ -133,7 +133,7 @@ QModelIndex EntryAttributesModel::indexByKey(const QString& key) const QString EntryAttributesModel::keyByIndex(const QModelIndex& index) const { if (!index.isValid()) { - return QString(); + return {}; } else { return m_attributes.at(index.row()); } diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index 97d671e58..b25b002ef 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -120,7 +120,7 @@ int EntryModel::columnCount(const QModelIndex& parent) const QVariant EntryModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) { - return QVariant(); + return {}; } Entry* entry = entryFromIndex(index); @@ -336,7 +336,7 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const } } - return QVariant(); + return {}; } QVariant EntryModel::headerData(int section, Qt::Orientation orientation, int role) const diff --git a/src/gui/export/ExportDialog.cpp b/src/gui/export/ExportDialog.cpp index 3537505cc..6985546fa 100644 --- a/src/gui/export/ExportDialog.cpp +++ b/src/gui/export/ExportDialog.cpp @@ -44,9 +44,7 @@ ExportDialog::ExportDialog(QSharedPointer db, DatabaseTabWidget* MessageWidget::Warning); } -ExportDialog::~ExportDialog() -{ -} +ExportDialog::~ExportDialog() = default; QString ExportDialog::getStrategyName(ExportSortingStrategy strategy) { diff --git a/src/gui/group/EditGroupWidget.cpp b/src/gui/group/EditGroupWidget.cpp index fc6f80624..1b473c1fc 100644 --- a/src/gui/group/EditGroupWidget.cpp +++ b/src/gui/group/EditGroupWidget.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer - * Copyright (C) 2021 KeePassXC Team + * Copyright (C) 2022 KeePassXC Team * * 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 @@ -73,7 +73,7 @@ EditGroupWidget::EditGroupWidget(QWidget* parent) #if defined(WITH_XC_BROWSER) , m_browserSettingsChanged(false) , m_browserUi(new Ui::EditGroupWidgetBrowser()) - , m_browserWidget(new QScrollArea()) + , m_browserWidget(new QWidget(this)) #endif , m_group(nullptr) { @@ -83,8 +83,7 @@ EditGroupWidget::EditGroupWidget(QWidget* parent) addPage(tr("Icon"), icons()->icon("preferences-desktop-icons"), m_editGroupWidgetIcons); #if defined(WITH_XC_BROWSER) if (config()->get(Config::Browser_Enabled).toBool()) { - addPage(tr("Browser Integration"), icons()->icon("internet-web-browser"), m_browserWidget); - m_browserUi->setupUi(m_browserWidget); + initializeBrowserPage(); } #endif #if defined(WITH_XC_KEESHARE) @@ -113,9 +112,7 @@ EditGroupWidget::EditGroupWidget(QWidget* parent) setupModifiedTracking(); } -EditGroupWidget::~EditGroupWidget() -{ -} +EditGroupWidget::~EditGroupWidget() = default; void EditGroupWidget::setupModifiedTracking() { @@ -135,28 +132,7 @@ void EditGroupWidget::setupModifiedTracking() #if defined(WITH_XC_BROWSER) if (config()->get(Config::Browser_Enabled).toBool()) { - // Browser integration tab - connect( - m_browserUi->browserIntegrationHideEntriesComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setModified())); - connect(m_browserUi->browserIntegrationSkipAutoSubmitComboBox, - SIGNAL(currentIndexChanged(int)), - SLOT(setModified())); - connect( - m_browserUi->browserIntegrationOnlyHttpAuthComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setModified())); - connect( - m_browserUi->browserIntegrationNotHttpAuthComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setModified())); - connect(m_browserUi->browserIntegrationHideEntriesComboBox, - SIGNAL(currentIndexChanged(int)), - SLOT(updateBrowserModified())); - connect(m_browserUi->browserIntegrationSkipAutoSubmitComboBox, - SIGNAL(currentIndexChanged(int)), - SLOT(updateBrowserModified())); - connect(m_browserUi->browserIntegrationOnlyHttpAuthComboBox, - SIGNAL(currentIndexChanged(int)), - SLOT(updateBrowserModified())); - connect(m_browserUi->browserIntegrationNotHttpAuthComboBox, - SIGNAL(currentIndexChanged(int)), - SLOT(updateBrowserModified())); + setupBrowserModifiedTracking(); } #endif } @@ -230,6 +206,14 @@ void EditGroupWidget::loadGroup(Group* group, bool create, const QSharedPointer< inheritOmitWww = parent->resolveCustomDataTriState(BrowserService::OPTION_OMIT_WWW); } + // If the page has not been created at all, some of the elements are null + if (m_browserUi->browserIntegrationHideEntriesComboBox == nullptr + && config()->get(Config::Browser_Enabled).toBool()) { + initializeBrowserPage(); + setupBrowserModifiedTracking(); + } + + setPageHidden(m_browserWidget, false); addTriStateItems(m_browserUi->browserIntegrationHideEntriesComboBox, inheritHideEntries); addTriStateItems(m_browserUi->browserIntegrationSkipAutoSubmitComboBox, inheritSkipSubmit); addTriStateItems(m_browserUi->browserIntegrationOnlyHttpAuthComboBox, inheritOnlyHttp); @@ -246,6 +230,8 @@ void EditGroupWidget::loadGroup(Group* group, bool create, const QSharedPointer< indexFromTriState(group->resolveCustomDataTriState(BrowserService::OPTION_NOT_HTTP_AUTH, false))); m_browserUi->browserIntegrationOmitWwwCombobox->setCurrentIndex( indexFromTriState(group->resolveCustomDataTriState(BrowserService::OPTION_OMIT_WWW, false))); + } else if (hasPage(m_browserWidget)) { + setPageHidden(m_browserWidget, true); } #endif @@ -363,6 +349,34 @@ void EditGroupWidget::cancel() } #ifdef WITH_XC_BROWSER +void EditGroupWidget::initializeBrowserPage() +{ + addPage(tr("Browser Integration"), icons()->icon("internet-web-browser"), m_browserWidget); + m_browserUi->setupUi(m_browserWidget); +} + +void EditGroupWidget::setupBrowserModifiedTracking() +{ + // Browser integration tab + connect(m_browserUi->browserIntegrationHideEntriesComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setModified())); + connect( + m_browserUi->browserIntegrationSkipAutoSubmitComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setModified())); + connect(m_browserUi->browserIntegrationOnlyHttpAuthComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setModified())); + connect(m_browserUi->browserIntegrationNotHttpAuthComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setModified())); + connect(m_browserUi->browserIntegrationHideEntriesComboBox, + SIGNAL(currentIndexChanged(int)), + SLOT(updateBrowserModified())); + connect(m_browserUi->browserIntegrationSkipAutoSubmitComboBox, + SIGNAL(currentIndexChanged(int)), + SLOT(updateBrowserModified())); + connect(m_browserUi->browserIntegrationOnlyHttpAuthComboBox, + SIGNAL(currentIndexChanged(int)), + SLOT(updateBrowserModified())); + connect(m_browserUi->browserIntegrationNotHttpAuthComboBox, + SIGNAL(currentIndexChanged(int)), + SLOT(updateBrowserModified())); +} + void EditGroupWidget::updateBrowserModified() { m_browserSettingsChanged = true; diff --git a/src/gui/group/EditGroupWidget.h b/src/gui/group/EditGroupWidget.h index 412269c85..8e8d2c85b 100644 --- a/src/gui/group/EditGroupWidget.h +++ b/src/gui/group/EditGroupWidget.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer - * Copyright (C) 2021 KeePassXC Team + * Copyright (C) 2022 KeePassXC Team * * 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 @@ -39,9 +39,7 @@ namespace Ui class IEditGroupPage { public: - virtual ~IEditGroupPage() - { - } + virtual ~IEditGroupPage() = default; virtual QString name() = 0; virtual QIcon icon() = 0; virtual QWidget* createWidget() = 0; @@ -72,6 +70,8 @@ private slots: void save(); void cancel(); #ifdef WITH_XC_BROWSER + void initializeBrowserPage(); + void setupBrowserModifiedTracking(); void updateBrowserModified(); #endif @@ -89,7 +89,7 @@ private: #ifdef WITH_XC_BROWSER bool m_browserSettingsChanged; const QScopedPointer m_browserUi; - QPointer m_browserWidget; + QWidget* const m_browserWidget; #endif QScopedPointer m_temporaryGroup; diff --git a/src/gui/group/EditGroupWidgetBrowser.ui b/src/gui/group/EditGroupWidgetBrowser.ui index 94069f7e6..dfe4b5971 100644 --- a/src/gui/group/EditGroupWidgetBrowser.ui +++ b/src/gui/group/EditGroupWidgetBrowser.ui @@ -1,34 +1,7 @@ EditGroupWidgetBrowser - - - - 0 - 0 - 539 - 523 - - - - Edit Group - - - QFrame::NoFrame - - - QFrame::Plain - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustToContents - - - true - - + 0 @@ -59,127 +32,126 @@ -    -   0 -   -   -   10 -   -   -   0 -   -   -   0 -    -    -   10 -    -    -   8 -    -    -    -    -   Hide entries from browser extension: -    -    -   Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter -    -    -    -    -    -    -   Hide entries from browser extension toggle for this and sub groups -    -    -    -    -    -    -   Skip Auto-Submit for entries: -    -    -   Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter -    -    -    -    -    -    -   Skip Auto-Submit toggle for this and sub groups -    -    -    -    -    -    -   Use entries only with HTTP Basic Auth: -    -    -   Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter -    -    -    -    -    -    -   Only HTTP Auth toggle for this and sub groups -    -    -    -    -   -    -    Do not use entries with HTTP Basic Auth: -    -    -    Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter -    -    -    -    -    -    -    Do not use HTTP Auth toggle for this and sub groups -    -    -    + + 0 + + + 10 + + + 0 + + + 0 + + + 10 + + + 8 + + + + + Hide entries from browser extension: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Hide entries from browser extension toggle for this and sub groups + + + + + + + Skip Auto-Submit for entries: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Skip Auto-Submit toggle for this and sub groups + + + + + + + Use entries only with HTTP Basic Auth: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Only HTTP Auth toggle for this and sub groups + + + + + + + Do not use entries with HTTP Basic Auth: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Do not use HTTP Auth toggle for this and sub groups + + + -   -    -    Omit WWW subdomain from matching: -    -    -    Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter -    -    -    -    -    -    -    Omit WWW subdomain from matching toggle for this and sub groups -    -    -    -    -    -    -    Qt::Vertical -    -    -    -    20 -    40 -    -    -    -    -    -   + + + Omit WWW subdomain from matching: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Omit WWW subdomain from matching toggle for this and sub groups + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + - browserIntegrationHideEntriesComboBox browserIntegrationSkipAutoSubmitComboBox diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp index 3b5fbe60b..18b926dc2 100644 --- a/src/gui/group/GroupModel.cpp +++ b/src/gui/group/GroupModel.cpp @@ -74,7 +74,7 @@ int GroupModel::columnCount(const QModelIndex& parent) const QModelIndex GroupModel::index(int row, int column, const QModelIndex& parent) const { if (!hasIndex(row, column, parent)) { - return QModelIndex(); + return {}; } Group* group; @@ -91,7 +91,7 @@ QModelIndex GroupModel::index(int row, int column, const QModelIndex& parent) co QModelIndex GroupModel::parent(const QModelIndex& index) const { if (!index.isValid()) { - return QModelIndex(); + return {}; } return parent(groupFromIndex(index)); @@ -103,7 +103,7 @@ QModelIndex GroupModel::parent(Group* group) const if (!parentGroup) { // index is already the root group - return QModelIndex(); + return {}; } else { const Group* grandParentGroup = parentGroup->parentGroup(); if (!grandParentGroup) { @@ -118,7 +118,7 @@ QModelIndex GroupModel::parent(Group* group) const QVariant GroupModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) { - return QVariant(); + return {}; } Group* group = groupFromIndex(index); @@ -145,7 +145,7 @@ QVariant GroupModel::data(const QModelIndex& index, int role) const } return tooltip; } else { - return QVariant(); + return {}; } } @@ -155,7 +155,7 @@ QVariant GroupModel::headerData(int section, Qt::Orientation orientation, int ro Q_UNUSED(orientation); Q_UNUSED(role); - return QVariant(); + return {}; } QModelIndex GroupModel::index(Group* group) const diff --git a/src/gui/osutils/OSUtilsBase.cpp b/src/gui/osutils/OSUtilsBase.cpp index a8395bb74..d0d83f8f5 100644 --- a/src/gui/osutils/OSUtilsBase.cpp +++ b/src/gui/osutils/OSUtilsBase.cpp @@ -22,9 +22,7 @@ OSUtilsBase::OSUtilsBase(QObject* parent) { } -OSUtilsBase::~OSUtilsBase() -{ -} +OSUtilsBase::~OSUtilsBase() = default; bool OSUtilsBase::setPreventScreenCapture(QWindow*, bool) const { diff --git a/src/gui/osutils/ScreenLockListener.cpp b/src/gui/osutils/ScreenLockListener.cpp index 2c1ba055a..1e3e4e47c 100644 --- a/src/gui/osutils/ScreenLockListener.cpp +++ b/src/gui/osutils/ScreenLockListener.cpp @@ -25,6 +25,4 @@ ScreenLockListener::ScreenLockListener(QWidget* parent) connect(m_listener, SIGNAL(screenLocked()), this, SIGNAL(screenLocked())); } -ScreenLockListener::~ScreenLockListener() -{ -} +ScreenLockListener::~ScreenLockListener() = default; diff --git a/src/gui/osutils/macutils/AppKitImpl.mm b/src/gui/osutils/macutils/AppKitImpl.mm index a94d9efb6..c700c06d5 100644 --- a/src/gui/osutils/macutils/AppKitImpl.mm +++ b/src/gui/osutils/macutils/AppKitImpl.mm @@ -38,10 +38,7 @@ name:NSWorkspaceSessionDidResignActiveNotification object:nil]; - [[NSDistributedNotificationCenter defaultCenter] addObserver:self - selector:@selector(interfaceThemeChanged:) - name:@"AppleInterfaceThemeChangedNotification" - object:nil]; + [NSApp addObserver:self forKeyPath:@"effectiveAppearance" options:NSKeyValueObservingOptionNew context:nil]; // Unfortunately, there is no notification for a wallpaper change, which affects // the status bar colour on macOS Big Sur, but we can at least subscribe to this. @@ -67,14 +64,29 @@ } } -// -// Light / dark theme toggled -// -- (void) interfaceThemeChanged:(NSNotification*) notification +- (void) observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { - Q_UNUSED(notification); - if (m_appkit) { - emit m_appkit->interfaceThemeChanged(); + Q_UNUSED(object) + Q_UNUSED(change) + Q_UNUSED(context) + if ([keyPath isEqualToString:@"effectiveAppearance"]) { + if (m_appkit) { + + void (^emitBlock)(void) = ^{ + emit m_appkit->interfaceThemeChanged(); + }; + + if(@available(macOS 11.0, *)) { + // Not sure why exactly this call is needed, but Apple sample code uses it so it's best to use it here too + [NSApp.effectiveAppearance performAsCurrentDrawingAppearance:emitBlock]; + } + else { + emitBlock(); + } + } } } @@ -127,10 +139,7 @@ // - (bool) isDarkMode { - NSDictionary* dict = [[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain]; - id style = [dict objectForKey:@"AppleInterfaceStyle"]; - return ( style && [style isKindOfClass:[NSString class]] - && NSOrderedSame == [style caseInsensitiveCompare:@"dark"] ); + return [NSApp.effectiveAppearance.name isEqualToString:NSAppearanceNameDarkAqua]; } diff --git a/src/gui/osutils/nixutils/NixUtils.cpp b/src/gui/osutils/nixutils/NixUtils.cpp index 030b54582..ebbea91d3 100644 --- a/src/gui/osutils/nixutils/NixUtils.cpp +++ b/src/gui/osutils/nixutils/NixUtils.cpp @@ -83,9 +83,7 @@ NixUtils::NixUtils(QObject* parent) sessionBus.callWithCallback(msg, this, SLOT(handleColorSchemeRead(QDBusVariant))); } -NixUtils::~NixUtils() -{ -} +NixUtils::~NixUtils() = default; bool NixUtils::isDarkMode() const { diff --git a/src/gui/reports/ReportsDialog.cpp b/src/gui/reports/ReportsDialog.cpp index e1da39839..123e02c2c 100644 --- a/src/gui/reports/ReportsDialog.cpp +++ b/src/gui/reports/ReportsDialog.cpp @@ -95,9 +95,7 @@ ReportsDialog::ReportsDialog(QWidget* parent) connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToMainView(bool))); } -ReportsDialog::~ReportsDialog() -{ -} +ReportsDialog::~ReportsDialog() = default; void ReportsDialog::load(const QSharedPointer& db) { diff --git a/src/gui/reports/ReportsDialog.h b/src/gui/reports/ReportsDialog.h index 25cb623eb..915c20eb9 100644 --- a/src/gui/reports/ReportsDialog.h +++ b/src/gui/reports/ReportsDialog.h @@ -41,9 +41,7 @@ namespace Ui class IReportsPage { public: - virtual ~IReportsPage() - { - } + virtual ~IReportsPage() = default; virtual QString name() = 0; virtual QIcon icon() = 0; virtual QWidget* createWidget() = 0; diff --git a/src/gui/reports/ReportsWidget.cpp b/src/gui/reports/ReportsWidget.cpp index 184434116..c822f4782 100644 --- a/src/gui/reports/ReportsWidget.cpp +++ b/src/gui/reports/ReportsWidget.cpp @@ -22,9 +22,7 @@ ReportsWidget::ReportsWidget(QWidget* parent) { } -ReportsWidget::~ReportsWidget() -{ -} +ReportsWidget::~ReportsWidget() = default; /** * Load the database to be configured by this page and initialize the page. diff --git a/src/gui/reports/ReportsWidgetHealthcheck.cpp b/src/gui/reports/ReportsWidgetHealthcheck.cpp index d23829031..19da39e02 100644 --- a/src/gui/reports/ReportsWidgetHealthcheck.cpp +++ b/src/gui/reports/ReportsWidgetHealthcheck.cpp @@ -158,9 +158,7 @@ ReportsWidgetHealthcheck::ReportsWidgetHealthcheck(QWidget* parent) new QShortcut(Qt::Key_Delete, this, SLOT(deleteSelectedEntries())); } -ReportsWidgetHealthcheck::~ReportsWidgetHealthcheck() -{ -} +ReportsWidgetHealthcheck::~ReportsWidgetHealthcheck() = default; void ReportsWidgetHealthcheck::addHealthRow(QSharedPointer health, Group* group, diff --git a/src/gui/reports/ReportsWidgetHibp.cpp b/src/gui/reports/ReportsWidgetHibp.cpp index 86be3d92f..d4ae1f4d6 100644 --- a/src/gui/reports/ReportsWidgetHibp.cpp +++ b/src/gui/reports/ReportsWidgetHibp.cpp @@ -79,9 +79,7 @@ ReportsWidgetHibp::ReportsWidgetHibp(QWidget* parent) new QShortcut(Qt::Key_Delete, this, SLOT(deleteSelectedEntries())); } -ReportsWidgetHibp::~ReportsWidgetHibp() -{ -} +ReportsWidgetHibp::~ReportsWidgetHibp() = default; void ReportsWidgetHibp::loadSettings(QSharedPointer db) { @@ -133,7 +131,7 @@ void ReportsWidgetHibp::makeHibpTable() } } - // Sort decending by the number the password has been exposed + // Sort descending by the number the password has been exposed qSort(items.begin(), items.end(), [](QPair& lhs, QPair& rhs) { return lhs.second > rhs.second; }); diff --git a/src/gui/reports/ReportsWidgetStatistics.cpp b/src/gui/reports/ReportsWidgetStatistics.cpp index 280ed4de5..e8068b564 100644 --- a/src/gui/reports/ReportsWidgetStatistics.cpp +++ b/src/gui/reports/ReportsWidgetStatistics.cpp @@ -41,9 +41,7 @@ ReportsWidgetStatistics::ReportsWidgetStatistics(QWidget* parent) m_ui->statisticsTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); } -ReportsWidgetStatistics::~ReportsWidgetStatistics() -{ -} +ReportsWidgetStatistics::~ReportsWidgetStatistics() = default; void ReportsWidgetStatistics::addStatsRow(QString name, QString value, bool bad, QString badMsg) { diff --git a/src/gui/settings/SettingsWidget.cpp b/src/gui/settings/SettingsWidget.cpp index 5053bf983..779d076c0 100644 --- a/src/gui/settings/SettingsWidget.cpp +++ b/src/gui/settings/SettingsWidget.cpp @@ -22,9 +22,7 @@ SettingsWidget::SettingsWidget(QWidget* parent) { } -SettingsWidget::~SettingsWidget() -{ -} +SettingsWidget::~SettingsWidget() = default; /** * Switch between simple mode (the default) and advanced mode. diff --git a/src/gui/styles/base/BaseStyle.cpp b/src/gui/styles/base/BaseStyle.cpp index 4c9aabb77..b74874bc1 100644 --- a/src/gui/styles/base/BaseStyle.cpp +++ b/src/gui/styles/base/BaseStyle.cpp @@ -773,9 +773,7 @@ namespace Phantom static MenuItemMetrics ofFontHeight(int fontHeight); private: - MenuItemMetrics() - { - } + MenuItemMetrics() = default; }; MenuItemMetrics MenuItemMetrics::ofFontHeight(int fontHeight) @@ -3979,14 +3977,14 @@ QSize BaseStyle::sizeFromContents(ContentsType type, if (!btn->icon.isNull() || !btn->text.isEmpty()) margins = proxy()->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing : PM_CheckBoxLabelSpacing, option, widget); - return QSize(size.width() + w + margins, qMax(size.height(), h)); + return {size.width() + w + margins, qMax(size.height(), h)}; } case CT_MenuBarItem: { int fontHeight = option ? option->fontMetrics.height() : size.height(); auto w = static_cast(fontHeight * Ph::MenuBar_HorizontalPaddingFontRatio); auto h = static_cast(fontHeight * Ph::MenuBar_VerticalPaddingFontRatio); int line = Ph::dpiScaled(1); - return QSize(size.width() + w * 2, size.height() + h * 2 + line); + return {size.width() + w * 2, size.height() + h * 2 + line}; } case CT_MenuItem: { auto menuItem = qstyleoption_cast(option); @@ -4113,7 +4111,7 @@ QSize BaseStyle::sizeFromContents(ContentsType type, xadd += 2; yadd += 2; } - return QSize(size.width() + xadd, size.height() + yadd); + return {size.width() + xadd, size.height() + yadd}; } case CT_ItemViewItem: { auto vopt = qstyleoption_cast(option); @@ -4335,7 +4333,7 @@ QRect BaseStyle::subControlRect(ComplexControl control, break; case SC_SpinBoxDown: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) - return QRect(); + return {}; rect = QRect(x, center, buttonWidth, spinbox->rect.bottom() - center - fw + 1); break; @@ -4429,13 +4427,13 @@ QRect BaseStyle::subControlRect(ComplexControl control, case CC_ComboBox: { auto cb = qstyleoption_cast(option); if (!cb) - return QRect(); + return {}; int frame = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, cb, widget) : 0; QRect r = option->rect; r.adjust(frame, frame, -frame, -frame); int dim = qMin(r.width(), r.height()); if (dim < 1) - return QRect(); + return {}; switch (subControl) { case SC_ComboBoxFrame: return cb->rect; diff --git a/src/gui/styles/base/phantomcolor.h b/src/gui/styles/base/phantomcolor.h index f9573ba65..b99761e9f 100644 --- a/src/gui/styles/base/phantomcolor.h +++ b/src/gui/styles/base/phantomcolor.h @@ -42,9 +42,7 @@ namespace Phantom struct Rgb { qreal r, g, b; - Rgb() - { - } + Rgb() = default; Rgb(qreal r, qreal g, qreal b) : r(r) , g(g) @@ -78,9 +76,7 @@ namespace Phantom struct Hsl { qreal h, s, l; - Hsl() - { - } + Hsl() = default; Hsl(qreal h, qreal s, qreal l) : h(h) , s(s) diff --git a/src/gui/tag/TagModel.cpp b/src/gui/tag/TagModel.cpp index 99f253270..dfa4e943d 100644 --- a/src/gui/tag/TagModel.cpp +++ b/src/gui/tag/TagModel.cpp @@ -33,9 +33,7 @@ TagModel::TagModel(QObject* parent) << qMakePair(tr("Weak Passwords"), QString("is:weak")); } -TagModel::~TagModel() -{ -} +TagModel::~TagModel() = default; void TagModel::setDatabase(QSharedPointer db) { diff --git a/src/gui/tag/TagView.cpp b/src/gui/tag/TagView.cpp index 82a977f3e..8afdac44a 100644 --- a/src/gui/tag/TagView.cpp +++ b/src/gui/tag/TagView.cpp @@ -76,14 +76,14 @@ void TagView::contextMenuRequested(const QPoint& pos) if (type == TagModel::SAVED_SEARCH) { // Allow deleting saved searches QMenu menu; - auto action = menu.exec({new QAction(icons()->icon("trash"), tr("Remove Search"))}, mapToGlobal(pos)); + auto action = menu.exec({new QAction(icons()->icon("trash"), tr("Remove Search"), nullptr)}, mapToGlobal(pos)); if (action) { m_db->metadata()->deleteSavedSearch(index.data(Qt::DisplayRole).toString()); } } else if (type == TagModel::TAG) { // Allow removing tags from all entries in a database QMenu menu; - auto action = menu.exec({new QAction(icons()->icon("trash"), tr("Remove Tag"))}, mapToGlobal(pos)); + auto action = menu.exec({new QAction(icons()->icon("trash"), tr("Remove Tag"), nullptr)}, mapToGlobal(pos)); if (action) { auto tag = index.data(Qt::DisplayRole).toString(); auto ans = MessageBox::question(this, diff --git a/src/gui/tag/TagsEdit.cpp b/src/gui/tag/TagsEdit.cpp index 7d5b657ce..6a8becbd0 100644 --- a/src/gui/tag/TagsEdit.cpp +++ b/src/gui/tag/TagsEdit.cpp @@ -238,11 +238,11 @@ struct TagsEdit::Impl auto const e = std::end(tags); if (cursorVisible()) { auto const m = b + static_cast(editing_index); - calcRects(lt, row, r, fm, std::make_pair(b, m)); + calcRects(lt, row, r, fm, std::pair(b, m)); calcEditorRect(lt, row, r, fm, m); - calcRects(lt, row, r, fm, std::make_pair(m + 1, e)); + calcRects(lt, row, r, fm, std::pair(m + 1, e)); } else { - calcRects(lt, row, r, fm, std::make_pair(b, e)); + calcRects(lt, row, r, fm, std::pair(b, e)); } r.setBottom(lt.y() + fm.height() + fm.leading() + tag_inner.top() + tag_inner.bottom() - 1); @@ -667,8 +667,7 @@ void TagsEdit::paintEvent(QPaintEvent*) // tags impl->drawTags( - p, - std::make_pair(impl->tags.cbegin(), std::next(impl->tags.cbegin(), std::ptrdiff_t(impl->editing_index)))); + p, std::pair(impl->tags.cbegin(), std::next(impl->tags.cbegin(), std::ptrdiff_t(impl->editing_index)))); // draw not terminated tag auto const formatting = impl->formatting(); @@ -683,12 +682,10 @@ void TagsEdit::paintEvent(QPaintEvent*) // tags impl->drawTags( - p, - std::make_pair(std::next(impl->tags.cbegin(), std::ptrdiff_t(impl->editing_index + 1)), impl->tags.cend())); + p, std::pair(std::next(impl->tags.cbegin(), std::ptrdiff_t(impl->editing_index + 1)), impl->tags.cend())); } else { - impl->drawTags(p, - std::make_pair(EmptySkipIterator(impl->tags.begin(), impl->tags.end()), - EmptySkipIterator(impl->tags.end()))); + impl->drawTags( + p, std::pair(EmptySkipIterator(impl->tags.begin(), impl->tags.end()), EmptySkipIterator(impl->tags.end()))); } } diff --git a/src/gui/wizard/NewDatabaseWizard.cpp b/src/gui/wizard/NewDatabaseWizard.cpp index 03bede632..7394e1fc5 100644 --- a/src/gui/wizard/NewDatabaseWizard.cpp +++ b/src/gui/wizard/NewDatabaseWizard.cpp @@ -63,9 +63,7 @@ NewDatabaseWizard::NewDatabaseWizard(QWidget* parent) pageFrame->setPalette(framePalette); } -NewDatabaseWizard::~NewDatabaseWizard() -{ -} +NewDatabaseWizard::~NewDatabaseWizard() = default; bool NewDatabaseWizard::validateCurrentPage() { diff --git a/src/gui/wizard/NewDatabaseWizardPage.cpp b/src/gui/wizard/NewDatabaseWizardPage.cpp index dd2d69d39..f1acd943c 100644 --- a/src/gui/wizard/NewDatabaseWizardPage.cpp +++ b/src/gui/wizard/NewDatabaseWizardPage.cpp @@ -31,9 +31,7 @@ NewDatabaseWizardPage::NewDatabaseWizardPage(QWidget* parent) connect(m_ui->advancedSettingsButton, SIGNAL(clicked()), SLOT(toggleAdvancedSettings())); } -NewDatabaseWizardPage::~NewDatabaseWizardPage() -{ -} +NewDatabaseWizardPage::~NewDatabaseWizardPage() = default; /** * Set the database settings page widget for this wizard page. diff --git a/src/gui/wizard/NewDatabaseWizardPageDatabaseKey.cpp b/src/gui/wizard/NewDatabaseWizardPageDatabaseKey.cpp index 3cd2abd31..b8847a141 100644 --- a/src/gui/wizard/NewDatabaseWizardPageDatabaseKey.cpp +++ b/src/gui/wizard/NewDatabaseWizardPageDatabaseKey.cpp @@ -27,6 +27,4 @@ NewDatabaseWizardPageDatabaseKey::NewDatabaseWizardPageDatabaseKey(QWidget* pare setSubTitle(tr("A set of credentials known only to you that protects your database.")); } -NewDatabaseWizardPageDatabaseKey::~NewDatabaseWizardPageDatabaseKey() -{ -} +NewDatabaseWizardPageDatabaseKey::~NewDatabaseWizardPageDatabaseKey() = default; diff --git a/src/gui/wizard/NewDatabaseWizardPageEncryption.cpp b/src/gui/wizard/NewDatabaseWizardPageEncryption.cpp index 743f7bcc2..d97abf1f4 100644 --- a/src/gui/wizard/NewDatabaseWizardPageEncryption.cpp +++ b/src/gui/wizard/NewDatabaseWizardPageEncryption.cpp @@ -28,6 +28,4 @@ NewDatabaseWizardPageEncryption::NewDatabaseWizardPageEncryption(QWidget* parent "Don't worry, you can change them later in the database settings.")); } -NewDatabaseWizardPageEncryption::~NewDatabaseWizardPageEncryption() -{ -} +NewDatabaseWizardPageEncryption::~NewDatabaseWizardPageEncryption() = default; diff --git a/src/gui/wizard/NewDatabaseWizardPageMetaData.cpp b/src/gui/wizard/NewDatabaseWizardPageMetaData.cpp index f4e2712fb..309895703 100644 --- a/src/gui/wizard/NewDatabaseWizardPageMetaData.cpp +++ b/src/gui/wizard/NewDatabaseWizardPageMetaData.cpp @@ -27,6 +27,4 @@ NewDatabaseWizardPageMetaData::NewDatabaseWizardPageMetaData(QWidget* parent) setSubTitle(tr("Please fill in the display name and an optional description for your new database:")); } -NewDatabaseWizardPageMetaData::~NewDatabaseWizardPageMetaData() -{ -} \ No newline at end of file +NewDatabaseWizardPageMetaData::~NewDatabaseWizardPageMetaData() = default; \ No newline at end of file diff --git a/src/keeshare/ShareExport.cpp b/src/keeshare/ShareExport.cpp index 670a2911e..33328cfab 100644 --- a/src/keeshare/ShareExport.cpp +++ b/src/keeshare/ShareExport.cpp @@ -173,7 +173,7 @@ ShareObserver::Result ShareExport::intoContainer(const QString& resolvedPath, KeePass2Writer writer; if (!writer.writeDatabase(&buffer, targetDb.data())) { - qWarning("Serializing export dabase failed: %s.", writer.errorString().toLatin1().data()); + qWarning("Serializing export database failed: %s.", writer.errorString().toLatin1().data()); return {reference.path, ShareObserver::Result::Error, writer.errorString()}; } @@ -202,7 +202,7 @@ ShareObserver::Result ShareExport::intoContainer(const QString& resolvedPath, } else { QString error; if (!targetDb->saveAs(resolvedPath, Database::Atomic, {}, &error)) { - qWarning("Exporting dabase failed: %s.", error.toLatin1().data()); + qWarning("Exporting database failed: %s.", error.toLatin1().data()); return {resolvedPath, ShareObserver::Result::Error, error}; } } diff --git a/src/keys/ChallengeResponseKey.cpp b/src/keys/ChallengeResponseKey.cpp index 6502e3714..eb52b7d09 100644 --- a/src/keys/ChallengeResponseKey.cpp +++ b/src/keys/ChallengeResponseKey.cpp @@ -30,7 +30,7 @@ ChallengeResponseKey::ChallengeResponseKey(YubiKeySlot keySlot) QByteArray ChallengeResponseKey::rawKey() const { - return QByteArray(m_key.data(), m_key.size()); + return {m_key.data(), static_cast(m_key.size())}; } void ChallengeResponseKey::setRawKey(const QByteArray&) diff --git a/src/keys/FileKey.cpp b/src/keys/FileKey.cpp index b50ffb30a..167b0462d 100644 --- a/src/keys/FileKey.cpp +++ b/src/keys/FileKey.cpp @@ -161,7 +161,7 @@ bool FileKey::load(const QString& fileName, QString* errorMsg) */ QByteArray FileKey::rawKey() const { - return QByteArray(m_key.data(), m_key.size()); + return {m_key.data(), int(m_key.size())}; } void FileKey::setRawKey(const QByteArray& data) diff --git a/src/keys/PasswordKey.cpp b/src/keys/PasswordKey.cpp index 60006dc30..7e0670647 100644 --- a/src/keys/PasswordKey.cpp +++ b/src/keys/PasswordKey.cpp @@ -44,7 +44,7 @@ QByteArray PasswordKey::rawKey() const if (!m_isInitialized) { return {}; } - return QByteArray(m_key.data(), m_key.size()); + return {m_key.data(), int(m_key.size())}; } void PasswordKey::setRawKey(const QByteArray& data) diff --git a/src/keys/drivers/YubiKeyInterfacePCSC.cpp b/src/keys/drivers/YubiKeyInterfacePCSC.cpp index e871d63d4..88447519d 100644 --- a/src/keys/drivers/YubiKeyInterfacePCSC.cpp +++ b/src/keys/drivers/YubiKeyInterfacePCSC.cpp @@ -107,7 +107,7 @@ namespace rv = SCardListReaders(context, nullptr, mszReaders, &dwReaders); if (rv == SCARD_S_SUCCESS) { char* readhead = mszReaders; - // Names are seperated by a null byte + // Names are separated by a null byte // The list is terminated by two null bytes while (*readhead != '\0') { QString reader = QString::fromUtf8(readhead); @@ -563,7 +563,7 @@ bool YubiKeyInterfacePCSC::findValidKeys() &dwActiveProtocol); if (rv == SCARD_S_SUCCESS) { - // Read the potocol and the ATR record + // Read the protocol and the ATR record char pbReader[MAX_READERNAME] = {0}; SCUINT dwReaderLen = sizeof(pbReader); SCUINT dwState = 0; @@ -683,7 +683,7 @@ YubiKeyInterfacePCSC::challenge(YubiKeySlot slot, const QByteArray& challenge, B So we wait for the user to re-present it to clear the time-out This condition usually only happens when the key times out after the initial key listing, because performTestChallenge implicitly - resets the key (see commnt above) */ + resets the key (see comment above) */ if (ret == YubiKey::ChallengeResult::YCR_SUCCESS) { emit challengeCompleted(); m_mutex.unlock(); @@ -728,7 +728,7 @@ YubiKey::ChallengeResult YubiKeyInterfacePCSC::performChallenge(void* key, * configurations even work, some docs say avoid it. * * In fact, the Yubikey always assumes the last byte (nr. 64) - * and all bytes of the same value preceeding it to be padding. + * and all bytes of the same value preceding it to be padding. * This does not conform fully to PKCS7, because the the actual value * of the padding bytes is ignored. */ diff --git a/src/keys/drivers/YubiKeyStub.cpp b/src/keys/drivers/YubiKeyStub.cpp index 5609c4b4a..d897ccd56 100644 --- a/src/keys/drivers/YubiKeyStub.cpp +++ b/src/keys/drivers/YubiKeyStub.cpp @@ -18,9 +18,7 @@ #include "YubiKey.h" -YubiKey::YubiKey() -{ -} +YubiKey::YubiKey() = default; YubiKey* YubiKey::m_instance(Q_NULLPTR); diff --git a/src/main.cpp b/src/main.cpp index 047e44740..f426a76e9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -120,11 +120,12 @@ int main(int argc, char** argv) // Get correct case for Windows filenames (fixes #7139) for (const auto& file : parser.positionalArguments()) { const auto fileInfo = QFileInfo(file); - WIN32_FIND_DATA findFileData; + WIN32_FIND_DATAW findFileData; HANDLE hFind; - hFind = FindFirstFile(fileInfo.absoluteFilePath().toUtf8(), &findFileData); + const wchar_t* absolutePathWchar = reinterpret_cast(fileInfo.absoluteFilePath().utf16()); + hFind = FindFirstFileW(absolutePathWchar, &findFileData); if (hFind != INVALID_HANDLE_VALUE) { - fileNames << QString("%1/%2").arg(fileInfo.absolutePath(), QString::fromUtf8(findFileData.cFileName)); + fileNames << QString("%1/%2").arg(fileInfo.absolutePath(), QString::fromWCharArray(findFileData.cFileName)); FindClose(hFind); } } @@ -155,6 +156,14 @@ int main(int argc, char** argv) return EXIT_SUCCESS; } + if (parser.isSet(lockOption)) { + qWarning() << QObject::tr("KeePassXC is not running. No open database to lock").toUtf8().constData(); + + // still return with EXIT_SUCCESS because when used within a script for ensuring that there is no unlocked + // keepass database (e.g. screen locking) we can consider it as successful + return EXIT_SUCCESS; + } + if (!Crypto::init()) { QString error = QObject::tr("Fatal error while testing the cryptographic functions."); error.append("\n"); diff --git a/src/post_install/CMakeLists.txt b/src/post_install/CMakeLists.txt index 359c891f3..1adc4740b 100644 --- a/src/post_install/CMakeLists.txt +++ b/src/post_install/CMakeLists.txt @@ -1,5 +1,5 @@ # The install commands in this subdirectory will be executed after all the install commands in the -# current scope are ran. It is required for correct functtioning of macdeployqt. +# current scope are ran. It is required for correct functioning of macdeployqt. if(APPLE AND WITH_APP_BUNDLE) # Run macdeloyqt on the main app and any extra binaries and plugins as specified by the diff --git a/src/sshagent/OpenSSHKey.cpp b/src/sshagent/OpenSSHKey.cpp index e7a2a9b85..e6b21c863 100644 --- a/src/sshagent/OpenSSHKey.cpp +++ b/src/sshagent/OpenSSHKey.cpp @@ -30,6 +30,7 @@ const QString OpenSSHKey::TYPE_DSA_PRIVATE = "DSA PRIVATE KEY"; const QString OpenSSHKey::TYPE_RSA_PRIVATE = "RSA PRIVATE KEY"; const QString OpenSSHKey::TYPE_OPENSSH_PRIVATE = "OPENSSH PRIVATE KEY"; +const QString OpenSSHKey::OPENSSH_CIPHER_SUFFIX = "@openssh.com"; OpenSSHKey::OpenSSHKey(QObject* parent) : QObject(parent) @@ -310,9 +311,16 @@ bool OpenSSHKey::openKey(const QString& passphrase) QByteArray rawData = m_rawData; if (m_cipherName != "none") { - auto cipherMode = SymmetricCipher::stringToMode(m_cipherName); + QString l_cipherName(m_cipherName); + if (l_cipherName.endsWith(OPENSSH_CIPHER_SUFFIX)) { + l_cipherName.remove(OPENSSH_CIPHER_SUFFIX); + } + auto cipherMode = SymmetricCipher::stringToMode(l_cipherName); if (cipherMode == SymmetricCipher::InvalidMode) { - m_error = tr("Unknown cipher: %1").arg(m_cipherName); + m_error = tr("Unknown cipher: %1").arg(l_cipherName); + return false; + } else if (cipherMode == SymmetricCipher::Aes256_GCM) { + m_error = tr("AES-256/GCM is currently not supported"); return false; } @@ -325,7 +333,7 @@ bool OpenSSHKey::openKey(const QString& passphrase) } int keySize = cipher->keySize(cipherMode); - int blockSize = 16; + int ivSize = cipher->ivSize(cipherMode); BinaryStream optionStream(&m_kdfOptions); @@ -335,7 +343,7 @@ bool OpenSSHKey::openKey(const QString& passphrase) optionStream.readString(salt); optionStream.read(rounds); - QByteArray decryptKey(keySize + blockSize, '\0'); + QByteArray decryptKey(keySize + ivSize, '\0'); try { auto baPass = passphrase.toUtf8(); auto pwhash = Botan::PasswordHashFamily::create_or_throw("Bcrypt-PBKDF")->from_iterations(rounds); @@ -351,7 +359,7 @@ bool OpenSSHKey::openKey(const QString& passphrase) } keyData = decryptKey.left(keySize); - ivData = decryptKey.right(blockSize); + ivData = decryptKey.right(ivSize); } else if (m_kdfName == "md5") { if (m_cipherIV.length() < 8) { m_error = tr("Cipher IV is too short for MD5 kdf"); diff --git a/src/sshagent/OpenSSHKey.h b/src/sshagent/OpenSSHKey.h index 78ccf7192..a42e433de 100644 --- a/src/sshagent/OpenSSHKey.h +++ b/src/sshagent/OpenSSHKey.h @@ -58,6 +58,7 @@ public: static const QString TYPE_DSA_PRIVATE; static const QString TYPE_RSA_PRIVATE; static const QString TYPE_OPENSSH_PRIVATE; + static const QString OPENSSH_CIPHER_SUFFIX; private: enum KeyPart diff --git a/src/sshagent/SSHAgent.cpp b/src/sshagent/SSHAgent.cpp index 847691221..c8804bcc7 100644 --- a/src/sshagent/SSHAgent.cpp +++ b/src/sshagent/SSHAgent.cpp @@ -433,7 +433,7 @@ bool SSHAgent::listIdentities(QList>& list) * Check if this identity is loaded in the SSH Agent. * * @param key identity to remove - * @param loaded is the key laoded + * @param loaded is the key loaded * @return true on success */ bool SSHAgent::checkIdentity(const OpenSSHKey& key, bool& loaded) diff --git a/src/totp/totp.cpp b/src/totp/totp.cpp index 82d9bb832..85919c55d 100644 --- a/src/totp/totp.cpp +++ b/src/totp/totp.cpp @@ -49,11 +49,11 @@ static QString getNameForHashType(const Totp::Algorithm hashType) { switch (hashType) { case Totp::Algorithm::Sha512: - return QString("SHA512"); + return "SHA512"; case Totp::Algorithm::Sha256: - return QString("SHA256"); + return "SHA256"; default: - return QString("SHA1"); + return "SHA1"; } } diff --git a/src/touchid/TouchID.mm b/src/touchid/TouchID.mm index 688ddc451..cc858a89a 100644 --- a/src/touchid/TouchID.mm +++ b/src/touchid/TouchID.mm @@ -110,7 +110,7 @@ bool TouchID::storeKey(const QString& databasePath, const QByteArray& passwordKe SymmetricCipher aes256Encrypt; if (!aes256Encrypt.init(SymmetricCipher::Aes256_GCM, SymmetricCipher::Encrypt, randomKey, randomIV)) { - debug("TouchID::storeKey - AES initialisation falied"); + debug("TouchID::storeKey - AES initialisation failed"); return false; } diff --git a/src/zxcvbn/zxcvbn.c b/src/zxcvbn/zxcvbn.c index 23792b4d6..9d355a2e2 100644 --- a/src/zxcvbn/zxcvbn.c +++ b/src/zxcvbn/zxcvbn.c @@ -60,7 +60,7 @@ /* Additional entropy to add when password is made of multiple matches. Use different * amounts depending on whether the match is at the end of the password, or in the - * middle. If the match is at the begining then there is no additional entropy. + * middle. If the match is at the beginning then there is no additional entropy. */ #define MULTI_END_ADDITION 1.0 #define MULTI_MID_ADDITION 1.75 @@ -169,7 +169,7 @@ static ZxcMatch_t *AllocMatch() static void AddResult(ZxcMatch_t **HeadRef, ZxcMatch_t *Nu, int MaxLen) { /* Adjust the entropy to be used for calculations depending on whether the passed match is - * at the begining, middle or end of the password + * at the beginning, middle or end of the password */ if (Nu->Begin) { @@ -546,7 +546,7 @@ static void AddLeetChr(uint8_t c, int IsLeet, uint8_t *Leeted, uint8_t *UnLeet) /********************************************************************************** * Given details of a word match, update it with the entropy (as natural log of - * number of possiblities) + * number of possibilities) */ static void DictionaryEntropy(ZxcMatch_t *m, DictMatchInfo_t *Extra, const uint8_t *Pwd) { @@ -1370,7 +1370,7 @@ static void RepeatMatch(ZxcMatch_t **Result, const uint8_t *Passwd, int Start, i int Len, i; uint8_t c; Passwd += Start; - /* Remember first char and the count its occurances */ + /* Remember first char and the count its occurrences */ c = *Passwd; for(Len = 1; (Len < MaxLen) && (c == Passwd[Len]); ++Len) { } @@ -1533,9 +1533,9 @@ static void SequenceMatch(ZxcMatch_t **Result, const uint8_t *Passwd, int Start, /********************************************************************************** * Matching a password is treated as a problem of finding the minimum distance - * between two vertexes in a graph. This is solved using Dijkstra's algorithm. + * between two vertices in a graph. This is solved using Dijkstra's algorithm. * - * There are a series of nodes (or vertexes in graph terminology) which correspond + * There are a series of nodes (or vertices in graph terminology) which correspond * to points between each character of the password. Also there is a start node * before the first character and an end node after the last character. * @@ -1546,7 +1546,7 @@ static void SequenceMatch(ZxcMatch_t **Result, const uint8_t *Passwd, int Start, * end node. * * Dijkstra's algorithm finds the combination of these part matches (or paths) - * which gives the lowest entropy (or smallest distance) from begining to end + * which gives the lowest entropy (or smallest distance) from beginning to end * of the password. */ diff --git a/src/zxcvbn/zxcvbn.h b/src/zxcvbn/zxcvbn.h index 9500c7a95..550680505 100644 --- a/src/zxcvbn/zxcvbn.h +++ b/src/zxcvbn/zxcvbn.h @@ -68,7 +68,7 @@ typedef enum /* Linked list of information returned in the Info arg to ZxcvbnMatch */ struct ZxcMatch { - int Begin; /* Char position of begining of match */ + int Begin; /* Char position of beginning of match */ int Length; /* Number of chars in the match */ double Entrpy; /* The entropy of the match */ double MltEnpy; /* Entropy with additional allowance for multipart password */ @@ -85,13 +85,13 @@ extern "C" { #ifdef USE_DICT_FILE /********************************************************************************** - * Read the dictionnary data from the given file. Returns 1 if OK, 0 if error. + * Read the dictionary data from the given file. Returns 1 if OK, 0 if error. * Called once at program startup. */ int ZxcvbnInit(const char *); /********************************************************************************** - * Free the dictionnary data after use. Called once at program shutdown. + * Free the dictionary data after use. Called once at program shutdown. */ void ZxcvbnUnInit(); @@ -107,7 +107,7 @@ void ZxcvbnUnInit(); * The main password matching function. May be called multiple times. * The parameters are: * Passwd The password to be tested. Null terminated string. - * UserDict User supplied dictionary words to be considered particulary bad. Passed + * UserDict User supplied dictionary words to be considered particularly bad. Passed * as a pointer to array of string pointers, with null last entry (like * the argv parameter to main()). May be null or point to empty array when * there are no user dictionary words. diff --git a/tests/TestDatabase.cpp b/tests/TestDatabase.cpp index 3b5864273..9ab9de785 100644 --- a/tests/TestDatabase.cpp +++ b/tests/TestDatabase.cpp @@ -99,6 +99,34 @@ void TestDatabase::testSave() QVERIFY(!QFile::exists(backupFilePath)); } +void TestDatabase::testSaveAs() +{ + TemporaryFile tempFile; + QVERIFY(tempFile.copyFromFile(dbFileName)); + + auto db = QSharedPointer::create(); + auto key = QSharedPointer::create(); + key->addKey(QSharedPointer::create("a")); + + QString error; + QVERIFY(db->open(tempFile.fileName(), key, &error)); + + // Happy path case when try to save as new DB. + QSignalSpy spyFilePathChanged(db.data(), SIGNAL(filePathChanged(const QString&, const QString&))); + QString newDbFileName = QStringLiteral(KEEPASSX_TEST_DATA_DIR).append("/SaveAsNewDatabase.kdbx"); + QVERIFY2(db->saveAs(newDbFileName, Database::Atomic, QString(), &error), error.toLatin1()); + QVERIFY(!db->isModified()); + QCOMPARE(spyFilePathChanged.count(), 1); + QVERIFY(QFile::exists(newDbFileName)); + QFile::remove(newDbFileName); + QVERIFY(!QFile::exists(newDbFileName)); + + // Negative case when try to save not initialized DB. + db->releaseData(); + QVERIFY2(!db->saveAs(newDbFileName, Database::Atomic, QString(), &error), error.toLatin1()); + QCOMPARE(error, QString("Could not save, database has not been initialized!")); +} + void TestDatabase::testSignals() { TemporaryFile tempFile; diff --git a/tests/TestDatabase.h b/tests/TestDatabase.h index 511703849..9f4bfab56 100644 --- a/tests/TestDatabase.h +++ b/tests/TestDatabase.h @@ -29,6 +29,7 @@ private slots: void initTestCase(); void testOpen(); void testSave(); + void testSaveAs(); void testSignals(); void testEmptyRecycleBinOnDisabled(); void testEmptyRecycleBinOnNotCreated(); diff --git a/tests/TestEntry.cpp b/tests/TestEntry.cpp index 70daff4d2..de7ef9b1c 100644 --- a/tests/TestEntry.cpp +++ b/tests/TestEntry.cpp @@ -169,7 +169,7 @@ void TestEntry::testClone() QScopedPointer entryCloneRename(entryOrg->clone(Entry::CloneRenameTitle)); QCOMPARE(entryCloneRename->uuid(), entryOrg->uuid()); QCOMPARE(entryCloneRename->title(), QString("New Title - Clone")); - // Cloning should not modify time info unless explicity requested + // Cloning should not modify time info unless explicitly requested QCOMPARE(entryCloneRename->timeInfo(), entryOrg->timeInfo()); QScopedPointer entryCloneResetTime(entryOrg->clone(Entry::CloneResetTimeInfo)); diff --git a/tests/TestFdoSecrets.cpp b/tests/TestFdoSecrets.cpp index 0f4c374a4..38a50af99 100644 --- a/tests/TestFdoSecrets.cpp +++ b/tests/TestFdoSecrets.cpp @@ -69,7 +69,7 @@ void TestFdoSecrets::testSpecialCharsInAttributeValue() e2->setTitle("titleB"); e2->attributes()->set("testAttribute", "Abc:*+.-"); - // search for custom entries via programatic API + // search for custom entries via programmatic API { const auto term = Collection::attributeToTerm("testAttribute", "OAuth::[test.name@gmail.com]"); const auto res = EntrySearcher().search({term}, root.data()); diff --git a/tests/TestKeePass1Reader.cpp b/tests/TestKeePass1Reader.cpp index 08ff8b986..18b35b5c7 100644 --- a/tests/TestKeePass1Reader.cpp +++ b/tests/TestKeePass1Reader.cpp @@ -244,7 +244,7 @@ QDateTime TestKeePass1Reader::genDT(int year, int month, int day, int hour, int { QDate date(year, month, day); QTime time(hour, min, 0); - return QDateTime(date, time, Qt::UTC); + return {date, time, Qt::UTC}; } void TestKeePass1Reader::reopenDatabase(QSharedPointer db, diff --git a/tests/TestMerge.cpp b/tests/TestMerge.cpp index fc5c58b8a..ecb37d509 100644 --- a/tests/TestMerge.cpp +++ b/tests/TestMerge.cpp @@ -79,7 +79,7 @@ void TestMerge::testMergeIntoNew() } /** - * Merging when no changes occured should not + * Merging when no changes occurred should not * have any side effect. */ void TestMerge::testMergeNoChanges() diff --git a/tests/gui/TestGuiFdoSecrets.cpp b/tests/gui/TestGuiFdoSecrets.cpp index 0f9d62040..d639d12f0 100644 --- a/tests/gui/TestGuiFdoSecrets.cpp +++ b/tests/gui/TestGuiFdoSecrets.cpp @@ -418,7 +418,7 @@ void TestGuiFdoSecrets::testServiceSearchBlockingUnlockMultiple() VERIFY(service); // when there are multiple locked databases, - // repeatly show the dialog until there is at least one unlocked collection + // repeatedly show the dialog until there is at least one unlocked collection FdoSecrets::settings()->setUnlockBeforeSearch(true); // when only unlocking the one with no exposed group, a second dialog is shown diff --git a/utils/keepassxc-snap-helper.sh b/utils/keepassxc-snap-helper.sh index e4af458fa..300b3909a 100755 --- a/utils/keepassxc-snap-helper.sh +++ b/utils/keepassxc-snap-helper.sh @@ -59,17 +59,7 @@ JSON_CHROME=$(cat << EOF EOF ) -askBrowserSnap() { - if (whiptail --title "Snap Choice" --defaultno \ - --yesno "Is this browser installed as a snap (usually NO)?" 8 60); then - # BASE_DIR="$1" - whiptail --title "Snap Choice" --msgbox "Sorry, browsers installed as snaps are not supported at this time" 8 50 - exit 0 - fi -} - setupFirefox() { - askBrowserSnap "./snap/firefox/common" JSON_OUT=${JSON_FIREFOX} INSTALL_DIR="${BASE_DIR}/.mozilla/native-messaging-hosts" } @@ -80,7 +70,6 @@ setupChrome() { } setupChromium() { - askBrowserSnap "./snap/chromium/current" JSON_OUT=${JSON_CHROME} INSTALL_DIR="${BASE_DIR}/.config/chromium/NativeMessagingHosts" }
    " + PixmapToHTML(Icons::entryIconPixmap(entry, IconSize::Medium)) + "

    " + entry->title().toHtmlEscaped() + "

    " + entry->title().toHtmlEscaped() + "
    " + formatted_entry + "
    " + caption + formatted_entry + "