/* 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 "movieinfopage.h" #include "wizardtreemodel.h" #include "smtreeview.h" #include "delegates.h" #include "smglobals.h" #include "helper.h" MovieInfoPage::MovieInfoPage(QWidget *parent) : QWizardPage(parent), mCurSeriesno(0), mCurQuality(8){ setupGui(); } void MovieInfoPage::setupGui(){ setTitle(tr("Collect files for movie")); setSubTitle(tr("Select files by clicking the \"Add files...\" button. After adding files select one by one and set the appropriate file type. The series no is the number the movie has in the series: 14 in case of e.g. rogue adventures 14. The part number only has to be set if the movie is split in several parts.")); setPixmap(QWizard::LogoPixmap, QPixmap(":/shemov.png")); //files model setup QStringList modelHeaders = QStringList() << tr("File name") << tr("Size") << tr("File Type") << tr("No.") << tr("Full path"); mFileModel = new WizardTreeModel(modelHeaders, this); //files view mFileView = new SmTreeView; mProxy = new QSortFilterProxyModel(this); mProxy->setSourceModel(mFileModel); mFileView->setModel(mProxy); mFileView->setItemDelegateForColumn(WizardTreeModel::FileType, new FileTypeDelegate(mFileView)); mFileView->setItemDelegateForColumn(WizardTreeModel::FileSize, new SizeDelegate(mFileView)); mFileView->setItemDelegateForColumn(WizardTreeModel::FilePart, new FileNoDelegate(mFileView)); mFileView->setSortingEnabled(true); mFileView->header()->moveSection(1, 3); mFileView->setSelectionMode(QAbstractItemView::ExtendedSelection); //add + remove files QHBoxLayout *fileButtonLayout = new QHBoxLayout; fileButtonLayout->addStretch(); QPushButton *extractTitleB = new QPushButton(tr("Title")); fileButtonLayout->addWidget(extractTitleB); connect(extractTitleB, &QPushButton::clicked, this, &MovieInfoPage::extractTitle); QPushButton *addOldB = new QPushButton(tr("Add Old...")); fileButtonLayout->addWidget(addOldB); connect(addOldB, &QPushButton::clicked, this, &MovieInfoPage::addOld); QPushButton *addFileB = new QPushButton(tr("Add files...")); fileButtonLayout->addWidget(addFileB); connect(addFileB, &QPushButton::clicked, this, &MovieInfoPage::addFiles); QPushButton *removeFileB = new QPushButton(tr("Remove from list")); fileButtonLayout->addWidget(removeFileB); connect(removeFileB, &QPushButton::clicked, this, &MovieInfoPage::removeFile); //movie name + subtitle QGridLayout *movieTitleLayout = new QGridLayout; mTitle = new QLineEdit; movieTitleLayout->addWidget(new QLabel(tr("Movie title")), 0, 0); movieTitleLayout->addWidget(mTitle, 0, 1, 1, 3); mSubtitle = new QLineEdit; movieTitleLayout->addWidget(new QLabel(tr("Movie subtitle")), 1, 0); movieTitleLayout->addWidget(mSubtitle, 1, 1, 1, 1); QPushButton *lowerCaseB = new QPushButton(QIcon(":/steel_collar.png"), tr("Lower case")); connect(lowerCaseB, &QPushButton::clicked, this, &MovieInfoPage::toLower); movieTitleLayout->addWidget(lowerCaseB, 1, 2, 1, 1); QPushButton *checkB = new QPushButton(QIcon(":/spreadingpants.png"), tr("Fuzzy check...")); connect(checkB, &QPushButton::clicked, this, &MovieInfoPage::fuzzyCheck); movieTitleLayout->addWidget(checkB, 1, 3, 1, 1); mSeriesCompleter = new QCompleter(this); mSeriesCompleterModel = new QStringListModel(this); mSeriesCompleter->setModel(mSeriesCompleterModel); mTitle->setCompleter(mSeriesCompleter); //series, part + quality QHBoxLayout *numberLayout = new QHBoxLayout; numberLayout->addStretch(); QLabel *l3 = new QLabel(tr("&Series no.")); mSeriesNo = new QSpinBox; l3->setBuddy(mSeriesNo); mSeriesNo->setMinimum(0); numberLayout->addWidget(l3); numberLayout->addWidget(mSeriesNo); QLabel *l5 = new QLabel(tr("&Quality")); mQuality = new QSpinBox; l5->setBuddy(mQuality); mQuality->setMinimum(1); mQuality->setMaximum(10); numberLayout->addWidget(l5); numberLayout->addWidget(mQuality); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(mFileView); mainLayout->addLayout(fileButtonLayout); mainLayout->addLayout(movieTitleLayout); mainLayout->addLayout(numberLayout); setLayout(mainLayout); initCompleters(); //expose data registerField("title*", mTitle); registerField("subtitle", mSubtitle); registerField("seriesNo", mSeriesNo); registerField("quality", mQuality); } void MovieInfoPage::initializePage(){ initCompleters(); QSettings s; bool clearPage = s.value("ui/clearnewmoviewizard").toBool(); if(clearPage == false){ restoreData(); } mFileModel->clear(); mOrigins.clear(); } void MovieInfoPage::addFile(const QString &file){ QFileInfo fi(file); if(fi.exists()){ if(mFileModel->find(file, WizardTreeModel::FullPath).isValid()){ return; } QList itemData; itemData << fi.fileName() << fi.size() << QVariant() << QVariant() << fi.absoluteFilePath(); QString mimeType = Helper::mimeType(fi.absoluteFilePath()); if(mimeType.startsWith("video") || fi.suffix() == "mkv"){ itemData[WizardTreeModel::FileType] = WizardTreeModel::Movie; }else{ QString baseName = fi.completeBaseName(); QRegExp reFront = QRegExp("front"); reFront.setCaseSensitivity(Qt::CaseInsensitive); QRegExp reBack = QRegExp("back"); reBack.setCaseSensitivity(Qt::CaseInsensitive); if(baseName.endsWith('f') || (reFront.indexIn(baseName) != -1)){ itemData[WizardTreeModel::FileType] = WizardTreeModel::FrontCover; }else if(baseName.endsWith('b') || (reBack.indexIn(baseName) != -1)){ itemData[WizardTreeModel::FileType] = WizardTreeModel::BackCover; }else{ itemData[WizardTreeModel::FileType] = WizardTreeModel::GeneralCover; } } mFileModel->appendRow(itemData, mFileModel->rootIndex()); } mFileView->resizeColumnToContents(0); mFileView->resizeColumnToContents(1); mFileView->resizeColumnToContents(2); } void MovieInfoPage::selectFirst(){ QModelIndex fIdx = mFileModel->index(0, 0, mFileModel->rootIndex()); if(fIdx.isValid()){ mFileView->selectionModel()->select(fIdx, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); } } void MovieInfoPage::saveData(){ mCurQuality = mQuality->value(); mCurSeriesno = mSeriesNo->value(); mCurTitle = mTitle->text(); mCurSubtitle = mSubtitle->text(); } void MovieInfoPage::restoreData(){ mQuality->setValue(mCurQuality); mSeriesNo->setValue(mCurSeriesno); mTitle->setText(mCurTitle); mSubtitle->setText(mCurSubtitle); } void MovieInfoPage::initCompleters(){ QSqlDatabase db = QSqlDatabase::database("treedb"); db.open(); QStringList series; QSqlQuery seriesQ("SELECT tseries_name FROM series", db); while(seriesQ.next()){ series << seriesQ.value(0).toString(); } mSeriesCompleterModel->setStringList(series); } void MovieInfoPage::extractTitle(){ QModelIndexList curIdxList = mFileView->selectionModel()->selectedRows(); if(!curIdxList.isEmpty()){ QString fp = curIdxList.at(0).data(WizardTreeModel::FullPathRole).toString(); QJsonDocument jDoc = Helper::streamData(fp); if(!jDoc.isNull()){ QJsonObject jObj1 = jDoc.object().value("format").toObject(); QJsonObject jObj2 = jObj1.value("tags").toObject(); QString title = jObj2.value("title").toString().toLower(); mSubtitle->setText(title); } } } void MovieInfoPage::addOld(){ QFileDialog *oldFileDlg = new QFileDialog(this, tr("Select source"), mCurrentDir); int retval = oldFileDlg->exec(); if(retval != QDialog::Accepted || oldFileDlg->selectedFiles().isEmpty()){ oldFileDlg->deleteLater(); return; } QStringList files = oldFileDlg->selectedFiles(); QString oldFile = files.first(); QFileInfo fi(oldFile); qint64 oldSize = fi.size(); QString fullPath = fi.absoluteFilePath(); QString fn = fi.fileName(); int filetype = FT_ORIGIN; //prepare item data QList itemData; itemData << fn << oldSize << filetype << QVariant() << fullPath; QModelIndexList curIdxList = mFileView->selectionModel()->selectedRows(); if(!curIdxList.isEmpty()){ QModelIndex realIdx = mProxy->mapToSource(curIdxList[0]); mFileModel->appendRow(itemData, realIdx); mFileView->expandAll(); mOrigins << fullPath; } oldFileDlg->deleteLater(); } void MovieInfoPage::guessOld(const QString &fullPath){ QFileInfo fi(fullPath); QString baseName = fi.completeBaseName(); QString fnReStr = QString("^%1").arg(baseName); QRegularExpression fnRe(fnReStr); QModelIndex parent; QDirIterator it(fi.dir()); QList itemData; while(it.hasNext()){ QFileInfo curFi = it.next(); QString curBaseName = curFi.completeBaseName(); for(int i = 0; i < mFileModel->rowCount(mFileModel->rootIndex()); ++i){ QModelIndex curIdx = mFileModel->index(i, WizardTreeModel::FileName, mFileModel->rootIndex()); if(curIdx.isValid()){ if(fnRe.match(curBaseName).hasMatch()){ if(curFi.absoluteFilePath() != fi.absoluteFilePath()){ parent = curIdx; itemData << curFi.fileName() << curFi.size() << FT_ORIGIN << QVariant() << curFi.absoluteFilePath(); mOrigins << curFi.absoluteFilePath(); mFileModel->appendRow(itemData, parent); break; } } } } } mFileView->expandAll(); } void MovieInfoPage::addFiles(){ QSettings s; QString startDir = s.value("paths/addfilespath", QDir::homePath()).toString(); QStringList files = QFileDialog::getOpenFileNames(this, tr("Select files"), startDir); if(files.isEmpty()){ return; } for(const QString &f : files){ addFile(f); } QFileInfo fi(files.at(0)); s.setValue("paths/addfilespath", fi.absolutePath()); } void MovieInfoPage::removeFile(){ QModelIndexList selected = mFileView->selectionModel()->selectedRows(); QList curSel; for(const QModelIndex &idx : selected){ curSel << QPersistentModelIndex(idx); } if(selected.isEmpty()){ return; } for(const QPersistentModelIndex &pi : curSel){ QModelIndex cur = mProxy->mapToSource(pi); if(cur.isValid()){ int type = cur.data(WizardTreeModel::FileTypeRole).toInt(); if(type == FT_ORIGIN){ mOrigins.removeAll(pi.data(WizardTreeModel::FullPathRole).toString()); }else{ for(int i = 0; i < mProxy->rowCount(pi); ++i){ QModelIndex child = mProxy->index(0, pi.column(), pi); if(child.isValid()){ int type = child.data(WizardTreeModel::FileTypeRole).toInt(); if(type == FT_ORIGIN){ mOrigins.removeAll(child.data(WizardTreeModel::FullPathRole).toString()); } } } } mFileModel->removeRow(cur.row(), cur.parent()); } } } void MovieInfoPage::toLower(){ QString newText = mSubtitle->text().toLower().trimmed(); mSubtitle->setText(newText); } void MovieInfoPage::fuzzyCheck(){ QStringList res = Helper::fuzzyCheck(mSubtitle->text()); if(!res.isEmpty()){ QString msg = QString(tr("Already have:
    ")); for(int i = 0; i < res.count() && i < 5; ++i){ msg = msg.append("
  • %1
  • ").arg(res.at(i)); } msg.append("
"); QMessageBox::information(this, tr("Matches found!"), msg); } }