Skip to content

Commit

Permalink
Run inputDialog() without additional event loop
Browse files Browse the repository at this point in the history
  • Loading branch information
hluk committed Jul 22, 2018
1 parent 375c9c7 commit e6dce60
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 39 deletions.
9 changes: 9 additions & 0 deletions src/app/clipboardclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ QString messageCodeToString(int code)
switch (code) {
case CommandFunctionCallReturnValue:
return "CommandFunctionCallReturnValue";
case CommandInputDialogFinished:
return "CommandInputDialogFinished";
case CommandStop:
return "CommandStop";
default:
Expand Down Expand Up @@ -122,6 +124,11 @@ void ClipboardClient::onMessageReceived(const QByteArray &data, int messageCode)
emit functionCallResultReceived(data);
break;

case CommandInputDialogFinished: {
emit inputDialogFinished(data);
break;
}

case CommandStop: {
emit stopEventLoops();

Expand Down Expand Up @@ -227,6 +234,8 @@ void ClipboardClient::start(const QStringList &arguments)
&scriptable, &Scriptable::setInput );
connect( this, &ClipboardClient::functionCallResultReceived,
&scriptableProxy, &ScriptableProxy::setFunctionCallReturnValue );
connect( this, &ClipboardClient::inputDialogFinished,
&scriptableProxy, &ScriptableProxy::setInputDialogResult );

connect( m_socket, &ClientSocket::disconnected,
&scriptable, &Scriptable::abort );
Expand Down
1 change: 1 addition & 0 deletions src/app/clipboardclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class ClipboardClient : public QObject, public App
signals:
void functionCallResultReceived(const QByteArray &returnValue);
void inputReceived(const QByteArray &input);
void inputDialogFinished(const QByteArray &data);
void stopEventLoops();
void scriptableFinished();

Expand Down
2 changes: 2 additions & 0 deletions src/common/commandstatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ enum CommandStatus {
CommandFunctionCallReturnValue = 9,

CommandStop = 10,

CommandInputDialogFinished = 11,
};

#endif // COMMANDSTATUS_H
16 changes: 15 additions & 1 deletion src/scriptable/scriptable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1891,7 +1891,21 @@ QScriptValue Scriptable::dialog()
values.append( NamedValue(key, toVariant(value)) );
}

values = m_proxy->inputDialog(values);
const auto dialogId = m_proxy->inputDialog(values);
if ( !canContinue() )
return QScriptValue();

QEventLoop loop;
connect(this, &Scriptable::finished, &loop, &QEventLoop::quit);
connect(this, &Scriptable::stop, &loop, &QEventLoop::quit);
connect( m_proxy, &ScriptableProxy::inputDialogFinished,
&loop, [&](int finishedDialogId, const NamedValueList &result) {
if (finishedDialogId != dialogId)
return;
values = result;
loop.quit();
});
loop.exec();

if (values.isEmpty())
return QScriptValue();
Expand Down
85 changes: 50 additions & 35 deletions src/scriptable/scriptableproxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,8 @@ const char propertyWidgetName[] = "CopyQ_widget_name";
const char propertyWidgetProperty[] = "CopyQ_widget_property";

struct InputDialog {
QDialog dialog;
QDialog *dialog = nullptr;
QString defaultChoice; /// Default text for list widgets.

explicit InputDialog(QWidget *parentWindow)
: dialog(parentWindow)
{
}
};

