diff options
-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 |