diff --git a/src/profiles_window.cpp b/src/profiles_window.cpp index bbcea37..b00a8f2 100644 --- a/src/profiles_window.cpp +++ b/src/profiles_window.cpp @@ -1,18 +1,20 @@ #include "profiles_window.h" +#include "profile_repository.h" #include "session_window.h" #include #include #include +#include #include #include #include #include #include #include -#include +#include #include #include @@ -22,15 +24,32 @@ ProfilesWindow::ProfilesWindow(QWidget* parent) m_profilesList(nullptr), m_newButton(nullptr), m_editButton(nullptr), - m_deleteButton(nullptr) + m_deleteButton(nullptr), + m_repository(std::make_unique()) { setWindowTitle(QStringLiteral("OrbitHub Profiles")); resize(520, 620); setupUi(); - populateSampleProfiles(); + + if (!m_repository->initError().isEmpty()) { + QMessageBox::critical(this, + QStringLiteral("Database Error"), + QStringLiteral("Failed to initialize SQLite database: %1") + .arg(m_repository->initError())); + m_newButton->setEnabled(false); + m_editButton->setEnabled(false); + m_deleteButton->setEnabled(false); + m_searchBox->setEnabled(false); + m_profilesList->setEnabled(false); + return; + } + + loadProfiles(); } +ProfilesWindow::~ProfilesWindow() = default; + void ProfilesWindow::setupUi() { auto* central = new QWidget(this); @@ -63,51 +82,133 @@ void ProfilesWindow::setupUi() connect(m_searchBox, &QLineEdit::textChanged, this, - [this](const QString& text) { filterProfiles(text); }); + [this](const QString& text) { loadProfiles(text); }); connect(m_profilesList, &QListWidget::itemDoubleClicked, this, [this](QListWidgetItem* item) { openSessionForItem(item); }); - // Milestone 0 keeps profile management as placeholders. - auto showTodo = [this](const QString& action) { - QMessageBox::information(this, - QStringLiteral("Milestone 0"), - QStringLiteral("%1 is planned for Milestone 1.").arg(action)); - }; - - connect(m_newButton, &QPushButton::clicked, this, [showTodo]() { showTodo(QStringLiteral("New Profile")); }); - connect(m_editButton, &QPushButton::clicked, this, [showTodo]() { showTodo(QStringLiteral("Edit Profile")); }); - connect(m_deleteButton, - &QPushButton::clicked, - this, - [showTodo]() { showTodo(QStringLiteral("Delete Profile")); }); + connect(m_newButton, &QPushButton::clicked, this, [this]() { createProfile(); }); + connect(m_editButton, &QPushButton::clicked, this, [this]() { editSelectedProfile(); }); + connect(m_deleteButton, &QPushButton::clicked, this, [this]() { deleteSelectedProfile(); }); } -void ProfilesWindow::populateSampleProfiles() +void ProfilesWindow::loadProfiles(const QString& query) { - const QStringList sampleProfiles = { - QStringLiteral("Production Bastion"), - QStringLiteral("Staging API Host"), - QStringLiteral("Local Lab VM"), - QStringLiteral("CI Build Agent")}; + m_profilesList->clear(); - m_profilesList->addItems(sampleProfiles); -} - -void ProfilesWindow::filterProfiles(const QString& query) -{ - const QString trimmed = query.trimmed(); - - for (int i = 0; i < m_profilesList->count(); ++i) { - QListWidgetItem* item = m_profilesList->item(i); - const bool matches = trimmed.isEmpty() - || item->text().contains(trimmed, Qt::CaseInsensitive); - item->setHidden(!matches); + const std::vector profiles = m_repository->listProfiles(query); + for (const Profile& profile : profiles) { + auto* item = new QListWidgetItem(profile.name, m_profilesList); + item->setData(Qt::UserRole, QVariant::fromValue(profile.id)); } } +std::optional ProfilesWindow::selectedProfileId() const +{ + QListWidgetItem* item = m_profilesList->currentItem(); + if (item == nullptr) { + return std::nullopt; + } + + const QVariant value = item->data(Qt::UserRole); + if (!value.isValid()) { + return std::nullopt; + } + + return value.toLongLong(); +} + +void ProfilesWindow::createProfile() +{ + bool accepted = false; + const QString name = QInputDialog::getText(this, + QStringLiteral("New Profile"), + QStringLiteral("Profile name:"), + QLineEdit::Normal, + QString(), + &accepted); + + if (!accepted || name.trimmed().isEmpty()) { + return; + } + + if (!m_repository->createProfile(name).has_value()) { + QMessageBox::warning(this, + QStringLiteral("Create Profile"), + QStringLiteral("Failed to create profile. Names must be unique.")); + return; + } + + loadProfiles(m_searchBox->text()); +} + +void ProfilesWindow::editSelectedProfile() +{ + const std::optional profileId = selectedProfileId(); + QListWidgetItem* currentItem = m_profilesList->currentItem(); + if (!profileId.has_value() || currentItem == nullptr) { + QMessageBox::information(this, + QStringLiteral("Edit Profile"), + QStringLiteral("Select a profile first.")); + return; + } + + bool accepted = false; + const QString name = QInputDialog::getText(this, + QStringLiteral("Edit Profile"), + QStringLiteral("Profile name:"), + QLineEdit::Normal, + currentItem->text(), + &accepted); + + if (!accepted || name.trimmed().isEmpty()) { + return; + } + + if (!m_repository->updateProfile(profileId.value(), name)) { + QMessageBox::warning(this, + QStringLiteral("Edit Profile"), + QStringLiteral("Failed to update profile. Names must be unique.")); + return; + } + + loadProfiles(m_searchBox->text()); +} + +void ProfilesWindow::deleteSelectedProfile() +{ + const std::optional profileId = selectedProfileId(); + QListWidgetItem* currentItem = m_profilesList->currentItem(); + if (!profileId.has_value() || currentItem == nullptr) { + QMessageBox::information(this, + QStringLiteral("Delete Profile"), + QStringLiteral("Select a profile first.")); + return; + } + + const QMessageBox::StandardButton confirm = QMessageBox::question( + this, + QStringLiteral("Delete Profile"), + QStringLiteral("Delete profile '%1'?").arg(currentItem->text()), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No); + + if (confirm != QMessageBox::Yes) { + return; + } + + if (!m_repository->deleteProfile(profileId.value())) { + QMessageBox::warning(this, + QStringLiteral("Delete Profile"), + QStringLiteral("Failed to delete profile.")); + return; + } + + loadProfiles(m_searchBox->text()); +} + void ProfilesWindow::openSessionForItem(QListWidgetItem* item) { if (item == nullptr) { diff --git a/src/profiles_window.h b/src/profiles_window.h index 67965de..36c3c46 100644 --- a/src/profiles_window.h +++ b/src/profiles_window.h @@ -3,7 +3,10 @@ #include #include +#include +#include +#include #include #include @@ -12,6 +15,7 @@ class QListWidgetItem; class QLineEdit; class QPushButton; class SessionWindow; +class ProfileRepository; class ProfilesWindow : public QMainWindow { @@ -19,6 +23,7 @@ class ProfilesWindow : public QMainWindow public: explicit ProfilesWindow(QWidget* parent = nullptr); + ~ProfilesWindow() override; private: QLineEdit* m_searchBox; @@ -27,10 +32,14 @@ private: QPushButton* m_editButton; QPushButton* m_deleteButton; std::vector> m_sessionWindows; + std::unique_ptr m_repository; void setupUi(); - void populateSampleProfiles(); - void filterProfiles(const QString& query); + void loadProfiles(const QString& query = QString()); + std::optional selectedProfileId() const; + void createProfile(); + void editSelectedProfile(); + void deleteSelectedProfile(); void openSessionForItem(QListWidgetItem* item); };