Merge branch 'develop' into feature/sharing_groups

This commit is contained in:
Jonathan White 2019-01-16 22:54:25 -05:00
commit 9b4a680f7e
No known key found for this signature in database
GPG Key ID: 440FC65F2E0C6E01
28 changed files with 284 additions and 88 deletions

View File

@ -10,6 +10,7 @@ Exec=keepassxc %f
TryExec=keepassxc
Icon=keepassxc
StartupWMClass=keepassxc
StartupNotify=true
Terminal=false
Type=Application
Version=1.0

View File

@ -55,6 +55,7 @@ BrowserService::BrowserService(DatabaseTabWidget* parent)
, m_dialogActive(false)
, m_bringToFrontRequested(false)
, m_wasMinimized(false)
, m_wasHidden(false)
, m_keepassBrowserUUID(QUuid::fromRfc4122(QByteArray::fromHex("de887cc3036343b8974b5911b8816224")))
{
// Don't connect the signals when used from DatabaseSettingsWidgetBrowser (parent is nullptr)
@ -96,7 +97,6 @@ bool BrowserService::openDatabase(bool triggerUnlock)
if (triggerUnlock) {
m_bringToFrontRequested = true;
m_wasMinimized = getMainWindow()->isMinimized();
raiseWindow(true);
}
@ -933,7 +933,11 @@ void BrowserService::hideWindow() const
getMainWindow()->showMinimized();
} else {
#ifdef Q_OS_MACOS
macUtils()->raiseLastActiveWindow();
if (m_wasHidden) {
macUtils()->hideOwnWindow();
} else {
macUtils()->raiseLastActiveWindow();
}
#else
getMainWindow()->lower();
#endif
@ -944,6 +948,7 @@ void BrowserService::raiseWindow(const bool force)
{
m_wasMinimized = getMainWindow()->isMinimized();
#ifdef Q_OS_MACOS
m_wasHidden = macUtils()->isHidden();
macUtils()->raiseOwnWindow();
Tools::wait(500);
#else

View File

@ -125,6 +125,7 @@ private:
bool m_dialogActive;
bool m_bringToFrontRequested;
bool m_wasMinimized;
bool m_wasHidden;
QUuid m_keepassBrowserUUID;
};

View File

@ -83,7 +83,7 @@ int Add::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() != 2) {
outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli add");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli add");
return EXIT_FAILURE;
}

View File

@ -83,6 +83,13 @@ if(APPLE AND WITH_APP_BUNDLE)
"@executable_path/../Frameworks/libykpers-1.1.dylib"
keepassxc-cli
COMMENT "Changing linking of keepassxc-cli")
# Copy app to staging directory for pre-install testing
set(CLI_APP_DIR "${CMAKE_BINARY_DIR}/src/${CLI_INSTALL_DIR}")
add_custom_command(TARGET keepassxc-cli
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy keepassxc-cli ${CLI_APP_DIR}/keepassxc-cli
COMMENT "Copying keepassxc-cli inside the application")
endif()
if(APPLE OR UNIX)

View File

