Skip to content

Commit

Permalink
Fix sending function call args through proxy in Qt 6.5 (#2441)
Browse files Browse the repository at this point in the history
Wraps lists/vectors of custom types in a struct to avoid following Qt 6
errors:

    Warning: [default] QtWarning: QMetaMethod::invoke: cannot convert formal parameter 5 from QList<NotificationButton> in call to ScriptableProxy::showMessage(QString,QString,QString,int,QString,NotificationButtons)
    ERROR: Bad scriptable proxy slot call: showMessage(QString,QString,QString,int,QString,NotificationButtons)

Fixes #2411
  • Loading branch information
hluk committed Aug 28, 2023
1 parent 61879f4 commit 8844a26
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 47 deletions.
18 changes: 9 additions & 9 deletions src/scriptable/scriptable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,7 @@ QJSValue Scriptable::notification()
int msec = -1;
QString icon;
QString notificationId;
NotificationButtons buttons;
NotificationButtonList buttons;

for ( int i = 0; i < argumentCount(); ++i ) {
const auto name = arg(i++);
Expand All @@ -1526,7 +1526,7 @@ QJSValue Scriptable::notification()
button.name = arg(i);
button.script = arg(++i);
button.data = makeByteArray( argument(++i) );
buttons.append(button);
buttons.items.append(button);
} else {
return throwError("Unknown argument: " + name);
}
Expand Down Expand Up @@ -2184,12 +2184,12 @@ QJSValue Scriptable::dialog()
m_skipArguments = -1;

NamedValueList values;
values.reserve(argumentCount() / 2);
values.items.reserve(argumentCount() / 2);

for ( int i = 0; i < argumentCount(); i += 2 ) {
const QString key = arg(i);
const QJSValue value = argument(i + 1);
values.append( NamedValue(key, toVariant(value)) );
values.items.append( NamedValue(key, toVariant(value)) );
}

const auto dialogId = m_proxy->inputDialog(values);
Expand All @@ -2207,15 +2207,15 @@ QJSValue Scriptable::dialog()
});
loop.exec();

if (values.isEmpty())
if (values.items.isEmpty())
return QJSValue();

if (values.size() == 1)
return toScriptValue( values.first().value, this );
if (values.items.size() == 1)
return toScriptValue( values.items.first().value, this );

QJSValue result = m_engine->newObject();

for (const auto &value : values)
for (const auto &value : values.items)
result.setProperty( value.name, toScriptValue(value.value, this) );

return result;
Expand Down Expand Up @@ -2458,7 +2458,7 @@ QJSValue Scriptable::screenNames()

