Skip to content

Commit e4bb80b

Browse files
authored
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 d6e726a commit e4bb80b

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
@@ -817,26 +817,45 @@ void MainWindow::updateCopyAttributesMenu()
817817

818818
void MainWindow::updateSetTagsMenu()
819819
{
820-
// Remove all existing actions
821-
m_ui->menuTags->clear();
820+
auto actionForTag = [](const QMenu* menu, const QString& tag) -> QAction* {
821+
for (const auto action : menu->actions()) {
822+
if (action->text() == tag) {
823+
return action;
824+
}
825+
}
826+
return nullptr;
827+
};
822828

823829
auto dbWidget = m_ui->tabWidget->currentDatabaseWidget();
824830
if (dbWidget) {
825831
// Enumerate tags applied to the selected entries
826832
QSet<QString> selectedTags;
827-
for (auto entry : dbWidget->entryView()->selectedEntries()) {
828-
for (auto tag : entry->tagList()) {
833+
for (const auto entry : dbWidget->entryView()->selectedEntries()) {
834+
for (const auto& tag : entry->tagList()) {
829835
selectedTags.insert(tag);
830836
}
831837
}
832838

833839
// Add known database tags as actions and set checked if
834840
// a selected entry has that tag
835-
for (auto tag : dbWidget->database()->tagList()) {
836-
auto action = m_ui->menuTags->addAction(icons()->icon("tag"), tag);
837-
action->setCheckable(true);
838-
action->setChecked(selectedTags.contains(tag));
839-
m_setTagsMenuActions->addAction(action);
841+
const auto tagList = dbWidget->database()->tagList();
842+
for (const auto& tag : tagList) {
843+
auto action = actionForTag(m_ui->menuTags, tag);
844+
if (action) {
845+
action->setChecked(selectedTags.contains(tag));
846+
} else {
847+
action = m_ui->menuTags->addAction(icons()->icon("tag"), tag);
848+
action->setCheckable(true);
849+
action->setChecked(selectedTags.contains(tag));
850+
m_setTagsMenuActions->addAction(action);
851+
}
852+
}
853+
854+
// Remove missing tags
855+
for (const auto action : m_ui->menuTags->actions()) {
856+
if (!tagList.contains(action->text())) {
857+
action->deleteLater();
858+
}
840859
}
841860
}
842861

@@ -942,6 +961,14 @@ void MainWindow::updateMenuActionState()
942961
m_ui->menuEntryCopyAttribute->setEnabled(singleEntryOrEditing);
943962
m_ui->menuEntryTotp->setEnabled(singleEntrySelected);
944963
m_ui->menuTags->setEnabled(multiEntrySelected);
964+
// Handle tear-off tags menu
965+
if (m_ui->menuTags->isTearOffMenuVisible()) {
966+
if (!databaseUnlocked) {
967+
m_ui->menuTags->hideTearOffMenu();
968+
} else {
969+
updateSetTagsMenu();
970+
}
971+
}
945972
m_ui->actionEntryAutoType->setEnabled(singleEntrySelected && dbWidget->currentEntryHasAutoTypeEnabled());
946973
m_ui->actionEntryAutoType->menu()->setEnabled(singleEntrySelected && dbWidget->currentEntryHasAutoTypeEnabled());
947974
m_ui->actionEntryAutoTypeSequence->setText(singleEntrySelected

src/gui/MainWindow.ui

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,9 @@
314314
<addaction name="actionEntrySetupTotp"/>
315315
</widget>
316316
<widget class="QMenu" name="menuTags">
317+
<property name="tearOffEnabled">
318+
<bool>true</bool>
319+
</property>
317320
<property name="title">
318321
<string>Tags</string>
319322
</property>

src/gui/styles/base/BaseStyle.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,7 +2636,21 @@ void BaseStyle::drawControl(ControlElement element,
26362636
}
26372637
break;
26382638
}
2639+
case CE_MenuTearoff: {
2640+
if (option->state & State_Selected) {
2641+
painter->fillRect(option->rect, option->palette.brush(QPalette::Highlight));
2642+
painter->setPen(QPen(option->palette.highlightedText().color(), 1, Qt::DashLine));
2643+
} else {
2644+
painter->fillRect(option->rect, option->palette.brush(QPalette::Button));
2645+
painter->setPen(QPen(option->palette.buttonText().color(), 1, Qt::DashLine));
2646+
}
26392647

2648+
painter->drawLine(option->rect.x() + 2,
2649+
option->rect.y() + option->rect.height() / 2,
2650+
option->rect.x() + option->rect.width() - 4,
2651+
option->rect.y() + option->rect.height() / 2);
2652+
break;
2653+
}
26402654
case CE_MenuItem: {
26412655
auto menuItem = qstyleoption_cast<const QStyleOptionMenuItem*>(option);
26422656
if (!menuItem)

0 commit comments

Comments
 (0)