mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2026-03-11 08:54:48 +00:00
Merge bbeaf94d1d into 36a26308d0
This commit is contained in:
commit
a3e27c5964
9 changed files with 168 additions and 17 deletions
|
|
@ -5997,6 +5997,10 @@ Are you sure you want to continue with this file?</source>
|
|||
<source>Show Toolbar</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Entries of Subgroups</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Show Preview Panel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
|
@ -6350,6 +6354,10 @@ Expect some bugs and minor issues, this version is meant for testing purposes.</
|
|||
<source>Toggle Show Toolbar</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Toggle Show Entries of Subgroups</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Toggle Show Preview Panel</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
|
|||
{Config::GUI_SearchWaitForEnter, {QS("GUI/SearchWaitForEnter"), Roaming, false}},
|
||||
{Config::GUI_ShowExpiredEntriesOnDatabaseUnlock, {QS("GUI/ShowExpiredEntriesOnDatabaseUnlock"), Roaming, true}},
|
||||
{Config::GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays, {QS("GUI/ShowExpiredEntriesOnDatabaseUnlockOffsetDays"), Roaming, 3}},
|
||||
{Config::GUI_ShowSubgroupEntries, {QS("GUI/ShowSubgroupEntries"), Roaming, false}},
|
||||
{Config::GUI_FontSizeOffset, {QS("GUI/FontSizeOffset"), Local, 0}},
|
||||
|
||||
{Config::GUI_MainWindowGeometry, {QS("GUI/MainWindowGeometry"), Local, {}}},
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ public:
|
|||
GUI_SearchWaitForEnter,
|
||||
GUI_ShowExpiredEntriesOnDatabaseUnlock,
|
||||
GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays,
|
||||
GUI_ShowSubgroupEntries,
|
||||
GUI_FontSizeOffset,
|
||||
|
||||
GUI_MainWindowGeometry,
|
||||
|
|
|
|||
|
|
@ -2059,6 +2059,11 @@ void MainWindow::initViewMenu()
|
|||
applySettingsChanges();
|
||||
});
|
||||
|
||||
m_ui->actionShowEntriesOfSubgroups->setChecked(config()->get(Config::GUI_ShowSubgroupEntries).toBool());
|
||||
connect(m_ui->actionShowEntriesOfSubgroups, &QAction::toggled, this, [](bool checked) {
|
||||
config()->set(Config::GUI_ShowSubgroupEntries, checked);
|
||||
});
|
||||
|
||||
m_ui->actionShowGroupPanel->setChecked(!config()->get(Config::GUI_HideGroupPanel).toBool());
|
||||
connect(m_ui->actionShowGroupPanel, &QAction::toggled, this, [](bool checked) {
|
||||
config()->set(Config::GUI_HideGroupPanel, !checked);
|
||||
|
|
|
|||
|
|
@ -399,6 +399,8 @@
|
|||
<addaction name="actionShowMenubar"/>
|
||||
<addaction name="actionShowToolbar"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionShowEntriesOfSubgroups"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionHideUsernames"/>
|
||||
<addaction name="actionHidePasswords"/>
|
||||
</widget>
|
||||
|
|
@ -1244,6 +1246,17 @@
|
|||
<string notr="true">Ctrl+Shift+A</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShowEntriesOfSubgroups">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Entries of Subgroups</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Toggle Show Entries of Subgroups</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHideUsernames">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
|
|
|||
|
|
@ -68,10 +68,38 @@ void EntryModel::setGroup(Group* group)
|
|||
|
||||
m_group = group;
|
||||
m_allGroups.clear();
|
||||
m_entries = group->entries();
|
||||
m_orgEntries.clear();
|
||||
|
||||
makeConnections(group);
|
||||
// Check if we should show subgroup entries
|
||||
if (config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
m_entries = group->entriesRecursive();
|
||||
|
||||
// When showing subgroup entries, we need to connect to all groups
|
||||
// that contain the entries being displayed
|
||||
for (const auto& entry : asConst(m_entries)) {
|
||||
if (entry->group() && !m_allGroups.contains(entry->group())) {
|
||||
m_allGroups.append(entry->group());
|
||||
}
|
||||
}
|
||||
|
||||
// Always include the current group itself to handle new entries added directly to it
|
||||
if (!m_allGroups.contains(group)) {
|
||||
m_allGroups.append(group);
|
||||
}
|
||||
|
||||
// Connect to all groups that have entries in the view (or could have entries)
|
||||
for (const auto& groupToConnect : m_allGroups) {
|
||||
if (groupToConnect) {
|
||||
makeConnections(groupToConnect);
|
||||
}
|
||||
}
|
||||
|
||||
// Also connect to groupAdded signal from the main group to detect new subgroups
|
||||
connect(group, SIGNAL(groupAdded()), SLOT(groupAdded()));
|
||||
} else {
|
||||
m_entries = group->entries();
|
||||
makeConnections(group);
|
||||
}
|
||||
m_orgEntries.clear();
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
|
@ -88,13 +116,15 @@ void EntryModel::setEntries(const QList<Entry*>& entries)
|
|||
m_orgEntries = entries;
|
||||
|
||||
for (const auto entry : asConst(m_entries)) {
|
||||
if (entry->group()) {
|
||||
m_allGroups.insert(entry->group());
|
||||
if (entry->group() && !m_allGroups.contains(entry->group())) {
|
||||
m_allGroups.append(entry->group());
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto group : m_allGroups) {
|
||||
makeConnections(group);
|
||||
if (group) {
|
||||
makeConnections(group);
|
||||
}
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
|
|
@ -530,7 +560,12 @@ void EntryModel::entryAdded(Entry* entry)
|
|||
}
|
||||
|
||||
if (m_group) {
|
||||
m_entries = m_group->entries();
|
||||
// Check if we should show subgroup entries
|
||||
if (config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
m_entries = m_group->entriesRecursive();
|
||||
} else {
|
||||
m_entries = m_group->entries();
|
||||
}
|
||||
}
|
||||
endInsertRows();
|
||||
}
|
||||
|
|
@ -546,7 +581,12 @@ void EntryModel::entryAboutToRemove(Entry* entry)
|
|||
void EntryModel::entryRemoved()
|
||||
{
|
||||
if (m_group) {
|
||||
m_entries = m_group->entries();
|
||||
// Check if we should show subgroup entries
|
||||
if (config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
m_entries = m_group->entriesRecursive();
|
||||
} else {
|
||||
m_entries = m_group->entries();
|
||||
}
|
||||
}
|
||||
endRemoveRows();
|
||||
}
|
||||
|
|
@ -562,7 +602,12 @@ void EntryModel::entryAboutToMoveUp(int row)
|
|||
void EntryModel::entryMovedUp()
|
||||
{
|
||||
if (m_group) {
|
||||
m_entries = m_group->entries();
|
||||
// Check if we should show subgroup entries
|
||||
if (config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
m_entries = m_group->entriesRecursive();
|
||||
} else {
|
||||
m_entries = m_group->entries();
|
||||
}
|
||||
}
|
||||
endMoveRows();
|
||||
}
|
||||
|
|
@ -578,11 +623,26 @@ void EntryModel::entryAboutToMoveDown(int row)
|
|||
void EntryModel::entryMovedDown()
|
||||
{
|
||||
if (m_group) {
|
||||
m_entries = m_group->entries();
|
||||
// Check if we should show subgroup entries
|
||||
if (config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
m_entries = m_group->entriesRecursive();
|
||||
} else {
|
||||
m_entries = m_group->entries();
|
||||
}
|
||||
}
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
void EntryModel::groupAdded()
|
||||
{
|
||||
// When a new subgroup is added to the current group and we're showing subgroup entries,
|
||||
// we need to refresh our connections to include the new subgroup
|
||||
if (m_group && config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
// Refresh the entry list and connections to include new subgroups
|
||||
setGroup(m_group);
|
||||
}
|
||||
}
|
||||
|
||||
void EntryModel::entryDataChanged(Entry* entry)
|
||||
{
|
||||
int row = m_entries.indexOf(entry);
|
||||
|
|
@ -598,6 +658,12 @@ void EntryModel::onConfigChanged(Config::ConfigKey key)
|
|||
case Config::GUI_HidePasswords:
|
||||
emit dataChanged(index(0, Password), index(rowCount() - 1, Password), {Qt::DisplayRole});
|
||||
break;
|
||||
case Config::GUI_ShowSubgroupEntries:
|
||||
// Refresh the entry list when the subgroup setting changes
|
||||
if (m_group) {
|
||||
setGroup(m_group);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -609,8 +675,17 @@ void EntryModel::severConnections()
|
|||
disconnect(m_group, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
for (const Group* group : asConst(m_allGroups)) {
|
||||
disconnect(group, nullptr, this, nullptr);
|
||||
// Use an iterator to safely remove null pointers while iterating
|
||||
auto it = m_allGroups.begin();
|
||||
while (it != m_allGroups.end()) {
|
||||
if (*it) {
|
||||
// Group is still valid, disconnect from it
|
||||
disconnect(*it, nullptr, this, nullptr);
|
||||
++it;
|
||||
} else {
|
||||
// Group has been deleted, remove the null pointer
|
||||
it = m_allGroups.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@
|
|||
#define KEEPASSX_ENTRYMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QList>
|
||||
#include <QPixmap>
|
||||
#include <QPointer>
|
||||
#include <QSet>
|
||||
|
||||
#include "core/Config.h"
|
||||
|
|
@ -81,6 +83,7 @@ private slots:
|
|||
void entryAboutToMoveDown(int row);
|
||||
void entryMovedDown();
|
||||
void entryDataChanged(Entry* entry);
|
||||
void groupAdded();
|
||||
|
||||
void onConfigChanged(Config::ConfigKey key);
|
||||
|
||||
|
|
@ -89,10 +92,10 @@ private:
|
|||
void makeConnections(const Group* group);
|
||||
|
||||
bool m_backgroundColorVisible = true;
|
||||
Group* m_group;
|
||||
QPointer<Group> m_group;
|
||||
QList<Entry*> m_entries;
|
||||
QList<Entry*> m_orgEntries;
|
||||
QSet<const Group*> m_allGroups;
|
||||
QList<QPointer<const Group>> m_allGroups;
|
||||
|
||||
const QString HiddenContentDisplay;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include "gui/Icons.h"
|
||||
#include "gui/SortFilterHideProxyModel.h"
|
||||
|
||||
#include "core/Config.h"
|
||||
|
||||
#define ICON_ONLY_SECTION_SIZE 26
|
||||
|
||||
class PasswordStrengthItemDelegate : public QStyledItemDelegate
|
||||
|
|
@ -94,6 +96,9 @@ EntryView::EntryView(QWidget* parent)
|
|||
emit entrySelectionChanged(currentEntry());
|
||||
});
|
||||
|
||||
// Listen for config changes to update Group column visibility
|
||||
connect(config(), &Config::changed, this, &EntryView::onConfigChanged);
|
||||
|
||||
new QShortcut(Qt::CTRL + Qt::Key_F10, this, SLOT(contextMenuShortcutPressed()), nullptr, Qt::WidgetShortcut);
|
||||
new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_J, this, SLOT(jumpToGroupShortcut()), nullptr, Qt::WidgetShortcut);
|
||||
|
||||
|
|
@ -214,7 +219,16 @@ void EntryView::focusInEvent(QFocusEvent* event)
|
|||
void EntryView::displayGroup(Group* group)
|
||||
{
|
||||
m_model->setGroup(group);
|
||||
header()->hideSection(EntryModel::ParentGroup);
|
||||
|
||||
// Show Group column when subgroup entries are enabled, since entries from different groups will be shown
|
||||
// But respect user's preference if they've manually hidden it
|
||||
if (config()->get(Config::GUI_ShowSubgroupEntries).toBool() && !m_userHidGroupColumnInSubgroupMode) {
|
||||
header()->showSection(EntryModel::ParentGroup);
|
||||
} else if (!config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
header()->hideSection(EntryModel::ParentGroup);
|
||||
}
|
||||
// If user has hidden the column in subgroup mode, don't force it to show
|
||||
|
||||
setFirstEntryActive();
|
||||
m_inSearchMode = false;
|
||||
}
|
||||
|
|
@ -360,7 +374,8 @@ void EntryView::showHeaderMenu(const QPoint& position)
|
|||
int columnIndex = action->data().toInt();
|
||||
action->setChecked(!isColumnHidden(columnIndex));
|
||||
}
|
||||
actions[EntryModel::ParentGroup]->setVisible(inSearchMode());
|
||||
actions[EntryModel::ParentGroup]->setVisible(inSearchMode()
|
||||
|| config()->get(Config::GUI_ShowSubgroupEntries).toBool());
|
||||
|
||||
m_headerMenu->popup(mapToGlobal(position));
|
||||
}
|
||||
|
|
@ -390,11 +405,21 @@ void EntryView::toggleColumnVisibility(QAction* action)
|
|||
if (header()->sectionSize(columnIndex) == 0) {
|
||||
header()->resizeSection(columnIndex, header()->defaultSectionSize());
|
||||
}
|
||||
// Reset flag when user manually shows Group column
|
||||
if (columnIndex == EntryModel::ParentGroup && !m_inSearchMode
|
||||
&& config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
m_userHidGroupColumnInSubgroupMode = false;
|
||||
}
|
||||
resetFixedColumns();
|
||||
return;
|
||||
}
|
||||
if ((header()->count() - header()->hiddenSectionCount()) > 1) {
|
||||
header()->hideSection(columnIndex);
|
||||
// Track when user manually hides Group column while subgroup entries is enabled
|
||||
if (columnIndex == EntryModel::ParentGroup && !m_inSearchMode
|
||||
&& config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
m_userHidGroupColumnInSubgroupMode = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
action->setChecked(true);
|
||||
|
|
@ -466,7 +491,8 @@ void EntryView::resetFixedColumns()
|
|||
void EntryView::resetViewToDefaults()
|
||||
{
|
||||
// Reduce number of columns that are shown by default
|
||||
if (m_inSearchMode) {
|
||||
if (m_inSearchMode
|
||||
|| (config()->get(Config::GUI_ShowSubgroupEntries).toBool() && !m_userHidGroupColumnInSubgroupMode)) {
|
||||
header()->showSection(EntryModel::ParentGroup);
|
||||
} else {
|
||||
header()->hideSection(EntryModel::ParentGroup);
|
||||
|
|
@ -602,6 +628,22 @@ bool EntryView::isColumnHidden(int logicalIndex)
|
|||
return header()->isSectionHidden(logicalIndex) || header()->sectionSize(logicalIndex) == 0;
|
||||
}
|
||||
|
||||
void EntryView::onConfigChanged(Config::ConfigKey key)
|
||||
{
|
||||
if (key == Config::GUI_ShowSubgroupEntries && !m_inSearchMode) {
|
||||
// Reset user preference when setting is toggled - this allows the
|
||||
// Group column to auto-appear when re-enabling the feature
|
||||
m_userHidGroupColumnInSubgroupMode = false;
|
||||
|
||||
// Update Group column visibility when subgroup entries setting changes
|
||||
if (config()->get(Config::GUI_ShowSubgroupEntries).toBool()) {
|
||||
header()->showSection(EntryModel::ParentGroup);
|
||||
} else {
|
||||
header()->hideSection(EntryModel::ParentGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntryView::jumpToGroupShortcut()
|
||||
{
|
||||
// Only allow jump to group in search mode
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <QTreeView>
|
||||
|
||||
#include "core/Config.h"
|
||||
#include "gui/entry/EntryModel.h"
|
||||
|
||||
class Entry;
|
||||
|
|
@ -72,6 +73,7 @@ private slots:
|
|||
void resetViewToDefaults();
|
||||
void contextMenuShortcutPressed();
|
||||
void sortIndicatorChanged(int logicalIndex, Qt::SortOrder order);
|
||||
void onConfigChanged(Config::ConfigKey key);
|
||||
void jumpToGroupShortcut();
|
||||
|
||||
private:
|
||||
|
|
@ -85,6 +87,7 @@ private:
|
|||
Qt::SortOrder m_lastOrder;
|
||||
bool m_inSearchMode = false;
|
||||
bool m_columnsNeedRelayout = true;
|
||||
bool m_userHidGroupColumnInSubgroupMode = false;
|
||||
|
||||
QMenu* m_headerMenu;
|
||||
QActionGroup* m_columnActions;
|
||||
|
|
|
|||
Loading…
Reference in a new issue