Skip to content

Commit 9a5a5f2

Browse files
First take on skycultureconverter
1 parent a6d0035 commit 9a5a5f2

File tree

4 files changed

+205
-67
lines changed

4 files changed

+205
-67
lines changed

plugins/SkyCultureMaker/CMakeLists.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ CPMAddPackage(
2121
)
2222

2323
# download https://github.com/artemvlas/qmicroz for archives
24-
# CPMAddPackage(
25-
# NAME qmicroz
26-
# GITHUB_REPOSITORY artemvlas/qmicroz
27-
# GIT_TAG v0.4
28-
# )
24+
CPMAddPackage(
25+
NAME qmicroz
26+
GITHUB_REPOSITORY artemvlas/qmicroz
27+
GIT_TAG v0.4
28+
)
2929

3030

3131
ADD_DEFINITIONS(-DSKYCULTUREMAKER_PLUGIN_VERSION="${SCM_VERSION}")

plugins/SkyCultureMaker/src/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,16 @@ ENDIF()
3333

3434
ADD_LIBRARY(SkyCultureMaker-static STATIC ${SkyCultureMaker_SRCS} ${SkyCultureMaker_RES_CXX} ${SCM_UIS})
3535
SET_TARGET_PROPERTIES(SkyCultureMaker-static PROPERTIES OUTPUT_NAME "SkyCultureMaker")
36-
TARGET_LINK_LIBRARIES(SkyCultureMaker-static Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Widgets skyculture_converter_lib)
36+
TARGET_LINK_LIBRARIES(SkyCultureMaker-static Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Widgets skyculture_converter_lib qmicroz)
37+
38+
target_include_directories(SkyCultureMaker-static
39+
PRIVATE
40+
${qmicroz_SOURCE_DIR}/src
41+
${qmicroz_SOURCE_DIR}/miniz
42+
)
3743

3844
SET_TARGET_PROPERTIES(SkyCultureMaker-static PROPERTIES COMPILE_FLAGS "-DQT_STATICPLUGIN")
3945
ADD_DEPENDENCIES(AllStaticPlugins SkyCultureMaker-static)
4046

4147
SET_TARGET_PROPERTIES(SkyCultureMaker-static PROPERTIES FOLDER "plugins/SkyCultureMaker")
48+

plugins/SkyCultureMaker/src/gui/ScmEditorDialog.cpp

Lines changed: 160 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
#include "ScmEditorDialog.hpp"
22
#include "ui_scmEditorDialog.h"
3+
#include "SkyCultureConverter.hpp"
4+
#include "qmicroz.h"
35
#include <QFileDialog>
46
#include <QFileSystemModel>
57
#include <QMessageBox>
8+
#include <QMimeDatabase>
9+
#include <QtConcurrent/QtConcurrent>
10+
#include <QFutureWatcher>
611

712
ScmEditorDialog::ScmEditorDialog()
813
: StelDialog("ScmEditorDialog")
@@ -88,31 +93,177 @@ void ScmEditorDialog::createDialogContent()
8893
connect(ui->saveLabelsBtn, &QPushButton::clicked, this, &ScmEditorDialog::saveLabels);
8994
updateLabelsSavedLabel(false);
9095

91-
/* ============================================= SCM importer/converter ============================================= */
96+
/* ============================================= SCM importer/converter */
9297
auto fsModel = new QFileSystemModel(this);
9398
fsModel->setRootPath(QDir::homePath());
9499
ui->fileSystem->setModel(fsModel);
95100
ui->fileSystem->setRootIndex(fsModel->index(QDir::homePath()));
96101

