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>