Skip to content

Commit beb314d

Browse files
committed
Support tearing off tags menu (#11652)
* Support tearing off tags menu * Closes #11649 - tags menu can be torn off to set and unset tags without having to dive into the context menu every time. * Tags menu will hide when database is locked or view is switched away from the main database view (eg, settings)
1 parent 903b8f1 commit beb314d

File tree

3 files changed

+53
-9
lines changed

3 files changed

+53
-9
lines changed

src/gui/MainWindow.cpp

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -856,26 +856,45 @@ void MainWindow::updateCopyAttributesMenu()
856856

857857
void MainWindow::updateSetTagsMenu()
858858
{
859-
// Remove all existing actions
860-
m_ui->menuTags->clear();
859+
auto actionForTag = [](const QMenu* menu, const QString& tag) -> QAction* {
860+
for (const auto action : menu->actions()) {
861+
if (action->text() == tag) {
862+
return action;
863+
}
864+
}
865+
return nullptr;
866+
};
861867

862868
auto dbWidget = m_ui->tabWidget->currentDatabaseWidget();
863869
if (dbWidget) {
864870
// Enumerate tags applied to the selected entries
865871
QSet<QString> selectedTags;
866-
for (auto entry : dbWidget->entryView()->selectedEntries()) {
867-
for (auto tag : entry->tagList()) {
872+
for (const auto entry : dbWidget->entryView()->selectedEntries()) {
873+
for (const auto& tag : entry->tagList()) {
868874
selectedTags.insert(tag);
869875
}
870876
}
871877

872878
// Add known database tags as actions and set checked if
873879
// a selected entry has that tag
874-
for (auto tag : dbWidget->database()->tagList()) {
875-
auto action = m_ui->menuTags->addAction(icons()->icon("tag"), tag);
876-
action->setCheckable(true);
877-
action->setChecked(selectedTags.contains(tag));
878-
m_setTagsMenuActions->addAction(action);
880+
const auto tagList = dbWidget->database()->tagList();
881+
for (const auto& tag : tagList) {
882+
auto action = actionForTag(m_ui->menuTags, tag);
883+
if (action) {
884+
action->setChecked(selectedTags.contains(tag));
885+
} else {
886+
action = m_ui->menuTags->addAction(icons()->icon("tag"), tag);
887+
action->setCheckable(true);
888+
action->setChecked(selectedTags.contains(tag));
889+
m_setTagsMenuActions->addAction(action);
890+
}
891+
}
892+
893+
// Remove missing tags
894+
for (const auto action : m_ui->menuTags->actions()) {
895+
if (!tagList.contains(action->text())) {
896+
action->deleteLater();
897+
}
879898
}
880899
}
881900

@@ -981,6 +1000,14 @@ void MainWindow::updateMenuActionState()
9811000
m_ui->menuEntryCopyAttribute->setEnabled(singleEntryOrEditing);
9821001
m_ui->menuEntryTotp->setEnabled(singleEntrySelected);
9831002
m_ui->menuTags->setEnabled(multiEntrySelected);
1003+
// Handle tear-off tags menu
1004+
if (m_ui->menuTags->isTearOffMenuVisible()) {
1005+
if (!databaseUnlocked) {
1006+
m_ui->menuTags->hideTearOffMenu();
1007+
} else {
1008+
updateSetTagsMenu();
1009+
}
1010+
}
9841011
m_ui->actionEntryAutoType->setEnabled(singleEntrySelected && dbWidget->currentEntryHasAutoTypeEnabled());
9851012
m_ui->actionEntryAutoType->menu()->setEnabled(singleEntrySelected && dbWidget->currentEntryHasAutoTypeEnabled());
9861013
m_ui->actionEntryAutoTypeSequence->setText(singleEntrySelected

src/gui/MainWindow.ui

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@
307307
<addaction name="actionEntrySetupTotp"/>
308308
</widget>
309309
<widget class="QMenu" name="menuTags">
310+
<property name="tearOffEnabled">
311+
<bool>true</bool>
312+
</property>
310313
<property name="title">
311314
<string>Tags</string>
312315
</property>

src/gui/styles/base/BaseStyle.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2658,7 +2658,21 @@ void BaseStyle::drawControl(ControlElement element,
26582658
}
26592659
break;
26602660
}
2661+
case CE_MenuTearoff: {
2662+
if (option->state & State_Selected) {
2663+
painter->fillRect(option->rect, option->palette.brush(QPalette::Highlight));
2664+
painter->setPen(QPen(option->palette.highlightedText().color(), 1, Qt::DashLine));
2665+
} else {
2666+
painter->fillRect(option->rect, option->palette.brush(QPalette::Button));
2667+
painter->setPen(QPen(option->palette.buttonText().color(), 1, Qt::DashLine));
2668+
}
26612669

2670+
painter->drawLine(option->rect.x() + 2,
2671+
option->rect.y() + option->rect.height() / 2,
2672+
option->rect.x() + option->rect.width() - 4,
2673+
option->rect.y() + option->rect.height() / 2);
2674+
break;
2675+
}
26622676
case CE_MenuItem: {
26632677
auto menuItem = qstyleoption_cast<const QStyleOptionMenuItem*>(option);
26642678
if (!menuItem)

0 commit comments

Comments
 (0)