From 6a7768603b7dff623e4ab6eab5f030acddc39a2b Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Tue, 18 Jun 2024 11:37:17 +0000 Subject: [PATCH] build based on e5fa1ec --- dev/.documenter-siteinfo.json | 2 +- dev/assets/documenter.js | 923 +++++++++++++++---------- dev/assets/themes/documenter-dark.css | 2 +- dev/assets/themes/documenter-light.css | 2 +- dev/developer/index.html | 2 +- dev/index.html | 34 +- dev/objects.inv | Bin 0 -> 899 bytes 7 files changed, 563 insertions(+), 402 deletions(-) create mode 100644 dev/objects.inv diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index a8c5c05..2d1a12f 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.8.5","generation_timestamp":"2023-10-16T18:27:42","documenter_version":"1.1.1"}} \ No newline at end of file +{"documenter":{"julia_version":"1.8.5","generation_timestamp":"2024-06-18T11:37:13","documenter_version":"1.4.1"}} \ No newline at end of file diff --git a/dev/assets/documenter.js b/dev/assets/documenter.js index f531160..c6562b5 100644 --- a/dev/assets/documenter.js +++ b/dev/assets/documenter.js @@ -4,7 +4,6 @@ requirejs.config({ 'highlight-julia': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/julia.min', 'headroom': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/headroom.min', 'jqueryui': 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min', - 'minisearch': 'https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min', 'katex-auto-render': 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/contrib/auto-render.min', 'jquery': 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min', 'headroom-jquery': 'https://cdnjs.cloudflare.com/ajax/libs/headroom/0.12.0/jQuery.headroom.min', @@ -103,9 +102,10 @@ $(document).on("click", ".docstring header", function () { }); }); -$(document).on("click", ".docs-article-toggle-button", function () { +$(document).on("click", ".docs-article-toggle-button", function (event) { let articleToggleTitle = "Expand docstring"; let navArticleToggleTitle = "Expand all docstrings"; + let animationSpeed = event.noToggleAnimation ? 0 : 400; debounce(() => { if (isExpanded) { @@ -116,7 +116,7 @@ $(document).on("click", ".docs-article-toggle-button", function () { isExpanded = false; - $(".docstring section").slideUp(); + $(".docstring section").slideUp(animationSpeed); } else { $(this).removeClass("fa-chevron-down").addClass("fa-chevron-up"); $(".docstring-article-toggle-button") @@ -127,7 +127,7 @@ $(document).on("click", ".docs-article-toggle-button", function () { articleToggleTitle = "Collapse docstring"; navArticleToggleTitle = "Collapse all docstrings"; - $(".docstring section").slideDown(); + $(".docstring section").slideDown(animationSpeed); } $(this).prop("title", navArticleToggleTitle); @@ -224,224 +224,465 @@ $(document).ready(function () { }) //////////////////////////////////////////////////////////////////////////////// -require(['jquery', 'minisearch'], function($, minisearch) { - -// In general, most search related things will have "search" as a prefix. -// To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc +require(['jquery'], function($) { -let results = []; -let timer = undefined; +$(document).ready(function () { + let meta = $("div[data-docstringscollapsed]").data(); -let data = documenterSearchIndex["docs"].map((x, key) => { - x["id"] = key; // minisearch requires a unique for each object - return x; + if (meta?.docstringscollapsed) { + $("#documenter-article-toggle-button").trigger({ + type: "click", + noToggleAnimation: true, + }); + } }); -// list below is the lunr 2.1.3 list minus the intersect with names(Base) -// (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with) -// ideally we'd just filter the original list but it's not available as a variable -const stopWords = new Set([ - "a", - "able", - "about", - "across", - "after", - "almost", - "also", - "am", - "among", - "an", - "and", - "are", - "as", - "at", - "be", - "because", - "been", - "but", - "by", - "can", - "cannot", - "could", - "dear", - "did", - "does", - "either", - "ever", - "every", - "from", - "got", - "had", - "has", - "have", - "he", - "her", - "hers", - "him", - "his", - "how", - "however", - "i", - "if", - "into", - "it", - "its", - "just", - "least", - "like", - "likely", - "may", - "me", - "might", - "most", - "must", - "my", - "neither", - "no", - "nor", - "not", - "of", - "off", - "often", - "on", - "or", - "other", - "our", - "own", - "rather", - "said", - "say", - "says", - "she", - "should", - "since", - "so", - "some", - "than", - "that", - "the", - "their", - "them", - "then", - "there", - "these", - "they", - "this", - "tis", - "to", - "too", - "twas", - "us", - "wants", - "was", - "we", - "were", - "what", - "when", - "who", - "whom", - "why", - "will", - "would", - "yet", - "you", - "your", -]); - -let index = new minisearch({ - fields: ["title", "text"], // fields to index for full-text search - storeFields: ["location", "title", "text", "category", "page"], // fields to return with search results - processTerm: (term) => { - let word = stopWords.has(term) ? null : term; - if (word) { - // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names - word = word - .replace(/^[^a-zA-Z0-9@!]+/, "") - .replace(/[^a-zA-Z0-9@!]+$/, ""); - } +}) +//////////////////////////////////////////////////////////////////////////////// +require(['jquery'], function($) { - return word ?? null; - }, - // add . as a separator, because otherwise "title": "Documenter.Anchors.add!", would not find anything if searching for "add!", only for the entire qualification - tokenize: (string) => string.split(/[\s\-\.]+/), - // options which will be applied during the search - searchOptions: { - boost: { title: 100 }, - fuzzy: 2, +/* +To get an in-depth about the thought process you can refer: https://hetarth02.hashnode.dev/series/gsoc + +PSEUDOCODE: + +Searching happens automatically as the user types or adjusts the selected filters. +To preserve responsiveness, as much as possible of the slow parts of the search are done +in a web worker. Searching and result generation are done in the worker, and filtering and +DOM updates are done in the main thread. The filters are in the main thread as they should +be very quick to apply. This lets filters be changed without re-searching with minisearch +(which is possible even if filtering is on the worker thread) and also lets filters be +changed _while_ the worker is searching and without message passing (neither of which are +possible if filtering is on the worker thread) + +SEARCH WORKER: + +Import minisearch + +Build index + +On message from main thread + run search + find the first 200 unique results from each category, and compute their divs for display + note that this is necessary and sufficient information for the main thread to find the + first 200 unique results from any given filter set + post results to main thread + +MAIN: + +Launch worker + +Declare nonconstant globals (worker_is_running, last_search_text, unfiltered_results) + +On text update + if worker is not running, launch_search() + +launch_search + set worker_is_running to true, set last_search_text to the search text + post the search query to worker + +on message from worker + if last_search_text is not the same as the text in the search field, + the latest search result is not reflective of the latest search query, so update again + launch_search() + otherwise + set worker_is_running to false + + regardless, display the new search results to the user + save the unfiltered_results as a global + update_search() + +on filter click + adjust the filter selection + update_search() + +update_search + apply search filters by looping through the unfiltered_results and finding the first 200 + unique results that match the filters + + Update the DOM +*/ + +/////// SEARCH WORKER /////// + +function worker_function(documenterSearchIndex, documenterBaseURL, filters) { + importScripts( + "https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js" + ); + + let data = documenterSearchIndex.map((x, key) => { + x["id"] = key; // minisearch requires a unique for each object + return x; + }); + + // list below is the lunr 2.1.3 list minus the intersect with names(Base) + // (all, any, get, in, is, only, which) and (do, else, for, let, where, while, with) + // ideally we'd just filter the original list but it's not available as a variable + const stopWords = new Set([ + "a", + "able", + "about", + "across", + "after", + "almost", + "also", + "am", + "among", + "an", + "and", + "are", + "as", + "at", + "be", + "because", + "been", + "but", + "by", + "can", + "cannot", + "could", + "dear", + "did", + "does", + "either", + "ever", + "every", + "from", + "got", + "had", + "has", + "have", + "he", + "her", + "hers", + "him", + "his", + "how", + "however", + "i", + "if", + "into", + "it", + "its", + "just", + "least", + "like", + "likely", + "may", + "me", + "might", + "most", + "must", + "my", + "neither", + "no", + "nor", + "not", + "of", + "off", + "often", + "on", + "or", + "other", + "our", + "own", + "rather", + "said", + "say", + "says", + "she", + "should", + "since", + "so", + "some", + "than", + "that", + "the", + "their", + "them", + "then", + "there", + "these", + "they", + "this", + "tis", + "to", + "too", + "twas", + "us", + "wants", + "was", + "we", + "were", + "what", + "when", + "who", + "whom", + "why", + "will", + "would", + "yet", + "you", + "your", + ]); + + let index = new MiniSearch({ + fields: ["title", "text"], // fields to index for full-text search + storeFields: ["location", "title", "text", "category", "page"], // fields to return with results processTerm: (term) => { let word = stopWords.has(term) ? null : term; if (word) { + // custom trimmer that doesn't strip @ and !, which are used in julia macro and function names word = word .replace(/^[^a-zA-Z0-9@!]+/, "") .replace(/[^a-zA-Z0-9@!]+$/, ""); + + word = word.toLowerCase(); } return word ?? null; }, + // add . as a separator, because otherwise "title": "Documenter.Anchors.add!", would not + // find anything if searching for "add!", only for the entire qualification tokenize: (string) => string.split(/[\s\-\.]+/), - }, -}); + // options which will be applied during the search + searchOptions: { + prefix: true, + boost: { title: 100 }, + fuzzy: 2, + }, + }); -index.addAll(data); + index.addAll(data); + + /** + * Used to map characters to HTML entities. + * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts + */ + const htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + }; + + /** + * Used to match HTML entities and HTML characters. + * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts + */ + const reUnescapedHtml = /[&<>"']/g; + const reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** + * Escape function from lodash + * Refer: https://github.com/lodash/lodash/blob/main/src/escape.ts + */ + function escape(string) { + return string && reHasUnescapedHtml.test(string) + ? string.replace(reUnescapedHtml, (chr) => htmlEscapes[chr]) + : string || ""; + } -let filters = [...new Set(data.map((x) => x.category))]; -var modal_filters = make_modal_body_filters(filters); -var filter_results = []; + /** + * Make the result component given a minisearch result data object and the value + * of the search input as queryString. To view the result object structure, refer: + * https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchresult + * + * @param {object} result + * @param {string} querystring + * @returns string + */ + function make_search_result(result, querystring) { + let search_divider = `
`; + let display_link = + result.location.slice(Math.max(0), Math.min(50, result.location.length)) + + (result.location.length > 30 ? "..." : ""); // To cut-off the link because it messes with the overflow of the whole div + + if (result.page !== "") { + display_link += ` (${result.page})`; + } -$(document).on("keyup", ".documenter-search-input", function (event) { - // Adding a debounce to prevent disruptions from super-speed typing! - debounce(() => update_search(filter_results), 300); + let textindex = new RegExp(`${querystring}`, "i").exec(result.text); + let text = + textindex !== null + ? result.text.slice( + Math.max(textindex.index - 100, 0), + Math.min( + textindex.index + querystring.length + 100, + result.text.length + ) + ) + : ""; // cut-off text before and after from the match + + text = text.length ? escape(text) : ""; + + let display_result = text.length + ? "..." + + text.replace( + new RegExp(`${escape(querystring)}`, "i"), // For first occurrence + '$&' + ) + + "..." + : ""; // highlights the match + + let in_code = false; + if (!["page", "section"].includes(result.category.toLowerCase())) { + in_code = true; + } + + // We encode the full url to escape some special characters which can lead to broken links + let result_div = ` + +
+
${escape(result.title)}
+
${result.category}
+
+

