Skip to content

Commit 7df614a

Browse files
committed
initial commit
0 parents  commit 7df614a

18 files changed

+1199
-0
lines changed

FileSelectionDialog.qml

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import QtQuick 2.0
2+
import QtQuick.Controls 2.0
3+
import QtQuick.Layouts 1.3
4+
import Qt.labs.settings 1.0
5+
6+
Item {
7+
property bool selected: false
8+
property string folder: ""
9+
property string file: ""
10+
property bool autoSelect: true
11+
property var model: []
12+
13+
id: root
14+
15+
QtObject {
16+
id: d
17+
readonly property var filteredModel: filterModel(root.model)
18+
19+
function filterModel(model) {
20+
var newModel = []
21+
for (var key in model) {
22+
var item = model[key]
23+
if (item.toLowerCase().indexOf(filterInput.text.toLowerCase()) !== -1) {
24+
newModel.push(item)
25+
}
26+
}
27+
return newModel
28+
}
29+
30+
function select(file) {
31+
root.file = "file://" + file
32+
// @disable-check M110
33+
root.folder = "file://" + new String(file).substring(
34+
0, file.lastIndexOf('/'))
35+
root.selected = true
36+
}
37+
}
38+
39+
Settings {
40+
property alias filterText: filterInput.text
41+
}
42+
43+
ColumnLayout {
44+
anchors.fill: parent
45+
46+
TextField {
47+
id: filterInput
48+
Layout.fillWidth: true
49+
placeholderText: "filter"
50+
51+
onFocusChanged: {
52+
if (focus) {
53+
selectAll()
54+
}
55+
}
56+
}
57+
58+
ListView {
59+
id: listView
60+
Layout.fillWidth: true
61+
Layout.fillHeight: true
62+
clip: true
63+
model: d.filteredModel
64+
65+
delegate: Button {
66+
readonly property string data_: d.filteredModel[index]
67+
text: data_
68+
onClicked: d.select(text)
69+
height: visible ? 30 : 0
70+
}
71+
72+
onCountChanged: {
73+
if (root.autoSelect && (count == 1) && !root.selected) {
74+
selectTimer.start()
75+
}
76+
}
77+
}
78+
}
79+
80+
Timer {
81+
id: selectTimer
82+
interval: 10
83+
onTriggered: d.select(d.filteredModel[0])
84+
}
85+
}

LiveWindow.qml

