Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions inc/liquidappconfigwindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <QGridLayout>
#include <QLabel>
#include <QListView>
#include <QLocalSocket>
#include <QPlainTextEdit>
#include <QTableView>
#include <QTabWidget>
Expand All @@ -24,15 +25,23 @@ class LiquidAppConfigDialog : public QDialog

public slots:
void save();
void reject() override;

private:
void bindShortcuts(void);
static QFrame* separator(void);
static QString getSettingsRequiringRestart(QSettings* liquidAppConfig);
void previewBackground(const QColor& color);
void sendPreview(const QByteArray& message);

bool isEditingExistingBool = false;
bool isPlanningToRunBool = false;

// Connection to the Liquid app being edited (if running), for previewing changes
QLocalSocket* liquidAppConnection = Q_NULLPTR;
bool hasPreviewedChanges = false;
QTimer* cssPreviewTimer = Q_NULLPTR;

QAction* quitAction;

QColor* backgroundColor;
Expand Down
6 changes: 6 additions & 0 deletions inc/liquidappwindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public slots:
void loadFinished(bool ok);
void loadStarted(void);
void reloadLiquidAppConfig(void);
void setBackground(const QColor& color);
void setAdditionalCss(const QString& css);
void setFrameless(const bool frameless);
void setScrollBarsHidden(const bool hidden);
void onIconChanged(QIcon icon);
void stopLoadingOrExitFullScreenMode(void);
void takeSnapshotSlot(void);
Expand Down Expand Up @@ -137,7 +141,9 @@ public slots:
void saveLiquidAppConfig(void);
void applyAllowedDomains(void);
void applyBackgroundColor(void);
void recreateNativeWindow(void);
void applyWebSettings(void);
void applyAdditionalCssAndJs(void);
static QString getAdditionalCssScript(const QString& css);
void setupContextMenu(void);
};
8 changes: 8 additions & 0 deletions inc/lqd.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,16 @@
#define LQD_INSTANCE_MSG_RAISE "raise"
#define LQD_INSTANCE_MSG_QUIT "quit" // Liquid apps only
#define LQD_INSTANCE_MSG_RELOAD_SETTINGS "reload-settings" // Liquid apps only
#define LQD_INSTANCE_MSG_PREVIEW_BG "preview-background" // Liquid apps only, followed by a space and #AARRGGBB (or "none")
#define LQD_INSTANCE_MSG_PREVIEW_CSS "preview-css" // Liquid apps only, followed by a space and base64-encoded CSS
#define LQD_INSTANCE_MSG_PREVIEW_FRAME "preview-frame" // Liquid apps only, followed by a space and "on" or "off"
#define LQD_INSTANCE_MSG_PREVIEW_SCROLL "preview-scrollbars" // Liquid apps only, followed by a space and "on" or "off"
#define LQD_INSTANCE_MSG_STARTED "started" // Main window only, followed by a space and Liquid app's name
#define LQD_ACTIVATION_TOKEN_TIMEOUT 500 // Milliseconds to wait for the compositor to issue an activation token
#define LQD_PREVIEW_CONNECT_TIMEOUT 100 // Milliseconds to wait for connecting to a Liquid app for previewing settings
#define LQD_RECREATED_WINDOW_RAISE_DELAY 100 // Milliseconds to wait before bringing a re-created native window to front
#define LQD_SCROLLBARS_RELAYOUT_DELAY 100 // Milliseconds to keep the document unscrollable for, to make it redo its scrollbars
#define LQD_CSS_PREVIEW_DELAY 150 // Milliseconds to wait after the last keystroke before previewing CSS
#define LQD_INSTANCE_STOP_TIMEOUT 5000 // Milliseconds to wait for a Liquid app to quit

/* Names of scripts Liquid injects into web pages */
Expand Down
103 changes: 91 additions & 12 deletions src/liquidappconfigwindow.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <QDir>
#include <QElapsedTimer>
#include <QLocalSocket>
#include <QNetworkCookie>
#include <QWebEngineProfile>

Expand Down Expand Up @@ -320,6 +321,11 @@ LiquidAppConfigDialog::LiquidAppConfigDialog(QWidget* parent, QString liquidAppN
}
}