@ -42,7 +42,7 @@ Clip::~Clip()
int Clip::execute(const QStringList& arguments)
{
TextStream out(Utils::STDOUT);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -62,7 +62,7 @@ int Clip::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() != 2 && args.size() != 3) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli clip");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli clip");
return EXIT_FAILURE;
}
@ -83,11 +83,11 @@ int Clip::clipEntry(QSharedPointer<Database> database,
bool clipTotp,
bool silent)
{
TextStream err(Utils::STDERR);
TextStream errorTextStream(Utils::STDERR);
int timeoutSeconds = 0;
if (!timeout.isEmpty() && !timeout.toInt()) {
err << QObject::tr("Invalid timeout value %1.").arg(timeout) << endl;
errorTextStream << QObject::tr("Invalid timeout value %1.").arg(timeout) << endl;
return EXIT_FAILURE;
} else if (!timeout.isEmpty()) {
timeoutSeconds = timeout.toInt();
@ -96,14 +96,14 @@ int Clip::clipEntry(QSharedPointer<Database> database,
TextStream outputTextStream(silent ? Utils::DEVNULL : Utils::STDOUT, QIODevice::WriteOnly);
Entry* entry = database->rootGroup()->findEntryByPath(entryPath);
if (!entry) {
err << QObject::tr("Entry %1 not found.").arg(entryPath) << endl;
errorTextStream << QObject::tr("Entry %1 not found.").arg(entryPath) << endl;
return EXIT_FAILURE;
}
QString value;
if (clipTotp) {
if (!entry->hasTotp()) {
err << QObject::tr("Entry with path %1 has no TOTP set up.").arg(entryPath) << endl;
errorTextStream << QObject::tr("Entry with path %1 has no TOTP set up.").arg(entryPath) << endl;
return EXIT_FAILURE;
}

View File

@ -38,8 +38,8 @@ Diceware::~Diceware()
int Diceware::execute(const QStringList& arguments)
{
TextStream in(Utils::STDIN, QIODevice::ReadOnly);
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -58,7 +58,7 @@ int Diceware::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (!args.isEmpty()) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware");
return EXIT_FAILURE;
}
@ -78,12 +78,12 @@ int Diceware::execute(const QStringList& arguments)
}
if (!dicewareGenerator.isValid()) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware");
outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware");
return EXIT_FAILURE;
}
QString password = dicewareGenerator.generatePassphrase();
out << password << endl;
outputTextStream << password << endl;
return EXIT_SUCCESS;
}

View File

@ -41,9 +41,8 @@ Edit::~Edit()
int Edit::execute(const QStringList& arguments)
{
TextStream in(Utils::STDIN, QIODevice::ReadOnly);
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream err(Utils::STDERR, QIODevice::WriteOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -88,7 +87,7 @@ int Edit::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() != 2) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli edit");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli edit");
return EXIT_FAILURE;
}
@ -105,19 +104,19 @@ int Edit::execute(const QStringList& arguments)
QString passwordLength = parser.value(length);
if (!passwordLength.isEmpty() && !passwordLength.toInt()) {
err << QObject::tr("Invalid value for password length: %1").arg(passwordLength) << endl;
errorTextStream << QObject::tr("Invalid value for password length: %1").arg(passwordLength) << endl;
return EXIT_FAILURE;
}
Entry* entry = db->rootGroup()->findEntryByPath(entryPath);
if (!entry) {
err << QObject::tr("Could not find entry with path %1.").arg(entryPath) << endl;
errorTextStream << QObject::tr("Could not find entry with path %1.").arg(entryPath) << endl;
return EXIT_FAILURE;
}
if (parser.value("username").isEmpty() && parser.value("url").isEmpty() && parser.value("title").isEmpty()
&& !parser.isSet(prompt) && !parser.isSet(generate)) {
err << QObject::tr("Not changing any field for entry %1.").arg(entryPath) << endl;
errorTextStream << QObject::tr("Not changing any field for entry %1.").arg(entryPath) << endl;
return EXIT_FAILURE;
}
@ -137,7 +136,7 @@ int Edit::execute(const QStringList& arguments)
if (parser.isSet(prompt)) {
if (!parser.isSet(Command::QuietOption)) {
out << QObject::tr("Enter new password for entry: ") << flush;
outputTextStream << QObject::tr("Enter new password for entry: ") << flush;
}
QString password = Utils::getPassword(parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT);
entry->setPassword(password);
@ -160,12 +159,12 @@ int Edit::execute(const QStringList& arguments)
QString errorMessage;
if (!db->save(databasePath, &errorMessage, true, false)) {
err << QObject::tr("Writing the database failed: %1").arg(errorMessage) << endl;
errorTextStream << QObject::tr("Writing the database failed: %1").arg(errorMessage) << endl;
return EXIT_FAILURE;
}
if (!parser.isSet(Command::QuietOption)) {
out << QObject::tr("Successfully edited entry %1.").arg(entry->title()) << endl;
outputTextStream << QObject::tr("Successfully edited entry %1.").arg(entry->title()) << endl;
}
return EXIT_SUCCESS;
}

View File

@ -156,8 +156,8 @@ static void estimate(const char* pwd, bool advanced)
int Estimate::execute(const QStringList& arguments)
{
TextStream in(Utils::STDIN, QIODevice::ReadOnly);
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream inputTextStream(Utils::STDIN, QIODevice::ReadOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -171,7 +171,7 @@ int Estimate::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() > 1) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli estimate");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli estimate");
return EXIT_FAILURE;
}
@ -179,7 +179,7 @@ int Estimate::execute(const QStringList& arguments)
if (args.size() == 1) {
password = args.at(0);
} else {
password = in.readLine();
password = inputTextStream.readLine();
}
estimate(password.toLatin1(), parser.isSet(advancedOption));

