mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-09-24 23:31:36 +08:00
frontend: Split Qt UI dialogs into single files per C++ class
This commit is contained in:
@@ -1,29 +1,14 @@
|
||||
#include "moc_window-extra-browsers.cpp"
|
||||
#include "window-dock-browser.hpp"
|
||||
#include "window-basic-main.hpp"
|
||||
#include "ExtraBrowsersModel.hpp"
|
||||
|
||||
#include <components/DelButton.hpp>
|
||||
#include <docks/BrowserDock.hpp>
|
||||
#include <widgets/OBSBasic.hpp>
|
||||
|
||||
#include <qt-wrappers.hpp>
|
||||
#include <QLineEdit>
|
||||
#include <QHBoxLayout>
|
||||
#include <QUuid>
|
||||
|
||||
#include <json11.hpp>
|
||||
#include <QTableView>
|
||||
|
||||
#include "ui_OBSExtraBrowsers.h"
|
||||
|
||||
using namespace json11;
|
||||
|
||||
#define OBJ_NAME_SUFFIX "_extraBrowser"
|
||||
|
||||
enum class Column : int {
|
||||
Title,
|
||||
Url,
|
||||
Delete,
|
||||
|
||||
Count,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#include "moc_ExtraBrowsersModel.cpp"
|
||||
|
||||
void ExtraBrowsersModel::Reset()
|
||||
{
|
||||
@@ -105,21 +90,6 @@ Qt::ItemFlags ExtraBrowsersModel::flags(const QModelIndex &index) const
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
class DelButton : public QPushButton {
|
||||
public:
|
||||
inline DelButton(QModelIndex index_) : QPushButton(), index(index_) {}
|
||||
|
||||
QPersistentModelIndex index;
|
||||
};
|
||||
|
||||
class EditWidget : public QLineEdit {
|
||||
public:
|
||||
inline EditWidget(QWidget *parent, QModelIndex index_) : QLineEdit(parent), index(index_) {}
|
||||
|
||||
QPersistentModelIndex index;
|
||||
};
|
||||
|
||||
void ExtraBrowsersModel::AddDeleteButton(int idx)
|
||||
{
|
||||
QTableView *widget = reinterpret_cast<QTableView *>(parent());
|
||||
@@ -282,281 +252,3 @@ void ExtraBrowsersModel::Init()
|
||||
for (int i = 0; i < items.count(); i++)
|
||||
AddDeleteButton(i);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
QWidget *ExtraBrowsersDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QLineEdit *text = new EditWidget(parent, index);
|
||||
text->installEventFilter(const_cast<ExtraBrowsersDelegate *>(this));
|
||||
text->setSizePolicy(QSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding,
|
||||
QSizePolicy::ControlType::LineEdit));
|
||||
return text;
|
||||
}
|
||||
|
||||
void ExtraBrowsersDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
QLineEdit *text = reinterpret_cast<QLineEdit *>(editor);
|
||||
text->blockSignals(true);
|
||||
text->setText(index.data().toString());
|
||||
text->blockSignals(false);
|
||||
}
|
||||
|
||||
bool ExtraBrowsersDelegate::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
QLineEdit *edit = qobject_cast<QLineEdit *>(object);
|
||||
if (!edit)
|
||||
return false;
|
||||
|
||||
if (LineEditCanceled(event)) {
|
||||
RevertText(edit);
|
||||
}
|
||||
if (LineEditChanged(event)) {
|
||||
UpdateText(edit);
|
||||
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (keyEvent->key() == Qt::Key_Tab) {
|
||||
model->TabSelection(true);
|
||||
} else if (keyEvent->key() == Qt::Key_Backtab) {
|
||||
model->TabSelection(false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ExtraBrowsersDelegate::ValidName(const QString &name) const
|
||||
{
|
||||
for (auto &item : model->items) {
|
||||
if (name.compare(item.title, Qt::CaseInsensitive) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExtraBrowsersDelegate::RevertText(QLineEdit *edit_)
|
||||
{
|
||||
EditWidget *edit = reinterpret_cast<EditWidget *>(edit_);
|
||||
int row = edit->index.row();
|
||||
int col = edit->index.column();
|
||||
bool newItem = (row == model->items.size());
|
||||
|
||||
QString oldText;
|
||||
if (col == (int)Column::Title) {
|
||||
oldText = newItem ? model->newTitle : model->items[row].title;
|
||||
} else {
|
||||
oldText = newItem ? model->newURL : model->items[row].url;
|
||||
}
|
||||
|
||||
edit->setText(oldText);
|
||||
}
|
||||
|
||||
bool ExtraBrowsersDelegate::UpdateText(QLineEdit *edit_)
|
||||
{
|
||||
EditWidget *edit = reinterpret_cast<EditWidget *>(edit_);
|
||||
int row = edit->index.row();
|
||||
int col = edit->index.column();
|
||||
bool newItem = (row == model->items.size());
|
||||
|
||||
QString text = edit->text().trimmed();
|
||||
|
||||
if (!newItem && text.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (col == (int)Column::Title) {
|
||||
QString oldText = newItem ? model->newTitle : model->items[row].title;
|
||||
bool same = oldText.compare(text, Qt::CaseInsensitive) == 0;
|
||||
|
||||
if (!same && !ValidName(text)) {
|
||||
edit->setText(oldText);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!newItem) {
|
||||
/* if edited existing item, update it*/
|
||||
switch (col) {
|
||||
case (int)Column::Title:
|
||||
model->items[row].title = text;
|
||||
break;
|
||||
case (int)Column::Url:
|
||||
model->items[row].url = text;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* if both new values filled out, create new one */
|
||||
switch (col) {
|
||||
case (int)Column::Title:
|
||||
model->newTitle = text;
|
||||
break;
|
||||
case (int)Column::Url:
|
||||
model->newURL = text;
|
||||
break;
|
||||
}
|
||||
|
||||
model->CheckToAdd();
|
||||
}
|
||||
|
||||
emit commitData(edit);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
OBSExtraBrowsers::OBSExtraBrowsers(QWidget *parent) : QDialog(parent), ui(new Ui::OBSExtraBrowsers)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
model = new ExtraBrowsersModel(ui->table);
|
||||
|
||||
ui->table->setModel(model);
|
||||
ui->table->setItemDelegateForColumn((int)Column::Title, new ExtraBrowsersDelegate(model));
|
||||
ui->table->setItemDelegateForColumn((int)Column::Url, new ExtraBrowsersDelegate(model));
|
||||
ui->table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::Stretch);
|
||||
ui->table->horizontalHeader()->setSectionResizeMode((int)Column::Delete, QHeaderView::ResizeMode::Fixed);
|
||||
ui->table->setEditTriggers(QAbstractItemView::EditTrigger::CurrentChanged);
|
||||
}
|
||||
|
||||
OBSExtraBrowsers::~OBSExtraBrowsers() {}
|
||||
|
||||
void OBSExtraBrowsers::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QDialog::closeEvent(event);
|
||||
model->Apply();
|
||||
}
|
||||
|
||||
void OBSExtraBrowsers::on_apply_clicked()
|
||||
{
|
||||
model->Apply();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void OBSBasic::ClearExtraBrowserDocks()
|
||||
{
|
||||
extraBrowserDockTargets.clear();
|
||||
extraBrowserDockNames.clear();
|
||||
extraBrowserDocks.clear();
|
||||
}
|
||||
|
||||
void OBSBasic::LoadExtraBrowserDocks()
|
||||
{
|
||||
const char *jsonStr = config_get_string(App()->GetUserConfig(), "BasicWindow", "ExtraBrowserDocks");
|
||||
|
||||
std::string err;
|
||||
Json json = Json::parse(jsonStr, err);
|
||||
if (!err.empty())
|
||||
return;
|
||||
|
||||
Json::array array = json.array_items();
|
||||
if (!array.empty())
|
||||
extraBrowserMenuDocksSeparator = ui->menuDocks->addSeparator();
|
||||
|
||||
for (Json &item : array) {
|
||||
std::string title = item["title"].string_value();
|
||||
std::string url = item["url"].string_value();
|
||||
std::string uuid = item["uuid"].string_value();
|
||||
|
||||
AddExtraBrowserDock(title.c_str(), url.c_str(), uuid.c_str(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::SaveExtraBrowserDocks()
|
||||
{
|
||||
Json::array array;
|
||||
for (int i = 0; i < extraBrowserDocks.size(); i++) {
|
||||
QDockWidget *dock = extraBrowserDocks[i].get();
|
||||
QString title = extraBrowserDockNames[i];
|
||||
QString url = extraBrowserDockTargets[i];
|
||||
QString uuid = dock->property("uuid").toString();
|
||||
Json::object obj{
|
||||
{"title", QT_TO_UTF8(title)},
|
||||
{"url", QT_TO_UTF8(url)},
|
||||
{"uuid", QT_TO_UTF8(uuid)},
|
||||
};
|
||||
array.push_back(obj);
|
||||
}
|
||||
|
||||
std::string output = Json(array).dump();
|
||||
config_set_string(App()->GetUserConfig(), "BasicWindow", "ExtraBrowserDocks", output.c_str());
|
||||
}
|
||||
|
||||
void OBSBasic::ManageExtraBrowserDocks()
|
||||
{
|
||||
if (!extraBrowsers.isNull()) {
|
||||
extraBrowsers->show();
|
||||
extraBrowsers->raise();
|
||||
return;
|
||||
}
|
||||
|
||||
extraBrowsers = new OBSExtraBrowsers(this);
|
||||
extraBrowsers->show();
|
||||
}
|
||||
|
||||
void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url, const QString &uuid, bool firstCreate)
|
||||
{
|
||||
static int panel_version = -1;
|
||||
if (panel_version == -1) {
|
||||
panel_version = obs_browser_qcef_version();
|
||||
}
|
||||
|
||||
BrowserDock *dock = new BrowserDock(title);
|
||||
QString bId(uuid.isEmpty() ? QUuid::createUuid().toString() : uuid);
|
||||
bId.replace(QRegularExpression("[{}-]"), "");
|
||||
dock->setProperty("uuid", bId);
|
||||
dock->setObjectName(title + OBJ_NAME_SUFFIX);
|
||||
dock->resize(460, 600);
|
||||
dock->setMinimumSize(80, 80);
|
||||
dock->setWindowTitle(title);
|
||||
dock->setAllowedAreas(Qt::AllDockWidgetAreas);
|
||||
|
||||
QCefWidget *browser = cef->create_widget(dock, QT_TO_UTF8(url), nullptr);
|
||||
if (browser && panel_version >= 1)
|
||||
browser->allowAllPopups(true);
|
||||
|
||||
dock->SetWidget(browser);
|
||||
|
||||
/* Add support for Twitch Dashboard panels */
|
||||
if (url.contains("twitch.tv/popout") && url.contains("dashboard/live")) {
|
||||
QRegularExpression re("twitch.tv\\/popout\\/([^/]+)\\/");
|
||||
QRegularExpressionMatch match = re.match(url);
|
||||
QString username = match.captured(1);
|
||||
if (username.length() > 0) {
|
||||
std::string script;
|
||||
script = "Object.defineProperty(document, 'referrer', { get: () => '";
|
||||
script += "https://twitch.tv/";
|
||||
script += QT_TO_UTF8(username);
|
||||
script += "/dashboard/live";
|
||||
script += "'});";
|
||||
browser->setStartupScript(script);
|
||||
}
|
||||
}
|
||||
|
||||
AddDockWidget(dock, Qt::RightDockWidgetArea, true);
|
||||
extraBrowserDocks.push_back(std::shared_ptr<QDockWidget>(dock));
|
||||
extraBrowserDockNames.push_back(title);
|
||||
extraBrowserDockTargets.push_back(url);
|
||||
|
||||
if (firstCreate) {
|
||||
dock->setFloating(true);
|
||||
|
||||
QPoint curPos = pos();
|
||||
QSize wSizeD2 = size() / 2;
|
||||
QSize dSizeD2 = dock->size() / 2;
|
||||
|
||||
curPos.setX(curPos.x() + wSizeD2.width() - dSizeD2.width());
|
||||
curPos.setY(curPos.y() + wSizeD2.height() - dSizeD2.height());
|
||||
|
||||
dock->move(curPos);
|
||||
dock->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user