diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index 183837fae..715e8dc59 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -3637,6 +3637,10 @@ Supported extensions are: %1. Select import/export file + + Share recursively + + EditGroupWidgetMain diff --git a/src/keeshare/KeeShareSettings.cpp b/src/keeshare/KeeShareSettings.cpp index 4f53fc25f..268e4e9a0 100644 --- a/src/keeshare/KeeShareSettings.cpp +++ b/src/keeshare/KeeShareSettings.cpp @@ -320,6 +320,9 @@ namespace KeeShareSettings writer.writeStartElement("Password"); writer.writeCharacters(reference.password.toUtf8().toBase64()); writer.writeEndElement(); + writer.writeStartElement("Recurse"); + writer.writeCharacters(reference.recurse ? "True" : "False"); + writer.writeEndElement(); }); } @@ -346,6 +349,8 @@ namespace KeeShareSettings reference.path = QString::fromUtf8(QByteArray::fromBase64(reader.readElementText().toLatin1())); } else if (reader.name() == "Password") { reference.password = QString::fromUtf8(QByteArray::fromBase64(reader.readElementText().toLatin1())); + } else if (reader.name() == "Recurse") { + reference.recurse = reader.readElementText().compare("True") == 0; } else { qWarning("Unknown Reference element %s", qPrintable(reader.name().toString())); reader.skipCurrentElement(); diff --git a/src/keeshare/KeeShareSettings.h b/src/keeshare/KeeShareSettings.h index b81dc15af..c8ee73d67 100644 --- a/src/keeshare/KeeShareSettings.h +++ b/src/keeshare/KeeShareSettings.h @@ -126,6 +126,7 @@ namespace KeeShareSettings QUuid uuid; QString path; QString password; + bool recurse; Reference(); bool isNull() const; diff --git a/src/keeshare/ShareExport.cpp b/src/keeshare/ShareExport.cpp index 1a64ccde0..3c5b618de 100644 --- a/src/keeshare/ShareExport.cpp +++ b/src/keeshare/ShareExport.cpp @@ -62,6 +62,39 @@ namespace } } + void cloneIcon(Metadata* targetMetadata, const Database* sourceDb, const QUuid& iconUuid) + { + if (!iconUuid.isNull() && !targetMetadata->hasCustomIcon(iconUuid)) { + targetMetadata->addCustomIcon(iconUuid, sourceDb->metadata()->customIcon(iconUuid)); + } + } + + void cloneEntries(Metadata* targetMetadata, const Group* sourceGroup, Group* targetGroup) + { + for (const Entry* sourceEntry : sourceGroup->entries()) { + auto* targetEntry = sourceEntry->clone(Entry::CloneIncludeHistory); + const bool updateTimeinfoEntry = targetEntry->canUpdateTimeinfo(); + targetEntry->setUpdateTimeinfo(false); + targetEntry->setGroup(targetGroup); + targetEntry->setUpdateTimeinfo(updateTimeinfoEntry); + cloneIcon(targetMetadata, sourceEntry->database(), targetEntry->iconUuid()); + } + } + + void cloneChildren(Metadata* targetMetadata, const Group* sourceRoot, Group* targetRoot) + { + for (const Group* sourceGroup : sourceRoot->children()) { + auto* targetGroup = sourceGroup->clone(Entry::CloneNoFlags, Group::CloneNoFlags); + const bool updateTimeinfo = targetGroup->canUpdateTimeinfo(); + targetGroup->setUpdateTimeinfo(false); + targetGroup->setParent(targetRoot); + targetGroup->setUpdateTimeinfo(updateTimeinfo); + cloneIcon(targetMetadata, sourceRoot->database(), targetGroup->iconUuid()); + cloneEntries(targetMetadata, sourceGroup, targetGroup); + cloneChildren(targetMetadata, sourceGroup, targetGroup); + } + } + Database* extractIntoDatabase(const KeeShareSettings::Reference& reference, const Group* sourceRoot) { const auto* sourceDb = sourceRoot->database(); @@ -75,17 +108,10 @@ namespace targetRoot->setUpdateTimeinfo(false); KeeShare::setReferenceTo(targetRoot, KeeShareSettings::Reference()); targetRoot->setUpdateTimeinfo(updateTimeinfo); - const auto sourceEntries = sourceRoot->entriesRecursive(false); - for (const Entry* sourceEntry : sourceEntries) { - auto* targetEntry = sourceEntry->clone(Entry::CloneIncludeHistory); - const bool updateTimeinfoEntry = targetEntry->canUpdateTimeinfo(); - targetEntry->setUpdateTimeinfo(false); - targetEntry->setGroup(targetRoot); - targetEntry->setUpdateTimeinfo(updateTimeinfoEntry); - const auto iconUuid = targetEntry->iconUuid(); - if (!iconUuid.isNull() && !targetMetadata->hasCustomIcon(iconUuid)) { - targetMetadata->addCustomIcon(iconUuid, sourceEntry->database()->metadata()->customIcon(iconUuid)); - } + cloneIcon(targetMetadata, sourceRoot->database(), targetRoot->iconUuid()); + cloneEntries(targetMetadata, sourceRoot, targetRoot); + if (reference.recurse) { + cloneChildren(targetMetadata, sourceRoot, targetRoot); } auto key = QSharedPointer::create(); diff --git a/src/keeshare/group/EditGroupWidgetKeeShare.cpp b/src/keeshare/group/EditGroupWidgetKeeShare.cpp index 82f8dd1c0..0efd061bc 100644 --- a/src/keeshare/group/EditGroupWidgetKeeShare.cpp +++ b/src/keeshare/group/EditGroupWidgetKeeShare.cpp @@ -43,6 +43,7 @@ EditGroupWidgetKeeShare::EditGroupWidgetKeeShare(QWidget* parent) connect(m_ui->pathEdit, SIGNAL(editingFinished()), SLOT(selectPath())); connect(m_ui->pathSelectionButton, SIGNAL(pressed()), SLOT(launchPathSelectionDialog())); connect(m_ui->typeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(selectType())); + connect(m_ui->recurseIntoGroupsCheckbox, SIGNAL(toggled(bool)), SLOT(recurseIntoGroupsToggled(bool))); connect(m_ui->clearButton, SIGNAL(clicked(bool)), SLOT(clearInputs())); connect(KeeShare::instance(), SIGNAL(activeChanged()), SLOT(updateSharingState())); @@ -97,6 +98,7 @@ void EditGroupWidgetKeeShare::updateSharingState() m_ui->pathEdit->setEnabled(isEnabled); m_ui->pathSelectionButton->setEnabled(isEnabled); m_ui->passwordEdit->setEnabled(isEnabled); + m_ui->recurseIntoGroupsCheckbox->setEnabled(isEnabled); if (!m_temporaryGroup || !isEnabled) { m_ui->messageWidget->hideMessage(); @@ -188,6 +190,7 @@ void EditGroupWidgetKeeShare::update() m_ui->typeComboBox->setCurrentIndex(reference.type); m_ui->passwordEdit->setText(reference.password); m_ui->pathEdit->setText(reference.path); + m_ui->recurseIntoGroupsCheckbox->setChecked(reference.recurse); } updateSharingState(); @@ -291,3 +294,13 @@ void EditGroupWidgetKeeShare::selectType() updateSharingState(); } + +void EditGroupWidgetKeeShare::recurseIntoGroupsToggled(bool toggled) +{ + if (!m_temporaryGroup) { + return; + } + auto reference = KeeShare::referenceOf(m_temporaryGroup); + reference.recurse = toggled; + KeeShare::setReferenceTo(m_temporaryGroup, reference); +} diff --git a/src/keeshare/group/EditGroupWidgetKeeShare.h b/src/keeshare/group/EditGroupWidgetKeeShare.h index aaa3ebbd3..3e403b1e3 100644 --- a/src/keeshare/group/EditGroupWidgetKeeShare.h +++ b/src/keeshare/group/EditGroupWidgetKeeShare.h @@ -48,6 +48,7 @@ private slots: void selectPassword(); void launchPathSelectionDialog(); void selectPath(); + void recurseIntoGroupsToggled(bool); private: QScopedPointer m_ui; diff --git a/src/keeshare/group/EditGroupWidgetKeeShare.ui b/src/keeshare/group/EditGroupWidgetKeeShare.ui index 857ba61c8..921b1f002 100644 --- a/src/keeshare/group/EditGroupWidgetKeeShare.ui +++ b/src/keeshare/group/EditGroupWidgetKeeShare.ui @@ -138,7 +138,7 @@ - + @@ -171,7 +171,7 @@ - + Qt::Vertical @@ -184,6 +184,13 @@ + + + + Share recursively + + +