summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArno <am@disconnect.de>2011-02-19 13:59:19 +0100
committerArno <am@disconnect.de>2011-02-19 13:59:19 +0100
commit23289ad65a1b06d3c3e9bbd4706ce75ce40c4b52 (patch)
tree6a3599e525a29141f9d658b94e7e32a012896ca5
parenta2e6438b97a8b9055bee400ccc40a062f0a0e9db (diff)
downloadSheMov-23289ad65a1b06d3c3e9bbd4706ce75ce40c4b52.tar.gz
SheMov-23289ad65a1b06d3c3e9bbd4706ce75ce40c4b52.tar.bz2
SheMov-23289ad65a1b06d3c3e9bbd4706ce75ce40c4b52.zip
Edit genres and actors
Added dialog for editing actors and genres.
-rw-r--r--mappingtableeditor.cpp236
-rw-r--r--mappingtableeditor.h77
-rw-r--r--shemov.cpp19
-rw-r--r--shemov.h3
-rw-r--r--shemov.pro6
5 files changed, 339 insertions, 2 deletions
diff --git a/mappingtableeditor.cpp b/mappingtableeditor.cpp
new file mode 100644
index 0000000..a5721d2
--- /dev/null
+++ b/mappingtableeditor.cpp
@@ -0,0 +1,236 @@
+/*
+ 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 <QSqlDatabase>
+#include <QSqlQuery>
+#include <QContextMenuEvent>
+#include <QMenu>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QLabel>
+#include <QMessageBox>
+#include <QAction>
+#include <QSortFilterProxyModel>
+
+#include "mappingtableeditor.h"
+
+//widget
+MappingTableEditor::MappingTableEditor(const QString &table, QWidget *parent) : QDialog(parent), mTable(table){
+ //caption
+ QString l1String = QString(tr("Edit %1s").arg(mTable));
+ QLabel *l1 = new QLabel(l1String);
+
+ //model + view
+ QStringList headers = QStringList() << QString("%1s").arg(mTable) << tr("Count");
+ mModel = new MappingTableEditorModel(table, headers, this);
+ mView = new MappingTableEditorView;
+ QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
+ proxy->setSourceModel(mModel);
+ mView->setModel(proxy);
+ mView->setRootIsDecorated(false);
+ mView->setColumnHidden(2, true);
+ mView->resizeColumnToContents(0);
+ mView->setSortingEnabled(true);
+ mView->setAlternatingRowColors(true);
+ mView->sortByColumn(0, Qt::AscendingOrder);
+ mView->setSelectionMode(QAbstractItemView::SingleSelection);
+
+ //edit
+ QHBoxLayout *editLayout = new QHBoxLayout;
+ QLabel *l2 = new QLabel(tr("Item"));
+ editLayout->addWidget(l2);
+ mDataEdit = new QLineEdit;
+ editLayout->addWidget(mDataEdit);
+
+ //buttons
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
+ buttonLayout->setAlignment(Qt::AlignRight);
+ mClose = new QPushButton(tr("Close"));
+ mClose->setDefault(true);
+ mRename = new QPushButton(tr("Rename"));
+ mDelete = new QPushButton(tr("Delete"));
+ buttonLayout->addWidget(mDelete);
+ buttonLayout->addWidget(mRename);
+ buttonLayout->addWidget(mClose);
+
+ //mainlayout
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(l1);
+ mainLayout->addWidget(mView);
+ mainLayout->addLayout(editLayout);
+ mainLayout->addLayout(buttonLayout);
+ setLayout(mainLayout);
+
+ //actions
+ mDeleteA = new QAction(tr("Delete"), this);
+ mView->addAction(mDeleteA);
+ mEditA = new QAction(tr("Edit..."), this);
+ mView->addAction(mEditA);
+
+ //connections
+ connect(mView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(selectionChanged(QModelIndex,QModelIndex)));
+ connect(mClose, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(mDelete, SIGNAL(clicked()), this, SLOT(removeItem()));
+ connect(mRename, SIGNAL(clicked()), this, SLOT(renameItem()));
+ connect(mDeleteA, SIGNAL(triggered()), this, SLOT(removeItem()));
+ connect(mEditA, SIGNAL(triggered()), this, SLOT(editItem()));
+}
+
+void MappingTableEditor::selectionChanged(const QModelIndex &cur, const QModelIndex &prev){
+ Q_UNUSED(prev);
+ mDataEdit->setText(cur.data(MappingTableEditorModel::NameRole).toString());
+}
+
+void MappingTableEditor::removeItem(){
+ QModelIndexList selected = mView->selectionModel()->selectedRows();
+ if(selected.isEmpty()){
+ return;
+ }
+ int count = selected.at(0).data(MappingTableEditorModel::CountRole).toInt();
+ if(count > 0){
+ QString warning = QString(tr("Really remove %1 %2? There are %3 items associated with it.")).arg(mTable).arg(selected.at(0).data(MappingTableEditorModel::NameRole).toString()).arg(QString::number(count));
+ int mbRetval = QMessageBox::warning(this, tr("Warning!"), warning, QMessageBox::Yes | QMessageBox::No);
+ if(mbRetval == QMessageBox::No){
+ return;
+ }
+ }
+ mModel->removeData(selected.at(0));
+}
+
+void MappingTableEditor::renameItem(){
+ QModelIndexList selected = mView->selectionModel()->selectedRows();
+ if(selected.isEmpty()){
+ return;
+ }
+ QString newValue = mDataEdit->text().toLower().trimmed();
+ QModelIndex newIdx = mModel->find(newValue, MappingTableEditorModel::Name);
+ if(newIdx.isValid()){
+ QString warning = QString(tr("New value %1 already exists. Merge?")).arg(newValue);
+ int mbRetval = QMessageBox::warning(this, tr("Warning!"), warning, QMessageBox::Yes | QMessageBox::No);
+ if(mbRetval == QMessageBox::No){
+ return;
+ }
+ }
+ mModel->setData(selected.at(0), newValue, Qt::EditRole);
+}
+
+void MappingTableEditor::editItem(){
+ QModelIndexList selected = mView->selectionModel()->selectedRows();
+ if(selected.isEmpty()){
+ return;
+ }
+ mView->edit(selected.at(0));
+}
+
+//view
+MappingTableEditorView::MappingTableEditorView(QWidget *parent) : QTreeView(parent) {}
+
+void MappingTableEditorView::contextMenuEvent(QContextMenuEvent *e){
+ QMenu contextMenu(this);
+ contextMenu.addActions(actions());
+ contextMenu.exec(e->globalPos());
+}
+
+//model
+MappingTableEditorModel::MappingTableEditorModel(const QString &table, const QStringList &headers, QObject *parent) : SmTreeModel(headers, parent), mTable(table){
+ mDb = QSqlDatabase::database("treedb");
+ QString queryString = QString("SELECT t%1name, COUNT(iseriesparts_id), %1s.i%1s_id from %1s, seriesparts_%1map WHERE %1s.i%1s_id = seriesparts_%1map.i%1s_id GROUP BY %1s.t%1name, %1s.i%1s_id ORDER BY t%1name").arg(mTable);
+ mDataQuery = new QSqlQuery(mDb);
+ mDataQuery->prepare(queryString);
+ QString mergeQuery = QString("UPDATE %1s SET %1s_id = %2 WHERE %1s_id = %3");
+ populate();
+}
+
+MappingTableEditorModel::~MappingTableEditorModel(){
+ delete mDataQuery;
+ mDb = QSqlDatabase();
+}
+
+Qt::ItemFlags MappingTableEditorModel::flags(const QModelIndex &index) const{
+ if(!index.isValid()){
+ return 0;
+ }
+ Qt::ItemFlags retval = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ if(index.column() == 0){
+ retval |= Qt::ItemIsEditable;
+ }
+ return retval;
+}
+
+QVariant MappingTableEditorModel::data(const QModelIndex &index, int role) const{
+ if(!index.isValid()){
+ return QVariant();
+ }
+ SmTreeItem *item = static_cast<SmTreeItem*>(index.internalPointer());
+ if(role == NameRole){
+ return item->data(Name);
+ }
+ if(role == CountRole){
+ return item->data(Count);
+ }
+ if(role == IdRole){
+ return item->data(Id);
+ }
+ return SmTreeModel::data(index, role);
+}
+
+bool MappingTableEditorModel::setData(const QModelIndex &idx, const QVariant &value, int role){
+ if(!idx.isValid()){
+ return false;
+ }
+ if(role != Qt::EditRole){
+ return false;
+ }
+ bool retval = false;
+ QModelIndex newValue = find(value);
+ if(newValue.isValid()){
+ QSqlQuery mergeQuery(mDb);
+ QString query = QString("UPDATE %1s SET %1s_id = :newid WHERE %1s_id = :oldid").arg(mTable);
+ mergeQuery.prepare(query);
+ mergeQuery.bindValue(":newid", newValue.data(IdRole));
+ mergeQuery.bindValue(":oldid", idx.data(IdRole));
+ retval = mergeQuery.exec();
+ }else{
+ QSqlQuery renameQuery(mDb);
+ QString query = QString("UPDATE %1s SET t%1name = :name WHERE i%1s_id = :id").arg(mTable);
+ renameQuery.prepare(query);
+ renameQuery.bindValue(":name", value);
+ renameQuery.bindValue(":id", idx.data(IdRole));
+ retval = renameQuery.exec();
+ }
+ if(retval){
+ populate();
+ }
+ return retval;
+}
+
+bool MappingTableEditorModel::removeData(const QModelIndex &idx){
+ if(!idx.isValid()){
+ return false;
+ }
+ QString removeQuery = QString("DELETE FROM %1s WHERE i%1s_id = %2").arg(mTable).arg(QString::number(idx.data(IdRole).toInt()));
+ QSqlQuery remove(removeQuery, mDb);
+ bool retval = remove.exec();
+ if(retval){
+ populate();
+ }
+ return retval;
+}
+
+void MappingTableEditorModel::populate(){
+ SmTreeItem *rootItem = new SmTreeItem(3);
+ mDataQuery->exec();
+ while(mDataQuery->next()){
+ QList<QVariant> data;
+ data << mDataQuery->value(0) << mDataQuery->value(1) << mDataQuery->value(2);
+ SmTreeItem *childItem = new SmTreeItem(data, rootItem);
+ rootItem->appendChild(childItem);
+ }
+ setRoot(rootItem);
+}
diff --git a/mappingtableeditor.h b/mappingtableeditor.h
new file mode 100644
index 0000000..124f76e
--- /dev/null
+++ b/mappingtableeditor.h
@@ -0,0 +1,77 @@
+/*
+ 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 MAPPINGTABLEEDITOR_H
+#define MAPPINGTABLEEDITOR_H
+
+#include <QDialog>
+#include <QTreeView>
+#include <QSqlDatabase>
+
+class QSqlQuery;
+class QContextMenuEvent;
+class QPushButton;
+class QLineEdit;
+class QAction;
+class MappingTableEditorView;
+class MappingTableEditorModel;
+
+#include "smtreemodel.h"
+#include "smtreeitem.h"
+
+class MappingTableEditor : public QDialog {
+ Q_OBJECT
+ public:
+ explicit MappingTableEditor(const QString &table, QWidget *parent = 0);
+
+ private slots:
+ void selectionChanged(const QModelIndex &cur, const QModelIndex &prev);
+ void removeItem();
+ void renameItem();
+ void editItem();
+
+ private:
+ const QString mTable;
+ QPushButton *mClose;
+ QPushButton *mDelete;
+ QPushButton *mRename;
+ QLineEdit *mDataEdit;
+ QAction *mDeleteA;
+ QAction *mEditA;
+ MappingTableEditorView *mView;
+ MappingTableEditorModel *mModel;
+};
+
+class MappingTableEditorView : public QTreeView {
+ Q_OBJECT
+ public:
+ explicit MappingTableEditorView(QWidget *parent = 0);
+
+ protected:
+ virtual void contextMenuEvent(QContextMenuEvent *e);
+};
+
+class MappingTableEditorModel : public SmTreeModel {
+ Q_OBJECT
+ public:
+ enum Roles { NameRole = Qt::UserRole + 1, CountRole = Qt::UserRole +2, IdRole = Qt::UserRole + 3 };
+ enum Fields { Name = 0, Count = 1, Id = 2 };
+ explicit MappingTableEditorModel(const QString &table, const QStringList &headers, QObject *parent = 0);
+ virtual ~MappingTableEditorModel();
+ virtual Qt::ItemFlags flags(const QModelIndex &idx) const;
+ virtual QVariant data(const QModelIndex &index, int role) const;
+ virtual bool setData(const QModelIndex &idx, const QVariant &value, int role);
+ virtual bool removeData(const QModelIndex &idx);
+
+ private:
+ void populate();
+ const QString mTable;
+ QSqlDatabase mDb;
+ QSqlQuery *mDataQuery;
+};
+
+#endif // MAPPINGTABLEEDITOR_H
diff --git a/shemov.cpp b/shemov.cpp
index 6a4f13f..ec846c5 100644
--- a/shemov.cpp
+++ b/shemov.cpp
@@ -49,6 +49,7 @@
#include "filestreewidget.h"
#include "filestreemodel.h"
#include "consistencycheck.h"
+#include "mappingtableeditor.h"
SheMov::SheMov(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags), mOpenWithGroupFS(0), mOpenWithGroupAV(0) {
//application icon
@@ -387,6 +388,14 @@ void SheMov::createActions(){
mToggleFavoriteA = new QAction(tr("Toggle as favorite"), this);
mToggleFavoriteA->setShortcut(tr("CTRL+m"));
connect(mToggleFavoriteA, SIGNAL(triggered()), mATree->seriesWidget(), SLOT(toggleFavorite()));
+ QSignalMapper *mappingMapper = new QSignalMapper(this);
+ mEditGenresA = new QAction(tr("Edit genres..."), this);
+ mappingMapper->setMapping(mEditGenresA, "genre");
+ connect(mEditGenresA, SIGNAL(triggered()), mappingMapper, SLOT(map()));
+ mEditActorsA = new QAction(tr("Edit actors..."), this);
+ mappingMapper->setMapping(mEditActorsA, "actor");
+ connect(mEditActorsA, SIGNAL(triggered()), mappingMapper, SLOT(map()));
+ connect(mappingMapper, SIGNAL(mapped(QString)), this, SLOT(editMappings(QString)));
//Edit menu rename submenu
mTemplateA = new QAction(tr("Set as template"), this);
@@ -646,6 +655,11 @@ void SheMov::createMenus(){
mEditAVMenu->addAction(a);
}
mEditAVMenuA = menuBar()->addMenu(mEditAVMenu);
+ QAction *sep20 = new QAction(this);
+ sep20->setSeparator(true);
+ mEditAVMenu->addAction(sep20);
+ mEditAVMenu->addAction(mEditActorsA);
+ mEditAVMenu->addAction(mEditGenresA);
//TreeView view menu
mTreeViewMenu = new QMenu(tr("&View"), this);
@@ -976,3 +990,8 @@ void SheMov::checkMount(bool mounted){
void SheMov::toggleFilterGroup(bool checked){
mFilterGroup->setEnabled(!checked);
}
+
+void SheMov::editMappings(QString table){
+ MappingTableEditor ed(table, this);
+ ed.exec();
+}
diff --git a/shemov.h b/shemov.h
index b926393..ab95425 100644
--- a/shemov.h
+++ b/shemov.h
@@ -48,6 +48,7 @@ class SheMov : public QMainWindow {
void toggleHover(QObject *object);
void checkMount(bool mounted);
void toggleFilterGroup(bool checked);
+ void editMappings(QString table);
signals:
void configChanged();
@@ -134,6 +135,8 @@ class SheMov : public QMainWindow {
QAction *mFilterBySizeA;
QActionGroup *mFilterGroup;
QAction *mFilterFavoritesA;
+ QAction *mEditGenresA;
+ QAction *mEditActorsA;
//TreeView FileWidget Actions
QAction *mMoveToBurnA;
diff --git a/shemov.pro b/shemov.pro
index 3123d26..4a52ca6 100644
--- a/shemov.pro
+++ b/shemov.pro
@@ -31,7 +31,8 @@ SOURCES = main.cpp \
filepropertiesdialog.cpp \
hoverwindow.cpp \
consistencycheck.cpp \
- seriesmetadatamodel.cpp
+ seriesmetadatamodel.cpp \
+ mappingtableeditor.cpp
HEADERS = listitem.h \
filesystemdirproxy.h \
filesystemwidget.h \
@@ -58,6 +59,7 @@ HEADERS = listitem.h \
filepropertiesdialog.h \
hoverwindow.h \
consistencycheck.h \
- seriesmetadatamodel.h
+ seriesmetadatamodel.h \
+ mappingtableeditor.h
LIBS += -lmagic -lXfixes
RESOURCES = shemov.qrc