+ ${display_result} +

+
+ ${display_link} +
+
+ ${search_divider} + `; + + return result_div; + } + + self.onmessage = function (e) { + let query = e.data; + let results = index.search(query, { + filter: (result) => { + // Only return relevant results + return result.score >= 1; + }, + }); + + // Pre-filter to deduplicate and limit to 200 per category to the extent + // possible without knowing what the filters are. + let filtered_results = []; + let counts = {}; + for (let filter of filters) { + counts[filter] = 0; + } + let present = {}; + + for (let result of results) { + cat = result.category; + cnt = counts[cat]; + if (cnt < 200) { + id = cat + "---" + result.location; + if (present[id]) { + continue; + } + present[id] = true; + filtered_results.push({ + location: result.location, + category: cat, + div: make_search_result(result, query), + }); + } + } + + postMessage(filtered_results); + }; +} + +// `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript! +const filters = [ + ...new Set(documenterSearchIndex["docs"].map((x) => x.category)), +]; +const worker_str = + "(" + + worker_function.toString() + + ")(" + + JSON.stringify(documenterSearchIndex["docs"]) + + "," + + JSON.stringify(documenterBaseURL) + + "," + + JSON.stringify(filters) + + ")"; +const worker_blob = new Blob([worker_str], { type: "text/javascript" }); +const worker = new Worker(URL.createObjectURL(worker_blob)); + +/////// SEARCH MAIN /////// + +// Whether the worker is currently handling a search. This is a boolean +// as the worker only ever handles 1 or 0 searches at a time. +var worker_is_running = false; + +// The last search text that was sent to the worker. This is used to determine +// if the worker should be launched again when it reports back results. +var last_search_text = ""; + +// The results of the last search. This, in combination with the state of the filters +// in the DOM, is used compute the results to display on calls to update_search. +var unfiltered_results = []; + +// Which filter is currently selected +var selected_filter = ""; + +$(document).on("input", ".documenter-search-input", function (event) { + if (!worker_is_running) { + launch_search(); + } }); +function launch_search() { + worker_is_running = true; + last_search_text = $(".documenter-search-input").val(); + worker.postMessage(last_search_text); +} + +worker.onmessage = function (e) { + if (last_search_text !== $(".documenter-search-input").val()) { + launch_search(); + } else { + worker_is_running = false; + } + + unfiltered_results = e.data; + update_search(); +}; + $(document).on("click", ".search-filter", function () { if ($(this).hasClass("search-filter-selected")) { - $(this).removeClass("search-filter-selected"); + selected_filter = ""; } else { - $(this).addClass("search-filter-selected"); + selected_filter = $(this).text().toLowerCase(); } - // Adding a debounce to prevent disruptions from crazy clicking! - debounce(() => get_filters(), 300); + // This updates search results and toggles classes for UI: + update_search(); }); -/** - * A debounce function, takes a function and an optional timeout in milliseconds - * - * @function callback - * @param {number} timeout - */ -function debounce(callback, timeout = 300) { - clearTimeout(timer); - timer = setTimeout(callback, timeout); -} - /** * Make/Update the search component - * - * @param {string[]} selected_filters */ -function update_search(selected_filters = []) { - let initial_search_body = ` -
Type something to get started!
- `; - +function update_search() { let querystring = $(".documenter-search-input").val(); if (querystring.trim()) { - results = index.search(querystring, { - filter: (result) => { - // Filtering results - if (selected_filters.length === 0) { - return result.score >= 1; - } else { - return ( - result.score >= 1 && selected_filters.includes(result.category) - ); - } - }, - }); + if (selected_filter == "") { + results = unfiltered_results; + } else { + results = unfiltered_results.filter((result) => { + return selected_filter == result.category.toLowerCase(); + }); + } let search_result_container = ``; + let modal_filters = make_modal_body_filters(); let search_divider = `
`; if (results.length) { @@ -449,19 +690,23 @@ function update_search(selected_filters = []) { let count = 0; let search_results = ""; - results.forEach(function (result) { - if (result.location) { - // Checking for duplication of results for the same page - if (!links.includes(result.location)) { - search_results += make_search_result(result, querystring); - count++; - } - + for (var i = 0, n = results.length; i < n && count < 200; ++i) { + let result = results[i]; + if (result.location && !links.includes(result.location)) { + search_results += result.div; + count++; links.push(result.location); } - }); + } - let result_count = `
${count} result(s)
`; + if (count == 1) { + count_str = "1 result"; + } else if (count == 200) { + count_str = "200+ results"; + } else { + count_str = count + " results"; + } + let result_count = `
${count_str}
`; search_result_container = `
@@ -490,125 +735,37 @@ function update_search(selected_filters = []) { $(".search-modal-card-body").html(search_result_container); } else { - filter_results = []; - modal_filters = make_modal_body_filters(filters, filter_results); - if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) { $(".search-modal-card-body").addClass("is-justify-content-center"); } - $(".search-modal-card-body").html(initial_search_body); + $(".search-modal-card-body").html(` +
Type something to get started!
+ `); } } /** * Make the modal filter html * - * @param {string[]} filters - * @param {string[]} selected_filters * @returns string */ -function make_modal_body_filters(filters, selected_filters = []) { - let str = ``; - - filters.forEach((val) => { - if (selected_filters.includes(val)) { - str += `${val}`; - } else { - str += `${val}`; - } - }); +function make_modal_body_filters() { + let str = filters + .map((val) => { + if (selected_filter == val.toLowerCase()) { + return `${val}`; + } else { + return `${val}`; + } + }) + .join(""); - let filter_html = ` + return `
Filters: ${str} -
- `; - - return filter_html; -} - -/** - * Make the result component given a minisearch result data object and the value of the search input as queryString. - * To view the result object structure, refer: https://lucaong.github.io/minisearch/modules/_minisearch_.html#searchresult - * - * @param {object} result - * @param {string} querystring - * @returns string - */ -function make_search_result(result, querystring) { - let search_divider = `
`; - let display_link = - result.location.slice(Math.max(0), Math.min(50, result.location.length)) + - (result.location.length > 30 ? "..." : ""); // To cut-off the link because it messes with the overflow of the whole div - - if (result.page !== "") { - display_link += ` (${result.page})`; - } - - let textindex = new RegExp(`\\b${querystring}\\b`, "i").exec(result.text); - let text = - textindex !== null - ? result.text.slice( - Math.max(textindex.index - 100, 0), - Math.min( - textindex.index + querystring.length + 100, - result.text.length - ) - ) - : ""; // cut-off text before and after from the match - - let display_result = text.length - ? "..." + - text.replace( - new RegExp(`\\b${querystring}\\b`, "i"), // For first occurrence - '$&' - ) + - "..." - : ""; // highlights the match - - let in_code = false; - if (!["page", "section"].includes(result.category.toLowerCase())) { - in_code = true; - } - - // We encode the full url to escape some special characters which can lead to broken links - let result_div = ` - -
-
${result.title}
-
${result.category}
-
-

- ${display_result} -

-
- ${display_link} -
-
- ${search_divider} - `; - - return result_div; -} - -/** - * Get selected filters, remake the filter html and lastly update the search modal - */ -function get_filters() { - let ele = $(".search-filters .search-filter-selected").get(); - filter_results = ele.map((x) => $(x).text().toLowerCase()); - modal_filters = make_modal_body_filters(filters, filter_results); - update_search(filter_results); +
`; } }) @@ -635,103 +792,107 @@ $(document).ready(function () { //////////////////////////////////////////////////////////////////////////////// require(['jquery'], function($) { -let search_modal_header = ` - -`; - -let initial_search_body = ` -
Type something to get started!
-`; - -let search_modal_footer = ` - -`; - -$(document.body).append( - ` - diff --git a/dev/index.html b/dev/index.html index b444af3..05dbdec 100644 --- a/dev/index.html +++ b/dev/index.html @@ -43,7 +43,7 @@ text: props.hi + Julia.world() } } -}

