summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArno <am@disconnect.de>2010-07-31 16:26:10 +0200
committerArno <am@disconnect.de>2010-07-31 16:26:10 +0200
commit8eba6e7f033617f3e7ea3bd9913105df0de74ae2 (patch)
tree8d4b93a4a686e6e57526b77033bb985fa9545036
parent6d3b28f9b12964b161b5a7ac0038435cfdd6e27b (diff)
downloadSheMov-8eba6e7f033617f3e7ea3bd9913105df0de74ae2.tar.gz
SheMov-8eba6e7f033617f3e7ea3bd9913105df0de74ae2.tar.bz2
SheMov-8eba6e7f033617f3e7ea3bd9913105df0de74ae2.zip
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.
-rw-r--r--actormodel.cpp117
-rw-r--r--actormodel.h37
-rw-r--r--actorwidget.cpp64
-rw-r--r--actorwidget.h42
-rw-r--r--configurationdialog.cpp12
-rw-r--r--configurationdialog.h1
-rw-r--r--filepropertiesdialog.cpp99
-rw-r--r--filepropertiesdialog.h36
-rw-r--r--filestreemodel.cpp76
-rw-r--r--filestreemodel.h4
-rw-r--r--filestreewidget.cpp33
-rw-r--r--filestreewidget.h1
-rw-r--r--helper.cpp17
-rw-r--r--helper.h1
-rw-r--r--moviepropertiesdialog.cpp214
-rw-r--r--moviepropertiesdialog.h45
-rw-r--r--shemov.cpp6
-rw-r--r--shemov.h1
-rw-r--r--shemov.pro16
-rw-r--r--smtreeitem.cpp12
-rw-r--r--smtreeitem.h1
21 files changed, 306 insertions, 529 deletions
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 <QIcon>
-
-#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 <QAbstractItemModel>
-#include <QList>
-
-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<QString> items() const { return mItems; };
-
- private:
- QList<QString> 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 <QVBoxLayout>
-#include <QHBoxLayout>
-#include <QPushButton>
-#include <QTreeView>
-#include <QLabel>
-
-#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 <QWidget>
-#include <QMap>
-
-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 <QApplication>
#include <QSettings>
#include <QRegExp>
+#include <QFileInfo>
#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 <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QTreeView>
+#include <QPushButton>
+
+#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<QMap<QString, QString> > &streamData){
+ SmTreeItem *root = new SmTreeItem(2);
+ for(int i = 0; i < streamData.size(); ++i){
+ QList<QVariant> titleData;
+ QString title = QString(tr("Stream %1")).arg(QString::number(i));
+ titleData << title << QVariant();
+ SmTreeItem *titleItem = new SmTreeItem(titleData, root);
+ root->appendChild(titleItem);
+ QMap<QString, QString>::const_iterator it = streamData.at(i).constBegin();
+ while(it != streamData.at(i).constEnd()){
+ QList<QVariant> 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<QString, QString> &data){
+ SmTreeItem *root = new SmTreeItem(*mModel->root());
+ QList<QVariant> titleData;
+ titleData << caption << QVariant();
+ SmTreeItem *titleItem = new SmTreeItem(titleData, root);
+ root->appendChild(titleItem);
+ QMap<QString, QString>::const_iterator it = data.constBegin();
+ while(it != data.constEnd()){
+ QList<QVariant> 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 <QDialog>
+#include <QList>
+#include <QMap>
+
+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<QMap<QString, QString> > &streamData);
+ void addData(const QString &caption, const QMap<QString, QString> &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 <QIcon>
#include <QFileInfo>
#include <QFile>
+#include <QSettings>
+#include <QProcess>
+#include <QImage>
#include "filestreemodel.h"
#include "smtreeitem.h"
@@ -235,6 +238,79 @@ QHash<QString, QString> FilesTreeModel::filesBySeriesPartId(int seriesPartId){
return retval;
}
+QList<QMap<QString, QString> > FilesTreeModel::streamInfo(const QModelIndex &idx){
+ QList<QMap<QString, QString> > 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<QByteArray> lines = ffData.split('\n');
+ QMap<QString, QString> 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<QString, QString> FilesTreeModel::pictureInfo(const QModelIndex &idx){
+ QMap<QString, QString> 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<QString, QString> FilesTreeModel::pictureMetaInfo(const QModelIndex &idx){
+ QMap<QString, QString> 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 <QSqlDatabase>
#include <QList>
#include <QHash>
+#include <QMap>
#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<QString, QString> filesBySeriesPartId(int seriesPartId);
+ QList<QMap<QString, QString> > streamInfo(const QModelIndex &idx);
+ QMap<QString, QString> pictureInfo(const QModelIndex &idx);
+ QMap<QString, QString> 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<QMap<QString, QString> > fileData = mModel->streamInfo(real);
+ dlg.setStreamData(fileData);
+ }else if(mimeType.startsWith("image")){
+ QMap<QString, QString> imageData = mModel->pictureInfo(real);
+ dlg.addData("Image data", imageData);
+ QMap<QString, QString> textData = mModel->pictureMetaInfo(real);
+ if(!textData.isEmpty()){
+ dlg.addData("Meta data", textData);
+ }
+ }
+ dlg.exec();
+ }
+
+}
+
void FilesTreeWidget::fileSelectionChanged(const QModelIndex &current, 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 &current, 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 <QSettings>
#include <QDir>
+#include <stdio.h>
+
#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<QString, QStringList> programData(const QString &prefix, const QString &preferred = QString());
+ QString durationFromSecs(qint64 secs);
class StringListContains : public std::binary_function<QString, QString, bool> {
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 <QHBoxLayout>
-#include <QVBoxLayout>
-#include <QGraphicsView>
-#include <QGraphicsScene>
-#include <QPushButton>
-#include <QLabel>
-#include <QSqlQuery>
-#include <QFileInfo>
-#include <QFont>
-#include <QApplication>
-#include <QGridLayout>
-#include <QLocale>
-#include <QGraphicsTextItem>
-#include <QGraphicsPixmapItem>
-#include <QPixmap>
-#include <QTreeView>
-
-#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 <QDialog>
-
-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<QVariant> &data, SmTreeItem *parent = 0);
SmTreeItem(int rows, SmTreeItem *parent = 0);
+ SmTreeItem(const SmTreeItem &other);
~SmTreeItem();
void appendChild(SmTreeItem *child);
SmTreeItem *child(int row) const;