Mercurial > retraceit
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: '%1'</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: '%1'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../mainwindow.cpp" line="147"/> + <location filename="../mainwindow.cpp" line="148"/> <source>Parsed: '%1'</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../mainwindow.cpp" line="157"/> + <location filename="../mainwindow.cpp" line="159"/> <source>Showing: '%1'</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; };