Interface

QML.QMLModule

Module for building Qt6 QML graphical user interfaces for Julia programs. Types starting with Q are equivalent of their Qt C++ counterpart, so, unless otherwise noted, they have no Julia docstring and we refer to the Qt documentation for details instead.

source
QML.JuliaDisplayType
struct JuliaDisplay

You can use display to send images to a JuliaDisplay. There is a corresponding QML block called JuliaDisplay. Of course the display can also be added using pushdisplay!, but passing by value can be more convenient when defining multiple displays in QML. See below for syntax.

julia> using QML
+}

Interface

QML.QMLModule

Module for building Qt6 QML graphical user interfaces for Julia programs. Types starting with Q are equivalent of their Qt C++ counterpart, so, unless otherwise noted, they have no Julia docstring and we refer to the Qt documentation for details instead.

source
QML.JuliaDisplayType
struct JuliaDisplay

You can use display to send images to a JuliaDisplay. There is a corresponding QML block called JuliaDisplay. Of course the display can also be added using pushdisplay!, but passing by value can be more convenient when defining multiple displays in QML. See below for syntax.

julia> using QML
 
 julia> using Colors
 
@@ -80,7 +80,7 @@
           loadqml(path)
           exec()
         end;
-
source
QML.JuliaItemModelMethod
function JuliaItemModel(items::AbstractVector, addroles::Bool = true)

