summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArno <am@disconnect.de>2010-06-26 15:24:00 +0200
committerArno <am@disconnect.de>2010-06-26 15:24:00 +0200
commit0b807eba97e65bf9e25f83387826ef2579b79c90 (patch)
tree9a86166a4ebd77d95e9a26b723c49ebab417e337
parent6567a92bec5ca8b2bc6b7156bddc5ba8508f31b3 (diff)
downloadSheMov-0b807eba97e65bf9e25f83387826ef2579b79c90.tar.gz
SheMov-0b807eba97e65bf9e25f83387826ef2579b79c90.tar.bz2
SheMov-0b807eba97e65bf9e25f83387826ef2579b79c90.zip
Actors and genre edit
Implemented widgets for actor and genre editing of movies. Created new MappingTableWidget for both genres and actors and revamped ArchiveTreeView to show 2 widgets below the FilesTreeView separated by a splitter. While testing the new setup several bugs were fixed: -an SQL syntax error in FilesTreeModel -fixed SmModelSingleton to properly work with table names I also changed the signature of MappingTableModel::addMapping for the ease of use and added MappingTableModel::removeMapping. MappingTableModel got 2 new convenience functions: 1. bool contains(QString) to check if an item is already present 2. QModelIndex find() to get the index of a specific value from the model.
-rw-r--r--archivetreeview.cpp48
-rw-r--r--archivetreeview.h10
-rw-r--r--filestreemodel.cpp2
-rw-r--r--mappingtablemodel.cpp52
-rw-r--r--mappingtablemodel.h6
-rw-r--r--mappingtablewidget.cpp146
-rw-r--r--mappingtablewidget.h59
-rw-r--r--shemov.pro6
-rw-r--r--smmodelsingleton.cpp4
9 files changed, 313 insertions, 20 deletions
diff --git a/archivetreeview.cpp b/archivetreeview.cpp
index 211aa37..d77f8e3 100644
--- a/archivetreeview.cpp
+++ b/archivetreeview.cpp
@@ -20,8 +20,14 @@
#include "filestreewidget.h"
#include "filestreemodel.h"
#include "seriestreemodel.h"
+#include "mappingtablewidget.h"
+#include "mappingtablemodel.h"
ArchiveTreeView::ArchiveTreeView(QWidget *parent) : QWidget(parent){
+ // models
+ mActorsModel = static_cast<MappingTableModel*>(SmModelSingleton::instance()->model("actors"));
+ mGenresModel = static_cast<MappingTableModel*>(SmModelSingleton::instance()->model("genres"));
+
// series view
mSeriesWidget = new SeriesTreeWidget;
QItemSelectionModel *selModel = mSeriesWidget->seriesTree()->selectionModel();
@@ -36,11 +42,29 @@ ArchiveTreeView::ArchiveTreeView(QWidget *parent) : QWidget(parent){
mFilesWidget->filesTree()->setColumnHidden(i, true);
}
+ // actors and genre
+ QWidget *genreActorWidget = new QWidget;
+ QHBoxLayout *genreActorLayout = new QHBoxLayout;
+ mActorsWidget = new MappingTableWidget("actors");
+ mGenresWidget = new MappingTableWidget("genres");
+ genreActorLayout->addWidget(mActorsWidget);
+ genreActorLayout->addWidget(mGenresWidget);
+ genreActorWidget->setLayout(genreActorLayout);
+
+ // fileview, actors and genres
+ QSplitter *verticalSplitter = new QSplitter(Qt::Vertical);
+ verticalSplitter->addWidget(mFilesWidget);
+ verticalSplitter->addWidget(genreActorWidget);
+ verticalSplitter->setStretchFactor(0, 3);
+ verticalSplitter->setStretchFactor(1, 1);
+
// layout
QHBoxLayout *mainLayout = new QHBoxLayout;
QSplitter *splitter = new QSplitter;
splitter->addWidget(mSeriesWidget);
- splitter->addWidget(mFilesWidget);
+ splitter->addWidget(verticalSplitter);
+ splitter->setStretchFactor(0, 2);
+ splitter->setStretchFactor(1, 3);
mainLayout->addWidget(splitter);
setLayout(mainLayout);
}
@@ -83,4 +107,26 @@ void ArchiveTreeView::currentChanged(const QItemSelection &selected, const QItem
mFilesWidget->filesTree()->resizeColumnToContents(1);
mFilesWidget->filesTree()->resizeColumnToContents(2);
mFilesWidget->filesTree()->resizeColumnToContents(3);
+ setMappingItems(selectedPartIds, mActorsModel, mActorsWidget);
+ setMappingItems(selectedPartIds, mGenresModel, mGenresWidget);
+}
+
+void ArchiveTreeView::setMappingItems(QList<int>seriesPartIds, MappingTableModel *model, MappingTableWidget *widget){
+ QStringList items;
+ foreach(int id, seriesPartIds){
+ QList<QVariant> actorNames = model->mappings(id);
+ foreach(QVariant v, actorNames){
+ if(!items.contains(v.toString())){
+ items << v.toString();
+ }
+ }
+ }
+ qSort(items);
+ widget->setStringList(items);
+ widget->setEditEnabled(seriesPartIds.count() == 1);
+ if(seriesPartIds.count() == 1){
+ widget->setCurrentId(seriesPartIds.at(0));
+ }else{
+ widget->setCurrentId(-1);
+ }
}
diff --git a/archivetreeview.h b/archivetreeview.h
index 9958138..13dc88a 100644
--- a/archivetreeview.h
+++ b/archivetreeview.h
@@ -10,12 +10,15 @@
#include <QWidget>
#include <QModelIndexList>
+#include <QList>
class SmUberModel;
class SeriesTreeWidget;
class FilesTreeWidget;
class FilesTreeModel;
class SeriesTreeModel;
+class MappingTableWidget;
+class MappingTableModel;
class QItemSelection;
class ArchiveTreeView : public QWidget
@@ -28,13 +31,20 @@ class ArchiveTreeView : public QWidget
private slots:
void currentChanged(const QItemSelection &selected, const QItemSelection &deselected);
+ void setMappingItems(const QList<int> seriesPartIds, MappingTableModel *model, MappingTableWidget *widget);
private:
//widgets
SeriesTreeWidget *mSeriesWidget;
FilesTreeWidget *mFilesWidget;
+ MappingTableWidget *mActorsWidget;
+ MappingTableWidget *mGenresWidget;
+
+ //models
FilesTreeModel *mFilesModel;
SeriesTreeModel *mSeriesModel;
+ MappingTableModel *mActorsModel;
+ MappingTableModel *mGenresModel;
//lists
QModelIndexList mSelectedItems;
diff --git a/filestreemodel.cpp b/filestreemodel.cpp
index 973e7a6..cbfbd24 100644
--- a/filestreemodel.cpp
+++ b/filestreemodel.cpp
@@ -18,7 +18,7 @@ FilesTreeModel::FilesTreeModel(QStringList &headers, QObject *parent) : SmTreeMo
mUpdateDvdQuery = new QSqlQuery(mDb);
mUpdateDvdQuery->prepare("UPDATE files SET idvd = :dvd WHERE ifiles_id = :id");
mUpdateQualityQuery = new QSqlQuery(mDb);
- mUpdateQualityQuery->prepare("UPDATE files SET iquality = :quality WHERE ifiles_id = :id");
+ mUpdateQualityQuery->prepare("UPDATE files SET siquality = :quality WHERE ifiles_id = :id");
}
FilesTreeModel::~FilesTreeModel(){
diff --git a/mappingtablemodel.cpp b/mappingtablemodel.cpp
index 84c242a..ad569ee 100644
--- a/mappingtablemodel.cpp
+++ b/mappingtablemodel.cpp
@@ -33,7 +33,10 @@ MappingTableModel::MappingTableModel(QStringList &headers, const QString &table,
QString addMappingQuery = QString("INSERT INTO %1 (iseriesparts_id, %2) VALUES (:id1, :id2)").arg(mMappingTable).arg(mIdColumnName);
mAddMappingQuery = new QSqlQuery(mDb);
mAddMappingQuery->prepare(addMappingQuery);
- QString mappingQuery = QString("SELECT %1 FROM %2, %3 WHERE %1.%4 = %3.%4 AND %3.iseriesparts_id = :id").arg(mNameColumnName).arg(mTable).arg(mMappingTable).arg(mIdColumnName);
+ QString removeMappingQuery = QString("DELETE FROM %1 WHERE iseriesparts_id = :id1 AND %2 = :id2").arg(mMappingTable).arg(mIdColumnName);
+ mRemoveMappingQuery = new QSqlQuery(mDb);
+ mRemoveMappingQuery->prepare(removeMappingQuery);
+ QString mappingQuery = QString("SELECT %1 FROM %2, %3 WHERE %2.%4 = %3.%4 AND %3.iseriesparts_id = :id").arg(mNameColumnName).arg(mTable).arg(mMappingTable).arg(mIdColumnName);
mMappingQuery = new QSqlQuery(mDb);
mMappingQuery->prepare(mappingQuery);
@@ -46,6 +49,7 @@ MappingTableModel::~MappingTableModel(){
delete mInsertItemQuery;
delete mDeleteItemQuery;
delete mAddMappingQuery;
+ delete mRemoveMappingQuery;
delete mMappingQuery;
mDb = QSqlDatabase();
}
@@ -98,6 +102,24 @@ bool MappingTableModel::setData(const QModelIndex &index, const QVariant &value,
return false;
}
+bool MappingTableModel::contains(const QString &value) const{
+ return mItemNames.contains(value);
+}
+
+QModelIndex MappingTableModel::find(const QVariant &value, int column, const QModelIndex &parent) const{
+ SmTreeItem *parentItem = root();
+ if(parent.isValid()){
+ parentItem = static_cast<SmTreeItem*>(parent.internalPointer());
+ }
+ for(int i = 0; i < parentItem->childCount(); ++i){
+ SmTreeItem *cur = parentItem->child(i);
+ if(cur->data(column) == value){
+ return index(i, column, parent);
+ }
+ }
+ return QModelIndex();
+}
+
bool MappingTableModel::addItem(const QVariant &name){
QString newValue = name.toString().toLower().trimmed();
if(mItemNames.contains(newValue)){
@@ -138,22 +160,24 @@ bool MappingTableModel::removeItem(const QModelIndex &idx){
return false;
}
-bool MappingTableModel::addMapping(int seriesId, const QList<int> &itemIds){
- if(itemIds.isEmpty()){
- return false;
- }
+bool MappingTableModel::addMapping(int seriesId, int itemId){
mDb.transaction();
- foreach(int id, itemIds){
- mAddMappingQuery->bindValue(":id1", seriesId);
- mAddMappingQuery->bindValue(":id2", id);
- if(!mAddMappingQuery->exec()){
- mDb.rollback();
- return false;
- }
+ mAddMappingQuery->bindValue(":id1", seriesId);
+ mAddMappingQuery->bindValue(":id2", itemId);
+ if(!mAddMappingQuery->exec()){
+ mDb.rollback();
+ return false;
}
+ mDb.commit();
return true;
}
+bool MappingTableModel::removeMapping(int seriesId, int itemId){
+ mRemoveMappingQuery->bindValue(":id1", seriesId);
+ mRemoveMappingQuery->bindValue(":id2", itemId);
+ return mRemoveMappingQuery->exec();
+}
+
QList<QVariant> MappingTableModel::mappings(int seriesId){
QList<QVariant> retval;
mMappingQuery->bindValue(":id", seriesId);
@@ -167,7 +191,9 @@ QList<QVariant> MappingTableModel::mappings(int seriesId){
void MappingTableModel::populate(){
QString query = QString("SELECT %1, %2 FROM %3 ORDER BY %2").arg(mIdColumnName).arg(mNameColumnName).arg(mTable);
- SmTreeItem *root = new SmTreeItem(2);
+ QList<QVariant> rootData;
+ rootData << QString(tr("%1 name")).arg(mTable) << tr("Id");
+ SmTreeItem *root = new SmTreeItem(rootData);
QSqlQuery dataQuery(query, mDb);
while(dataQuery.next()){
QList<QVariant> data;
diff --git a/mappingtablemodel.h b/mappingtablemodel.h
index f624bff..d600437 100644
--- a/mappingtablemodel.h
+++ b/mappingtablemodel.h
@@ -29,13 +29,16 @@ class MappingTableModel : public SmTreeModel{
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
virtual QVariant data(const QModelIndex &index, int role) const;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
+ bool contains(const QString &value) const;
+ QModelIndex find(const QVariant &value, int column = 0, const QModelIndex &parent = QModelIndex()) const;
//add and remove items
bool addItem(const QVariant &name);
bool removeItem(const QModelIndex &idx);
//mappings
- bool addMapping(int seriesId, const QList<int> &itemIds);
+ bool addMapping(int seriesId, int itemId);
+ bool removeMapping(int seriesId, int itemId);
QList<QVariant> mappings(int seriesId);
signals:
@@ -56,6 +59,7 @@ class MappingTableModel : public SmTreeModel{
QSqlQuery *mInsertItemQuery;
QSqlQuery *mDeleteItemQuery;
QSqlQuery *mAddMappingQuery;
+ QSqlQuery *mRemoveMappingQuery;
QSqlQuery *mMappingQuery;
};
diff --git a/mappingtablewidget.cpp b/mappingtablewidget.cpp
new file mode 100644
index 0000000..e4a177c
--- /dev/null
+++ b/mappingtablewidget.cpp
@@ -0,0 +1,146 @@
+/*
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version
+ 2 of the License, or (at your option) any later version.
+*/
+
+#include <QIcon>
+#include <QTreeView>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QLabel>
+#include <QCompleter>
+#include <QGroupBox>
+
+#include "mappingtablewidget.h"
+#include "mappingtablemodel.h"
+#include "smmodelsingleton.h"
+
+MappingTableWidget::MappingTableWidget(const QString &table, QWidget *parent) : QWidget(parent), mTable(table), mCurrentId(-1){
+ //the view
+ mView = new QTreeView;
+ mView->setHeaderHidden(true);
+ mModel = new MappingTableItemModel(this);
+ mModel->setHeaderData(0, Qt::Horizontal, mTable);
+ mView->setModel(mModel);
+
+ //mapping model
+ mMappingModel = static_cast<MappingTableModel*>(SmModelSingleton::instance()->model(mTable));
+
+ //editor
+ QHBoxLayout *itemEditLayout = new QHBoxLayout;
+ QString l1Text = QString(tr("&Edit %1")).arg(mTable);
+ QLabel *l1 = new QLabel(l1Text);
+ mItemEdit = new QLineEdit;
+ QCompleter *completer = new QCompleter(this);
+ completer->setModel(mMappingModel);
+ mItemEdit->setCompleter(completer);
+ l1->setBuddy(mItemEdit);
+ itemEditLayout->addWidget(l1);
+ itemEditLayout->addWidget(mItemEdit);
+ connect(mItemEdit, SIGNAL(returnPressed()), this, SLOT(addItem()));
+
+ //buttons
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
+ buttonLayout->addStretch();
+ mAddItem = new QPushButton(tr("Add item"));
+ mRemoveItem = new QPushButton(tr("Remove item"));
+ buttonLayout->addWidget(mAddItem);
+ buttonLayout->addWidget(mRemoveItem);
+ connect(mAddItem, SIGNAL(clicked()), this, SLOT(addItem()));
+ connect(mRemoveItem, SIGNAL(clicked()), this, SLOT(removeItem()));
+
+ //layout
+ QVBoxLayout *groupBoxLayout = new QVBoxLayout;
+ groupBoxLayout->addWidget(mView);
+ groupBoxLayout->addLayout(itemEditLayout);
+ groupBoxLayout->addLayout(buttonLayout);
+ QString gbCaption = QString(tr("Edit %1")).arg(mTable);
+ QGroupBox *gb = new QGroupBox(gbCaption);
+ gb->setLayout(groupBoxLayout);
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(gb);
+ setLayout(mainLayout);
+ setContentsMargins(0, 0, 0, 0);
+}
+
+void MappingTableWidget::setStringList(const QStringList &list){
+ mModel->setStringList(list);
+}
+
+void MappingTableWidget::setEditEnabled(bool enabled){
+ mAddItem->setEnabled(enabled);
+ mRemoveItem->setEnabled(enabled);
+ mItemEdit->setEnabled(enabled);
+}
+void MappingTableWidget::addItem(){
+ QString value = mItemEdit->text().toLower().trimmed();
+ if(mModel->stringList().contains(value)){
+ return;
+ }
+ if(!mMappingModel->contains(value)){
+ mMappingModel->addItem(value);
+ }
+ int row = mModel->lowerBound(value);
+ if(mModel->insertRows(row, 1)){
+ QModelIndex idx = mModel->index(row, 0);
+ mModel->setData(idx, value);
+ QModelIndex mapIndex = mMappingModel->find(value, 0, QModelIndex());
+ if(mapIndex.isValid()){
+ int id = mapIndex.data(MappingTableModel::ItemIdRole).toInt();
+ mMappingModel->addMapping(mCurrentId, id);
+ }
+ }
+}
+
+void MappingTableWidget::removeItem(){
+ QModelIndexList selected = mView->selectionModel()->selectedRows();
+ if(selected.isEmpty()){
+ return;
+ }
+ foreach(QPersistentModelIndex i, selected){
+ QString item = i.data().toString();
+ mModel->removeRows(i.column(), 1);
+ QModelIndex itemIdx = mMappingModel->find(item);
+ if(itemIdx.isValid()){
+ mMappingModel->removeMapping(mCurrentId, itemIdx.data(MappingTableModel::ItemIdRole).toInt());
+ }
+ }
+}
+
+MappingTableItemModel::MappingTableItemModel(QObject *parent) : QStringListModel(parent) {}
+
+QVariant MappingTableItemModel::data(const QModelIndex &index, int role) const{
+ if(role == Qt::DecorationRole){
+ return QIcon(":/dildo.png");
+ }
+ return QStringListModel::data(index, role);
+}
+
+Qt::ItemFlags MappingTableItemModel::flags(const QModelIndex &index) const{
+ Q_UNUSED(index);
+ return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+}
+
+int MappingTableItemModel::lowerBound(const QString &value) const{
+ int retval = 0;
+ for(int i = 0; i < stringList().count(); ++i){
+ if(value < stringList().at(i)){
+ ++retval;
+ }else{
+ break;
+ }
+ }
+ return retval;
+}
+
+QModelIndex MappingTableItemModel::find(const QString &value) const{
+ int row = stringList().indexOf(value);
+ if(row == -1){
+ return QModelIndex();
+ }
+ return index(row, 0);
+}
diff --git a/mappingtablewidget.h b/mappingtablewidget.h
new file mode 100644
index 0000000..d6df991
--- /dev/null
+++ b/mappingtablewidget.h
@@ -0,0 +1,59 @@
+/*
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version
+ 2 of the License, or (at your option) any later version.
+*/
+
+#ifndef MAPPINGTABLEWIDGET_H
+#define MAPPINGTABLEWIDGET_H
+
+#include <QWidget>
+#include <QStringListModel>
+
+class QTreeView;
+class QLineEdit;
+class QPushButton;
+class MappingTableItemModel;
+class MappingTableModel;
+
+class MappingTableWidget : public QWidget{
+ Q_OBJECT
+ public:
+ explicit MappingTableWidget(const QString &table, QWidget *parent = 0);
+
+ public slots:
+ void setStringList(const QStringList &list);
+ void setEditEnabled(bool enabled);
+ void setCurrentId(int id) { mCurrentId = id; }
+
+ private slots:
+ void addItem();
+ void removeItem();
+
+ private:
+ QTreeView *mView;
+ QPushButton *mAddItem;
+ QPushButton *mRemoveItem;
+ QLineEdit *mItemEdit;
+ MappingTableItemModel *mModel;
+ MappingTableModel *mMappingModel;
+ const QString mTable;
+ int mCurrentId;
+};
+
+class MappingTableItemModel : public QStringListModel {
+ Q_OBJECT
+ public:
+ explicit MappingTableItemModel(QObject *parent = 0);
+
+ //data + flags
+ virtual QVariant data(const QModelIndex &index, int role) const;
+ virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ //find
+ int lowerBound(const QString &value) const;
+ QModelIndex find(const QString &value) const;
+};
+
+#endif // MAPPINGTABLEWIDGET_H
diff --git a/shemov.pro b/shemov.pro
index 60bc419..6d54047 100644
--- a/shemov.pro
+++ b/shemov.pro
@@ -54,7 +54,8 @@ SOURCES = main.cpp \
seriestreemodel.cpp \
filestreemodel.cpp \
filestreewidget.cpp \
- mappingtablemodel.cpp
+ mappingtablemodel.cpp \
+ mappingtablewidget.cpp
HEADERS = listitem.h \
listmodel.h \
movieitem.h \
@@ -104,6 +105,7 @@ HEADERS = listitem.h \
seriestreemodel.h \
filestreemodel.h \
filestreewidget.h \
- mappingtablemodel.h
+ mappingtablemodel.h \
+ mappingtablewidget.h
LIBS += -lmagic
RESOURCES = shemov.qrc
diff --git a/smmodelsingleton.cpp b/smmodelsingleton.cpp
index 2ee5623..7425aeb 100644
--- a/smmodelsingleton.cpp
+++ b/smmodelsingleton.cpp
@@ -51,13 +51,13 @@ QAbstractItemModel *SmModelSingleton::model(const QString &which){
FilesTreeModel *model = new FilesTreeModel(headers);
mModels.insert(which, model);
}
- }else if(which == "ActorsModel"){
+ }else if(which == "actors"){
if(!mModels.contains(which)){
QStringList headers = QStringList() << tr("Actor") << tr("Id");
MappingTableModel *model = new MappingTableModel(headers, "actors");
mModels.insert(which, model);
}
- }else if(which == "GenresModel"){
+ }else if(which == "genres"){
if(!mModels.contains(which)){
QStringList headers = QStringList() << tr("Genre") << tr("Id");
MappingTableModel *model = new MappingTableModel(headers, "genres");