comparison src/gui/pages/search.cc @ 370:ea3a74ed2ef9

*: hm, last commit wasn't quite finished?
author Paper <paper@tflc.us>
date Fri, 25 Jul 2025 10:22:04 -0400
parents 8d45d892be88
children
comparison
equal deleted inserted replaced
369:47c9f8502269 370:ea3a74ed2ef9
21 #include <algorithm> 21 #include <algorithm>
22 #include <fstream> 22 #include <fstream>
23 #include <iostream> 23 #include <iostream>
24 #include <sstream> 24 #include <sstream>
25 25
26 SearchPageSearchThread::SearchPageSearchThread(QObject* parent) : QThread(parent) { 26 SearchPageSearchThread::SearchPageSearchThread(QObject *parent) : QThread(parent)
27 } 27 {
28 28 }
29 void SearchPageSearchThread::SetSearch(const std::string& search) { 29
30 void SearchPageSearchThread::SetSearch(const std::string &search)
31 {
30 search_ = search; 32 search_ = search;
31 } 33 }
32 34
33 void SearchPageSearchThread::run() { 35 void SearchPageSearchThread::run()
36 {
34 emit GotResults(Services::Search(search_)); 37 emit GotResults(Services::Search(search_));
35 } 38 }
36 39
37 SearchPageListSortFilter::SearchPageListSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { 40 SearchPageListSortFilter::SearchPageListSortFilter(QObject *parent) : QSortFilterProxyModel(parent)
38 } 41 {
39 42 }
40 bool SearchPageListSortFilter::lessThan(const QModelIndex& l, const QModelIndex& r) const { 43
44 bool SearchPageListSortFilter::lessThan(const QModelIndex &l, const QModelIndex &r) const
45 {
41 QVariant left = sourceModel()->data(l, sortRole()); 46 QVariant left = sourceModel()->data(l, sortRole());
42 QVariant right = sourceModel()->data(r, sortRole()); 47 QVariant right = sourceModel()->data(r, sortRole());
43 48
44 switch (left.userType()) { 49 switch (left.userType()) {
45 case QMetaType::Int: 50 case QMetaType::Int:
53 } 58 }
54 } 59 }
55 60
56 /* -------------------------------------------- */ 61 /* -------------------------------------------- */
57 62
58 SearchPageListModel::SearchPageListModel(QObject* parent) : QAbstractListModel(parent) { 63 SearchPageListModel::SearchPageListModel(QObject *parent) : QAbstractListModel(parent)
59 } 64 {
60 65 }
61 void SearchPageListModel::ParseSearch(const std::vector<int>& ids) { 66
67 void SearchPageListModel::ParseSearch(const std::vector<int> &ids)
68 {
62 /* hack!!! */ 69 /* hack!!! */
63 if (!rowCount(index(0))) { 70 if (!rowCount(index(0))) {
64 beginInsertRows(QModelIndex(), 0, 0); 71 beginInsertRows(QModelIndex(), 0, 0);
65 endInsertRows(); 72 endInsertRows();
66 } 73 }
70 this->ids = ids; 77 this->ids = ids;
71 78
72 endResetModel(); 79 endResetModel();
73 } 80 }
74 81
75 int SearchPageListModel::rowCount(const QModelIndex& parent) const { 82 int SearchPageListModel::rowCount(const QModelIndex &parent) const
83 {
76 return ids.size(); 84 return ids.size();
77 (void)(parent); 85 (void)(parent);
78 } 86 }
79 87
80 int SearchPageListModel::columnCount(const QModelIndex& parent) const { 88 int SearchPageListModel::columnCount(const QModelIndex &parent) const
89 {
81 return NB_COLUMNS; 90 return NB_COLUMNS;
82 (void)(parent); 91 (void)(parent);
83 } 92 }
84 93
85 QVariant SearchPageListModel::headerData(const int section, const Qt::Orientation orientation, const int role) const { 94 QVariant SearchPageListModel::headerData(const int section, const Qt::Orientation orientation, const int role) const
95 {
86 switch (role) { 96 switch (role) {
87 case Qt::DisplayRole: { 97 case Qt::DisplayRole: {
88 switch (section) { 98 switch (section) {
89 case SR_TITLE: return tr("Anime title"); 99 case SR_TITLE: return tr("Anime title");
90 case SR_EPISODES: return tr("Episode"); 100 case SR_EPISODES: return tr("Episode");
108 } 118 }
109 } 119 }
110 return QAbstractListModel::headerData(section, orientation, role); 120 return QAbstractListModel::headerData(section, orientation, role);
111 } 121 }
112 122
113 QVariant SearchPageListModel::data(const QModelIndex& index, int role) const { 123 QVariant SearchPageListModel::data(const QModelIndex &index, int role) const
124 {
114 if (!index.isValid()) 125 if (!index.isValid())
115 return QVariant(); 126 return QVariant();
116 127
117 const Anime::Anime& anime = Anime::db.items[ids[index.row()]]; 128 const Anime::Anime &anime = Anime::db.items[ids[index.row()]];
118 129
119 switch (role) { 130 switch (role) {
120 case Qt::DisplayRole: 131 case Qt::DisplayRole:
121 switch (index.column()) { 132 switch (index.column()) {
122 case SR_TITLE: return Strings::ToQString(anime.GetUserPreferredTitle()); 133 case SR_TITLE: return Strings::ToQString(anime.GetUserPreferredTitle());
153 case Qt::TextAlignmentRole: return headerData(index.column(), Qt::Horizontal, Qt::TextAlignmentRole); 164 case Qt::TextAlignmentRole: return headerData(index.column(), Qt::Horizontal, Qt::TextAlignmentRole);
154 } 165 }
155 return QVariant(); 166 return QVariant();
156 } 167 }
157 168
158 Qt::ItemFlags SearchPageListModel::flags(const QModelIndex& index) const { 169 Qt::ItemFlags SearchPageListModel::flags(const QModelIndex &index) const
170 {
159 if (!index.isValid()) 171 if (!index.isValid())
160 return Qt::NoItemFlags; 172 return Qt::NoItemFlags;
161 173
162 return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 174 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
163 } 175 }
164 176
165 Anime::Anime* SearchPageListModel::GetAnimeFromIndex(const QModelIndex& index) const { 177 Anime::Anime *SearchPageListModel::GetAnimeFromIndex(const QModelIndex &index) const
178 {
166 return &Anime::db.items[ids[index.row()]]; 179 return &Anime::db.items[ids[index.row()]];
167 } 180 }
168 181
169 void SearchPage::DisplayListMenu() { 182 void SearchPage::DisplayListMenu()
170 QMenu* menu = new QMenu(this); 183 {
184 QMenu *menu = new QMenu(this);
171 menu->setAttribute(Qt::WA_DeleteOnClose); 185 menu->setAttribute(Qt::WA_DeleteOnClose);
172 menu->setToolTipsVisible(true); 186 menu->setToolTipsVisible(true);
173 187
174 const QItemSelection selection = sort_model->mapSelectionToSource(treeview->selectionModel()->selection()); 188 const QItemSelection selection = sort_model->mapSelectionToSource(treeview->selectionModel()->selection());
175 189
176 bool add_to_list_enable = true; 190 bool add_to_list_enable = true;
177 191
178 std::set<Anime::Anime*> animes; 192 std::set<Anime::Anime *> animes;
179 for (const auto& index : selection.indexes()) { 193 for (const auto &index : selection.indexes()) {
180 if (!index.isValid()) 194 if (!index.isValid())
181 continue; 195 continue;
182 196
183 Anime::Anime* anime = model->GetAnimeFromIndex(index); 197 Anime::Anime *anime = model->GetAnimeFromIndex(index);
184 if (anime) { 198 if (anime) {
185 animes.insert(anime); 199 animes.insert(anime);
186 if (anime->IsInUserList()) 200 if (anime->IsInUserList())
187 add_to_list_enable = false; 201 add_to_list_enable = false;
188 } 202 }
189 } 203 }
190 204
191 menu->addAction(tr("Information"), [this, animes] { 205 menu->addAction(tr("Information"), [this, animes] {
192 for (auto& anime : animes) { 206 for (auto &anime : animes) {
193 InformationDialog* dialog = new InformationDialog( 207 InformationDialog *dialog = new InformationDialog(
194 anime, 208 anime,
195 [this](Anime::Anime* anime) { 209 [this](Anime::Anime *anime) {
196 // UpdateAnime(anime->GetId()); 210 // UpdateAnime(anime->GetId());
197 }, 211 },
198 InformationDialog::PAGE_MAIN_INFO, this); 212 InformationDialog::PAGE_MAIN_INFO, this);
199 213
200 dialog->show(); 214 dialog->show();
202 dialog->activateWindow(); 216 dialog->activateWindow();
203 } 217 }
204 }); 218 });
205 menu->addSeparator(); 219 menu->addSeparator();
206 { 220 {
207 QMenu* submenu = menu->addMenu(tr("Add to list...")); 221 QMenu *submenu = menu->addMenu(tr("Add to list..."));
208 for (const auto& status : Anime::ListStatuses) { 222 for (const auto &status : Anime::ListStatuses) {
209 submenu->addAction(Strings::ToQString(Translate::ToLocalString(status)), [animes, status] { 223 submenu->addAction(Strings::ToQString(Translate::ToLocalString(status)), [animes, status] {
210 for (auto& anime : animes) { 224 for (auto &anime : animes) {
211 if (!anime->IsInUserList()) 225 if (!anime->IsInUserList())
212 anime->AddToUserList(); 226 anime->AddToUserList();
213 anime->SetUserStatus(status); 227 anime->SetUserStatus(status);
214 Services::UpdateAnimeEntry(anime->GetId()); 228 Services::UpdateAnimeEntry(anime->GetId());
215 } 229 }
218 submenu->setEnabled(add_to_list_enable); 232 submenu->setEnabled(add_to_list_enable);
219 } 233 }
220 menu->popup(QCursor::pos()); 234 menu->popup(QCursor::pos());
221 } 235 }
222 236
223 void SearchPage::ItemDoubleClicked() { 237 void SearchPage::ItemDoubleClicked()
238 {
224 /* throw out any other garbage */ 239 /* throw out any other garbage */
225 const QItemSelection selection = sort_model->mapSelectionToSource(treeview->selectionModel()->selection()); 240 const QItemSelection selection = sort_model->mapSelectionToSource(treeview->selectionModel()->selection());
226 if (!selection.indexes().first().isValid()) 241 if (!selection.indexes().first().isValid())
227 return; 242 return;
228 243
229 const QModelIndex index = model->index(selection.indexes().first().row()); 244 const QModelIndex index = model->index(selection.indexes().first().row());
230 Anime::Anime* anime = model->GetAnimeFromIndex(index); 245 Anime::Anime *anime = model->GetAnimeFromIndex(index);
231 246
232 InformationDialog* dialog = new InformationDialog( 247 InformationDialog *dialog = new InformationDialog(
233 anime, 248 anime,
234 [this](Anime::Anime* anime) { 249 [this](Anime::Anime *anime) {
235 // UpdateAnime(anime->GetId()); 250 // UpdateAnime(anime->GetId());
236 }, 251 },
237 InformationDialog::PAGE_MAIN_INFO, this); 252 InformationDialog::PAGE_MAIN_INFO, this);
238 253
239 dialog->show(); 254 dialog->show();
240 dialog->raise(); 255 dialog->raise();
241 dialog->activateWindow(); 256 dialog->activateWindow();
242 } 257 }
243 258
244 SearchPage::SearchPage(QWidget* parent) : QFrame(parent) { 259 SearchPage::SearchPage(QWidget *parent) : QFrame(parent)
260 {
245 setFrameShape(QFrame::Box); 261 setFrameShape(QFrame::Box);
246 setFrameShadow(QFrame::Sunken); 262 setFrameShadow(QFrame::Sunken);
247 263
248 QVBoxLayout* layout = new QVBoxLayout(this); 264 QVBoxLayout *layout = new QVBoxLayout(this);
249 layout->setContentsMargins(0, 0, 0, 0); 265 layout->setContentsMargins(0, 0, 0, 0);
250 layout->setSpacing(0); 266 layout->setSpacing(0);
251 267
252 { 268 {
253 /* Toolbar */ 269 /* Toolbar */
254 QToolBar* toolbar = new QToolBar(this); 270 QToolBar *toolbar = new QToolBar(this);
255 toolbar->setMovable(false); 271 toolbar->setMovable(false);
256 272
257 { 273 {
258 QLineEdit* line_edit = new QLineEdit("", toolbar); 274 QLineEdit *line_edit = new QLineEdit("", toolbar);
259 connect(line_edit, &QLineEdit::returnPressed, this, [this, line_edit] { 275 connect(line_edit, &QLineEdit::returnPressed, this, [this, line_edit] {
260 /* static thread here. */ 276 /* static thread here. */
261 if (thread_.isRunning()) 277 if (thread_.isRunning())
262 thread_.exit(1); /* fail */ 278 thread_.exit(1); /* fail */
263 279
264 thread_.SetSearch(Strings::ToUtf8String(line_edit->text())); 280 thread_.SetSearch(Strings::ToUtf8String(line_edit->text()));
265 281
266 thread_.start(); 282 thread_.start();
267 }); 283 });
268 connect(&thread_, &SearchPageSearchThread::GotResults, this, [this](const std::vector<int>& search) { 284 connect(&thread_, &SearchPageSearchThread::GotResults, this,
269 model->ParseSearch(search); 285 [this](const std::vector<int> &search) { model->ParseSearch(search); });
270 });
271 toolbar->addWidget(line_edit); 286 toolbar->addWidget(line_edit);
272 } 287 }
273 288
274 layout->addWidget(toolbar); 289 layout->addWidget(toolbar);
275 } 290 }
276 291
277 { 292 {
278 QFrame* line = new QFrame(this); 293 QFrame *line = new QFrame(this);
279 line->setFrameShape(QFrame::HLine); 294 line->setFrameShape(QFrame::HLine);
280 line->setFrameShadow(QFrame::Sunken); 295 line->setFrameShadow(QFrame::Sunken);
281 line->setLineWidth(1); 296 line->setLineWidth(1);
282 layout->addWidget(line); 297 layout->addWidget(line);
283 } 298 }