changeset 9:e3c8f61e45a9

Implement folderselection dialogs
author Andre Heinecke <andre.heinecke@intevation.de>
date Thu, 26 Mar 2015 16:30:18 +0100
parents ac4db84f1d9d
children f290e8c4e097
files src/CMakeLists.txt src/constants.h src/folderselectdialog.cpp src/folderselectdialog.h src/l10n/main_de_DE.ts src/main.cpp src/mainwindow.cpp src/mainwindow.h
diffstat 8 files changed, 377 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/CMakeLists.txt	Wed Mar 25 14:25:21 2015 +0100
+++ b/src/CMakeLists.txt	Thu Mar 26 16:30:18 2015 +0100
@@ -21,6 +21,7 @@
    pngplayer.cpp
    imagelabel.cpp
    filterwidget.cpp
+   folderselectdialog.cpp
 )
 
 find_package(Qt5LinguistTools)
--- a/src/constants.h	Wed Mar 25 14:25:21 2015 +0100
+++ b/src/constants.h	Thu Mar 26 16:30:18 2015 +0100
@@ -65,4 +65,7 @@
 /**@def the value for a step in the speed slider */
 #define REPLAY_SPEED_STEP_MS 500
 
+/**@def The seperator used in the patterns. */
+#define PATTERN_SEPERATOR "_"
+
 #endif // CONSTANTS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/folderselectdialog.cpp	Thu Mar 26 16:30:18 2015 +0100
