From 8eba6e7f033617f3e7ea3bd9913105df0de74ae2 Mon Sep 17 00:00:00 2001 From: Arno Date: Sat, 31 Jul 2010 16:26:10 +0200 Subject: Implement FilePropertiesDialog Implemented a dialog for file properties. When the mime type says it's a video, fork ffprobe to read the properties of all streams and show them in a QTreeView powered by a SmTreeModel. If the mime type is image, use QImage to read some properties and show them in the same dialog. This commit introduces the new class FilePropertiesDialog. I also had to implement a copy constructor for SmTreeItem. It obsoletes classes ActorWidget, ActorModel and MoviePropertiesDialog. --- actormodel.cpp | 117 ------------------------- actormodel.h | 37 -------- actorwidget.cpp | 64 -------------- actorwidget.h | 42 --------- configurationdialog.cpp | 12 +++ configurationdialog.h | 1 + filepropertiesdialog.cpp | 99 +++++++++++++++++++++ filepropertiesdialog.h | 36 ++++++++ filestreemodel.cpp | 76 ++++++++++++++++ filestreemodel.h | 4 + filestreewidget.cpp | 33 +++++++ filestreewidget.h | 1 + helper.cpp | 17 ++++ helper.h | 1 + moviepropertiesdialog.cpp | 214 ---------------------------------------------- moviepropertiesdialog.h | 45 ---------- shemov.cpp | 6 ++ shemov.h | 1 + shemov.pro | 16 ++-- smtreeitem.cpp | 12 +++ smtreeitem.h | 1 + 21 files changed, 306 insertions(+), 529 deletions(-) delete mode 100644 actormodel.cpp delete mode 100644 actormodel.h delete mode 100644 actorwidget.cpp delete mode 100644 actorwidget.h create mode 100644 filepropertiesdialog.cpp create mode 100644 filepropertiesdialog.h delete mode 100644 moviepropertiesdialog.cpp delete mode 100644 moviepropertiesdialog.h diff --git a/actormodel.cpp b/actormodel.cpp deleted file mode 100644 index 14edcf8..0000000 --- a/actormodel.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - 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 "actormodel.h" - -ActorModel::ActorModel() {}; - -QModelIndex ActorModel::index(int row, int column, const QModelIndex &) const { - if((column != 0) || (row >= mItems.size()) || row < 0){ - return QModelIndex(); - } - return createIndex(row, 0, 0); -} - -QModelIndex ActorModel::index(const QVariant &item) const { - if(item == QVariant()){ - return QModelIndex(); - } - QString sItem = item.toString(); - for(int i = 0; i < mItems.size(); ++i){ - if(mItems.at(i) == sItem){ - return createIndex(i, 0, 0); - } - } - return QModelIndex(); -} - -int ActorModel::rowCount(const QModelIndex &) const { - return mItems.size(); -} - -QVariant ActorModel::data(const QModelIndex &index, int role) const { - if(!index.isValid() || (index.column() > 0) || (index.row() > mItems.size())){ - return QVariant(); - } - switch (role) { - case Qt::DisplayRole: - return mItems.at(index.row()); - break; - case Qt::DecorationRole: - return QIcon(":/dildo.png"); - break; - } - return QVariant(); -} - -bool ActorModel::insertRows(int row, int count, const QModelIndex &){ - beginInsertRows(QModelIndex(), row, row + count - 1); - for(int i = row; i < (row + count); ++i){ - mItems.insert(i, QString()); - } - endInsertRows(); - return true; -} - -bool ActorModel::removeRows(int row, int count, const QModelIndex &){ - if((row > mItems.size()) || ((row + count) > mItems.size())){ - return false; - } - beginRemoveRows(QModelIndex(), row, row + (count - 1)); - for(int i = row; i < (row + count); ++i){ - mItems.removeAt(i); - } - endRemoveRows(); - return true; -} - -bool ActorModel::setData(const QModelIndex &idx, const QVariant &data, int role){ - if(!idx.isValid() || (idx.column() != 0) || (role != Qt::EditRole)){ - return false; - } - mItems[idx.row()] = data.toString(); - qSort(mItems); - dataChanged(index(0, 0), index((mItems.size() - 1), 0)); - return true; -} - -bool ActorModel::addItem(const QVariant &data){ - if(mItems.contains(data.toString())){ - return false; - } - bool success = false; - if(insertRows(0, 1, QModelIndex())){ - QModelIndex idx = index(0, 0); - if(idx.isValid()){ - success = setData(idx, data, Qt::EditRole); - } - } - return success; -} - -bool ActorModel::removeItem(const QVariant &data){ - QModelIndex idx = index(data); - if(!idx.isValid()){ - return false; - } - bool retval = removeRows(idx.row(), 1, QModelIndex()); - if(retval){ - int lidx = mItems.indexOf(data.toString()); - if(lidx != -1){ - mItems.removeAt(lidx); - } - } - return retval; -} - -void ActorModel::clear() { - removeRows(0, mItems.size(), QModelIndex()); - mItems.clear(); -} - diff --git a/actormodel.h b/actormodel.h deleted file mode 100644 index 9f15423..0000000 --- a/actormodel.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - 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 ACTORMODEL_H -#define ACTORMODEL_H - -#include -#include - -class ActorModel : public QAbstractItemModel { - public: - ActorModel(); - ~ActorModel() {}; - QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; - QModelIndex index(const QVariant &item) const; - QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &) const { return 1; }; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - bool insertRows(int row, int count, const QModelIndex &parent); - bool removeRows(int row, int count, const QModelIndex &parent); - bool setData(const QModelIndex &idx, const QVariant &data, int role = Qt::EditRole); - bool addItem(const QVariant &data); - bool removeItem(const QVariant &data); - void clear(); - const QList items() const { return mItems; }; - - private: - QList mItems; -}; - -#endif - diff --git a/actorwidget.cpp b/actorwidget.cpp deleted file mode 100644 index 2a98dfd..0000000 --- a/actorwidget.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - 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 "actorwidget.h" -#include "actormodel.h" - -ActorWidget::ActorWidget(QWidget *parent) : QWidget(parent) { - QVBoxLayout *mainLayout = new QVBoxLayout; - - QLabel *l1 = new QLabel(tr("Actors")); - - mModel = new ActorModel; - mView = new QTreeView; - mView->setModel(mModel); - mView->setRootIsDecorated(false); - mView->setSelectionMode(QAbstractItemView::ExtendedSelection); - mView->setHeaderHidden(true); - - QHBoxLayout *buttonLayout = new QHBoxLayout; - mRemoveActor = new QPushButton(tr("&Remove selected")); - connect(mRemoveActor, SIGNAL(clicked()), this, SLOT(removeActor())); - mClearAll = new QPushButton(tr("Remove &all")); - connect(mClearAll, SIGNAL(clicked()), this, SLOT(clear())); - buttonLayout->addStretch(); - buttonLayout->addWidget(mClearAll); - buttonLayout->addWidget(mRemoveActor); - - mainLayout->addWidget(l1); - mainLayout->addWidget(mView); - mainLayout->addLayout(buttonLayout); - mainLayout->setContentsMargins(0, 0, 0, 0); - - setLayout(mainLayout); -} - -const QStringList ActorWidget::actors(){ - return mModel->items(); -} - -void ActorWidget::addActor(const QString &actor) { - mModel->addItem(actor); -} - -void ActorWidget::clear() { - mModel->clear(); -} - -void ActorWidget::removeActor() { - QModelIndexList idxs = mView->selectionModel()->selectedRows(); - foreach(QModelIndex idx, idxs){ - mModel->removeItem(idx.data()); - } -} - diff --git a/actorwidget.h b/actorwidget.h deleted file mode 100644 index 864d300..0000000 --- a/actorwidget.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - 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 ACTORWIDGET_H -#define ACTORWIDGET_H - -#include -#include - -class QPushButton; -class QHBoxLayout; -class QTreeView; -class ActorModel; - -class ActorWidget : public QWidget { - Q_OBJECT - Q_PROPERTY(QStringList actors READ actors()); - public: - ActorWidget(QWidget *parent = 0); - ~ActorWidget() {}; - const QStringList actors(); - - public slots: - void addActor(const QString &actor); - void clear(); - - private slots: - void removeActor(); - - private: - QPushButton *mRemoveActor; - QPushButton *mClearAll; - QTreeView *mView; - ActorModel *mModel; -}; - -#endif - diff --git a/configurationdialog.cpp b/configurationdialog.cpp index f453700..6d6899c 100644 --- a/configurationdialog.cpp +++ b/configurationdialog.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "configurationdialog.h" #include "programconfigurator.h" @@ -52,6 +53,11 @@ ConfigurationDialog::ConfigurationDialog(QWidget *parent, Qt::WindowFlags f) : Q mBurnDir->setCompleter(fsCompleter); miscGrid->addWidget(miscl3, 2, 0); miscGrid->addWidget(mBurnDir, 2, 1); + QLabel *miscl4 = new QLabel(tr("Path to ffprobe")); + mFfProbePath = new QLineEdit; + mFfProbePath->setCompleter(fsCompleter); + miscGrid->addWidget(miscl4, 3, 0); + miscGrid->addWidget(mFfProbePath, 3, 1); mTab->addTab(miscWidget, tr("Misc. settings")); // movie viewer @@ -124,6 +130,7 @@ void ConfigurationDialog::readSettings(){ } mArchiveDir->setText(s.value("paths/archivedir").toString()); mBurnDir->setText(s.value("paths/burn").toString()); + mFfProbePath->setText(s.value("paths/ffprobe").toString()); //read database mDatabaseHost->setText(s.value("database/hostname").toString()); @@ -140,6 +147,11 @@ void ConfigurationDialog::writeSettings(){ s.setValue("ui/folderIcon", mIconForFolder->currentText()); s.setValue("paths/archivedir", mArchiveDir->text()); s.setValue("paths/burn", mBurnDir->text()); + QString ffprobe = mFfProbePath->text(); + QFileInfo ffProbeInfo(ffprobe); + if(ffProbeInfo.exists() && ffProbeInfo.isExecutable()){ + s.setValue("paths/ffprobe", ffprobe); + } //write database s.setValue("database/hostname", mDatabaseHost->text()); diff --git a/configurationdialog.h b/configurationdialog.h index 1575f41..da04c7c 100644 --- a/configurationdialog.h +++ b/configurationdialog.h @@ -38,6 +38,7 @@ class ConfigurationDialog : public QDialog { ProgramConfigurator *mPicConfig; QLineEdit *mArchiveDir; QLineEdit *mBurnDir; + QLineEdit *mFfProbePath; QLineEdit *mDatabaseHost; QLineEdit *mDatabaseName; QLineEdit *mDatabaseUsername; diff --git a/filepropertiesdialog.cpp b/filepropertiesdialog.cpp new file mode 100644 index 0000000..969eac4 --- /dev/null +++ b/filepropertiesdialog.cpp @@ -0,0 +1,99 @@ +/* + 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 "filepropertiesdialog.h" +#include "smtreemodel.h" +#include "smtreeitem.h" +#include "helper.h" + +FilePropertiesDialog::FilePropertiesDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){ + //main layout + QVBoxLayout *mainLayout = new QVBoxLayout; + + //description + mDescriptionLabel = new QLabel(tr("Properties for [none]")); + mainLayout->addWidget(mDescriptionLabel); + + //the view + model + mModel = new SmTreeModel((QStringList() << QString() << QString()), this); + mView = new QTreeView; + mView->setHeaderHidden(true); + mView->setEditTriggers(QAbstractItemView::NoEditTriggers); + mView->setModel(mModel); + mainLayout->addWidget(mView); + + //ok button + QHBoxLayout *buttonLayout = new QHBoxLayout; + mClose = new QPushButton(tr("Close")); + connect(mClose, SIGNAL(clicked()), this, SLOT(accept())); + buttonLayout->setAlignment(Qt::AlignCenter); + buttonLayout->addWidget(mClose); + mainLayout->addLayout(buttonLayout); + + setLayout(mainLayout); + setMinimumWidth(450); +} + +void FilePropertiesDialog::setFileName(const QString &fileName){ + QString text = QString(tr("Properties for %1")).arg(fileName); + mDescriptionLabel->setText(text); + setWindowTitle(text); +} + +void FilePropertiesDialog::setStreamData(const QList > &streamData){ + SmTreeItem *root = new SmTreeItem(2); + for(int i = 0; i < streamData.size(); ++i){ + QList titleData; + QString title = QString(tr("Stream %1")).arg(QString::number(i)); + titleData << title << QVariant(); + SmTreeItem *titleItem = new SmTreeItem(titleData, root); + root->appendChild(titleItem); + QMap::const_iterator it = streamData.at(i).constBegin(); + while(it != streamData.at(i).constEnd()){ + QList itemData; + if(it.key() == "duration" && it.value() != "N/A"){ + qint64 duration = it.value().toFloat(); + itemData << it.key() << Helper::durationFromSecs(duration); + }else{ + itemData << it.key() << it.value(); + } + SmTreeItem *item = new SmTreeItem(itemData, titleItem); + titleItem->appendChild(item); + ++it; + } + } + mModel->setRoot(root); + mView->expandAll(); + mView->resizeColumnToContents(0); + mView->resizeColumnToContents(1); +} + +void FilePropertiesDialog::addData(const QString &caption, const QMap &data){ + SmTreeItem *root = new SmTreeItem(*mModel->root()); + QList titleData; + titleData << caption << QVariant(); + SmTreeItem *titleItem = new SmTreeItem(titleData, root); + root->appendChild(titleItem); + QMap::const_iterator it = data.constBegin(); + while(it != data.constEnd()){ + QList itemData; + itemData << it.key() << it.value(); + SmTreeItem *item = new SmTreeItem(itemData, titleItem); + titleItem->appendChild(item); + ++it; + } + mModel->setRoot(root); + mView->expandAll(); + mView->resizeColumnToContents(0); + mView->resizeColumnToContents(1); +} diff --git a/filepropertiesdialog.h b/filepropertiesdialog.h new file mode 100644 index 0000000..a4f5da0 --- /dev/null +++ b/filepropertiesdialog.h @@ -0,0 +1,36 @@ +/* + 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 FILEPROPERTIESDIALOG_H +#define FILEPROPERTIESDIALOG_H + +#include +#include +#include + +class QPushButton; +class QTreeView; +class QLabel; +class SmTreeModel; + +class FilePropertiesDialog : public QDialog +{ + Q_OBJECT + public: + explicit FilePropertiesDialog(QWidget *parent = 0, Qt::WindowFlags f = 0); + void setFileName(const QString &fileName); + void setStreamData(const QList > &streamData); + void addData(const QString &caption, const QMap &data); + + private: + QTreeView *mView; + QPushButton *mClose; + QLabel *mDescriptionLabel; + SmTreeModel *mModel; +}; + +#endif // FILEPROPERTIESDIALOG_H diff --git a/filestreemodel.cpp b/filestreemodel.cpp index 1f224fd..9c17084 100644 --- a/filestreemodel.cpp +++ b/filestreemodel.cpp @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include "filestreemodel.h" #include "smtreeitem.h" @@ -235,6 +238,79 @@ QHash FilesTreeModel::filesBySeriesPartId(int seriesPartId){ return retval; } +QList > FilesTreeModel::streamInfo(const QModelIndex &idx){ + QList > retval; + if(!idx.isValid()){ + return retval; + } + QSettings s; + QString ffProbe = s.value("paths/ffprobe").toString(); + QString fullPath = idx.data(FullPathRole).toString(); + QStringList args; + args << "-show_streams" << fullPath; + QProcess ffproc; + ffproc.start(ffProbe, args); + if(!ffproc.waitForStarted()){ + return retval; + } + ffproc.waitForFinished(); + QByteArray ffData = ffproc.readAllStandardOutput(); + QList lines = ffData.split('\n'); + QMap current; + foreach(QString l, lines){ + if(l.startsWith("[STREAM]")){ + continue; + } + if(l.startsWith("[/STREAM]")){ + retval << current; + current.clear(); + continue; + } + QStringList parts = l.split('='); + if(parts.size() == 2){ + current.insert(parts.at(0), parts.at(1)); + } + } + return retval; +} + +QMap FilesTreeModel::pictureInfo(const QModelIndex &idx){ + QMap retval; + if(!idx.isValid()){ + return retval; + } + QString fullPath = idx.data(FullPathRole).toString(); + QImage img(fullPath); + if(img.isNull()){ + return retval; + } + retval.insert("Width", QString::number(img.width())); + retval.insert("Height", QString::number(img.height())); + retval.insert("Colors", QString::number(img.colorCount())); + retval.insert("Color depth", QString::number(img.depth())); + retval.insert("Byte count", QString::number(img.byteCount())); + retval.insert("Bytes per line", QString::number(img.bytesPerLine())); + retval.insert("Alpha channel", img.hasAlphaChannel() ? tr("yes") : tr("no")); + retval.insert("Gray scale", img.isGrayscale() ? tr("yes") : tr("no")); + return retval; +} + +QMap FilesTreeModel::pictureMetaInfo(const QModelIndex &idx){ + QMap retval; + if(!idx.isValid()){ + return retval; + } + QString fullPath = idx.data(FullPathRole).toString(); + QImage img(fullPath); + if(img.isNull()){ + return retval; + } + foreach(QString v, img.textKeys()){ + retval.insert(v, img.text(v)); + } + return retval; +} + bool FilesTreeModel::addFile(const QString &fullPath, int type, int quality, int filePart, int seriesPartId, int dvd){ QFileInfo fi(fullPath); qint64 size = fi.size(); diff --git a/filestreemodel.h b/filestreemodel.h index 2408e35..bea1d5c 100644 --- a/filestreemodel.h +++ b/filestreemodel.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "smtreemodel.h" @@ -37,6 +38,9 @@ class FilesTreeModel : public SmTreeModel { bool setData(const QModelIndex &index, const QVariant &value, int role); Qt::ItemFlags flags(const QModelIndex &index) const; QHash filesBySeriesPartId(int seriesPartId); + QList > streamInfo(const QModelIndex &idx); + QMap pictureInfo(const QModelIndex &idx); + QMap pictureMetaInfo(const QModelIndex &idx); //file manipulation bool addFile(const QString &fullPath, int type, int quality, int filePart, int seriesPartId, int dvd = -1); diff --git a/filestreewidget.cpp b/filestreewidget.cpp index a348ac4..3161e57 100644 --- a/filestreewidget.cpp +++ b/filestreewidget.cpp @@ -28,6 +28,7 @@ #include "seriestreemodel.h" #include "helper.h" #include "pictureviewer.h" +#include "filepropertiesdialog.h" FilesTreeWidget::FilesTreeWidget(QWidget *parent) : QWidget(parent), mSelectedSize(0){ //the view @@ -158,6 +159,38 @@ void FilesTreeWidget::moveToDirectory(){ } } +void FilesTreeWidget::fileProperties(){ + QModelIndexList selected = mView->selectionModel()->selectedRows(); + if(selected.isEmpty()){ + return; + } + QModelIndex real = mProxy->mapToSource(selected.at(0)); + if(real.isValid()){ + int dvd = real.data(FilesTreeModel::DvdNoRole).toInt(); + if(dvd != -1){ + QMessageBox::critical(this, tr("Error"), tr("File is not available!")); + return; + } + QString fullPath = real.data(FilesTreeModel::FullPathRole).toString(); + QString mimeType = Helper::mimeType(fullPath); + FilePropertiesDialog dlg(this); + dlg.setFileName(real.data(FilesTreeModel::FileNameRole).toString()); + if(mimeType.startsWith("video")){ + QList > fileData = mModel->streamInfo(real); + dlg.setStreamData(fileData); + }else if(mimeType.startsWith("image")){ + QMap imageData = mModel->pictureInfo(real); + dlg.addData("Image data", imageData); + QMap textData = mModel->pictureMetaInfo(real); + if(!textData.isEmpty()){ + dlg.addData("Meta data", textData); + } + } + dlg.exec(); + } + +} + void FilesTreeWidget::fileSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous){ Q_UNUSED(previous); int seriesPartId = current.data(FilesTreeModel::SeriesPartIdRole).toInt(); diff --git a/filestreewidget.h b/filestreewidget.h index c11431b..4afa20a 100644 --- a/filestreewidget.h +++ b/filestreewidget.h @@ -34,6 +34,7 @@ class FilesTreeWidget : public QWidget { void setDvdNo(); void removeFiles(); void moveToDirectory(); + void fileProperties(); private slots: void fileSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous); diff --git a/helper.cpp b/helper.cpp index 9be7066..dff3584 100644 --- a/helper.cpp +++ b/helper.cpp @@ -15,6 +15,8 @@ #include #include +#include + #include "helper.h" namespace Helper { @@ -147,6 +149,21 @@ namespace Helper { return qMakePair(programData.value("path").toString(), programData.value("args").toStringList()); } + QString durationFromSecs(qint64 secs){ + int minutes = secs / 60; + int hours = 0; + int seconds = 0; + if(minutes > 60){ + hours = minutes / 60; + minutes -= hours * 60; + } + seconds = secs - hours * 60 * 60 - minutes * 60; + seconds = (seconds > 60) ? 59 : seconds; + QByteArray retval(10, '\0'); + ::snprintf(retval.data(), 9, "%.2d:%.2d:%.2d", hours, minutes, seconds); + return retval; + } + bool StringListContains::operator()(const QString s, const QString &part) const { return s.contains(part); } diff --git a/helper.h b/helper.h index 62919bb..96816b2 100644 --- a/helper.h +++ b/helper.h @@ -23,6 +23,7 @@ namespace Helper { bool removeFromArchive(const QString &filename, const QString &md5); const QString createArchivePath(const QString &path, const QString &md5, bool withMd5 = false); QPair programData(const QString &prefix, const QString &preferred = QString()); + QString durationFromSecs(qint64 secs); class StringListContains : public std::binary_function { public: bool operator()(const QString s, const QString &part) const; diff --git a/moviepropertiesdialog.cpp b/moviepropertiesdialog.cpp deleted file mode 100644 index 843c447..0000000 --- a/moviepropertiesdialog.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - 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 "moviepropertiesdialog.h" -#include "actormodel.h" -#include "helper.h" - -MoviePropertiesDialog::MoviePropertiesDialog(int movid, QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), mId(movid), mIndex(-1){ - //gather data - covers(); - QSqlQuery q1; - q1.prepare("SELECT ttitle, tfilename, cmd5sum, bisize, genre.tgenrename, iquality, idvd FROM movies, genre WHERE movies.igenreid = genre.igenreid AND movies.imovid = :id"); - q1.bindValue(":id", mId); - q1.exec(); - QString title, filename, md5, genre; - quint64 size(0); - qint32 quality, dvd; - quality = dvd = 0; - q1.exec(); - while(q1.next()){ - title = q1.value(0).toString(); - filename = q1.value(1).toString(); - md5 = q1.value(2).toString(); - genre = q1.value(4).toString(); - size = q1.value(3).toLongLong(); - quality = q1.value(5).toInt(); - dvd = q1.value(6).toInt(); - } - //QStringList actors; - mActorModel = new ActorModel; - QSqlQuery q2; - q2.prepare("SELECT tactorname FROM actor, movieactormap WHERE movieactormap.iactorid = actor.iactorid AND movieactormap.imovid = :id"); - q2.bindValue(":id", mId); - q2.exec(); - while(q2.next()){ - //actors << q2.value(0).toString(); - mActorModel->addItem(q2.value(0)); - } - //layout - QVBoxLayout *mainLayout = new QVBoxLayout; - mView = new QGraphicsView; - mScene = new QGraphicsScene(this); - mView->setScene(mScene); - mainLayout->addWidget(mView); - - //cover buttons - QHBoxLayout *buttonPicLayout = new QHBoxLayout; - mPrev = new QPushButton(tr("Previous")); - connect(mPrev, SIGNAL(clicked()), this, SLOT(previousCover())); - mNext = new QPushButton(tr("Next")); - connect(mNext, SIGNAL(clicked()), this, SLOT(nextCover())); - buttonPicLayout->addWidget(mPrev); - buttonPicLayout->addStretch(); - buttonPicLayout->addWidget(mNext); - mainLayout->addLayout(buttonPicLayout); - - //actors - mActors = new QTreeView; - mActors->setRootIsDecorated(false); - mActors->setHeaderHidden(true); - mActors->setModel(mActorModel); - - //properties - QGridLayout *propertiesGrid = new QGridLayout; - QFont font = qApp->font(); - font.setWeight(QFont::Bold); - QLabel *l1 = new QLabel("Genre"); - l1->setFont(font); - QLabel *l2 = new QLabel(genre); - propertiesGrid->addWidget(l1, 0, 0); - propertiesGrid->addWidget(l2, 0, 1); - QLabel *l3 = new QLabel(tr("Title")); - l3->setFont(font); - QLabel *l4 = new QLabel(title); - propertiesGrid->addWidget(l3, 1, 0); - propertiesGrid->addWidget(l4, 1, 1); - QLabel *l5 = new QLabel(tr("Filename")); - l5->setFont(font); - QLabel *l6 = new QLabel(filename); - propertiesGrid->addWidget(l5, 2, 0); - propertiesGrid->addWidget(l6, 2, 1); - QLabel *l7 = new QLabel(tr("MD5")); - l7->setFont(font); - QLabel *l8 = new QLabel(md5); - propertiesGrid->addWidget(l7, 3, 0); - propertiesGrid->addWidget(l8, 3, 1); - QLabel *l9 = new QLabel(tr("Size")); - l9->setFont(font); - QLocale l; - QLabel *l10 = new QLabel(l.toString(size)); - propertiesGrid->addWidget(l9, 4, 0); - propertiesGrid->addWidget(l10, 4, 1); - QLabel *l11 = new QLabel(tr("Quality")); - l11->setFont(font); - QLabel *l12 = new QLabel(QString::number(quality)); - propertiesGrid->addWidget(l11, 5, 0); - propertiesGrid->addWidget(l12, 5, 1); - QLabel *l13 = new QLabel(tr("Archived")); - l13->setFont(font); - QLabel *l14 = new QLabel; - if(dvd < 0){ - l14->setText(tr("No - local")); - }else{ - QString s = QString(tr("On DVD #%1")).arg(QString::number(dvd)); - l14->setText(s); - } - propertiesGrid->addWidget(l13, 6, 0); - propertiesGrid->addWidget(l14, 6, 1); - QHBoxLayout *actorsPropertiesLayout = new QHBoxLayout; - actorsPropertiesLayout->addWidget(mActors); - actorsPropertiesLayout->addLayout(propertiesGrid); - mainLayout->addLayout(actorsPropertiesLayout); - - //close button - mClose = new QPushButton(tr("Close")); - connect(mClose, SIGNAL(clicked()), this, SLOT(reject())); - QHBoxLayout *closeButtonLayout = new QHBoxLayout; - closeButtonLayout->addStretch(); - closeButtonLayout->addWidget(mClose); - closeButtonLayout->addStretch(); - mainLayout->addLayout(closeButtonLayout); - - setLayout(mainLayout); - QString winTitle = QString("%1 - Properties of %2").arg(qApp->applicationName()).arg(title); - setWindowTitle(winTitle); - - if(!mCovers.isEmpty()){ - mIndex = 0; - } - setCover(mIndex); - -} - -MoviePropertiesDialog::~MoviePropertiesDialog() { - delete mActorModel; -} - -void MoviePropertiesDialog::setCover(int index){ - mScene->clear(); - if((index < 0) || (index >= mCovers.size())){ - QGraphicsTextItem *item = new QGraphicsTextItem(tr("No covers")); - QFont font = QFont("Courier new", 30 , QFont::Bold); - item->setFont(font); - item->setDefaultTextColor(Qt::red); - item->rotate(45); - mScene->addItem(item); - item->setPos(0, 0); - mNext->setEnabled(false); - mPrev->setEnabled(false); - }else{ - QPixmap pm(mCovers.at(index)); - QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pm); - mScene->addItem(item); - item->setPos(0, 0); - } -} - -void MoviePropertiesDialog::nextCover(){ - if(mIndex < 0){ - return; - } - ++mIndex; - if(mIndex >= mCovers.size()){ - mIndex = 0; - } - setCover(mIndex); -} - -void MoviePropertiesDialog::previousCover(){ - if(mIndex < 0){ - return; - } - --mIndex; - if(mIndex < 0){ - mIndex = mCovers.size() - 1; - } - setCover(mIndex); -} - -void MoviePropertiesDialog::covers(){ - QSqlQuery q; - q.prepare("SELECT tfilename, cmd5sum FROM covers WHERE imovid = :id"); - q.bindValue(":id", mId); - q.exec(); - while(q.next()){ - QString path = Helper::createArchivePath(q.value(0).toString(), q.value(1).toString()); - QFileInfo fi(path); - if(fi.exists()){ - mCovers << path; - } - } -} - diff --git a/moviepropertiesdialog.h b/moviepropertiesdialog.h deleted file mode 100644 index 2bf0fbf..0000000 --- a/moviepropertiesdialog.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - 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 MOVIEPROPERTIESDIALOG_H -#define MOVIEPROPERTIESDIALOG_H - -#include - -class QGraphicsView; -class QGraphicsScene; -class QPushButton; -class ActorModel; -class QTreeView; - -class MoviePropertiesDialog : public QDialog { - Q_OBJECT - public: - MoviePropertiesDialog(int movid, QWidget *parent = 0, Qt::WindowFlags f = 0); - ~MoviePropertiesDialog(); - - private slots: - void setCover(int index); - void nextCover(); - void previousCover(); - - private: - void covers(); - QGraphicsView *mView; - QGraphicsScene *mScene; - QPushButton *mNext; - QPushButton *mPrev; - QPushButton *mClose; - QTreeView *mActors; - ActorModel *mActorModel; - int mId; - int mIndex; - QStringList mCovers; -}; - -#endif - diff --git a/shemov.cpp b/shemov.cpp index 1c180b7..36b0f1f 100644 --- a/shemov.cpp +++ b/shemov.cpp @@ -373,6 +373,8 @@ void SheMov::createActions(){ connect(mSetDvdNoA, SIGNAL(triggered()), mATree->filesWidget(), SLOT(setDvdNo())); mDeleteFilesFromTreeA = new QAction(tr("Delete file(s)..."), this); connect(mDeleteFilesFromTreeA, SIGNAL(triggered()), mATree->filesWidget(), SLOT(removeFiles())); + mFilePropertiesA = new QAction(tr("Properties..."), this); + connect(mFilePropertiesA, SIGNAL(triggered()), mATree->filesWidget(), SLOT(fileProperties())); // misc mOpenWithMapperFS = new QSignalMapper(this); @@ -496,6 +498,10 @@ void SheMov::createMenus(){ sep8->setSeparator(true); mATree->filesWidget()->filesTree()->addAction(sep8); mATree->filesWidget()->filesTree()->addAction(mDeleteFilesFromTreeA); + QAction *sep9 = new QAction(this); + sep9->setSeparator(true); + mATree->filesWidget()->filesTree()->addAction(sep9); + mATree->filesWidget()->filesTree()->addAction(mFilePropertiesA); } void SheMov::createOpenWithMenuFS(){ diff --git a/shemov.h b/shemov.h index 2b90b25..24e00dc 100644 --- a/shemov.h +++ b/shemov.h @@ -104,6 +104,7 @@ class SheMov : public QMainWindow { QAction *mMoveFilesA; QAction *mSetDvdNoA; QAction *mDeleteFilesFromTreeA; + QAction *mFilePropertiesA; QActionGroup *mOpenWithGroupFS; QActionGroup *mOpenWithGroupAV; diff --git a/shemov.pro b/shemov.pro index 5173801..a58d4ca 100644 --- a/shemov.pro +++ b/shemov.pro @@ -17,16 +17,13 @@ SOURCES = main.cpp \ messagedialog.cpp \ configurationdialog.cpp \ textenterdialog.cpp \ - moviepropertiesdialog.cpp \ statisticsdialog.cpp \ - actorwidget.cpp \ - actormodel.cpp \ programconfigurator.cpp \ pictureviewer.cpp \ pictureviewerinfoitem.cpp \ smtreeitem.cpp \ smtreemodel.cpp \ - smglobals.cpp \ + smglobals.cpp \ archivetreeview.cpp \ seriestreewidget.cpp \ seriestreemodel.cpp \ @@ -34,7 +31,8 @@ SOURCES = main.cpp \ filestreewidget.cpp \ mappingtablemodel.cpp \ mappingtablewidget.cpp \ - newmoviewizard.cpp + newmoviewizard.cpp \ + filepropertiesdialog.cpp HEADERS = listitem.h \ filesystemdirproxy.h \ filesystemwidget.h \ @@ -46,16 +44,13 @@ HEADERS = listitem.h \ messagedialog.h \ configurationdialog.h \ textenterdialog.h \ - moviepropertiesdialog.h \ statisticsdialog.h \ - actorwidget.h \ - actormodel.h \ programconfigurator.h \ pictureviewer.h \ pictureviewerinfoitem.h \ smtreeitem.h \ smtreemodel.h \ - smglobals.h \ + smglobals.h \ archivetreeview.h \ seriestreewidget.h \ seriestreemodel.h \ @@ -63,6 +58,7 @@ HEADERS = listitem.h \ filestreewidget.h \ mappingtablemodel.h \ mappingtablewidget.h \ - newmoviewizard.h + newmoviewizard.h \ + filepropertiesdialog.h LIBS += -lmagic RESOURCES = shemov.qrc diff --git a/smtreeitem.cpp b/smtreeitem.cpp index e7f4336..a13e76a 100644 --- a/smtreeitem.cpp +++ b/smtreeitem.cpp @@ -15,6 +15,18 @@ SmTreeItem::SmTreeItem(int rows, SmTreeItem *parent) : mParent(parent){ } } +SmTreeItem::SmTreeItem(const SmTreeItem &other){ + mData = other.mData; + if(other.mParent){ + mParent = new SmTreeItem(*mParent); + }else{ + mParent = 0; + } + foreach(SmTreeItem *child, other.mChildren){ + mChildren << new SmTreeItem(*child); + } +} + SmTreeItem::~SmTreeItem(){ qDeleteAll(mChildren); } diff --git a/smtreeitem.h b/smtreeitem.h index 402d73f..591f2a4 100644 --- a/smtreeitem.h +++ b/smtreeitem.h @@ -15,6 +15,7 @@ class SmTreeItem { public: SmTreeItem(const QList &data, SmTreeItem *parent = 0); SmTreeItem(int rows, SmTreeItem *parent = 0); + SmTreeItem(const SmTreeItem &other); ~SmTreeItem(); void appendChild(SmTreeItem *child); SmTreeItem *child(int row) const; -- cgit v1.2.3-70-g09d2