View File

@ -43,8 +43,8 @@ Extract::~Extract()
int Extract::execute(const QStringList& arguments)
{
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream err(Utils::STDERR, QIODevice::WriteOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -56,12 +56,12 @@ int Extract::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() != 1) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli extract");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli extract");
return EXIT_FAILURE;
}
if (!parser.isSet(Command::QuietOption)) {
out << QObject::tr("Insert password to unlock %1: ").arg(args.at(0)) << flush;
outputTextStream << QObject::tr("Insert password to unlock %1: ").arg(args.at(0)) << flush;
}
auto compositeKey = QSharedPointer<CompositeKey>::create();
@ -77,12 +77,12 @@ int Extract::execute(const QStringList& arguments)
auto fileKey = QSharedPointer<FileKey>::create();
QString errorMsg;
if (!fileKey->load(keyFilePath, &errorMsg)) {
err << QObject::tr("Failed to load key file %1: %2").arg(keyFilePath, errorMsg) << endl;
errorTextStream << QObject::tr("Failed to load key file %1: %2").arg(keyFilePath, errorMsg) << endl;
return EXIT_FAILURE;
}
if (fileKey->type() != FileKey::Hashed) {
err << QObject::tr("WARNING: You are using a legacy key file format which may become\n"
errorTextStream << QObject::tr("WARNING: You are using a legacy key file format which may become\n"
"unsupported in the future.\n\n"
"Please consider generating a new key file.")
<< endl;
@ -95,11 +95,11 @@ int Extract::execute(const QStringList& arguments)
const QString& databaseFilename = args.at(0);
QFile dbFile(databaseFilename);
if (!dbFile.exists()) {
err << QObject::tr("File %1 does not exist.").arg(databaseFilename) << endl;
errorTextStream << QObject::tr("File %1 does not exist.").arg(databaseFilename) << endl;
return EXIT_FAILURE;
}
if (!dbFile.open(QIODevice::ReadOnly)) {
err << QObject::tr("Unable to open file %1.").arg(databaseFilename) << endl;
errorTextStream << QObject::tr("Unable to open file %1.").arg(databaseFilename) << endl;
return EXIT_FAILURE;
}
@ -112,14 +112,14 @@ int Extract::execute(const QStringList& arguments)
if (reader.hasError()) {
if (xmlData.isEmpty()) {
err << QObject::tr("Error while reading the database:\n%1").arg(reader.errorString()) << endl;
errorTextStream << QObject::tr("Error while reading the database:\n%1").arg(reader.errorString()) << endl;
} else {
err << QObject::tr("Error while parsing the database:\n%1").arg(reader.errorString()) << endl;
errorTextStream << QObject::tr("Error while parsing the database:\n%1").arg(reader.errorString()) << endl;
}
return EXIT_FAILURE;
}
out << xmlData.constData() << endl;
outputTextStream << xmlData.constData() << endl;
return EXIT_SUCCESS;
}

View File

@ -38,8 +38,8 @@ Generate::~Generate()
int Generate::execute(const QStringList& arguments)
{
TextStream in(Utils::STDIN, QIODevice::ReadOnly);
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -84,7 +84,7 @@ int Generate::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (!args.isEmpty()) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli generate");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli generate");
return EXIT_FAILURE;
}
@ -128,12 +128,12 @@ int Generate::execute(const QStringList& arguments)
passwordGenerator.setExcludedChars(parser.value(exclude));
if (!passwordGenerator.isValid()) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli generate");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli generate");
return EXIT_FAILURE;
}
QString password = passwordGenerator.generatePassword();
out << password << endl;
outputTextStream << password << endl;
return EXIT_SUCCESS;
}

View File