Constructor for a JuliaItemModel. The JuliaItemModel type allows using data in QML views such as ListView and Repeater, providing a two-way synchronization of the data. A JuliaItemModel is constructed from a 1D Julia array. To use the model from QML, it can be exposed as a context attribute.

Setter and getter "roles" based on the fieldnames of the eltype will be automatically created if addroles is true.

In Qt, each of the elements of a model has a series of roles, available as properties in the delegate that is used to display each item. The roles can be added using the addrole! function.

julia> using QML
+
source
QML.JuliaItemModelMethod
function JuliaItemModel(items::AbstractVector, addroles::Bool = true)

Constructor for a JuliaItemModel. The JuliaItemModel type allows using data in QML views such as ListView and Repeater, providing a two-way synchronization of the data. A JuliaItemModel is constructed from a 1D Julia array. To use the model from QML, it can be exposed as a context attribute.

Setter and getter "roles" based on the fieldnames of the eltype will be automatically created if addroles is true.

In Qt, each of the elements of a model has a series of roles, available as properties in the delegate that is used to display each item. The roles can be added using the addrole! function.

julia> using QML
 
 julia> mutable struct Fruit
           name::String
@@ -123,7 +123,7 @@
           """)
           loadqml(path; fruits)
           exec()
-        end
source
QML.JuliaPropertyMapMethod
function JuliaPropertyMap(pairs...)

Store Julia values for access from QML. Observables are connected so they change on the QML side when updated from Julia and vice versa only when passed in a property map. Note that in the example below, if you run output[] = new_value from within Julia, the slider in QML will move.

julia> using QML
+        end
source
QML.JuliaPropertyMapMethod
function JuliaPropertyMap(pairs...)

Store Julia values for access from QML. Observables are connected so they change on the QML side when updated from Julia and vice versa only when passed in a property map. Note that in the example below, if you run output[] = new_value from within Julia, the slider in QML will move.

julia> using QML
 
 julia> using Observables: Observable, on
 
@@ -151,7 +151,7 @@
          """)
          loadqml(path; observables = JuliaPropertyMap("output" => output))
          exec()