@@ -0,0 +1,194 @@
+/* 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 "folderselectdialog.h"
+#include "constants.h"
+
+#include <QSortFilterProxyModel>
+#include <QStandardItemModel>
+#include <QTableView>
+#include <QVBoxLayout>
+#include <QLineEdit>
+#include <QLabel>
+#include <QApplication>
+#include <QStyle>
+#include <QFileDialog>
+#include <QStandardPaths>
+#include <QPushButton>
+#include <QHeaderView>
+#include <QDebug>
+#include <QSettings>
+#include <QStringList>
+#include <QStandardItem>
+
+FolderSelectDialog::FolderSelectDialog(const QString& startFolder,
+                                       const QString& folderPattern,
+                                       const QString& pathLabel,
+                                       QWidget * parent,
+                                       Qt::WindowFlags f) :
+    QDialog(parent, f),
+    mCurFolder(startFolder),
+    mFolderPattern(folderPattern),
+    mPathLabelString(pathLabel),
+    mPathLabel(NULL),
+    mPathLineEdit(NULL)
+{
+    mSortModel = new QSortFilterProxyModel();
+    mModel = new QStandardItemModel();
+    mShowPathSelection = !pathLabel.isEmpty();
+    setupGUI();
+    if (mShowPathSelection) {
+        mPathLabel->setText("<b>" + pathLabel + ":</b>   ");
+    }
+    setFolder(mCurFolder);
+}
+
+void FolderSelectDialog::setupGUI() {
+    QVBoxLayout *base = new QVBoxLayout;
+    QHBoxLayout *folderChangeArea = new QHBoxLayout;
+
+    if (mShowPathSelection) {
+        mPathLabel = new QLabel;
+        folderChangeArea->addWidget(mPathLabel);
+        base->addLayout(folderChangeArea);
+
+        QPushButton *folderSelect = new QPushButton();
+        folderSelect->setToolTip(tr("Select folder"));
+        folderSelect->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirIcon));
+        connect(folderSelect, &QPushButton::clicked, this,
+                &FolderSelectDialog::changeFolderClicked);
+        folderChangeArea->addWidget(folderSelect);
+
+        mPathLineEdit = new QLineEdit;
+        mPathLineEdit->setClearButtonEnabled(true);
+        connect(mPathLineEdit, &QLineEdit::textChanged, this,
+                &FolderSelectDialog::pathLineChanged);
+        folderChangeArea->addWidget(mPathLineEdit);
+
+        mGoButton = new QPushButton(tr("Go"));
+        mGoButton->setEnabled(false);
+        folderChangeArea->addWidget(mGoButton);
+        connect(mGoButton, &QPushButton::clicked, this,
+                &FolderSelectDialog::goClicked);
+    }
+
+    mFilterWidget = new FilterWidget(mSortModel);
+    base->addWidget(mFilterWidget);
+
+    mView = new QTableView;
+    mView->setModel(mSortModel);
+
+    mView->resizeColumnsToContents();
+    mView->setSelectionBehavior(QAbstractItemView::SelectRows);
+    mView->setSelectionMode(QAbstractItemView::SingleSelection);
+    mView->setSortingEnabled(true);
+    mView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+    connect(mView->selectionModel(), &QItemSelectionModel::selectionChanged,
+            this, &FolderSelectDialog::selectionChanged);
+    connect(mView, &QTableView::doubleClicked, this,
+            &FolderSelectDialog::wantToAccept);
+
+    base->addWidget(mView);
+
+    QHBoxLayout * bottomButtons = new QHBoxLayout;
+    base->addLayout(bottomButtons);
+
+    mOkButton = new QPushButton(tr("Ok"));
+    mOkButton->setEnabled(false);
+    connect(mOkButton, &QPushButton::clicked, this,
+            &FolderSelectDialog::wantToAccept);
+    bottomButtons->addStretch(-1);
+    bottomButtons->addWidget(mOkButton);
+    setLayout(base);
+}
+
+void FolderSelectDialog::selectionChanged (const QItemSelection& selected,
+                                           const QItemSelection& deselected) {
+    mOkButton->setEnabled(!selected.indexes().isEmpty());
+}
+
+void FolderSelectDialog::pathLineChanged() {
+    const QString path = mPathLineEdit->text();
+    qDebug() << "path: " << path;
+    if (path.isEmpty()) {
+        mGoButton->setEnabled(false);
+        return;
+    }
+    QDir dir(path);
+    if (dir.exists()) {
+        mGoButton->setEnabled(true);
+        return;
+    }
+    mGoButton->setEnabled(false);
+}
+
+
+void FolderSelectDialog::goClicked() {
+    setFolder(mPathLineEdit->text());
+    QSettings settings;
+    /* assuming go is only available in root folder mode */
+    settings.setValue(ROOT_FOLDER_KEY, mPathLineEdit->text());
+}
+
+void FolderSelectDialog::setFolder(const QString& folder) {
+    mCurFolder = folder;
+    if (mPathLineEdit) {
+        mPathLineEdit->setText(mCurFolder);
+    }
+
+    QStringList columns = mFolderPattern.split(PATTERN_SEPERATOR);
+    mModel->clear();
+    mModel->setHorizontalHeaderLabels(columns);
+    QDir dir(folder);
+    qDebug() << "Folder set to: " << folder;
+    foreach (const QString & subfolder, dir.entryList(QDir::Dirs |
+                                                      QDir::Readable |
+                                                      QDir::NoDotAndDotDot)) {
+        qDebug() << "Looking at: " << subfolder;
+        QStringList itemData = subfolder.split(PATTERN_SEPERATOR);
+        if (itemData.size() != columns.size()) {
+            qDebug() << "Failed to parse: " << subfolder;
+            continue;
+        }
+        QList<QStandardItem*> items;
+        foreach (const QString& part, itemData) {
+            QStandardItem * item = new QStandardItem(part);
+            item->setData(dir.absoluteFilePath(subfolder));
+            items.append(item);
+        }
+        mModel->appendRow(items);
+    }
+    mSortModel->setSourceModel(mModel);
+}
+
+void FolderSelectDialog::wantToAccept() {
+    QItemSelectionModel *selection = mView->selectionModel();
+    QModelIndexList selected = selection->selectedIndexes();
+    if (selected.isEmpty()) { /* Ok should not be enabled in that case */
+        return;
+    }
+    const QString folder = selected[0].data(Qt::UserRole + 1).toString();
+
+    emit folderSelected(folder);
+    accept();
+}
+
+void FolderSelectDialog::changeFolderClicked()
+{
+    const QString oldFolder = mCurFolder;
+    const QString startLoc = mCurFolder.isEmpty() ?
+        QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) :
+        mCurFolder;
+
+    QString outFolder = QFileDialog::getExistingDirectory(
+            this, tr("Select ") + mPathLabelString,
+            startLoc);
+    if (outFolder.isEmpty()) {
+        /* User aborted */
+        return;
+    }
+    setFolder(outFolder);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/folderselectdialog.h	Thu Mar 26 16:30:18 2015 +0100
@@ -0,0 +1,80 @@
+#ifndef FOLDERSELECTDIALOG_H
+#define FOLDERSELECTDIALOG_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 <QDialog>
+#include <QItemSelection>
+
+#include "filterwidget.h"
+
+class QTableView;
+class QSortFilterProxyModel;
+class FilterWidget;
+class QStandardItemModel;
+class QLabel;
+class QPushButton;
+class QLineEdit;
+
+class FolderSelectDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    /** @brief initialize a folder select dialog with a start folder and
+     * for a specific folder name pattern.
+     *
+     * If the parameter pathLabel is not empty it includes a path selection
+     * area.
+     * */
+    FolderSelectDialog(const QString& startFolder,
+            const QString& folderPattern,
+            const QString& pathLabel = QString(),
+            QWidget * parent = 0, Qt::WindowFlags f = 0);
+
+    void setFolder(const QString& folder);
+
+protected:
+    void setupGUI();
+
+protected slots:
+    /** @brief The user wants to accept the selection */
+    void wantToAccept();
+
+    /** @brief Open the folder selection dialog for the output folder */
+    void changeFolderClicked();
+
+    /** @brief try to load the folder line into the model */
+    void goClicked();
+
+    /** @brief enable or disable the go button depending on the path. */
+    void pathLineChanged();
+
+    /** @brief enable or disable the ok button depending on the selection. */
+    void selectionChanged (const QItemSelection& selected,
+                           const QItemSelection& deselected);
+
+Q_SIGNALS:
+    /** @brief emited before the dialog is closed when a folder is selected */
+    void folderSelected(const QString& folder);
+
+private:
+    QTableView *mView;
+    FilterWidget *mFilterWidget;
+    QSortFilterProxyModel *mSortModel;
+    QString mCurFolder,
+            mFolderPattern;
+    QString mPathLabelString;
+    QStandardItemModel *mModel;
+    QLabel *mPathLabel;
+    QLineEdit *mPathLineEdit;
+    QPushButton *mGoButton,
+                *mOkButton;
+    bool mShowPathSelection;
+};
+
+#endif // FOLDERSELECTDIALOG_H
--- a/src/l10n/main_de_DE.ts	Wed Mar 25 14:25:21 2015 +0100
+++ b/src/l10n/main_de_DE.ts	Thu Mar 26 16:30:18 2015 +0100
@@ -15,42 +15,80 @@
     </message>
 </context>
 <context>