97102
connect(ui->fileSystem,
98-
&QTreeView::doubleClicked,
103+
&QTreeView::clicked,
99104
this,
100105
[this, fsModel](const QModelIndex &idx)
101106
{
102107
const QString path = fsModel->filePath(idx);
103108
ui->filePathLineEdit->setText(path);
104109
});
105-
connect(ui->pushButton, &QPushButton::clicked, this, [this]()
110+
111+
connect(
112+
ui->pushButton,
113+
&QPushButton::clicked,
114+
this,
115+
[this]()
116+
{
117+
const QString path = ui->filePathLineEdit->text();
118+
if (path.isEmpty())
119+
{
120+
ui->filePathLineEdit->setText("Please select a file.");
121+
return;
122+
}
123+
124+
qDebug() << "Selected file:" << path;
125+
126+
// Create a temporary directory for extraction
127+
QString baseName = QFileInfo(path).fileName(); // e.g. "foo.zip"
128+
int dotPos = baseName.indexOf('.');
129+
QString stem =
130+
(dotPos == -1) ? baseName : baseName.left(dotPos); // Extract the part before the first dot
131+
const QString tempDir = QDir::tempPath() + "/skycultures/" + stem;
132+
QDir().mkpath(tempDir);
133+
QDir tempFolder(tempDir);
134+
135+
ui->pushButton->setEnabled(false);
136+
137+
// Run conversion in a background thread
138+
QFuture<QString> future = QtConcurrent::run(
139+
[path, tempDir, tempFolder]() mutable -> QString
140+
{
141+
QString baseName = QFileInfo(path).fileName(); // e.g. "foo.zip"
142+
QString stem = baseName.left(baseName.lastIndexOf('.'));
143+
const QString tempDir = QDir::tempPath() + "/skycultures/" + stem;
144+
// Check if the file is a valid archive
145+
QMimeDatabase db;
146+
QMimeType mime = db.mimeTypeForFile(path, QMimeDatabase::MatchContent);
147+
148+
static const QStringList archiveTypes = {QStringLiteral("application/zip"),
149+
QStringLiteral("application/x-tar"),
150+
QStringLiteral("application/x-7z-compressed"),
151+
QStringLiteral("application/gzip"),
152+
QStringLiteral("application/x-rar-compressed"),
153+
QStringLiteral("application/vnd.rar")};
154+
155+
if (!archiveTypes.contains(mime.name()))
156+
{
157+
return QStringLiteral(
158+
"Please select a valid archive file (zip, tar, rar, 7z, gzip…)");
159+
}
160+
161+
try
162+
{
163+
QMicroz::extract(path, tempDir);
164+
qDebug() << "Archive extracted to:" << tempDir;
165+
}
166+
catch (const std::exception &e)
167+
{
168+
return QString("Error extracting archive: %1").arg(e.what());
169+
}
170+
171+
QStringList extracted_files =
172+
tempFolder.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
173+
qDebug() << "Extracted files:" << extracted_files.length();
174+
for (const QString &file : extracted_files)
175+
{
176+
qDebug() << " - " << file;
177+
}
178+
if (extracted_files.isEmpty())
179+
{
180+
return "No files found in the archive.";
181+
}
182+
183+
// set source as the folder that gets converted
184+
QString source;
185+
if (extracted_files.contains("info.ini"))
186+
source = tempDir;
187+
else if (extracted_files.length() == 1)
188+
source = tempDir + "/" + extracted_files.first();
189+
else
190+
return "Invalid archive structure. Expected 'info.ini' or a single subfolder.";
191+
192+
qDebug() << "Source for conversion:" << source;
193+
194+
// Destination is where the converted files will be saved
195+
QString destDir =
196+
QDir::homePath() + "/Documents/SkyCultureConverter/" +
197+
QFileInfo(path).fileName().left(QFileInfo(path).fileName().lastIndexOf('.'));
198+
qDebug() << "Destination for conversion:" << destDir;
199+
200+
SkyCultureConverter::ReturnValue result;
201+
202+
try
203+
{
204+
result = SkyCultureConverter::convert(source, destDir);
205+
}
206+
catch (const std::exception &e)
207+
{
208+
return QString("Error during conversion: %1").arg(e.what());
209+
}
210+
211+
QString msg;
212+
switch (result)
213+
{
214+
case SkyCultureConverter::ReturnValue::CONVERT_SUCCESS:
215+
msg = "Conversion completed successfully.";
216+
break;
217+
case SkyCultureConverter::ReturnValue::ERR_OUTPUT_DIR_EXISTS:
218+
msg = "Output directory already exists.";
219+
break;
220+
case SkyCultureConverter::ReturnValue::ERR_INFO_INI_NOT_FOUND:
221+
msg = "info.ini not found in the archive.";
222+
break;
223+
case SkyCultureConverter::ReturnValue::ERR_OUTPUT_DIR_CREATION_FAILED:
224+
msg = "Failed to create output directory.";
225+
break;
226+
case SkyCultureConverter::ReturnValue::ERR_OUTPUT_FILE_WRITE_FAILED:
227+
msg = "Failed to write output file.";
228+
break;
229+
default:
230+
msg = "Unknown error.";
231+
break;
232+
}
233+
qDebug() << "Conversion result:" << msg;
234+
return msg;
235+
});
236+
237+
// Watcher to re-enable the button & report result on UI thread
238+
auto *watcher = new QFutureWatcher<QString>(this);
239+
connect(watcher,
240+
&QFutureWatcher<QString>::finished,
241+
this,
242+
[this, watcher, tempFolder]() mutable
243+
{
244+
QString resultText = watcher->future().result();
245+
ui->filePathLineEdit->setText(resultText);
246+
tempFolder.removeRecursively();
247+
ui->pushButton->setEnabled(true);
248+
watcher->deleteLater();
249+
});
250+
watcher->setFuture(future);
251+
252+
qDebug() << "Conversion ended.";
253+
});
254+
// Reset the dialog when switching tabs
255+
const int importPage = ui->tabs->indexOf(ui->Import);
256+
connect(ui->tabs,
257+
&QTabWidget::currentChanged,
258+
this,
259+
[this, importPage](int idx)
106260
{
107-
const QString path = ui->filePathLineEdit->text();
108-
if (path.isEmpty())
261+
if (idx != importPage)
109262
{
110-
QMessageBox::warning(dialog, tr("No file selected"), tr("Please pick a file first."));
111-
return;
263+
ui->filePathLineEdit->clear();
112264
}
113-
qDebug() << "Importing file:" << path;
114265
});
115-
/* ================================================================================================================== */
266+
/* ==================================================================== */
116267
}
117268

