From 37ef2c0e4345f58c244a46a992a853e0d1e98056 Mon Sep 17 00:00:00 2001 From: Vladislav P Date: Wed, 13 Nov 2024 14:12:46 +0300 Subject: [PATCH 1/2] bookmarks: Avoid leaking taglist menu and QDialog Avoid leaking taglist menu each time it is shown Avoid leaking QDialog each time it is shown --- src/qtgui/bookmarkstaglist.cpp | 87 +++++++++++++++++----------------- src/qtgui/bookmarkstaglist.h | 2 +- src/qtgui/dockbookmarks.cpp | 39 ++++++++------- src/qtgui/dockbookmarks.h | 3 ++ 4 files changed, 66 insertions(+), 65 deletions(-) diff --git a/src/qtgui/bookmarkstaglist.cpp b/src/qtgui/bookmarkstaglist.cpp index 791f48d93c..3702b47c3a 100644 --- a/src/qtgui/bookmarkstaglist.cpp +++ b/src/qtgui/bookmarkstaglist.cpp @@ -36,6 +36,48 @@ BookmarksTagList::BookmarksTagList(QWidget *parent, bool bShowUntagged ) this, SLOT(on_cellClicked(int,int))); // right click menu + popupMenu=new QMenu(this); + + // Rename currently does not work. + // The problem is that after the tag name is changed in GUI + // you can not find the right TagInfo because you dont know + // the old tag name. + #if 0 + // MenuItem "Rename" + { + QAction* actionRename = new QAction("Rename", this); + popupMenu->addAction(actionRename); + connect(actionRename, SIGNAL(triggered()), this, SLOT(RenameSelectedTag())); + } + #endif + + // MenuItem "Create new Tag" + { + QAction* actionNewTag = new QAction("Create new Tag", this); + popupMenu->addAction(actionNewTag); + connect(actionNewTag, SIGNAL(triggered()), this, SLOT(AddNewTag())); + } + + // Menu "Delete Tag" + { + QAction* actionDeleteTag = new QAction("Delete Tag", this); + popupMenu->addAction(actionDeleteTag); + connect(actionDeleteTag, SIGNAL(triggered()), this, SLOT(DeleteSelectedTag())); + } + + // Menu "Select All" + { + QAction* action = new QAction("Select All", this); + popupMenu->addAction(action); + connect(action, SIGNAL(triggered()), this, SLOT(SelectAll())); + } + + // Menu "Deselect All" + { + QAction* action = new QAction("Deselect All", this); + popupMenu->addAction(action); + connect(action, SIGNAL(triggered()), this, SLOT(DeselectAll())); + } setContextMenuPolicy(Qt::CustomContextMenu); connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ShowContextMenu(const QPoint&))); @@ -180,50 +222,7 @@ QStringList BookmarksTagList::getSelectedTags() void BookmarksTagList::ShowContextMenu(const QPoint& pos) { - QMenu* menu=new QMenu(this); - - // Rename currently does not work. - // The problem is that after the tag name is changed in GUI - // you can not find the right TagInfo because you dont know - // the old tag name. - #if 0 - // MenuItem "Rename" - { - QAction* actionRename = new QAction("Rename", this); - menu->addAction(actionRename); - connect(actionRename, SIGNAL(triggered()), this, SLOT(RenameSelectedTag())); - } - #endif - - // MenuItem "Create new Tag" - { - QAction* actionNewTag = new QAction("Create new Tag", this); - menu->addAction(actionNewTag); - connect(actionNewTag, SIGNAL(triggered()), this, SLOT(AddNewTag())); - } - - // Menu "Delete Tag" - { - QAction* actionDeleteTag = new QAction("Delete Tag", this); - menu->addAction(actionDeleteTag); - connect(actionDeleteTag, SIGNAL(triggered()), this, SLOT(DeleteSelectedTag())); - } - - // Menu "Select All" - { - QAction* action = new QAction("Select All", this); - menu->addAction(action); - connect(action, SIGNAL(triggered()), this, SLOT(SelectAll())); - } - - // Menu "Deselect All" - { - QAction* action = new QAction("Deselect All", this); - menu->addAction(action); - connect(action, SIGNAL(triggered()), this, SLOT(DeselectAll())); - } - - menu->popup(viewport()->mapToGlobal(pos)); + popupMenu->popup(viewport()->mapToGlobal(pos)); } #if 0 diff --git a/src/qtgui/bookmarkstaglist.h b/src/qtgui/bookmarkstaglist.h index 66caa9a48c..f7f7a06066 100644 --- a/src/qtgui/bookmarkstaglist.h +++ b/src/qtgui/bookmarkstaglist.h @@ -39,7 +39,7 @@ class BookmarksTagList : public QTableWidget private: bool m_bShowUntagged; - + QMenu* popupMenu{nullptr}; signals: public slots: diff --git a/src/qtgui/dockbookmarks.cpp b/src/qtgui/dockbookmarks.cpp index ff518588de..afa5c70af8 100644 --- a/src/qtgui/dockbookmarks.cpp +++ b/src/qtgui/dockbookmarks.cpp @@ -30,7 +30,6 @@ #include #include "bookmarks.h" -#include "bookmarkstaglist.h" #include "dockbookmarks.h" #include "dockrxopt.h" #include "qtcolorpicker.h" @@ -73,6 +72,20 @@ DockBookmarks::DockBookmarks(QWidget *parent) : connect(ui->tableViewFrequencyList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ShowContextMenu(const QPoint&))); + tagsDialog = new QDialog(this); + tagsDialog->setWindowTitle("Change Bookmark Tags"); + + dialogTaglist = new BookmarksTagList(tagsDialog, false); + + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok + | QDialogButtonBox::Cancel); + connect(buttonBox, SIGNAL(accepted()), tagsDialog, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), tagsDialog, SLOT(reject())); + + QVBoxLayout *mainLayout = new QVBoxLayout(tagsDialog); + mainLayout->addWidget(dialogTaglist); + mainLayout->addWidget(buttonBox); + // Update GUI Bookmarks::Get().load(); bookmarksTableModel->update(); @@ -249,27 +262,13 @@ void DockBookmarks::changeBookmarkTags(int row, int /*column*/) // Create and show the Dialog for a new Bookmark. // Write the result into variable 'tags'. { - QDialog dialog(this); - dialog.setWindowTitle("Change Bookmark Tags"); - - BookmarksTagList* taglist = new BookmarksTagList(&dialog, false); - taglist->updateTags(); - taglist->setSelectedTags(bmi.tags); - taglist->DeleteTag(TagInfo::strUntagged); - - QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok - | QDialogButtonBox::Cancel); - connect(buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); - connect(buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject())); - - QVBoxLayout *mainLayout = new QVBoxLayout(&dialog); - mainLayout->addWidget(taglist); - mainLayout->addWidget(buttonBox); - - ok = dialog.exec(); + dialogTaglist->updateTags(); + dialogTaglist->setSelectedTags(bmi.tags); + dialogTaglist->DeleteTag(TagInfo::strUntagged); + ok = tagsDialog->exec(); if (ok) { - tags = taglist->getSelectedTags(); + tags = dialogTaglist->getSelectedTags(); // Change Tags of Bookmark bmi.tags.clear(); diff --git a/src/qtgui/dockbookmarks.h b/src/qtgui/dockbookmarks.h index baf3818b0f..ab63b228d1 100644 --- a/src/qtgui/dockbookmarks.h +++ b/src/qtgui/dockbookmarks.h @@ -25,6 +25,7 @@ #include #include #include "qtgui/bookmarkstablemodel.h" +#include "qtgui/bookmarkstaglist.h" #include namespace Ui { @@ -48,6 +49,8 @@ class DockBookmarks : public QDockWidget private: Ui::DockBookmarks *ui; QMenu* contextmenu; + QDialog* tagsDialog; + BookmarksTagList* dialogTaglist; qint64 m_currentFrequency; bool m_updating; BookmarksTableModel *bookmarksTableModel; From 34d5cb062e4b1b5d30ab77b14c7a40979e57779d Mon Sep 17 00:00:00 2001 From: Vladslav P Date: Sun, 10 Nov 2024 02:56:51 +0300 Subject: [PATCH 2/2] bookmarks: Support tag renaming Support tag renaming in all 3 places: new bookmark dialog, bookmark tags dialog and tag selection list in a bookmarks dock. Immediately update tags/bookmarks everywhere when tag name/color is changed. Prevent renaming "Untagged" tag and accidental creation of duplicate tags by renaming. --- src/applications/gqrx/mainwindow.cpp | 2 ++ src/qtgui/bookmarks.cpp | 4 +-- src/qtgui/bookmarkstaglist.cpp | 40 ++++++++++++++-------- src/qtgui/bookmarkstaglist.h | 4 ++- src/qtgui/dockbookmarks.cpp | 51 ++++++++++++++++++++++++++-- src/qtgui/dockbookmarks.h | 2 ++ 6 files changed, 83 insertions(+), 20 deletions(-) diff --git a/src/applications/gqrx/mainwindow.cpp b/src/applications/gqrx/mainwindow.cpp index 72681f13af..7d48905659 100644 --- a/src/applications/gqrx/mainwindow.cpp +++ b/src/applications/gqrx/mainwindow.cpp @@ -2491,6 +2491,8 @@ void MainWindow::on_actionAddBookmark_triggered() mainLayout->addWidget(buttonCreateTag); mainLayout->addWidget(taglist); mainLayout->addWidget(buttonBox); + connect(taglist, SIGNAL(itemChanged(QTableWidgetItem *)), uiDockBookmarks, SLOT(dialog_tableWidgetTagList_itemChanged(QTableWidgetItem *))); + connect(taglist, SIGNAL(colorChanged()), uiDockBookmarks, SLOT(dialog_tableWidgetTagList_colorChanged())); ok = dialog.exec(); if (ok) diff --git a/src/qtgui/bookmarks.cpp b/src/qtgui/bookmarks.cpp index d4593e5ac6..1712ddf40b 100644 --- a/src/qtgui/bookmarks.cpp +++ b/src/qtgui/bookmarks.cpp @@ -289,8 +289,8 @@ bool Bookmarks::removeTag(QString tagName) bool Bookmarks::setTagChecked(QString tagName, bool bChecked) { int idx = getTagIndex(tagName); - if (idx == -1) return false; - m_TagList[idx]->active = bChecked; + if (idx != -1) + m_TagList[idx]->active = bChecked; emit BookmarksChanged(); emit TagListChanged(); return true; diff --git a/src/qtgui/bookmarkstaglist.cpp b/src/qtgui/bookmarkstaglist.cpp index 3702b47c3a..b678780376 100644 --- a/src/qtgui/bookmarkstaglist.cpp +++ b/src/qtgui/bookmarkstaglist.cpp @@ -34,22 +34,18 @@ BookmarksTagList::BookmarksTagList(QWidget *parent, bool bShowUntagged ) { connect(this, SIGNAL(cellClicked(int,int)), this, SLOT(on_cellClicked(int,int))); + connect(this, SIGNAL(cellDoubleClicked(int,int)), + this, SLOT(on_cellDoubleClicked(int,int))); // right click menu popupMenu=new QMenu(this); - // Rename currently does not work. - // The problem is that after the tag name is changed in GUI - // you can not find the right TagInfo because you dont know - // the old tag name. - #if 0 // MenuItem "Rename" { QAction* actionRename = new QAction("Rename", this); popupMenu->addAction(actionRename); connect(actionRename, SIGNAL(triggered()), this, SLOT(RenameSelectedTag())); } - #endif // MenuItem "Create new Tag" { @@ -104,6 +100,14 @@ void BookmarksTagList::on_cellClicked(int row, int column) } } +void BookmarksTagList::on_cellDoubleClicked(int row, int column) +{ + if(column==1) + { + toggleCheckedState(row, column); + } +} + void BookmarksTagList::changeColor(int row, int /*column*/) { TagInfo::sptr info = Bookmarks::Get().findOrAddTag(item(row, 1)->text()); @@ -113,7 +117,8 @@ void BookmarksTagList::changeColor(int row, int /*column*/) return; info->color=color; - updateTags(); + item(row,0)->setBackground(color); + emit colorChanged(); Bookmarks::Get().save(); } @@ -225,7 +230,6 @@ void BookmarksTagList::ShowContextMenu(const QPoint& pos) popupMenu->popup(viewport()->mapToGlobal(pos)); } -#if 0 bool BookmarksTagList::RenameSelectedTag() { QModelIndexList selected = selectionModel()->selectedRows(); @@ -236,19 +240,24 @@ bool BookmarksTagList::RenameSelectedTag() } int iRow = selected.first().row(); - QTableWidgetItem* pItem = item(iRow,1);bUpdating + QTableWidgetItem* pItem = item(iRow,1); editItem(pItem); - //Bookmarks::Get().save(); - return true; } -#endif void BookmarksTagList::AddNewTag() { - AddTag("*new*"); - scrollToBottom(); - editItem(item(rowCount()-1, 1)); + constexpr const char * newItemName = "*new*"; + QList found = findItems(newItemName, Qt::MatchExactly); + if(found.isEmpty()) + { + m_bUpdating = true; + AddTag(newItemName); + scrollToBottom(); + m_bUpdating = false; + editItem(item(rowCount()-1, 1)); + }else + editItem(found[0]); } void BookmarksTagList::AddTag(QString name, Qt::CheckState checkstate, QColor color) @@ -258,6 +267,7 @@ void BookmarksTagList::AddTag(QString name, Qt::CheckState checkstate, QColor co // Column 1 QTableWidgetItem *item = new QTableWidgetItem(name); + item->setData(Qt::UserRole, name); item->setCheckState(checkstate); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); setItem(i, 1, item); diff --git a/src/qtgui/bookmarkstaglist.h b/src/qtgui/bookmarkstaglist.h index f7f7a06066..b94f3088fd 100644 --- a/src/qtgui/bookmarkstaglist.h +++ b/src/qtgui/bookmarkstaglist.h @@ -41,14 +41,16 @@ class BookmarksTagList : public QTableWidget bool m_bShowUntagged; QMenu* popupMenu{nullptr}; signals: + void colorChanged(); public slots: void updateTags(); void on_cellClicked(int row, int column); + void on_cellDoubleClicked(int row, int column); void changeColor(int row, int column); void toggleCheckedState(int row, int column); void ShowContextMenu(const QPoint& pos); - //bool RenameSelectedTag(); + bool RenameSelectedTag(); void AddNewTag(); void AddTag(QString name, Qt::CheckState checkstate = Qt::Checked, QColor color = TagInfo::DefaultColor); void DeleteSelectedTag(); diff --git a/src/qtgui/dockbookmarks.cpp b/src/qtgui/dockbookmarks.cpp index afa5c70af8..b378e43e95 100644 --- a/src/qtgui/dockbookmarks.cpp +++ b/src/qtgui/dockbookmarks.cpp @@ -81,6 +81,8 @@ DockBookmarks::DockBookmarks(QWidget *parent) : | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), tagsDialog, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), tagsDialog, SLOT(reject())); + connect(dialogTaglist, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(dialog_tableWidgetTagList_itemChanged(QTableWidgetItem *))); + connect(dialogTaglist, SIGNAL(colorChanged()), this, SLOT(dialog_tableWidgetTagList_colorChanged())); QVBoxLayout *mainLayout = new QVBoxLayout(tagsDialog); mainLayout->addWidget(dialogTaglist); @@ -103,7 +105,7 @@ DockBookmarks::DockBookmarks(QWidget *parent) : connect(bookmarksTableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(onDataChanged(const QModelIndex &, const QModelIndex &))); connect(&Bookmarks::Get(), SIGNAL(TagListChanged()), - ui->tableWidgetTagList, SLOT(updateTags())); + ui->tableWidgetTagList, SLOT(updateTags()), Qt::QueuedConnection); connect(&Bookmarks::Get(), SIGNAL(BookmarksChanged()), bookmarksTableModel, SLOT(update())); } @@ -161,12 +163,57 @@ void DockBookmarks::on_tableWidgetTagList_itemChanged(QTableWidgetItem *item) // we only want to react on changed by the user, not changes by the program itself. if(ui->tableWidgetTagList->m_bUpdating) return; + int col = item->column(); + if (col != 1) + return; + + QString strText = item->text().trimmed(); + QString strOld = item->data(Qt::UserRole).toString(); + bool isChecked = (item->checkState() == Qt::Checked); + if(strText != strOld) + { + if((Bookmarks::Get().getTagIndex(strText) == -1) + && (strText.compare(TagInfo::strUntagged) != 0) + && (strOld.compare(TagInfo::strUntagged) != 0) + ) + { + Bookmarks::Get().findOrAddTag(strOld)->name = strText; + Bookmarks::Get().save(); + } + } + Bookmarks::Get().setTagChecked(strText, isChecked); +} + +void DockBookmarks::dialog_tableWidgetTagList_itemChanged(QTableWidgetItem *item) +{ + // we only want to react on changed by the user, not changes by the program itself. + if(ui->tableWidgetTagList->m_bUpdating) return; + int col = item->column(); if (col != 1) return; QString strText = item->text(); - Bookmarks::Get().setTagChecked(strText, (item->checkState() == Qt::Checked)); + QString strOld = item->data(Qt::UserRole).toString(); + if(strText != strOld) + { + if((Bookmarks::Get().getTagIndex(strText) == -1) + && (strText.compare(TagInfo::strUntagged) != 0) + && (strOld.compare(TagInfo::strUntagged) != 0) + ) + { + Bookmarks::Get().findOrAddTag(strOld)->name = strText; + item->setData(Qt::UserRole, strText); + Bookmarks::Get().save(); + }else + item->setText(strOld); + updateTags(); + } +} + +void DockBookmarks::dialog_tableWidgetTagList_colorChanged() +{ + updateTags(); } bool DockBookmarks::eventFilter(QObject* object, QEvent* event) diff --git a/src/qtgui/dockbookmarks.h b/src/qtgui/dockbookmarks.h index ab63b228d1..4db6c64d74 100644 --- a/src/qtgui/dockbookmarks.h +++ b/src/qtgui/dockbookmarks.h @@ -74,6 +74,8 @@ class DockBookmarks : public QDockWidget public slots: void setNewFrequency(qint64 rx_freq); + void dialog_tableWidgetTagList_itemChanged(QTableWidgetItem *item); + void dialog_tableWidgetTagList_colorChanged(); private slots: void activated(const QModelIndex & index );