From d6b178b1fdcdac519ded25e3f253d9eeffa84053 Mon Sep 17 00:00:00 2001 From: Arno Date: Sun, 28 Jul 2013 07:46:16 +0200 Subject: Implement file properties dialog Show file properties in Filemanager and Archive, if the file is available. Also get rid of the palette stuff in SmGlobals. Just call setPalette() early enough and set it in SmTreeView. --- archivecontroller.cpp | 11 +++ archivecontroller.h | 1 + filepropertiesdialog.cpp | 214 +++++++++++++++++++++++++---------------------- filepropertiesdialog.h | 34 ++++---- fileview.cpp | 11 +++ fileview.h | 1 + helper.cpp | 16 +++- helper.h | 2 + shemov.cpp | 17 ++-- shemov.h | 3 +- smglobals.cpp | 4 - smglobals.h | 7 -- smtreeview.cpp | 5 +- 13 files changed, 191 insertions(+), 135 deletions(-) diff --git a/archivecontroller.cpp b/archivecontroller.cpp index d75f52f..4475166 100644 --- a/archivecontroller.cpp +++ b/archivecontroller.cpp @@ -18,6 +18,7 @@ #include "archivemodel.h" #include "archiveview.h" #include "pictureviewer2.h" +#include "filepropertiesdialog.h" #include "smglobals.h" #include "helper.h" @@ -165,6 +166,16 @@ void ArchiveController::editFileNo(){ } } +void ArchiveController::showProperties(){ + QModelIndexList sel = mFileSelection->selectedRows(ArchiveFilesModel::FullPath); + if(sel.isEmpty()){ + return; + } + QModelIndex first = sel.first(); + FilePropertiesDialog dlg(first.data().toString()); + dlg.exec(); +} + void ArchiveController::addActionForTree(QAction *a){ mActionsForTree << a; mArchiveTree->addAction(a); diff --git a/archivecontroller.h b/archivecontroller.h index 4f24973..2fbde4e 100644 --- a/archivecontroller.h +++ b/archivecontroller.h @@ -51,6 +51,7 @@ class ArchiveController : public QObject { void editDvdNo(); void editFileType(); void editFileNo(); + void showProperties(); void addActionForTree(QAction *a); void readConfig(); diff --git a/filepropertiesdialog.cpp b/filepropertiesdialog.cpp index a22076c..f130b0b 100644 --- a/filepropertiesdialog.cpp +++ b/filepropertiesdialog.cpp @@ -5,121 +5,137 @@ 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 "filepropertiesdialog.h" -#include "seriesmetadatamodel.h" +#include "smtreemodel.h" #include "smtreeitem.h" #include "smtreeview.h" #include "helper.h" -FilePropertiesDialog::FilePropertiesDialog(/*int seriesPartId, */QWidget *parent, Qt::WindowFlags f) : SmDialog(parent, f){ - //tab - mTab = new QTabWidget; +FilePropertiesDialog::FilePropertiesDialog(const QString &file, QWidget *parent, Qt::WindowFlags f) : SmDialog(parent, f), mFile(file){ + mStack = new QStackedWidget; + mTab = new QTabWidget; + QString lText = QString(tr("Properties - %1")).arg(mFile); + QLabel *l = new QLabel(lText); + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(l); - //stream data widget - QVBoxLayout *streamDataLayout = new QVBoxLayout; - QWidget *streamData = new QWidget; + QWidget *formatWidget = new QWidget; + mFormatView = new SmTreeView; + mFormatModel = new SmTreeModel(QStringList() << tr("Key") << tr("Value"), this); + mFormatView->setModel(mFormatModel); + QHBoxLayout *formatLayout = new QHBoxLayout; + formatLayout->addWidget(mFormatView); + formatWidget->setLayout(formatLayout); + mTab->addTab(formatWidget, tr("Format")); - //description - mDescriptionLabel = new QLabel(tr("Properties for [none]")); - mDescriptionLabel->setAutoFillBackground(true); - mDescriptionLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); - streamDataLayout->addWidget(mDescriptionLabel); - QSettings s; - QVariant varColor = s.value("ui/alternatecolor"); - QColor labelColor = varColor.value(); - QPalette labelPalette = mDescriptionLabel->palette(); - labelPalette.setColor(QPalette::Window, labelColor); - mDescriptionLabel->setPalette(labelPalette); + QWidget *streamWidget = new QWidget; + mStreamView = new SmTreeView; + mStreamModel = new SmTreeModel(QStringList() << tr("Key") << tr("Value"), this); + mStreamView->setModel(mStreamModel); + QHBoxLayout *streamLayout = new QHBoxLayout; + streamLayout->addWidget(mStreamView); + streamWidget->setLayout(streamLayout); + mTab->addTab(streamWidget, tr("Streams")); + mStack->addWidget(mTab); - //the view + model - mModel = new SmTreeModel((QStringList() << QString() << QString()), this); - mView = new SmTreeView; - mView->setHeaderHidden(true); - mView->setEditTriggers(QAbstractItemView::NoEditTriggers); - mView->setModel(mModel); - streamDataLayout->addWidget(mView); - streamData->setLayout(streamDataLayout); - mTab->addTab(streamData, tr("Stream data")); + QWidget *picWidget = new QWidget; + mPicView = new SmTreeView; + mPicModel = new SmTreeModel(QStringList() << tr("Key") << tr("Value"), this); + mPicView->setModel(mPicModel); + QHBoxLayout *picLayout = new QHBoxLayout; + picLayout->addWidget(mPicView); + picWidget->setLayout(picLayout); + mStack->addWidget(picWidget); - //metadata widget - mMetadata = new MetadataWidget; - mTab->addTab(mMetadata, tr("Metadata")); + mainLayout->addWidget(mStack); + mOk = new QPushButton(tr("Ok")); + connect(mOk, SIGNAL(clicked()), this, SLOT(accept())); + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(); + buttonLayout->addWidget(mOk); + buttonLayout->addStretch(); + mainLayout->addLayout(buttonLayout); + setLayout(mainLayout); - //buttons - QHBoxLayout *buttonLayout = new QHBoxLayout; - mOk = new QPushButton(tr("Ok")); - connect(mOk, SIGNAL(clicked()), this, SLOT(accept())); - connect(mOk, SIGNAL(clicked()), mMetadata, SLOT(accept())); - mCancel = new QPushButton(tr("Cancel")); - connect(mCancel, SIGNAL(clicked()), this, SLOT(reject())); - buttonLayout->setAlignment(Qt::AlignRight); - buttonLayout->addWidget(mOk); - buttonLayout->addWidget(mCancel); + QString mimeType = Helper::mimeType(mFile); + if(mimeType.startsWith("video")){ + mStack->setCurrentIndex(0); + movieData(); + }else if(mimeType.startsWith("image")){ + mStack->setCurrentIndex(1); + pictureData(); + } +} - //main layout - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(mTab); - mainLayout->addLayout(buttonLayout); - setLayout(mainLayout); - setMinimumWidth(450); +void FilePropertiesDialog::movieData(){ + QJsonDocument jsDoc = Helper::streamData(mFile); + if(jsDoc.isNull()){ + return; + } + QJsonObject obj = jsDoc.object(); + SmTreeItem *formatItem = new SmTreeItem(2); + movieDataRecursive(obj.value("format"), formatItem); + mFormatModel->setRoot(formatItem); + mFormatView->expandAll(); + SmTreeItem *streamItem = new SmTreeItem(2); + QJsonArray streamA = obj.value("streams").toArray(); + for(int i = 0; i < streamA.size(); ++i){ + QString itemName = QString(tr("Stream %1 [%2]")).arg(QString::number(i + 1)).arg(streamA.at(i).toObject().value("codec_type").toString()); + SmTreeItem *item = new SmTreeItem(QList() << itemName << QVariant(), streamItem); + streamItem->appendChild(item); + movieDataRecursive(streamA.at(i), item); + } + mStreamModel->setRoot(streamItem); + mStreamView->expandAll(); } -void FilePropertiesDialog::setFileName(const QString &fileName){ - QString text = QString(tr("Properties for %1")).arg(fileName); - mDescriptionLabel->setText(text); - setWindowTitle(text); +void FilePropertiesDialog::movieDataRecursive(QJsonValue start, SmTreeItem *appendTo){ + QJsonObject sObject = start.toObject(); + QJsonObject::const_iterator it; + for(it = sObject.constBegin(); it != sObject.constEnd(); ++it){ + QList data = QList() << it.key() << it.value().toVariant(); + if(it.key() == "duration"){ + qint64 seconds = it.value().toString().toDouble(); + Helper::Duration dur(seconds); + data[1] = dur.toString(); + } + if(it.key() == "bit_rate"){ + qint64 br = it.value().toString().toInt() / 1000; + data[1] = QString("%1 kb/s").arg(QString::number(br)); + } + SmTreeItem *newItem = new SmTreeItem(data, appendTo); + appendTo->appendChild(newItem); + movieDataRecursive(*it, newItem); + } } -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::pictureData(){ + QImage img = QImage(mFile); + if(img.isNull()){ + return; + } + SmTreeItem *rootItem = new SmTreeItem(2); + appendItem(QList() << tr("width") << img.width(), rootItem); + appendItem(QList() << tr("height") << img.height(), rootItem); + appendItem(QList() << tr("depth") << img.depth(), rootItem); + appendItem(QList() << tr("alpha channel") << (img.hasAlphaChannel() ? tr("yes") : tr("no")), rootItem); + appendItem(QList() << tr("qt format") << img.format(), rootItem); + appendItem(QList() << tr("byte count") << img.byteCount(), rootItem); + mPicModel->setRoot(rootItem); } -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); +void FilePropertiesDialog::appendItem(const QList &data, SmTreeItem *parent){ + SmTreeItem *item = new SmTreeItem(data, parent); + parent->appendChild(item); } diff --git a/filepropertiesdialog.h b/filepropertiesdialog.h index ee9aa96..425f6e6 100644 --- a/filepropertiesdialog.h +++ b/filepropertiesdialog.h @@ -10,29 +10,33 @@ #include "smdialog.h" +class QPushButton; class SmTreeView; -class QLabel; -class QTabWidget; +class SmTreeItem; class SmTreeModel; -class MetadataWidget; +class QTabWidget; +class QStackedWidget; class FilePropertiesDialog : public SmDialog { Q_OBJECT public: - explicit FilePropertiesDialog(/*int seriesPartId, */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); - MetadataWidget *metaWidget() { return mMetadata; }; + explicit FilePropertiesDialog(const QString &file, QWidget *parent = 0, Qt::WindowFlags f = 0); private: - QTabWidget *mTab; - MetadataWidget *mMetadata; - SmTreeView *mView; - QPushButton *mOk; - QPushButton *mCancel; - QLabel *mDescriptionLabel; - SmTreeModel *mModel; + void movieData(); + void movieDataRecursive(QJsonValue start, SmTreeItem *appendTo); + void pictureData(); + void appendItem(const QList &data, SmTreeItem *parent); + QTabWidget *mTab; + QStackedWidget *mStack; + QPushButton *mOk; + SmTreeModel *mFormatModel; + SmTreeView *mFormatView; + SmTreeModel *mStreamModel; + SmTreeView *mStreamView; + SmTreeModel *mPicModel; + SmTreeView *mPicView; + QString mFile; }; #endif // FILEPROPERTIESDIALOG_H diff --git a/fileview.cpp b/fileview.cpp index 336d179..80a81bd 100644 --- a/fileview.cpp +++ b/fileview.cpp @@ -32,6 +32,7 @@ #include "hoverwindow.h" #include "smglobals.h" #include "filesystemfileproxy.h" +#include "filepropertiesdialog.h" #include "smdirmodel.h" #include "framecache.h" @@ -231,6 +232,16 @@ void FileView::selectedFilesChanged(){ emit selectedDuration(dur, false); } +void FileView::properties(){ + QModelIndexList selected = selectionModel()->selectedRows(); + if(selected.isEmpty()){ + return; + } + QString fp = selected.at(0).data(SmDirModel::FullPathRole).toString(); + FilePropertiesDialog fpd(fp, this); + fpd.exec(); +} + void FileView::saveSelection(){ mMd5Sums.clear(); QModelIndexList selected = selectionModel()->selectedRows(SmDirModel::Md5sum); diff --git a/fileview.h b/fileview.h index 2f4a51c..aa9244c 100644 --- a/fileview.h +++ b/fileview.h @@ -49,6 +49,7 @@ class FileView : public SmTreeView { void saveSelection(); void restoreSelection(); void selectedFilesChanged(); + void properties(); protected slots: virtual void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint); diff --git a/helper.cpp b/helper.cpp index 1881102..3856bfc 100644 --- a/helper.cpp +++ b/helper.cpp @@ -223,7 +223,6 @@ namespace Helper { QSettings s; QString ffProbe = s.value("paths/ffprobe").toString(); QStringList args; - QVariantMap retval; args << "-v" << "quiet" << "-print_format" << "json" << "-show_format" << path; QProcess ffproc; ffproc.start(ffProbe, args); @@ -236,6 +235,21 @@ namespace Helper { return jsDoc.object().value("format").toObject().toVariantMap(); } + QJsonDocument streamData(const QString &path){ + QSettings s; + QString ffProbe = s.value("paths/ffprobe").toString(); + QStringList args; + args << "-v" << "quiet" << "-print_format" << "json" << "-show_format" << "-show_streams" << path; + QProcess ffproc; + ffproc.start(ffProbe, args); + if(!ffproc.waitForStarted()){ + return QJsonDocument(); + } + ffproc.waitForFinished(); + QByteArray ffData = ffproc.readAllStandardOutput(); + return QJsonDocument::fromJson(ffData); + } + Duration::Duration() : mHours(0), mMinutes(0), mSeconds(0) {} Duration::Duration(qint64 seconds){ diff --git a/helper.h b/helper.h index 634eb12..75aa811 100644 --- a/helper.h +++ b/helper.h @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -33,6 +34,7 @@ namespace Helper { const QString colorToHtml(const QColor &color); void centerWidget(QWidget *widget); QVariantMap ffmpegData(const QString &path); + QJsonDocument streamData(const QString &path); class Duration { public: Duration(); diff --git a/shemov.cpp b/shemov.cpp index 7a905c4..07876d4 100644 --- a/shemov.cpp +++ b/shemov.cpp @@ -40,6 +40,7 @@ SheMov::SheMov(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags), mOpenWithGroupFS(0), mOpenWithGroupAV(0) { //application icon qApp->setWindowIcon(QIcon(":/shemov.png")); + createPalette(); setAttribute(Qt::WA_DeleteOnClose); QSplashScreen splash(QPixmap(":/shemov_splash2.png")); splash.show(); @@ -435,6 +436,8 @@ void SheMov::createActions(){ //View menu (FS) mRefreshA = new QAction(tr("Refresh"), this); connect(mRefreshA, SIGNAL(triggered()), mFSWidget->fileModel(), SLOT(refresh())); + mFSViewPropertiesA = new QAction(tr("Properties..."), this); + connect(mFSViewPropertiesA, SIGNAL(triggered()), mFSWidget->fileView(), SLOT(properties())); //Help menu QString aboutLabel = QString(tr("About %1...")).arg(qApp->applicationName()); @@ -596,6 +599,9 @@ void SheMov::createActions(){ // set file no mArchiveFilesFileNoA = new QAction(tr("Set File No. ..."), this); connect(mArchiveFilesFileNoA, SIGNAL(triggered()), c, SLOT(editFileNo())); + // show properties + mArchiveFilesPropertiesA = new QAction(tr("Properties..."), this); + connect(mArchiveFilesPropertiesA, SIGNAL(triggered()), c, SLOT(showProperties())); // db analyzer dialogs // analyze actors @@ -756,6 +762,8 @@ void SheMov::createMenus(){ mFSWidget->fileView()->addAction(mArchiveSelectedPicsA); mFSWidget->fileView()->addAction(mArchiveSelectedMovsA); + mFSWidget->fileView()->addAction(createSeparator()); + mFSWidget->fileView()->addAction(mFSViewPropertiesA); // Movie archive ArchiveController *c = SmGlobals::instance()->archiveController(); @@ -775,6 +783,8 @@ void SheMov::createMenus(){ c->archiveFiles()->addAction(mArchiveFilesDvdNoA); c->archiveFiles()->addAction(mArchiveFilesTypeA); c->archiveFiles()->addAction(mArchiveFilesFileNoA); + c->archiveFiles()->addAction(createSeparator()); + c->archiveFiles()->addAction(mArchiveFilesPropertiesA); QMenu *archiveFilesM = new QMenu(tr("Files"), this); archiveFilesM->addActions(c->archiveFiles()->actions()); @@ -867,12 +877,7 @@ void SheMov::createPalette(){ pal.setColor(QPalette::Base, Qt::white); pal.setColor(QPalette::AlternateBase, Qt::white); } - foreach(QWidget *w, SmGlobals::instance()->treeWidgets()){ - SmTreeView *aiv = qobject_cast(w); - if(aiv){ - aiv->setPalette(pal); - } - } + qApp->setPalette(pal); } void SheMov::rebuildFrameCache(){ diff --git a/shemov.h b/shemov.h index aab035a..1bc92dc 100644 --- a/shemov.h +++ b/shemov.h @@ -16,7 +16,6 @@ class FilesystemWidget; class QLabel; class QSignalMapper; class QActionGroup; -//class ArchiveTreeView; class NewMovieWizard; class PicturesWidget; class SmTreeModel; @@ -108,6 +107,7 @@ class SheMov : public QMainWindow { QAction *mRebuildFrameCacheA; QAction *mNewMovieWizardA; QAction *mMoveToArchiveA; + QAction *mFSViewPropertiesA; //Filesystem View Actions QActionGroup *mFSHoverGroup; @@ -150,6 +150,7 @@ class SheMov : public QMainWindow { QAction *mArchiveFilesDvdNoA; QAction *mArchiveFilesTypeA; QAction *mArchiveFilesFileNoA; + QAction *mArchiveFilesPropertiesA; //DB analyze actions QAction *mAnalyzeActorsA; diff --git a/smglobals.cpp b/smglobals.cpp index 2ed698c..949b5ae 100644 --- a/smglobals.cpp +++ b/smglobals.cpp @@ -115,10 +115,6 @@ FrameCache *SmGlobals::frameCache() { return mFrameCache; } -SeriesTreeWidget *SmGlobals::seriesTreeWidget(){ - return mSeriesTreeWidget; -} - QSize SmGlobals::cursorSize() { if(!mCursorSize.isValid()){ Display *dpy = XOpenDisplay(0); diff --git a/smglobals.h b/smglobals.h index 5580f47..72604ab 100644 --- a/smglobals.h +++ b/smglobals.h @@ -9,11 +9,8 @@ #define SMUBERMODELSINGLETON_H #include - #include #include -#include -#include class QAbstractItemModel; class PictureViewer2; @@ -30,8 +27,6 @@ class SmGlobals : public QObject { QAbstractItemModel *model(const QString &which); PictureViewer2 *pictureViewer(); FrameCache *frameCache(); - void setSeriesTreeWidget(SeriesTreeWidget *stree) { mSeriesTreeWidget = stree; } - SeriesTreeWidget *seriesTreeWidget(); void setArchiveController(ArchiveController *c) { mArchiveController = c; } ArchiveController *archiveController() { return mArchiveController; } QSize cursorSize(); @@ -39,7 +34,6 @@ class SmGlobals : public QObject { const QSize minPVSize() const { return QSize(640, 480); } const QHash & icons() const { return mIcons; } qint64 dvdSize() const { return mDvdSize; } - QList &treeWidgets() { return mTreeWidgets; } QHash filetypeMap() const { return mFiletypeMap; } private: @@ -54,7 +48,6 @@ class SmGlobals : public QObject { QSize mCursorSize; QHash mIcons; qint64 mDvdSize; - QList mTreeWidgets; ArchiveController *mArchiveController; QHash mFiletypeMap; }; diff --git a/smtreeview.cpp b/smtreeview.cpp index d4faab8..7fd7b48 100644 --- a/smtreeview.cpp +++ b/smtreeview.cpp @@ -11,20 +11,21 @@ #include #include #include +#include #include "smtreeview.h" #include "smglobals.h" SmTreeView::SmTreeView(QWidget *parent) : QTreeView(parent) { header()->setSectionResizeMode(QHeaderView::ResizeToContents); - SmGlobals::instance()->treeWidgets().append(this); setAlternatingRowColors(true); + setPalette(qApp->palette()); } SmTreeView::SmTreeView(const QString &hSetting, QWidget *parent) : QTreeView(parent), mHeaderSetting(hSetting){ header()->setSectionResizeMode(QHeaderView::ResizeToContents); - SmGlobals::instance()->treeWidgets().append(this); setAlternatingRowColors(true); + setPalette(qApp->palette()); } void SmTreeView::readHeaderConfig(){ -- cgit v1.2.3-70-g09d2