+    <name>FolderSelectDialog</name>
+    <message>
+        <location filename="../folderselectdialog.cpp" line="59"/>
+        <source>Select folder</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../folderselectdialog.cpp" line="71"/>
+        <source>Go</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../folderselectdialog.cpp" line="99"/>
+        <source>Ok</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../folderselectdialog.cpp" line="187"/>
+        <source>Select </source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>MainWindow</name>
     <message>
-        <location filename="../mainwindow.cpp" line="54"/>
+        <location filename="../mainwindow.cpp" line="55"/>
         <source>Player</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="55"/>
+        <location filename="../mainwindow.cpp" line="56"/>
         <source>Filter/Details</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="71"/>
+        <location filename="../mainwindow.cpp" line="72"/>
         <source>Error!</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="133"/>
+        <location filename="../mainwindow.cpp" line="134"/>
         <source>Failed to access directory: &apos;%1&apos;</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="138"/>
+        <location filename="../mainwindow.cpp" line="139"/>
         <source>Failed to access meta data file: &apos;%1&apos;</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="147"/>
+        <location filename="../mainwindow.cpp" line="148"/>
         <source>Parsed: &apos;%1&apos;</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../mainwindow.cpp" line="157"/>
+        <location filename="../mainwindow.cpp" line="159"/>
         <source>Showing: &apos;%1&apos;</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="173"/>
