diff options
author | Arno <arno@disconnect.de> | 2016-11-10 05:02:44 +0100 |
---|---|---|
committer | Arno <arno@disconnect.de> | 2016-11-10 05:02:44 +0100 |
commit | 5cde173217fd8cb1dbc21f3ac54f18e8234e709b (patch) | |
tree | 309980ee31734db8ca154694137c54a831f3e01a | |
parent | 1d05ace3bdd9cd07012116b48f847b4a118e1af9 (diff) | |
download | ShemovCleaner-5cde173217fd8cb1dbc21f3ac54f18e8234e709b.tar.gz ShemovCleaner-5cde173217fd8cb1dbc21f3ac54f18e8234e709b.tar.bz2 ShemovCleaner-5cde173217fd8cb1dbc21f3ac54f18e8234e709b.zip |
New feature: Add Origin
Since SheMov now displays origin files (i.e. source files for a
reencode), add an option here to add origin files for already archived
movies.
We guess the archived movie from the filename by cutting off the
extension and look it up in the files table.
If we find an archived movie with that filename, mark the source blue.
Deactive "Add" if we don't find one or if we already have an origin.
-rw-r--r-- | ShemovCleaner.pro | 6 | ||||
-rw-r--r-- | filewidget.cpp | 45 | ||||
-rw-r--r-- | filewidget.h | 9 | ||||
-rw-r--r-- | origindialog.cpp | 166 | ||||
-rw-r--r-- | origindialog.h | 47 |
5 files changed, 265 insertions, 8 deletions
diff --git a/ShemovCleaner.pro b/ShemovCleaner.pro index 1b3ea3b..2647e72 100644 --- a/ShemovCleaner.pro +++ b/ShemovCleaner.pro @@ -25,7 +25,8 @@ SOURCES += main.cpp\ helper.cpp \ filedisplay.cpp \ globals.cpp \ - actorwidget.cpp + actorwidget.cpp \ + origindialog.cpp HEADERS += \ filesorter.h \ @@ -38,7 +39,8 @@ HEADERS += \ helper.h \ filedisplay.h \ globals.h \ - actorwidget.h + actorwidget.h \ + origindialog.h DISTFILES += diff --git a/filewidget.cpp b/filewidget.cpp index 216cce7..4b22b77 100644 --- a/filewidget.cpp +++ b/filewidget.cpp @@ -35,6 +35,7 @@ #include "filewidget.h" #include "filesorter.h" #include "filedisplay.h" +#include "origindialog.h" #include "helper.h" #include "globals.h" @@ -91,8 +92,13 @@ void FileWidget::setupGui(){ mQOrigin.prepare("SELECT COUNT(*) FROM files_origin WHERE cmd5sum = :md5"); mQFiles = QSqlQuery(mDb); mQFiles.prepare("SELECT COUNT(*) FROM files WHERE cmd5sum = :md5"); + mQSimilar = QSqlQuery(mDb); + mQSimilar.prepare("SELECT ifiles_id, tfilename FROM files WHERE tfilename ~ :fn AND files.ifiles_id NOT IN (SELECT ifiles_id FROM files_origin WHERE ifiles_id = files.ifiles_id)"); mFileDisplay = new FileDisplay(this); + mOrignDlg = new OriginDialog(this); + connect(mOrignDlg, SIGNAL(statusMessage(QString)), this, SIGNAL(statusMessage(QString))); + connect(mOrignDlg, SIGNAL(refreshNeeded()), this, SLOT(gatherData())); mMenuBar = new QMenuBar; mToolBar = new QToolBar; mToolBar->setIconSize(QSize(16, 16)); @@ -139,6 +145,8 @@ void FileWidget::createActions(){ mPropertiesA = new QAction(QIcon(":/diaper.png"), tr("Properties..."), this); mPropertiesA->setShortcut(Qt::CTRL + Qt::Key_Return); connect(mPropertiesA, SIGNAL(triggered()), this, SLOT(properties())); + mAddAsOriginA = new QAction(QIcon(":/butt_plug.png"), tr("Add as Origin..."), this); + connect(mAddAsOriginA, SIGNAL(triggered()), this, SLOT(addAsOrigin())); QMenu *fileMenu = new QMenu(tr("&File")); fileMenu->addAction(mSelDirA); @@ -156,6 +164,7 @@ void FileWidget::createActions(){ editMenu->addAction(mDeleteA); editMenu->addSeparator(); editMenu->addAction(mPropertiesA); + editMenu->addAction(mAddAsOriginA); editMenu->addSeparator(); editMenu->addAction(Globals::instance()->action(Globals::ConfigAction)); @@ -174,10 +183,11 @@ void FileWidget::createActions(){ mToolBar->addAction(mDeleteA); mToolBar->addAction(createSeparator()); mToolBar->addAction(mPropertiesA); + mToolBar->addAction(mAddAsOriginA); mToolBar->addAction(createSeparator()); mToolBar->addAction(Globals::instance()->action(Globals::ConfigAction)); - addActions(QList<QAction*>() << mDirBackA << mDirUpA << createSeparator() << mRefreshA << mSelDirA << createSeparator() << mCopyA << mCutA << mPasteA << mDeleteA << createSeparator() << mPropertiesA); + addActions(QList<QAction*>() << mDirBackA << mDirUpA << createSeparator() << mRefreshA << mSelDirA << createSeparator() << mCopyA << mCutA << mPasteA << mDeleteA << createSeparator() << mAddAsOriginA << mPropertiesA); } void FileWidget::fileData(const QString &fullPath, const QString &md5){ @@ -201,6 +211,7 @@ void FileWidget::gatherData(){ mModel->setHorizontalHeaderLabels(QStringList() << QChar(0x26A7) << tr("Name") << tr("MIME") << tr("Duration") << tr("MD5")); QBrush redBrush(Qt::red); QBrush greenBrush(Qt::darkGreen); + QBrush blueBrush(Qt::darkBlue); QMimeDatabase db; qApp->setOverrideCursor(Qt::BusyCursor); @@ -238,9 +249,17 @@ void FileWidget::gatherData(){ fData[NameColumn]->setForeground(greenBrush); attr = Present; }else{ - fData[IconColumn]->setIcon(QIcon(":/chastity_belt.png")); - fData[NameColumn]->setForeground(redBrush); - attr = NotPresent; + QString complFn = fi.completeBaseName(); + bool hasOrig = haveOrigin(complFn); + if(hasOrig){ + fData[IconColumn]->setIcon(QIcon(":/butt_plug.png")); + fData[NameColumn]->setForeground(blueBrush); + attr = Origin; + }else{ + fData[IconColumn]->setIcon(QIcon(":/chastity_belt.png")); + fData[NameColumn]->setForeground(redBrush); + attr = NotPresent; + } } QJsonDocument jDoc = Helper::ffpmegData(fi.absoluteFilePath()); QJsonObject jObj = jDoc.object(); @@ -299,6 +318,16 @@ int FileWidget::md5Count(const QString &md5) { return retval; } +bool FileWidget::haveOrigin(const QString filename){ + bool retval = false; + mQSimilar.bindValue(":fn", filename); + mQSimilar.exec(); + while(mQSimilar.next()){ + retval = true; + } + return retval; +} + void FileWidget::readHeaderData(){ QSettings s; QByteArray headers = s.value("video/fileheaders").toByteArray(); @@ -425,6 +454,14 @@ void FileWidget::selectFirst(){ } } +void FileWidget::addAsOrigin(){ + mOrignDlg->clear(); + QModelIndex idx = mFileView->selectionModel()->selectedRows().first(); + QString fp = idx.data(FullPathRole).toString(); + mOrignDlg->setSrctData(fp); + mOrignDlg->setDstData(fp); + mOrignDlg->show(); +} void FileWidget::fileSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected){ Q_UNUSED(selected); diff --git a/filewidget.h b/filewidget.h index b9133e2..ef18603 100644 --- a/filewidget.h +++ b/filewidget.h @@ -18,12 +18,12 @@ class QAction; class QMimeData; class VideoSorter; class FileDisplay; - +class OriginDialog; class FileWidget : public QWidget { Q_OBJECT public: - enum FileAttrs { NotPresent = 0, Present = 1, NoVideo = 2, ParentDir = 3, Directory = 4 }; + enum FileAttrs { NotPresent = 0, Present = 1, NoVideo = 2, ParentDir = 3, Directory = 4, Origin = 5 }; enum CustomRoles { AttrsRole = Qt::UserRole + 1, FullPathRole = Qt::UserRole + 2, DurationRole = Qt::UserRole + 3, MD5SumRole = Qt::UserRole + 4, SecondsRole = Qt::UserRole + 5 }; enum { ColumnCount = 5 }; enum Columns { IconColumn = 0, NameColumn = 1, MimeColumn = 2, DurationColumn = 3, Md5Column = 4 }; @@ -56,6 +56,7 @@ class FileWidget : public QWidget { void cut(); void paste(); void selectFirst(); + void addAsOrigin(); protected: virtual void keyPressEvent(QKeyEvent *e); @@ -66,6 +67,7 @@ class FileWidget : public QWidget { void createActions(); void fileData(const QString &fullPath, const QString &md5); int md5Count(const QString &md5); + bool haveOrigin(const QString filename); void readHeaderData(); void writeHeaderData(); void readSettings(); @@ -84,6 +86,7 @@ class FileWidget : public QWidget { QSqlDatabase mDb; QSqlQuery mQOrigin; QSqlQuery mQFiles; + QSqlQuery mQSimilar; QMimeData *mMimeData; QAction *mSelDirA; QAction *mRefreshA; @@ -94,8 +97,10 @@ class FileWidget : public QWidget { QAction *mCutA; QAction *mPasteA; QAction *mDeleteA; + QAction *mAddAsOriginA; FileDisplay *mFileDisplay; VideoSorter *mProxy; + OriginDialog *mOrignDlg; int mFileAction; }; diff --git a/origindialog.cpp b/origindialog.cpp new file mode 100644 index 0000000..3e8bd3a --- /dev/null +++ b/origindialog.cpp @@ -0,0 +1,166 @@ +#include <QLabel> +#include <QGridLayout> +#include <QGroupBox> +#include <QPushButton> +#include <QLineEdit> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QFileInfo> +#include <QLocale> +#include <QJsonObject> +#include <QSqlDatabase> +#include <QSqlQuery> + +#include "origindialog.h" +#include "helper.h" + +OriginDialog::OriginDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) { + setupGui(); +} + +void OriginDialog::setupGui(){ + QGroupBox *origGB = new QGroupBox(tr("Origin data")); + mOrigDur = new QLineEdit; + mOrigDur->setReadOnly(true); + mOrigName = new QLineEdit; + mOrigName->setReadOnly(true); + mOrigSize = new QLineEdit; + mOrigSize->setReadOnly(true); + mOrigBitrate = new QLineEdit; + mOrigBitrate->setReadOnly(true); + mOrigMd5 = new QLineEdit; + mOrigMd5->setReadOnly(true); + mOrigMd5->setFont(QFont("courier new")); + QGridLayout *origLayout = new QGridLayout; + origLayout->addWidget(new QLabel(tr("Origin Name")), 0, 0); + origLayout->addWidget(mOrigName, 0, 1); + origLayout->addWidget(new QLabel(tr("Origin duration")), 1, 0); + origLayout->addWidget(mOrigDur, 1, 1); + origLayout->addWidget(new QLabel(tr("Origin Size")), 2, 0); + origLayout->addWidget(mOrigSize, 2, 1); + origLayout->addWidget(new QLabel(tr("Origin Bitrate")), 3, 0); + origLayout->addWidget(mOrigBitrate, 3, 1); + origLayout->addWidget(new QLabel(tr("MD5")), 4, 0); + origLayout->addWidget(mOrigMd5, 4, 1); + origGB->setLayout(origLayout); + QGroupBox *destGB = new QGroupBox(tr("Destination data")); + mDstDur = new QLineEdit; + mDstDur->setReadOnly(true); + mDstName = new QLineEdit; + mDstName->setReadOnly(true); + mDstSize = new QLineEdit; + mDstSize->setReadOnly(true); + mDstMd5 = new QLineEdit; + mDstMd5->setReadOnly(true); + mDstMd5->setFont(QFont("courier new")); + QGridLayout *dstLayout = new QGridLayout; + dstLayout->addWidget(new QLabel(tr("Destination Name")), 0, 0); + dstLayout->addWidget(mDstName, 0, 1); + dstLayout->addWidget(new QLabel(tr("Destination duration")), 1, 0); + dstLayout->addWidget(mDstDur, 1, 1); + dstLayout->addWidget(new QLabel(tr("Destination Size")), 2, 0); + dstLayout->addWidget(mDstSize, 2, 1); + dstLayout->addWidget(new QLabel(tr("MD5")), 3, 0); + dstLayout->addWidget(mDstMd5, 3, 1); + destGB->setLayout(dstLayout); + mOk = new QPushButton(tr("Add")); + connect(mOk, SIGNAL(clicked()), this, SLOT(accept())); + mCancel = new QPushButton(tr("Cancel")); + connect(mCancel, SIGNAL(clicked()), this, SLOT(reject())); + QHBoxLayout *btnLayout = new QHBoxLayout; + btnLayout->addStretch(); + btnLayout->addWidget(mOk); + btnLayout->addWidget(mCancel); + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(origGB); + mainLayout->addWidget(destGB); + mainLayout->addLayout(btnLayout); + setLayout(mainLayout); + setMinimumWidth(400); + mLineEdits << mOrigBitrate << mOrigDur << mOrigMd5 << mOrigName << mOrigSize << mDstDur << mDstMd5 << mDstName << mDstSize; +} + +void OriginDialog::setSrctData(const QString &absolutefn){ + QFileInfo fi(absolutefn); + if(fi.exists() && fi.isFile()){ + mOrigName->setText(fi.fileName()); + QLocale l; + mOrigSize->setText(l.toString(fi.size())); + mSize = fi.size(); + QJsonDocument jDoc = Helper::ffpmegData(absolutefn); + QJsonObject jObj = jDoc.object(); + QJsonValue durationV = jObj["format"].toObject()["duration"]; + qint64 seconds = durationV.toVariant().toDouble(); + Helper::Duration dur = Helper::Duration(seconds); + QString duration = dur.toString(); + mOrigDur->setText(duration); + QJsonValue brv = jObj["format"].toObject()["bit_rate"]; + mBitrate = brv.toVariant().toLongLong(); + QString brString = QString("%1 kb/s").arg(l.toString(mBitrate / 1000)); + mOrigBitrate->setText(brString); + mMd5 = Helper::md5Sum(absolutefn); + mOrigMd5->setText(mMd5); + } +} + +void OriginDialog::setDstData(const QString &absolutefn){ + QFileInfo fi(absolutefn); + QSqlDatabase db = QSqlDatabase::database("shemovdb"); + QSqlQuery dstQ(db); + dstQ.prepare("SELECT tfilename, iduration, bisize, cmd5sum, ifiles_id FROM files WHERE tfilename ~ :fnb"); + dstQ.bindValue(":fnb", fi.completeBaseName()); + dstQ.exec(); + while(dstQ.next()){ + mDstName->setText(dstQ.value(0).toString()); + Helper::Duration dur = Helper::Duration(dstQ.value(1).toDouble()); + mDstDur->setText(dur.toString()); + QLocale l; + mDstSize->setText(l.toString(dstQ.value(2).toLongLong())); + mDstMd5->setText(dstQ.value(3).toString()); + mFileId = dstQ.value(4).toInt(); + } + if(mDstName->text().isEmpty()){ + mOk->setEnabled(false); + mDstName->setText(tr("(n/a)")); + return; + } + bool originExists = false; + QSqlQuery origExistsQ(db); + origExistsQ.prepare("SELECT COUNT(*) FROM files_origin where ifiles_id = :fid"); + origExistsQ.bindValue(":fid", mFileId); + origExistsQ.exec(); + while(origExistsQ.next()){ + originExists = origExistsQ.value(0).toInt() == 0 ? false : true; + } + if(originExists){ + mOk->setEnabled(false); + return; + } + mOk->setEnabled(true); +} + +void OriginDialog::clear(){ + foreach(QLineEdit *le, mLineEdits){ + le->clear(); + } +} + +void OriginDialog::accept(){ + QSqlDatabase db = QSqlDatabase::database("shemovdb"); + QSqlQuery insertQ(db); + insertQ.prepare("INSERT INTO files_origin (ifiles_id, tname, cmd5sum, bisize, ibitrate) VALUES(:fid, :name, :md5, :size, :bitrate)"); + insertQ.bindValue(":fid", mFileId); + insertQ.bindValue(":name", mOrigName->text()); + insertQ.bindValue(":md5", mMd5); + insertQ.bindValue(":size", mSize); + insertQ.bindValue(":bitrate", mBitrate); + if(insertQ.exec()){ + QString msg = QString(tr("Inserted %1 as origin to %2")).arg(mOrigName->text()).arg(mFileId); + emit statusMessage(msg); + emit refreshNeeded(); + }else{ + QString msg = QString(tr("Failed to add %1 as origin")).arg(mOrigName->text()); + emit statusMessage(msg); + } + QDialog::accept(); +} diff --git a/origindialog.h b/origindialog.h new file mode 100644 index 0000000..dd9cb3f --- /dev/null +++ b/origindialog.h @@ -0,0 +1,47 @@ +#ifndef ORIGINDIALOG_H +#define ORIGINDIALOG_H + +#include <QDialog> +#include <QVector> + +class QLineEdit; +class QPushButton; + +class OriginDialog : public QDialog { + Q_OBJECT + public: + explicit OriginDialog(QWidget *parent = 0, Qt::WindowFlags f = 0); + + signals: + void statusMessage(const QString &msg); + void refreshNeeded(); + + public slots: + void setSrctData(const QString &absolutefn); + void setDstData(const QString &absolutefn); + void clear(); + virtual void accept(); + + private: + void setupGui(); + QLineEdit *mOrigName; + QLineEdit *mOrigDur; + QLineEdit *mOrigSize; + QLineEdit *mOrigBitrate; + QLineEdit *mOrigMd5; + QLineEdit *mDstName; + QLineEdit *mDstDur; + QLineEdit *mDstSize; + QLineEdit *mDstMd5; + QVector<QLineEdit*> mLineEdits; + QPushButton *mOk; + QPushButton *mCancel; + qint64 mSeconds; + qint64 mSize; + qint64 mBitrate; + QString mMd5; + int mFileId; + +}; + +#endif // ORIGINDIALOG_H |