// Show or hide scrollbars in the running Liquid app right away
connect(hideScrollBarsCheckBox, &QCheckBox::toggled, this, [this](const bool isChecked) {
sendPreview(QByteArray(LQD_INSTANCE_MSG_PREVIEW_SCROLL " ") + ((isChecked) ? "off" : "on"));
});

appearanceTabWidgetLayout->addWidget(hideScrollBarsCheckBox);
}
#endif
Expand All @@ -339,6 +345,11 @@ LiquidAppConfigDialog::LiquidAppConfigDialog(QWidget* parent, QString liquidAppN
}
}

// Remove or bring back the running Liquid app's window frame right away
connect(removeWindowFrameCheckBox, &QCheckBox::toggled, this, [this](const bool isChecked) {
sendPreview(QByteArray(LQD_INSTANCE_MSG_PREVIEW_FRAME " ") + ((isChecked) ? "off" : "on"));
});

appearanceTabWidgetLayout->addWidget(removeWindowFrameCheckBox);
}

Expand Down Expand Up @@ -378,16 +389,29 @@ LiquidAppConfigDialog::LiquidAppConfigDialog(QWidget* parent, QString liquidAppN
customBackgroundColorButtonLayout->addWidget(customBackgroundColorButton);

connect(customBackgroundColorButton, &QPushButton::clicked, [&]() {
const QColorDialog::ColorDialogOptions options = QColorDialog::ShowAlphaChannel;
QColor color = QColorDialog::getColor(*backgroundColor, this, tr("Pick custom background color"), options);
QColorDialog colorDialog(*backgroundColor, this);
colorDialog.setWindowTitle(tr("Pick custom background color"));
colorDialog.setOptions(QColorDialog::ShowAlphaChannel);

if (color.isValid()) {
if (!useCustomBackgroundCheckBox->isChecked()) {
useCustomBackgroundCheckBox->setChecked(true);
}
// Show colors in the running Liquid app as they're being picked
connect(&colorDialog, &QColorDialog::currentColorChanged, this, [this](const QColor& color) {
previewBackground(color);
});

if (colorDialog.exec() == QDialog::Accepted && colorDialog.selectedColor().isValid()) {
const QColor color = colorDialog.selectedColor();

*backgroundColor = color;
customBackgroundColorButton->setStyleSheet(buttonStyle.arg(backgroundColor->name(QColor::HexArgb)).arg(fontSize));

if (!useCustomBackgroundCheckBox->isChecked()) {
useCustomBackgroundCheckBox->setChecked(true); // Previews the color too
} else {
previewBackground(color);
}
} else if (hasPreviewedChanges) {
// Picking got cancelled, go back to previewing whatever was there before
previewBackground((useCustomBackgroundCheckBox->isChecked()) ? *backgroundColor : QColor());
}
});
}
Expand All @@ -398,6 +422,10 @@ LiquidAppConfigDialog::LiquidAppConfigDialog(QWidget* parent, QString liquidAppN
bool enabledInConfig = existingLiquidAppConfig->value(LQD_CFG_KEY_NAME_USE_CUSTOM_BG, false).toBool();
useCustomBackgroundCheckBox->setChecked(enabledInConfig);
}

connect(useCustomBackgroundCheckBox, &QCheckBox::toggled, this, [this](const bool isChecked) {
previewBackground((isChecked) ? *backgroundColor : QColor());
});
}

