| 1 | // Copyright (C) 2021 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
| 3 | |
| 4 | #include "inputtab.h" |
| 5 | |
| 6 | #include "inputlistview.h" |
| 7 | #include "settingstab.h" |
| 8 | |
| 9 | #include <QFileDialog> |
| 10 | #include <QGridLayout> |
| 11 | #include <QLabel> |
| 12 | #include <QLineEdit> |
| 13 | #include <QPlainTextEdit> |
| 14 | #include <QPushButton> |
| 15 | #include <QtQuick3DAssetImport/private/qssgassetimportmanager_p.h> |
| 16 | |
| 17 | InputTab::InputTab(SettingsTab *settings, QWidget *parent) : QWidget(parent), settingsTab(settings) |
| 18 | { |
| 19 | QLabel *fileNameLabel = new QLabel(tr(s: "Input files:" )); |
| 20 | lastInputPath = QDir::currentPath(); |
| 21 | inputFilesListBox = new InputListView; |
| 22 | |
| 23 | convertButton = new QPushButton("Convert" , this); |
| 24 | connect(sender: convertButton, signal: &QAbstractButton::clicked, context: this, slot: [&]() { convert(); }); |
| 25 | |
| 26 | statusText = new QPlainTextEdit; |
| 27 | statusText->setReadOnly(true); |
| 28 | |
| 29 | QObject::connect(sender: &converterThread, signal: &ConverterThread::convertDone, context: this, slot: &InputTab::convertDone); |
| 30 | QObject::connect(sender: &converterThread, signal: &ConverterThread::convertStart, context: this, slot: &InputTab::convertStart); |
| 31 | QObject::connect(sender: &converterThread, signal: &ConverterThread::convertUpdate, context: this, slot: &InputTab::convertUpdate); |
| 32 | |
| 33 | QPushButton *browseInputButton = new QPushButton(tr(s: "Browse..." ), this); |
| 34 | connect(sender: browseInputButton, signal: &QAbstractButton::clicked, context: this, slot: &InputTab::browseInput); |
| 35 | |
| 36 | QPushButton *removeSelectedButton = new QPushButton(tr(s: "Remove selected" ), this); |
| 37 | connect(sender: removeSelectedButton, signal: &QAbstractButton::clicked, context: this, slot: &InputTab::removeSelected); |
| 38 | QPushButton *selectAllButton = new QPushButton(tr(s: "Select all" ), this); |
| 39 | connect(sender: selectAllButton, signal: &QAbstractButton::clicked, context: this, slot: &InputTab::selectAll); |
| 40 | |
| 41 | QLabel *pathLabel = new QLabel(tr(s: "Output folder:" )); |
| 42 | outputPathEdit = new QLineEdit(QDir::currentPath()); |
| 43 | QPushButton *browseOutputButton = new QPushButton(tr(s: "Browse..." ), this); |
| 44 | connect(sender: browseOutputButton, signal: &QAbstractButton::clicked, context: this, slot: &InputTab::browseOutput); |
| 45 | |
| 46 | QLabel *emptyLabel = new QLabel(); |
| 47 | |
| 48 | QGridLayout *mainLayout = new QGridLayout; |
| 49 | |
| 50 | constexpr int rowFileNameLabel = 0; |
| 51 | constexpr int rowinputFiles = 1; |
| 52 | constexpr int rowOutputPathLabel = 5; |
| 53 | constexpr int rowOutputPathEdit = 6; |
| 54 | constexpr int rowStatusLabel = 7; |
| 55 | |
| 56 | mainLayout->addWidget(fileNameLabel, row: rowFileNameLabel, column: 0, rowSpan: 1, columnSpan: 2); |
| 57 | mainLayout->addWidget(inputFilesListBox, row: rowinputFiles, column: 0, rowSpan: 4, columnSpan: 1); |
| 58 | mainLayout->addWidget(browseInputButton, row: rowinputFiles, column: 1); |
| 59 | mainLayout->addWidget(removeSelectedButton, row: rowinputFiles + 1, column: 1); |
| 60 | mainLayout->addWidget(selectAllButton, row: rowinputFiles + 2, column: 1); |
| 61 | mainLayout->addWidget(emptyLabel, row: rowinputFiles + 3, column: 1); |
| 62 | mainLayout->setRowStretch(row: rowinputFiles + 3, stretch: 1); |
| 63 | |
| 64 | mainLayout->addWidget(pathLabel, row: rowOutputPathLabel, column: 0, rowSpan: 1, columnSpan: 2); |
| 65 | |
| 66 | mainLayout->addWidget(outputPathEdit, row: rowOutputPathEdit, column: 0); |
| 67 | mainLayout->addWidget(browseOutputButton, row: rowOutputPathEdit, column: 1); |
| 68 | |
| 69 | mainLayout->addWidget(new QLabel("Status:" ), row: rowStatusLabel, column: 0, rowSpan: 1, columnSpan: 2); |
| 70 | mainLayout->addWidget(statusText, row: rowStatusLabel + 1, column: 0, rowSpan: 1, columnSpan: 2); |
| 71 | mainLayout->addWidget(convertButton, row: rowStatusLabel + 2, column: 0, rowSpan: 1, columnSpan: 2); |
| 72 | |
| 73 | setLayout(mainLayout); |
| 74 | } |
| 75 | |
| 76 | void InputTab::convert() |
| 77 | { |
| 78 | QStringList filenames = getInputFiles(); |
| 79 | QDir outputPath = getOutputPath(); |
| 80 | |
| 81 | const auto options = settingsTab->getOptions(); |
| 82 | |
| 83 | converterThread.convert(filenames, outputPath, options); |
| 84 | } |
| 85 | |
| 86 | void InputTab::convertStart(const QString &text) |
| 87 | { |
| 88 | statusText->setPlainText(text); |
| 89 | convertButton->setText(QString("Converting..." )); |
| 90 | convertButton->setDisabled(true); |
| 91 | } |
| 92 | |
| 93 | void InputTab::convertUpdate(const QString &text) |
| 94 | { |
| 95 | statusText->appendPlainText(text); |
| 96 | } |
| 97 | |
| 98 | void InputTab::convertDone(const QString &text) |
| 99 | { |
| 100 | statusText->appendPlainText(text); |
| 101 | convertButton->setText(QString("Convert" )); |
| 102 | convertButton->setDisabled(false); |
| 103 | } |
| 104 | |
| 105 | QStringList InputTab::getInputFiles() const |
| 106 | { |
| 107 | QStringList files; |
| 108 | for (int i = 0; i < inputFilesListBox->count(); ++i) |
| 109 | files.push_back(t: inputFilesListBox->item(row: i)->text()); |
| 110 | return files; |
| 111 | } |
| 112 | |
| 113 | QString InputTab::getOutputPath() const |
| 114 | { |
| 115 | return outputPathEdit->text(); |
| 116 | } |
| 117 | |
| 118 | void InputTab::browseInput() |
| 119 | { |
| 120 | QFileDialog dialog(this); |
| 121 | dialog.setFileMode(QFileDialog::ExistingFiles); |
| 122 | dialog.setDirectory(lastInputPath); |
| 123 | |
| 124 | const auto allDescs = QSSGAssetImportManager().getImporterPluginInfos(); |
| 125 | |
| 126 | QStringList nameFilters; |
| 127 | for (const auto &plugin : allDescs) { |
| 128 | nameFilters.append(t: tr(s: "%1 files (*.%2)" ).arg(args: plugin.typeDescription, args: plugin.inputExtensions.join(QStringLiteral(" *." )))); |
| 129 | } |
| 130 | nameFilters.append(t: tr(s: "Any files (*)" )); |
| 131 | dialog.setNameFilters(nameFilters); |
| 132 | |
| 133 | if (!dialog.exec()) |
| 134 | return; |
| 135 | |
| 136 | const auto selectedFiles = dialog.selectedFiles(); |
| 137 | for (const auto &file : selectedFiles) |
| 138 | inputFilesListBox->tryAddItem(label: QDir::toNativeSeparators(pathName: file)); |
| 139 | |
| 140 | if (!selectedFiles.empty()) |
| 141 | lastInputPath = QFileInfo(selectedFiles.first()).absoluteDir().absolutePath(); |
| 142 | } |
| 143 | |
| 144 | void InputTab::browseOutput() |
| 145 | { |
| 146 | QString dir = QFileDialog::getExistingDirectory(parent: this, |
| 147 | caption: tr(s: "Open Directory" ), |
| 148 | dir: outputPathEdit->text(), |
| 149 | options: QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); |
| 150 | if (!dir.isEmpty()) { |
| 151 | outputPathEdit->setText(dir); |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | void InputTab::removeSelected() |
| 156 | { |
| 157 | QList<QListWidgetItem *> selectedItems = inputFilesListBox->selectedItems(); |
| 158 | for (int i = 0; i < inputFilesListBox->count(); ++i) { |
| 159 | auto item = inputFilesListBox->item(row: i); |
| 160 | if (selectedItems.contains(t: item)) { |
| 161 | inputFilesListBox->takeItem(row: i); |
| 162 | selectedItems.removeAll(t: item); |
| 163 | i--; |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | void InputTab::selectAll() |
| 169 | { |
| 170 | for (int i = 0; i < inputFilesListBox->count(); ++i) { |
| 171 | auto item = inputFilesListBox->item(row: i); |
| 172 | item->setSelected(true); |
| 173 | } |
| 174 | } |
| 175 | |