+217
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
import QtQuick 2.9
2+
import QtQuick.Controls 2.2
3+
import QtQuick.Layouts 1.3
4+
import QtQuick.Window 2.0
5+
import Qt.labs.settings 1.0
6+
import com.machinekoder.live 1.0
7+
8+
Item {
9+
id: root
10+
property alias hideToolBar: hideToolBarCheck.checked
11+
property int flags: Qt.Window
12+
property int visibility: Window.AutomaticVisibility
13+
14+
QtObject {
15+
id: d
16+
17+
function reload() {
18+
loader.source = ""
19+
ApplicationHelpers.clearQmlComponentCache()
20+
loader.source = fileDialog.file
21+
}
22+
23+
function openWithSystemEditor() {
24+
ApplicationHelpers.openUrlWithDefaultApplication(fileDialog.file)
25+
}
26+
27+
function unload() {
28+
loader.source = ""
29+
fileDialog.selected = false
30+
browser.update()
31+
}
32+
33+
function restart() {
34+
ApplicationHelpers.restartApplication()
35+
}
36+
}
37+
38+
MouseArea {
39+
id: smallArea
40+
anchors.top: parent.top
41+
anchors.left: parent.left
42+
anchors.right: parent.right
43+
height: 10
44+
width: height
45+
z: 10
46+
visible: contentItem.loaded && !fullArea.delayedVisible
47+
hoverEnabled: true
48+
propagateComposedEvents: true
49+
50+
onClicked: mouse.accepted = false
51+
onEntered: fullArea.visible = true
52+
}
53+
54+
MouseArea {
55+
property bool delayedVisible: false
56+
57+
id: fullArea
58+
anchors.top: parent.top
59+
anchors.right: parent.right
60+
anchors.left: parent.left
61+
height: 40
62+
z: 9
63+
hoverEnabled: true
64+
propagateComposedEvents: true
65+
visible: false
66+
67+
onClicked: mouse.accepted = false
68+
onPressed: mouse.accepted = false
69+
onReleased: mouse.accepted = false
70+
onExited: visible = false
71+
onVisibleChanged: delayTimer.start()
72+
73+
Timer {
74+
id: delayTimer
75+
interval: 10
76+
onTriggered: fullArea.delayedVisible = fullArea.visible // break binding loop
77+
}
78+
}
79+
80+
ColumnLayout {
81+
anchors.fill: parent
82+
anchors.topMargin: menuBar.visible ? 5 : 0
83+
84+
RowLayout {
85+
id: menuBar
86+
visible: !hideToolBarCheck.checked || (smallArea.containsMouse
87+
|| fullArea.containsMouse
88+
|| !contentItem.loaded)
89+
90+
Button {
91+
Layout.preferredHeight: 30
92+
enabled: fileDialog.selected
93+
text: qsTr("Edit")
94+
onClicked: d.openWithSystemEditor()
95+
}
96+
97+
Button {
98+
Layout.preferredHeight: 30
99+
enabled: fileDialog.selected
100+
text: qsTr("Unload")
101+
onClicked: d.unload()
102+
}
103+
104+
Button {
105+
Layout.preferredHeight: 30
106+
text: qsTr("Reload")
107+
onClicked: d.reload()
108+
}
109+
110+
Button {
111+
Layout.preferredHeight: 30
112+
text: qsTr("Restart")
113+
onClicked: d.restart()
114+
}
115+
116+
Item {
117+
Layout.fillWidth: true
118+
}
119+
120+
CheckBox {
121+
id: hideToolBarCheck
122+
text: qsTr("Hide Tool Bar")
123+
checked: false
124+
}
125+
126+
CheckBox {
127+
text: qsTr("Fullscreen")
128+
checked: root.visibility === Window.FullScreen
129+
130+
onClicked: {
131+
if (checked) {
132+
root.visibility = Window.FullScreen
133+
} else {
134+
root.visibility = Window.AutomaticVisibility
135+
}
136+
}
137+
138+
Component.onCompleted: checked = root.visibility === Window.FullScreen
139+
}
140+
141+
CheckBox {
142+
text: qsTr("On Top")
143+
checked: root.flags & Qt.WindowStaysOnTopHint
144+
145+
onClicked: {
146+
if (checked) {
147+
root.flags = root.flags | Qt.WindowStaysOnTopHint
148+
} else {
149+
root.flags = root.flags & ~Qt.WindowStaysOnTopHint
150+
}
151+
}
152+
153+
Component.onCompleted: checked = root.flags & Qt.WindowStaysOnTopHint
154+
}
155+
}
156+
157+
Item {
158+
id: contentItem
159+
Layout.fillWidth: true
160+
Layout.fillHeight: true
161+
property bool loaded: loader.status !== Loader.Null
162+
163+
Loader {
164+
id: loader
165+
anchors.fill: parent
166+
167+
onStatusChanged: {
168+
if (status !== Loader.Error) {
169+
return
170+
}
171+
172+
var msg = loader.sourceComponent.errorString()
173+
errorLabel.text = qsTr("QML Error: Loading QML file failed:\n") + msg
174+
}
175+
}
176+
177+
Label {
178+
id: errorLabel
179+
anchors.left: parent.left
180+
anchors.right: parent.right
181+
anchors.verticalCenter: parent.verticalCenter
182+
horizontalAlignment: Text.AlignHCenter
183+
wrapMode: Text.Wrap
184+
visible: loader.status === Loader.Error
185+
}
186+
187+
FileSelectionDialog {
188+
id: fileDialog
189+
anchors.fill: parent
190+
model: browser.qmlFiles
191+
visible: !contentItem.loaded
192+
193+
onSelectedChanged: {
194+
if (selected) {
195+
d.reload()
196+
}
197+
}
198+
}
199+
}
200+
}
201+
202+
ProjectBrowser {
203+
id: browser
204+
}
205+
206+
FileWatcher {
207+
id: fileWatcher
208+
fileUrl: browser.projectPath
209+
recursive: true
210+
enabled: fileDialog.selected
211+
onFileChanged: {
212+
d.reload()
213+
}
214+
nameFilters: ["*.qmlc", "*.jsc", "*.pyc", ".#*", ".*", "__pycache__", "*___jb_tmp___", // PyCharm safe write
215+
"*___jb_old___"]
216+
}
217+
}

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# C++ Qt Live Coding
2+
3+
This project aims to be the C++ version for Qt/QML live coding.
4+
5+
In constrast to other live coding environments, this project is a live coding QML module meant to be integrated into your application.
6+
7+
Integrating QML live coding into your application significantly boosts your HMI developers productivity. Compared to stand-alone solutions, this approach enables integration of C++ QML components without deploying them first.
8+
9+
Additionally, it enabled customization of the live coding environemnt, including pre-loading of resource intensive QML components.
10+
11+
## Install
12+
13+
14+
## How to Use

applicationhelpers.cpp

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "applicationhelpers.h"
2+
#include <QDesktopServices>
3+
#include <QLocale>
4+
#include <QProcess>
5+
#include <QSettings>
6+
#include <QCoreApplication>
7+
8+
ApplicationHelpers::ApplicationHelpers(QQmlEngine *engine, QObject *parent)
9+
: QObject(parent)
10+
, m_engine(engine)
11+
{
12+
13+
}
14+
15+
bool ApplicationHelpers::openUrlWithDefaultApplication(const QUrl &url) const
16+
{
17+
return QDesktopServices::openUrl(url);
18+
}
19+
20+
void ApplicationHelpers::clearQmlComponentCache() const
21+
{
22+
m_engine->clearComponentCache();
23+
}
24+
25+
QString ApplicationHelpers::currentLanguage() const
26+
{
27+
const auto languages = QLocale().uiLanguages();
28+
return languages.first();
29+
}
30+
31+
void ApplicationHelpers::setLanguage(const QString &language)
32+
{
33+
QSettings settings;
34+
settings.setValue("language", language);
35+
settings.sync();
36+
}
37+
38+
void ApplicationHelpers::restartApplication()
39+
{
40+
qApp->quit();
41+
QProcess::startDetached(qApp->arguments()[0], qApp->arguments());
42+
}

0 commit comments

Comments
 (0)