template<typename ...Ts>
Expand Down Expand Up @@ -481,7 +476,7 @@ void installShortcutToCloseDialog(QWidget *dialog, QWidget *shortcutParent, int

QWidget *createListWidget(const QString &name, const QStringList &items, InputDialog *inputDialog)
{
QDialog *parent = &inputDialog->dialog;
QDialog *parent = inputDialog->dialog;

const QString currentText = inputDialog->defaultChoice.isNull()
? items.value(0)
Expand Down Expand Up @@ -562,7 +557,7 @@ QWidget *createTextEdit(const QString &name, const QVariant &value, QWidget *par

QWidget *createWidget(const QString &name, const QVariant &value, InputDialog *inputDialog)
{
QDialog *parent = &inputDialog->dialog;
QDialog *parent = inputDialog->dialog;

switch ( value.type() ) {
case QVariant::Bool:
Expand Down Expand Up @@ -972,6 +967,20 @@ void ScriptableProxy::setFunctionCallReturnValue(const QByteArray &bytes)
emit functionCallFinished(functionCallId, returnValue);
}

void ScriptableProxy::setInputDialogResult(const QByteArray &bytes)
{
QDataStream stream(bytes);
int dialogId;
NamedValueList result;
stream >> dialogId >> result;
if (stream.status() != QDataStream::Ok) {
log("Failed to read input dialog result", LogError);
Q_ASSERT(false);
return;
}
emit inputDialogFinished(dialogId, result);
}

QVariantMap ScriptableProxy::getActionData(int id)
{
INVOKE(getActionData, (id));
Expand Down Expand Up @@ -1628,12 +1637,14 @@ QString ScriptableProxy::currentWindowTitle()
return window ? window->getTitle() : QString();
}

NamedValueList ScriptableProxy::inputDialog(const NamedValueList &values)
int ScriptableProxy::inputDialog(const NamedValueList &values)
{
INVOKE(inputDialog, (values));

InputDialog inputDialog(m_wnd);
QDialog &dialog = inputDialog.dialog;
InputDialog inputDialog;
const auto dialogPtr = std::make_shared<QDialog>(m_wnd);
inputDialog.dialog = dialogPtr.get();
QDialog &dialog = *dialogPtr;

QIcon icon;
QVBoxLayout layout(&dialog);
Expand Down Expand Up @@ -1680,11 +1691,11 @@ NamedValueList ScriptableProxy::inputDialog(const NamedValueList &values)
if ( !styleSheet.isEmpty() )
dialog.setStyleSheet(styleSheet);

QDialogButtonBox buttons(
auto buttons = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
QObject::connect( &buttons, SIGNAL(accepted()), &dialog, SLOT(accept()) );
QObject::connect( &buttons, SIGNAL(rejected()), &dialog, SLOT(reject()) );
layout.addWidget(&buttons);
QObject::connect( buttons, SIGNAL(accepted()), &dialog, SLOT(accept()) );
QObject::connect( buttons, SIGNAL(rejected()), &dialog, SLOT(reject()) );
layout.addWidget(buttons);

installShortcutToCloseDialog(&dialog, &dialog, Qt::CTRL | Qt::Key_Enter);
installShortcutToCloseDialog(&dialog, &dialog, Qt::CTRL | Qt::Key_Return);
Expand All @@ -1693,10 +1704,29 @@ NamedValueList ScriptableProxy::inputDialog(const NamedValueList &values)
icon = appIcon();
dialog.setWindowIcon(icon);

// Rather then using QDialog::exec() to show modal dialog and block main window,
// create event loop and wait for dialog to close.
QEventLoop loop;
connect(&dialog, &QDialog::finished, &loop, &QEventLoop::quit);
int dialogId = ++m_lastInputDialogId;
connect(&dialog, &QDialog::finished, this, [=]() {
NamedValueList result;
result.reserve( widgets.size() );

if ( dialogPtr->result() ) {
for ( auto w : widgets ) {
const QString propertyName = w->property(propertyWidgetProperty).toString();
const QString name = w->property(propertyWidgetName).toString();
const QVariant value = w->property(propertyName.toUtf8().constData());
result.append( NamedValue(name, value) );
}
}

QByteArray bytes;
{
QDataStream stream(&bytes, QIODevice::WriteOnly);
stream << dialogId << result;
}

emit sendMessage(bytes, CommandInputDialogFinished);
});

// Connecting this directly to QEventLoop::quit() doesn't seem to work always.
connect(this, &ScriptableProxy::clientDisconnected, &dialog, &QDialog::reject);

Expand All @@ -1706,22 +1736,7 @@ NamedValueList ScriptableProxy::inputDialog(const NamedValueList &values)
if ( !qApp->property("CopyQ_test_id").isValid() )
raiseWindow(&dialog);

loop.exec();

if ( !dialog.result() )
return NamedValueList();

NamedValueList result;
result.reserve( widgets.size() );

for ( auto w : widgets ) {
const QString propertyName = w->property(propertyWidgetProperty).toString();
const QString name = w->property(propertyWidgetName).toString();
const QVariant value = w->property(propertyName.toUtf8().constData());
result.append( NamedValue(name, value) );
}

return result;
return dialogId;
}

void ScriptableProxy::setUserValue(const QString &key, const QVariant &value)
Expand Down
7 changes: 5 additions & 2 deletions src/scriptable/scriptableproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ class ScriptableProxy : public QObject

int actionId() const { return m_actionId; }

public slots:
void setFunctionCallReturnValue(const QByteArray &bytes);
void setInputDialogResult(const QByteArray &bytes);

public slots:
QVariantMap getActionData(int id);
void setActionData(int id, const QVariantMap &data);

Expand Down Expand Up @@ -195,7 +196,7 @@ public slots:

QString currentWindowTitle();

NamedValueList inputDialog(const NamedValueList &values);
int inputDialog(const NamedValueList &values);

void setUserValue(const QString &key, const QVariant &value);

Expand Down Expand Up @@ -245,6 +246,7 @@ public slots:

signals:
void functionCallFinished(int functionCallId, const QVariant &returnValue);
void inputDialogFinished(int dialogId, const NamedValueList &result);
void sendMessage(const QByteArray &message, int messageCode);
void clientDisconnected();

Expand Down Expand Up @@ -273,6 +275,7 @@ public slots:
int m_actionId = -1;

int m_lastFunctionCallId = -1;
int m_lastInputDialogId = -1;
};

QString pluginsPath();
Expand Down
2 changes: 1 addition & 1 deletion src/tests/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1370,7 +1370,7 @@ void Tests::commandAfterMilliseconds()

void Tests::commandAsync()
{
RUN("afterMilliseconds(0, function() { print(currentItem()); abort(); }); dialog()", "-1\n");
RUN("afterMilliseconds(0, function() { print(currentItem()); abort(); }); dialog()", "-1");
}

void Tests::classFile()
Expand Down

0 comments on commit e6dce60

Please sign in to comment.