Compare commits

..

No commits in common. "4cacaa04e4e43bbdfded1752a1059f9331ebe241" and "9d0dc6298c243cd2a0aa8e640db49015abf0a503" have entirely different histories.

12 changed files with 112 additions and 236 deletions

View file

@ -40,8 +40,6 @@ add_executable(${PROJECT_NAME}
${MusicGeneratorGUI_H} ${MusicGeneratorGUI_H}
res/resources.qrc res/resources.qrc
src/elidedlabel.h src/elidedlabel.cpp src/elidedlabel.h src/elidedlabel.cpp
src/SongItem.cpp
) )
# UI file # UI file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before After
Before After

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

View file

@ -102,7 +102,14 @@ bool AceStep::requestGeneration(SongItem song, QString requestTemplate, QString
} }
QJsonObject requestObj = templateDoc.object(); QJsonObject requestObj = templateDoc.object();
song.store(requestObj); requestObj["caption"] = song.caption;
if (!song.lyrics.isEmpty())
requestObj["lyrics"] = song.lyrics;
if (!song.vocalLanguage.isEmpty())
requestObj["vocal_language"] = song.vocalLanguage;
requestObj["use_cot_caption"] = song.cotCaption;
// Write the request file // Write the request file
QFile requestFileHandle(request.requestFilePath); QFile requestFileHandle(request.requestFilePath);

View file

