From 0009bc4d35e65ff7bca5205ff44de2ffa5137d7c Mon Sep 17 00:00:00 2001 From: luginf Date: Sat, 23 May 2026 11:34:03 +0200 Subject: [PATCH 1/7] custom syntax new-note-namer --- new-note-namer/info.json | 6 +- new-note-namer/new-note-namer.qml | 110 ++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 31 deletions(-) diff --git a/new-note-namer/info.json b/new-note-namer/info.json index ad33d4c..81411f8 100644 --- a/new-note-namer/info.json +++ b/new-note-namer/info.json @@ -2,9 +2,9 @@ "name": "New note namer", "identifier": "new-note-namer", "script": "new-note-namer.qml", - "authors": ["@diegovskytl", "@Mystechry"], + "authors": ["@diegovskytl", "@Mystechry", "@luginf"], "platforms": ["linux", "macos", "windows"], - "version": "0.0.2", + "version": "0.0.4", "minAppVersion": "17.06.2", - "description": "Enables a dialog window (or two) so the user can choose the note title and file name at the moment of creation.
Specially useful when the 'Allow note file name to be different to note title. \n No more cumbersome renaming :)" + "description": "Enables a dialog window (or two, or even none) so the user can choose the note title and file name at the moment of creation, or simply use the search term for the name and title of the note with custom formattings.