-       end
source
QML.QQmlApplicationEngineType
struct QQmlApplicationEngine

One of 3 ways to interact with QML (the others being QQuickView and QQmlComponent. You can load a QML file to create an engine with [load]. Use exec to execute a file after it's been loaded.

The lifetime of the QQmlApplicationEngine is managed from C++ and it gets cleaned up when the application quits. This means it is not necessary to keep a reference to the engine to prevent it from being garbage collected prematurely.

julia> using QML
+       end
source
QML.QQmlApplicationEngineType
struct QQmlApplicationEngine

One of 3 ways to interact with QML (the others being QQuickView and QQmlComponent. You can load a QML file to create an engine with [load]. Use exec to execute a file after it's been loaded.

The lifetime of the QQmlApplicationEngine is managed from C++ and it gets cleaned up when the application quits. This means it is not necessary to keep a reference to the engine to prevent it from being garbage collected prematurely.

julia> using QML
 
 julia> mktempdir() do folder
           path = joinpath(folder, "main.qml")
@@ -171,7 +171,7 @@
           """)
           loadqml(path; greeting = "Hello, World!")
           exec()
-        end
source
QML.QQuickViewType
struct QQuickView

One of 3 ways to interact with QML (the others being QQmlApplicationEngine and QQmlComponent. QQuickView creates a window, so it's not necessary to wrap the QML in ApplicationWindow. Use init_qquickview to create a quick view, set_source to set the source for the quick view, QML.show to view, and exec to execute.

julia> using QML
 
 julia> mktempdir() do folder
           path = joinpath(folder, "main.qml")
@@ -215,7 +215,7 @@
           set_source(quick_view, QUrlFromLocalFile(path))
           QML.show(quick_view)
           exec()
-        end
source
QML.QTimerType
struct QTimer

You can use QTimer to simulate running Julia in the background. Note that QML provides the infrastructure to connect to the QTimer signal through the Connections item.

julia> using QML
+        end
source
QML.QTimerType
struct QTimer

You can use QTimer to simulate running Julia in the background. Note that QML provides the infrastructure to connect to the QTimer signal through the Connections item.

julia> using QML
 
 julia> counter = Ref(0);
 
@@ -249,10 +249,10 @@
           """)
           loadqml(path, timer=QTimer())
           exec()
-        end
source
Base.stringFunction
function string(data::QByteArray)

Equivalent to QByteArray::toString. Use to convert a QByteArray back to a string.

julia> using QML
+        end
source
Base.stringFunction
function string(data::QByteArray)

Equivalent to QByteArray::toString. Use to convert a QByteArray back to a string.

julia> using QML
 
 julia> string(QByteArray("Hello, World!"))
-"Hello, World!"
source
QML.addrole!Function
function addrole!(model::JuliaItemModel, name::String, getter, [setter])

Add your own getter (and optionally, setter) functions to a JuliaItemModel for use by QML. setter is optional, and if it is not provided the role will be read-only. getter will process an item before it is returned. The arguments of setter will be collection, new_value, index as in the standard setindex! function. If you would like to see the roles defined for a list, use roles.

julia> using QML
+"Hello, World!"
source
QML.addrole!Function
function addrole!(model::JuliaItemModel, name::String, getter, [setter])

Add your own getter (and optionally, setter) functions to a JuliaItemModel for use by QML. setter is optional, and if it is not provided the role will be read-only. getter will process an item before it is returned. The arguments of setter will be collection, new_value, index as in the standard setindex! function. If you would like to see the roles defined for a list, use roles.

julia> using QML
 
 julia> items = ["A", "B"];
 
@@ -287,7 +287,7 @@
           """)
           loadqml(path; array_model = array_model)
           exec()
-        end
source
QML.content_itemFunction
function content_item(quick_view::QQuickView)

Get the content item of a quick view. Equivalent to QQuickWindow::contentItem.

julia> using QML
+        end
source
QML.content_itemFunction
function content_item(quick_view::QQuickView)

Get the content item of a quick view. Equivalent to QQuickWindow::contentItem.

julia> using QML
 
 julia> using CxxWrap.CxxWrapCore: CxxPtr
 
@@ -307,7 +307,7 @@
           set_source(quick_view, QUrlFromLocalFile(path))
           @assert content_item(quick_view) isa CxxPtr{QQuickItem}
           exec()
-        end
source
QML.createFunction
function create(component::QQmlComponent, context::QQmlContext)

Equivalent to QQmlComponent::create. This creates a component defined by the QML code set using set_data. It also makes sure the newly created object is parented to the given context. See the example for set_data.

source
QML.engineFunction
function engine(quick_view::QQuickView)

Equivalent to QQuickView::engine. If you would like to modify the context of a QQuickView, use engine to get an engine from the window, and then root_context to get the context from the engine.

julia> using QML
+        end
source
QML.createFunction
function create(component::QQmlComponent, context::QQmlContext)

Equivalent to QQmlComponent::create. This creates a component defined by the QML code set using set_data. It also makes sure the newly created object is parented to the given context. See the example for set_data.

source
QML.engineFunction
function engine(quick_view::QQuickView)

Equivalent to QQuickView::engine. If you would like to modify the context of a QQuickView, use engine to get an engine from the window, and then root_context to get the context from the engine.

julia> using QML
 
 julia> mktempdir() do folder
           path = joinpath(folder, "main.qml")
@@ -330,10 +330,10 @@
           set_source(quick_view, QUrlFromLocalFile(path))
           QML.show(quick_view)
           exec()
-        end
source
QML.exec_asyncFunction
function exec_async()

Similar to exec, but will not block the main process. This method keeps the REPL active and polls the QML interface periodically for events, using a timer in the Julia event loop.

source
QML.init_qmlengineFunction
function init_qmlengine()

Create a QML engine. You can modify the context of an engine using root_context. You can use an engine to create QQmlComponents. See the example for set_data. Note that you can also get the engine for a QQuickView using engine.

source
QML.qmlfunctionFunction
function qmlfunction(function_name::String, a_function)

Register a_function using function_name. If you want to register a function under it's own name, you can use @qmlfunction. Note, however, that you can't use the macro for registering functions from a non-exported module or registering functions wtih ! in the name.

source
QML.qt_prefix_pathFunction
function qt_prefix_path()

Equivalent to QLibraryInfo::location(QLibraryInfo::PrefixPath). Useful to check whether the intended Qt version is being used.

julia> using QML
+        end
source
QML.exec_asyncFunction
function exec_async()

Similar to exec, but will not block the main process. This method keeps the REPL active and polls the QML interface periodically for events, using a timer in the Julia event loop.

source
QML.init_qmlengineFunction
function init_qmlengine()

Create a QML engine. You can modify the context of an engine using root_context. You can use an engine to create QQmlComponents. See the example for set_data. Note that you can also get the engine for a QQuickView using engine.

source
QML.qmlfunctionFunction
function qmlfunction(function_name::String, a_function)

Register a_function using function_name. If you want to register a function under it's own name, you can use @qmlfunction. Note, however, that you can't use the macro for registering functions from a non-exported module or registering functions wtih ! in the name.

source
QML.qt_prefix_pathFunction
function qt_prefix_path()

Equivalent to QLibraryInfo::location(QLibraryInfo::PrefixPath). Useful to check whether the intended Qt version is being used.

julia> using QML
 
 julia> isdir(qt_prefix_path())
-true
source
QML.set_dataFunction
function set_data(component::QQmlComponent, data::QByteArray, file::QUrl)

Equivalent to QQmlComponent::setData. Use this to set the QML code for a QQmlComponent from a Julia string literal wrapped in a QByteArray. Also requires an empty QUrl. See QQmlComponent for an example.

source
QML.set_sourceFunction
function set_source(window::QQuickView, file::QUrl)

Equivalent to QQuickView::setSource. See the example for init_qquickview. The file path should be a path wrapped with QUrl.

source
QML.setheadergetter!Method

setheadergetter!(itemmodel::JuliaItemModel, f::Function)

Set f as function to call when getting header data. The signature of of should be:

  f(data, row_or_col, orientation, role)

Here, data is the internal data array stored in the model, row_or_col is the index of the row or column, orientation is either QML.Horizontal for column headers or QML.Vertical for row headers and role is an integer describing the role (e.g. QML.DisplayRole)

source
QML.setheadersetter!Method

setheadersetter!(itemmodel::JuliaItemModel, f::Function)

Set f as function to call when setting header data. The signature of of should be:

  f(data, row_or_col, orientation, value, role)

Here, value is the value for the given header item. The other arguments are the same as in setheadergetter!

source
QML.@emitMacro
@emit signal_name(arguments...)

Emit a signal from Julia to QML. Handle signals in QML using a JuliaSignals block. See the example below for syntax.

Warning

There must never be more than one JuliaSignals block in QML

julia> using QML
+julia> exec()
source
QML.set_dataFunction
function set_data(component::QQmlComponent, data::QByteArray, file::QUrl)

Equivalent to QQmlComponent::setData. Use this to set the QML code for a QQmlComponent from a Julia string literal wrapped in a QByteArray. Also requires an empty QUrl. See QQmlComponent for an example.

source
QML.set_sourceFunction
function set_source(window::QQuickView, file::QUrl)

Equivalent to QQuickView::setSource. See the example for init_qquickview. The file path should be a path wrapped with QUrl.

source
QML.setheadergetter!Method

setheadergetter!(itemmodel::JuliaItemModel, f::Function)

Set f as function to call when getting header data. The signature of of should be:

  f(data, row_or_col, orientation, role)

Here, data is the internal data array stored in the model, row_or_col is the index of the row or column, orientation is either QML.Horizontal for column headers or QML.Vertical for row headers and role is an integer describing the role (e.g. QML.DisplayRole)

source
QML.setheadersetter!Method

setheadersetter!(itemmodel::JuliaItemModel, f::Function)

Set f as function to call when setting header data. The signature of of should be:

  f(data, row_or_col, orientation, value, role)

Here, value is the value for the given header item. The other arguments are the same as in setheadergetter!

source
QML.@emitMacro
@emit signal_name(arguments...)

Emit a signal from Julia to QML. Handle signals in QML using a JuliaSignals block. See the example below for syntax.

Warning

There must never be more than one JuliaSignals block in QML

julia> using QML
 
 julia> duplicate(value) = @emit duplicateSignal(value);
 
@@ -401,10 +401,10 @@
           """)
           loadqml(path)
           exec()