118269
void ScmEditorDialog::saveLabels()

plugins/SkyCultureMaker/src/gui/scmEditorDialog.ui

Lines changed: 32 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -244,58 +244,38 @@
244244
<attribute name="title">
245245
<string>Import</string>
246246
</attribute>
247-
<widget class="QPushButton" name="pushButton">
248-
<property name="geometry">
249-
<rect>
250-
<x>10</x>
251-
<y>300</y>
252-
<width>581</width>
253-
<height>22</height>
254-
</rect>
255-
</property>
256-
<property name="text">
257-
<string>Import</string>
258-
</property>
259-
</widget>
260-
<widget class="QTreeView" name="fileSystem">
261-
<property name="geometry">
262-
<rect>
263-
<x>10</x>
264-
<y>39</y>
265-
<width>581</width>
266-
<height>221</height>
267-
</rect>
268-
</property>
269-
</widget>
270-
<widget class="QLineEdit" name="filePathLineEdit">
271-
<property name="geometry">
272-
<rect>
273-
<x>10</x>
274-
<y>270</y>
275-
<width>581</width>
276-
<height>22</height>
277-
</rect>
278-
</property>
279-
<property name="readOnly">
280-
<bool>true</bool>
281-
</property>
282-
<property name="placeholderText">
283-
<string>Select a file…</string>
284-
</property>
285-
</widget>
286-
<widget class="QLabel" name="label">
287-
<property name="geometry">
288-
<rect>
289-
<x>10</x>
290-
<y>10</y>
291-
<width>581</width>
292-
<height>16</height>
293-
</rect>
294-
</property>
295-
<property name="text">
296-
<string>Select an archive (.zip, .rar, ...) with an old format to convert to the new format</string>
297-
</property>
298-
</widget>
247+
<layout class="QVBoxLayout" name="importLayout">
248+
<item>
249+
<widget class="QLabel" name="label">
250+
<property name="text">
251+
<string>Select an archive (.zip, .rar, ...) with an old format to convert to the new format</string>
252+
</property>
253+
<property name="wordWrap">
254+
<bool>true</bool>
255+
</property>
256+
</widget>
257+
</item>
258+
<item>
259+
<widget class="QTreeView" name="fileSystem"/>
260+
</item>
261+
<item>
262+
<widget class="QLineEdit" name="filePathLineEdit">
263+
<property name="readOnly">
264+
<bool>true</bool>
265+
</property>
266+
<property name="placeholderText">
267+
<string>Select a file…</string>
268+
</property>
269+
</widget>
270+
</item>
271+
<item>
272+
<widget class="QPushButton" name="pushButton">
273+
<property name="text">
274+
<string>Import</string>
275+
</property>
276+
</widget>
277+
</item>
278+
</layout>
299279
</widget>
300280
<widget class="QWidget" name="License">
301281
<attribute name="title">

0 commit comments

Comments
 (0)