Mercurial > retraceit
view src/folderselectdialog.cpp @ 106:32dd6ea6a582
Explicitly use c++11 as newer qt versions need that.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Thu, 08 Dec 2016 15:21:11 +0100 |
parents | 4302ca793c5a |
children | 0ad468912ff3 |
line wrap: on
line source
/* Copyright (C) 2015 by ETH Zürich * Software engineering 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> #include <QMessageBox> static ulong ipStringToLong(const QString str) { QStringList octets = str.split("."); if (!(octets.size() > 3)) { qWarning() << "invalid call to str to long"; return 0; } ulong s1 = octets.at(0).toLong(); ulong s2 = octets.at(1).toLong(); ulong s3 = octets.at(2).toLong(); ulong s4 = octets.at(3).toLong(); return (s1 << 24) | (s2 << 16) | (s3 << 8) | s4; } class IPAwareSortModel : public QSortFilterProxyModel { public: bool lessThan(const QModelIndex &left, const QModelIndex &right) const { QString leftString = sourceModel()->data(left).toString(); QString rightString = sourceModel()->data(right).toString(); static QRegExp ipPattern("\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b"); if (ipPattern.indexIn(leftString) != -1 && ipPattern.indexIn(rightString) != -1) { return ipStringToLong(leftString) > ipStringToLong(rightString); } else { return QSortFilterProxyModel::lessThan(left, right); } } }; 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 IPAwareSortModel(); mModel = new QStandardItemModel(); mShowPathSelection = !pathLabel.isEmpty(); setupGUI(); if (mShowPathSelection) { mPathLabel->setText("<b>" + pathLabel + ":</b> "); } setFolder(mCurFolder); #ifndef Q_OS_WIN QIcon windowIcon = QIcon(":/icon-64.png"); setWindowIcon(windowIcon); #endif } 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); QPushButton *backBtn = new QPushButton; backBtn->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowBack)); backBtn->setToolTip(tr("Back to exam selection.")); folderChangeArea->addWidget(mGoButton); connect(mGoButton, &QPushButton::clicked, this, &FolderSelectDialog::goClicked); connect(mPathLineEdit, &QLineEdit::returnPressed, this, &FolderSelectDialog::goClicked); } mFilterWidget = new FilterWidget(mSortModel, false); base->addWidget(mFilterWidget); connect(mSortModel, &QSortFilterProxyModel::sourceModelChanged, mFilterWidget, &FilterWidget::headersChanged); mView = new QTableView; mView->setModel(mSortModel); 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); QPushButton *backBtn = NULL; if (!mShowPathSelection) { backBtn = new QPushButton(tr("Back")); backBtn->setToolTip(tr("Back to exam selection.")); connect(backBtn, &QPushButton::clicked, this, &FolderSelectDialog::backClicked); bottomButtons->addWidget(backBtn); } bottomButtons->addWidget(mOkButton); setLayout(base); resize(700, 600); } void FolderSelectDialog::selectionChanged (const QItemSelection& selected, const QItemSelection& deselected) { mOkButton->setEnabled(!selected.indexes().isEmpty()); if (mOkButton->isEnabled()) { mOkButton->setFocus(); } } void FolderSelectDialog::pathLineChanged() { const QString path = mPathLineEdit->text(); if (path.isEmpty()) { mGoButton->setEnabled(false); return; } mGoButton->setEnabled(true); } void FolderSelectDialog::goClicked() { const QString path = mPathLineEdit->text(); QDir dir(path); if (!dir.exists()) { QMessageBox::warning(this, tr("Error!"), tr("Failed to access directory: '%1'").arg(path)); mGoButton->setEnabled(false); return; } setFolder(mPathLineEdit->text()); QSettings settings; /* assuming go is only available in root folder mode */ settings.setValue(ROOT_FOLDER_KEY, mPathLineEdit->text()); } QString stripQuotes (const QString &in) { QString out = in; if (in.startsWith("\"")) { out = out.right(out.size()-1); } if (in.endsWith("\"")) { out = out.left(out.size()-1); } return out; } QMap <QString, QString> readExtraColumns(const QString &path) { QMap <QString, QString> ret; QFile file(path); if (!file.open(QIODevice::ReadOnly)) { qDebug () << "Failed to open: " << path; return ret; } QTextStream in(&file); while (!in.atEnd()) { QString line = in.readLine(); int equalsign = line.indexOf("="); if (equalsign != -1) { QString name = stripQuotes(line.left(equalsign).replace (QStringLiteral("export "), "")); QString value = stripQuotes(line.right(line.size() - equalsign - 1)); ret.insert (name, value); } } return ret; } void FolderSelectDialog::setFolder(const QString& folder) { if (folder.isEmpty()) { return; } mCurFolder = folder; if (mPathLineEdit) { mPathLineEdit->setText(mCurFolder); } QStringList columns = mFolderPattern.split(PATTERN_SEPERATOR); int patternSize = columns.size(); QDir dir(folder); mModel->clear(); 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() != patternSize) { qDebug() << "Folder does not match pattern: " << subfolder; continue; } QList<QStandardItem*> items; foreach (const QString& part, itemData) { QStandardItem * item = new QStandardItem(part); item->setData(dir.absoluteFilePath(subfolder)); QFileInfo fi (dir.absoluteFilePath(subfolder + "/.exam-setup-user")); items.append(item); if (fi.isReadable()) { const QMap<QString, QString> map = readExtraColumns (fi.filePath()); Q_FOREACH (const QString &name, map.keys()) { qDebug() << "Adding extra column: " << name; if (!columns.contains(name)) { columns << name; } QStandardItem * subitem = new QStandardItem(map[name]); items.append(subitem); } } } mModel->appendRow(items); } mModel->setHorizontalHeaderLabels(columns); mSortModel->setSourceModel(mModel); mView->resizeColumnsToContents(); } 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 %1").arg(mPathLabelString), startLoc); if (outFolder.isEmpty()) { /* User aborted */ return; } setFolder(outFolder); }