-        end
source
QML.@expand_dotsMacro
QML.@expand_dots object_.field_ func

Expand an expression of the form a.b.c to replace the dot operator by function calls.

julia> using QML
+        end
source
QML.@expand_dotsMacro
QML.@expand_dots object_.field_ func

Expand an expression of the form a.b.c to replace the dot operator by function calls.

julia> using QML
 
 julia> @macroexpand QML.@expand_dots a.b.c.d f
-:(f(f(f(a, "b"), "c"), "d"))
source
QML.@qmlfunctionMacro
@qmlfunction function_names...

Register Julia functions for access from QML under their own name. Function names must be valid in QML, e.g. they can't contain !. You can use your newly registered functions in QML by first importing org.julialang 1.0, and then calling them with Julia.function_name(arguments...). If you would like to register a function under a different name, use qmlfunction. This will be necessary for non-exported functions from a different module or in case the function contains a ! character.

julia> using QML
+:(f(f(f(a, "b"), "c"), "d"))
source
QML.@qmlfunctionMacro
@qmlfunction function_names...

Register Julia functions for access from QML under their own name. Function names must be valid in QML, e.g. they can't contain !. You can use your newly registered functions in QML by first importing org.julialang 1.0, and then calling them with Julia.function_name(arguments...). If you would like to register a function under a different name, use qmlfunction. This will be necessary for non-exported functions from a different module or in case the function contains a ! character.

julia> using QML
 
 julia> greet() = "Hello, World!";
 
@@ -429,4 +429,4 @@
           """)
           loadqml(path)
           exec()
-        end
source
+ endsource diff --git a/dev/objects.inv b/dev/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..176fc42c871147a50e8b0253c8a2190521c080fe GIT binary patch literal 899 zcmV-}1AP1=AX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkWO-wFo zYziYFR%LQ?X>V>iATTaDE-(rsAXI2&AaZ4GVQFq;WpW^IW*~HEX>%ZEX>4U6X>%ZB zZ*6dLWpi_7WFU2OX>MmAdTeQ8E(&;@rB=&s+b|Hk>nm8azJ+cc1p)*;#E%w8kpOY) zKgb{}zB_g=hjJx9&67y+r zqbwK}S)r9DT5F-GGmAl4*3E1ws1c-v2*#O^P6D+{Xp>Q?BPQkM2x$c-2yXL|5?u80 z%p&k~fv$T_=bHp*q}3ak)YrX>lYKmxXl0Ff%52BTme#x+jWy3Cq#aTxrHlnXK{5-R zCMn!vZC}Q0E@G^YQR_@^L|_e3 z$kL69`mjc88~%Zxac;DP4~OwaY;b zEQQ>P2?f{h7k9;5*Hf*L+$~U3=F_5VC@|FbDnTuTg1)Fw!iKArv+k|5&O6t*?M`E{ ziid-8Z`^v@%^ge1{vMfOX0g3z!fd}@jh=AY@M`{*&)jb3>DSMLtrtxA!ExbZa4{KN zjM|LlT-3JA#v2PGW7x(w3KD-paFa`=ZgRVFS~*y?7`~?KYj>j*a*tdm#l)olJ#*7Kl}1-umw)5}7Qy>5+TERPQ@ zCe+8rF0iRc6X_p<$o;?QEijwKa-!ozE8H$0+$D^XM2aZ?@%~oJ_1rsQsxuSy)^Ztt ZJ5kq-&I>1fc6XD?N=xls@ZVTTMXSrzqmTdq literal 0 HcmV?d00001