@ -40,7 +40,7 @@ List::~List()
int List::execute(const QStringList& arguments)
{
TextStream out(Utils::STDOUT);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -58,7 +58,7 @@ int List::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() != 1 && args.size() != 2) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli ls");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli ls");
return EXIT_FAILURE;
}
@ -80,20 +80,20 @@ int List::execute(const QStringList& arguments)
int List::listGroup(Database* database, bool recursive, const QString& groupPath)
{
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream err(Utils::STDERR, QIODevice::WriteOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
if (groupPath.isEmpty()) {
out << database->rootGroup()->print(recursive) << flush;
outputTextStream << database->rootGroup()->print(recursive) << flush;
return EXIT_SUCCESS;
}
Group* group = database->rootGroup()->findGroupByPath(groupPath);
if (!group) {
err << QObject::tr("Cannot find group %1.").arg(groupPath) << endl;
errorTextStream << QObject::tr("Cannot find group %1.").arg(groupPath) << endl;
return EXIT_FAILURE;
}
out << group->print(recursive) << flush;
outputTextStream << group->print(recursive) << flush;
return EXIT_SUCCESS;
}

View File

@ -42,7 +42,7 @@ Locate::~Locate()
int Locate::execute(const QStringList& arguments)
{
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -55,7 +55,7 @@ int Locate::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() != 2) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli locate");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli locate");
return EXIT_FAILURE;
}
@ -72,17 +72,17 @@ int Locate::execute(const QStringList& arguments)
int Locate::locateEntry(Database* database, const QString& searchTerm)
{
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream err(Utils::STDERR, QIODevice::WriteOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QStringList results = database->rootGroup()->locate(searchTerm);
if (results.isEmpty()) {
err << "No results for that search term." << endl;
errorTextStream << "No results for that search term." << endl;
return EXIT_FAILURE;
}
for (const QString& result : asConst(results)) {
out << result << endl;
outputTextStream << result << endl;
}
return EXIT_SUCCESS;
}

View File

@ -38,8 +38,8 @@ Merge::~Merge()
int Merge::execute(const QStringList& arguments)
{
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream err(Utils::STDERR, QIODevice::WriteOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -64,7 +64,7 @@ int Merge::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() != 2) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli merge");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli merge");
return EXIT_FAILURE;
}
@ -83,7 +83,7 @@ int Merge::execute(const QStringList& arguments)
db2 = QSharedPointer<Database>::create();
QString errorMessage;
if (!db2->open(args.at(1), db1->key(), &errorMessage, false)) {
err << QObject::tr("Error reading merge file:\n%1").arg(errorMessage);
errorTextStream << QObject::tr("Error reading merge file:\n%1").arg(errorMessage);
return EXIT_FAILURE;
}
}
@ -94,14 +94,14 @@ int Merge::execute(const QStringList& arguments)
if (databaseChanged) {
QString errorMessage;
if (!db1->save(args.at(0), &errorMessage, true, false)) {
err << QObject::tr("Unable to save database to file : %1").arg(errorMessage) << endl;
errorTextStream << QObject::tr("Unable to save database to file : %1").arg(errorMessage) << endl;
return EXIT_FAILURE;
}
if (!parser.isSet(Command::QuietOption)) {
out << "Successfully merged the database files." << endl;
outputTextStream << "Successfully merged the database files." << endl;
}
} else if (!parser.isSet(Command::QuietOption)) {
out << "Database was not modified by merge operation." << endl;
outputTextStream << "Database was not modified by merge operation." << endl;
}
return EXIT_SUCCESS;

View File

