/* 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 #include #include #include #include #include #include #include #include #include #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" #include "seriestreemodel.h" #include "mappingtablewidget.h" #include "mappingtablemodel.h" #include "seriesmetadatamodel.h" #include "helper.h" ArchiveTreeView::ArchiveTreeView(QWidget *parent) : QWidget(parent), mShowAllFiles(false){ // models mActorsModel = static_cast(SmGlobals::instance()->model("actors")); mGenresModel = static_cast(SmGlobals::instance()->model("genres")); // series view mSeriesWidget = new SeriesTreeWidget(this); QItemSelectionModel *selModel = mSeriesWidget->seriesTree()->selectionModel(); connect(selModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(currentChanged(QItemSelection,QItemSelection))); connect(mSeriesWidget->seriesTree(), SIGNAL(doubleClicked(QModelIndex)), this, SLOT(playSelected())); mSeriesModel = static_cast(SmGlobals::instance()->model("SeriesModel")); connect(mSeriesModel, SIGNAL(localsChanged()), this, SLOT(invalidateSorting())); // files view mFilesWidget = new FilesTreeWidget; mFilesModel = qobject_cast(SmGlobals::instance()->model("FilesModel")); connect(mSeriesWidget, SIGNAL(filesReload()), mFilesWidget->filesTree(), SLOT(expandAll())); // actors and genre QWidget *genreActorWidget = new QWidget; QHBoxLayout *genreActorLayout = new QHBoxLayout; mActorsWidget = new MappingTableWidget("actors"); mGenresWidget = new MappingTableWidget("genres"); mMetaData = new MetadataDisplay; genreActorLayout->addWidget(mActorsWidget); genreActorLayout->addWidget(mGenresWidget); genreActorLayout->addWidget(mMetaData); 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); // misc mFilesWidget->filesTree()->setAlternatingRowColors(true); mSeriesWidget->seriesTree()->setAlternatingRowColors(true); // layout QHBoxLayout *mainLayout = new QHBoxLayout; QSplitter *splitter = new QSplitter; splitter->addWidget(mSeriesWidget); splitter->addWidget(verticalSplitter); splitter->setStretchFactor(0, 2); splitter->setStretchFactor(1, 3); mainLayout->addWidget(splitter); setLayout(mainLayout); constructWindowTitle(); readSettings(); } void ArchiveTreeView::setFileViewMode(int mode){ mSeriesModel->setRowFilter(mode); mSeriesWidget->seriesProxy()->invalidate(); mFilesModel->setMode(mode); showAllFiles(mShowAllFiles); constructWindowTitle(); mSeriesWidget->expandItems(); } void ArchiveTreeView::showAllFiles(bool toggled){ mShowAllFiles = toggled; if(mShowAllFiles){ mFilesWidget->resetSize(); int seriesRow = 0; QModelIndex series = mSeriesModel->index(seriesRow, 0, QModelIndex()); QList ids; while(series.isValid()){ int childRow = 0; QModelIndex child = mSeriesModel->index(childRow, 0, series); while(child.isValid()){ if(mSeriesWidget->seriesProxy()->acceptedByFilter(child.row(), child.parent())){ ids << child.data(SeriesTreeModel::SeriesPartIdRole).toInt(); } child = mSeriesModel->index(++childRow, 0, child.parent()); } series = mSeriesModel->index(++seriesRow, 0, series.parent()); } mFilesModel->setIds(ids); mFilesWidget->filesTree()->expandAll(); mFilesWidget->filesTree()->resizeColumnToContents(0); }else{ QModelIndexList selectedSeries = mSeriesWidget->seriesTree()->selectionModel()->selectedRows(); QModelIndex selected; if(selectedSeries.isEmpty()){ selected = mSeriesWidget->seriesProxy()->index(0, 0); }else{ selected = selectedSeries.at(0); } mSeriesWidget->seriesTree()->selectionModel()->setCurrentIndex(selected, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); currentChanged(QItemSelection(), QItemSelection()); } } void ArchiveTreeView::cleanDatabase(const QString &table){ MappingTableModel *model = 0; if(table == "genres"){ model = mGenresModel; }else if(table == "actors"){ model = mActorsModel; } Q_ASSERT(model); QHash zeroUsers = model->zeroUsers(); if(zeroUsers.isEmpty()){ QMessageBox::information(this, tr("Message"), tr("Nothing to clean up!")); return; } QString message = QString(tr("

Really delete these items from %1?

")).arg(table); message.append("

    "); QStringList userNames = zeroUsers.keys(); qSort(userNames); foreach(QString s, userNames){ message.append(QString("
  • %1
  • ").arg(s)); } message.append("
"); int answer = QMessageBox::question(this, tr("Question"), message, QMessageBox::Yes | QMessageBox::No); if(answer == QMessageBox::Yes){ QList ids = zeroUsers.values(); model->deleteItems(ids); } } void ArchiveTreeView::selectMoviePart(int seriespartId, int seriesId){ QModelIndex seriesIdx = mSeriesModel->findValue(seriesId, QModelIndex(), SeriesTreeModel::SeriesId); QModelIndex partIdx = mSeriesModel->findValue(seriespartId, seriesIdx, SeriesTreeModel::SeriesPartId); if(partIdx.isValid()){ QModelIndex viewSelect = mSeriesWidget->seriesProxy()->mapFromSource(partIdx); mSeriesWidget->seriesTree()->expand(viewSelect.parent()); mSeriesWidget->seriesTree()->selectionModel()->select(viewSelect, QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); mSeriesWidget->seriesTree()->scrollTo(viewSelect.parent(), QAbstractItemView::PositionAtTop); } } void ArchiveTreeView::copyPath(int type){ QModelIndexList selected = mFilesWidget->filesTree()->selectionModel()->selectedRows(); if(selected.isEmpty()){ return; } QString fullPath = selected.at(0).data(FilesTreeModel::FullPathRole).toString(); QFileInfo fi(fullPath); if(!fi.exists()){ int dvdNo = selected.at(0).data(FilesTreeModel::DvdNoRole).toInt(); QString msg = QString(tr("File not found. File is archived on DVD #%1")).arg(QString::number(dvdNo)); QMessageBox::critical(this, tr("Error"), msg); return; } QClipboard *clipBoard = QApplication::clipboard(); if(type == UnixFullPath){ clipBoard->setText(fi.absoluteFilePath()); } if(type == UnixDir){ clipBoard->setText(fi.absolutePath()); } if(type == WindowsFullPath){ clipBoard->setText(createWindowsPath(fi.absoluteFilePath())); } if(type == WindowsDir){ clipBoard->setText(createWindowsPath(fi.absolutePath())); } } void ArchiveTreeView::readSettings(){ seriesWidget()->seriesTree()->readSettings(); filesWidget()->filesTree()->readSettings(); mFilesModel->readSettings(); QSettings s; QString iconName = s.value("ui/foldericon", "Dildo").toString(); const QHash icons = SmGlobals::instance()->icons(); QIcon decorationIcon = QIcon(icons.value(iconName)); mFilesModel->setDecorationIcon(decorationIcon); mSeriesModel->setDecorationIcon(decorationIcon); MappingTableItemModel *actorsModel = mActorsWidget->model(); actorsModel->setDecorationIcon(decorationIcon); MappingTableItemModel *genreModel = mGenresWidget->model(); genreModel->setDecorationIcon(decorationIcon); } void ArchiveTreeView::currentChanged(const QItemSelection &selected, const QItemSelection &deselected){ Q_UNUSED(selected); Q_UNUSED(deselected); QModelIndexList selectedSeries = mSeriesWidget->seriesTree()->selectionModel()->selectedRows(); mFilesWidget->resetSize(); if(selectedSeries.isEmpty()){ return; } QList selectedPartIds; SeriesTreeSortModel *proxy = mSeriesWidget->seriesProxy(); foreach(QModelIndex i, selectedSeries){ QModelIndex real = proxy->mapToSource(i); if(real.isValid()){ int type = real.data(SeriesTreeModel::TypeRole).toInt(); if(type == SeriesTreeModel::Series){ QList childIds = mSeriesModel->childrenColumnList(real, SeriesTreeModel::SeriesPartId); foreach(QVariant id, childIds){ int realId = id.toInt(); if(!selectedPartIds.contains(realId)){ selectedPartIds << realId; } } }else if(type == SeriesTreeModel::Part){ int realId = i.data(SeriesTreeModel::SeriesPartIdRole).toInt(); if(!selectedPartIds.contains(realId)){ selectedPartIds << realId; } } } } mFilesModel->setIds(selectedPartIds); mFilesWidget->filesTree()->expandAll(); mFilesWidget->filesTree()->header()->resizeSections(QHeaderView::ResizeToContents); setMappingItems(selectedPartIds, mActorsModel, mActorsWidget); setMappingItems(selectedPartIds, mGenresModel, mGenresWidget); mMetaData->setSeriesPartId(selectedPartIds.at(0)); } void ArchiveTreeView::setMappingItems(QListseriesPartIds, MappingTableModel *model, MappingTableWidget *widget){ QStringList items; foreach(int id, seriesPartIds){ QList 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); } } void ArchiveTreeView::playSelected(const QString &preferred){ QModelIndexList selected = mSeriesWidget->seriesTree()->selectionModel()->selectedRows(); if(selected.isEmpty()){ return; } QStringList files; foreach(QModelIndex idx, selected){ QModelIndex real = mSeriesWidget->seriesProxy()->mapToSource(idx); QFileInfoList movies = mSeriesModel->findSortedMovies(real); foreach(QFileInfo fi, movies){ if(!files.contains(fi.absoluteFilePath())){ files << fi.absoluteFilePath(); } } } QPair progData = Helper::programData("movieviewer", preferred); QString program = progData.first; QStringList args = progData.second; args << files; QProcess::startDetached(program, args); } void ArchiveTreeView::invalidateSorting(){ mSeriesWidget->seriesProxy()->invalidate(); } void ArchiveTreeView::constructWindowTitle(){ int rowFilter = mSeriesModel->rowFilter(); mWindowTitle = QString(tr("Movie Archive")); switch(rowFilter){ case SeriesTreeModel::Archived: mWindowTitle.append(tr(" - [Archived]")); break; case SeriesTreeModel::Local: mWindowTitle.append(tr(" - [Local]")); break; default: ; } emit needWindowTitleChange(mWindowTitle); } const QString ArchiveTreeView::createWindowsPath(const QString &path) const{ QString retval = path; QSettings s; const QString strip = s.value("paths/strippath").toString(); retval.remove(strip); retval.replace('/', '\\'); retval = QString("%1\\%2").arg(s.value("paths/windowsdrive").toString()).arg(retval); return retval; }