1 /* -*- c++ -*- */
2 /*
3 * Gqrx SDR: Software defined radio receiver powered by GNU Radio and Qt
4 * https://gqrx.dk/
5 *
6 * Copyright 2013 Christian Lindner DL2VCL, Stefano Leucci.
7 *
8 * Gqrx is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3, or (at your option)
11 * any later version.
12 *
13 * Gqrx is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Gqrx; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street,
21 * Boston, MA 02110-1301, USA.
22 */
23 #include <cmath>
24 #include <cstdlib>
25 #include <QComboBox>
26 #include <QDialogButtonBox>
27 #include <QDir>
28 #include <QInputDialog>
29 #include <QMenu>
30 #include <QMessageBox>
31
32 #include "bookmarks.h"
33 #include "bookmarkstaglist.h"
34 #include "dockbookmarks.h"
35 #include "dockrxopt.h"
36 #include "qtcolorpicker.h"
37 #include "ui_dockbookmarks.h"
38
DockBookmarks(QWidget * parent)39 DockBookmarks::DockBookmarks(QWidget *parent) :
40 QDockWidget(parent),
41 ui(new Ui::DockBookmarks)
42 {
43 ui->setupUi(this);
44
45 bookmarksTableModel = new BookmarksTableModel();
46
47 // Frequency List
48 ui->tableViewFrequencyList->setModel(bookmarksTableModel);
49 ui->tableViewFrequencyList->setColumnWidth(BookmarksTableModel::COL_NAME,
50 ui->tableViewFrequencyList->columnWidth(BookmarksTableModel::COL_NAME) * 2);
51 ui->tableViewFrequencyList->setSelectionBehavior(QAbstractItemView::SelectRows);
52 ui->tableViewFrequencyList->setSelectionMode(QAbstractItemView::SingleSelection);
53 ui->tableViewFrequencyList->installEventFilter(this);
54
55 // Demod Selection in Frequency List Table.
56 ComboBoxDelegateModulation* delegateModulation = new ComboBoxDelegateModulation(this);
57 ui->tableViewFrequencyList->setItemDelegateForColumn(2, delegateModulation);
58
59 // Bookmarks Context menu
60 contextmenu = new QMenu(this);
61 // MenuItem Delete
62 {
63 QAction* action = new QAction("Delete Bookmark", this);
64 contextmenu->addAction(action);
65 connect(action, SIGNAL(triggered()), this, SLOT(DeleteSelectedBookmark()));
66 }
67 // MenuItem Add
68 {
69 actionAddBookmark = new QAction("Add Bookmark", this);
70 contextmenu->addAction(actionAddBookmark);
71 }
72 ui->tableViewFrequencyList->setContextMenuPolicy(Qt::CustomContextMenu);
73 connect(ui->tableViewFrequencyList, SIGNAL(customContextMenuRequested(const QPoint&)),
74 this, SLOT(ShowContextMenu(const QPoint&)));
75
76 // Update GUI
77 Bookmarks::Get().load();
78 bookmarksTableModel->update();
79
80 m_currentFrequency = 0;
81 m_updating = false;
82
83 // TagList
84 updateTags();
85
86 connect(ui->tableViewFrequencyList, SIGNAL(activated(const QModelIndex &)),
87 this, SLOT(activated(const QModelIndex &)));
88 connect(ui->tableViewFrequencyList, SIGNAL(doubleClicked(const QModelIndex &)),
89 this, SLOT(doubleClicked(const QModelIndex &)));
90 connect(bookmarksTableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
91 this, SLOT(onDataChanged(const QModelIndex &, const QModelIndex &)));
92 connect(&Bookmarks::Get(), SIGNAL(TagListChanged()),
93 ui->tableWidgetTagList, SLOT(updateTags()));
94 connect(&Bookmarks::Get(), SIGNAL(BookmarksChanged()),
95 bookmarksTableModel, SLOT(update()));
96 }
97
~DockBookmarks()98 DockBookmarks::~DockBookmarks()
99 {
100 delete ui;
101 delete bookmarksTableModel;
102 }
103
activated(const QModelIndex & index)104 void DockBookmarks::activated(const QModelIndex & index)
105 {
106 BookmarkInfo *info = bookmarksTableModel->getBookmarkAtRow(index.row());
107 emit newBookmarkActivated(info->frequency, info->modulation, info->bandwidth);
108 }
109
setNewFrequency(qint64 rx_freq)110 void DockBookmarks::setNewFrequency(qint64 rx_freq)
111 {
112 ui->tableViewFrequencyList->clearSelection();
113 const int iRowCount = bookmarksTableModel->rowCount();
114 for (int row = 0; row < iRowCount; ++row)
115 {
116 BookmarkInfo& info = *(bookmarksTableModel->getBookmarkAtRow(row));
117 if (std::abs(rx_freq - info.frequency) <= ((info.bandwidth / 2 ) + 1))
118 {
119 ui->tableViewFrequencyList->selectRow(row);
120 ui->tableViewFrequencyList->scrollTo(ui->tableViewFrequencyList->currentIndex(), QAbstractItemView::EnsureVisible );
121 break;
122 }
123 }
124 m_currentFrequency = rx_freq;
125 }
126
updateTags()127 void DockBookmarks::updateTags()
128 {
129 m_updating = true;
130 ui->tableWidgetTagList->updateTags();
131 m_updating = false;
132 }
133
updateBookmarks()134 void DockBookmarks::updateBookmarks()
135 {
136 bookmarksTableModel->update();
137 }
138
139 //Data has been edited
onDataChanged(const QModelIndex &,const QModelIndex &)140 void DockBookmarks::onDataChanged(const QModelIndex&, const QModelIndex &)
141 {
142 updateTags();
143 Bookmarks::Get().save();
144 }
145
on_tableWidgetTagList_itemChanged(QTableWidgetItem * item)146 void DockBookmarks::on_tableWidgetTagList_itemChanged(QTableWidgetItem *item)
147 {
148 // we only want to react on changed by the user, not changes by the program itself.
149 if(ui->tableWidgetTagList->m_bUpdating) return;
150
151 int col = item->column();
152 if (col != 1)
153 return;
154
155 QString strText = item->text();
156 Bookmarks::Get().setTagChecked(strText, (item->checkState() == Qt::Checked));
157 }
158
eventFilter(QObject * object,QEvent * event)159 bool DockBookmarks::eventFilter(QObject* object, QEvent* event)
160 {
161 if (event->type() == QEvent::KeyPress)
162 {
163 QKeyEvent* pKeyEvent = static_cast<QKeyEvent *>(event);
164 if (pKeyEvent->key() == Qt::Key_Delete && ui->tableViewFrequencyList->hasFocus())
165 {
166 return DeleteSelectedBookmark();
167 }
168 }
169 return QWidget::eventFilter(object, event);
170 }
171
DeleteSelectedBookmark()172 bool DockBookmarks::DeleteSelectedBookmark()
173 {
174 QModelIndexList selected = ui->tableViewFrequencyList->selectionModel()->selectedRows();
175
176 if (selected.empty())
177 {
178 return true;
179 }
180
181 if (QMessageBox::question(this, "Delete bookmark", "Really delete?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
182 {
183 int iIndex = bookmarksTableModel->GetBookmarksIndexForRow(selected.first().row());
184 Bookmarks::Get().remove(iIndex);
185 bookmarksTableModel->update();
186 }
187 return true;
188 }
189
ShowContextMenu(const QPoint & pos)190 void DockBookmarks::ShowContextMenu(const QPoint& pos)
191 {
192 contextmenu->popup(ui->tableViewFrequencyList->viewport()->mapToGlobal(pos));
193 }
194
doubleClicked(const QModelIndex & index)195 void DockBookmarks::doubleClicked(const QModelIndex & index)
196 {
197 if(index.column() == BookmarksTableModel::COL_TAGS)
198 {
199 changeBookmarkTags(index.row(), index.column());
200 }
201 }
202
ComboBoxDelegateModulation(QObject * parent)203 ComboBoxDelegateModulation::ComboBoxDelegateModulation(QObject *parent)
204 :QItemDelegate(parent)
205 {
206 }
207
createEditor(QWidget * parent,const QStyleOptionViewItem &,const QModelIndex & index) const208 QWidget *ComboBoxDelegateModulation::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &index) const
209 {
210 QComboBox* comboBox = new QComboBox(parent);
211 for (int i = 0; i < DockRxOpt::ModulationStrings.size(); ++i)
212 {
213 comboBox->addItem(DockRxOpt::ModulationStrings[i]);
214 }
215 setEditorData(comboBox, index);
216 return comboBox;
217 }
218
setEditorData(QWidget * editor,const QModelIndex & index) const219 void ComboBoxDelegateModulation::setEditorData(QWidget *editor, const QModelIndex &index) const
220 {
221 QComboBox *comboBox = static_cast<QComboBox*>(editor);
222 QString value = index.model()->data(index, Qt::EditRole).toString();
223 int iModulation = DockRxOpt::GetEnumForModulationString(value);
224 comboBox->setCurrentIndex(iModulation);
225 }
226
setModelData(QWidget * editor,QAbstractItemModel * model,const QModelIndex & index) const227 void ComboBoxDelegateModulation::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
228 {
229 QComboBox *comboBox = static_cast<QComboBox*>(editor);
230 model->setData(index, comboBox->currentText(), Qt::EditRole);
231 }
232
changeBookmarkTags(int row,int)233 void DockBookmarks::changeBookmarkTags(int row, int /*column*/)
234 {
235 bool ok = false;
236 QString tags; // list of tags separated by comma
237
238 int iIdx = bookmarksTableModel->GetBookmarksIndexForRow(row);
239 BookmarkInfo& bmi = Bookmarks::Get().getBookmark(iIdx);
240
241 // Create and show the Dialog for a new Bookmark.
242 // Write the result into variable 'tags'.
243 {
244 QDialog dialog(this);
245 dialog.setWindowTitle("Change Bookmark Tags");
246
247 BookmarksTagList* taglist = new BookmarksTagList(&dialog, false);
248 taglist->updateTags();
249 taglist->setSelectedTags(bmi.tags);
250 taglist->DeleteTag(TagInfo::strUntagged);
251
252 QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
253 | QDialogButtonBox::Cancel);
254 connect(buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
255 connect(buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
256
257 QVBoxLayout *mainLayout = new QVBoxLayout(&dialog);
258 mainLayout->addWidget(taglist);
259 mainLayout->addWidget(buttonBox);
260
261 ok = dialog.exec();
262 if (ok)
263 {
264 tags = taglist->getSelectedTagsAsString();
265 // list of selected tags is now in string 'tags'.
266
267 // Change Tags of Bookmark
268 QStringList listTags = tags.split(",",QString::SkipEmptyParts);
269 bmi.tags.clear();
270 if (listTags.size() == 0)
271 {
272 bmi.tags.append(&Bookmarks::Get().findOrAddTag("")); // "Untagged"
273 }
274 for (int i = 0; i < listTags.size(); ++i)
275 {
276 bmi.tags.append(&Bookmarks::Get().findOrAddTag(listTags[i]));
277 }
278 Bookmarks::Get().save();
279 }
280 }
281 }
282