QJSValue Scriptable::queryKeyboardModifiers()
{
const auto modifiers = m_proxy->queryKeyboardModifiers();
const auto modifiers = m_proxy->queryKeyboardModifiers().items;
QStringList modifierList;
if (modifiers.testFlag(Qt::ControlModifier))
modifierList.append("Ctrl");
Expand Down
56 changes: 28 additions & 28 deletions src/scriptable/scriptableproxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,23 +87,23 @@ void registerMetaTypes() {
qRegisterMetaTypeStreamOperators<ClipboardMode>("ClipboardMode");
qRegisterMetaTypeStreamOperators<Command>("Command");
qRegisterMetaTypeStreamOperators<NamedValueList>("NamedValueList");
qRegisterMetaTypeStreamOperators<NotificationButtons>("NotificationButtons");
qRegisterMetaTypeStreamOperators<NotificationButtonList>("NotificationButtonList");
qRegisterMetaTypeStreamOperators<ScriptablePath>("ScriptablePath");
qRegisterMetaTypeStreamOperators<QVector<int>>("QVector<int>");
qRegisterMetaTypeStreamOperators<QVector<Command>>("QVector<Command>");
qRegisterMetaTypeStreamOperators<VariantMapList>("VariantMapList");
qRegisterMetaTypeStreamOperators<Qt::KeyboardModifiers>("Qt::KeyboardModifiers");
qRegisterMetaTypeStreamOperators<KeyboardModifierList>("KeyboardModifierList");
#else
qRegisterMetaType<QPointer<QWidget>>("QPointer<QWidget>");
qRegisterMetaType<ClipboardMode>("ClipboardMode");
qRegisterMetaType<Command>("Command");
qRegisterMetaType<NamedValueList>("NamedValueList");
qRegisterMetaType<NotificationButtons>("NotificationButtons");
qRegisterMetaType<NotificationButtonList>("NotificationButtonList");
qRegisterMetaType<ScriptablePath>("ScriptablePath");
qRegisterMetaType<QVector<int>>("QVector<int>");
qRegisterMetaType<QVector<Command>>("QVector<Command>");
qRegisterMetaType<VariantMapList>("VariantMapList");
qRegisterMetaType<Qt::KeyboardModifiers>("Qt::KeyboardModifiers");
qRegisterMetaType<KeyboardModifierList>("KeyboardModifierList");
#endif

registered = true;
Expand Down Expand Up @@ -183,47 +183,47 @@ void selectionRemoveInvalid(QList<QPersistentModelIndex> *indexes)

Q_DECLARE_METATYPE(QFile*)

QDataStream &operator<<(QDataStream &out, const NotificationButtons &list)
QDataStream &operator<<(QDataStream &out, const NotificationButtonList &list)
{
out << list.size();
for (const auto &button : list)
out << list.items.size();
for (const auto &button : list.items)
out << button.name << button.script << button.data;
Q_ASSERT(out.status() == QDataStream::Ok);
return out;
}

QDataStream &operator>>(QDataStream &in, NotificationButtons &list)
QDataStream &operator>>(QDataStream &in, NotificationButtonList &list)
{
decltype(list.size()) size;
decltype(list.items.size()) size;
in >> size;
list.reserve(size);
list.items.reserve(size);
for (int i = 0; i < size; ++i) {
NotificationButton button;
in >> button.name >> button.script >> button.data;
list.append(button);
list.items.append(button);
}
Q_ASSERT(in.status() == QDataStream::Ok);
return in;
}

QDataStream &operator<<(QDataStream &out, const NamedValueList &list)
{
out << list.size();
for (const auto &item : list)
out << list.items.size();
for (const auto &item : list.items)
out << item.name << item.value;
Q_ASSERT(out.status() == QDataStream::Ok);
return out;
}

QDataStream &operator>>(QDataStream &in, NamedValueList &list)
{
decltype(list.size()) size;
decltype(list.items.size()) size;
in >> size;
list.reserve(size);
list.items.reserve(size);
for (int i = 0; i < size; ++i) {
NamedValue item;
in >> item.name >> item.value;
list.append(item);
list.items.append(item);
}
Q_ASSERT(in.status() == QDataStream::Ok);
return in;
Expand Down Expand Up @@ -270,17 +270,17 @@ QDataStream &operator>>(QDataStream &in, ScriptablePath &path)
return in >> path.path;
}

QDataStream &operator<<(QDataStream &out, Qt::KeyboardModifiers value)
QDataStream &operator<<(QDataStream &out, KeyboardModifierList value)
{
return out << static_cast<int>(value);
return out << static_cast<int>(value.items);
}

QDataStream &operator>>(QDataStream &in, Qt::KeyboardModifiers &value)
QDataStream &operator>>(QDataStream &in, KeyboardModifierList &value)
{
int valueInt;
in >> valueInt;
Q_ASSERT(in.status() == QDataStream::Ok);
value = static_cast<Qt::KeyboardModifiers>(valueInt);
value.items = static_cast<Qt::KeyboardModifiers>(valueInt);
return in;
}

Expand Down Expand Up @@ -1282,7 +1282,7 @@ void ScriptableProxy::showMessage(const QString &title,
const QString &icon,
int msec,
const QString &notificationId,
const NotificationButtons &buttons)
const NotificationButtonList &buttons)
{
INVOKE2(showMessage, (title, msg, icon, msec, notificationId, buttons));

Expand All @@ -1291,7 +1291,7 @@ void ScriptableProxy::showMessage(const QString &title,
notification->setMessage(msg, Qt::AutoText);
notification->setIcon(icon);
notification->setInterval(msec);
notification->setButtons(buttons);
notification->setButtons(buttons.items);
}

QVariantMap ScriptableProxy::nextItem(const QString &tabName, int where)
Expand Down Expand Up @@ -2093,12 +2093,12 @@ int ScriptableProxy::inputDialog(const NamedValueList &values)
QIcon icon;
QVBoxLayout layout(&dialog);
QWidgetList widgets;
widgets.reserve(values.size());
widgets.reserve(values.items.size());

QString styleSheet;
QRect geometry(-1, -1, 0, 0);

for (const auto &value : values) {
for (const auto &value : values.items) {
if (value.name == ".title")
dialogTitle = value.value.toString();
else if (value.name == ".icon")
Expand Down Expand Up @@ -2154,14 +2154,14 @@ int ScriptableProxy::inputDialog(const NamedValueList &values)
return;

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

if ( inputDialog.dialog->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) );
result.items.append( NamedValue(name, value) );
}
}

Expand Down Expand Up @@ -2309,10 +2309,10 @@ QStringList ScriptableProxy::screenNames()
return result;
}

Qt::KeyboardModifiers ScriptableProxy::queryKeyboardModifiers()
KeyboardModifierList ScriptableProxy::queryKeyboardModifiers()
{
INVOKE(queryKeyboardModifiers, ());
return QApplication::queryKeyboardModifiers();
return {QApplication::queryKeyboardModifiers()};
}

QPoint ScriptableProxy::pointerPosition()
Expand Down
28 changes: 19 additions & 9 deletions src/scriptable/scriptableproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,17 @@ struct VariantMapList {
QVector<QVariantMap> items;
};

using NamedValueList = QVector<NamedValue>;
struct NamedValueList {
QList<NamedValue> items;
};

struct NotificationButtonList {
QList<NotificationButton> items;
};

struct KeyboardModifierList {
Qt::KeyboardModifiers items;
};

struct ScriptablePath {
QString path;
Expand All @@ -50,16 +60,16 @@ struct ItemSelection {

Q_DECLARE_METATYPE(NamedValueList)
Q_DECLARE_METATYPE(ScriptablePath)
Q_DECLARE_METATYPE(NotificationButtons)
Q_DECLARE_METATYPE(NotificationButtonList)
Q_DECLARE_METATYPE(VariantMapList)
Q_DECLARE_METATYPE(Qt::KeyboardModifiers)
Q_DECLARE_METATYPE(KeyboardModifierList)

#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
Q_DECLARE_METATYPE(ClipboardMode)
#endif

QDataStream &operator<<(QDataStream &out, const NotificationButtons &list);
QDataStream &operator>>(QDataStream &in, NotificationButtons &list);
QDataStream &operator<<(QDataStream &out, const NotificationButtonList &list);
QDataStream &operator>>(QDataStream &in, NotificationButtonList &list);
QDataStream &operator<<(QDataStream &out, const NamedValueList &list);
QDataStream &operator>>(QDataStream &in, NamedValueList &list);
QDataStream &operator<<(QDataStream &out, const VariantMapList &list);
Expand All @@ -68,8 +78,8 @@ QDataStream &operator<<(QDataStream &out, ClipboardMode mode);
QDataStream &operator>>(QDataStream &in, ClipboardMode &mode);
QDataStream &operator<<(QDataStream &out, const ScriptablePath &path);
QDataStream &operator>>(QDataStream &in, ScriptablePath &path);
QDataStream &operator<<(QDataStream &out, Qt::KeyboardModifiers value);
QDataStream &operator>>(QDataStream &in, Qt::KeyboardModifiers &value);
QDataStream &operator<<(QDataStream &out, KeyboardModifierList value);
QDataStream &operator>>(QDataStream &in, KeyboardModifierList &value);

class ScriptableProxy final : public QObject
{
Expand Down Expand Up @@ -131,7 +141,7 @@ public slots:
const QString &icon,
int msec,
const QString &notificationId = QString(),
const NotificationButtons &buttons = NotificationButtons());
const NotificationButtonList &buttons = NotificationButtonList());

QVariantMap nextItem(const QString &tabName, int where);
void browserMoveToClipboard(const QString &tabName, int row);
Expand Down Expand Up @@ -235,7 +245,7 @@ public slots:

QStringList screenNames();

Qt::KeyboardModifiers queryKeyboardModifiers();
KeyboardModifierList queryKeyboardModifiers();
QPoint pointerPosition();
void setPointerPosition(int x, int y);

Expand Down
5 changes: 4 additions & 1 deletion src/tests/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,12 @@ bool testStderr(const QByteArray &stderrData, TestInterface::ReadStderrFlag flag
regex(R"(QtWarning: Window position.* outside any known screen.*)"),
regex(R"(QtWarning: Populating font family aliases took .* ms. Replace uses of missing font family "Font Awesome.*" with one that exists to avoid this cost.)"),

// New in Qt 5.15.0.
// New in Qt 5.15.0
regex(R"(QtWarning: Populating font family aliases took .* ms. Replace uses of missing font family "Monospace" with one that exists to avoid this cost.)"),

// New in Qt 6.5
regex("QtWarning: Error in contacting registry"),

// KNotification bug
plain(R"(QtWarning: QLayout: Attempting to add QLayout "" to QWidget "", which already has a layout)"),
};
Expand Down

0 comments on commit 8844a26

Please sign in to comment.