Specially useful when the 'Allow note file name to be different to note title. \n No more cumbersome renaming :)" } diff --git a/new-note-namer/new-note-namer.qml b/new-note-namer/new-note-namer.qml index 960fcac..bbde948 100644 --- a/new-note-namer/new-note-namer.qml +++ b/new-note-namer/new-note-namer.qml @@ -8,6 +8,12 @@ import QOwnNotesTypes 1.0 */ QtObject { property bool extraDialogForFileName + property bool underlineHeading + property bool useSearchTermAsName + property string searchTermHeadingStyle + property string customHeadingOpen + property string customHeadingClose + property string _pendingSearchTerm: "" property variant settingsVariables: [ { 'identifier': 'extraDialogForFileName', @@ -18,52 +24,100 @@ QtObject { }, { 'identifier': 'underlineHeading', - 'name': 'Underline heading', - 'description': 'Highlight the first line by underlining it with =, if not checked, use a preceding # instead.', + 'name': 'Setext Markdown underline heading', + 'description': 'Use Setext heading style (Title / =====) for the dialog flow; if unchecked, use ATX (# Title).', + 'type': 'boolean', + 'default': 'false' + }, + { + 'identifier': 'useSearchTermAsName', + 'name': 'Name note from search term', + 'description': 'Skip the title dialog and use the current search term as the note name.', 'type': 'boolean', 'default': 'false' }, + { + 'identifier': 'searchTermHeadingStyle', + 'name': 'Search term note – heading style', + 'description': 'Title format when creating a note from the search term.', + 'type': 'selection', + 'default': '0', + 'items': { + '0': 'ATX Markdown heading (# Title)', + '1': 'Setext Markdown underline heading (Title / =====)', + '2': 'Custom heading (opening and closing tags)' + } + }, + { + 'identifier': 'customHeadingOpen', + 'name': 'Search term note – custom heading opening tag', + 'description': 'Text inserted before the note name (only used when heading style is "Custom").', + 'type': 'string', + 'default': '' + }, + { + 'identifier': 'customHeadingClose', + 'name': 'Search term note – custom heading closing tag', + 'description': 'Text inserted after the note name (only used when heading style is "Custom").', + 'type': 'string', + 'default': '' + }, ] - property bool underlineHeading - function handleNewNoteHeadlineHook(note) { - var newName = newNamer("New note", "New note title", "Title"); - script.log(note.fileCreated); - script.log(note.fileLastModified); + function handleNewNoteHeadlineHook(headline) { + // 'headline' is a plain string (the search term or default text), not a Note object. + if (useSearchTermAsName) { + _pendingSearchTerm = headline; + return headline; // noteOpenedHook will replace content with the chosen heading style + } + var newName = newNamer("New note", "New note title", "Title"); if (underlineHeading) { return newName + "\n" + "=".repeat(newName.length); - } else { - return "# " + newName; } + return "# " + newName; } - function handleNoteTextFileNameHook(note) { - script.log("note name: " + note.name); - script.log("file name: " + note.fileName); - script.log(note.fileCreated); - script.log(note.fileLastModified); - - var noteLines = note.noteText.split("\n"); - var firstLine = noteLines[0]; - var noteTitle = firstLine.slice(2); // Remove the preceding "# " - if (underlineHeading) { - // Underlined headings use the entire first line - noteTitle = firstLine; + function buildHeadline(name) { + if (searchTermHeadingStyle === "2") { + return customHeadingOpen + name + customHeadingClose; } - - script.log("note title: " + noteTitle); - - // right when a note is created, the fileCreated property value is 'Invald Date' - // this blocks the hook to further change the note file name if the note title is changed + if (searchTermHeadingStyle === "1") { + return name + "\n" + "=".repeat(name.length); + } + return "# " + name; // "0" (ATX) or unset + } + function handleNoteTextFileNameHook(note) { + // right when a note is created, the fileCreated property value is 'Invalid Date' + // this blocks the hook from further changing the note file name if the note title is changed if (note.fileCreated != "Invalid Date") { return ""; } + if (useSearchTermAsName && _pendingSearchTerm !== "") { + return _pendingSearchTerm; // set by handleNewNoteHeadlineHook + } + if (extraDialogForFileName) { return newNamer("New note", "New file name", "File name"); - } else { - return noteTitle; } + + var noteLines = (note.noteText || "").split("\n"); + var firstLine = noteLines[0]; + var noteTitle = firstLine.slice(2); // Remove the preceding "# " + if (underlineHeading) { + noteTitle = firstLine; + } + return noteTitle; + } + function noteOpenedHook(note) { + if (_pendingSearchTerm === "") { + return; + } + var name = _pendingSearchTerm; + _pendingSearchTerm = ""; + script.noteTextEditSetSelection(0, (note.noteText || "").length); + script.noteTextEditWrite(buildHeadline(name)); + mainWindow.focusNoteTextEdit(); } function init() { script.log("New-note-namer active"); From 23f4948d2ff675ad4c399e6069f4703d7121ab61 Mon Sep 17 00:00:00 2001 From: luginf Date: Sat, 23 May 2026 15:02:32 +0200 Subject: [PATCH 2/7] fix new note namer --- new-note-namer/new-note-namer.qml | 79 ++++++++++++++++--------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/new-note-namer/new-note-namer.qml b/new-note-namer/new-note-namer.qml index bbde948..b29afe3 100644 --- a/new-note-namer/new-note-namer.qml +++ b/new-note-namer/new-note-namer.qml @@ -7,57 +7,49 @@ import QOwnNotesTypes 1.0 Avoids cumbersome renaming and title editing. */ QtObject { - property bool extraDialogForFileName - property bool underlineHeading property bool useSearchTermAsName - property string searchTermHeadingStyle + property bool extraDialogForFileName + property string headingStyle property string customHeadingOpen property string customHeadingClose property string _pendingSearchTerm: "" property variant settingsVariables: [ { - 'identifier': 'extraDialogForFileName', - 'name': 'Extra dialog for note title', - 'description': 'Show an additional dialog window so user can write a file name different to the note title.', - 'type': 'boolean', - 'default': 'false' - }, - { - 'identifier': 'underlineHeading', - 'name': 'Setext Markdown underline heading', - 'description': 'Use Setext heading style (Title / =====) for the dialog flow; if unchecked, use ATX (# Title).', + 'identifier': 'useSearchTermAsName', + 'name': 'Name note from search term', + 'description': 'Skip the title dialog and use the current search term as the note name.', 'type': 'boolean', 'default': 'false' }, { - 'identifier': 'useSearchTermAsName', - 'name': 'Name note from search term', - 'description': 'Skip the title dialog and use the current search term as the note name.', + 'identifier': 'extraDialogForFileName', + 'name': 'Extra dialog for note title', + 'description': 'Show an additional dialog window so user can write a file name different to the note title.', 'type': 'boolean', 'default': 'false' }, { - 'identifier': 'searchTermHeadingStyle', - 'name': 'Search term note – heading style', - 'description': 'Title format when creating a note from the search term.', + 'identifier': 'headingStyle', + 'name': 'Heading style', + 'description': 'Title format for new notes.', 'type': 'selection', 'default': '0', 'items': { '0': 'ATX Markdown heading (# Title)', - '1': 'Setext Markdown underline heading (Title / =====)', + '1': 'Setext Markdown heading (Title / =====)', '2': 'Custom heading (opening and closing tags)' } }, { 'identifier': 'customHeadingOpen', - 'name': 'Search term note – custom heading opening tag', + 'name': 'Custom heading – opening tag', 'description': 'Text inserted before the note name (only used when heading style is "Custom").', 'type': 'string', 'default': '' }, { 'identifier': 'customHeadingClose', - 'name': 'Search term note – custom heading closing tag', + 'name': 'Custom heading – closing tag', 'description': 'Text inserted after the note name (only used when heading style is "Custom").', 'type': 'string', 'default': '' @@ -71,21 +63,35 @@ QtObject { return headline; // noteOpenedHook will replace content with the chosen heading style } - var newName = newNamer("New note", "New note title", "Title"); - if (underlineHeading) { - return newName + "\n" + "=".repeat(newName.length); - } - return "# " + newName; + // If QOwnNotes already provided a headline (its own dialog, or a search term), + // apply the chosen style directly rather than asking again. + var name = headline !== "" ? headline : newNamer("New note", "New note title", "Title"); + return buildHeadline(name); } function buildHeadline(name) { - if (searchTermHeadingStyle === "2") { + if (headingStyle === "2") { return customHeadingOpen + name + customHeadingClose; } - if (searchTermHeadingStyle === "1") { + if (headingStyle === "1") { return name + "\n" + "=".repeat(name.length); } return "# " + name; // "0" (ATX) or unset } + function extractTitle(noteText) { + var firstLine = (noteText || "").split("\n")[0]; + if (headingStyle === "2") { + var t = firstLine.slice(customHeadingOpen.length); + var closeLen = customHeadingClose.length; + if (closeLen > 0 && t.slice(-closeLen) === customHeadingClose) { + t = t.slice(0, t.length - closeLen); + } + return t; + } + if (headingStyle === "1") { + return firstLine; // setext: first line is the bare title + } + return firstLine.slice(2); // ATX: remove "# " + } function handleNoteTextFileNameHook(note) { // right when a note is created, the fileCreated property value is 'Invalid Date' // this blocks the hook from further changing the note file name if the note title is changed @@ -94,20 +100,17 @@ QtObject { } if (useSearchTermAsName && _pendingSearchTerm !== "") { - return _pendingSearchTerm; // set by handleNewNoteHeadlineHook + if (extraDialogForFileName) { + return newNamer("New note", "New file name", _pendingSearchTerm); + } + return _pendingSearchTerm; } if (extraDialogForFileName) { - return newNamer("New note", "New file name", "File name"); + return newNamer("New note", "New file name", extractTitle(note.noteText)); } - var noteLines = (note.noteText || "").split("\n"); - var firstLine = noteLines[0]; - var noteTitle = firstLine.slice(2); // Remove the preceding "# " - if (underlineHeading) { - noteTitle = firstLine; - } - return noteTitle; + return extractTitle(note.noteText); } function noteOpenedHook(note) { if (_pendingSearchTerm === "") { From 6a36a5fca1d115d952a4602c9fd37a5c282ecc6c Mon Sep 17 00:00:00 2001 From: luginf Date: Sat, 23 May 2026 18:27:49 +0200 Subject: [PATCH 3/7] simplify interface --- new-note-namer/new-note-namer.qml | 34 +------------------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/new-note-namer/new-note-namer.qml b/new-note-namer/new-note-namer.qml index b29afe3..ec70fe4 100644 --- a/new-note-namer/new-note-namer.qml +++ b/new-note-namer/new-note-namer.qml @@ -7,20 +7,11 @@ import QOwnNotesTypes 1.0 Avoids cumbersome renaming and title editing. */ QtObject { - property bool useSearchTermAsName property bool extraDialogForFileName property string headingStyle property string customHeadingOpen property string customHeadingClose - property string _pendingSearchTerm: "" property variant settingsVariables: [ - { - 'identifier': 'useSearchTermAsName', - 'name': 'Name note from search term', - 'description': 'Skip the title dialog and use the current search term as the note name.', - 'type': 'boolean', - 'default': 'false' - }, { 'identifier': 'extraDialogForFileName', 'name': 'Extra dialog for note title', @@ -58,13 +49,7 @@ QtObject { function handleNewNoteHeadlineHook(headline) { // 'headline' is a plain string (the search term or default text), not a Note object. - if (useSearchTermAsName) { - _pendingSearchTerm = headline; - return headline; // noteOpenedHook will replace content with the chosen heading style - } - - // If QOwnNotes already provided a headline (its own dialog, or a search term), - // apply the chosen style directly rather than asking again. + // If already provided (search term or QOwnNotes own dialog), use it directly. var name = headline !== "" ? headline : newNamer("New note", "New note title", "Title"); return buildHeadline(name); } @@ -99,29 +84,12 @@ QtObject { return ""; } - if (useSearchTermAsName && _pendingSearchTerm !== "") { - if (extraDialogForFileName) { - return newNamer("New note", "New file name", _pendingSearchTerm); - } - return _pendingSearchTerm; - } - if (extraDialogForFileName) { return newNamer("New note", "New file name", extractTitle(note.noteText)); } return extractTitle(note.noteText); } - function noteOpenedHook(note) { - if (_pendingSearchTerm === "") { - return; - } - var name = _pendingSearchTerm; - _pendingSearchTerm = ""; - script.noteTextEditSetSelection(0, (note.noteText || "").length); - script.noteTextEditWrite(buildHeadline(name)); - mainWindow.focusNoteTextEdit(); - } function init() { script.log("New-note-namer active"); } From 395dc5bf7337d1d72bf0c15e221f2d237d1c5211 Mon Sep 17 00:00:00 2001 From: luginf Date: Sat, 23 May 2026 19:49:32 +0200 Subject: [PATCH 4/7] add extra dialog for more versability --- new-note-namer/info.json | 2 +- new-note-namer/new-note-namer.qml | 32 +++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/new-note-namer/info.json b/new-note-namer/info.json index 81411f8..5e74d1c 100644 --- a/new-note-namer/info.json +++ b/new-note-namer/info.json @@ -6,5 +6,5 @@ "platforms": ["linux", "macos", "windows"], "version": "0.0.4", "minAppVersion": "17.06.2", - "description": "Enables a dialog window (or two, or even none) so the user can choose the note title and file name at the moment of creation, or simply use the search term for the name and title of the note with custom formattings.

