changeset 2:97d2c8869c39

First prototype implementation of table view and player
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 23 Mar 2015 16:34:42 +0100
parents 7a2637c3eb83
children 248d5d1cdb38
files src/CMakeLists.txt src/l10n/main_de_DE.ts src/mainwindow.cpp src/mainwindow.h src/metadataview.cpp src/metadataview.h src/pngplayer.cpp src/pngplayer.h
diffstat 8 files changed, 308 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/CMakeLists.txt	Mon Mar 23 16:33:26 2015 +0100
+++ b/src/CMakeLists.txt	Mon Mar 23 16:34:42 2015 +0100
@@ -17,6 +17,8 @@
    strhelp.c
    util_win.c
    util_linux.c
+   metadataview.cpp
+   pngplayer.cpp
 )
 
 find_package(Qt5LinguistTools)
--- a/src/l10n/main_de_DE.ts	Mon Mar 23 16:33:26 2015 +0100
+++ b/src/l10n/main_de_DE.ts	Mon Mar 23 16:34:42 2015 +0100
@@ -4,15 +4,51 @@
 <context>
     <name>MainWindow</name>
     <message>
-        <location filename="../mainwindow.cpp" line="50"/>
+        <location filename="../mainwindow.cpp" line="54"/>
+        <source>Player</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="55"/>
+        <source>Filter/Details</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="67"/>
         <source>Error!</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="112"/>
+        <location filename="../mainwindow.cpp" line="129"/>
         <source>Failed to access directory: &apos;%1&apos;</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="134"/>
+        <source>Failed to access meta data file: &apos;%1&apos;</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="143"/>
+        <source>Parsed: &apos;%1&apos;</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>MetaDataView</name>
+    <message>
+        <location filename="../metadataview.cpp" line="47"/>
+        <source>Failed to parse file: &apos;%1&apos;</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
+    <name>PNGPlayer</name>
+    <message>
+        <location filename="../pngplayer.cpp" line="32"/>
+        <source>Failed to load picture: &apos;%1&apos;</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>main</name>
--- a/src/mainwindow.cpp	Mon Mar 23 16:33:26 2015 +0100
+++ b/src/mainwindow.cpp	Mon Mar 23 16:34:42 2015 +0100
@@ -9,6 +9,8 @@
 #include "mainwindow.h"
 
 #include "constants.h"
+#include "metadataview.h"
+#include "pngplayer.h"
 
 #include <QDebug>
 #include <QDialog>
@@ -28,11 +30,13 @@
 #include <QStandardPaths>
 #include <QStyle>
 #include <QStatusBar>
+#include <QTabWidget>
+#include <QVBoxLayout>
 
 MainWindow::MainWindow() :