+        <source>Persons</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="189"/>
+        <source>Exams</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../mainwindow.cpp" line="188"/>
+        <source>Root-Path</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>MetaDataView</name>
--- a/src/main.cpp	Wed Mar 25 14:25:21 2015 +0100
+++ b/src/main.cpp	Thu Mar 26 16:30:18 2015 +0100
@@ -161,12 +161,14 @@
     MainWindow mainWin;
 
     const QStringList args = parser.positionalArguments();
-    if (args.isEmpty() || args.size() > 1) {
+    if (args.size() > 1) {
         parser.showHelp(1);
     }
-    mainWin.setFolder(args.first());
-
-    mainWin.show();
+    if (args.size() == 1) {
+        mainWin.setFolder(args.first());
+    } else {
+        mainWin.showWithFolderSelect();
+    }
 
     return app.exec(); /* Go event loop */
 }
--- a/src/mainwindow.cpp	Wed Mar 25 14:25:21 2015 +0100
+++ b/src/mainwindow.cpp	Thu Mar 26 16:30:18 2015 +0100
@@ -11,6 +11,7 @@
 #include "constants.h"
 #include "metadataview.h"
 #include "pngplayer.h"
+#include "folderselectdialog.h"
 
 #include <QDebug>
 #include <QDialog>
@@ -149,6 +150,7 @@
     mCurFolder = folder;
     mPlayer->setBaseDir(folder);
     mDataView->selectNextRow();
+    show();
 }
 
 void MainWindow::showPictureNameStatus(const QString& fileName, int current,
@@ -157,3 +159,37 @@
         statusBar()->showMessage(tr("Showing: '%1'").arg(fileName));
     }
 }
+
+void MainWindow::setRootFolder(const QString &folder) {
+    mRootFolder = folder;
+    showSubFolderSelect();
+}
+
+void MainWindow::showSubFolderSelect() {
+    const QString subPattern = mSettings.value(SUB_FOLDER_PATTERN_KEY,
+                                               SUB_FOLDER_PATTERN).toString();
+    FolderSelectDialog *fsDialog = new FolderSelectDialog(mRootFolder,
+                                                          subPattern);
+    fsDialog->setWindowTitle(tr("Persons"));
+    connect(fsDialog, &FolderSelectDialog::folderSelected,
+            this, &MainWindow::setFolder);
+
+    fsDialog->show();
+//    connect(fsDialog, &QDialog::closeEvent, fsDialog, &QObject::deleteLater);
+}
+
+void MainWindow::showWithFolderSelect() {
+    const QString startFolder = mSettings.value(ROOT_FOLDER_KEY,
+                                                QString()).toString();
+    const QString rootPattern = mSettings.value(ROOT_FOLDER_PATTERN_KEY,
+                                                DEFAULT_ROOT_PATTERN).toString();
+    FolderSelectDialog *fsDialog = new FolderSelectDialog(startFolder,
+                                                          rootPattern,
+                                                          tr("Root-Path"));
+    fsDialog->setWindowTitle(tr("Exams"));
+    connect(fsDialog, &FolderSelectDialog::folderSelected,
+            this, &MainWindow::setRootFolder);
+
+    fsDialog->show();
+   // connect(fsDialog, &QDialog::closeEvent, fsDialog, &QObject::deleteLater);
+}
--- a/src/mainwindow.h	Wed Mar 25 14:25:21 2015 +0100
+++ b/src/mainwindow.h	Thu Mar 26 16:30:18 2015 +0100
@@ -49,6 +49,16 @@
     /** @brief set an absolute folder to read a metadata.csv from. */
     void setFolder(const QString &folder);
 
+    /** @brief set an absolute folder to check for subfolders. */
+    void setRootFolder(const QString &folder);
+
+public:
+    /** @brief start the folder selection and show afterwards. */
+    void showWithFolderSelect();
+
+    /** @brief start the subfolder selection and show afterwards. */
+    void showSubFolderSelect();
+
 protected slots:
     /** @brief Show an error dialog to the user. */
     void showErrorMessage(const QString& errMsg);
@@ -64,6 +74,8 @@
     QSettings mSettings;
 
     QString mCurFolder;
+    QString mRootFolder;
+    QString mSubFolder;
     MetaDataView *mDataView;
     PNGPlayer *mPlayer;
 };
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)