diff options
-rw-r--r-- | mappingtableeditor.cpp | 236 | ||||
-rw-r--r-- | mappingtableeditor.h | 77 | ||||
-rw-r--r-- | shemov.cpp | 19 | ||||
-rw-r--r-- | shemov.h | 3 | ||||
-rw-r--r-- | shemov.pro | 6 |
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 @@ -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(); +} @@ -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; @@ -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 |