diff --git a/CMakeLists.txt b/CMakeLists.txt index 191c922..a542e75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,8 +40,6 @@ add_executable(${PROJECT_NAME} ${MusicGeneratorGUI_H} res/resources.qrc src/elidedlabel.h src/elidedlabel.cpp - src/SongItem.cpp - ) # UI file diff --git a/res/xyz.uvos.aceradio.png b/res/xyz.uvos.aceradio.png index 032045e..603d014 100644 Binary files a/res/xyz.uvos.aceradio.png and b/res/xyz.uvos.aceradio.png differ diff --git a/res/xyz.uvos.aceradio.svg b/res/xyz.uvos.aceradio.svg index 70a6ec5..23516fd 100644 --- a/res/xyz.uvos.aceradio.svg +++ b/res/xyz.uvos.aceradio.svg @@ -7,7 +7,7 @@ width="594" height="594" viewBox="0 0 594 594" - sodipodi:docname="xyz.uvos.aceradio.svg" + sodipodi:docname="icon.svg" inkscape:export-filename="icon64.png" inkscape:export-xdpi="10.343434" inkscape:export-ydpi="10.343434" @@ -28,9 +28,9 @@ inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" showguides="true" - inkscape:zoom="0.82324218" - inkscape:cx="38.8707" - inkscape:cy="407.535" + inkscape:zoom="0.58212013" + inkscape:cx="-146.01797" + inkscape:cy="490.44859" inkscape:window-width="1920" inkscape:window-height="1054" inkscape:window-x="0" @@ -45,14 +45,6 @@ - addSong(newSong); // Select the new item @@ -330,10 +335,18 @@ void MainWindow::on_songListView_doubleClicked(const QModelIndex &index) { SongItem song = songModel->getSong(row); - SongDialog dialog(this, song); + SongDialog dialog(this, song.caption, song.lyrics, song.vocalLanguage); if (dialog.exec() == QDialog::Accepted) - songModel->updateSong(songModel->index(row, 1), dialog.getSong()); + { + QString caption = dialog.getCaption(); + QString lyrics = dialog.getLyrics(); + QString vocalLanguage = dialog.getVocalLanguage(); + + songModel->setData(songModel->index(row, 1), caption, SongListModel::CaptionRole); + songModel->setData(songModel->index(row, 1), lyrics, SongListModel::LyricsRole); + songModel->setData(songModel->index(row, 1), vocalLanguage, SongListModel::VocalLanguageRole); + } } connect(ui->songListView, &QTableView::doubleClicked, this, &MainWindow::on_songListView_doubleClicked); @@ -682,13 +695,17 @@ bool MainWindow::savePlaylistToJson(const QString &filePath, const QList(song.uniqueId); + songObj["use_cot_caption"] = song.cotCaption; songsArray.append(songObj); } QJsonObject rootObj; rootObj["songs"] = songsArray; - rootObj["version"] = "1.1"; + rootObj["version"] = "1.0"; QJsonDocument doc(rootObj); QByteArray jsonData = doc.toJson(); @@ -737,7 +754,8 @@ bool MainWindow::loadPlaylistFromJson(const QString &filePath, QList & QJsonObject rootObj = doc.object(); - if (rootObj.contains("version") && rootObj["version"].toString() != "1.0" && rootObj["version"].toString() != "1.1") + // Check for version compatibility + if (rootObj.contains("version") && rootObj["version"].toString() != "1.0") { qWarning() << "Unsupported playlist version:" << rootObj["version"].toString(); return false; @@ -759,7 +777,24 @@ bool MainWindow::loadPlaylistFromJson(const QString &filePath, QList & continue; QJsonObject songObj = value.toObject(); - SongItem song(songObj); + SongItem song; + + if (songObj.contains("caption")) + song.caption = songObj["caption"].toString(); + + if (songObj.contains("lyrics")) + song.lyrics = songObj["lyrics"].toString(); + + if (songObj.contains("vocalLanguage")) + song.vocalLanguage = songObj["vocalLanguage"].toString(); + + if (songObj.contains("uniqueId")) + song.uniqueId = static_cast(songObj["uniqueId"].toInteger()); + else + song.uniqueId = QRandomGenerator::global()->generate64(); + + song.cotCaption = songObj["use_cot_caption"].toBool(true); + songs.append(song); } diff --git a/src/SongDialog.cpp b/src/SongDialog.cpp index 58f4ec6..6f5db6b 100644 --- a/src/SongDialog.cpp +++ b/src/SongDialog.cpp @@ -5,19 +5,19 @@ #include "ui_SongDialog.h" #include -SongDialog::SongDialog(QWidget *parent, const SongItem &song) +SongDialog::SongDialog(QWidget *parent, const QString &caption, const QString &lyrics, const QString &vocalLanguage, bool cotEnabled) : QDialog(parent), - song(song), - ui(new Ui::SongDialog) + ui(new Ui::SongDialog) { ui->setupUi(this); - ui->captionEdit->setPlainText(song.caption); - ui->lyricsEdit->setPlainText(song.lyrics); - ui->checkBoxEnhanceCaption->setChecked(song.cotCaption); + ui->captionEdit->setPlainText(caption); + ui->lyricsEdit->setPlainText(lyrics); + + ui->checkBoxEnhanceCaption->setChecked(cotEnabled); // Setup vocal language combo box - ui->vocalLanguageCombo->addItem("--", ""); + ui->vocalLanguageCombo->addItem("--", ""); // Unset ui->vocalLanguageCombo->addItem("English (en)", "en"); ui->vocalLanguageCombo->addItem("Chinese (zh)", "zh"); ui->vocalLanguageCombo->addItem("Japanese (ja)", "ja"); @@ -70,69 +70,19 @@ SongDialog::SongDialog(QWidget *parent, const SongItem &song) ui->vocalLanguageCombo->addItem("Cantonese (yue)", "yue"); ui->vocalLanguageCombo->addItem("Unknown", "unknown"); - ui->keyScaleCombo->addItem("--"); - ui->keyScaleCombo->addItem("C major"); - ui->keyScaleCombo->addItem("C# major"); - ui->keyScaleCombo->addItem("D major"); - ui->keyScaleCombo->addItem("D# major"); - ui->keyScaleCombo->addItem("E major"); - ui->keyScaleCombo->addItem("F major"); - ui->keyScaleCombo->addItem("F# major"); - ui->keyScaleCombo->addItem("G major"); - ui->keyScaleCombo->addItem("G# major"); - ui->keyScaleCombo->addItem("A major"); - ui->keyScaleCombo->addItem("A# major"); - ui->keyScaleCombo->addItem("B major"); - ui->keyScaleCombo->addItem("C minor"); - ui->keyScaleCombo->addItem("C# minor"); - ui->keyScaleCombo->addItem("D minor"); - ui->keyScaleCombo->addItem("D# minor"); - ui->keyScaleCombo->addItem("E minor"); - ui->keyScaleCombo->addItem("F minor"); - ui->keyScaleCombo->addItem("F# minor"); - ui->keyScaleCombo->addItem("G minor"); - ui->keyScaleCombo->addItem("G# minor"); - ui->keyScaleCombo->addItem("A minor"); - ui->keyScaleCombo->addItem("A# minor"); - ui->keyScaleCombo->addItem("B minor"); - - if (!song.vocalLanguage.isEmpty()) + // Set current language if provided + if (!vocalLanguage.isEmpty()) { - int index = ui->vocalLanguageCombo->findData(song.vocalLanguage); + int index = ui->vocalLanguageCombo->findData(vocalLanguage); if (index >= 0) { ui->vocalLanguageCombo->setCurrentIndex(index); } - else - { - ui->vocalLanguageCombo->addItem(song.vocalLanguage); - ui->vocalLanguageCombo->setCurrentIndex(ui->vocalLanguageCombo->count()-1); - } } else { - ui->vocalLanguageCombo->setCurrentIndex(0); + ui->vocalLanguageCombo->setCurrentIndex(0); // Default to unset } - - if (!song.key.isEmpty()) - { - int index = ui->keyScaleCombo->findText(song.key); - if (index >= 0) - { - ui->keyScaleCombo->setCurrentIndex(index); - } - else - { - ui->keyScaleCombo->addItem(song.key); - ui->keyScaleCombo->setCurrentIndex(ui->keyScaleCombo->count()-1); - } - } - else - { - ui->keyScaleCombo->setCurrentIndex(0); - } - - ui->bpmSpinBox->setValue(song.bpm); } SongDialog::~SongDialog() @@ -140,10 +90,30 @@ SongDialog::~SongDialog() delete ui; } +QString SongDialog::getCaption() const +{ + return ui->captionEdit->toPlainText(); +} + +QString SongDialog::getLyrics() const +{ + return ui->lyricsEdit->toPlainText(); +} + +QString SongDialog::getVocalLanguage() const +{ + return ui->vocalLanguageCombo->currentData().toString(); +} + +bool SongDialog::getCotEnabled() const +{ + return ui->checkBoxEnhanceCaption->isChecked(); +} + void SongDialog::on_okButton_clicked() { // Validate that caption is not empty - QString caption = ui->captionEdit->toPlainText(); + QString caption = getCaption(); if (caption.trimmed().isEmpty()) { QMessageBox::warning(this, "Invalid Input", "Caption cannot be empty."); @@ -156,19 +126,4 @@ void SongDialog::on_okButton_clicked() void SongDialog::on_cancelButton_clicked() { reject(); -} - -const SongItem& SongDialog::getSong() -{ - song.caption = ui->captionEdit->toPlainText(); - song.lyrics = ui->lyricsEdit->toPlainText(); - song.vocalLanguage = ui->vocalLanguageCombo->currentData().toString(); - song.cotCaption = ui->checkBoxEnhanceCaption->isChecked(); - if(ui->keyScaleCombo->currentIndex() > 0) - song.key = ui->keyScaleCombo->currentText(); - else - song.key = ""; - song.bpm = ui->bpmSpinBox->value(); - return song; -} - +} \ No newline at end of file diff --git a/src/SongDialog.h b/src/SongDialog.h index 1ab08de..7230814 100644 --- a/src/SongDialog.h +++ b/src/SongDialog.h @@ -9,8 +9,6 @@ #include #include -#include "SongItem.h" - namespace Ui { class SongDialog; @@ -19,13 +17,16 @@ class SongDialog; class SongDialog : public QDialog { Q_OBJECT - SongItem song; public: - explicit SongDialog(QWidget *parent = nullptr, const SongItem& song = SongItem()); + explicit SongDialog(QWidget *parent = nullptr, const QString &caption = "", const QString &lyrics = "", + const QString &vocalLanguage = "", bool cotEnabled = true); ~SongDialog(); - const SongItem& getSong(); + QString getCaption() const; + QString getLyrics() const; + QString getVocalLanguage() const; + bool getCotEnabled() const; private slots: void on_okButton_clicked(); diff --git a/src/SongDialog.ui b/src/SongDialog.ui index 56e0842..8c0710a 100644 --- a/src/SongDialog.ui +++ b/src/SongDialog.ui @@ -58,66 +58,21 @@ - - - 5 + + + Vocal Language: - - - - Keyscale - - - - - - - true - - - - - - - Vocal Language: - - - Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter - - - - - - - true - - - - - - - Bpm (0 for llm chooses) - - - - - - - 9999 - - - - + + Qt::AlignmentFlag::AlignTop + + - - - 5 + + + true - - 0 - - + diff --git a/src/SongItem.cpp b/src/SongItem.cpp deleted file mode 100644 index 68eef23..0000000 --- a/src/SongItem.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "SongItem.h" - -SongItem::SongItem(const QString &caption, const QString &lyrics) - : caption(caption), lyrics(lyrics), cotCaption(true) -{ - uniqueId = QRandomGenerator::global()->generate64(); -} - -SongItem::SongItem(const QJsonObject& json) -{ - load(json); -} - -void SongItem::store(QJsonObject &json) const -{ - if(!caption.isEmpty()) - json["caption"] = caption; - if(!lyrics.isEmpty()) - json["lyrics"] = lyrics; - json["unique_id"] = QString::number(uniqueId); - json["use_cot_caption"] = cotCaption; - if(!vocalLanguage.isEmpty()) - json["vocal_language"] = vocalLanguage; - if(!key.isEmpty()) - json["keyscale"] = key; - if(bpm != 0) - json["bpm"] = static_cast(bpm); -} - -void SongItem::load(const QJsonObject &json) -{ - caption = json["caption"].toString(); - lyrics = json["lyrics"].toString(); - if(json.contains("unique_id")) - uniqueId = json["unique_id"].toString().toULongLong(); - else - uniqueId = QRandomGenerator::global()->generate64(); - cotCaption = json["use_cot_caption"].toBool(true); - vocalLanguage = json["vocal_language"].toString(); - key = json["keyscale"].toString(); - bpm = json["bpm"].toInt(0); -} - diff --git a/src/SongItem.h b/src/SongItem.h index a8e993c..7084e0f 100644 --- a/src/SongItem.h +++ b/src/SongItem.h @@ -7,25 +7,22 @@ #include #include #include -#include class SongItem { public: QString caption; QString lyrics; - unsigned int bpm; - QString key; - QString vocalLanguage; - bool cotCaption; - uint64_t uniqueId; QString file; + QString vocalLanguage; + bool cotCaption; QString json; - SongItem(const QString &caption = "", const QString &lyrics = ""); - SongItem(const QJsonObject& json); - - void store(QJsonObject& json) const; - void load(const QJsonObject& json); + inline SongItem(const QString &caption = "", const QString &lyrics = "") + : caption(caption), lyrics(lyrics), cotCaption(true) + { + // Generate a unique ID using a cryptographically secure random number + uniqueId = QRandomGenerator::global()->generate64(); + } }; diff --git a/src/SongListModel.cpp b/src/SongListModel.cpp index 0b40f05..a77747a 100644 --- a/src/SongListModel.cpp +++ b/src/SongListModel.cpp @@ -111,26 +111,6 @@ bool SongListModel::setData(const QModelIndex &index, const QVariant &value, int return true; } -void SongListModel::updateSong(const QModelIndex &index, const SongItem& song) -{ - const SongItem &oldSong = songList[index.row()]; - - if(song.caption != oldSong.caption) - { - emit dataChanged(index, index, {CaptionRole}); - } - if(song.lyrics != oldSong.lyrics) - { - emit dataChanged(index, index, {LyricsRole}); - } - if(song.vocalLanguage != oldSong.vocalLanguage) - { - emit dataChanged(index, index, {VocalLanguageRole}); - } - - songList[index.row()] = song; -} - Qt::ItemFlags SongListModel::flags(const QModelIndex &index) const { if (!index.isValid()) diff --git a/src/SongListModel.h b/src/SongListModel.h index bf1e22e..c13ff4c 100644 --- a/src/SongListModel.h +++ b/src/SongListModel.h @@ -37,7 +37,6 @@ public: // Editable: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - void updateSong(const QModelIndex &index, const SongItem& song); Qt::ItemFlags flags(const QModelIndex& index) const override; // Add/remove songs