File indexing completed on 2024-12-22 05:37:20

0001 <!doctype html>
0002 <html lang="en-us">
0003 
0004 <!-- Matomo -->
0005 <script type="text/javascript">
0006     var _paq = window._paq = window._paq || [];
0007     /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
0008     _paq.push(['trackPageView']);
0009     _paq.push(['enableLinkTracking']);
0010     (function() {
0011       var u="https://stats.kde.org/";
0012       _paq.push(['setTrackerUrl', u+'piwik.php']);
0013       _paq.push(['setSiteId', '32']);
0014       var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
0015       g.type='text/javascript'; g.async=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
0016     })();
0017 </script>
0018 <!-- End Matomo Code -->
0019 
0020 <head>
0021     <meta charset="utf-8">
0022     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
0023     <link rel="stylesheet" href="https://cdn.metroui.org.ua/v4/css/metro-all.min.css">
0024     <link rel="stylesheet" type="text/css" href="styles.css">
0025     <script src="https://code.iconify.design/1/1.0.6/iconify.min.js"></script>
0026     <title>qmlonline</title>
0027 </head>
0028 
0029 <body onload>
0030     <!--Use not released version for splitter event-->
0031     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/metro/4.3.7/js/metro.min.js"></script>
0032 
0033     <div class="header-row">
0034         <span class="header-brand-1">QML</span>
0035         <span class="header-brand-2">Online</span>
0036 
0037         <div class="dropdown">
0038             <button class="dropdown-button">Examples</button>
0039             <div id="dropdown-content" class="dropdown-content"></div>
0040         </div>
0041 
0042         <div class="dropdown" style="cursor:pointer">
0043             <button onclick="format()" class="dropdown-button">Format</button>
0044         </div>
0045 
0046         <div class="dropdown" style="cursor:pointer">
0047             <button onclick="share()" class="dropdown-button">Share</button>
0048         </div>
0049 
0050         <div class="build-info" style="cursor:pointer">
0051             <a id="build-info" target="_blank" href="https://invent.kde.org/webapps/qmlonline" style="color:white"></a>
0052         </div>
0053 
0054         <div class="qt-info" style="cursor:pointer">
0055             <a id="qt-info" target="_blank" style="color:white"></a>
0056         </div>
0057 
0058         <div class="github-button" onclick="window.open('https://invent.kde.org/webapps/qmlonline');">
0059             <span class="iconify" data-icon="octicon-repo" data-inline="false"></span>
0060         </div>
0061     </div>
0062     <div id="main-div" data-role="splitter" class="h-100" data-on-resize-split="resizeSplitY">
0063         <div data-role="splitter" data-split-mode="vertical" data-split-sizes="95, 5" data-min-sizes="18px"
0064             data-on-resize-split="resizeSplitX">
0065             <div id="editor-div"></div>
0066             <div id="editor-bottom">
0067                 <div id="terminal"></div>
0068                 <div id="status-bar" class="status-bar">
0069                     <p> Status Bar </p>
0070                     <p> Ctrl+Alt+h for shortcuts </p>
0071                     <p id="status-bar-line"></p>
0072                     <script type='text/javascript'>
0073                         function updateStatusBarLineColumnFromCursos(cursor) {
0074                             document.getElementById("status-bar-line").innerHTML =
0075                                 `Ln ${cursor.row + 1}, Col ${cursor.column + 1}`
0076                         }
0077                     </script>
0078                 </div>
0079             </div>
0080         </div>
0081         <div id="qmlonline"></div>
0082     </div>
0083 
0084     <script src="examples.js" type="text/javascript" charset="utf-8"></script>
0085     <script type='text/javascript'>
0086         const examples = getExamples();
0087         let select = document.getElementById("dropdown-content");
0088         for (let example_type in examples) {
0089             const examples_of_type = examples[example_type];
0090             console.log(`opt ${example_type}, ${examples_of_type}`)
0091 
0092             const div = document.createElement("div")
0093             div.className = "cell-3"
0094             select.appendChild(div);
0095 
0096             const h4 = document.createElement("h4")
0097             h4.innerHTML = example_type
0098             div.appendChild(h4)
0099 
0100             const ul = document.createElement("ul")
0101             ul.className = "unstyled-list pl-0"
0102             div.appendChild(ul)
0103 
0104             for (let i = 0; i < examples_of_type.length; i++) {
0105                 const content = examples_of_type[i]
0106 
0107                 const li = document.createElement("li");
0108                 ul.appendChild(li)
0109 
0110                 const a = document.createElement("a");
0111                 a.alt = content.file
0112                 a.href = "javascript:openExample('" + content.file + "')"
0113                 a.innerHTML = content.name
0114                 li.appendChild(a)
0115             }
0116         }
0117 
0118         function openExample(file) {
0119             let content = loadFile(file);
0120             editor.session.setValue(content);
0121             qml.setCode(content)
0122             eraseTerminal()
0123         }
0124 
0125         function loadFile(filePath) {
0126             //TODO: use https://xhr.spec.whatwg.org/
0127             let request = new XMLHttpRequest();
0128             request.open("GET", "qml/examples/" + filePath, false);
0129             request.send();
0130             return request.status === 200 ? request.responseText : "";
0131         }
0132     </script>
0133 
0134     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/ace.js"></script>
0135     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/ext-beautify.min.js"></script>
0136     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/ext-language_tools.min.js"></script>
0137     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/ext-keybinding_menu.min.js"></script>
0138     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/theme-dracula.js"></script>
0139     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/mode-qml.js"></script>
0140     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.4.4/lz-string.js"></script>
0141 
0142     <!--qml-->
0143     <script type="text/javascript" src="qtloader.js"></script>
0144     <script type="text/javascript" src="qml.js"></script>
0145     <!--qml-->
0146 
0147     <script type='text/javascript'>
0148         const qml = new QmlOnline("qmlonline")
0149         qml.registerCall({
0150             posInit: function() {
0151                 init()
0152             },
0153             qmlMessage: function(msg) {
0154                 appendLine(msg)
0155             },
0156             qmlError: function(data) {
0157                 var annotations = editor.session.getAnnotations()
0158                 annotations.push(data)
0159                 editor.session.setAnnotations(annotations)
0160             },
0161         })
0162         qml.init()
0163 
0164         /* trigger extension */
0165         ace.require("ace/ext/language_tools");
0166         var editor = ace.edit("editor-div");
0167         /*data-on-resize-window*/
0168         function resizeSplitY(event) {
0169             if (event.x % 2) { // decrease the number of events by half
0170                 qml.resizeCanvas()
0171             }
0172             editor.resize();
0173         }
0174 
0175         /* terminal splitter */
0176         function resizeSplitX(event) {
0177             editor.resize();
0178         }
0179 
0180         var frame;
0181         var editor = ace.edit("editor-div");
0182 
0183         function appendLine(content) {
0184             let terminal = document.getElementById("terminal")
0185             let element = document.createElement("p");
0186             element.innerHTML = '> ' + content
0187             terminal.appendChild(element)
0188             terminal.scroll(0, element.offsetTop);
0189         }
0190 
0191         function eraseTerminal() {
0192             let terminal = document.getElementById("terminal")
0193             terminal.innerHTML = '';
0194         }
0195 
0196         function populateBuildInfo(version) {
0197             let buildInfo = document.getElementById("build-info")
0198             buildInfo.href = `${version.url.replace('.git', '')}/-/tree/${version.hash}`
0199             buildInfo.innerHTML = `Build: ${version.date} - ${version.hash}`
0200 
0201             console.log(`Running Qt ${version.qtVersion}`)
0202             let qtInfo = document.getElementById("qt-info")
0203             let qtMajorMinor = version.qtVersion.split('.').slice(0, 2).join('.')
0204             qtInfo.setAttribute("href", `https://wiki.qt.io/Qt_${qtMajorMinor}_Release`)
0205             qtInfo.innerHTML = `Qt ${version.qtVersion}`
0206         }
0207 
0208         editor.setTheme("ace/theme/dracula");
0209         editor.session.setMode("ace/mode/qml");
0210         editor.setOptions({
0211             showInvisibles: true,
0212             useWorker: false, // Avoid problems with syntax check
0213             enableBasicAutocompletion: true,
0214             enableSnippets: true,
0215             enableLiveAutocompletion: true,
0216         })
0217         editor.commands.addCommand({
0218             name: 'save',
0219             bindKey: {
0220                 win: "Ctrl-S",
0221                 "mac": "Cmd-S"
0222             },
0223             exec: function (editor) {
0224                 qml.setCode(editor.session.getValue())
0225                 localStorage.setItem("lastSessionCode", editor.session.getValue());
0226                 eraseTerminal()
0227             }
0228         })
0229         editor.commands.addCommand({
0230             name: 'format',
0231             bindKey: {
0232                 win: "Ctrl-Shift-F",
0233                 "mac": "Cmd-Shift-F"
0234             },
0235             exec: function () {
0236                 format();
0237             }
0238         })
0239         editor.commands.addCommand({
0240             name: "shortcuts",
0241             bindKey: {
0242                 win: "Ctrl-Alt-h",
0243                 "mac": "Command-Alt-h"
0244             },
0245             exec: function(editor) {
0246                 ace.config.loadModule("ace/ext/keybinding_menu", function(module) {
0247                     module.init(editor);
0248                     editor.showKeyboardShortcuts()
0249                 })
0250             }
0251         })
0252         editor.getSession().on('change', function () {
0253             editor.session.clearAnnotations()
0254             qml.setCode(editor.session.getValue())
0255             localStorage.setItem("lastSessionCode", editor.session.getValue());
0256             eraseTerminal()
0257         });
0258 
0259         editor.getSelection().on('changeCursor', function () {
0260             updateStatusBarLineColumnFromCursos(editor.selection.getCursor())
0261         })
0262 
0263         function init() {
0264             // Get params
0265             const urlParams = new URLSearchParams(window.location.search);
0266 
0267             // Check for code in param
0268             const codeParam = urlParams.get('code');
0269             if (codeParam) { // We do have code!
0270                 decodeCodePara = LZString.decompressFromEncodedURIComponent(codeParam);
0271                 editor.session.setValue(decodeCodePara)
0272             } else { // We don't
0273                 // Try to load last session
0274                 var lastSessionCode = localStorage.getItem("lastSessionCode");
0275                 if (lastSessionCode) {
0276                     editor.session.setValue(lastSessionCode);
0277                     qml.setCode(lastSessionCode)
0278                     eraseTerminal()
0279                 } else { // No last session, load the magic of the infinity happiness
0280                     openExample('rotationanimator.qml')
0281                 }
0282                 // Force resize: Fix bug with firefox 77.0.1
0283                 editor.resize();
0284             }
0285 
0286             const buildInfo = qml.buildInfo()
0287             if (buildInfo) {
0288                 populateBuildInfo(buildInfo)
0289             }
0290 
0291             // Resize editor
0292             resizeSplitX()
0293         }
0294 
0295         function format() {
0296             let cursorPosition = editor.selection.getCursor();
0297             var beautify = ace.require("ace/ext/beautify");
0298             beautify.beautify(editor.session);
0299             editor.moveCursorTo(cursorPosition.row, cursorPosition.column);
0300         }
0301 
0302         function share() {
0303             let string = editor.session.getValue();
0304             let compressed = LZString.compressToEncodedURIComponent(string);
0305             console.log("Compressed in:", compressed.length / string.length)
0306 
0307             let tinyUrl = "https://tinyurl.com/api-create.php\?url\=" + window.location.href.split('?')[0] + "?code=" +
0308                 encodeURI(compressed)
0309 
0310             let request = new XMLHttpRequest();
0311             request.open('GET', tinyUrl);
0312             // TODO: Only for debug, remove after github pages test
0313             open(tinyUrl)
0314             request.send();
0315             request.onload = function () {
0316                 if (request.status == 200) {
0317                     console.log(`Get OK ${request.response}`)
0318                     var popup = document.getElementById("myPopup");
0319                     popup.value = request.response
0320                     popup.classList.toggle("show");
0321                 } else {
0322                     console.log(`GET Error ${request.status}: ${request.statusText}`);
0323                 }
0324             }
0325         }
0326     </script>
0327 </body>
0328 
0329 </html>