Specially useful when the 'Allow note file name to be different to note title. \n No more cumbersome renaming :)" + "description": "Enables a dialog window (or two, or even none) so the user can choose the note title and file name at the moment of creation, or simply use the search term for the filename and title of the note with custom formattings.

Specially useful when the 'Allow note file name to be different to note title. \n No more cumbersome renaming :)" } diff --git a/new-note-namer/new-note-namer.qml b/new-note-namer/new-note-namer.qml index ec70fe4..e958615 100644 --- a/new-note-namer/new-note-namer.qml +++ b/new-note-namer/new-note-namer.qml @@ -7,15 +7,24 @@ import QOwnNotesTypes 1.0 Avoids cumbersome renaming and title editing. */ QtObject { + property bool extraDialogForTitle property bool extraDialogForFileName property string headingStyle + property string _searchTerm: "" property string customHeadingOpen property string customHeadingClose property variant settingsVariables: [ + { + 'identifier': 'extraDialogForTitle', + 'name': 'Show a dialog to define the note title', + 'description': 'If checked, ask for a custom note title.', + 'type': 'boolean', + 'default': 'false' + }, { 'identifier': 'extraDialogForFileName', - 'name': 'Extra dialog for note title', - 'description': 'Show an additional dialog window so user can write a file name different to the note title.', + 'name': 'Show a dialog to define the file name', + 'description': 'If checked, ask for a custom file name.', 'type': 'boolean', 'default': 'false' }, @@ -49,8 +58,16 @@ QtObject { function handleNewNoteHeadlineHook(headline) { // 'headline' is a plain string (the search term or default text), not a Note object. - // If already provided (search term or QOwnNotes own dialog), use it directly. - var name = headline !== "" ? headline : newNamer("New note", "New note title", "Title"); + // Strip QOwnNotes search filter prefixes (e.g. "n:" for name-only search). + _searchTerm = headline.replace(/^n:/i, ""); + var name; + if (extraDialogForTitle || _searchTerm === "") { + // Show dialog: pre-fill with the search term if available, otherwise a placeholder. + name = newNamer("New note", "New note title", _searchTerm !== "" ? _searchTerm : "Title"); + } else { + // If already provided (search term or QOwnNotes own dialog), use it directly. + name = _searchTerm; + } return buildHeadline(name); } function buildHeadline(name) { @@ -84,11 +101,14 @@ QtObject { return ""; } + // Default file name: search term if available, otherwise derived from the title. + var defaultName = _searchTerm !== "" ? _searchTerm : extractTitle(note.noteText); + if (extraDialogForFileName) { - return newNamer("New note", "New file name", extractTitle(note.noteText)); + return newNamer("New note", "New file name", defaultName); } - return extractTitle(note.noteText); + return defaultName; } function init() { script.log("New-note-namer active"); From fff296443796a0d7e18b92ea80232f286e5473e1 Mon Sep 17 00:00:00 2001 From: luginf Date: Sun, 24 May 2026 11:41:15 +0200 Subject: [PATCH 5/7] adding a readme with full instructions --- new-note-namer/README.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 new-note-namer/README.md diff --git a/new-note-namer/README.md b/new-note-namer/README.md new file mode 100644 index 0000000..9ec8e74 --- /dev/null +++ b/new-note-namer/README.md @@ -0,0 +1,37 @@ +# New note namer + +Sets the note title and file name at creation time, with optional dialogs for each field. +Especially useful when the _Allow note file name to be different from note title_ option is enabled in QOwnNotes. + +## Settings + +| Setting | Description | +| ------------------------------------------ | ----------------------------------------------------------------------------------- | +| **Show a dialog to define the note title** | If checked, a dialog asks for a custom title (pre-filled with the search term). | +| **Show a dialog to define the file name** | If checked, a dialog asks for a custom file name (pre-filled with the search term). | +| **Heading style** | Format applied to the title: ATX (`# Title`), Setext (`Title / =====`), or Custom. | +| **Custom heading – opening tag** | Text inserted before the title (Custom style only). | +| **Custom heading – closing tag** | Text inserted after the title (Custom style only). | + +The two dialog options are independent: each defaults to the search term, regardless of the other. + +## Behaviour + +| Source | Dialog: note title | Dialog: file name | Title | File name | +| ---------------- | ------------------ | ----------------- | ---------------------------- | ------------------------------------------- | +| Search "foo" | ☐ | ☐ | `# foo` | `foo` | +| Search "foo" | ☑ | ☐ | dialog pre-filled with `foo` | `foo` (search term, independent from title) | +| Search "foo" | ☐ | ☑ | `# foo` | dialog pre-filled with `foo` | +| Search "foo" | ☑ | ☑ | dialog pre-filled with `foo` | dialog pre-filled with `foo` | +| Menu (no search) | — | ☐ | dialog (no pre-fill) | = entered title | +| Menu (no search) | — | ☑ | dialog (no pre-fill) | dialog pre-filled with entered title | + +> **Note:** the `n:` search prefix (name-only filter) is automatically stripped from the note name. + +## Tips + +- Leave both dialogs unchecked for a fully automatic workflow: create a note directly from the search bar with one keypress. +- Check only _file name_ to keep the search term as the title but write a longer or different file name. +- Check only _title_ to write a custom heading while keeping the file name equal to the search term. +- The heading style applies in all cases, including when no dialog is shown. +- All settings require a **script engine reload** to take effect after being changed. From 40144e5f9c61b42f256bc5e9091dea25588213ec Mon Sep 17 00:00:00 2001 From: luginf Date: Sun, 24 May 2026 12:15:38 +0200 Subject: [PATCH 6/7] trigger new CI --- new-note-namer/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 new-note-namer/README.md diff --git a/new-note-namer/README.md b/new-note-namer/README.md old mode 100644 new mode 100755 From 7c62dbe29d8e741102772e060890dc20713dadb8 Mon Sep 17 00:00:00 2001 From: Patrizio Bekerle Date: Sun, 24 May 2026 22:49:10 +0200 Subject: [PATCH 7/7] lint: format file Signed-off-by: Patrizio Bekerle --- new-note-namer/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/new-note-namer/README.md b/new-note-namer/README.md index 9ec8e74..934cb5a 100755 --- a/new-note-namer/README.md +++ b/new-note-namer/README.md @@ -20,11 +20,11 @@ The two dialog options are independent: each defaults to the search term, regard | Source | Dialog: note title | Dialog: file name | Title | File name | | ---------------- | ------------------ | ----------------- | ---------------------------- | ------------------------------------------- | | Search "foo" | ☐ | ☐ | `# foo` | `foo` | -| Search "foo" | ☑ | ☐ | dialog pre-filled with `foo` | `foo` (search term, independent from title) | -| Search "foo" | ☐ | ☑ | `# foo` | dialog pre-filled with `foo` | -| Search "foo" | ☑ | ☑ | dialog pre-filled with `foo` | dialog pre-filled with `foo` | +| Search "foo" | ☑ | ☐ | dialog pre-filled with `foo` | `foo` (search term, independent from title) | +| Search "foo" | ☐ | ☑ | `# foo` | dialog pre-filled with `foo` | +| Search "foo" | ☑ | ☑ | dialog pre-filled with `foo` | dialog pre-filled with `foo` | | Menu (no search) | — | ☐ | dialog (no pre-fill) | = entered title | -| Menu (no search) | — | ☑ | dialog (no pre-fill) | dialog pre-filled with entered title | +| Menu (no search) | — | ☑ | dialog (no pre-fill) | dialog pre-filled with entered title | > **Note:** the `n:` search prefix (name-only filter) is automatically stripped from the note name.