summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--archivetreeview.cpp190
-rw-r--r--archivetreeview.h68
-rw-r--r--seriestreemodel.cpp10
-rw-r--r--seriestreemodel.h2
-rw-r--r--shemov.cpp6
-rw-r--r--shemov.h1
-rw-r--r--shemov.qrc1
-rw-r--r--smtreemodel.h3
8 files changed, 276 insertions, 5 deletions
diff --git a/archivetreeview.cpp b/archivetreeview.cpp
index b00737e..3529b01 100644
--- a/archivetreeview.cpp
+++ b/archivetreeview.cpp
@@ -17,10 +17,25 @@
#include <QHash>
#include <QProcess>
#include <QMessageBox>
+#include <QSqlDatabase>
+#include <QSqlQuery>
+#include <QMenu>
+#include <QAction>
+#include <QContextMenuEvent>
+#include <QLabel>
+#include <QPushButton>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QProcess>
+#include <QUrl>
+#include <QMessageBox>
+#include <QClipboard>
+#include <QApplication>
#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<QVariant> 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;
+}
diff --git a/archivetreeview.h b/archivetreeview.h
index ddfad7e..2789298 100644
--- a/archivetreeview.h
+++ b/archivetreeview.h
@@ -11,6 +11,11 @@
#include <QWidget>
#include <QModelIndexList>
#include <QList>
+#include <QSqlDatabase>
+#include <QTreeView>
+#include <QDialog>
+
+#include "smtreemodel.h"
class SeriesTreeWidget;
class FilesTreeWidget;
@@ -18,7 +23,12 @@ class FilesTreeModel;
class SeriesTreeModel;
class MappingTableWidget;
class MappingTableModel;
+class NoCoverMovieDialog;
class QItemSelection;
+class QSqlQuery;
+class QPushButton;
+class QContextMenuEvent;
+class QLabel;
class ArchiveTreeView : public QWidget
{
@@ -35,6 +45,8 @@ class ArchiveTreeView : public QWidget
public slots:
void setFileViewMode(int mode);
void cleanDatabase(const QString &table);
+ void showNoCoverDialog();
+ void selectMovie(const QModelIndex &idx);
private slots:
void currentChanged(const QItemSelection &selected, const QItemSelection &deselected);
@@ -59,6 +71,62 @@ class ArchiveTreeView : public QWidget
//misc
QString mWindowTitle;
+ NoCoverMovieDialog *mNoCoverDialog;
+};
+
+class NoCoverMovieModel : public SmTreeModel {
+ Q_OBJECT
+ public:
+ enum CustomRoles { SeriesNameRole = Qt::UserRole + 1, SeriesPartRole = Qt::UserRole + 2, SeriesIdRole = Qt::UserRole + 3 };
+ enum Fields { Display = 0, SeriesName = 1, SeriesPart = 2, SeriesId = 3 };
+ explicit NoCoverMovieModel(const QStringList &headers, QObject *parent = 0);
+ virtual ~NoCoverMovieModel() {}
+ virtual QVariant data(const QModelIndex &index, int role) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ public slots:
+ void refresh();
+
+ signals:
+ void refreshed();
+
+ private:
+ QSqlDatabase mDb;
+ QSqlQuery *mDataQuery;
+};
+
+class NoCoverMovieView : public QTreeView {
+ Q_OBJECT
+ public:
+ explicit NoCoverMovieView(QWidget *parent = 0);
+ virtual ~NoCoverMovieView() {}
+
+ protected:
+ void contextMenuEvent(QContextMenuEvent *e);
+};
+
+class NoCoverMovieDialog : public QDialog {
+ Q_OBJECT
+ public:
+ explicit NoCoverMovieDialog(QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~NoCoverMovieDialog() {}
+ NoCoverMovieView *view() { return mView; }
+
+ private slots:
+ void openInBrowser();
+ void copyToClipboard();
+ void updateLabel();
+
+ private:
+ const QString selectedText() const;
+ const QString labelText() const;
+ QPushButton *mClose;
+ QPushButton *mRefresh;
+ NoCoverMovieView *mView;
+ NoCoverMovieModel *mModel;
+ QLabel *mMovieLabel;
+ QAction *mCopyA;
+ QAction *mBrowserA;
};
#endif
diff --git a/seriestreemodel.cpp b/seriestreemodel.cpp
index ab3fe8c..a2bde55 100644
--- a/seriestreemodel.cpp
+++ b/seriestreemodel.cpp
@@ -164,15 +164,19 @@ QList<QVariant> SeriesTreeModel::childrenColumnList(const QModelIndex &parent, i
return retval;
}
-QModelIndex SeriesTreeModel::findValue(const QVariant &value, const QModelIndex &parent, int column) const{
+QModelIndex SeriesTreeModel::findValue(const QVariant &value, const QModelIndex &parent, int searchColumn, int indexColumn) const{
SmTreeItem *parentItem = root();
if(parent != QModelIndex()){
parentItem = static_cast<SmTreeItem*>(parent.internalPointer());
}
for(int i = 0; i < parentItem->childCount(); ++i){
SmTreeItem *childItem = parentItem->child(i);
- if(value == childItem->data(column)){
- return createIndex(i, column, childItem);
+ if(value == childItem->data(searchColumn)){
+ if(indexColumn == -1){
+ return createIndex(i, searchColumn, childItem);
+ }else{
+ return createIndex(i, indexColumn, childItem);
+ }
}
}
return QModelIndex();
diff --git a/seriestreemodel.h b/seriestreemodel.h
index 63820ec..e26e49b 100644
--- a/seriestreemodel.h
+++ b/seriestreemodel.h
@@ -35,7 +35,7 @@ class SeriesTreeModel : public SmTreeModel {
QList<QVariant> childrenColumnList(const QModelIndex &parent, int column) const;
//find
- QModelIndex findValue(const QVariant &value, const QModelIndex &parent = QModelIndex(), int column = 0) const;
+ QModelIndex findValue(const QVariant &value, const QModelIndex &parent = QModelIndex(), int searchColumn = 0, int indexColumn = -1) const;
QFileInfoList findFiles(const QModelIndex &where) const;
QFileInfoList findMovies(const QModelIndexList &from) const;
QFileInfoList findSortedMovies(const QModelIndex &from) const;
diff --git a/shemov.cpp b/shemov.cpp
index 8821a7b..7cbbce6 100644
--- a/shemov.cpp
+++ b/shemov.cpp
@@ -165,6 +165,7 @@ void SheMov::tabChanged(int newTab){
mShowNormalA->setEnabled(false);
mShowArchivedA->setEnabled(false);
mShowLocalA->setEnabled(false);
+ mShowNoCoverDialogA->setEnabled(false);
}
if(newTab == 1){
setWindowTitle(mATree->windowTitle());
@@ -173,6 +174,7 @@ void SheMov::tabChanged(int newTab){
mShowNormalA->setEnabled(true);
mShowArchivedA->setEnabled(true);
mShowLocalA->setEnabled(true);
+ mShowNoCoverDialogA->setEnabled(true);
}
updateSelectionCount(QItemSelection(), QItemSelection());
}
@@ -413,6 +415,8 @@ void SheMov::createActions(){
connect(mShowNormalA, SIGNAL(triggered()), viewMapper, SLOT(map()));
mShowNormalA->setCheckable(true);
mShowNormalA->setChecked(true);
+ mShowNoCoverDialogA = new QAction(QIcon(":/higheels.png"), tr("List movies without cover..."), this);
+ connect(mShowNoCoverDialogA, SIGNAL(triggered()), mATree, SLOT(showNoCoverDialog()));
//Tree FileWidget actions
mMoveToBurnA = new QAction(tr("Move to burn directory"), this);
@@ -457,6 +461,7 @@ void SheMov::createMenus(){
cleanupMenu->addActions(mCleanupGroup->actions());
fileMenu->addMenu(cleanupMenu);
fileMenu->addAction(mConsistencyA);
+ fileMenu->addAction(mShowNoCoverDialogA);
fileMenu->addSeparator();
fileMenu->addAction(mQuitA);
menuBar()->addMenu(fileMenu);
@@ -638,6 +643,7 @@ void SheMov::createToolBar(){
toolBar->addAction(mCdupA);
toolBar->addSeparator();
toolBar->addAction(mConfigA);
+ toolBar->addAction(mShowNoCoverDialogA);
toolBar->addSeparator();
toolBar->addAction(mShowNormalA);
toolBar->addAction(mShowArchivedA);
diff --git a/shemov.h b/shemov.h
index 9ffa69b..de80a41 100644
--- a/shemov.h
+++ b/shemov.h
@@ -115,6 +115,7 @@ class SheMov : public QMainWindow {
QAction *mShowLocalA;
QAction *mShowArchivedA;
QAction *mShowNormalA;
+ QAction *mShowNoCoverDialogA;
QActionGroup *mViewTreeGroup;
//TreeView FileWidget Actions
diff --git a/shemov.qrc b/shemov.qrc
index 068dfef..5f7e302 100644
--- a/shemov.qrc
+++ b/shemov.qrc
@@ -16,5 +16,6 @@
<file>bald_pussy.png</file>
<file>prince_albert.png</file>
<file>diaper.png</file>
+ <file>higheels.png</file>
</qresource>
</RCC>
diff --git a/smtreemodel.h b/smtreemodel.h
index 6d89fb2..3eae432 100644
--- a/smtreemodel.h
+++ b/smtreemodel.h
@@ -46,9 +46,10 @@ class SmTreeModel : public QAbstractItemModel {
bool removeRows(int row, int count, const QModelIndex &parent);
bool addRow(const QList<QVariant> &data, const QModelIndex &parent);
+ protected:
+ SmTreeItem *itemAt(const QModelIndex &index) const;
private:
- SmTreeItem *itemAt(const QModelIndex &index) const;
QStringList mHeaders;
SmTreeItem *mRootItem;
};