mirror of
https://github.com/pbek/QOwnNotes.git
synced 2025-06-28 21:09:52 +00:00
Update links for new webpage (#1897)
This commit is contained in:
parent
e44844c519
commit
41da7a442e
139 changed files with 325749 additions and 325654 deletions
24
docs/scripting/examples/absolute-media-links.qml
Normal file
24
docs/scripting/examples/absolute-media-links.qml
Normal file
|
@ -0,0 +1,24 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script will make the paths of inserted media files absolute in the markdown link (tested on Linux)
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This function is called when media file is inserted into the note
|
||||
*
|
||||
* @param fileName string the file path of the source media file before it was copied to the media folder
|
||||
* @param mediaMarkdownText string the markdown text of the media file, e.g. 
|
||||
* @return string the new markdown text of the media file
|
||||
*/
|
||||
function callInsertMediaHook(fileName, mediaMarkdownText) {
|
||||
// get the path of the current note folder
|
||||
var path = script.currentNoteFolderPath();
|
||||
|
||||
// Windows users might want to add an additional slash in front of the path
|
||||
//path = "/" + path;
|
||||
|
||||
// make the path of inserted media files absolute
|
||||
return mediaMarkdownText.replace(new RegExp("media", "g"), path + "/media");
|
||||
}
|
||||
}
|
23
docs/scripting/examples/autocompletion.qml
Normal file
23
docs/scripting/examples/autocompletion.qml
Normal file
|
@ -0,0 +1,23 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script is an example for adding text to the autocompletion list
|
||||
*/
|
||||
Script {
|
||||
/**
|
||||
* Hook to feed the autocompletion with tags if the current word starts with an "@"
|
||||
*/
|
||||
function autocompletionHook() {
|
||||
// get the current word plus non-word-characters before the word to also get the "@"-character
|
||||
var word = script.noteTextEditCurrentWord(true);
|
||||
|
||||
if (!word.startsWith("@")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// cut the "@" off of the string and do a substring search for tags
|
||||
var tags = script.searchTagsByName(word.substr(1));
|
||||
return tags;
|
||||
}
|
||||
}
|
37
docs/scripting/examples/callback.qml
Normal file
37
docs/scripting/examples/callback.qml
Normal file
|
@ -0,0 +1,37 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script is a short example of how to use detatched processes and callbacks
|
||||
* to relieve the UI thread.
|
||||
* Visit http://docs.qownnotes.org/ for more information about scripting
|
||||
*/
|
||||
Script {
|
||||
|
||||
function log(txt) {
|
||||
script.log("[callback-example] " + txt);
|
||||
}
|
||||
|
||||
function init() {
|
||||
log("init")
|
||||
for (var i = 0; i < 100; i++) {
|
||||
var dur = Math.floor(Math.random() * 10) + 1;
|
||||
script.startDetachedProcess("sleep", [`${dur}s`], "callback-example", i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when a script thread is done executing.
|
||||
* Hint: thread[1]==0 helps to determine if a bulk of started processes for a certain identifier is done.
|
||||
*
|
||||
* @param {QString} callBackIdentifier - the provided id when calling startDetachedProcess()
|
||||
* @param {QString} resultSet - the result of the process
|
||||
* @param {QVariantList} cmd - the entire command array [0-executablePath, 1-parameters, 2-exitCode]
|
||||
* @param {QVariantList} thread - the thread information array [0-passed callbackParameter, 1-remaining threads for this identifier]
|
||||
*/
|
||||
function onDetachedProcessCallback(callBackIdentifier, resultSet, cmd, thread) {
|
||||
if (callBackIdentifier == "callback-example") {
|
||||
log(`#${thread[1]} i[${thread[0]}] t${cmd[1]}`);
|
||||
}
|
||||
}
|
||||
}
|
79
docs/scripting/examples/custom-actions.qml
Normal file
79
docs/scripting/examples/custom-actions.qml
Normal file
|
@ -0,0 +1,79 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script is an example for creating custom actions, that can be invoked
|
||||
* via menu entries and buttons
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom actions
|
||||
*/
|
||||
function init() {
|
||||
// create a menu entry "Open with KWrite" with a button "KWrite"
|
||||
script.registerCustomAction("openWithKWrite", "Open with KWrite", "KWrite");
|
||||
|
||||
// create a menu entry "Create meeting note" with a button and a freedesktop theme icon
|
||||
script.registerCustomAction("createMeetingNote", "Create meeting note", "Meeting note", "task-new");
|
||||
|
||||
// create a menu entry "No button here", but no button for it
|
||||
script.registerCustomAction("noButtonAction", "No button here");
|
||||
|
||||
// create a menu entry to transform text with rot13
|
||||
script.registerCustomAction("transformTextRot13", "Transform selected text with rot13", "rot13", "text-wrap", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
script.log("customActionInvoked - " + identifier);
|
||||
|
||||
switch (identifier) {
|
||||
// open the current note with KWrite
|
||||
case "openWithKWrite":
|
||||
var note = script.currentNote();
|
||||
var fileName = note.fullNoteFilePath;
|
||||
script.startDetachedProcess("kwrite", [fileName]);
|
||||
break;
|
||||
|
||||
// create a new note with a custom content
|
||||
case "createMeetingNote":
|
||||
var date = new Date();
|
||||
// create the headline
|
||||
// we are removing the ":", because they should not be in the filename of the note
|
||||
var text = "Meeting note " + date.toISOString().replace(/:/g, ".") + "\n";
|
||||
var underline = "";
|
||||
|
||||
// add the underline for the headline
|
||||
for (var i = 0; i < (text.length - 1); i++) {
|
||||
underline += "=";
|
||||
}
|
||||
|
||||
// add some text to our meeting note
|
||||
text += underline + "\n\n## Important points\n\n\n## Things to remember\n\n";
|
||||
|
||||
// add the text that is currently in the clipboard
|
||||
text += script.clipboard();
|
||||
|
||||
// create a new note
|
||||
script.createNote(text);
|
||||
break;
|
||||
|
||||
// transform selected text with rot13
|
||||
case "transformTextRot13":
|
||||
var text = script.noteTextEditSelectedText();
|
||||
|
||||
// do the rot13 transformation
|
||||
text = text.replace(/[a-zA-Z]/g, function(c){
|
||||
return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
|
||||
});
|
||||
|
||||
script.noteTextEditWrite(text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
31
docs/scripting/examples/custom-new-note-headline.qml
Normal file
31
docs/scripting/examples/custom-new-note-headline.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script is an example how to modify the headline of new notes
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This function is called before a note note is created
|
||||
*
|
||||
* It allows you to modify the headline of the note before it is created
|
||||
* Note that you have to take care about a unique note name, otherwise
|
||||
* the new note will not be created, it will just be found in the note list
|
||||
*
|
||||
* You can use this method for creating note templates
|
||||
*
|
||||
* @param headline text that would be used to create the headline
|
||||
* @return {string} the headline of the note
|
||||
*/
|
||||
function handleNewNoteHeadlineHook(headline) {
|
||||
var text = headline + " - my custom note name " + "\n";
|
||||
var underline = "";
|
||||
|
||||
// add the underline
|
||||
for (var i = 0; i < (text.length - 1); i++) {
|
||||
underline += "=";
|
||||
}
|
||||
|
||||
return text + underline;
|
||||
}
|
||||
}
|
20
docs/scripting/examples/custom-stylesheet.qml
Normal file
20
docs/scripting/examples/custom-stylesheet.qml
Normal file
|
@ -0,0 +1,20 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script adds custom styles to the application
|
||||
*
|
||||
* You can get the object names from the *.ui files, for example
|
||||
* https://github.com/pbek/QOwnNotes/blob/develop/src/mainwindow.ui
|
||||
*
|
||||
* Take a look at http://doc.qt.io/qt-5/stylesheet-reference.html for
|
||||
* a reference of what styles are available.
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Adds custom styles
|
||||
*/
|
||||
function init() {
|
||||
// add a custom stylesheet to increase font size in the note list and set a font
|
||||
script.addStyleSheet("QTreeWidget#noteTreeWidget {font-family: Pacifico; font-size: 28px;}");
|
||||
}
|
||||
}
|
20
docs/scripting/examples/disable-readonly-mode.qml
Normal file
20
docs/scripting/examples/disable-readonly-mode.qml
Normal file
|
@ -0,0 +1,20 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script will disable the read-only mode if a note is double clicked
|
||||
*/
|
||||
Script {
|
||||
/**
|
||||
* This function is called after a note was double clicked
|
||||
*
|
||||
* @param {NoteApi} note - the note object that was clicked
|
||||
*/
|
||||
function noteDoubleClickedHook(note) {
|
||||
// disable the read-only mode
|
||||
script.triggerMenuAction("actionAllow_note_editing", 1);
|
||||
|
||||
// focus the note text edit
|
||||
mainWindow.focusNoteTextEdit();
|
||||
}
|
||||
}
|
31
docs/scripting/examples/encryption-keybase.qml
Normal file
31
docs/scripting/examples/encryption-keybase.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script will encrypt and decrypt notes with https://keybase.io
|
||||
*
|
||||
* You have to use your keybase user instead of "pbek"
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This is called when the script is loaded by QOwnNotes
|
||||
*/
|
||||
function init() {
|
||||
// disable the password dialog
|
||||
script.encryptionDisablePassword();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when text has to be encrypted or decrypted
|
||||
*
|
||||
* @param text string the text to encrypt or decrypt
|
||||
* @param password string the password
|
||||
* @param decrypt bool if false encryption is demanded, if true decryption is demanded
|
||||
* @return the encrypted decrypted text
|
||||
*/
|
||||
function encryptionHook(text, password, decrypt) {
|
||||
// encrypt or decrypt text with keybase.io for user pbek
|
||||
var param = decrypt ? ["decrypt"] : ["encrypt", "pbek"];
|
||||
var result = script.startSynchronousProcess("/usr/bin/keybase", param, text);
|
||||
return result;
|
||||
}
|
||||
}
|
33
docs/scripting/examples/encryption-pgp.qml
Normal file
33
docs/scripting/examples/encryption-pgp.qml
Normal file
|
@ -0,0 +1,33 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script will encrypt and decrypt notes with PGP
|
||||
*
|
||||
* You have to use your own public key instead of "F5161BD3"
|
||||
* Decryption only will work if you don't have to enter a password
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This is called when the script is loaded by QOwnNotes
|
||||
*/
|
||||
function init() {
|
||||
// disable the password dialog
|
||||
script.encryptionDisablePassword();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when text has to be encrypted or decrypted
|
||||
*
|
||||
* @param text string the text to encrypt or decrypt
|
||||
* @param password string the password
|
||||
* @param decrypt bool if false encryption is demanded, if true decryption is demanded
|
||||
* @return the encrypted decrypted text
|
||||
*/
|
||||
function encryptionHook(text, password, decrypt) {
|
||||
// encrypt the text for public key "F5161BD3" or decrypt with gpg
|
||||
// decryption only will work if you don't have to enter a password
|
||||
var param = decrypt ? ["--decrypt"] : ["--encrypt", "--armor", "-r", "F5161BD3"];
|
||||
var result = script.startSynchronousProcess("/usr/bin/gpg", param, text);
|
||||
return result;
|
||||
}
|
||||
}
|
31
docs/scripting/examples/encryption-rot13.qml
Normal file
31
docs/scripting/examples/encryption-rot13.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script will "encrypt" and "decrypt" notes with ROT13
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This is called when the script is loaded by QOwnNotes
|
||||
*/
|
||||
function init() {
|
||||
// disable the password dialog
|
||||
script.encryptionDisablePassword();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when text has to be encrypted or decrypted
|
||||
*
|
||||
* @param text string the text to encrypt or decrypt
|
||||
* @param password string the password
|
||||
* @param decrypt bool if false encryption is demanded, if true decryption is demanded
|
||||
* @return the encrypted decrypted text
|
||||
*/
|
||||
function encryptionHook(text, password, decrypt) {
|
||||
// do the rot13 transformation
|
||||
text = text.replace(/[a-zA-Z]/g, function(c){
|
||||
return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
|
||||
});
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
150
docs/scripting/examples/example.qml
Normal file
150
docs/scripting/examples/example.qml
Normal file
|
@ -0,0 +1,150 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script is a generic example of some functions that will be called by QOwnNotes
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This is called when the script is loaded by QOwnNotes
|
||||
*/
|
||||
function init() {
|
||||
script.log("Script init");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when a note gets stored to disk
|
||||
* You cannot modify stored notes, that would be a mess since
|
||||
* you are most likely editing them by hand at the same time
|
||||
*
|
||||
* @param {Note} note - the note object of the stored note
|
||||
*/
|
||||
function onNoteStored(note) {
|
||||
script.log("fileName was stored!");
|
||||
script.log(note.id);
|
||||
script.log(note.name);
|
||||
script.log(note.fileName);
|
||||
|
||||
// tagNames() returns a list of all tag names
|
||||
var tagNameList = note.tagNames();
|
||||
script.log(tagNameList);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when a note gets stored to disk if
|
||||
* "Allow note file name to be different from headline" is enabled
|
||||
* in the settings
|
||||
*
|
||||
* It allows you to modify the name of the note file
|
||||
* Return an empty string if the file name of the note should
|
||||
* not be modified
|
||||
*
|
||||
* @param {Note} note - the note object of the stored note
|
||||
* @return {string} the file name of the note
|
||||
*/
|
||||
function handleNoteTextFileNameHook(note) {
|
||||
script.log(note.id);
|
||||
script.log(note.name);
|
||||
script.log(note.fileName);
|
||||
|
||||
// tagNames() returns a list of all tag names
|
||||
var tagNameList = note.tagNames();
|
||||
script.log(tagNameList);
|
||||
|
||||
// don't actually change anything
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the note name is determined for a note
|
||||
*
|
||||
* It allows you to modify the name of the note that is viewed
|
||||
*
|
||||
* Return an empty string if the name of the note should not be modified
|
||||
*
|
||||
* @param {NoteApi} note - the note object of the stored note
|
||||
* @return {string} the name of the note
|
||||
*/
|
||||
function handleNoteNameHook(note) {
|
||||
return note.name + " some text";
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the markdown html of a note is generated
|
||||
*
|
||||
* It allows you to modify this html
|
||||
* This is for example called before by the note preview
|
||||
*
|
||||
* @param {Note} note - the note object
|
||||
* @param {string} html - the html that is about to being rendered
|
||||
* @param {string} forExport - true if the html is used for an export, false for the preview
|
||||
* @return {string} the modified html or an empty string if nothing should be modified
|
||||
*/
|
||||
function noteToMarkdownHtmlHook(note, html, forExport) {
|
||||
script.log("noteToMarkdownHtmlHook was called");
|
||||
|
||||
// show a custom headline and a horizontal ruler on top of the preview
|
||||
return html.replace("body>", "body><h1>Custom preview for note " + note.name + "</h1><hr />");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when media file is inserted into the note
|
||||
* If this function is defined in multiple scripts, then the first script that returns a non-empty string wins
|
||||
*
|
||||
* @param fileName string the file path of the source media file before it was copied to the media folder
|
||||
* @param mediaMarkdownText string the markdown text of the media file, e.g. 
|
||||
* @return string the new markdown text of the media file
|
||||
*/
|
||||
function insertMediaHook(fileName, mediaMarkdownText) {
|
||||
script.log("mediafile was inserted: " + fileName);
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when html or a media file is pasted to a note with `Ctrl + Shift + V`
|
||||
*
|
||||
* @param text text of the QMimeData object
|
||||
* @param html html of the QMimeData object
|
||||
* @returns the string that should be inserted instead of the text from the QMimeData object
|
||||
*/
|
||||
function insertingFromMimeDataHook(text, html) {
|
||||
script.log("text was pasted: " + text);
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* This starts a timer that triggers every 30 seconds
|
||||
*/
|
||||
property QtObject timer: Timer {
|
||||
interval: 30000
|
||||
repeat: true
|
||||
running: true
|
||||
|
||||
property int count: 0
|
||||
|
||||
onTriggered: {
|
||||
count++;
|
||||
script.log("count = " + count);
|
||||
|
||||
var note = script.currentNote();
|
||||
if (note) {
|
||||
script.log(note.id);
|
||||
script.log(note.name);
|
||||
script.log(note.fileName);
|
||||
|
||||
// the tags property returns a list of assigned tag objects
|
||||
var tags = note.tags;
|
||||
|
||||
// print out all tag names
|
||||
for (var i in tags) {
|
||||
var tag = tags[i];
|
||||
script.log(tag.name);
|
||||
}
|
||||
|
||||
// tagNames() returns a list of all tag names
|
||||
var tagNameList = note.tagNames();
|
||||
script.log(tagNameList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script will execute an external program every time a note was written to the disk
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This function is called when a note gets stored to disk
|
||||
* You cannot modify stored notes, that would be a mess since
|
||||
* you are most likely editing them by hand at the same time
|
||||
*
|
||||
* @param {Note} note - the note object of the stored note
|
||||
*/
|
||||
function onNoteStored(note) {
|
||||
// execute an external program
|
||||
// try not to alter the note file or QOwnNotes will try to update
|
||||
// the file every time you change the note
|
||||
script.startDetachedProcess("/path/to/my/program", [note.fileName]);
|
||||
|
||||
script.log("program was executed for file: " + note.fileName);
|
||||
}
|
||||
}
|
53
docs/scripting/examples/export-notes-as-one-html.qml
Normal file
53
docs/scripting/examples/export-notes-as-one-html.qml
Normal file
|
@ -0,0 +1,53 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
import com.qownnotes.noteapi 1.0
|
||||
|
||||
/**
|
||||
* This script exports multiple notes as one HTML file
|
||||
*/
|
||||
Script {
|
||||
/**
|
||||
* Initializes the custom actions
|
||||
*/
|
||||
function init() {
|
||||
script.registerCustomAction("exportHTML", "Export notes as html file",
|
||||
"", "", false, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "exportHTML") {
|
||||
return;
|
||||
}
|
||||
|
||||
var noteIds = script.selectedNotesIds();
|
||||
|
||||
if (noteIds.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var html = "";
|
||||
|
||||
noteIds.forEach(function (noteId){
|
||||
var note = script.fetchNoteById(noteId);
|
||||
var noteHtml = note.toMarkdownHtml();
|
||||
|
||||
// TODO: multiple html headers have to be removed
|
||||
html += noteHtml;
|
||||
});
|
||||
|
||||
var filePath = script.getSaveFileName("Please select where to store the HTML",
|
||||
"Notes.html", "HTML (*.html)");
|
||||
|
||||
if (filePath == "") {
|
||||
return;
|
||||
}
|
||||
|
||||
script.writeToFile(filePath, html);
|
||||
}
|
||||
}
|
44
docs/scripting/examples/external-note-diff.qml
Normal file
44
docs/scripting/examples/external-note-diff.qml
Normal file
|
@ -0,0 +1,44 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script adds a menu entry to the context menu of the note list to diff selected notes in an external diff program
|
||||
* The path of the diff program can be selected in the script settings of the script
|
||||
*/
|
||||
Script {
|
||||
property string executablePath;
|
||||
|
||||
// register your settings variables so the user can set them in the script settings
|
||||
property variant settingsVariables: [
|
||||
{
|
||||
"identifier": "executablePath",
|
||||
"name": "Path of external diff program",
|
||||
"description": "Please select the path to the executable:",
|
||||
"type": "file",
|
||||
"default": "kdiff3",
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Initializes the custom actions
|
||||
*/
|
||||
function init() {
|
||||
script.registerCustomAction("externalNoteDiff", "Diff selected notes", "", "", false, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "externalNoteDiff") {
|
||||
return;
|
||||
}
|
||||
|
||||
// start the diff program with the selected note paths as parameters
|
||||
var params = script.selectedNotesPaths();
|
||||
script.startDetachedProcess(executablePath, params);
|
||||
}
|
||||
}
|
31
docs/scripting/examples/external-note-open.qml
Normal file
31
docs/scripting/examples/external-note-open.qml
Normal file
|
@ -0,0 +1,31 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script allows you to configure an external editor (or an other application) that should open
|
||||
* a note when it is double clicked in the note list
|
||||
*/
|
||||
Script {
|
||||
property string executablePath;
|
||||
|
||||
// register your settings variables so the user can set them in the script settings
|
||||
property variant settingsVariables: [
|
||||
{
|
||||
"identifier": "executablePath",
|
||||
"name": "Path of external editor",
|
||||
"description": "Please select the path to the executable:",
|
||||
"type": "file",
|
||||
"default": "kate",
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* This function is called after a note was double clicked
|
||||
*
|
||||
* @param {NoteApi} note - the note object that was clicked
|
||||
*/
|
||||
function noteDoubleClickedHook(note) {
|
||||
// start the editor with the note path as parameters
|
||||
script.startDetachedProcess(executablePath, [note.fullNoteFilePath]);
|
||||
}
|
||||
}
|
29
docs/scripting/examples/favorite-note.qml
Normal file
29
docs/scripting/examples/favorite-note.qml
Normal file
|
@ -0,0 +1,29 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button that adds a "favorite" tag to the current note
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
// create the menu entry
|
||||
script.registerCustomAction("favoriteNote", "Favorite note", "fav", "bookmark-new");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
switch (identifier) {
|
||||
// add a "favorite" tag to the current note
|
||||
case "favoriteNote":
|
||||
script.tagCurrentNote("favorite");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
41
docs/scripting/examples/input-dialogs.qml
Normal file
41
docs/scripting/examples/input-dialogs.qml
Normal file
|
@ -0,0 +1,41 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This example script with input dialogs as custom actions
|
||||
*/
|
||||
Script {
|
||||
/**
|
||||
* Initializes the custom actions
|
||||
*/
|
||||
function init() {
|
||||
script.registerCustomAction("inputDialogGetItem", "Combo box");
|
||||
script.registerCustomAction("questionMessageBox", "Question message box");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
script.log("customActionInvoked - " + identifier);
|
||||
|
||||
switch (identifier) {
|
||||
// open an input dialog with a select box
|
||||
case "inputDialogGetItem":
|
||||
var result = script.inputDialogGetItem(
|
||||
"combo box", "Please select an item", ["Item 1", "Item 2", "Item 3"]);
|
||||
script.log(result);
|
||||
break;
|
||||
case "questionMessageBox":
|
||||
// show a question message box with an apply and a help button
|
||||
// see: https://doc.qt.io/qt-5/qmessagebox.html#StandardButton-enum
|
||||
var result = script.questionMessageBox(
|
||||
"The text I want to show", "Some optional title", 0x01000000|0x02000000, 0x02000000);
|
||||
script.log(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,340 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script detects if a GitHub issue url is in the clipboard and downloads the page
|
||||
* so it can parse the headline from it to paste a markdown headline and a link
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This function is called when html or a media file is pasted to a note with `Ctrl + Shift + V`
|
||||
*
|
||||
* @param text text of the QMimeData object
|
||||
* @param html html of the QMimeData object
|
||||
* @returns the string that should be inserted instead of the text from the QMimeData object
|
||||
*/
|
||||
function insertingFromMimeDataHook(text, html) {
|
||||
text = text.trim();
|
||||
|
||||
// http://www.regexpal.com is your friend
|
||||
// check if the pasted text is a GitHub issue url
|
||||
var re = /^http[s]?:\/\/github\.com.+\/issues\//igm;
|
||||
if (re.test(text)) {
|
||||
script.log("found GitHub issue url in clipboard: " + text);
|
||||
|
||||
// download matched GitHub url
|
||||
var output = script.downloadUrlToString(text);
|
||||
|
||||
// parse the headline
|
||||
var re2 = /<span class="\s*js-issue-title">([^>]+)<\/span>/im
|
||||
var result2 = re2.exec(output);
|
||||
|
||||
if (result2 !== null) {
|
||||
var headline = entityToHtml(result2[1].trim());
|
||||
script.log("found headline: " + headline);
|
||||
|
||||
// generate markdown to paste
|
||||
var result = "## " + headline + "\n- <" + text + ">\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
script.log("no headline was found!");
|
||||
} else {
|
||||
script.log("no GitHub issue url was found");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces html entities to characters
|
||||
*/
|
||||
function entityToHtml(string) {
|
||||
var entity_table = {
|
||||
34: """, // Quotation mark. Not required
|
||||
38: "&", // Ampersand. Applied before everything else in the application
|
||||
60: "<", // Less-than sign
|
||||
62: ">", // Greater-than sign
|
||||
63: "?", // Question mark
|
||||
111: "o", // Latin small letter o
|
||||
160: " ", // Non-breaking space
|
||||
161: "¡", // Inverted exclamation mark
|
||||
162: "¢", // Cent sign
|
||||
163: "£", // Pound sign
|
||||
164: "¤", // Currency sign
|
||||
165: "¥", // Yen sign
|
||||
166: "¦", // Broken vertical bar
|
||||
167: "§", // Section sign
|
||||
168: "¨", // Diaeresis
|
||||
169: "©", // Copyright sign
|
||||
170: "ª", // Feminine ordinal indicator
|
||||
171: "«", // Left-pointing double angle quotation mark
|
||||
172: "¬", // Not sign
|
||||
173: "­", // Soft hyphen
|
||||
174: "®", // Registered sign
|
||||
175: "¯", // Macron
|
||||
176: "°", // Degree sign
|
||||
177: "±", // Plus-minus sign
|
||||
178: "²", // Superscript two
|
||||
179: "³", // Superscript three
|
||||
180: "´", // Acute accent
|
||||
181: "µ", // Micro sign
|
||||
182: "¶", // Pilcrow sign
|
||||
183: "·", // Middle dot
|
||||
184: "¸", // Cedilla
|
||||
185: "¹", // Superscript one
|
||||
186: "º", // Masculine ordinal indicator
|
||||
187: "»", // Right-pointing double angle quotation mark
|
||||
188: "¼", // Vulgar fraction one-quarter
|
||||
189: "½", // Vulgar fraction one-half
|
||||
190: "¾", // Vulgar fraction three-quarters
|
||||
191: "¿", // Inverted question mark
|
||||
192: "À", // A with grave
|
||||
193: "Á", // A with acute
|
||||
194: "Â", // A with circumflex
|
||||
195: "Ã", // A with tilde
|
||||
196: "Ä", // A with diaeresis
|
||||
197: "Å", // A with ring above
|
||||
198: "Æ", // AE
|
||||
199: "Ç", // C with cedilla
|
||||
200: "È", // E with grave
|
||||
201: "É", // E with acute
|
||||
202: "Ê", // E with circumflex
|
||||
203: "Ë", // E with diaeresis
|
||||
204: "Ì", // I with grave
|
||||
205: "Í", // I with acute
|
||||
206: "Î", // I with circumflex
|
||||
207: "Ï", // I with diaeresis
|
||||
208: "Ð", // Eth
|
||||
209: "Ñ", // N with tilde
|
||||
210: "Ò", // O with grave
|
||||
211: "Ó", // O with acute
|
||||
212: "Ô", // O with circumflex
|
||||
213: "Õ", // O with tilde
|
||||
214: "Ö", // O with diaeresis
|
||||
215: "×", // Multiplication sign
|
||||
216: "Ø", // O with stroke
|
||||
217: "Ù", // U with grave
|
||||
218: "Ú", // U with acute
|
||||
219: "Û", // U with circumflex
|
||||
220: "Ü", // U with diaeresis
|
||||
221: "Ý", // Y with acute
|
||||
222: "Þ", // Thorn
|
||||
223: "ß", // Sharp s. Also known as ess-zed
|
||||
224: "à", // a with grave
|
||||
225: "á", // a with acute
|
||||
226: "â", // a with circumflex
|
||||
227: "ã", // a with tilde
|
||||
228: "ä", // a with diaeresis
|
||||
229: "å", // a with ring above
|
||||
230: "æ", // ae. Also known as ligature ae
|
||||
231: "ç", // c with cedilla
|
||||
232: "è", // e with grave
|
||||
233: "é", // e with acute
|
||||
234: "ê", // e with circumflex
|
||||
235: "ë", // e with diaeresis
|
||||
236: "ì", // i with grave
|
||||
237: "í", // i with acute
|
||||
238: "î", // i with circumflex
|
||||
239: "ï", // i with diaeresis
|
||||
240: "ð", // eth
|
||||
241: "ñ", // n with tilde
|
||||
242: "ò", // o with grave
|
||||
243: "ó", // o with acute
|
||||
244: "ô", // o with circumflex
|
||||
245: "õ", // o with tilde
|
||||
246: "ö", // o with diaeresis
|
||||
247: "÷", // Division sign
|
||||
248: "ø", // o with stroke. Also known as o with slash
|
||||
249: "ù", // u with grave
|
||||
250: "ú", // u with acute
|
||||
251: "û", // u with circumflex
|
||||
252: "ü", // u with diaeresis
|
||||
253: "ý", // y with acute
|
||||
254: "þ", // thorn
|
||||
255: "ÿ", // y with diaeresis
|
||||
264: "Ĉ", // Latin capital letter C with circumflex
|
||||
265: "ĉ", // Latin small letter c with circumflex
|
||||
338: "Œ", // Latin capital ligature OE
|
||||
339: "œ", // Latin small ligature oe
|
||||
352: "Š", // Latin capital letter S with caron
|
||||
353: "š", // Latin small letter s with caron
|
||||
372: "Ŵ", // Latin capital letter W with circumflex
|
||||
373: "ŵ", // Latin small letter w with circumflex
|
||||
374: "Ŷ", // Latin capital letter Y with circumflex
|
||||
375: "ŷ", // Latin small letter y with circumflex
|
||||
376: "Ÿ", // Latin capital letter Y with diaeresis
|
||||
402: "ƒ", // Latin small f with hook, function, florin
|
||||
710: "ˆ", // Modifier letter circumflex accent
|
||||
732: "˜", // Small tilde
|
||||
913: "Α", // Alpha
|
||||
914: "Β", // Beta
|
||||
915: "Γ", // Gamma
|
||||
916: "Δ", // Delta
|
||||
917: "Ε", // Epsilon
|
||||
918: "Ζ", // Zeta
|
||||
919: "Η", // Eta
|
||||
920: "Θ", // Theta
|
||||
921: "Ι", // Iota
|
||||
922: "Κ", // Kappa
|
||||
923: "Λ", // Lambda
|
||||
924: "Μ", // Mu
|
||||
925: "Ν", // Nu
|
||||
926: "Ξ", // Xi
|
||||
927: "Ο", // Omicron
|
||||
928: "Π", // Pi
|
||||
929: "Ρ", // Rho
|
||||
931: "Σ", // Sigma
|
||||
932: "Τ", // Tau
|
||||
933: "Υ", // Upsilon
|
||||
934: "Φ", // Phi
|
||||
935: "Χ", // Chi
|
||||
936: "Ψ", // Psi
|
||||
937: "Ω", // Omega
|
||||
945: "α", // alpha
|
||||
946: "β", // beta
|
||||
947: "γ", // gamma
|
||||
948: "δ", // delta
|
||||
949: "ε", // epsilon
|
||||
950: "ζ", // zeta
|
||||
951: "η", // eta
|
||||
952: "θ", // theta
|
||||
953: "ι", // iota
|
||||
954: "κ", // kappa
|
||||
955: "λ", // lambda
|
||||
956: "μ", // mu
|
||||
957: "ν", // nu
|
||||
958: "ξ", // xi
|
||||
959: "ο", // omicron
|
||||
960: "π", // pi
|
||||
961: "ρ", // rho
|
||||
962: "ς", // sigmaf
|
||||
963: "σ", // sigma
|
||||
964: "τ", // tau
|
||||
965: "υ", // upsilon
|
||||
966: "φ", // phi
|
||||
967: "χ", // chi
|
||||
968: "ψ", // psi
|
||||
969: "ω", // omega
|
||||
977: "ϑ", // Theta symbol
|
||||
978: "ϒ", // Greek upsilon with hook symbol
|
||||
982: "ϖ", // Pi symbol
|
||||
8194: " ", // En space
|
||||
8195: " ", // Em space
|
||||
8201: " ", // Thin space
|
||||
8204: "‌", // Zero width non-joiner
|
||||
8205: "‍", // Zero width joiner
|
||||
8206: "‎", // Left-to-right mark
|
||||
8207: "‏", // Right-to-left mark
|
||||
8211: "–", // En dash
|
||||
8212: "—", // Em dash
|
||||
8216: "‘", // Left single quotation mark
|
||||
8217: "’", // Right single quotation mark
|
||||
8218: "‚", // Single low-9 quotation mark
|
||||
8220: "“", // Left double quotation mark
|
||||
8221: "”", // Right double quotation mark
|
||||
8222: "„", // Double low-9 quotation mark
|
||||
8224: "†", // Dagger
|
||||
8225: "‡", // Double dagger
|
||||
8226: "•", // Bullet
|
||||
8230: "…", // Horizontal ellipsis
|
||||
8240: "‰", // Per mille sign
|
||||
8242: "′", // Prime
|
||||
8243: "″", // Double Prime
|
||||
8249: "‹", // Single left-pointing angle quotation
|
||||
8250: "›", // Single right-pointing angle quotation
|
||||
8254: "‾", // Overline
|
||||
8260: "⁄", // Fraction Slash
|
||||
8364: "€", // Euro sign
|
||||
8472: "℘", // Script capital
|
||||
8465: "ℑ", // Blackletter capital I
|
||||
8476: "ℜ", // Blackletter capital R
|
||||
8482: "™", // Trade mark sign
|
||||
8501: "ℵ", // Alef symbol
|
||||
8592: "←", // Leftward arrow
|
||||
8593: "↑", // Upward arrow
|
||||
8594: "→", // Rightward arrow
|
||||
8595: "↓", // Downward arrow
|
||||
8596: "↔", // Left right arrow
|
||||
8629: "↵", // Downward arrow with corner leftward. Also known as carriage return
|
||||
8656: "⇐", // Leftward double arrow. ISO 10646 does not say that lArr is the same as the 'is implied by' arrow but also does not have any other character for that function. So ? lArr can be used for 'is implied by' as ISOtech suggests
|
||||
8657: "⇑", // Upward double arrow
|
||||
8658: "⇒", // Rightward double arrow. ISO 10646 does not say this is the 'implies' character but does not have another character with this function so ? rArr can be used for 'implies' as ISOtech suggests
|
||||
8659: "⇓", // Downward double arrow
|
||||
8660: "⇔", // Left-right double arrow
|
||||
// Mathematical Operators
|
||||
8704: "∀", // For all
|
||||
8706: "∂", // Partial differential
|
||||
8707: "∃", // There exists
|
||||
8709: "∅", // Empty set. Also known as null set and diameter
|
||||
8711: "∇", // Nabla. Also known as backward difference
|
||||
8712: "∈", // Element of
|
||||
8713: "∉", // Not an element of
|
||||
8715: "∋", // Contains as member
|
||||
8719: "∏", // N-ary product. Also known as product sign. Prod is not the same character as U+03A0 'greek capital letter pi' though the same glyph might be used for both
|
||||
8721: "∑", // N-ary summation. Sum is not the same character as U+03A3 'greek capital letter sigma' though the same glyph might be used for both
|
||||
8722: "−", // Minus sign
|
||||
8727: "∗", // Asterisk operator
|
||||
8729: "∙", // Bullet operator
|
||||
8730: "√", // Square root. Also known as radical sign
|
||||
8733: "∝", // Proportional to
|
||||
8734: "∞", // Infinity
|
||||
8736: "∠", // Angle
|
||||
8743: "∧", // Logical and. Also known as wedge
|
||||
8744: "∨", // Logical or. Also known as vee
|
||||
8745: "∩", // Intersection. Also known as cap
|
||||
8746: "∪", // Union. Also known as cup
|
||||
8747: "∫", // Integral
|
||||
8756: "∴", // Therefore
|
||||
8764: "∼", // tilde operator. Also known as varies with and similar to. The tilde operator is not the same character as the tilde, U+007E, although the same glyph might be used to represent both
|
||||
8773: "≅", // Approximately equal to
|
||||
8776: "≈", // Almost equal to. Also known as asymptotic to
|
||||
8800: "≠", // Not equal to
|
||||
8801: "≡", // Identical to
|
||||
8804: "≤", // Less-than or equal to
|
||||
8805: "≥", // Greater-than or equal to
|
||||
8834: "⊂", // Subset of
|
||||
8835: "⊃", // Superset of. Note that nsup, 'not a superset of, U+2283' is not covered by the Symbol font encoding and is not included.
|
||||
8836: "⊄", // Not a subset of
|
||||
8838: "⊆", // Subset of or equal to
|
||||
8839: "⊇", // Superset of or equal to
|
||||
8853: "⊕", // Circled plus. Also known as direct sum
|
||||
8855: "⊗", // Circled times. Also known as vector product
|
||||
8869: "⊥", // Up tack. Also known as orthogonal to and perpendicular
|
||||
8901: "⋅", // Dot operator. The dot operator is not the same character as U+00B7 middle dot
|
||||
// Miscellaneous Technical
|
||||
8968: "⌈", // Left ceiling. Also known as an APL upstile
|
||||
8969: "⌉", // Right ceiling
|
||||
8970: "⌊", // left floor. Also known as APL downstile
|
||||
8971: "⌋", // Right floor
|
||||
9001: "⟨", // Left-pointing angle bracket. Also known as bra. Lang is not the same character as U+003C 'less than'or U+2039 'single left-pointing angle quotation mark'
|
||||
9002: "⟩", // Right-pointing angle bracket. Also known as ket. Rang is not the same character as U+003E 'greater than' or U+203A 'single right-pointing angle quotation mark'
|
||||
// Geometric Shapes
|
||||
9642: "▪", // Black small square
|
||||
9643: "▫", // White small square
|
||||
9674: "◊", // Lozenge
|
||||
// Miscellaneous Symbols
|
||||
9702: "◦", // White bullet
|
||||
9824: "♠", // Black (filled) spade suit
|
||||
9827: "♣", // Black (filled) club suit. Also known as shamrock
|
||||
9829: "♥", // Black (filled) heart suit. Also known as shamrock
|
||||
9830: "♦" // Black (filled) diamond suit
|
||||
}
|
||||
|
||||
for (var i in entity_table) {
|
||||
for (var i in entity_table) {
|
||||
if (i != 38) {
|
||||
string = string.replace(new RegExp(entity_table[i], "g"), String.fromCharCode(i));
|
||||
}
|
||||
}
|
||||
|
||||
string = string.replace(new RegExp("&#(x?)(\\d+);", "g"), function(match, p1, p2, string) {
|
||||
|
||||
return String.fromCharCode(((p1 == 'x') ? parseInt(p2, 16) : p2));
|
||||
|
||||
});
|
||||
|
||||
string = string.replace(new RegExp(entity_table[38], "g"), String.fromCharCode(38));
|
||||
return string;
|
||||
}
|
||||
}
|
||||
}
|
45
docs/scripting/examples/journal-entry.qml
Normal file
45
docs/scripting/examples/journal-entry.qml
Normal file
|
@ -0,0 +1,45 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button to create or jump to the current date's journal entry
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
script.registerCustomAction("journalEntry", "Create or open a journal entry", "Journal", "document-new");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "journalEntry") {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the date headline
|
||||
var m = new Date();
|
||||
var headline = m.getFullYear() + ("0" + (m.getMonth()+1)).slice(-2) + ("0" + m.getDate()).slice(-2);
|
||||
|
||||
var fileName = headline + ".md";
|
||||
var note = script.fetchNoteByFileName(fileName);
|
||||
|
||||
// check if note was found
|
||||
if (note.id > 0) {
|
||||
// jump to the note if it was found
|
||||
script.log("found journal entry: " + headline);
|
||||
script.setCurrentNote(note);
|
||||
} else {
|
||||
// create a new journal entry note if it wasn't found
|
||||
// keep in mind that the note will not be created instantly on the disk
|
||||
script.log("creating new journal entry: " + headline);
|
||||
script.createNote(headline + "\n========\n\n");
|
||||
}
|
||||
}
|
||||
}
|
49
docs/scripting/examples/meeting-note.qml
Normal file
49
docs/scripting/examples/meeting-note.qml
Normal file
|
@ -0,0 +1,49 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button to create or jump to the current date's meeting note
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
script.registerCustomAction("meetingNote", "Create or open a meeting note", "Meeting", "document-new");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "meetingNote") {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the date headline
|
||||
var m = new Date();
|
||||
var headline = "Teammeeting " + m.getFullYear() + "-" + ("0" + (m.getMonth()+1)).slice(-2) + "-" + ("0" + m.getDate()).slice(-2);
|
||||
|
||||
var fileName = headline + ".md";
|
||||
var note = script.fetchNoteByFileName(fileName);
|
||||
|
||||
// check if note was found
|
||||
if (note.id > 0) {
|
||||
// jump to the note if it was found
|
||||
script.log("found meeting note: " + headline);
|
||||
script.setCurrentNote(note);
|
||||
} else {
|
||||
// create a new meeting note if it wasn't found
|
||||
// keep in mind that the note will not be created instantly on the disk
|
||||
script.log("creating new meeting note: " + headline);
|
||||
script.createNote(headline + "\n====================\n\n");
|
||||
|
||||
// tag the current note
|
||||
script.tagCurrentNote("meeting");
|
||||
script.tagCurrentNote("fuf");
|
||||
}
|
||||
}
|
||||
}
|
118
docs/scripting/examples/note-from-5pm-mail.qml
Normal file
118
docs/scripting/examples/note-from-5pm-mail.qml
Normal file
|
@ -0,0 +1,118 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button that parses the text that was copied
|
||||
* from a task email of the webservice 5pm and creates a new note with a headline,
|
||||
* the link to the task and the description
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
// create a menu entry "New 5pm note" with a button and a freedesktop theme icon
|
||||
script.registerCustomAction("new5pmNote", "New 5pm note", "5pm", "task-new");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
switch (identifier) {
|
||||
// create a new note from a 5pm mail text in the clipboard
|
||||
case "new5pmNote":
|
||||
// get the text that is currently in the clipboard
|
||||
text = script.clipboard();
|
||||
|
||||
// http://www.regexpal.com is your friend
|
||||
var re1 = /^(.+)\sStart Datum/igm;
|
||||
var result1 = re1.exec(text);
|
||||
|
||||
if (result1 === null) {
|
||||
re1 = /^Neue Aufgabe von [\w\s]+$\s\s^(.+)$/igm;
|
||||
result1 = re1.exec(text);
|
||||
}
|
||||
|
||||
if (result1 === null) {
|
||||
re1 = /^Nachricht aktualisiert von [\w\s]+$\s\s^Aufgabe: (.+)$/igm;
|
||||
result1 = re1.exec(text);
|
||||
}
|
||||
|
||||
if (result1 === null) {
|
||||
re1 = /^Neue Nachricht erstellt von [\w\s]+$\s\s^Aufgabe: (.+)$/igm;
|
||||
result1 = re1.exec(text);
|
||||
}
|
||||
|
||||
var re2 = /^Direkter Zugriff hier: (http.+\d+)$/im;
|
||||
var result2 = re2.exec(text);
|
||||
|
||||
var re3 = /^Projekt: .+\nBeschreibung: ((.|\n)+)^Priorität: /igm;
|
||||
var result3 = re3.exec(text);
|
||||
|
||||
if (result3 === null) {
|
||||
re3 = /^Projekt: .+\n((.|\n)+)^Direkter Zugriff hier: /igm;
|
||||
result3 = re3.exec(text);
|
||||
}
|
||||
|
||||
script.log("result1: " + result1);
|
||||
script.log("result2: " + result2);
|
||||
// script.log(result3);
|
||||
|
||||
// return an empty string if we didn't find anything
|
||||
if ((result1 === null) || (result2 === null)) {
|
||||
script.log("no 5pm task was found");
|
||||
return "";
|
||||
}
|
||||
|
||||
var url = result2[1];
|
||||
// script.log("url: " + url);
|
||||
|
||||
var re4 = /task=(\d+)/i;
|
||||
var result4 = re4.exec(url);
|
||||
// script.log("result4: " + result4);
|
||||
|
||||
var id = result4[1];
|
||||
var headline = result1[1] + " (" + id + ")";
|
||||
|
||||
// add the headline of the task
|
||||
var text = headline + "\n";
|
||||
|
||||
// add "=" characters so that the headline is really a headline
|
||||
for (var i = 0; i < headline.length; i++) {
|
||||
text += "=";
|
||||
}
|
||||
|
||||
// add the url to the task
|
||||
text += "\n\n- <" + url + ">";
|
||||
|
||||
// add the description of the task
|
||||
if (result3 !== null) {
|
||||
var description = result3[1];
|
||||
text += "\n\n" + description
|
||||
}
|
||||
|
||||
// add a date headline
|
||||
var m = new Date();
|
||||
var dateString =
|
||||
("0" + m.getDate()).slice(-2) + "." +
|
||||
("0" + (m.getMonth()+1)).slice(-2) + "." +
|
||||
(" " + m.getFullYear()).slice(-2);
|
||||
text += "\n\n## " + dateString + "\n\n";
|
||||
|
||||
// create a new note
|
||||
script.createNote(text);
|
||||
|
||||
// tag the current note
|
||||
script.tagCurrentNote("todo");
|
||||
|
||||
// workaround because the parsers don't seem to work every time
|
||||
script.reloadScriptingEngine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
127
docs/scripting/examples/note-from-bitrix-task.qml
Normal file
127
docs/scripting/examples/note-from-bitrix-task.qml
Normal file
|
@ -0,0 +1,127 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button that parses the text that was copied
|
||||
* from a task webpage of the webservice bitrix24 and creates a new note with a headline,
|
||||
* the link to the task and the description
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
// create a menu entry "New Bitrix note" with a button and a freedesktop theme icon
|
||||
script.registerCustomAction("newBitrixTaskNote", "New Bitrix task note", "Bitrix", "task-new");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
switch (identifier) {
|
||||
// create a new note from a Bitrix task webpage text in the clipboard
|
||||
// like from https://yourname.bitrix24.com/workgroups/group/10/tasks/task/view/150/
|
||||
case "newBitrixTaskNote":
|
||||
// get the text that is currently in the clipboard
|
||||
var html = script.clipboard(true);
|
||||
|
||||
script.log(html);
|
||||
|
||||
// https://regex101.com is your friend
|
||||
// var headlineRegExp = /<span class="pagetitle-inner".*?>(.+?)<\/span>/im;
|
||||
var headlineRegExp = /<span id="pagetitle".*?>(.+?)<\/?span/im;
|
||||
var headlineMatch = headlineRegExp.exec(html);
|
||||
var headline = headlineMatch !== null ? headlineMatch[1] : "";
|
||||
// remove the "aufgabe" text and all "/"
|
||||
headline = headline.replace("(aufgabe #", "(#").replace(/\s*\//igm, "");
|
||||
|
||||
if (headline == "") {
|
||||
script.informationMessageBox("No Bitrix task headline was found!", "Bitrix task note");
|
||||
return;
|
||||
}
|
||||
|
||||
// add the task id to the headline
|
||||
var taskIdRegExp = /<div class="task-detail-subtitle-status.*?".*?>Aufgabe #(\d+)/im;
|
||||
var taskIdMatch = taskIdRegExp.exec(html);
|
||||
if (taskIdMatch !== null) {
|
||||
headline += " (#" + taskIdMatch[1] + ")";
|
||||
}
|
||||
|
||||
var descriptionRegExp = /<div.*? id="task-detail-description".*?>(.+?)<\/div>/im;
|
||||
var descriptionMatch = descriptionRegExp.exec(html);
|
||||
var description = descriptionMatch !== null ? descriptionMatch[1] : "";
|
||||
|
||||
// replace links
|
||||
// description = description.replace(/<a href="(.+?)".*?>(.+?)<\/a>/gim, "[$2]($1)");
|
||||
description = description.replace(/<a href="(.+?)".*?>(.+?)<\/a>/gim, "<$1>");
|
||||
|
||||
// transform html breaks to \n and remove all other tags
|
||||
description = description.replace(/<br.*?>/gim, "\n").replace(/<.+?>/gim, "");
|
||||
|
||||
// var urlRegExp = /<form name="COMMENTS_.+?".*? action="(.+?)" method/im;
|
||||
var urlRegExp = /<a href="(.+?\d+\/tasks\/task\/view\/d+\/)[\?#].*?" class="main-buttons-item-link"/im;
|
||||
var urlMatch = urlRegExp.exec(html);
|
||||
var url = urlMatch !== null ? urlMatch[1] : "";
|
||||
|
||||
// fallback url parsing
|
||||
if (url == "") {
|
||||
var urlRegExp = /<\/span><a href="(.+?)[\?#].*?" class="task-view-button edit.*?"/im;
|
||||
var urlMatch = urlRegExp.exec(html);
|
||||
var url = urlMatch !== null ? urlMatch[1] : "";
|
||||
|
||||
// we got the edit-url, but we want the view-url
|
||||
url = url.replace("task/edit", "task/view");
|
||||
}
|
||||
|
||||
// script.log("headline");
|
||||
// script.log(headline);
|
||||
// script.log(url);
|
||||
// script.log(descriptionMatch);
|
||||
// script.log(description);
|
||||
// script.log(url);
|
||||
|
||||
// add the headline of the task
|
||||
var text = headline + "\n";
|
||||
|
||||
// add "=" characters so that the headline is really a headline
|
||||
for (var i = 0; i < headline.length; i++) {
|
||||
text += "=";
|
||||
}
|
||||
|
||||
// add the url to the task
|
||||
if (url != "") {
|
||||
text += "\n\n- <" + url + ">";
|
||||
}
|
||||
|
||||
// add the description of the task
|
||||
if (description != "") {
|
||||
text += "\n\n" + description;
|
||||
}
|
||||
|
||||
text = text.replace(/>/gim, ">").replace(/</gim, "<");
|
||||
|
||||
// add a date headline
|
||||
var m = new Date();
|
||||
var dateString =
|
||||
("0" + m.getDate()).slice(-2) + "." +
|
||||
("0" + (m.getMonth()+1)).slice(-2) + "." +
|
||||
m.getFullYear();
|
||||
text += "\n\n## " + dateString + "\n\n";
|
||||
|
||||
// create a new note
|
||||
script.createNote(text);
|
||||
|
||||
// tag the current note
|
||||
script.tagCurrentNote("todo");
|
||||
|
||||
// workaround because the parsers don't seem to work every time
|
||||
script.reloadScriptingEngine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
108
docs/scripting/examples/note-from-jira-issue.qml
Normal file
108
docs/scripting/examples/note-from-jira-issue.qml
Normal file
|
@ -0,0 +1,108 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button that parses the text that was copied
|
||||
* from an issue webpage of Jira and creates a new note with a headline,
|
||||
* the link to the issue and the description
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
// create a menu entry "New Jira note" with a button and a freedesktop theme icon
|
||||
script.registerCustomAction("newJiraIssueNote", "New Jira issue note", "Jira", "task-new");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "newJiraIssueNote") {
|
||||
return;
|
||||
}
|
||||
|
||||
// create a new note from a Jira issue webpage text in the clipboard
|
||||
// like from https://jira.madsack-online.de/browse/EZ-127185
|
||||
|
||||
// get the text that is currently in the clipboard
|
||||
var html = script.clipboard(true);
|
||||
|
||||
// script.log(html);
|
||||
|
||||
// https://regex101.com is your friend
|
||||
var headlineRegExp = /<h1 id="summary-val".*?>(.+?)<\/?h1>/im;
|
||||
var headlineMatch = headlineRegExp.exec(html);
|
||||
var headline = headlineMatch !== null ? headlineMatch[1] : "";
|
||||
// remove all /, " and '
|
||||
headline = headline.replace(/\s*\//igm, "").replace(/["']/igm, "").replace(/<.+?>/igm, "");
|
||||
|
||||
if (headline == "") {
|
||||
script.informationMessageBox("No Jira issue headline was found!", "Jira issue note");
|
||||
return;
|
||||
}
|
||||
|
||||
// add the issue id to the headline
|
||||
var issueIdRegExp = /<a class="issue-link" data-issue-key="([^"]+)" href="(http[^"]+\/browse\/[^"]+)" id="key-val"/im;
|
||||
var issueIdMatch = issueIdRegExp.exec(html);
|
||||
var url;
|
||||
if (issueIdMatch !== null) {
|
||||
headline += " (" + issueIdMatch[1] + ")";
|
||||
url = issueIdMatch[2];
|
||||
}
|
||||
|
||||
var descriptionRegExp = /<div.*? id="description-val".*?>(.+?)<\/div>/im;
|
||||
var descriptionMatch = descriptionRegExp.exec(html);
|
||||
var description = descriptionMatch !== null ? descriptionMatch[1] : "";
|
||||
|
||||
// replace links
|
||||
// description = description.replace(/<a href="(.+?)".*?>(.+?)<\/a>/gim, "[$2]($1)");
|
||||
description = description.replace(/<a href="(.+?)".*?>(.+?)<\/a>/gim, "<$1>");
|
||||
|
||||
// transform html breaks to \n, <p> into \n\n and remove all other tags
|
||||
description = description.replace(/<br.*?>/gim, "\n").replace(/<\/p>/gim, "\n\n").replace(/<.+?>/gim, "").trim();
|
||||
|
||||
// add the headline of the issue
|
||||
var text = headline + "\n";
|
||||
|
||||
// add "=" characters so that the headline is really a headline
|
||||
for (var i = 0; i < headline.length; i++) {
|
||||
text += "=";
|
||||
}
|
||||
|
||||
text += "\n\n";
|
||||
|
||||
// add the url to the issue
|
||||
if (url != "") {
|
||||
text += "- <" + url + ">\n\n";
|
||||
}
|
||||
|
||||
// add the description of the issue
|
||||
if (description != "") {
|
||||
text += description + "\n\n";
|
||||
}
|
||||
|
||||
text = text.replace(/>/gim, ">").replace(/</gim, "<");
|
||||
|
||||
// add a date headline
|
||||
var m = new Date();
|
||||
var dateString =
|
||||
("0" + m.getDate()).slice(-2) + "." +
|
||||
("0" + (m.getMonth()+1)).slice(-2) + "." +
|
||||
m.getFullYear();
|
||||
text += "\n\n## " + dateString + "\n\n";
|
||||
|
||||
// create a new note
|
||||
script.createNote(text);
|
||||
|
||||
// tag the current note
|
||||
script.tagCurrentNote("todo");
|
||||
|
||||
// workaround because the parsers don't seem to work every time
|
||||
// script.reloadScriptingEngine();
|
||||
}
|
||||
}
|
29
docs/scripting/examples/note-stats.qml
Normal file
29
docs/scripting/examples/note-stats.qml
Normal file
|
@ -0,0 +1,29 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/* This script shows current note statistics in a "label":
|
||||
Char(+s) = characters including spaces
|
||||
Char(−s) = characters excluding spaces
|
||||
Words = character groups divided by spaces
|
||||
Paras = paragraphs - character groups divided by line breaks
|
||||
*/
|
||||
|
||||
QtObject {
|
||||
|
||||
function init() {script.registerLabel("note stats")}
|
||||
|
||||
function noteStats(note) {
|
||||
script.setLabelText("note stats",
|
||||
"<table align=center width=90%>
|
||||
<tr>
|
||||
<td align=center>Char(+s) <b>" + note.noteText.length + "</b></th>
|
||||
<td align=center>Char(−s) <b>" + note.noteText.match(/[^ ]/gi).length + "</b></th>
|
||||
<td align=center>Words <b>" + note.noteText.split(/\s+/).length + "</b></th>
|
||||
<td align=center>Paras <b>" + (note.noteText.match(/^.*?\S/gm) || "").length + "</b></th>
|
||||
</tr>
|
||||
</table>")
|
||||
}
|
||||
|
||||
function noteOpenedHook(note) {noteStats(note)}
|
||||
function onNoteStored(note) {noteStats(note)}
|
||||
}
|
104
docs/scripting/examples/note-tagging-by-object.qml
Normal file
104
docs/scripting/examples/note-tagging-by-object.qml
Normal file
|
@ -0,0 +1,104 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script handles tagging in a note for tags in the note text like:
|
||||
* @tag1 @tag2 @tag3
|
||||
*/
|
||||
Script {
|
||||
/**
|
||||
* Handles note tagging for a note
|
||||
*
|
||||
* This function is called when tags are added to, removed from or renamed in
|
||||
* a note or the tags of a note should be listed
|
||||
*
|
||||
* @param note
|
||||
* @param action can be "add", "remove", "rename" or "list"
|
||||
* @param tag to be added, removed or renamed
|
||||
* @param newTagName tag name to be renamed to if action = "rename"
|
||||
* @return note text string or string-list of tag ids (if action = "list")
|
||||
*/
|
||||
function noteTaggingByObjectHook(note, action, tag, newTagName) {
|
||||
var tagName = tag.name;
|
||||
var noteText = note.noteText;
|
||||
var tagRegExp = RegExp("\\B@" + escapeRegExp(tagName) + "\\b");
|
||||
script.log("action: " + action);
|
||||
|
||||
switch (action) {
|
||||
// adds the tag "tagName" to the note
|
||||
// the new note text has to be returned so that the note can be updated
|
||||
// returning an empty string indicates that nothing has to be changed
|
||||
case "add":
|
||||
// check if tag already exists
|
||||
if (noteText.search(tagRegExp) > 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// add the tag at the end of the note
|
||||
noteText += "\n@" + tagName;
|
||||
script.log("Adding tag '" + tagName + "' to note");
|
||||
return noteText;
|
||||
break;
|
||||
|
||||
// removes the tag "tagName" from the note
|
||||
// the new note text has to be returned so that the note can be updated
|
||||
// returning an empty string indicates that nothing has to be changed
|
||||
case "remove":
|
||||
noteText = noteText.replace(tagRegExp, "");
|
||||
script.log("Removing tag '" + tagName + "' from note");
|
||||
return noteText;
|
||||
break;
|
||||
|
||||
// renames the tag "tagName" in the note to "newTagName"
|
||||
// the new note text has to be returned so that the note can be updated
|
||||
// returning an empty string indicates that nothing has to be changed
|
||||
case "rename":
|
||||
noteText = noteText.replace(tagRegExp, "@" + newTagName);
|
||||
script.log("Renaming tag '" + tagName + "' in note");
|
||||
return noteText;
|
||||
break;
|
||||
|
||||
// returns a list of all tag names of the note
|
||||
case "list":
|
||||
var tag = script.getTagByNameBreadcrumbList(["level1a", "level2b", "level3b"]);
|
||||
script.log(tag.id);
|
||||
script.log(tag.name);
|
||||
|
||||
var re = new RegExp("\\B@([^\\s,]+)", "gi"),
|
||||
result, tagIdList = [];
|
||||
|
||||
while ((result = re.exec(noteText)) !== null) {
|
||||
var tagName = result[1];
|
||||
tag.fetchByName(tagName);
|
||||
var tagId = tag.id;
|
||||
|
||||
if (tagId == 0) {
|
||||
// TODO: create tag and set tagId
|
||||
continue;
|
||||
}
|
||||
|
||||
// add the tag if it wasn't in the list
|
||||
if (tagIdList.indexOf(tagId) == -1) {
|
||||
tagIdList.push(tagId);
|
||||
script.log(tagId);
|
||||
}
|
||||
}
|
||||
|
||||
if (tagIdList.length > 0) {
|
||||
script.log("Found tags '" + tagIdList + "' in note");
|
||||
}
|
||||
|
||||
return tagIdList;
|
||||
break;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a string for regular expressions
|
||||
*/
|
||||
function escapeRegExp(str) {
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||
}
|
||||
}
|
89
docs/scripting/examples/note-tagging.qml
Normal file
89
docs/scripting/examples/note-tagging.qml
Normal file
|
@ -0,0 +1,89 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script handles tagging in a note for tags in the note text like:
|
||||
* @tag1 @tag2 @tag3
|
||||
*/
|
||||
Script {
|
||||
/**
|
||||
* Handles note tagging for a note
|
||||
*
|
||||
* This function is called when tags are added to, removed from or renamed in
|
||||
* a note or the tags of a note should be listed
|
||||
*
|
||||
* @param note
|
||||
* @param action can be "add", "remove", "rename" or "list"
|
||||
* @param tagName tag name to be added, removed or renamed
|
||||
* @param newTagName tag name to be renamed to if action = "rename"
|
||||
* @return string or string-list (if action = "list")
|
||||
*/
|
||||
function noteTaggingHook(note, action, tagName, newTagName) {
|
||||
var noteText = note.noteText;
|
||||
var tagRegExp = RegExp("\\B@" + escapeRegExp(tagName) + "\\b");
|
||||
|
||||
switch (action) {
|
||||
// adds the tag "tagName" to the note
|
||||
// the new note text has to be returned so that the note can be updated
|
||||
// returning an empty string indicates that nothing has to be changed
|
||||
case "add":
|
||||
// check if tag already exists
|
||||
if (noteText.search(tagRegExp) > 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// add the tag at the end of the note
|
||||
noteText += "\n@" + tagName;
|
||||
script.log("Adding tag '" + tagName + "' to note");
|
||||
return noteText;
|
||||
break;
|
||||
|
||||
// removes the tag "tagName" from the note
|
||||
// the new note text has to be returned so that the note can be updated
|
||||
// returning an empty string indicates that nothing has to be changed
|
||||
case "remove":
|
||||
noteText = noteText.replace(tagRegExp, "");
|
||||
script.log("Removing tag '" + tagName + "' from note");
|
||||
return noteText;
|
||||
break;
|
||||
|
||||
// renames the tag "tagName" in the note to "newTagName"
|
||||
// the new note text has to be returned so that the note can be updated
|
||||
// returning an empty string indicates that nothing has to be changed
|
||||
case "rename":
|
||||
noteText = noteText.replace(tagRegExp, "@" + newTagName);
|
||||
script.log("Renaming tag '" + tagName + "' in note");
|
||||
return noteText;
|
||||
break;
|
||||
|
||||
// returns a list of all tag names of the note
|
||||
case "list":
|
||||
var re = new RegExp("\\B@([^\\s,]+)", "gi"),
|
||||
result, tagNameList = [];
|
||||
|
||||
while ((result = re.exec(noteText)) !== null) {
|
||||
var tagName = result[1];
|
||||
|
||||
// add the tag if it wasn't in the list
|
||||
if (tagNameList.indexOf(tagName) == -1) {
|
||||
tagNameList.push(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
if (tagNameList.length > 0) {
|
||||
script.log("Found tags '" + tagNameList + "' in note");
|
||||
}
|
||||
return tagNameList;
|
||||
break;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a string for regular expressions
|
||||
*/
|
||||
function escapeRegExp(str) {
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||
}
|
||||
}
|
82
docs/scripting/examples/note-text-from-5pm-mail.qml
Normal file
82
docs/scripting/examples/note-text-from-5pm-mail.qml
Normal file
|
@ -0,0 +1,82 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script parses the text that was copied from a task email of the webservice 5pm
|
||||
* and creates a note text with a headline, the link to the task and the description
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This function is called when html or a media file is pasted to a note with `Ctrl + Shift + V`
|
||||
*
|
||||
* @param text text of the QMimeData object
|
||||
* @param html html of the QMimeData object
|
||||
* @returns the string that should be inserted instead of the text from the QMimeData object
|
||||
*/
|
||||
function insertingFromMimeDataHook(text, html) {
|
||||
// script.log(text);
|
||||
// script.log(html);
|
||||
|
||||
// http://www.regexpal.com is your friend
|
||||
var re1 = /^Neue Aufgabe von [\w\s]+$\s\s^(.+)$/igm;
|
||||
var result1 = re1.exec(text);
|
||||
|
||||
if (result1 === null) {
|
||||
re1 = /^Nachricht aktualisiert von [\w\s]+$\s\s^Aufgabe: (.+)$/igm;
|
||||
result1 = re1.exec(text);
|
||||
}
|
||||
|
||||
if (result1 === null) {
|
||||
re1 = /^Neue Nachricht erstellt von [\w\s]+$\s\s^Aufgabe: (.+)$/igm;
|
||||
result1 = re1.exec(text);
|
||||
}
|
||||
|
||||
var re2 = /^Direkter Zugriff hier: (http.+\d+)$/igm;
|
||||
var result2 = re2.exec(text);
|
||||
|
||||
var re3 = /^Projekt: .+\nBeschreibung: ((.|\n)+)^Priorität: /igm;
|
||||
var result3 = re3.exec(text);
|
||||
|
||||
if (result3 === null) {
|
||||
re3 = /^Projekt: .+\n((.|\n)+)^Direkter Zugriff hier: /igm;
|
||||
result3 = re3.exec(text);
|
||||
}
|
||||
|
||||
// script.log(result1);
|
||||
// script.log(result2);
|
||||
// script.log(result3);
|
||||
|
||||
// return an empty string if we didn't find anything
|
||||
if ((result1 === null) || (result2 === null)) {
|
||||
script.log("no 5pm task was found");
|
||||
return "";
|
||||
}
|
||||
|
||||
var url = result2[1];
|
||||
|
||||
var re4 = /(\d+)$/igm;
|
||||
var result4 = re4.exec(url);
|
||||
|
||||
var id = result4[1];
|
||||
var headline = result1[1] + " (" + id + ")";
|
||||
|
||||
// add the headline of the task
|
||||
var text = headline + "\n";
|
||||
|
||||
// add "=" charactes so that the headline is really a headline
|
||||
for (var i = 0; i < headline.length; i++) {
|
||||
text += "=";
|
||||
}
|
||||
|
||||
// add the url to the task
|
||||
text += "\n\n- <" + url + ">";
|
||||
|
||||
// add the description of the task
|
||||
if (result3 !== null) {
|
||||
var description = result3[1];
|
||||
text += "\n\n" + description
|
||||
}
|
||||
|
||||
// return the text that should be pasted
|
||||
return text;
|
||||
}
|
||||
}
|
16
docs/scripting/examples/on-note-opened.qml
Normal file
16
docs/scripting/examples/on-note-opened.qml
Normal file
|
@ -0,0 +1,16 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script is an example how to get a notification when a note was opened
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This function is called after a note was opened
|
||||
*
|
||||
* @param {Note} note - the note object that was opened
|
||||
*/
|
||||
function noteOpenedHook(note) {
|
||||
script.log(note.fullNoteFilePath);
|
||||
}
|
||||
}
|
39
docs/scripting/examples/paste-from-skype-history.qml
Normal file
39
docs/scripting/examples/paste-from-skype-history.qml
Normal file
|
@ -0,0 +1,39 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button that parses the text that was copied from the Skype Electron client
|
||||
* to the clipboard and tries to extract and paste text from it
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
// create a menu entry with a button and a freedesktop theme icon
|
||||
script.registerCustomAction("pasteFromSkypeHistory", "Paste text from Skype history", "Paste Skype Text", "edit-paste");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "pasteFromSkypeHistory") {
|
||||
return;
|
||||
}
|
||||
// get the text that is currently in the clipboard
|
||||
var html = script.clipboard(true);
|
||||
|
||||
// script.log(html);
|
||||
|
||||
var textRegExp = /<p.*?>(.+?)<\/p>/gim;
|
||||
var match;
|
||||
|
||||
while ((match = textRegExp.exec(html)) !== null) {
|
||||
script.noteTextEditWrite(match[1].replace(/<.+?>/gim, "") + "\n");
|
||||
}
|
||||
}
|
||||
}
|
19
docs/scripting/examples/paste-full-image-url.qml
Normal file
19
docs/scripting/examples/paste-full-image-url.qml
Normal file
|
@ -0,0 +1,19 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script is an example of pasting an image link with the full file url if a file is dropped into QOwnNotes
|
||||
* It was created for this question: https://github.com/pbek/QOwnNotes/issues/623
|
||||
*/
|
||||
Script {
|
||||
/**
|
||||
* This function is called when html or a media file is pasted to a note with `Ctrl + Shift + V`
|
||||
*
|
||||
* @param text text of the QMimeData object
|
||||
* @param html html of the QMimeData object
|
||||
* @returns the string that should be inserted instead of the text from the QMimeData object
|
||||
*/
|
||||
function insertingFromMimeDataHook(text, html) {
|
||||
return "";
|
||||
}
|
||||
}
|
38
docs/scripting/examples/paste-latex-image.qml
Normal file
38
docs/scripting/examples/paste-latex-image.qml
Normal file
|
@ -0,0 +1,38 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button that generates and pastes an image from
|
||||
* Latex code in the clipboard
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
// create a menu entry to paste Latex code as an image
|
||||
script.registerCustomAction("pasteLatexImage", "Paste Latex image", "Latex", "insert-image", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
switch (identifier) {
|
||||
case "pasteLatexImage":
|
||||
// get the text that is currently in the clipboard
|
||||
var text = script.clipboard();
|
||||
|
||||
// use the webservice to generate and download the image
|
||||
var url = "http://latex.codecogs.com/gif.latex?" + text;
|
||||
var markdown = script.downloadUrlToMedia(url);
|
||||
|
||||
// write the image markdown to the note
|
||||
script.noteTextEditWrite(markdown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
34
docs/scripting/examples/persistent-variables.qml
Normal file
34
docs/scripting/examples/persistent-variables.qml
Normal file
|
@ -0,0 +1,34 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This is an example on how to use persistent variables.
|
||||
*/
|
||||
Script {
|
||||
|
||||
function init() {
|
||||
script.registerCustomAction("persistentVariablesSetTest", "Persistent variables set test", "Persistent var set test", "edit-copy");
|
||||
script.registerCustomAction("persistentVariablesGetTest", "Persistent variables get test", "Persistent var get test", "edit-paste");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier == "persistentVariablesSetTest") {
|
||||
var result = script.inputDialogGetItem(
|
||||
"combo box", "Please select an item", ["Item 1", "Item 2", "Item 3"]);
|
||||
|
||||
// store persistent variable
|
||||
script.setPersistentVariable("PersistentVariablesTest/myVar", result);
|
||||
}
|
||||
|
||||
if (identifier == "persistentVariablesGetTest") {
|
||||
// load and log persistent variable
|
||||
script.log(script.getPersistentVariable("PersistentVariablesTest/myVar", "nothing here yet"));
|
||||
}
|
||||
}
|
||||
}
|
76
docs/scripting/examples/pin-note.qml
Normal file
76
docs/scripting/examples/pin-note.qml
Normal file
|
@ -0,0 +1,76 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/* This script is tested only on GNU/Linux, it's not tested on OSX and won't work on Windows.
|
||||
* If you know how to make it properly rename note files in Windows feel free to make a pull request.
|
||||
*
|
||||
* This script implements custom action buttons to prepend current note name with a special (or any other)
|
||||
* unicode symbols so the note will be "pinned" on top of the list with "alphabetical sorting" on.
|
||||
* You can use different symbols, one at a time, to "pin" notes.
|
||||
* That allows to make kind of hierarchy of pinned notes.
|
||||
*
|
||||
* Notes can be "unpinned" by using same symbol second time.
|
||||
*
|
||||
* Since the script actually creates a new note with the same content assigned tags won't be saved.
|
||||
*
|
||||
* This script should be used with "Allow note file name to be different from headline",
|
||||
* "Accept all external modification of current note", "Sort by -> Alphabetical" options on. */
|
||||
|
||||
QtObject {
|
||||
|
||||
/* Put different symbols to prepend note name here, as much of them as you like.
|
||||
* You can get more unicode symbols at https://unicode-table.com/en/#dingbats
|
||||
* Some unicode symbols can be unavailable in font set used in your system. */
|
||||
property var symbol:["★", "⚑", "✔", "☎"]
|
||||
|
||||
/// Each symbol will get own button to add it to selected note name.
|
||||
function init() {
|
||||
for (var n = 0; n < symbol.length; n++) {
|
||||
script.registerCustomAction(n, "Mark note with " + symbol[n], symbol[n])
|
||||
}
|
||||
}
|
||||
|
||||
/// Each symbol uses single algorithm to prepend note name with it.
|
||||
function customActionInvoked(n) {
|
||||
|
||||
if (symbol.indexOf(symbol[n]) == -1) {
|
||||
exit()
|
||||
}
|
||||
|
||||
/// Get note data
|
||||
var note = script.currentNote()
|
||||
var fullFileName = note.fullNoteFilePath
|
||||
var fileName = note.fileName
|
||||
var filePath = fullFileName.replace(fileName,"")
|
||||
|
||||
script.log("Note: " + note + fullFileName)
|
||||
|
||||
/* Delete symbol if note is "pinned" by it.
|
||||
* Or prepend "unpinned" note with that symbol.
|
||||
* Or "repin" note with the new symbol. */
|
||||
if (fileName.substring(0,2) == symbol[n] + " ") {
|
||||
var newFileName = fileName.substring(2)
|
||||
script.log("Note " + fileName + " unmarked")
|
||||
}
|
||||
else if (symbol.indexOf(fileName.substring(0,1)) != -1 && fileName.substring(1,2) == " ") {
|
||||
var newFileName = symbol[n] + " " + fileName.substring(2)
|
||||
script.log("Note " + fileName + " marked with " + symbol[n])
|
||||
}
|
||||
else {
|
||||
var newFileName = symbol[n] + " " + fileName
|
||||
script.log("Note " + fileName + " marked with " + symbol[n])
|
||||
}
|
||||
|
||||
/* Since QOwnNotes doesn't allow to delete notes with scripting yet,
|
||||
* rename the note file by a system's native command with a new "prepended" name.
|
||||
* Use different commands for Windows and POSIX systems. */
|
||||
if (script.platformIsWindows()) {
|
||||
script.log("This script currently doesn't work in Windows. Sorry for inconvenience." )
|
||||
} else {
|
||||
var moveCommand = "mv"
|
||||
var arguments = [fullFileName,filePath + newFileName]
|
||||
}
|
||||
|
||||
script.startSynchronousProcess(moveCommand, arguments, "")
|
||||
}
|
||||
}
|
49
docs/scripting/examples/preview-styling.qml
Normal file
49
docs/scripting/examples/preview-styling.qml
Normal file
|
@ -0,0 +1,49 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This is an example for custom styling of html in the note preview
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This function is called before the markdown html of a note is generated
|
||||
*
|
||||
* It allows you to modify what is passed to the markdown to html converter
|
||||
*
|
||||
* The method can for example be used in multiple scripts to render code (like LaTeX math or mermaid)
|
||||
* to its graphical representation for the preview
|
||||
*
|
||||
* The note will not be changed in this process
|
||||
*
|
||||
* @param {NoteApi} note - the note object
|
||||
* @param {string} markdown - the markdown that is about to being converted to html
|
||||
* @param {string} forExport - true if the html is used for an export, false for the preview
|
||||
* @return {string} the modified markdown or an empty string if nothing should be modified
|
||||
*/
|
||||
function preNoteToMarkdownHtmlHook(note, markdown, forExport) {
|
||||
markdown = markdown.replace("- special text", "- something else");
|
||||
return markdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the markdown html of a note is generated
|
||||
*
|
||||
* It allows you to modify this html
|
||||
* This is for example called before by the note preview
|
||||
*
|
||||
* @param {Note} note - the note object
|
||||
* @param {string} html - the html that is about to being rendered
|
||||
* @param {string} forExport - true if the html is used for an export, false for the preview
|
||||
* @return {string} the modified html or an empty string if nothing should be modified
|
||||
*/
|
||||
function noteToMarkdownHtmlHook(note, html, forExport) {
|
||||
// see http://doc.qt.io/qt-5/richtext-html-subset.html for a list of
|
||||
// supported css styles
|
||||
if (forExport) {
|
||||
var stylesheet = "h2 {margin-left: 25px; color: blue;} h3 {margin-left: 45px;} h4 {margin-left: 65px;}";
|
||||
} else {
|
||||
var stylesheet = "h2 {margin-left: 20px; color: red;} h3 {margin-left: 40px;} h4 {margin-left: 60px;}";
|
||||
}
|
||||
html = html.replace("</style>", stylesheet + "</style>");
|
||||
return html;
|
||||
}
|
||||
}
|
79
docs/scripting/examples/scribble.qml
Normal file
79
docs/scripting/examples/scribble.qml
Normal file
|
@ -0,0 +1,79 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script adds a menu entry to the context menu of the note edit to insert a
|
||||
* scribble image to the media-folder, that will be edited by an external image editor
|
||||
*
|
||||
* The path of the image editor and the image template can be selected in the script settings of the script
|
||||
*/
|
||||
Script {
|
||||
property string executablePath;
|
||||
property string imagePath;
|
||||
property bool executeInBackground;
|
||||
|
||||
// the path to the script's directory will be set here
|
||||
property string scriptDirPath;
|
||||
|
||||
// register your settings variables so the user can set them in the script settings
|
||||
property variant settingsVariables: [
|
||||
{
|
||||
"identifier": "executablePath",
|
||||
"name": "Path of external image editor",
|
||||
"description": "Please select the path of the executable:",
|
||||
"type": "file",
|
||||
"default": "gimp",
|
||||
},
|
||||
{
|
||||
"identifier": "imagePath",
|
||||
"name": "Path of template image",
|
||||
"description": "Please select the path of the template image:",
|
||||
"type": "file",
|
||||
"default": scriptDirPath + "/scribble.png",
|
||||
},
|
||||
{
|
||||
"identifier": "executeInBackground",
|
||||
"name": "Execute image editor in background",
|
||||
"description": "If the image editor is executed in the background you will be able to work with QOwnNotes while you are editing the scribble, but the note preview will not be refreshed automatically after you close the image editor.",
|
||||
"text": "Execute in background",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Initializes the custom actions
|
||||
*/
|
||||
function init() {
|
||||
script.registerCustomAction("scribble", "Add scribble", "Scribble", "view-preview", true, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "scribble") {
|
||||
return;
|
||||
}
|
||||
|
||||
// insert the scribble template image as media file
|
||||
var mediaFile = script.insertMediaFile(imagePath, true);
|
||||
var mediaFilePath = mediaFile.replace("file://media", script.currentNoteFolderPath() + "/media");
|
||||
|
||||
// write the scribble image to the note
|
||||
script.noteTextEditWrite("\n");
|
||||
|
||||
var params = [mediaFilePath];
|
||||
|
||||
// edit the scribble image
|
||||
if (executeInBackground) {
|
||||
script.startDetachedProcess(executablePath, params);
|
||||
} else {
|
||||
script.startSynchronousProcess(executablePath, params);
|
||||
script.regenerateNotePreview();
|
||||
}
|
||||
}
|
||||
}
|
34
docs/scripting/examples/scripting-label-demo.qml
Normal file
34
docs/scripting/examples/scripting-label-demo.qml
Normal file
|
@ -0,0 +1,34 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script creates scripting labels
|
||||
*
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the labels
|
||||
*/
|
||||
function init() {
|
||||
script.registerLabel("html-label", "<strong>Strong</strong> HTML text<br />with three lines<br />and a <a href='https://www.qownnotes.org'>link to a website</a>.");
|
||||
|
||||
script.registerLabel("long-label", "another very long text, another very long text, another very long text, another very long text, another very long text, another very long text, another very long text, another very long text, another very long text, another very long text, another very long text that will wrap");
|
||||
|
||||
script.registerLabel("counter-label");
|
||||
}
|
||||
|
||||
/**
|
||||
* This starts a timer that triggers two seconds
|
||||
*/
|
||||
property QtObject timer: Timer {
|
||||
interval: 1000
|
||||
repeat: true
|
||||
running: true
|
||||
|
||||
property int count: 0
|
||||
|
||||
onTriggered: {
|
||||
count++;
|
||||
script.setLabelText("counter-label", "count = " + count);
|
||||
}
|
||||
}
|
||||
}
|
95
docs/scripting/examples/selected-markdown-to-bbcode.qml
Normal file
95
docs/scripting/examples/selected-markdown-to-bbcode.qml
Normal file
|
@ -0,0 +1,95 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button that converts the selected Markdown
|
||||
* text to BBCode in the clipboard
|
||||
*
|
||||
* Dependencies:
|
||||
* http://pandoc.org
|
||||
* https://github.com/2ion/pandoc-bbcode
|
||||
*/
|
||||
QtObject {
|
||||
property string panbbcodePath;
|
||||
property string pandocPath;
|
||||
|
||||
// register your settings variables so the user can set them in the script settings
|
||||
property variant settingsVariables: [
|
||||
{
|
||||
"identifier": "pandocPath",
|
||||
"name": "Pandoc path",
|
||||
"description": "Please select the path to your Pandoc executable:",
|
||||
"type": "file",
|
||||
"default": "pandoc",
|
||||
},
|
||||
{
|
||||
"identifier": "panbbcodePath",
|
||||
"name": "panbbcode path",
|
||||
"description": "Please select the path to your <code>panbbcode.lua</code> executable:",
|
||||
"type": "file",
|
||||
"default": "/opt/scripts/panbbcode.lua",
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
script.registerCustomAction("markdownToBBCode", "Markdown to BBCode", "BBCode", "edit-copy", true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "markdownToBBCode") {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the selected text from the note text edit
|
||||
var text = script.noteTextEditSelectedText();
|
||||
|
||||
// you need pandoc and the BBCode writer from https://github.com/2ion/pandoc-bbcode
|
||||
// to convert Markdown to BBCode
|
||||
var params = ["-t", panbbcodePath, "-f", "markdown"];
|
||||
var result = script.startSynchronousProcess(pandocPath, params, text);
|
||||
|
||||
// do some code list cleanup
|
||||
result = replaceAll(result, "[list=*]", "[list]");
|
||||
result = replaceAll(result, "[/*]", "");
|
||||
|
||||
// convert inline code blocks to italic
|
||||
// do this 10 times to take care of multiple code blocks in a line
|
||||
for (var i = 0; i < 10; i++) {
|
||||
result = result.replace(/^(.+?)\[code\](.+?)\[\/code\]/img, "$1[i]$2[/i]");
|
||||
}
|
||||
|
||||
// convert headlines to bold
|
||||
result = replaceAll(result, "[h]", "[b]");
|
||||
result = replaceAll(result, "[/h]", "[/b]");
|
||||
|
||||
// convert `em` to `i`
|
||||
result = replaceAll(result, "[em]", "[i]");
|
||||
result = replaceAll(result, "[/em]", "[/i]");
|
||||
|
||||
// link some users
|
||||
result = replaceAll(result, "@Georg", "[USER=1]Georg[/USER]");
|
||||
result = replaceAll(result, "@Sören", "[USER=2]Sören[/USER]");
|
||||
result = replaceAll(result, "@Robert", "[USER=16]Robert[/USER]");
|
||||
result = replaceAll(result, "@Stephan", "[USER=8]Stephan[/USER]");
|
||||
result = replaceAll(result, "@Gunnar", "[USER=14]Gunnar[/USER]");
|
||||
|
||||
// put the result into the clipboard
|
||||
script.setClipboardText(result);
|
||||
}
|
||||
|
||||
function replaceAll(str, find, replace) {
|
||||
return String(str).replace(new RegExp(escapeRegExp(find), 'g'), replace);
|
||||
}
|
||||
|
||||
function escapeRegExp(str) {
|
||||
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
|
||||
}
|
||||
}
|
63
docs/scripting/examples/selected-markdown-to-jira.qml
Normal file
63
docs/scripting/examples/selected-markdown-to-jira.qml
Normal file
|
@ -0,0 +1,63 @@
|
|||
import QtQml 2.0
|
||||
|
||||
/**
|
||||
* This script creates a menu item and a button that converts the selected Markdown
|
||||
* text to Jira code in the clipboard
|
||||
*
|
||||
* Dependencies:
|
||||
* Node.js: https://nodejs.org/en/download/
|
||||
* https://github.com/kylefarris/J2M
|
||||
*
|
||||
* first you have to install jira2md:
|
||||
* npm install jira2md
|
||||
*/
|
||||
QtObject {
|
||||
property string nodejsExecutablePath;
|
||||
|
||||
// register your settings variables so the user can set them in the script settings
|
||||
property variant settingsVariables: [
|
||||
{
|
||||
"identifier": "nodejsExecutablePath",
|
||||
"name": "Node.js path",
|
||||
"description": "Please select the path to your Node.js executable:",
|
||||
"type": "file",
|
||||
"default": "nodejs",
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Initializes the custom action
|
||||
*/
|
||||
function init() {
|
||||
script.registerCustomAction("markdownToJira", "Markdown to Jira", "Jira", "edit-copy", true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "markdownToJira") {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the selected text from the note text edit
|
||||
var text = script.noteTextEditSelectedText();
|
||||
|
||||
// fix unordered lists
|
||||
text = text.replace(/^-/gm, "*");
|
||||
text = text.replace(/\t-/gm, "\t*");
|
||||
|
||||
// you need NodeJs and jira2md (https://github.com/kylefarris/J2M) to convert Markdown to Jira
|
||||
var params = ["-e", "console.log(require('jira2md').to_jira(require('fs').readFileSync('/dev/stdin').toString()))"];
|
||||
var result = script.startSynchronousProcess(nodejsExecutablePath, params, text);
|
||||
|
||||
// replace some names
|
||||
result = String(result).replace(/\@Georg/ig, "[~g.franz]").replace(/\@Jacob/ig, "[~j.ester]").replace(/\@Gandalf/ig, "[~g.sievers]");
|
||||
|
||||
// put the result into the clipboard
|
||||
script.setClipboardText(result);
|
||||
}
|
||||
}
|
73
docs/scripting/examples/unique-note-id.qml
Normal file
73
docs/scripting/examples/unique-note-id.qml
Normal file
|
@ -0,0 +1,73 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
import com.qownnotes.noteapi 1.0
|
||||
|
||||
/**
|
||||
* This script generates a 10 character alphanumeric id for the current note and also allows to jump to the note by it
|
||||
*/
|
||||
Script {
|
||||
/**
|
||||
* Initializes the custom actions
|
||||
*/
|
||||
function init() {
|
||||
script.registerCustomAction("generateId", "Generate unique id for current note",
|
||||
"Unique id", "xml-element-new", false, false, true);
|
||||
script.registerCustomAction("jumpById", "Jump to note with unique id",
|
||||
"Jump to id", "edit-find", true, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
switch (identifier) {
|
||||
case "generateId":
|
||||
var uniqueId = uniqueid();
|
||||
var noteText = script.currentNote().noteText;
|
||||
|
||||
// check if we already have generated an id for the note
|
||||
if (noteText.search("id:\\[") != -1) {
|
||||
script.log("Note already has a unique id");
|
||||
return;
|
||||
}
|
||||
|
||||
var noteText = script.currentNote().noteText;
|
||||
noteText += "\nid:[" + uniqueId + "]";
|
||||
|
||||
script.noteTextEditSelectAll();
|
||||
script.noteTextEditWrite(noteText);
|
||||
break;
|
||||
case "jumpById":
|
||||
var uniqueId = script.inputDialogGetText("Unique id", "Please enter the id of the note");
|
||||
var noteIds = script.fetchNoteIdsByNoteTextPart("id:[" + uniqueId + "]");
|
||||
|
||||
if (noteIds.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var note = script.fetchNoteById(noteIds[0]);
|
||||
script.setCurrentNote(note);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function uniqueid() {
|
||||
// always start with a letter
|
||||
var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65));
|
||||
|
||||
do {
|
||||
// between numbers and characters (48 is 0 and 90 is Z (42-48 = 90)
|
||||
var ascicode=Math.floor((Math.random()*42)+48);
|
||||
|
||||
if (ascicode<58 || ascicode>64) {
|
||||
// exclude all chars between : (58) and @ (64)
|
||||
idstr+=String.fromCharCode(ascicode);
|
||||
}
|
||||
} while (idstr.length<10);
|
||||
|
||||
return idstr.toLowerCase();
|
||||
}
|
||||
}
|
49
docs/scripting/examples/use-tag-names-in-filename.qml
Normal file
49
docs/scripting/examples/use-tag-names-in-filename.qml
Normal file
|
@ -0,0 +1,49 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script is an example how to add the tag names to the file names of notes
|
||||
* when a note file gets stored in QOwnNotes
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* This function is called when a note gets stored to disk if
|
||||
* "Allow note file name to be different from headline" is enabled
|
||||
* in the settings
|
||||
*
|
||||
* It allows you to modify the name of the note file
|
||||
* Return an empty string if the file name of the note should
|
||||
* not be modified
|
||||
*
|
||||
* @param {Note} note - the note object of the stored note
|
||||
* @return {string} the file name of the note without file extension
|
||||
*/
|
||||
function handleNoteTextFileNameHook(note) {
|
||||
// the current note name is the fallback
|
||||
var fileName = note.name;
|
||||
|
||||
// get a list of note text lines
|
||||
var noteLines = note.noteText.split("\n");
|
||||
|
||||
// set the first line of the note as base for the file name
|
||||
if (noteLines.length > 0) {
|
||||
// you maybe also want to exclude some disallowed characters here
|
||||
fileName = noteLines[0];
|
||||
}
|
||||
|
||||
// get a list of all assigned tag names
|
||||
var tagNameList = note.tagNames();
|
||||
|
||||
// add the tag names to the filename
|
||||
if (tagNameList.length > 0) {
|
||||
fileName += " [" + tagNameList.join("] [") + "]";
|
||||
}
|
||||
|
||||
script.log("note file name: " + fileName);
|
||||
|
||||
var noteExists = script.noteExistsByFileName(fileName + ".md", note.id);
|
||||
script.log("note " + (noteExists ? "exists" : "doesn't exist"));
|
||||
|
||||
return fileName;
|
||||
}
|
||||
}
|
112
docs/scripting/examples/variables.qml
Normal file
112
docs/scripting/examples/variables.qml
Normal file
|
@ -0,0 +1,112 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This is an example on how to register variables that can be set by the user in
|
||||
* the script settings.
|
||||
*/
|
||||
Script {
|
||||
// you have to define your registered variables so you can access them later
|
||||
property string myString;
|
||||
property bool myBoolean;
|
||||
property string myText;
|
||||
property int myInt;
|
||||
property string myFile;
|
||||
property string mySelection;
|
||||
|
||||
// register your settings variables so the user can set them in the script settings
|
||||
//
|
||||
// unfortunately there is no QVariantHash in Qt, we only can use
|
||||
// QVariantMap (that has no arbitrary ordering) or QVariantList (which at
|
||||
// least can be ordered arbitrarily)
|
||||
property variant settingsVariables: [
|
||||
{
|
||||
"identifier": "myString",
|
||||
"name": "I am a line edit",
|
||||
"description": "Please enter a valid string:",
|
||||
"type": "string",
|
||||
"default": "My default value",
|
||||
},
|
||||
{
|
||||
"identifier": "myBoolean",
|
||||
"name": "I am a checkbox",
|
||||
"description": "Some description",
|
||||
"text": "Check this checkbox",
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
},
|
||||
{
|
||||
"identifier": "myText",
|
||||
"name": "I am a textbox",
|
||||
"description": "Please enter your text:",
|
||||
"type": "text",
|
||||
"default": "This can be a really long text\nwith multiple lines.",
|
||||
},
|
||||
{
|
||||
"identifier": "myInt",
|
||||
"name": "I am a number selector",
|
||||
"description": "Please enter a number:",
|
||||
"type": "integer",
|
||||
"default": 42,
|
||||
},
|
||||
{
|
||||
"identifier": "myFile",
|
||||
"name": "I am a file selector",
|
||||
"description": "Please select the file:",
|
||||
"type": "file",
|
||||
"default": "pandoc",
|
||||
},
|
||||
{
|
||||
"identifier": "mySelection",
|
||||
"name": "I am an item selector",
|
||||
"description": "Please select an item:",
|
||||
"type": "selection",
|
||||
"default": "option2",
|
||||
"items": {"option1": "Text for option 1", "option2": "Text for option 2", "option3": "Text for option 3"},
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
function init() {
|
||||
script.registerCustomAction("variablesTest", "Variables test", "Var test", "edit-copy");
|
||||
doSomethingWithYourVariables();
|
||||
}
|
||||
|
||||
function doSomethingWithYourVariables() {
|
||||
// these variables will be set by QOwnNotes from the settings
|
||||
// if the user didn't set a variable your default value will be set
|
||||
script.log(myString);
|
||||
script.log(myBoolean);
|
||||
script.log(myText);
|
||||
script.log(myInt);
|
||||
script.log(myFile);
|
||||
script.log(mySelection);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier != "variablesTest") {
|
||||
return;
|
||||
}
|
||||
|
||||
doSomethingWithYourVariables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the settings variables again
|
||||
*
|
||||
* Use this method if you want to use code to override your variables, like setting
|
||||
* default values depended on the operating system.
|
||||
*/
|
||||
function registerSettingsVariables() {
|
||||
if (script.platformIsWindows()) {
|
||||
// override the myFile default value
|
||||
settingsVariables[3].default = "pandoc.exe"
|
||||
}
|
||||
}
|
||||
}
|
81
docs/scripting/examples/weather-stats.qml
Normal file
81
docs/scripting/examples/weather-stats.qml
Normal file
|
@ -0,0 +1,81 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script shows current weather statistics in a "scripting label"
|
||||
*
|
||||
* The Yahoo weather api is used for fetching the weather data
|
||||
* https://developer.yahoo.com/weather/
|
||||
*/
|
||||
|
||||
Script {
|
||||
// you have to define your registered variables so you can access them later
|
||||
property string city;
|
||||
property bool useFahrenheit;
|
||||
|
||||
// register your settings variables so the user can set them in the script settings
|
||||
property variant settingsVariables: [
|
||||
{
|
||||
"identifier": "city",
|
||||
"name": "City",
|
||||
"description": "Please enter your city:",
|
||||
"type": "string",
|
||||
"default": "Graz",
|
||||
},
|
||||
{
|
||||
"identifier": "useFahrenheit",
|
||||
"name": "Unit",
|
||||
"description": "Use Fahrenheit instead of Celsius",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
},
|
||||
];
|
||||
|
||||
function init() {
|
||||
script.registerLabel("weather stats")
|
||||
weatherStats();
|
||||
}
|
||||
|
||||
function weatherStats() {
|
||||
script.log(useFahrenheit);
|
||||
var unitString = useFahrenheit ? "f" : "c"
|
||||
var json = script.downloadUrlToString("https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22" + city + "%22)%20and%20u%3D%27" + unitString + "%27&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys");
|
||||
var weatherInfo = JSON.parse(json);
|
||||
|
||||
var temp = weatherInfo.query.results.channel.item.condition.temp
|
||||
var tempUnit = weatherInfo.query.results.channel.units.temperature;
|
||||
var conditionText = weatherInfo.query.results.channel.item.condition.text
|
||||
var weatherCity = weatherInfo.query.results.channel.location.city
|
||||
var windSpeed = weatherInfo.query.results.channel.wind.speed
|
||||
var windUnit = weatherInfo.query.results.channel.units.speed;
|
||||
|
||||
if (!useFahrenheit) {
|
||||
tempUnit = "°" + tempUnit;
|
||||
}
|
||||
|
||||
script.setLabelText("weather stats",
|
||||
"<table align='center' width='90%'>
|
||||
<tr>
|
||||
<td align='center'>
|
||||
Weather in <b>" + weatherCity + "</b>: " + conditionText + " at <b>" + temp + " " + tempUnit + "</b>
|
||||
(" + windSpeed + " " + windUnit + " wind)
|
||||
</tb>
|
||||
</tr>
|
||||
</table>")
|
||||
}
|
||||
|
||||
/**
|
||||
* This starts a timer that triggers every 10min
|
||||
*/
|
||||
property QtObject timer: Timer {
|
||||
interval: 600000
|
||||
repeat: true
|
||||
running: true
|
||||
|
||||
property int count: 0
|
||||
|
||||
onTriggered: {
|
||||
weatherStats();
|
||||
}
|
||||
}
|
||||
}
|
44
docs/scripting/examples/websocket-client.qml
Normal file
44
docs/scripting/examples/websocket-client.qml
Normal file
|
@ -0,0 +1,44 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
import QtWebSockets 1.1
|
||||
|
||||
/**
|
||||
* This is an example on how to use web sockets as a client
|
||||
* when sending data to an echo server
|
||||
*
|
||||
* Under Ubuntu Linux I installed: qml-module-qtwebsockets
|
||||
*
|
||||
* Also see: http://doc.qt.io/qt-5/qml-qtwebsockets-websocket.html
|
||||
*/
|
||||
WebSocket {
|
||||
id: socket
|
||||
url: "ws://echo.websocket.org"
|
||||
|
||||
function init() {
|
||||
script.registerCustomAction("socketClientTest", "socketClientTest", "socketClientTest", "edit-copy");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier == "socketClientTest") {
|
||||
socket.active = !socket.active
|
||||
}
|
||||
}
|
||||
|
||||
onTextMessageReceived: {
|
||||
script.log("Received message: " + message);
|
||||
}
|
||||
onStatusChanged: if (socket.status == WebSocket.Error) {
|
||||
script.log("Error: " + socket.errorString)
|
||||
} else if (socket.status == WebSocket.Open) {
|
||||
socket.sendTextMessage("Hello World")
|
||||
} else if (socket.status == WebSocket.Closed) {
|
||||
script.log("Socket closed");
|
||||
}
|
||||
active: false
|
||||
}
|
39
docs/scripting/examples/websocket-raw-data-new-note.qml
Normal file
39
docs/scripting/examples/websocket-raw-data-new-note.qml
Normal file
|
@ -0,0 +1,39 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
Script {
|
||||
/**
|
||||
* Create a new note with page url, screenshot and page text if a page is
|
||||
* sent to QOwnNotes from the browser extension
|
||||
*/
|
||||
function websocketRawDataHook(requestType, pageUrl, pageTitle, rawData,
|
||||
screenshotDataUrl) {
|
||||
// we only want to handle page requests, selection requests are ignored
|
||||
if (requestType != "page") {
|
||||
return false;
|
||||
}
|
||||
|
||||
let underline = "";
|
||||
|
||||
// add underline characters
|
||||
for (var i = 0; i < (pageTitle.length - 1); i++) {
|
||||
underline += "=";
|
||||
}
|
||||
|
||||
// create a new note with page title as headline
|
||||
const text = pageTitle + "\n" + underline + "\ntest\n";
|
||||
script.createNote(text);
|
||||
console.log(rawData);
|
||||
|
||||
// add html for page url and the screenshot to the note as markdown
|
||||
const html = "<a href=\"" + pageUrl + "\">" + pageTitle + "</a><br />" +
|
||||
"<br /><img src=\"" + screenshotDataUrl + "\" /><br /><br />";
|
||||
mainWindow.insertHtmlAsMarkdownIntoCurrentNote(html);
|
||||
|
||||
// add html to the note as markdown
|
||||
// we do that separately so it the raw html of the page can't disturbe the rest of our note
|
||||
mainWindow.insertHtmlAsMarkdownIntoCurrentNote(rawData);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
Script {
|
||||
/**
|
||||
* Writes the selected text on the webpage that was sent to QOwnNotes from
|
||||
* the browser extension into the current note
|
||||
*/
|
||||
function websocketRawDataHook(requestType, pageUrl, pageTitle, rawData,
|
||||
screenshotDataUrl) {
|
||||
// we only want to handle selection requests, page requests are ignored
|
||||
if (requestType != "selection") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// write selected text from the page to the current note
|
||||
script.noteTextEditWrite(rawData);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
50
docs/scripting/examples/websocket-server.qml
Normal file
50
docs/scripting/examples/websocket-server.qml
Normal file
|
@ -0,0 +1,50 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
import QtWebSockets 1.1
|
||||
|
||||
/**
|
||||
* This is an example on how to use web sockets as socket server
|
||||
* This can be for example used to remote control QOwnNotes
|
||||
*
|
||||
* You can test the socket server by connecting to it on
|
||||
* https://www.websocket.org/echo.html?location=ws://127.0.0.1:35345
|
||||
*
|
||||
* Under Ubuntu Linux I installed: qml-module-qtwebsockets
|
||||
*
|
||||
* Also see: http://doc.qt.io/qt-5/qml-qtwebsockets-websocketserver.html
|
||||
*/
|
||||
WebSocketServer {
|
||||
// if you don't set a port then a random port will be chosen
|
||||
port: 35345
|
||||
|
||||
id: server
|
||||
listen: true
|
||||
|
||||
function init() {
|
||||
script.registerCustomAction("socketServerTest", "Print socket server url", "socketServerTest", "edit-copy");
|
||||
script.log("Socket server url: " + server.url);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
if (identifier == "socketServerTest") {
|
||||
script.log("Socket server url: " + server.url);
|
||||
}
|
||||
}
|
||||
|
||||
onClientConnected: {
|
||||
webSocket.onTextMessageReceived.connect(function(message) {
|
||||
script.log(qsTr("Server received message: %1").arg(message));
|
||||
webSocket.sendTextMessage(qsTr("Hello Client!"));
|
||||
});
|
||||
}
|
||||
|
||||
onErrorStringChanged: {
|
||||
script.log(qsTr("Server error: %1").arg(errorString));
|
||||
}
|
||||
}
|
48
docs/scripting/examples/zettelkasten.qml
Normal file
48
docs/scripting/examples/zettelkasten.qml
Normal file
|
@ -0,0 +1,48 @@
|
|||
import QtQml 2.0
|
||||
import QOwnNotesTypes 1.0
|
||||
|
||||
/**
|
||||
* This script is an example for creating custom actions, that can be invoked
|
||||
* via menu entries and buttons
|
||||
*/
|
||||
QtObject {
|
||||
/**
|
||||
* Initializes the custom actions
|
||||
*/
|
||||
function init() {
|
||||
// create a menu entry "Create Zettelkasten note" with a button and a freedesktop theme icon
|
||||
script.registerCustomAction("createZettelkastenNote", "Create Zettelkasten note", "Zettelkasten note", "task-new");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is invoked when a custom action is triggered
|
||||
* in the menu or via button
|
||||
*
|
||||
* @param identifier string the identifier defined in registerCustomAction
|
||||
*/
|
||||
function customActionInvoked(identifier) {
|
||||
script.log("customActionInvoked - " + identifier);
|
||||
|
||||
switch (identifier) {
|
||||
// create a new note with a custom content
|
||||
case "createZettelkastenNote":
|
||||
var m = new Date();
|
||||
// create the headline
|
||||
var text = m.getFullYear() + ("0" + (m.getMonth()+1)).slice(-2) + ("0" + m.getDate()).slice(-2) + ("0" + m.getHours()).slice(-2) + ("0" + m.getMinutes()).slice(-2) + ("0" + m.getSeconds()).slice(-2) + " Title\n";
|
||||
|
||||
var underline = "";
|
||||
|
||||
// add the underline for the headline
|
||||
for (var i = 0; i < (text.length - 1); i++) {
|
||||
underline += "-";
|
||||
}
|
||||
|
||||
// add some text to our Zettelkasten note
|
||||
text += underline + "\n\n Note\n\n\n# keywords\n\n### Cf\n\n---\n\n### References\n\n";
|
||||
|
||||
// create a new note
|
||||
script.createNote(text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue