#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "searchdialog.h" #include "searchview.h" #include "helper.h" #include "globals.h" SearchDialog::SearchDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){ //search bar QLabel *typeL = new QLabel(tr("Search by:")); mTypeSel = new QComboBox; mTypeSel->addItem(tr("Actor"), Actors); mTypeSel->addItem(tr("Filename"), Filename); mTypeSel->addItem(tr("Title"), Title); connect(mTypeSel, QOverload::of(&QComboBox::activated), this, &SearchDialog::doSearch); connect(mTypeSel, QOverload::of(&QComboBox::currentIndexChanged), this, &SearchDialog::doSearch); mSearch = new QLineEdit; QPushButton *goB = new QPushButton(tr("Go!")); connect(goB, &QPushButton::clicked, this, &SearchDialog::doSearch); QHBoxLayout *topHBL = new QHBoxLayout; topHBL->addWidget(typeL); topHBL->addWidget(mTypeSel); topHBL->addWidget(mSearch); topHBL->addWidget(goB); //result view QGroupBox *resGB = new QGroupBox(tr("Search result")); mResM = new QStandardItemModel; QSortFilterProxyModel *resMProxy = new QSortFilterProxyModel; resMProxy->setSourceModel(mResM); mResV = new SearchView; Globals::instance()->addView(mResV); mResV->setModel(resMProxy); connect(mResV->selectionModel(), &QItemSelectionModel::currentChanged, this, &SearchDialog::doResult); QHBoxLayout *resGBL = new QHBoxLayout; resGBL->addWidget(mResV); resGB->setLayout(resGBL); QGroupBox *dataGB = new QGroupBox(tr("Data")); mDataM = new QStandardItemModel; QSortFilterProxyModel *dataMProxy = new QSortFilterProxyModel; dataMProxy->setSourceModel(mDataM); mDataV = new SearchView; Globals::instance()->addView(mDataV); mDataV->setModel(dataMProxy); QHBoxLayout *dataGBL = new QHBoxLayout; dataGBL->addWidget(mDataV); dataGB->setLayout(dataGBL); QHBoxLayout *resL = new QHBoxLayout; resL->addWidget(resGB); resL->addWidget(dataGB); //hide button QPushButton *hideB = new QPushButton(tr("Close")); connect(hideB, &QPushButton::clicked, this, &SearchDialog::hide); QHBoxLayout *buttonL = new QHBoxLayout; buttonL->addStretch(); buttonL->addWidget(hideB); buttonL->addStretch(); //main layout QVBoxLayout *mainL = new QVBoxLayout; mainL->addLayout(topHBL); mainL->addLayout(resL); mainL->addLayout(buttonL); setLayout(mainL); setMinimumSize(QSize(1024, 468)); readSettings(); doSearch(); } SearchDialog::~SearchDialog(){ writeSettings(); } void SearchDialog::doSearch(){ int type = mTypeSel->currentData().toInt(); qApp->setOverrideCursor(Qt::BusyCursor); if(type == Title){ doSearchTitle(); }else if(type == Filename){ doSearchFilename(); }else if(type == Actors){ doSearchActor(); } QModelIndex first = mResV->selectionModel()->model()->index(0, 0); if(first.isValid()){ mResV->selectionModel()->setCurrentIndex(first, QItemSelectionModel::ClearAndSelect); } qApp->restoreOverrideCursor(); } void SearchDialog::doResult(const QModelIndex &cur, const QModelIndex &prev){ Q_UNUSED(prev) int type = mTypeSel->currentData().toInt(); bool restoreCursor = false; if(!qApp->overrideCursor()){ qApp->setOverrideCursor(Qt::BusyCursor); restoreCursor = true; } if(type == Title || type == Filename){ doResultName(cur, type); }else if(type == Actors){ doResultActor(cur); } if(restoreCursor){ qApp->restoreOverrideCursor(); } } void SearchDialog::doSearchTitle(){ if(mSearch->text().isEmpty()){ return; } QString title = QString(tr("%1 Search [Title: %2]")).arg(qApp->applicationName()).arg(mSearch->text()); setWindowTitle(title); mResV->setSortingEnabled(false); mResM->clear(); mResM->setColumnCount(1); mResM->setHeaderData(0, Qt::Horizontal, tr("Title")); QIcon icon = Helper::icon(QColor(255,85,255), QChar(0x26A7)); QStandardItem *root = mResM->invisibleRootItem(); QSqlDatabase db = QSqlDatabase::database("shemovdb"); QSqlQuery tQ(db); tQ.prepare("SELECT DISTINCT(iseries_id), tseries_name FROM series WHERE tseries_name ~ :title ORDER BY tseries_name"); tQ.bindValue(":title", mSearch->text()); tQ.exec(); while(tQ.next()){ QStandardItem *cur = new QStandardItem(tQ.value(1).toString()); cur->setIcon(icon); cur->setData(tQ.value(0), IdRole); cur->setEditable(false); root->appendRow(cur); } mResV->setSortingEnabled(true); } void SearchDialog::doSearchFilename(){ if(mSearch->text().isEmpty()){ return; } QString title = QString(tr("%1 Search [Filename: %2]")).arg(qApp->applicationName()).arg(mSearch->text()); setWindowTitle(title); mResV->setSortingEnabled(false); mResM->clear(); mResM->setColumnCount(1); mResM->setHeaderData(0, Qt::Horizontal, tr("Filename")); QIcon fnIcon = Helper::icon(QColor(255,85,255), QChar(0x26A6)); QIcon oIcon = Helper::icon(QColor(255,85,255), QChar(0x26A5)); QStandardItem *root = mResM->invisibleRootItem(); QSqlDatabase db = QSqlDatabase::database("shemovdb"); QSqlQuery fnQ(db); fnQ.prepare("SELECT tfilename, iseriespart_id FROM files WHERE tfilename ~ :fn ORDER BY tfilename"); fnQ.bindValue(":fn", mSearch->text()); fnQ.exec(); while(fnQ.next()){ QStandardItem *cur = new QStandardItem(fnQ.value(0).toString()); cur->setIcon(fnIcon); cur->setData(fnQ.value(1), IdRole); cur->setEditable(false); root->appendRow(cur); } QSqlQuery oQ(db); oQ.prepare("SELECT tname, iseriespart_id FROM files, files_origin WHERE tname ~ :fn AND files_origin.ifiles_id = files.ifiles_id ORDER BY tname"); oQ.bindValue(":fn", mSearch->text()); oQ.exec(); while(oQ.next()){ QStandardItem *cur = new QStandardItem(oQ.value(0).toString()); cur->setIcon(oIcon); cur->setData(oQ.value(1), IdRole); cur->setEditable(false); root->appendRow(cur); } mResV->setSortingEnabled(true); mResV->sortByColumn(0); } void SearchDialog::doSearchActor(){ if(mSearch->text().isEmpty()){ return; } QString title = QString(tr("%1 Search [Actor: %2]")).arg(qApp->applicationName()).arg(mSearch->text()); setWindowTitle(title); mResV->setSortingEnabled(false); mResM->clear(); mResM->setColumnCount(1); mResM->setHeaderData(0, Qt::Horizontal, tr("Title")); QIcon icon = Helper::icon(QColor(255,85,255), QChar(0x26A8)); QStandardItem *root = mResM->invisibleRootItem(); QSqlDatabase db = QSqlDatabase::database("shemovdb"); QSqlQuery aQ(db); aQ.prepare("SELECT tactorname, iactors_id FROM actors WHERE tactorname ~ :name ORDER BY tactorname"); aQ.bindValue(":name", mSearch->text()); aQ.exec(); while(aQ.next()){ QStandardItem *cur = new QStandardItem(aQ.value(0).toString()); cur->setIcon(icon); cur->setData(aQ.value(1), IdRole); cur->setEditable(false); doActorGenres(cur); root->appendRow(cur); } mResV->setSortingEnabled(true); mResV->sortByColumn(0); } void SearchDialog::doResultName(const QModelIndex &sel, int resType){ int seriesId = sel.data(IdRole).toInt(); QSqlDatabase db = QSqlDatabase::database("shemovdb"); QSqlQuery rQ(db); mDataM->clear(); mDataM->setColumnCount(1); QIcon icon = Helper::icon(QColor(255,85,255), QChar(0x26A5)); QStandardItem *root = mDataM->invisibleRootItem(); if(resType == Title){ rQ.prepare("SELECT series.tseries_name, seriesparts.iseriespart, seriesparts.iseriesparts_id, seriesparts.tsubtitle FROM series, seriesparts WHERE series.iseries_id = :id AND seriesparts.iseries_id = series.iseries_id"); mDataM->setHeaderData(0, Qt::Horizontal, tr("Parts")); }else if(resType == Filename){ rQ.prepare("SELECT series.tseries_name, seriesparts.iseriespart, seriesparts.iseriesparts_id, seriesparts.tsubtitle FROM series, seriesparts WHERE seriesparts.iseriesparts_id = :id AND seriesparts.iseries_id = series.iseries_id"); mDataM->setHeaderData(0, Qt::Horizontal, tr("Series")); } rQ.bindValue(":id", seriesId); rQ.exec(); while(rQ.next()){ int sPart = rQ.value(1).toInt(); QString curDisp; if(sPart > 0){ curDisp = QString("%1 %2").arg(rQ.value(0).toString()).arg(sPart, 3, 10, QChar('0')); }else{ QString sub = rQ.value(3).toString(); if(sub.isEmpty()){ curDisp = QString("%1 - ").arg(rQ.value(0).toString()); }else{ curDisp = QString("%1 - %2").arg(rQ.value(0).toString()).arg(sub); } } QStandardItem *cur = new QStandardItem(curDisp); cur->setIcon(icon); cur->setData(rQ.value(2), IdRole); cur->setEditable(false); doChild(cur, Actor); doChild(cur, Genre); root->appendRow(cur); } mDataV->setSortingEnabled(true); mDataV->sortByColumn(0); } void SearchDialog::doResultActor(const QModelIndex &sel){ mDataM->clear(); mDataM->setColumnCount(1); mDataM->setHeaderData(0, Qt::Horizontal, tr("Series")); QIcon icon = Helper::icon(QColor(255,85,255), QChar(0x26A8)); QVector seriesParts; QStandardItem *root = mDataM->invisibleRootItem(); QSqlDatabase db = QSqlDatabase::database("shemovdb"); QSqlQuery r1Q(db); r1Q.prepare("SELECT DISTINCT(seriesparts.iseriesparts_id) FROM seriesparts_actormap, seriesparts WHERE seriesparts_actormap.iactors_id = :id AND seriesparts_actormap.iseriesparts_id = seriesparts.iseriesparts_id"); r1Q.bindValue(":id", sel.data(IdRole)); r1Q.exec(); while(r1Q.next()){ seriesParts << r1Q.value(0).toInt(); } QSqlQuery r2Q(db); r2Q.prepare("SELECT series.tseries_name, seriesparts.iseriespart, seriesparts.iseriesparts_id, seriesparts.tsubtitle FROM series, seriesparts WHERE seriesparts.iseriesparts_id = :id AND seriesparts.iseries_id = series.iseries_id"); for(int sp : seriesParts){ r2Q.bindValue(":id", sp); r2Q.exec(); while(r2Q.next()){ int sPart = r2Q.value(1).toInt(); QString curDisp; if(sPart > 0){ curDisp = QString("%1 %2").arg(r2Q.value(0).toString()).arg(sPart, 3, 10, QChar('0')); }else{ QString sub = r2Q.value(3).toString(); if(sub.isEmpty()){ curDisp = QString("%1 - ").arg(r2Q.value(0).toString()); }else{ curDisp = QString("%1 - %2").arg(r2Q.value(0).toString()).arg(sub); } } QStandardItem *cur = new QStandardItem(curDisp); cur->setIcon(icon); cur->setData(r2Q.value(2), IdRole); cur->setEditable(false); QSqlQuery fQ(db); fQ.prepare("SELECT tfilename FROM files WHERE iseriespart_id = :fid"); fQ.bindValue(":fid", r2Q.value(2)); fQ.exec(); while(fQ.next()){ QStandardItem *curf = new QStandardItem(fQ.value(0).toString()); curf->setIcon(icon); curf->setEditable(false); cur->appendRow(curf); } root->appendRow(cur); } mDataV->setSortingEnabled(true); mDataV->sortByColumn(0); } } void SearchDialog::writeSettings(){ QSettings s; s.setValue("searchby", mTypeSel->currentText()); s.setValue("searchvalue", mSearch->text()); } void SearchDialog::readSettings(){ QSettings s; QString val = s.value("searchvalue").toString(); mSearch->setText(val); QString type = s.value("searchby").toString(); int tIdx = mTypeSel->findText(type); if(tIdx > -1){ mTypeSel->setCurrentIndex(tIdx); } } void SearchDialog::keyPressEvent(QKeyEvent *e){ if(e->key() == Qt::Key_X && (e->modifiers() & Qt::ControlModifier)){ hide(); goto exit; } if(e->key() == Qt::Key_L && (e->modifiers() & Qt::ControlModifier)){ mSearch->selectAll(); mSearch->setFocus(); goto exit; } if(e->key() == Qt::Key_M && (e->modifiers() & Qt::ControlModifier)){ mTypeSel->setCurrentIndex(0); goto exit; } if(e->key() == Qt::Key_F && (e->modifiers() & Qt::ControlModifier)){ mTypeSel->setCurrentIndex(1); goto exit; } if(e->key() == Qt::Key_T && (e->modifiers() & Qt::ControlModifier)){ mTypeSel->setCurrentIndex(2); goto exit; } return QDialog::keyPressEvent(e); exit: e->accept(); } void SearchDialog::doChild(QStandardItem *item, int childMode){ QStringList res; QIcon aIcon; QString parentName; QSqlDatabase db = QSqlDatabase::database("shemovdb"); QSqlQuery rQ(db); if(childMode == Actor){ rQ.prepare("SELECT actors.tactorname FROM seriesparts_actormap, actors WHERE seriesparts_actormap.iseriesparts_id = :id and seriesparts_actormap.iactors_id = actors.iactors_id ORDER by tactorname"); parentName = tr("actors"); aIcon = Helper::icon(QColor(255,85,255), 'A'); }else if(childMode == Genre){ rQ.prepare("SELECT genres.tgenrename FROM seriesparts_genremap, genres WHERE seriesparts_genremap.iseriesparts_id = :id and seriesparts_genremap.igenres_id = genres.igenres_id ORDER by tgenrename"); parentName = tr("genres"); aIcon = Helper::icon(QColor(255,85,255), 'G'); } rQ.bindValue(":id", item->data(IdRole)); rQ.exec(); while(rQ.next()){ res << rQ.value(0).toString(); } if(!res.isEmpty()){ QStandardItem *aItem = new QStandardItem(parentName); aItem->setEditable(false); aItem->setIcon(aIcon); for(QString a : res){ QStandardItem *curItem = new QStandardItem(a); curItem->setIcon(aIcon); curItem->setEditable(false); aItem->appendRow(curItem); } item->appendRow(aItem); } } void SearchDialog::doActorGenres(QStandardItem *item){ QStringList res; QIcon aIcon = Helper::icon(QColor(255,85,255), QChar(0x26A6)); QSqlDatabase db = QSqlDatabase::database("shemovdb"); QSqlQuery aQ(db); aQ.prepare("SELECT DISTINCT(genres.tgenrename) FROM genres, seriesparts, seriesparts_actormap, seriesparts_genremap WHERE seriesparts_actormap.iseriesparts_id = seriesparts.iseriesparts_id AND seriesparts.iseriesparts_id = seriesparts_genremap.iseriesparts_id AND seriesparts_genremap.igenres_id = genres.igenres_id AND seriesparts_actormap.iactors_id = :id ORDER BY genres.tgenrename"); aQ.bindValue(":id", item->data(IdRole)); aQ.exec(); while(aQ.next()){ res << aQ.value(0).toString(); } if(!res.isEmpty()){ std::sort(res.begin(), res.end()); for(QString s : res){ QStandardItem *cur = new QStandardItem(s); cur->setIcon(aIcon); cur->setEditable(false); cur->setData(item->data(IdRole), IdRole); item->appendRow(cur); } } }