valentina/src/libs/vpropertyexplorer/plugins/vfilepropertyeditor.cpp

270 lines
7.7 KiB
C++
Raw Normal View History

/************************************************************************
**
** @file vfilepropertyeditor.cpp
** @author hedgeware <internal(at)hedgeware.net>
** @date
**
** @brief
** @copyright
** All rights reserved. This program and the accompanying materials
** are made available under the terms of the GNU Lesser General Public License
** (LGPL) version 2.1 which accompanies this distribution, and is available at
** http://www.gnu.org/licenses/lgpl-2.1.html
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
*************************************************************************/
#include "vfilepropertyeditor.h"
#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDragMoveEvent>
#include <QDropEvent>
#include <QEvent>
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QList>
#include <QMimeData>
#include <QSizePolicy>
#include <QToolButton>
#include <QUrl>
#include <Qt>
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#include <QRegularExpression>
#else
2023-02-09 15:35:30 +01:00
#include <QRegExp>
#endif
VPE::VFileEditWidget::VFileEditWidget(QWidget *parent, bool is_directory)
2014-09-20 18:05:21 +02:00
: QWidget(parent), CurrentFilePath(), ToolButton(nullptr), FileLineEdit(nullptr), FileDialogFilter(), FilterList(),
Directory(is_directory)
{
// Create the tool button,ToolButton = new QToolButton(this);
ToolButton = new QToolButton(this);
ToolButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored);
ToolButton->setText("...");
ToolButton->setFixedWidth(20);
ToolButton->installEventFilter(this);
2014-09-10 19:57:08 +02:00
setFocusProxy(ToolButton); // Make the ToolButton the focus proxy
setFocusPolicy(ToolButton->focusPolicy());
connect(ToolButton, &QToolButton::clicked, this, &VFileEditWidget::onToolButtonClicked);
// Create the line edit widget
FileLineEdit = new QLineEdit(this);
FileLineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
FileLineEdit->setText(CurrentFilePath);
FileLineEdit->installEventFilter(this);
// The layout (a horizontal layout)
QHBoxLayout* layout = new QHBoxLayout(this);
layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(FileLineEdit);
layout->addWidget(ToolButton);
// Accept drops
setAcceptDrops(true);
}
VPE::VFileEditWidget::~VFileEditWidget()
{
// nothing needs to be done here
}
void VPE::VFileEditWidget::setFile(const QString &value, bool emit_signal)
{
if (CurrentFilePath != value)
{
CurrentFilePath = value;
FileLineEdit->setText(CurrentFilePath);
2014-09-10 19:57:08 +02:00
if (emit_signal)
{
emit dataChangedByUser(CurrentFilePath, this);
emit commitData(this);
}
}
}
void VPE::VFileEditWidget::setFilter(const QString &dialog_filter, const QStringList& filter_list)
{
FileDialogFilter = dialog_filter;
FilterList = filter_list;
}
void VPE::VFileEditWidget::setDirectory(bool dir)
{
Directory = dir;
}
2023-05-03 13:07:02 +02:00
auto VPE::VFileEditWidget::getFile() const -> QString
{
return CurrentFilePath;
}
void VPE::VFileEditWidget::onToolButtonClicked()
{
2017-07-05 18:35:34 +02:00
QString filepath = (Directory ? QFileDialog::getExistingDirectory(nullptr, tr("Directory"), CurrentFilePath,
QFileDialog::ShowDirsOnly
#ifdef Q_OS_LINUX
| QFileDialog::DontUseNativeDialog
#endif
)
2017-07-05 18:35:34 +02:00
: QFileDialog::getOpenFileName(nullptr, tr("Open File"), CurrentFilePath,
FileDialogFilter, nullptr
#ifdef Q_OS_LINUX
, QFileDialog::DontUseNativeDialog
#endif
));
2014-09-10 19:57:08 +02:00
if (filepath.isNull() == false)
{
setFile(filepath, true);
2014-09-10 19:57:08 +02:00
}
}
2023-05-03 13:07:02 +02:00
auto VPE::VFileEditWidget::eventFilter(QObject *obj, QEvent *ev) -> bool
{
2014-09-10 19:57:08 +02:00
if (ev->type() == QEvent::DragEnter || ev->type() == QEvent::Drop)
{
ev->ignore();
2014-09-10 19:57:08 +02:00
if (ev->type() == QEvent::DragEnter)
{
dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
2014-09-10 19:57:08 +02:00
}
else if (ev->type() == QEvent::Drop)
{
dropEvent(static_cast<QDropEvent*>(ev));
2014-09-10 19:57:08 +02:00
}
2014-09-10 19:57:08 +02:00
if (ev->isAccepted())
{
return true;
2014-09-10 19:57:08 +02:00
}
2023-05-03 13:07:02 +02:00
return QWidget::eventFilter(obj, ev);
}
else if (obj == ToolButton && ev->type() == QEvent::KeyPress)
{
// Ignore the event, so that eventually the delegate gets the event.
ev->ignore();
return true;
}
2014-09-10 19:57:08 +02:00
else if (obj == FileLineEdit)
{
2014-09-10 19:57:08 +02:00
if (ev->type() == QEvent::FocusOut)
{
setFile(FileLineEdit->text(), true);
// We don't return true here because we still want the line edit to catch the event as well
}
}
// forward the signal to the parent class
return QWidget::eventFilter(obj, ev);
}
2023-05-03 13:07:02 +02:00
auto VPE::VFileEditWidget::isDirectory() -> bool
{
return Directory;
}
void VPE::VFileEditWidget::dragEnterEvent(QDragEnterEvent* event)
{
QString tmpFileName;
2014-09-10 19:57:08 +02:00
if (checkMimeData(event->mimeData(), tmpFileName))
{
event->accept();
event->acceptProposedAction();
}
}
2015-04-15 14:44:57 +02:00
// cppcheck-suppress unusedFunction
void VPE::VFileEditWidget::dragMoveEvent(QDragMoveEvent* event)
{
event->acceptProposedAction();
}
2015-04-15 14:44:57 +02:00
// cppcheck-suppress unusedFunction
void VPE::VFileEditWidget::dragLeaveEvent(QDragLeaveEvent* event)
{
event->accept();
}
void VPE::VFileEditWidget::dropEvent(QDropEvent* event)
{
QString tmpFileName;
2014-09-10 19:57:08 +02:00
if (checkMimeData(event->mimeData(), tmpFileName))
{
setFile(tmpFileName);
emit dataChangedByUser(getFile(), this);
emit commitData(this);
event->accept();
event->acceptProposedAction();
}
}
2022-08-08 14:25:14 +02:00
auto VPE::VFileEditWidget::checkMimeData(const QMimeData* data, QString& file) const -> bool
{
if (data->hasUrls())
{
QList<QUrl> tmpUrlList = data->urls();
QFileInfo tmpFileInfo;
2022-08-08 14:25:14 +02:00
auto tmpUrl = std::find_if(tmpUrlList.cbegin(), tmpUrlList.cend(),
[](const QUrl &tmpUrl){return QFile::exists(tmpUrl.toLocalFile());});
if (tmpUrl != tmpUrlList.cend())
{
2022-08-08 14:25:14 +02:00
tmpFileInfo = QFileInfo(tmpUrl->toLocalFile());
}
2014-09-10 19:57:08 +02:00
if (checkFileFilter(tmpFileInfo.fileName()))
{
file = tmpFileInfo.absoluteFilePath();
return true;
}
}
return false;
}
2023-05-03 13:07:02 +02:00
auto VPE::VFileEditWidget::checkFileFilter(const QString &file) const -> bool
{
2014-09-10 19:57:08 +02:00
if (FilterList.isEmpty())
{
return true;
2014-09-10 19:57:08 +02:00
}
QFileInfo tmpFileInfo(file);
2014-09-10 19:57:08 +02:00
if ((Directory && !tmpFileInfo.isDir()) || (!Directory && !tmpFileInfo.isFile()))
{
return false;
2014-09-10 19:57:08 +02:00
}
2023-02-09 15:35:30 +01:00
return std::any_of(FilterList.begin(), FilterList.end(), [file](const QString &tmpFilter)
{
2023-02-09 15:35:30 +01:00
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
const QString wildcardFilter = QRegularExpression::wildcardToRegularExpression(tmpFilter);
QRegularExpression tmpRegExpFilter(QRegularExpression::anchoredPattern(wildcardFilter),
QRegularExpression::CaseInsensitiveOption);
return tmpRegExpFilter.match(file).hasMatch();
#else
QRegExp tmpRegExpFilter(tmpFilter, Qt::CaseInsensitive, QRegExp::Wildcard);
2023-02-09 15:35:30 +01:00
return tmpRegExpFilter.exactMatch(file);
#endif
});
}