From da30a02976792a07c72e8be01aebde019a6a09d5 Mon Sep 17 00:00:00 2001 From: Arno Date: Sat, 27 Nov 2010 12:28:34 +0100 Subject: Implemented dialog for showing movies without covers Implemented a new dialog to show movies without covers. The view is a QTreeView with another model. While working on the model several shortcomings of SmTreeModel were resolved. findValue() now takes another argument to indicate the column the returned QModelIndex() should represent. Also, itemAt() was promoted from private to protected. It's quite useful for derived classes. --- archivetreeview.cpp | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) (limited to 'archivetreeview.cpp') diff --git a/archivetreeview.cpp b/archivetreeview.cpp index b00737e..3529b01 100644 --- a/archivetreeview.cpp +++ b/archivetreeview.cpp @@ -17,10 +17,25 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "archivetreeview.h" #include "smglobals.h" #include "smtreemodel.h" +#include "smtreeitem.h" #include "seriestreewidget.h" #include "filestreewidget.h" #include "filestreemodel.h" @@ -67,6 +82,11 @@ ArchiveTreeView::ArchiveTreeView(QWidget *parent) : QWidget(parent){ verticalSplitter->setStretchFactor(0, 3); verticalSplitter->setStretchFactor(1, 1); + // misc + mNoCoverDialog = new NoCoverMovieDialog(this); + mNoCoverDialog->setHidden(true); + connect(mNoCoverDialog->view(), SIGNAL(doubleClicked(QModelIndex)), this, SLOT(selectMovie(QModelIndex))); + // layout QHBoxLayout *mainLayout = new QHBoxLayout; QSplitter *splitter = new QSplitter; @@ -132,6 +152,28 @@ void ArchiveTreeView::cleanDatabase(const QString &table){ } } +void ArchiveTreeView::showNoCoverDialog(){ + mNoCoverDialog->show(); +} + +void ArchiveTreeView::selectMovie(const QModelIndex &idx){ + if(!idx.isValid()){ + return; + } + QVariant movieName = idx.data(NoCoverMovieModel::SeriesNameRole); + QVariant part = idx.data(NoCoverMovieModel::SeriesPartRole); + QModelIndex movieIdx = mSeriesModel->findValue(movieName, QModelIndex(), SeriesTreeModel::Name); + if(!movieIdx.isValid()){ + return; + } + QModelIndex partIdx = mSeriesModel->findValue(part, movieIdx, SeriesTreeModel::SeriesPart, 0); + QModelIndex toSelect = partIdx.isValid() ? mSeriesWidget->seriesProxy()->mapFromSource(partIdx) : mSeriesWidget->seriesProxy()->mapFromSource(movieIdx); + mSeriesWidget->seriesTree()->expand(mSeriesWidget->seriesProxy()->mapFromSource(movieIdx)); + mSeriesWidget->seriesTree()->selectionModel()->select(toSelect, QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + mSeriesWidget->seriesTree()->scrollTo(toSelect, QAbstractItemView::PositionAtCenter); + mNoCoverDialog->hide(); +} + void ArchiveTreeView::currentChanged(const QItemSelection &selected, const QItemSelection &deselected){ Q_UNUSED(selected); Q_UNUSED(deselected); @@ -224,3 +266,151 @@ void ArchiveTreeView::constructWindowTitle(){ mWindowTitle = QString("Movie Archive - [%1]").arg(modeString); emit needWindowTitleChange(mWindowTitle); } + +//NoCoverMovieModel + +NoCoverMovieModel::NoCoverMovieModel(const QStringList &headers, QObject *parent) : SmTreeModel(headers, parent){ + mDb = QSqlDatabase::database("treedb"); + mDataQuery = new QSqlQuery(mDb); + mDataQuery->prepare("SELECT files.iseriespart_id, series.tseries_name, seriesparts.iseriespart FROM files, series, seriesparts WHERE files.iseriespart_id = seriesparts.iseriesparts_id AND seriesparts.iseries_id = series.iseries_id GROUP BY files.iseriespart_id,series.tseries_name,seriesparts.iseriespart HAVING COUNT(iseriespart_id) = 1 ORDER BY series.tseries_name"); + refresh(); +} + +QVariant NoCoverMovieModel::data(const QModelIndex &index, int role) const{ + if(!index.isValid()){ + return QVariant(); + } + SmTreeItem *item = itemAt(index); + if(role == SeriesNameRole){ + return item->data(SeriesName); + } + if(role == SeriesPartRole){ + return item->data(SeriesPart); + } + if(role == SeriesIdRole){ + return item->data(SeriesId); + } + return SmTreeModel::data(index, role); +} void populate(); + + +void NoCoverMovieModel::refresh(){ + SmTreeItem *rootItem = new SmTreeItem(4); + mDataQuery->exec(); + while(mDataQuery->next()){ + QString displayName = QString("%1 %2").arg(mDataQuery->value(1).toString()).arg(QString::number(mDataQuery->value(2).toInt())); + QList data; + data << displayName << mDataQuery->value(1) << mDataQuery->value(2) << mDataQuery->value(0); + SmTreeItem *child = new SmTreeItem(data, rootItem); + rootItem->appendChild(child); + } + setRoot(rootItem); + emit refreshed(); +} + +Qt::ItemFlags NoCoverMovieModel::flags(const QModelIndex &index) const{ + if(!index.isValid()){ + return 0; + } + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; +} + +//NoCoverMovieView + +NoCoverMovieView::NoCoverMovieView(QWidget *parent) : QTreeView(parent) {} + +void NoCoverMovieView::contextMenuEvent(QContextMenuEvent *e){ + QMenu ctxMenu; + foreach(QAction *a, actions()){ + ctxMenu.addAction(a); + } + ctxMenu.exec(e->globalPos()); +} + +//NoCoverMovieDialog + +NoCoverMovieDialog::NoCoverMovieDialog(QWidget *parent, Qt::WindowFlags flags) : QDialog(parent, flags){ + //model + view + mView = new NoCoverMovieView; + QStringList headers = QStringList() << "Movie" << "Name" << "Part" << "Id"; + mModel = new NoCoverMovieModel(headers); + mView->setModel(mModel); + connect(mModel, SIGNAL(refreshed()), this, SLOT(updateLabel())); + mView->setColumnHidden(1, true); + mView->setColumnHidden(2, true); + mView->setColumnHidden(3, true); + mView->resizeColumnToContents(0); + + //actions + mBrowserA = new QAction(tr("Search with google..."), this); + connect(mBrowserA, SIGNAL(triggered()), this, SLOT(openInBrowser())); + mView->addAction(mBrowserA); + mCopyA = new QAction(tr("Copy name"), this); + connect(mCopyA, SIGNAL(triggered()), this, SLOT(copyToClipboard())); + mView->addAction(mCopyA); + + //buttons + QHBoxLayout *buttonLayout = new QHBoxLayout; + mClose = new QPushButton(tr("Close")); + connect(mClose, SIGNAL(clicked()), this, SLOT(hide())); + mRefresh = new QPushButton(tr("Refresh")); + connect(mRefresh, SIGNAL(clicked()), mModel, SLOT(refresh())); + buttonLayout->addWidget(mRefresh); + buttonLayout->addStretch(); + buttonLayout->addWidget(mClose); + + //label + mMovieLabel = new QLabel(labelText()); + + //main + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(mMovieLabel); + mainLayout->addWidget(mView); + mainLayout->addLayout(buttonLayout); + setLayout(mainLayout); +} + +void NoCoverMovieDialog::openInBrowser(){ + QString selText = selectedText(); + if(selText.isEmpty()){ + return; + } + selText.append(" covers"); + QByteArray searchString = QUrl::toPercentEncoding(selText); + QString url = QString("http://www.google.com/search?hl=en&q=%1").arg(QString(searchString)); + QStringList args = QStringList() << "openURL" << url; + bool success = QProcess::startDetached("kfmclient", args); + if(!success){ + QMessageBox::critical(this, tr("Error"), tr("Launching browser failed. Most likely kfmclient is not installed")); + } +} + +void NoCoverMovieDialog::copyToClipboard(){ + QString selText = selectedText(); + if(selText.isEmpty()){ + return; + } + QClipboard *clip = QApplication::clipboard(); + clip->setText(selText); +} + +void NoCoverMovieDialog::updateLabel(){ + mMovieLabel->setText(labelText()); +} + +const QString NoCoverMovieDialog::selectedText() const{ + QModelIndexList selected = mView->selectionModel()->selectedRows(); + if(selected.isEmpty()){ + return QString(); + } + QModelIndex real = mModel->index(selected.at(0).row(), 0, selected.at(0).parent()); + if(!real.isValid()){ + return QString(); + } + return real.data().toString(); +} + +const QString NoCoverMovieDialog::labelText() const{ + QString retval = QString(tr("Movies without covers (%1)")).arg(QString::number(mModel->rowCount(QModelIndex()))); + return retval; +} -- cgit v1.2.3-70-g09d2