mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-08-05 21:14:20 -04:00
Merge branch 'develop' into meta/release-preparation
This commit is contained in:
commit
5652018cde
15 changed files with 140 additions and 62 deletions
89
.github/CONTRIBUTING.md
vendored
89
.github/CONTRIBUTING.md
vendored
|
@ -1,31 +1,32 @@
|
||||||
# Contributing to KeePassX Reboot
|
# Contributing to KeePassXC
|
||||||
|
|
||||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
||||||
|
|
||||||
The following is a set of guidelines for contributing to KeePassX Reboot on GitHub.
|
The following is a set of guidelines for contributing to KeePassXC on GitHub.
|
||||||
These are just guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
|
These are just guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
|
||||||
|
|
||||||
#### Table Of Contents
|
#### Table of contents
|
||||||
|
|
||||||
[What should I know before I get started?](#what-should-i-know-before-i-get-started)
|
[What should I know before I get started?](#what-should-i-know-before-i-get-started)
|
||||||
* [Open Source Contribution Policy](#open-source-contribution-policy)
|
* [Open Source Contribution Policy](#open-source-contribution-policy)
|
||||||
|
|
||||||
[How Can I Contribute?](#how-can-i-contribute)
|
[How can I contribute?](#how-can-i-contribute)
|
||||||
* [Feature Requests](#feature-requests)
|
* [Feature requests](#feature-requests)
|
||||||
* [Bug Reports](#bug-reports)
|
* [Bug reports](#bug-reports)
|
||||||
* [Your First Code Contribution](#your-first-code-contribution)
|
* [Discuss with the team](#discuss-with-the-team)
|
||||||
* [Pull Requests](#pull-requests)
|
* [Your first code contribution](#your-first-code-contribution)
|
||||||
|
* [Pull requests](#pull-requests)
|
||||||
* [Translations](#translations)
|
* [Translations](#translations)
|
||||||
|
|
||||||
[Styleguides](#styleguides)
|
[Styleguides](#styleguides)
|
||||||
* [Git Branch Strategy](#git_branch_strategy)
|
* [Git branch strategy](#git-branch-strategy)
|
||||||
* [Git Commit Messages](#git-commit-messages)
|
* [Git commit messages](#git-commit-messages)
|
||||||
* [Coding Styleguide](#coding-styleguide)
|
* [Coding styleguide](#coding-styleguide)
|
||||||
|
|
||||||
|
|
||||||
## What should I know before I get started?
|
## What should I know before I get started?
|
||||||
### Open Source Contribution Policy
|
### Open Source Contribution Policy
|
||||||
[Version 0.3, 2015–11–18](https://medium.com/@jmaynard/a-contribution-policy-for-open-source-that-works-bfc4600c9d83#.i9ntbhmad)
|
**Source**: [Version 0.3, 2015–11–18](https://medium.com/@jmaynard/a-contribution-policy-for-open-source-that-works-bfc4600c9d83#.i9ntbhmad)
|
||||||
|
|
||||||
#### Policy
|
#### Policy
|
||||||
|
|
||||||
|
@ -49,35 +50,35 @@ If we reject your contribution, it means only that we do not consider it suitabl
|
||||||
* 0.3, 2011–11–19: Added “irrevocably” to “we can use” and changed “it” to “your contribution” in the “if rejected” section. Thanks to Patrick Maupin.
|
* 0.3, 2011–11–19: Added “irrevocably” to “we can use” and changed “it” to “your contribution” in the “if rejected” section. Thanks to Patrick Maupin.
|
||||||
|
|
||||||
|
|
||||||
## How Can I Contribute?
|
## How can I contribute?
|
||||||
### Feature Requests
|
### Feature requests
|
||||||
|
|
||||||
We're always looking for suggestions to improve our application. If you have a suggestion for improving an existing feature, or would like to suggest a completely new feature for KeePassX Reboot, please use the Issues section or our [Google Groups](https://groups.google.com/forum/#!forum/keepassx-reboot) forum.
|
We're always looking for suggestions to improve our application. If you have a suggestion to improve an existing feature, or would like to suggest a completely new feature for KeePassXC, please use the [issue tracker on GitHub][issues-section]. For more general discussion, try using our [Google Groups][google-groups] forum.
|
||||||
|
|
||||||
### Bug Reports
|
### Bug reports
|
||||||
|
|
||||||
Our software isn't always perfect, but we strive to always improve our work. You may file bug reports in the Issues section.
|
Our software isn't always perfect, but we strive to always improve our work. You may file bug reports in the issue tracker.
|
||||||
|
|
||||||
Before submitting a Bug Report, check if the problem has already been reported. Please refrain from opening a duplicate issue. If you want to highlight a deficiency on an existing issue, simply add a comment.
|
Before submitting a bug report, check if the problem has already been reported. Please refrain from opening a duplicate issue. If you want to add further information to an existing issue, simply add a comment on that issue.
|
||||||
|
|
||||||
### Discuss with the Team
|
### Discuss with the team
|
||||||
|
|
||||||
You can talk to the KeePassX Reboot Team about Bugs, new feature, Issue and PullRequests at our [Google Groups](https://groups.google.com/forum/#!forum/keepassx-reboot) forum
|
As with feature requests, you can talk to the KeePassXC team about bugs, new features, other issues and pull requests on the dedicated issue tracker, using the [Google Groups][google-groups] forum, or in the IRC channel on Freenode (`#keepassxc-dev` on `irc.freenode.net`, or use a [webchat link](https://webchat.freenode.net/?channels=%23keepassxc-dev)).
|
||||||
|
|
||||||
### Your First Code Contribution
|
### Your first code contribution
|
||||||
|
|
||||||
Unsure where to begin contributing to KeePassX Reboot? You can start by looking through these `beginner` and `help-wanted` issues:
|
Unsure where to begin contributing to KeePassXC? You can start by looking through these `beginner` and `help-wanted` issues:
|
||||||
|
|
||||||
* [Beginner issues][beginner] - issues which should only require a few lines of code, and a test or two.
|
* [Beginner issues][beginner] – issues which should only require a few lines of code, and a test or two.
|
||||||
* [Help wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues.
|
* ['Help wanted' issues][help-wanted] – issues which should be a bit more involved than `beginner` issues.
|
||||||
|
|
||||||
Both issue lists are sorted by total number of comments. While not perfect, number of comments is a reasonable proxy for impact a given change will have.
|
Both issue lists are sorted by total number of comments. While not perfect, looking at the number of comments on an issue can give a general idea of how much an impact a given change will have.
|
||||||
|
|
||||||
### Pull Requests
|
### Pull requests
|
||||||
|
|
||||||
Along with our desire to hear your feedback and suggestions, we're also interested in accepting direct assistance in the form of code.
|
Along with our desire to hear your feedback and suggestions, we're also interested in accepting direct assistance in the form of code.
|
||||||
|
|
||||||
All pull requests must comply with the above requirements and with the [Styleguides](#styleguides).
|
All pull requests must comply with the above requirements and with the [styleguides](#styleguides).
|
||||||
|
|
||||||
### Translations
|
### Translations
|
||||||
|
|
||||||
|
@ -86,19 +87,20 @@ Please join an existing language team or request a new one if there is none.
|
||||||
|
|
||||||
## Styleguides
|
## Styleguides
|
||||||
|
|
||||||
### Git Branch Strategy
|
### Git branch strategy
|
||||||
|
|
||||||
The Branch Strategy is based on [git-flow-lite](http://nvie.com/posts/a-successful-git-branching-model/).
|
The Branch Strategy is based on [git-flow-lite](http://nvie.com/posts/a-successful-git-branching-model/).
|
||||||
|
|
||||||
* **master** -> always points to the last release published
|
* **master** – points to the latest public release
|
||||||
* **develop** -> points to the next planned release, tested and reviewed code
|
* **develop** – points to the development of the next release, contains tested and reviewed code
|
||||||
* **feature/**[name] -> points to brand new feature in codebase, candidate for merge into develop (subject to rebase)
|
* **feature/**[name] – points to a branch with a new feature, one which is candidate for merge into develop (subject to rebase)
|
||||||
|
* **hotfix/**[id]-[description] – points to a branch with a fix for a particular issue ID
|
||||||
|
|
||||||
|
|
||||||
### Git Commit Messages
|
### Git commit messages
|
||||||
|
|
||||||
* Use the present tense ("Add feature" not "Added feature")
|
* Use the present tense ("Add feature" not "Added feature")
|
||||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
* Use the imperative mood ("Move cursor to…" not "Moves cursor to…")
|
||||||
* Limit the first line to 72 characters or less
|
* Limit the first line to 72 characters or less
|
||||||
* Reference issues and pull requests liberally
|
* Reference issues and pull requests liberally
|
||||||
* When only changing documentation, include `[ci skip]` in the commit description
|
* When only changing documentation, include `[ci skip]` in the commit description
|
||||||
|
@ -114,21 +116,21 @@ The Branch Strategy is based on [git-flow-lite](http://nvie.com/posts/a-successf
|
||||||
* :lock: `:lock:` when dealing with security
|
* :lock: `:lock:` when dealing with security
|
||||||
|
|
||||||
|
|
||||||
### Coding Styleguide
|
### Coding styleguide
|
||||||
|
|
||||||
This project follows the [Qt Coding Style](https://wiki.qt.io/Qt_Coding_Style). All submissions are expected to follow this style.
|
This project follows the [Qt Coding Style](https://wiki.qt.io/Qt_Coding_Style). All submissions are expected to follow this style.
|
||||||
|
|
||||||
In particular Code must follow the following specific rules:
|
In particular, code must stick to the following rules:
|
||||||
|
|
||||||
#### Naming Convention
|
#### Naming convention
|
||||||
`lowerCamelCase`
|
`lowerCamelCase`
|
||||||
|
|
||||||
For names made of only one word, the fist letter is lowercase.
|
For names made of only one word, the first letter should be lowercase.
|
||||||
For names made of multiple concatenated words, the first letter is lowercase and each subsequent concatenated word is capitalized.
|
For names made of multiple concatenated words, the first letter of the whole is lowercase, and the first letter of each subsequent word is capitalized.
|
||||||
|
|
||||||
#### Indention
|
#### Indention
|
||||||
For C++ files (.cpp .h): 4 spaces
|
For **C++ files** (*.cpp .h*): 4 spaces
|
||||||
For Qt-UI files (.ui): 2 spaces
|
For **Qt-UI files** (*.ui*): 2 spaces
|
||||||
|
|
||||||
#### Pointers
|
#### Pointers
|
||||||
```c
|
```c
|
||||||
|
@ -165,9 +167,8 @@ Use prefix: `m_*`
|
||||||
|
|
||||||
Example: `m_variable`
|
Example: `m_variable`
|
||||||
|
|
||||||
#### GUI Widget names
|
#### GUI widget names
|
||||||
Widget names must be related to the desired program behaviour.
|
Widget names must be related to the desired program behavior, and preferably end with the widget's classname.
|
||||||
Preferably end the name with the Widget Classname
|
|
||||||
|
|
||||||
Example: `<widget class="QCheckBox" name="rememberCheckBox">`
|
Example: `<widget class="QCheckBox" name="rememberCheckBox">`
|
||||||
|
|
||||||
|
@ -175,3 +176,5 @@ Example: `<widget class="QCheckBox" name="rememberCheckBox">`
|
||||||
|
|
||||||
[beginner]:https://github.com/keepassxreboot/keepassx/issues?q=is%3Aopen+is%3Aissue+label%3Abeginner+label%3A%22help+wanted%22+sort%3Acomments-desc
|
[beginner]:https://github.com/keepassxreboot/keepassx/issues?q=is%3Aopen+is%3Aissue+label%3Abeginner+label%3A%22help+wanted%22+sort%3Acomments-desc
|
||||||
[help-wanted]:https://github.com/keepassxreboot/keepassx/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+sort%3Acomments-desc
|
[help-wanted]:https://github.com/keepassxreboot/keepassx/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+sort%3Acomments-desc
|
||||||
|
[issues-section]:https://github.com/keepassxreboot/keepassxc/issues
|
||||||
|
[google-groups]:https://groups.google.com/forum/#!forum/keepassx-reboot
|
||||||
|
|
|
@ -98,7 +98,9 @@ QString AutoTypePlatformMac::activeWindowTitle()
|
||||||
if (windowLayer(window) == 0) {
|
if (windowLayer(window) == 0) {
|
||||||
// First toplevel window in list (front to back order)
|
// First toplevel window in list (front to back order)
|
||||||
title = windowTitle(window);
|
title = windowTitle(window);
|
||||||
break;
|
if (!title.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -353,6 +353,12 @@ void Entry::setTitle(const QString& title)
|
||||||
|
|
||||||
void Entry::setUrl(const QString& url)
|
void Entry::setUrl(const QString& url)
|
||||||
{
|
{
|
||||||
|
bool remove = url != m_attributes->value(EntryAttributes::URLKey) &&
|
||||||
|
(m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "1" ||
|
||||||
|
m_attributes->value(EntryAttributes::RememberCmdExecAttr) == "0");
|
||||||
|
if (remove) {
|
||||||
|
m_attributes->remove(EntryAttributes::RememberCmdExecAttr);
|
||||||
|
}
|
||||||
m_attributes->set(EntryAttributes::URLKey, url, m_attributes->isProtected(EntryAttributes::URLKey));
|
m_attributes->set(EntryAttributes::URLKey, url, m_attributes->isProtected(EntryAttributes::URLKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,7 +514,8 @@ Entry* Entry::clone(CloneFlags flags) const
|
||||||
entry->m_data.timeInfo.setLocationChanged(now);
|
entry->m_data.timeInfo.setLocationChanged(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & CloneRenameTitle)
|
||||||
|
entry->setTitle(entry->title() + tr(" - Clone"));
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,8 @@ public:
|
||||||
CloneNoFlags = 0,
|
CloneNoFlags = 0,
|
||||||
CloneNewUuid = 1, // generate a random uuid for the clone
|
CloneNewUuid = 1, // generate a random uuid for the clone
|
||||||
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
|
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
|
||||||
CloneIncludeHistory = 4 // clone the history items
|
CloneIncludeHistory = 4, // clone the history items
|
||||||
|
CloneRenameTitle = 8 // add "-Clone" after the original title
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(CloneFlags, CloneFlag)
|
Q_DECLARE_FLAGS(CloneFlags, CloneFlag)
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ const QString EntryAttributes::URLKey = "URL";
|
||||||
const QString EntryAttributes::NotesKey = "Notes";
|
const QString EntryAttributes::NotesKey = "Notes";
|
||||||
const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey
|
const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey
|
||||||
<< PasswordKey << URLKey << NotesKey);
|
<< PasswordKey << URLKey << NotesKey);
|
||||||
|
const QString EntryAttributes::RememberCmdExecAttr = "_EXEC_CMD";
|
||||||
|
|
||||||
EntryAttributes::EntryAttributes(QObject* parent)
|
EntryAttributes::EntryAttributes(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
|
|
|
@ -52,6 +52,7 @@ public:
|
||||||
static const QString URLKey;
|
static const QString URLKey;
|
||||||
static const QString NotesKey;
|
static const QString NotesKey;
|
||||||
static const QStringList DefaultAttributes;
|
static const QStringList DefaultAttributes;
|
||||||
|
static const QString RememberCmdExecAttr;
|
||||||
static bool isDefaultAttribute(const QString& key);
|
static bool isDefaultAttribute(const QString& key);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
|
@ -42,7 +42,11 @@ QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Grou
|
||||||
const QList<Group*> children = group->children();
|
const QList<Group*> children = group->children();
|
||||||
for (Group* childGroup : children) {
|
for (Group* childGroup : children) {
|
||||||
if (childGroup->searchingEnabled() != Group::Disable) {
|
if (childGroup->searchingEnabled() != Group::Disable) {
|
||||||
searchResult.append(searchEntries(searchTerm, childGroup, caseSensitivity));
|
if (matchGroup(searchTerm, childGroup, caseSensitivity)) {
|
||||||
|
searchResult.append(childGroup->entriesRecursive());
|
||||||
|
} else {
|
||||||
|
searchResult.append(searchEntries(searchTerm, childGroup, caseSensitivity));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,3 +73,21 @@ bool EntrySearcher::wordMatch(const QString& word, Entry* entry, Qt::CaseSensiti
|
||||||
entry->url().contains(word, caseSensitivity) ||
|
entry->url().contains(word, caseSensitivity) ||
|
||||||
entry->notes().contains(word, caseSensitivity);
|
entry->notes().contains(word, caseSensitivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntrySearcher::matchGroup(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
|
||||||
|
{
|
||||||
|
const QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
|
||||||
|
for (const QString& word : wordList) {
|
||||||
|
if (!wordMatch(word, group, caseSensitivity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntrySearcher::wordMatch(const QString& word, const Group* group, Qt::CaseSensitivity caseSensitivity)
|
||||||
|
{
|
||||||
|
return group->name().contains(word, caseSensitivity) ||
|
||||||
|
group->notes().contains(word, caseSensitivity);
|
||||||
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ private:
|
||||||
QList<Entry*> searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
|
QList<Entry*> searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
|
||||||
QList<Entry*> matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity);
|
QList<Entry*> matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity);
|
||||||
bool wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity);
|
bool wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity);
|
||||||
|
bool matchGroup(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
|
||||||
|
bool wordMatch(const QString& word, const Group* group, Qt::CaseSensitivity caseSensitivity);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSX_ENTRYSEARCHER_H
|
#endif // KEEPASSX_ENTRYSEARCHER_H
|
||||||
|
|
|
@ -388,7 +388,7 @@ void KeePass2XmlReader::parseBinaries()
|
||||||
QString id = attr.value("ID").toString();
|
QString id = attr.value("ID").toString();
|
||||||
|
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
if (attr.value("Compressed").compare("True", Qt::CaseInsensitive) == 0) {
|
if (attr.value("Compressed").compare(QLatin1String("True"), Qt::CaseInsensitive) == 0) {
|
||||||
data = readCompressedBinary();
|
data = readCompressedBinary();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
#include <QCheckBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
@ -312,8 +313,10 @@ void DatabaseWidget::cloneEntry()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* entry = currentEntry->clone(Entry::CloneNewUuid | Entry::CloneResetTimeInfo);
|
Entry* entry = currentEntry->clone(Entry::CloneNewUuid | Entry::CloneResetTimeInfo | Entry::CloneRenameTitle);
|
||||||
entry->setGroup(currentEntry->group());
|
entry->setGroup(currentEntry->group());
|
||||||
|
if (isInSearchMode())
|
||||||
|
search(m_lastSearchText);
|
||||||
m_entryView->setFocus();
|
m_entryView->setFocus();
|
||||||
m_entryView->setCurrentEntry(entry);
|
m_entryView->setCurrentEntry(entry);
|
||||||
}
|
}
|
||||||
|
@ -494,8 +497,46 @@ void DatabaseWidget::openUrlForEntry(Entry* entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (urlString.startsWith("cmd://")) {
|
if (urlString.startsWith("cmd://")) {
|
||||||
|
// check if decision to execute command was stored
|
||||||
|
if (entry->attributes()->hasKey(EntryAttributes::RememberCmdExecAttr)) {
|
||||||
|
if (entry->attributes()->value(EntryAttributes::RememberCmdExecAttr) == "1") {
|
||||||
|
QProcess::startDetached(urlString.mid(6));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise ask user
|
||||||
if (urlString.length() > 6) {
|
if (urlString.length() > 6) {
|
||||||
QProcess::startDetached(urlString.mid(6));
|
QString cmdTruncated = urlString.mid(6);
|
||||||
|
if (cmdTruncated.length() > 400)
|
||||||
|
cmdTruncated = cmdTruncated.left(400) + " […]";
|
||||||
|
QMessageBox msgbox(QMessageBox::Icon::Question,
|
||||||
|
tr("Execute command?"),
|
||||||
|
tr("Do you really want to execute the following command?<br><br>%1<br>")
|
||||||
|
.arg(cmdTruncated.toHtmlEscaped()),
|
||||||
|
QMessageBox::Yes | QMessageBox::No,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
msgbox.setDefaultButton(QMessageBox::No);
|
||||||
|
|
||||||
|
QCheckBox* checkbox = new QCheckBox(tr("Remember my choice"), &msgbox);
|
||||||
|
msgbox.setCheckBox(checkbox);
|
||||||
|
bool remember = false;
|
||||||
|
QObject::connect(checkbox, &QCheckBox::stateChanged, [&](int state) {
|
||||||
|
if (static_cast<Qt::CheckState>(state) == Qt::CheckState::Checked) {
|
||||||
|
remember = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
int result = msgbox.exec();
|
||||||
|
if (result == QMessageBox::Yes) {
|
||||||
|
QProcess::startDetached(urlString.mid(6));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remember) {
|
||||||
|
entry->attributes()->set(EntryAttributes::RememberCmdExecAttr,
|
||||||
|
result == QMessageBox::Yes ? "1" : "0");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -750,7 +791,7 @@ void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::Mod
|
||||||
void DatabaseWidget::switchToEntryEdit()
|
void DatabaseWidget::switchToEntryEdit()
|
||||||
{
|
{
|
||||||
Entry* entry = m_entryView->currentEntry();
|
Entry* entry = m_entryView->currentEntry();
|
||||||
Q_ASSERT(entry);
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -761,7 +802,7 @@ void DatabaseWidget::switchToEntryEdit()
|
||||||
void DatabaseWidget::switchToGroupEdit()
|
void DatabaseWidget::switchToGroupEdit()
|
||||||
{
|
{
|
||||||
Group* group = m_groupView->currentGroup();
|
Group* group = m_groupView->currentGroup();
|
||||||
Q_ASSERT(group);
|
|
||||||
if (!group) {
|
if (!group) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,7 +364,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
|
||||||
bool groupSelected = dbWidget->isGroupSelected();
|
bool groupSelected = dbWidget->isGroupSelected();
|
||||||
|
|
||||||
m_ui->actionEntryNew->setEnabled(!inSearch);
|
m_ui->actionEntryNew->setEnabled(!inSearch);
|
||||||
m_ui->actionEntryClone->setEnabled(singleEntrySelected && !inSearch);
|
m_ui->actionEntryClone->setEnabled(singleEntrySelected);
|
||||||
m_ui->actionEntryEdit->setEnabled(singleEntrySelected);
|
m_ui->actionEntryEdit->setEnabled(singleEntrySelected);
|
||||||
m_ui->actionEntryDelete->setEnabled(entriesSelected);
|
m_ui->actionEntryDelete->setEnabled(entriesSelected);
|
||||||
m_ui->actionEntryCopyTitle->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTitle());
|
m_ui->actionEntryCopyTitle->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTitle());
|
||||||
|
|
|
@ -41,6 +41,7 @@ SearchWidget::SearchWidget(QWidget *parent)
|
||||||
connect(this, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear()));
|
connect(this, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear()));
|
||||||
|
|
||||||
new QShortcut(Qt::CTRL + Qt::Key_F, this, SLOT(searchFocus()), nullptr, Qt::ApplicationShortcut);
|
new QShortcut(Qt::CTRL + Qt::Key_F, this, SLOT(searchFocus()), nullptr, Qt::ApplicationShortcut);
|
||||||
|
new QShortcut(Qt::Key_Escape, m_ui->searchEdit, SLOT(clear()), nullptr, Qt::ApplicationShortcut);
|
||||||
|
|
||||||
m_ui->searchEdit->installEventFilter(this);
|
m_ui->searchEdit->installEventFilter(this);
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ void EditEntryWidget::setupMain()
|
||||||
add(tr("Entry"), m_mainWidget);
|
add(tr("Entry"), m_mainWidget);
|
||||||
|
|
||||||
m_mainUi->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show"));
|
m_mainUi->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show"));
|
||||||
|
m_mainUi->togglePasswordGeneratorButton->setIcon(filePath()->icon("actions", "password-generator", false));
|
||||||
connect(m_mainUi->togglePasswordButton, SIGNAL(toggled(bool)), m_mainUi->passwordEdit, SLOT(setShowPassword(bool)));
|
connect(m_mainUi->togglePasswordButton, SIGNAL(toggled(bool)), m_mainUi->passwordEdit, SLOT(setShowPassword(bool)));
|
||||||
connect(m_mainUi->togglePasswordGeneratorButton, SIGNAL(toggled(bool)), SLOT(togglePasswordGeneratorButton(bool)));
|
connect(m_mainUi->togglePasswordGeneratorButton, SIGNAL(toggled(bool)), SLOT(togglePasswordGeneratorButton(bool)));
|
||||||
connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool)));
|
connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool)));
|
||||||
|
@ -433,6 +434,9 @@ void EditEntryWidget::saveEntry()
|
||||||
|
|
||||||
void EditEntryWidget::updateEntryData(Entry* entry) const
|
void EditEntryWidget::updateEntryData(Entry* entry) const
|
||||||
{
|
{
|
||||||
|
entry->attributes()->copyCustomKeysFrom(m_entryAttributes);
|
||||||
|
entry->attachments()->copyDataFrom(m_entryAttachments);
|
||||||
|
|
||||||
entry->setTitle(m_mainUi->titleEdit->text());
|
entry->setTitle(m_mainUi->titleEdit->text());
|
||||||
entry->setUsername(m_mainUi->usernameEdit->text());
|
entry->setUsername(m_mainUi->usernameEdit->text());
|
||||||
entry->setUrl(m_mainUi->urlEdit->text());
|
entry->setUrl(m_mainUi->urlEdit->text());
|
||||||
|
@ -442,9 +446,6 @@ void EditEntryWidget::updateEntryData(Entry* entry) const
|
||||||
|
|
||||||
entry->setNotes(m_mainUi->notesEdit->toPlainText());
|
entry->setNotes(m_mainUi->notesEdit->toPlainText());
|
||||||
|
|
||||||
entry->attributes()->copyCustomKeysFrom(m_entryAttributes);
|
|
||||||
entry->attachments()->copyDataFrom(m_entryAttachments);
|
|
||||||
|
|
||||||
IconStruct iconStruct = m_iconsWidget->state();
|
IconStruct iconStruct = m_iconsWidget->state();
|
||||||
|
|
||||||
if (iconStruct.number < 0) {
|
if (iconStruct.number < 0) {
|
||||||
|
|
|
@ -77,9 +77,6 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="togglePasswordGeneratorButton">
|
<widget class="QToolButton" name="togglePasswordGeneratorButton">
|
||||||
<property name="text">
|
|
||||||
<string>Generate</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -481,8 +481,7 @@ void TestGui::testSearch()
|
||||||
QCOMPARE(entry->title(), origTitle.append("_edited"));
|
QCOMPARE(entry->title(), origTitle.append("_edited"));
|
||||||
|
|
||||||
// Cancel search, should return to normal view
|
// Cancel search, should return to normal view
|
||||||
QTest::mouseClick(searchTextEdit, Qt::LeftButton);
|
QTest::keyClick(m_mainWindow, Qt::Key_Escape);
|
||||||
QTest::keyClick(searchTextEdit, Qt::Key_Escape);
|
|
||||||
QTRY_COMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
|
QTRY_COMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,7 +566,7 @@ void TestGui::testCloneEntry()
|
||||||
QCOMPARE(entryView->model()->rowCount(), 2);
|
QCOMPARE(entryView->model()->rowCount(), 2);
|
||||||
Entry* entryClone = entryView->entryFromIndex(entryView->model()->index(1, 1));
|
Entry* entryClone = entryView->entryFromIndex(entryView->model()->index(1, 1));
|
||||||
QVERIFY(entryOrg->uuid() != entryClone->uuid());
|
QVERIFY(entryOrg->uuid() != entryClone->uuid());
|
||||||
QCOMPARE(entryClone->title(), entryOrg->title());
|
QCOMPARE(entryClone->title(), entryOrg->title() + QString(" - Clone"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGui::testDragAndDropEntry()
|
void TestGui::testDragAndDropEntry()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue