Skip to content

Commit

Permalink
Add event handlers
Browse files Browse the repository at this point in the history
Fixes #59
  • Loading branch information
hluk committed Dec 13, 2023
1 parent 5a798ba commit 6e44d6e
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 14 deletions.
33 changes: 33 additions & 0 deletions docs/scripting-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,39 @@ unlike in GUI, where row numbers start from 1 by default.
config("style", styleName)
.. js:function:: onItemsAdded()

Called when items are added to a tab.

The target tab is returned by `selectedTab()`.

The new items can be accessed with `selectedItemsData()`,
`selectedItemData()`, `selectedItems()` and `ItemSelection().current()`.

.. js:function:: onItemsRemoved()

Called when items are being removed from a tab.

The target tab is returned by `selectedTab()`.

The removed items can be accessed with `selectedItemsData()`,
`selectedItemData()`, `selectedItems()` and `ItemSelection().current()`.

.. js:function:: onSelectedTabChanged()

Called currently selected tab changes.

The newly selected tab is returned by `selectedTab()`.

The changed items can be accessed with `selectedItemsData()`,
`selectedItemData()`, `selectedItems()` and `ItemSelection().current()`.

.. js:function:: onItemsLoaded()

Called when items a loaded to a tab.

The target tab is returned by `selectedTab()`.

Types
-----

Expand Down
1 change: 1 addition & 0 deletions src/gui/clipboardbrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,7 @@ bool ClipboardBrowser::loadItems()
return false;

d.rowsInserted(QModelIndex(), 0, m.rowCount());
emit itemsLoaded(this);
if ( hasFocus() )
setCurrent(0);
onItemCountChanged();
Expand Down
2 changes: 2 additions & 0 deletions src/gui/clipboardbrowser.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ class ClipboardBrowser final : public QListView

void itemsChanged(const ClipboardBrowser *self);

void itemsLoaded(const ClipboardBrowser *self);

void itemSelectionChanged(const ClipboardBrowser *self);

void internalEditorStateChanged(const ClipboardBrowser *self);
Expand Down
5 changes: 5 additions & 0 deletions src/gui/commandcompleterdocumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ void addDocumentation(AddDocumentationCallback addDocumentation)
addDocumentation("open", "open(url, ...) -> bool", "Tries to open URLs in appropriate applications.");
addDocumentation("execute", "execute(argument, ..., null, stdinData, ...) -> `FinishedCommand` or `undefined`", "Executes a command.");
addDocumentation("currentWindowTitle", "String currentWindowTitle() -> string", "Returns window title of currently focused window.");
addDocumentation("currentClipboardOwner", "String currentClipboardOwner() -> string", "Returns name of the current clipboard owner.");
addDocumentation("dialog", "dialog(...)", "Shows messages or asks user for input.");
addDocumentation("menuItems", "menuItems(text...) -> string", "Opens menu with given items and returns selected item or an empty string.");
addDocumentation("menuItems", "menuItems(items[]) -> int", "Opens menu with given items and returns index of selected item or -1.");
Expand Down Expand Up @@ -171,6 +172,10 @@ void addDocumentation(AddDocumentationCallback addDocumentation)
addDocumentation("hideDataNotification", "hideDataNotification()", "Hide notification for current data.");
addDocumentation("setClipboardData", "setClipboardData()", "Sets clipboard data for menu commands.");
addDocumentation("styles", "styles() -> array of strings", "List available styles for `style` option.");
addDocumentation("onItemsAdded", "onItemsAdded()", "Called when items are added to a tab.");
addDocumentation("onItemsRemoved", "onItemsRemoved()", "Called when items are being removed from a tab.");
addDocumentation("onSelectedTabChanged", "onSelectedTabChanged()", "Called currently selected tab changes.");
addDocumentation("onItemsLoaded", "onItemsLoaded()", "Called when items a loaded to a tab.");
addDocumentation("ByteArray", "ByteArray", "Wrapper for QByteArray Qt class.");
addDocumentation("File", "File", "Wrapper for QFile Qt class.");
addDocumentation("Dir", "Dir", "Wrapper for QDir Qt class.");
Expand Down
108 changes: 95 additions & 13 deletions src/gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,18 @@ void disableActionWhenTabGroupSelected(WidgetOrAction *action, MainWindow *windo
action, &WidgetOrAction::setDisabled );
}

void addSelectionData(
QVariantMap *result,
const QModelIndexList &selectedIndexes)
{
QList<QPersistentModelIndex> selected;
selected.reserve(selectedIndexes.size());
for (const auto &index : selectedIndexes)
selected.append(index);
std::sort(selected.begin(), selected.end());
result->insert(mimeSelectedItems, QVariant::fromValue(selected));
}

/// Adds information about current tab and selection if command is triggered by user.
QVariantMap addSelectionData(
const ClipboardBrowser &c,
Expand All @@ -203,12 +215,7 @@ QVariantMap addSelectionData(
}

if ( !selectedIndexes.isEmpty() ) {
QList<QPersistentModelIndex> selected;
selected.reserve(selectedIndexes.size());
for (const auto &index : selectedIndexes)
selected.append(index);
std::sort(selected.begin(), selected.end());
result.insert(mimeSelectedItems, QVariant::fromValue(selected));
addSelectionData(&result, selectedIndexes);
}

return result;
Expand Down Expand Up @@ -1073,9 +1080,16 @@ void MainWindow::setScriptOverrides(const QVector<int> &overrides)

bool MainWindow::isScriptOverridden(int id) const
{
waitCollectOverrides();
return std::binary_search(m_overrides.begin(), m_overrides.end(), id);
}

void MainWindow::waitCollectOverrides() const
{
if (m_actionCollectOverrides && m_actionCollectOverrides->isRunning())
m_actionCollectOverrides->waitForFinished();
}

void MainWindow::onAboutToQuit()
{
if (cm)
Expand Down Expand Up @@ -1253,6 +1267,8 @@ void MainWindow::onBrowserCreated(ClipboardBrowser *browser)
this, &MainWindow::onSearchShowRequest );
connect( browser, &ClipboardBrowser::itemWidgetCreated,
this, &MainWindow::onItemWidgetCreated );
connect( browser, &ClipboardBrowser::itemsLoaded,
this, &MainWindow::onBrowserItemsLoaded );

if (browserOrNull() == browser) {
const int index = ui->tabWidget->currentIndex();
Expand All @@ -1268,6 +1284,34 @@ void MainWindow::onBrowserDestroyed(ClipboardBrowserPlaceholder *placeholder)
}
}

void MainWindow::onBrowserItemsLoaded(const ClipboardBrowser *browser)
{
if (isScriptOverridden(ScriptOverrides::OnItemsLoaded)) {
runEventHandlerScript(
QStringLiteral("onItemsLoaded()"),
createDataMap(mimeCurrentTab, browser->tabName()));
}

connect( browser->model(), &QAbstractItemModel::rowsAboutToBeRemoved,
browser, [this, browser](const QModelIndex &, int first, int last) {
if (isScriptOverridden(ScriptOverrides::OnItemsRemoved))
runItemHandlerScript(QStringLiteral("onItemsRemoved()"), browser, first, last);
} );
connect( browser->model(), &QAbstractItemModel::rowsInserted,
browser, [this, browser](const QModelIndex &, int first, int last) {
if (isScriptOverridden(ScriptOverrides::OnItemsAdded))
runItemHandlerScript(QStringLiteral("onItemsAdded()"), browser, first, last);
} );
connect( browser->model(), &QAbstractItemModel::dataChanged,
browser, [this, browser](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
if (isScriptOverridden(ScriptOverrides::OnItemsChanged)) {
runItemHandlerScript(
QStringLiteral("onItemsChanged()"),
browser, topLeft.row(), bottomRight.row());
}
} );
}

void MainWindow::onItemSelectionChanged(const ClipboardBrowser *browser)
{
if (browser == browserOrNull()) {
Expand Down Expand Up @@ -1346,7 +1390,7 @@ void MainWindow::runDisplayCommands()

if ( !isInternalActionId(m_displayActionId) ) {
m_currentDisplayItem = m_displayItemList.takeFirst();
const auto action = runScript("runDisplayCommands()", m_currentDisplayItem.data());
const auto action = runScript(QStringLiteral("runDisplayCommands()"), m_currentDisplayItem.data());
m_displayActionId = action->id();
}

Expand Down Expand Up @@ -1613,7 +1657,7 @@ void MainWindow::runMenuCommandFilters(MenuMatchCommands *menuMatchCommands, QVa
if (isRunning) {
m_sharedData->actions->setActionData(menuMatchCommands->actionId, data);
} else {
const auto act = runScript("runMenuCommandFilters()", data);
const auto act = runScript(QStringLiteral("runMenuCommandFilters()"), data);
menuMatchCommands->actionId = act->id();
}

Expand Down Expand Up @@ -1884,7 +1928,7 @@ void MainWindow::activateMenuItem(ClipboardBrowserPlaceholder *placeholder, cons
if ( m_options.trayItemPaste && !omitPaste && canPaste() ) {
if (isScriptOverridden(ScriptOverrides::Paste)) {
COPYQ_LOG("Pasting item with paste()");
runScript("paste()");
runScript(QStringLiteral("paste()"));
} else if (lastWindow) {
COPYQ_LOG( QStringLiteral("Pasting item from tray menu to: %1")
.arg(lastWindow->getTitle()) );
Expand Down Expand Up @@ -2348,7 +2392,8 @@ void MainWindow::updateCommands(QVector<Command> allCommands, bool forceSave)
reloadBrowsers();
}

runScript("collectOverrides()");
waitCollectOverrides();
m_actionCollectOverrides = runScript(QStringLiteral("collectOverrides()"));

updateContextMenu(contextMenuUpdateIntervalMsec);
updateTrayMenuCommands();
Expand Down Expand Up @@ -2404,12 +2449,43 @@ const Theme &MainWindow::theme() const
Action *MainWindow::runScript(const QString &script, const QVariantMap &data)
{
auto act = new Action();
act->setCommand(QStringList() << "copyq" << "eval" << "--" << script);
act->setCommand(
{QStringLiteral("copyq"), QStringLiteral("eval"), QStringLiteral("--"), script});
act->setData(data);
runInternalAction(act);
return act;
}

void MainWindow::runEventHandlerScript(const QString &script, const QVariantMap &data)
{
if (m_maxEventHandlerScripts == 0)
return;

--m_maxEventHandlerScripts;
if (m_maxEventHandlerScripts == 0)
log("Event handler maximum recursion reached", LogWarning);

const auto action = runScript(script, data);
action->waitForFinished();
++m_maxEventHandlerScripts;
}

void MainWindow::runItemHandlerScript(
const QString &script, const ClipboardBrowser *browser, int firstRow, int lastRow)
{
QModelIndexList indexes;
indexes.reserve(lastRow - firstRow + 1);
for (int row = firstRow; row <= lastRow; ++row) {
const auto index = browser->model()->index(row, 0);
if (index.isValid())
indexes.append(index);
}

QVariantMap data = createDataMap(mimeCurrentTab, browser->tabName());
addSelectionData(&data, indexes);
runEventHandlerScript(script, data);
}

int MainWindow::findTabIndex(const QString &name)
{
TabWidget *w = ui->tabWidget;
Expand Down Expand Up @@ -2984,6 +3060,12 @@ void MainWindow::tabChanged(int current, int)
}

setTabOrder(ui->searchBar, c);

if (isScriptOverridden(ScriptOverrides::OnSelectedTabChanged)) {
runEventHandlerScript(
QStringLiteral("onSelectedTabChanged()"),
createDataMap(mimeCurrentTab, c->tabName()));
}
}
}

Expand Down Expand Up @@ -3333,7 +3415,7 @@ void MainWindow::activateCurrentItemHelper()
if (paste) {
if (isScriptOverridden(ScriptOverrides::Paste)) {
COPYQ_LOG("Pasting item with paste()");
runScript("paste()");
runScript(QStringLiteral("paste()"));
} else if (lastWindow) {
COPYQ_LOG( QStringLiteral("Pasting item from main window to: %1")
.arg(lastWindow->getTitle()) );
Expand Down Expand Up @@ -3366,7 +3448,7 @@ void MainWindow::disableClipboardStoring(bool disable)

updateIcon();

runScript("setTitle(); showDataNotification()");
runScript(QStringLiteral("setTitle(); showDataNotification()"));

COPYQ_LOG( QString("Clipboard monitoring %1.")
.arg(m_clipboardStoringDisabled ? "disabled" : "enabled") );
Expand Down
7 changes: 7 additions & 0 deletions src/gui/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ class MainWindow final : public QMainWindow

void setScriptOverrides(const QVector<int> &overrides);
bool isScriptOverridden(int id) const;
void waitCollectOverrides() const;

signals:
/** Request clipboard change. */
Expand Down Expand Up @@ -500,6 +501,7 @@ class MainWindow final : public QMainWindow

void onBrowserCreated(ClipboardBrowser *browser);
void onBrowserDestroyed(ClipboardBrowserPlaceholder *placeholder);
void onBrowserItemsLoaded(const ClipboardBrowser *browser);

void onItemSelectionChanged(const ClipboardBrowser *browser);
void onItemsChanged(const ClipboardBrowser *browser);
Expand Down Expand Up @@ -630,6 +632,9 @@ class MainWindow final : public QMainWindow
const Theme &theme() const;

Action *runScript(const QString &script, const QVariantMap &data = QVariantMap());
void runEventHandlerScript(const QString &script, const QVariantMap &data = QVariantMap());
void runItemHandlerScript(
const QString &script, const ClipboardBrowser *browser, int firstRow, int lastRow);

void activateCurrentItemHelper();
void onItemClicked();
Expand Down Expand Up @@ -699,6 +704,8 @@ class MainWindow final : public QMainWindow
bool m_enteringSearchMode = false;

QVector<int> m_overrides;
int m_maxEventHandlerScripts = 10;
QPointer<Action> m_actionCollectOverrides;
};

#endif // MAINWINDOW_H
12 changes: 11 additions & 1 deletion src/scriptable/scriptable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2954,8 +2954,18 @@ void Scriptable::collectOverrides()

QVector<int> overrides;
const auto pasteFn = globalObject.property("paste");
if (pasteFn.property("_copyq").toInt() != 1)
if (pasteFn.property(QStringLiteral("_copyq")).toInt() != 1)
overrides.append(ScriptOverrides::Paste);
if (globalObject.hasOwnProperty(QStringLiteral("onItemsAdded")))
overrides.append(ScriptOverrides::OnItemsAdded);
if (globalObject.hasOwnProperty(QStringLiteral("onItemsRemoved")))
overrides.append(ScriptOverrides::OnItemsRemoved);
if (globalObject.hasOwnProperty(QStringLiteral("onItemsChanged")))
overrides.append(ScriptOverrides::OnItemsChanged);
if (globalObject.hasOwnProperty(QStringLiteral("onSelectedTabChanged")))
overrides.append(ScriptOverrides::OnSelectedTabChanged);
if (globalObject.hasOwnProperty(QStringLiteral("onItemsLoaded")))
overrides.append(ScriptOverrides::OnItemsLoaded);

m_proxy->setScriptOverrides(overrides);
}
Expand Down
5 changes: 5 additions & 0 deletions src/scriptable/scriptoverrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@
namespace ScriptOverrides {
enum ScriptOverrides {
Paste = 0,
OnItemsAdded = 1,
OnItemsRemoved = 2,
OnItemsChanged = 3,
OnSelectedTabChanged = 4,
OnItemsLoaded = 5,
};
}
Loading

0 comments on commit 6e44d6e

Please sign in to comment.