-    mHasValidFolder(false)
-{
+    mDataView(NULL) {
     setStatusBar(new QStatusBar());
+    resize(1190, 500);
 
     setupGUI();
     readSettings();
@@ -42,8 +46,21 @@
 
 }
 
-void MainWindow::setupGUI()
-{
+void MainWindow::setupGUI() {
+    QTabWidget *tabWidget = new QTabWidget;
+    mDataView = new MetaDataView(this);
+    mPlayer = new PNGPlayer(this);
+
+    tabWidget->addTab(mPlayer, tr("Player"));
+    tabWidget->addTab(mDataView, tr("Filter/Details"));
+    tabWidget->setMovable(true);
+
+    setCentralWidget(tabWidget);
+
+    connect (mPlayer, &PNGPlayer::error, this, &MainWindow::showErrorMessage);
+    connect (mPlayer, &PNGPlayer::advance, mDataView, &MetaDataView::selectNextRow);
+    connect (mDataView, &MetaDataView::selectionChanged, mPlayer,
+             &PNGPlayer::showPicture);
 }
 
 void MainWindow::showErrorMessage(const QString& errMsg) {
@@ -61,7 +78,7 @@
     restoreGeometry(mSettings.value("geometry").toByteArray());
     restoreState(mSettings.value("windowState").toByteArray());
 }
-
+/*
 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
 {
     if (event->mimeData()->hasUrls()) {
@@ -104,7 +121,7 @@
 {
     event->accept();
 }
-
+*/
 void MainWindow::setFolder(const QString& folder)
 {
     QFileInfo fi(folder);
@@ -112,6 +129,19 @@
         showErrorMessage(tr("Failed to access directory: '%1'").arg(folder));
     }
     QDir dir = QDir(folder);
+    QFileInfo metaData = dir.absoluteFilePath("metadata.csv");
+    if (!metaData.exists() || !metaData.isReadable()) {
+        showErrorMessage(tr("Failed to access meta data file: '%1'").arg(
+                    metaData.filePath()));
 
-    // TODO;
+    }
+    QString errorMsg = mDataView->parseMetaData(metaData.filePath());
+    if (!errorMsg.isEmpty()) {
+        showErrorMessage(errorMsg);
+        return;
+    }
+    statusBar()->showMessage(tr("Parsed: '%1'").arg(metaData.filePath()));
+    qDebug() << "Parsed: " << metaData.filePath();
+    mCurFolder = folder;
+    mPlayer->setBaseDir(folder);
 }
--- a/src/mainwindow.h	Mon Mar 23 16:33:26 2015 +0100
+++ b/src/mainwindow.h	Mon Mar 23 16:34:42 2015 +0100
@@ -18,6 +18,8 @@
 class QDragLeaveEvent;
 class QDragMoveEvent;
 class QDragEnterEvent;
+class MetaDataView;
+class PNGPlayer;
 
 class MainWindow : public QMainWindow
 {
@@ -36,12 +38,12 @@
     /** @brief Restores the last window state */
     void readSettings();
 
-    /* The drag drop actions */
+    /* The drag drop actions
     void dragEnterEvent(QDragEnterEvent *event);
     void dragMoveEvent(QDragMoveEvent *event);
     void dragLeaveEvent(QDragLeaveEvent *event);
     void dropEvent(QDropEvent *event);
-
+ */
 public slots:
     /** @brief set an absolute folder to read a metadata.csv from. */
     void setFolder(const QString &folder);
@@ -53,6 +55,7 @@
 private:
     QSettings mSettings;
 
-    bool mHasValidFolder;
     QString mCurFolder;
+    MetaDataView *mDataView;
+    PNGPlayer *mPlayer;
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/metadataview.cpp	Mon Mar 23 16:34:42 2015 +0100
@@ -0,0 +1,86 @@
+#include "metadataview.h"
+#include "qxtcsvmodel.h"
+
+#include <QTextCodec>
+#include <QTableView>
+#include <QSortFilterProxyModel>
+#include <QVBoxLayout>
+#include <QLabel>
+#include <QDebug>
+#include <QHeaderView>
+#include <QModelIndex>
+#include <QItemSelectionModel>
+
+MetaDataView::MetaDataView(QWidget *parent, Qt::WindowFlags f) :
+    QWidget(parent, f) {
+    /* Create models */
+    mSortModel = new QSortFilterProxyModel;
+    mCSVModel = new QxtCsvModel;
+    setupGUI();
+
+    connect(mView->selectionModel(), &QItemSelectionModel::selectionChanged,
+            this, &MetaDataView::viewSelectionChanged);
+    return;
+}
+
+void MetaDataView::setupGUI() {
+    QVBoxLayout *baseLayout = new QVBoxLayout;
+    mView = new QTableView;
+    mView->setModel(mSortModel);
+
+    mView->horizontalHeader()->setStretchLastSection(true);
+    mView->resizeColumnsToContents();
+//    mView->setColumnWidth(0, 60);
+    mView->setSelectionBehavior(QAbstractItemView::SelectRows);
+    mView->setSelectionMode(QAbstractItemView::SingleSelection);
+    mView->setSortingEnabled(true);
+    mView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+    baseLayout->addWidget(mView);
+
+    setLayout(baseLayout);
+}
+
+QString MetaDataView::parseMetaData(const QString& filePath) {
+    mCSVModel->setSource(filePath, true, ';', QTextCodec::codecForName("UTF8"));
+    if (!mCSVModel->rowCount()) {
+        return tr("Failed to parse file: '%1'").arg(filePath);
+    }
+
+    mSortModel->setSourceModel(mCSVModel);
+    qDebug() << "Parsed: " << mCSVModel->rowCount() << " rows.";
+    return QString();
+}
+
+void MetaDataView::viewSelectionChanged(const QItemSelection& selected,
+                                        const QItemSelection& deselected) {
+    /* One row selected */
+    Q_ASSERT(selected.indexes().count() == mCSVModel->columnCount());
+    const QModelIndex idx = selected.indexes()[0];
+    emit selectionChanged(idx.data().toString(), QString());
+    qDebug() << "Selection changed: " << idx.data();
+}
+
+void MetaDataView::selectNextRow() {
+    QItemSelectionModel *selection = mView->selectionModel();
+    QModelIndexList selected = selection->selectedIndexes();
+    int row = 0,
+        col = 0;
+    if (selected.isEmpty()) {
+        qDebug() << "Selection empty. Start at row 0";
+        if (!mSortModel->hasIndex(row, col)) {
+            qDebug() << "Empty model. Failed to advance.";
+            return;
+        }
+    } else {
+        QModelIndex old = selection->selectedIndexes().first();
+        if (!mSortModel->hasIndex(old.row() + 1, old.column())) {
+            qDebug() << "No more rows.";
+            return;
+        }
+        row = old.row() + 1;
+        col = old.column();
+    }
+    QModelIndex newIdx = mSortModel->index(row, col);
+    selection->select(newIdx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/metadataview.h	Mon Mar 23 16:34:42 2015 +0100
@@ -0,0 +1,53 @@
+#ifndef METADATAVIEW_H
+#define METADATAVIEW_H
+/* Copyright (C) 2014 by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+#include <QWidget>
+#include <QItemSelection>
+
+class QTableView;
+class QSortFilterProxyModel;
+class QxtCsvModel;
+class MetaDataView: public QWidget
+{
+    Q_OBJECT
+
+public:
+    MetaDataView(QWidget * parent = 0, Qt::WindowFlags f = 0);
+
+protected:
+    void setupGUI();
+
+public:
+    /**@brief parse a metadata file and set up the model accordingly.
+     *
+     * @returns a localized error message in case of parsing errors. Or
+     * an empty string on success. */
+    QString parseMetaData(const QString& fileName);
+
+Q_SIGNALS:
+    /**@brief emited when the selection changed.
+     *
+     * @param pictureFile: The file that is now selected.
+     * @param info: Additional info to show with the file.*/
+    void selectionChanged(const QString& pictureFile, const QString& info);
+
+protected slots:
+    void viewSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
+
+public slots:
+    /**@brief selects the next row and emits a selection changed signal */
+    void selectNextRow();
+
+protected:
+    QxtCsvModel *mCSVModel;
+    QSortFilterProxyModel *mSortModel;
+    QTableView *mView;
+};
+
+
+#endif // METADATAVIEW_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pngplayer.cpp	Mon Mar 23 16:34:42 2015 +0100
@@ -0,0 +1,36 @@
+/* Copyright (C) 2014 by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+#include "pngplayer.h"
+#include <QVBoxLayout>
+#include <QPixmap>
+#include <QLabel>
+
+PNGPlayer::PNGPlayer(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) {
+    setupGUI();
+    return;
+}
+
+void PNGPlayer::setupGUI() {
+    QVBoxLayout *baseLayout = new QVBoxLayout;
+    mPNGLabel = new QLabel;
+    baseLayout->addWidget(mPNGLabel);
+    connect(&mAdvanceTimer, SIGNAL(timeout()), this, SIGNAL(advance()));
+    setLayout(baseLayout);
+    mAdvanceTimer.setInterval(2000);
+    mAdvanceTimer.start();
+}
+
+void PNGPlayer::showPicture(const QString& fileName, const QString& info) {
+    QPixmap pic(mBaseDir.filePath(fileName));
+    /* If this is too slow we could use a pixmap cache here and do
+     * some intelligent preloading */
+    if (pic.isNull()) {
+        emit error(tr("Failed to load picture: '%1'").arg(fileName));
+        return;
+    }
+    mPNGLabel->setPixmap(pic);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pngplayer.h	Mon Mar 23 16:34:42 2015 +0100
@@ -0,0 +1,50 @@
+#ifndef PNGPLAYER_H
+#define PNGPLAYER_H
+/* Copyright (C) 2014 by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+#include <QWidget>
+#include <QDir>
+#include <QTimer>
+
+class QLabel;
+
+class PNGPlayer: public QWidget
+{
+    Q_OBJECT
+
+public:
+    PNGPlayer (QWidget * parent = 0, Qt::WindowFlags f = 0);
+
+protected:
+    void setupGUI();
+
+public slots:
+    /**@brief show a PNG in the viewer.
+     *
+     * @param fileName: The picture file to show.
+     * @param info: Additional meta data to show with the image.
+     */
+    void showPicture(const QString& fileName, const QString& info);
+
+    void setBaseDir(const QString& dirName) { mBaseDir.setPath(dirName); }
+
+Q_SIGNALS:
+    /** @brief Emited if something went wrong. e.g. file not readable */
+    void error(const QString& msg);
+
+    /** @brief Emited if the player wants to advance to the next picture */
+    void advance();
+
+protected:
+    QLabel * mPNGLabel;
+    QDir mBaseDir;
+    QTimer mAdvanceTimer;
+};
+
+
+
+#endif // PNGPLAYER_H
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)