@ -44,7 +44,7 @@ Remove::~Remove()
int Remove::execute(const QStringList& arguments)
{
TextStream out(Utils::STDERR, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::tr("main", "Remove an entry from the database."));
@ -57,7 +57,7 @@ int Remove::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() != 2) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli rm");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli rm");
return EXIT_FAILURE;
}
@ -74,12 +74,12 @@ int Remove::execute(const QStringList& arguments)
int Remove::removeEntry(Database* database, const QString& databasePath, const QString& entryPath, bool quiet)
{
TextStream out(quiet ? Utils::DEVNULL : Utils::STDOUT, QIODevice::WriteOnly);
TextStream err(Utils::STDERR, QIODevice::WriteOnly);
TextStream outputTextStream(quiet ? Utils::DEVNULL : Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QPointer<Entry> entry = database->rootGroup()->findEntryByPath(entryPath);
if (!entry) {
err << QObject::tr("Entry %1 not found.").arg(entryPath) << endl;
errorTextStream << QObject::tr("Entry %1 not found.").arg(entryPath) << endl;
return EXIT_FAILURE;
}
@ -95,14 +95,14 @@ int Remove::removeEntry(Database* database, const QString& databasePath, const Q
QString errorMessage;
if (!database->save(databasePath, &errorMessage, true, false)) {
err << QObject::tr("Unable to save database to file: %1").arg(errorMessage) << endl;
errorTextStream << QObject::tr("Unable to save database to file: %1").arg(errorMessage) << endl;
return EXIT_FAILURE;
}
if (recycled) {
out << QObject::tr("Successfully recycled entry %1.").arg(entryTitle) << endl;
outputTextStream << QObject::tr("Successfully recycled entry %1.").arg(entryTitle) << endl;
} else {
out << QObject::tr("Successfully deleted entry %1.").arg(entryTitle) << endl;
outputTextStream << QObject::tr("Successfully deleted entry %1.").arg(entryTitle) << endl;
}
return EXIT_SUCCESS;

View File

@ -41,7 +41,7 @@ Show::~Show()
int Show::execute(const QStringList& arguments)
{
TextStream out(Utils::STDOUT);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(description);
@ -67,7 +67,7 @@ int Show::execute(const QStringList& arguments)
const QStringList args = parser.positionalArguments();
if (args.size() != 2) {
out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli show");
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli show");
return EXIT_FAILURE;
}
@ -84,18 +84,17 @@ int Show::execute(const QStringList& arguments)
int Show::showEntry(Database* database, QStringList attributes, bool showTotp, const QString& entryPath)
{
TextStream in(Utils::STDIN, QIODevice::ReadOnly);
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
TextStream err(Utils::STDERR, QIODevice::WriteOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
Entry* entry = database->rootGroup()->findEntryByPath(entryPath);
if (!entry) {
err << QObject::tr("Could not find entry with path %1.").arg(entryPath) << endl;
errorTextStream << QObject::tr("Could not find entry with path %1.").arg(entryPath) << endl;
return EXIT_FAILURE;
}
if (showTotp && !entry->hasTotp()) {
err << QObject::tr("Entry with path %1 has no TOTP set up.").arg(entryPath) << endl;
errorTextStream << QObject::tr("Entry with path %1 has no TOTP set up.").arg(entryPath) << endl;
return EXIT_FAILURE;
}
@ -110,20 +109,20 @@ int Show::showEntry(Database* database, QStringList attributes, bool showTotp, c
for (const QString& attribute : asConst(attributes)) {
if (!entry->attributes()->contains(attribute)) {
sawUnknownAttribute = true;
err << QObject::tr("ERROR: unknown attribute %1.").arg(attribute) << endl;
errorTextStream << QObject::tr("ERROR: unknown attribute %1.").arg(attribute) << endl;
continue;
}
if (showAttributeNames) {
out << attribute << ": ";
outputTextStream << attribute << ": ";
}
out << entry->resolveMultiplePlaceholders(entry->attributes()->value(attribute)) << endl;
outputTextStream << entry->resolveMultiplePlaceholders(entry->attributes()->value(attribute)) << endl;
}
if (showTotp) {
if (showAttributeNames) {
out << "TOTP: ";
outputTextStream << "TOTP: ";
}
out << entry->totp() << endl;
outputTextStream << entry->totp() << endl;
}
return sawUnknownAttribute ? EXIT_FAILURE : EXIT_SUCCESS;

View File

@ -196,6 +196,8 @@ void Config::init(const QString& fileName)
m_defaults.insert("security/resettouchidscreenlock", true);
m_defaults.insert("GUI/Language", "system");
m_defaults.insert("GUI/HideToolbar", false);
m_defaults.insert("GUI/MovableToolbar", false);
m_defaults.insert("GUI/ToolButtonStyle", Qt::ToolButtonIconOnly);
m_defaults.insert("GUI/ShowTrayIcon", false);
m_defaults.insert("GUI/DarkTrayIcon", false);
m_defaults.insert("GUI/MinimizeToTray", false);

View File

@ -81,6 +81,7 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
// clang-format off
connect(m_generalUi->autoSaveAfterEveryChangeCheckBox, SIGNAL(toggled(bool)), SLOT(enableAutoSaveOnExit(bool)));
connect(m_generalUi->systrayShowCheckBox, SIGNAL(toggled(bool)), this, SLOT(enableSystray(bool)));
connect(m_generalUi->toolbarHideCheckBox, SIGNAL(toggled(bool)), this, SLOT(enableToolbarSettings(bool)));
connect(m_secUi->clearClipboardCheckBox, SIGNAL(toggled(bool)),
m_secUi->clearClipboardSpinBox, SLOT(setEnabled(bool)));
@ -155,6 +156,19 @@ void ApplicationSettingsWidget::loadSettings()
m_generalUi->previewHideCheckBox->setChecked(config()->get("GUI/HidePreviewPanel").toBool());
m_generalUi->toolbarHideCheckBox->setChecked(config()->get("GUI/HideToolbar").toBool());
m_generalUi->toolbarMovableCheckBox->setChecked(config()->get("GUI/MovableToolbar").toBool());
m_generalUi->toolButtonStyleComboBox->clear();
m_generalUi->toolButtonStyleComboBox->addItem(tr("Icon only"), Qt::ToolButtonIconOnly);
m_generalUi->toolButtonStyleComboBox->addItem(tr("Text only"), Qt::ToolButtonTextOnly);
m_generalUi->toolButtonStyleComboBox->addItem(tr("Text beside icon"), Qt::ToolButtonTextBesideIcon);
m_generalUi->toolButtonStyleComboBox->addItem(tr("Text under icon"), Qt::ToolButtonTextUnderIcon);
m_generalUi->toolButtonStyleComboBox->addItem(tr("Follow style"), Qt::ToolButtonFollowStyle);
int toolButtonStyleIndex = m_generalUi->toolButtonStyleComboBox->findData(config()->get("GUI/ToolButtonStyle"));
if (toolButtonStyleIndex > 0) {
m_generalUi->toolButtonStyleComboBox->setCurrentIndex(toolButtonStyleIndex);
}
m_generalUi->systrayShowCheckBox->setChecked(config()->get("GUI/ShowTrayIcon").toBool());
m_generalUi->systrayDarkIconCheckBox->setChecked(config()->get("GUI/DarkTrayIcon").toBool());
m_generalUi->systrayMinimizeToTrayCheckBox->setChecked(config()->get("GUI/MinimizeToTray").toBool());
@ -231,6 +245,11 @@ void ApplicationSettingsWidget::saveSettings()
config()->set("GUI/HidePreviewPanel", m_generalUi->previewHideCheckBox->isChecked());
config()->set("GUI/HideToolbar", m_generalUi->toolbarHideCheckBox->isChecked());
config()->set("GUI/MovableToolbar", m_generalUi->toolbarMovableCheckBox->isChecked());
int currentToolButtonStyleIndex = m_generalUi->toolButtonStyleComboBox->currentIndex();
config()->set("GUI/ToolButtonStyle", m_generalUi->toolButtonStyleComboBox->itemData(currentToolButtonStyleIndex).toString());
config()->set("GUI/ShowTrayIcon", m_generalUi->systrayShowCheckBox->isChecked());
config()->set("GUI/DarkTrayIcon", m_generalUi->systrayDarkIconCheckBox->isChecked());
config()->set("GUI/MinimizeToTray", m_generalUi->systrayMinimizeToTrayCheckBox->isChecked());
@ -299,3 +318,11 @@ void ApplicationSettingsWidget::enableSystray(bool checked)
m_generalUi->systrayDarkIconCheckBox->setEnabled(checked);
m_generalUi->systrayMinimizeToTrayCheckBox->setEnabled(checked);
}
void ApplicationSettingsWidget::enableToolbarSettings(bool checked)
{
m_generalUi->toolbarMovableCheckBox->setEnabled(!checked);
m_generalUi->toolButtonStyleComboBox->setEnabled(!checked);
m_generalUi->toolButtonStyleLabel->setEnabled(!checked);
}

View File

@ -55,6 +55,7 @@ private slots:
void reject();
void enableAutoSaveOnExit(bool checked);
void enableSystray(bool checked);
void enableToolbarSettings(bool checked);
private:
QWidget* const m_secWidget;

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>684</width>
<height>842</height>
<height>881</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
@ -186,6 +186,100 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="toolbarMovableLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<item>
<spacer name="toolbarMovableSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="toolbarMovableCheckBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Movable toolbar</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="toolButtonStyleLayout">
<property name="spacing">
<number>15</number>
</property>
<item>
<spacer name="toolButtonStyleSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="toolButtonStyleLabel">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Button style</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="toolButtonStyleComboBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="minimizeOnCloseCheckBox">
<property name="text">

View File

@ -151,7 +151,7 @@ MainWindow::MainWindow()
m_countDefaultAttributes = m_ui->menuEntryCopyAttribute->actions().size();
restoreGeometry(config()->get("GUI/MainWindowGeometry").toByteArray());
restoreState(config()->get("GUI/MainWindowState").toByteArray());
#ifdef WITH_XC_BROWSER
m_ui->settingsWidget->addSettingsPage(new BrowserPlugin(m_ui->tabWidget));
#endif
@ -842,6 +842,7 @@ void MainWindow::saveWindowInformation()
{
if (isVisible()) {
config()->set("GUI/MainWindowGeometry", saveGeometry());
config()->set("GUI/MainWindowState", saveState());
}
}
@ -964,6 +965,13 @@ void MainWindow::applySettingsChanges()
#endif
m_ui->toolBar->setHidden(config()->get("GUI/HideToolbar").toBool());
m_ui->toolBar->setMovable(config()->get("GUI/MovableToolbar").toBool());
bool isOk = false;
const auto toolButtonStyle = static_cast<Qt::ToolButtonStyle>(config()->get("GUI/ToolButtonStyle").toInt(&isOk));
if (isOk) {
m_ui->toolBar->setToolButtonStyle(toolButtonStyle);
}
updateTrayIcon();
}

View File

@ -1002,7 +1002,9 @@ bool EditEntryWidget::hasBeenModified() const
void EditEntryWidget::togglePasswordGeneratorButton(bool checked)
{
m_mainUi->passwordGenerator->regeneratePassword();
if (checked) {
m_mainUi->passwordGenerator->regeneratePassword();
}
m_mainUi->passwordGenerator->setVisible(checked);
}

View File

@ -33,6 +33,8 @@ public:
pid_t activeProcessId();
pid_t ownProcessId();
bool activateProcess(pid_t pid);
bool hideProcess(pid_t pid);
bool isHidden(pid_t pid);
private:
void *self;

View File

@ -28,5 +28,7 @@
- (pid_t) activeProcessId;
- (pid_t) ownProcessId;
- (bool) activateProcess:(pid_t) pid;
- (bool) hideProcess:(pid_t) pid;
- (bool) isHidden:(pid_t) pid;
@end

View File

@ -72,10 +72,27 @@ AppKit::~AppKit()
- (bool) activateProcess:(pid_t) pid
{
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
return [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
}
//
// Hide application by process id
//
- (bool) hideProcess:(pid_t) pid
{
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
return [app hide];
}
//
// Get application hidden state by process id
//
- (bool) isHidden:(pid_t) pid
{
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
return [app isHidden];
}
//
// ------------------------- C++ Trampolines -------------------------
//
@ -100,4 +117,14 @@ bool AppKit::activateProcess(pid_t pid)
return [static_cast<id>(self) activateProcess:pid];
}
bool AppKit::hideProcess(pid_t pid)
{
return [static_cast<id>(self) hideProcess:pid];
}
bool AppKit::isHidden(pid_t pid)
{
return [static_cast<id>(self) isHidden:pid];
}
@end

View File

@ -60,3 +60,13 @@ bool MacUtils::raiseLastActiveWindow()
{
return m_appkit->activateProcess(m_appkit->lastActiveProcessId());
}
bool MacUtils::hideOwnWindow()
{
return m_appkit->hideProcess(m_appkit->ownProcessId());
}
bool MacUtils::isHidden()
{
return m_appkit->isHidden(m_appkit->ownProcessId());
}

View File

@ -35,6 +35,8 @@ public:
bool raiseWindow(WId pid);
bool raiseLastActiveWindow();
bool raiseOwnWindow();
bool hideOwnWindow();
bool isHidden();
private:
explicit MacUtils(QObject* parent = nullptr);

View File

@ -45,6 +45,13 @@ if(WITH_XC_BROWSER)
"@executable_path/../Frameworks/QtNetwork.framework/Versions/5/QtNetwork"
keepassxc-proxy
COMMENT "Changing linking of keepassxc-proxy")
# Copy app to staging directory for pre-install testing
set(PROXY_APP_DIR "${CMAKE_BINARY_DIR}/src/${PROXY_INSTALL_DIR}")
add_custom_command(TARGET keepassxc-proxy
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy keepassxc-proxy ${PROXY_APP_DIR}/keepassxc-proxy
COMMENT "Copying keepassxc-proxy inside the application")
endif()
if(MINGW)
target_link_libraries(keepassxc-proxy Wtsapi32.lib Ws2_32.lib)