aboutsummaryrefslogtreecommitdiff
path: root/qt
diff options
context:
space:
mode:
Diffstat (limited to 'qt')
-rw-r--r--qt/CMakeLists.txt2
-rw-r--r--qt/Main.qml (renamed from qt/NissyMain.qml)135
-rw-r--r--qt/adapter.cpp33
-rw-r--r--qt/adapter.h7
-rw-r--r--qt/main.cpp2
5 files changed, 137 insertions, 42 deletions
diff --git a/qt/CMakeLists.txt b/qt/CMakeLists.txt
index 8ba768c..42c6d52 100644
--- a/qt/CMakeLists.txt
+++ b/qt/CMakeLists.txt
@@ -19,7 +19,7 @@ qt_add_executable(appnissyqt
19qt_add_qml_module(appnissyqt 19qt_add_qml_module(appnissyqt
20 URI nissyqt 20 URI nissyqt
21 VERSION 1.0 21 VERSION 1.0
22 QML_FILES NissyMain.qml 22 QML_FILES Main.qml
23) 23)
24 24
25target_link_libraries(appnissyqt 25target_link_libraries(appnissyqt
diff --git a/qt/NissyMain.qml b/qt/Main.qml
index 24aff43..a6e034a 100644
--- a/qt/NissyMain.qml
+++ b/qt/Main.qml
@@ -43,9 +43,11 @@ Window {
43 id: mainArea 43 id: mainArea
44 44
45 property alias scramble: scrambleRow.scramble 45 property alias scramble: scrambleRow.scramble
46 property alias solver: solverCfg.solver
46 property alias minmoves: solverCfg.minmoves 47 property alias minmoves: solverCfg.minmoves
47 property alias maxmoves: solverCfg.maxmoves 48 property alias maxmoves: solverCfg.maxmoves
48 property alias maxsolutions: solverCfg.maxsolutions 49 property alias maxsolutions: solverCfg.maxsolutions
50 property alias optimal: solverCfg.optimal
49 property alias sols: sols.text 51 property alias sols: sols.text
50 property alias solsHeader: solsHeader.text 52 property alias solsHeader: solsHeader.text
51 53
@@ -59,7 +61,7 @@ Window {
59 spacing: 10 61 spacing: 10
60 62
61 SplitView.minimumHeight: 180 63 SplitView.minimumHeight: 180
62 SplitView.preferredHeight: 300 64 SplitView.preferredHeight: 500
63 65
64 component Separator: Rectangle { 66 component Separator: Rectangle {
65 height: 1 67 height: 1
@@ -67,6 +69,50 @@ Window {
67 color: "black" 69 color: "black"
68 } 70 }
69 71
72 component OptionalValue: RowLayout {
73 property alias currentValue: valueRect.value
74 property alias from: spinBox.from
75 property alias to: spinBox.to
76 property alias defaultValue: spinBox.value
77 property alias defaultEnabled: sw.checked
78 property alias label: sw.text
79 property int defaultSavedValue: 1
80 property int savedValue: defaultSavedValue
81
82 Switch {
83 id: sw
84
85 checked: true
86
87 onToggled: () => {
88 if (checked) {
89 currentValue = savedValue
90 } else {
91 savedValue = currentValue
92 currentValue = spinBox.to
93 }
94 }
95 }
96
97 Rectangle {
98 id: valueRect
99
100 property alias enabled: sw.checked
101 property alias value: spinBox.value
102
103 width: 65
104 height: 20
105
106 SpinBox {
107 id: spinBox
108
109 width: parent.width
110 editable: true
111 enabled: parent.enabled
112 }
113 }
114 }
115
70 ColumnLayout { 116 ColumnLayout {
71 id: scrambleRow 117 id: scrambleRow
72 118
@@ -114,9 +160,36 @@ Window {
114 160
115 ColumnLayout { 161 ColumnLayout {
116 id: solverCfg 162 id: solverCfg
163
117 property alias minmoves: minMaxRow.min 164 property alias minmoves: minMaxRow.min
118 property alias maxmoves: minMaxRow.max 165 property alias maxmoves: minMaxRow.max
119 property alias maxsolutions: maxOptimal.maxsolutions 166 property alias maxsolutions: maxSols.currentValue
167 property alias optimal: optimal.currentValue
168 property alias solver: solverRow.solver
169
170 RowLayout {
171 id: solverRow
172
173 property alias solver: comboBox.currentValue
174
175 Label { text: "Solver" }
176 ComboBox {
177 id: comboBox
178
179 currentIndex: 3
180 textRole: "text"
181 valueRole: "name"
182 implicitContentWidthPolicy: ComboBox.WidestTextWhenCompleted
183
184 model: ListModel {
185 ListElement { text: "h48 h=0, k=4 (59 Mb)"; name: "h48h0k4" }
186 ListElement { text: "h48 h=1, k=2 (115 Mb)"; name: "h48h1k2" }
187 ListElement { text: "h48 h=2, k=2 (171 Mb)"; name: "h48h2k2" }
188 ListElement { text: "h48 h=3, k=2 (283 Mb)"; name: "h48h3k2" }
189 ListElement { text: "h48 h=7, k=2 (3.6 Gb)"; name: "h48h7k2" }
190 }
191 }
192 }
120 193
121 RowLayout { 194 RowLayout {
122 id: minMaxRow 195 id: minMaxRow
@@ -148,40 +221,38 @@ Window {
148 } 221 }
149 } 222 }
150 223
151 RowLayout { 224 OptionalValue {
152 id: maxOptimal 225 id: optimal
153
154 property alias maxsolutions: maxSolsRect.maxsolutions
155
156 Rectangle {
157 width: 220
158 height: 20
159 Label { text: "Maximum number of solutions:" }
160 }
161 Rectangle {
162 id: maxSolsRect
163
164 property int maxsolutions: parseInt(textField.text)
165
166 width: 35
167 height: 20
168 226
169 TextField { 227 label: "Above optimal by at most"
170 id: textField 228 from: 0
229 to: 20
230 defaultValue: 20
231 defaultEnabled: false
232 defaultSavedValue: 0
233 }
171 234
172 width: parent.width 235 OptionalValue {
173 text: "1" 236 id: maxSols
174 validator: IntValidator{ bottom: 1; top: 999; }
175 237
176 onAccepted: submitScramble() 238 label: "Limit number of solutions to"
177 } 239 from: 1
178 } 240 to: 999
241 defaultValue: 1
242 defaultEnabled: true
243 defaultSavedValue: 1
179 } 244 }
180 } 245 }
181 246
182 Separator {} 247 Separator {}
183 248
184 Label { id: solsHeader } 249 StackLayout {
250 Layout.maximumHeight: 30
251 currentIndex: mainArea.solutionsLoading ? 0 : 1
252
253 BusyIndicator { running: mainArea.solutionsLoading }
254 Label { id: solsHeader }
255 }
185 256
186 ScrollView { 257 ScrollView {
187 Layout.fillHeight: true 258 Layout.fillHeight: true
@@ -229,16 +300,16 @@ Window {
229 300
230 function submitScramble() { 301 function submitScramble() {
231 mainArea.solutionsLoading = true; 302 mainArea.solutionsLoading = true;
232 mainArea.solsHeader = "Loading solutions..." 303 mainArea.solsHeader = ""
233 mainArea.sols = "" 304 mainArea.sols = ""
234 logView.text = "" 305 logView.text = ""
235 NissyAdapter.requestSolve( 306 NissyAdapter.requestSolve(
236 mainArea.scramble, 307 mainArea.scramble,
237 "h48h3k2", 308 mainArea.solver,
238 mainArea.minmoves, 309 mainArea.minmoves,
239 mainArea.maxmoves, 310 mainArea.maxmoves,
240 mainArea.maxsolutions, 311 mainArea.maxsolutions,
241 -1 312 mainArea.optimal
242 ) 313 )
243 } 314 }
244 315
@@ -251,7 +322,7 @@ Window {
251 } 322 }
252 function onSolverError(msg) { 323 function onSolverError(msg) {
253 mainArea.solutionsLoading = false 324 mainArea.solutionsLoading = false
254 mainArea.solusHeader = msg 325 mainArea.solsHeader = msg
255 mainArea.sols = "" 326 mainArea.sols = ""
256 } 327 }
257 function onAppendLog(msg) { 328 function onAppendLog(msg) {
diff --git a/qt/adapter.cpp b/qt/adapter.cpp
index 3711fa4..cb690a4 100644
--- a/qt/adapter.cpp
+++ b/qt/adapter.cpp
@@ -9,20 +9,25 @@
9 9
10void logWrapper(const char *str, void *data) 10void logWrapper(const char *str, void *data)
11{ 11{
12 auto f = *reinterpret_cast<std::function<void(const char*)>*>(data); 12 auto f = *reinterpret_cast<std::function<void(std::string)>*>(data);
13 f(str); 13 f(std::string{str});
14} 14}
15 15
16NissyAdapter::NissyAdapter() 16NissyAdapter::NissyAdapter()
17{ 17{
18 // TODO: this list must be kept in sync with UI code, it is a bit ugly
18 std::vector<std::string> solverNames { 19 std::vector<std::string> solverNames {
19 "h48h3k2" 20 "h48h0k4",
21 "h48h1k2",
22 "h48h2k2",
23 "h48h3k2",
24 "h48h7k2",
20 }; 25 };
21 26
22 for (auto s : solverNames) 27 for (auto s : solverNames)
23 initSolver(s); 28 initSolver(s);
24 29
25 writeLog = [&](const char *str) { 30 writeLog = [&](std::string str) {
26 emit appendLog(QString::fromStdString(str)); 31 emit appendLog(QString::fromStdString(str));
27 }; 32 };
28 33
@@ -45,6 +50,8 @@ bool NissyAdapter::loadSolverData(nissy::solver& solver) {
45 50
46 std::filesystem::path filePath("./tables/" + solver.id); 51 std::filesystem::path filePath("./tables/" + solver.id);
47 if (!std::filesystem::exists(filePath)) { 52 if (!std::filesystem::exists(filePath)) {
53 logLine("Data file for solver " + solver.name + " not found, "
54 "generating it...");
48 auto err = solver.generate_data(); 55 auto err = solver.generate_data();
49 if (!err.ok()) { 56 if (!err.ok()) {
50 emit solverError(QString("Error generating data!")); 57 emit solverError(QString("Error generating data!"));
@@ -55,16 +62,23 @@ bool NissyAdapter::loadSolverData(nissy::solver& solver) {
55 ofs.write(reinterpret_cast<char *>(solver.data.data()), 62 ofs.write(reinterpret_cast<char *>(solver.data.data()),
56 solver.size); 63 solver.size);
57 ofs.close(); 64 ofs.close();
65 logLine("Data generated succesfully");
58 } else { 66 } else {
67 logLine("Reading data for solver " + solver.name +
68 " from file");
59 std::ifstream ifs(filePath, std::ios::binary); 69 std::ifstream ifs(filePath, std::ios::binary);
60 solver.read_data(ifs); 70 solver.read_data(ifs);
61 ifs.close(); 71 ifs.close();
72 logLine("Data loaded");
62 } 73 }
63 74
75 logLine("Checking data integrity "
76 "(this is done only once per solver per session)...");
64 if (!solver.check_data().ok()) { 77 if (!solver.check_data().ok()) {
65 emit solverError(QString("Error reading data!")); 78 emit solverError(QString("Error reading data!"));
66 return false; 79 return false;
67 } 80 }
81 logLine("Data checked");
68 82
69 return true; 83 return true;
70} 84}
@@ -102,7 +116,7 @@ Q_INVOKABLE void NissyAdapter::requestSolve(
102 } 116 }
103 117
104 SolveOptions opts{c, ss, (unsigned)minmoves, (unsigned)maxmoves, 118 SolveOptions opts{c, ss, (unsigned)minmoves, (unsigned)maxmoves,
105 (unsigned)maxsolutions, optimal}; 119 (unsigned)maxsolutions, (unsigned)optimal};
106 auto _ = QtConcurrent::run(&NissyAdapter::startSolve, this, opts); 120 auto _ = QtConcurrent::run(&NissyAdapter::startSolve, this, opts);
107 return; 121 return;
108} 122}
@@ -132,9 +146,16 @@ void NissyAdapter::startSolve(SolveOptions opts)
132 std::stringstream ss; 146 std::stringstream ss;
133 for (auto s : sols) { 147 for (auto s : sols) {
134 auto n = nissy::count_moves(s).value; 148 auto n = nissy::count_moves(s).value;
135 ss << s << "(" << n << ")" << std::endl; // TODO: remove last newline 149 ss << s << " (" << n << ")" << std::endl; // TODO: remove last newline
136 } 150 }
137 emit solutionsReady(QString::fromStdString(hs.str()), 151 emit solutionsReady(QString::fromStdString(hs.str()),
138 QString::fromStdString(ss.str())); 152 QString::fromStdString(ss.str()));
139 } 153 }
140} 154}
155
156void NissyAdapter::logLine(std::string str)
157{
158 std::stringstream ss;
159 ss << str << std::endl;
160 writeLog(ss.str());
161}
diff --git a/qt/adapter.h b/qt/adapter.h
index 856cdad..e961459 100644
--- a/qt/adapter.h
+++ b/qt/adapter.h
@@ -14,7 +14,7 @@ struct SolveOptions {
14 unsigned minmoves; 14 unsigned minmoves;
15 unsigned maxmoves; 15 unsigned maxmoves;
16 unsigned maxsolutions; 16 unsigned maxsolutions;
17 int optimal; 17 unsigned optimal;
18}; 18};
19 19
20class NissyAdapter : public QObject { 20class NissyAdapter : public QObject {
@@ -23,6 +23,8 @@ class NissyAdapter : public QObject {
23 QML_ELEMENT 23 QML_ELEMENT
24 24
25public: 25public:
26 static constexpr int maxSolutionsHardLimit = 9999;
27
26 NissyAdapter(); 28 NissyAdapter();
27 29
28 Q_INVOKABLE bool isValidScramble(QString); 30 Q_INVOKABLE bool isValidScramble(QString);
@@ -42,11 +44,12 @@ signals:
42 44
43private: 45private:
44 std::vector<nissy::solver> solvers; 46 std::vector<nissy::solver> solvers;
45 std::function<void(const char*)> writeLog; 47 std::function<void(std::string)> writeLog;
46 48
47 void initSolver(const std::string&); 49 void initSolver(const std::string&);
48 void startSolve(SolveOptions); 50 void startSolve(SolveOptions);
49 bool loadSolverData(nissy::solver&); 51 bool loadSolverData(nissy::solver&);
52 void logLine(std::string);
50}; 53};
51 54
52#endif 55#endif
diff --git a/qt/main.cpp b/qt/main.cpp
index 658d448..a012642 100644
--- a/qt/main.cpp
+++ b/qt/main.cpp
@@ -10,7 +10,7 @@ int main(int argc, char *argv[])
10 QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, 10 QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
11 &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); 11 &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection);
12 12
13 engine.loadFromModule("nissyqt", "NissyMain"); 13 engine.loadFromModule("nissyqt", "Main");
14 14
15 return app.exec(); 15 return app.exec();
16} 16}

Generated with cgit - Back to sebastiano.tronto.net