// Additional CSS text area
Expand All @@ -413,10 +441,22 @@ LiquidAppConfigDialog::LiquidAppConfigDialog(QWidget* parent, QString liquidAppN
additionalCssTextArea->setPlaceholderText(tr("/* put your custom CSS here */"));
connect(additionalCssTextArea, &QPlainTextEdit::textChanged, [=]{ style()->polish(additionalCssTextArea); });

// Repaint the running Liquid app as its CSS is being edited (shortly after typing stops)
cssPreviewTimer = new QTimer(this);
cssPreviewTimer->setSingleShot(true);
cssPreviewTimer->setInterval(LQD_CSS_PREVIEW_DELAY);
connect(cssPreviewTimer, &QTimer::timeout, this, [this]() {
// Base64, since messages are newline-terminated and CSS may have line breaks in it
sendPreview(QByteArray(LQD_INSTANCE_MSG_PREVIEW_CSS " ") + additionalCssTextArea->toPlainText().toUtf8().toBase64());
});

if (isEditingExistingBool) {
additionalCssTextArea->setPlainText(existingLiquidAppConfig->value(LQD_CFG_KEY_NAME_ADDITIONAL_CSS).toString());
}

// Connected only now, to not preview what's been loaded from the file
connect(additionalCssTextArea, &QPlainTextEdit::textChanged, cssPreviewTimer, QOverload<>::of(&QTimer::start));

appearanceTabWidgetLayout->addWidget(additionalCssTextArea);
}
}
Expand Down Expand Up @@ -1153,6 +1193,9 @@ void LiquidAppConfigDialog::save()

tempLiquidAppConfig->sync();

// A pending CSS preview is no longer needed, the saved CSS gets applied below
cssPreviewTimer->stop();

// Apply new settings to the Liquid app if it's running
if (isEditingExistingBool) {
const QString instanceId = LQD_INSTANCE_ID_APP_PREFIX + appName;
Expand Down Expand Up @@ -1181,10 +1224,50 @@ void LiquidAppConfigDialog::save()
accept();
}

void LiquidAppConfigDialog::previewBackground(const QColor& color)
{
const QByteArray colorName = (color.isValid()) ? color.name(QColor::HexArgb).toUtf8() : QByteArray("none");

sendPreview(QByteArray(LQD_INSTANCE_MSG_PREVIEW_BG " ") + colorName);
}

void LiquidAppConfigDialog::sendPreview(const QByteArray& message)
{
// Only applies to Liquid apps that already exist (and are running)
if (!isEditingExistingBool) {
return;
}

if (liquidAppConnection == Q_NULLPTR) {
liquidAppConnection = new QLocalSocket(this);
liquidAppConnection->connectToServer(SingleInstance::serverName(LQD_INSTANCE_ID_APP_PREFIX + nameInput->text()));
liquidAppConnection->waitForConnected(LQD_PREVIEW_CONNECT_TIMEOUT);
}

if (liquidAppConnection->state() == QLocalSocket::ConnectedState) {
liquidAppConnection->write(message + "\n");
liquidAppConnection->flush();
hasPreviewedChanges = true;
}
}

void LiquidAppConfigDialog::reject()
{
// Don't let a pending CSS preview arrive after the settings have been restored
cssPreviewTimer->stop();

// Bring back what's been previewed so far to how it is in the saved settings
if (hasPreviewedChanges && liquidAppConnection != Q_NULLPTR && liquidAppConnection->state() == QLocalSocket::ConnectedState) {
liquidAppConnection->write(LQD_INSTANCE_MSG_RELOAD_SETTINGS "\n");
liquidAppConnection->flush();
}

QDialog::reject();
}

QString LiquidAppConfigDialog::getSettingsRequiringRestart(QSettings* liquidAppConfig)
{
// Proxy settings get picked up by the web engine only upon start,
// and window transparency can't be turned on or off once the window is shown
// Proxy settings get picked up by the web engine only upon start
static const QStringList keys = {
LQD_CFG_KEY_NAME_USE_PROXY,
LQD_CFG_KEY_NAME_PROXY_USE_SOCKS,
Expand All @@ -1200,10 +1283,6 @@ QString LiquidAppConfigDialog::getSettingsRequiringRestart(QSettings* liquidAppC
values << ((liquidAppConfig->contains(key)) ? liquidAppConfig->value(key).toString() : QStringLiteral("<unset>"));
}

const bool isTranslucent = liquidAppConfig->value(LQD_CFG_KEY_NAME_USE_CUSTOM_BG, false).toBool()
&& QColor(liquidAppConfig->value(LQD_CFG_KEY_NAME_CUSTOM_BG_COLOR).toString()).alpha() < 255;
values << ((isTranslucent) ? "translucent" : "opaque");

return values.join('\n');
}

Expand Down
Loading
Loading