@ -291,7 +291,12 @@ void MainWindow::on_addSongButton_clicked()
if (dialog.exec() == QDialog::Accepted) if (dialog.exec() == QDialog::Accepted)
{ {
SongItem newSong = dialog.getSong(); QString caption = dialog.getCaption();
QString lyrics = dialog.getLyrics();
QString vocalLanguage = dialog.getVocalLanguage();
SongItem newSong(caption, lyrics);
newSong.vocalLanguage = vocalLanguage;
songModel->addSong(newSong); songModel->addSong(newSong);
// Select the new item // Select the new item
@ -330,10 +335,18 @@ void MainWindow::on_songListView_doubleClicked(const QModelIndex &index)
{ {
SongItem song = songModel->getSong(row); SongItem song = songModel->getSong(row);
SongDialog dialog(this, song); SongDialog dialog(this, song.caption, song.lyrics, song.vocalLanguage);
if (dialog.exec() == QDialog::Accepted) 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); connect(ui->songListView, &QTableView::doubleClicked, this, &MainWindow::on_songListView_doubleClicked);
@ -682,13 +695,17 @@ bool MainWindow::savePlaylistToJson(const QString &filePath, const QList<SongIte
for (const SongItem &song : songs) for (const SongItem &song : songs)
{ {
QJsonObject songObj; QJsonObject songObj;
song.store(songObj); songObj["caption"] = song.caption;
songObj["lyrics"] = song.lyrics;
songObj["vocalLanguage"] = song.vocalLanguage;
songObj["uniqueId"] = static_cast<qint64>(song.uniqueId);
songObj["use_cot_caption"] = song.cotCaption;
songsArray.append(songObj); songsArray.append(songObj);
} }
QJsonObject rootObj; QJsonObject rootObj;
rootObj["songs"] = songsArray; rootObj["songs"] = songsArray;
rootObj["version"] = "1.1"; rootObj["version"] = "1.0";
QJsonDocument doc(rootObj); QJsonDocument doc(rootObj);
QByteArray jsonData = doc.toJson(); QByteArray jsonData = doc.toJson();
@ -737,7 +754,8 @@ bool MainWindow::loadPlaylistFromJson(const QString &filePath, QList<SongItem> &
QJsonObject rootObj = doc.object(); 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(); qWarning() << "Unsupported playlist version:" << rootObj["version"].toString();
return false; return false;
@ -759,7 +777,24 @@ bool MainWindow::loadPlaylistFromJson(const QString &filePath, QList<SongItem> &
continue; continue;
QJsonObject songObj = value.toObject(); 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<uint64_t>(songObj["uniqueId"].toInteger());
else
song.uniqueId = QRandomGenerator::global()->generate64();
song.cotCaption = songObj["use_cot_caption"].toBool(true);
songs.append(song); songs.append(song);
} }

View file

@ -5,19 +5,19 @@
#include "ui_SongDialog.h" #include "ui_SongDialog.h"
#include <QMessageBox> #include <QMessageBox>
SongDialog::SongDialog(QWidget *parent, const SongItem &song) SongDialog::SongDialog(QWidget *parent, const QString &caption, const QString &lyrics, const QString &vocalLanguage, bool cotEnabled)
: QDialog(parent), : QDialog(parent),
song(song), ui(new Ui::SongDialog)
ui(new Ui::SongDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->captionEdit->setPlainText(song.caption); ui->captionEdit->setPlainText(caption);
ui->lyricsEdit->setPlainText(song.lyrics); ui->lyricsEdit->setPlainText(lyrics);
ui->checkBoxEnhanceCaption->setChecked(song.cotCaption);
ui->checkBoxEnhanceCaption->setChecked(cotEnabled);
// Setup vocal language combo box // Setup vocal language combo box
ui->vocalLanguageCombo->addItem("--", ""); ui->vocalLanguageCombo->addItem("--", ""); // Unset
ui->vocalLanguageCombo->addItem("English (en)", "en"); ui->vocalLanguageCombo->addItem("English (en)", "en");
ui->vocalLanguageCombo->addItem("Chinese (zh)", "zh"); ui->vocalLanguageCombo->addItem("Chinese (zh)", "zh");
ui->vocalLanguageCombo->addItem("Japanese (ja)", "ja"); 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("Cantonese (yue)", "yue");
ui->vocalLanguageCombo->addItem("Unknown", "unknown"); ui->vocalLanguageCombo->addItem("Unknown", "unknown");
ui->keyScaleCombo->addItem("--"); // Set current language if provided
ui->keyScaleCombo->addItem("C major"); if (!vocalLanguage.isEmpty())
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())
{ {
int index = ui->vocalLanguageCombo->findData(song.vocalLanguage); int index = ui->vocalLanguageCombo->findData(vocalLanguage);
if (index >= 0) if (index >= 0)
{ {
ui->vocalLanguageCombo->setCurrentIndex(index); ui->vocalLanguageCombo->setCurrentIndex(index);
} }
else
{
ui->vocalLanguageCombo->addItem(song.vocalLanguage);
ui->vocalLanguageCombo->setCurrentIndex(ui->vocalLanguageCombo->count()-1);
}
} }
else 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() SongDialog::~SongDialog()
@ -140,10 +90,30 @@ SongDialog::~SongDialog()
delete ui; 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() void SongDialog::on_okButton_clicked()
{ {
// Validate that caption is not empty // Validate that caption is not empty
QString caption = ui->captionEdit->toPlainText(); QString caption = getCaption();
if (caption.trimmed().isEmpty()) if (caption.trimmed().isEmpty())
{ {
QMessageBox::warning(this, "Invalid Input", "Caption cannot be empty."); QMessageBox::warning(this, "Invalid Input", "Caption cannot be empty.");
@ -157,18 +127,3 @@ void SongDialog::on_cancelButton_clicked()
{ {
reject(); 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;
}

View file

@ -9,8 +9,6 @@
#include <QDialog> #include <QDialog>
#include <QString> #include <QString>
#include "SongItem.h"
namespace Ui namespace Ui
{ {
class SongDialog; class SongDialog;
@ -19,13 +17,16 @@ class SongDialog;
class SongDialog : public QDialog class SongDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
SongItem song;
public: 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(); ~SongDialog();
const SongItem& getSong(); QString getCaption() const;
QString getLyrics() const;
QString getVocalLanguage() const;
bool getCotEnabled() const;
private slots: private slots:
void on_okButton_clicked(); void on_okButton_clicked();

View file

@ -58,66 +58,21 @@
<widget class="QPlainTextEdit" name="lyricsEdit"/> <widget class="QPlainTextEdit" name="lyricsEdit"/>
</item> </item>
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <widget class="QLabel" name="vocalLanguageLabel">
<property name="topMargin"> <property name="text">
<number>5</number> <string>Vocal Language:</string>
</property> </property>
<item row="1" column="0"> <property name="alignment">
<widget class="QLabel" name="keyScalelabel"> <set>Qt::AlignmentFlag::AlignTop</set>
<property name="text"> </property>
<string>Keyscale</string> </widget>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="vocalLanguageCombo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="vocalLanguageLabel">
<property name="text">
<string>Vocal Language:</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="keyScaleCombo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Bpm (0 for llm chooses)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="bpmSpinBox">
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch=""> <widget class="QComboBox" name="vocalLanguageCombo">
<property name="spacing"> <property name="editable">
<number>5</number> <bool>true</bool>
</property> </property>
<property name="bottomMargin"> </widget>
<number>0</number>
</property>
</layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="buttonLayout"> <layout class="QHBoxLayout" name="buttonLayout">

View file

@ -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<qlonglong>(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);
}

View file

@ -7,25 +7,22 @@
#include <QString> #include <QString>
#include <QRandomGenerator> #include <QRandomGenerator>
#include <cstdint> #include <cstdint>
#include <QJsonObject>
class SongItem class SongItem
{ {
public: public:
QString caption; QString caption;
QString lyrics; QString lyrics;
unsigned int bpm;
QString key;
QString vocalLanguage;
bool cotCaption;
uint64_t uniqueId; uint64_t uniqueId;
QString file; QString file;
QString vocalLanguage;
bool cotCaption;
QString json; QString json;
SongItem(const QString &caption = "", const QString &lyrics = ""); inline SongItem(const QString &caption = "", const QString &lyrics = "")
SongItem(const QJsonObject& json); : caption(caption), lyrics(lyrics), cotCaption(true)
{
void store(QJsonObject& json) const; // Generate a unique ID using a cryptographically secure random number
void load(const QJsonObject& json); uniqueId = QRandomGenerator::global()->generate64();
}
}; };

View file

@ -111,26 +111,6 @@ bool SongListModel::setData(const QModelIndex &index, const QVariant &value, int
return true; 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 Qt::ItemFlags SongListModel::flags(const QModelIndex &index) const
{ {
if (!index.isValid()) if (!index.isValid())

View file

@ -37,7 +37,6 @@ public:
// Editable: // Editable:
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; 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; Qt::ItemFlags flags(const QModelIndex& index) const override;
// Add/remove songs // Add/remove songs