Files
obs-studio/frontend/utility/MissingFilesPathItemDelegate.cpp
gxalpha 5129612b6c frontend,shared: Replace and disable contextless connect calls
# Conflicts:
#	frontend/OBSApp.cpp
2025-12-17 16:35:45 -05:00

162 lines
5.4 KiB
C++

/******************************************************************************
Copyright (C) 2019 by Dillon Pentz <dillon@vodbox.io>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include "MissingFilesPathItemDelegate.hpp"
#include <OBSApp.hpp>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QToolButton>
#include "moc_MissingFilesPathItemDelegate.cpp"
enum MissingFilesRole { EntryStateRole = Qt::UserRole, NewPathsToProcessRole };
MissingFilesPathItemDelegate::MissingFilesPathItemDelegate() : QStyledItemDelegate() {}
QWidget *MissingFilesPathItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & /* option */,
const QModelIndex &) const
{
QSizePolicy buttonSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Expanding,
QSizePolicy::ControlType::PushButton);
QWidget *container = new QWidget(parent);
auto browseCallback = [this, container]() {
const_cast<MissingFilesPathItemDelegate *>(this)->handleBrowse(container);
};
auto clearCallback = [this, container]() {
const_cast<MissingFilesPathItemDelegate *>(this)->handleClear(container);
};
QHBoxLayout *layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
QLineEdit *text = new QLineEdit();
text->setObjectName(QStringLiteral("text"));
text->setSizePolicy(QSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding,
QSizePolicy::ControlType::LineEdit));
layout->addWidget(text);
QToolButton *browseButton = new QToolButton();
browseButton->setText("...");
browseButton->setSizePolicy(buttonSizePolicy);
layout->addWidget(browseButton);
connect(browseButton, &QToolButton::clicked, this, browseCallback);
QToolButton *clearButton = new QToolButton();
QIcon icon;
icon.addFile(QString::fromUtf8(":/res/images/close.svg"), QSize(), QIcon::Mode::Normal, QIcon::State::Off);
clearButton->setIcon(icon);
clearButton->setProperty("class", "icon-close");
clearButton->setSizePolicy(buttonSizePolicy);
layout->addWidget(clearButton);
connect(clearButton, &QToolButton::clicked, this, clearCallback);
container->setLayout(layout);
container->setFocusProxy(text);
return container;
}
void MissingFilesPathItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QLineEdit *text = editor->findChild<QLineEdit *>();
text->setText(index.data().toString());
editor->setProperty(PATH_LIST_PROP, QVariant());
}
void MissingFilesPathItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
// We use the PATH_LIST_PROP property to pass a list of
// path strings from the editor widget into the model's
// NewPathsToProcessRole. This is only used when paths
// are selected through the "browse" or "delete" buttons
// in the editor. If the user enters new text in the
// text box, we simply pass that text on to the model
// as normal text data in the default role.
QVariant pathListProp = editor->property(PATH_LIST_PROP);
if (pathListProp.isValid()) {
QStringList list = editor->property(PATH_LIST_PROP).toStringList();
model->setData(index, list);
} else {
QLineEdit *lineEdit = editor->findChild<QLineEdit *>();
model->setData(index, lineEdit->text(), 0);
}
}
void MissingFilesPathItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItem localOption = option;
initStyleOption(&localOption, index);
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &localOption, painter);
}
void MissingFilesPathItemDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
{
QStyledItemDelegate::initStyleOption(option, index);
option->textElideMode = Qt::ElideMiddle;
}
void MissingFilesPathItemDelegate::handleBrowse(QWidget *container)
{
QLineEdit *text = container->findChild<QLineEdit *>();
QString currentPath = text->text();
if (currentPath.isEmpty() || currentPath.compare(QTStr("MissingFiles.Clear")) == 0)
currentPath = "";
bool isSet = false;
QString newPath =
QFileDialog::getOpenFileName(container, QTStr("MissingFiles.SelectFile"), currentPath, nullptr);
#ifdef __APPLE__
// TODO: Revisit when QTBUG-42661 is fixed
container->window()->raise();
#endif
if (!newPath.isEmpty()) {
container->setProperty(PATH_LIST_PROP, QStringList() << newPath);
isSet = true;
}
if (isSet)
emit commitData(container);
}
void MissingFilesPathItemDelegate::handleClear(QWidget *container)
{
// An empty string list will indicate that the entry is being
// blanked and should be deleted.
container->setProperty(PATH_LIST_PROP, QStringList() << QTStr("MissingFiles.Clear"));
container->findChild<QLineEdit *>()->clearFocus();
((QWidget *)container->parent())->setFocus();
emit commitData(container);
}