Implement Milestone 2 profile schema, dialog, and connect lifecycle
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "profiles_window.h"
|
||||
|
||||
#include "profile_dialog.h"
|
||||
#include "profile_repository.h"
|
||||
#include "session_window.h"
|
||||
|
||||
@@ -7,7 +8,6 @@
|
||||
|
||||
#include <QAbstractItemView>
|
||||
#include <QHBoxLayout>
|
||||
#include <QInputDialog>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidget>
|
||||
@@ -18,6 +18,14 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
namespace {
|
||||
QString formatProfileListItem(const Profile& profile)
|
||||
{
|
||||
return QStringLiteral("%1 [%2 %3:%4]")
|
||||
.arg(profile.name, profile.protocol, profile.host, QString::number(profile.port));
|
||||
}
|
||||
}
|
||||
|
||||
ProfilesWindow::ProfilesWindow(QWidget* parent)
|
||||
: QMainWindow(parent),
|
||||
m_searchBox(nullptr),
|
||||
@@ -28,7 +36,7 @@ ProfilesWindow::ProfilesWindow(QWidget* parent)
|
||||
m_repository(std::make_unique<ProfileRepository>())
|
||||
{
|
||||
setWindowTitle(QStringLiteral("OrbitHub Profiles"));
|
||||
resize(520, 620);
|
||||
resize(640, 620);
|
||||
|
||||
setupUi();
|
||||
|
||||
@@ -57,7 +65,7 @@ void ProfilesWindow::setupUi()
|
||||
|
||||
auto* searchLabel = new QLabel(QStringLiteral("Search"), central);
|
||||
m_searchBox = new QLineEdit(central);
|
||||
m_searchBox->setPlaceholderText(QStringLiteral("Filter profiles..."));
|
||||
m_searchBox->setPlaceholderText(QStringLiteral("Filter by name or host..."));
|
||||
|
||||
m_profilesList = new QListWidget(central);
|
||||
m_profilesList->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
@@ -97,15 +105,31 @@ void ProfilesWindow::setupUi()
|
||||
void ProfilesWindow::loadProfiles(const QString& query)
|
||||
{
|
||||
m_profilesList->clear();
|
||||
m_profileCache.clear();
|
||||
|
||||
const std::vector<Profile> profiles = m_repository->listProfiles(query);
|
||||
if (!m_repository->lastError().isEmpty()) {
|
||||
QMessageBox::warning(this,
|
||||
QStringLiteral("Load Profiles"),
|
||||
QStringLiteral("Failed to load profiles: %1")
|
||||
.arg(m_repository->lastError()));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const Profile& profile : profiles) {
|
||||
auto* item = new QListWidgetItem(profile.name, m_profilesList);
|
||||
auto* item = new QListWidgetItem(formatProfileListItem(profile), m_profilesList);
|
||||
item->setData(Qt::UserRole, QVariant::fromValue(profile.id));
|
||||
item->setToolTip(QStringLiteral("%1://%2@%3:%4\nAuth: %5")
|
||||
.arg(profile.protocol,
|
||||
profile.username.isEmpty() ? QStringLiteral("<none>") : profile.username,
|
||||
profile.host,
|
||||
QString::number(profile.port),
|
||||
profile.authMode));
|
||||
m_profileCache.insert_or_assign(profile.id, profile);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<qint64> ProfilesWindow::selectedProfileId() const
|
||||
std::optional<Profile> ProfilesWindow::selectedProfile() const
|
||||
{
|
||||
QListWidgetItem* item = m_profilesList->currentItem();
|
||||
if (item == nullptr) {
|
||||
@@ -117,27 +141,31 @@ std::optional<qint64> ProfilesWindow::selectedProfileId() const
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return value.toLongLong();
|
||||
const qint64 id = value.toLongLong();
|
||||
const auto cacheIt = m_profileCache.find(id);
|
||||
if (cacheIt != m_profileCache.end()) {
|
||||
return cacheIt->second;
|
||||
}
|
||||
|
||||
return m_repository->getProfile(id);
|
||||
}
|
||||
|
||||
void ProfilesWindow::createProfile()
|
||||
{
|
||||
bool accepted = false;
|
||||
const QString name = QInputDialog::getText(this,
|
||||
QStringLiteral("New Profile"),
|
||||
QStringLiteral("Profile name:"),
|
||||
QLineEdit::Normal,
|
||||
QString(),
|
||||
&accepted);
|
||||
ProfileDialog dialog(this);
|
||||
dialog.setDialogTitle(QStringLiteral("New Profile"));
|
||||
|
||||
if (!accepted || name.trimmed().isEmpty()) {
|
||||
if (dialog.exec() != QDialog::Accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_repository->createProfile(name).has_value()) {
|
||||
if (!m_repository->createProfile(dialog.profile()).has_value()) {
|
||||
QMessageBox::warning(this,
|
||||
QStringLiteral("Create Profile"),
|
||||
QStringLiteral("Failed to create profile. Names must be unique."));
|
||||
QStringLiteral("Failed to create profile: %1")
|
||||
.arg(m_repository->lastError().isEmpty()
|
||||
? QStringLiteral("unknown error")
|
||||
: m_repository->lastError()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -146,31 +174,32 @@ void ProfilesWindow::createProfile()
|
||||
|
||||
void ProfilesWindow::editSelectedProfile()
|
||||
{
|
||||
const std::optional<qint64> profileId = selectedProfileId();
|
||||
QListWidgetItem* currentItem = m_profilesList->currentItem();
|
||||
if (!profileId.has_value() || currentItem == nullptr) {
|
||||
const std::optional<Profile> selected = selectedProfile();
|
||||
if (!selected.has_value()) {
|
||||
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);
|
||||
ProfileDialog dialog(this);
|
||||
dialog.setDialogTitle(QStringLiteral("Edit Profile"));
|
||||
dialog.setProfile(selected.value());
|
||||
|
||||
if (!accepted || name.trimmed().isEmpty()) {
|
||||
if (dialog.exec() != QDialog::Accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_repository->updateProfile(profileId.value(), name)) {
|
||||
Profile updated = dialog.profile();
|
||||
updated.id = selected->id;
|
||||
|
||||
if (!m_repository->updateProfile(updated)) {
|
||||
QMessageBox::warning(this,
|
||||
QStringLiteral("Edit Profile"),
|
||||
QStringLiteral("Failed to update profile. Names must be unique."));
|
||||
QStringLiteral("Failed to update profile: %1")
|
||||
.arg(m_repository->lastError().isEmpty()
|
||||
? QStringLiteral("unknown error")
|
||||
: m_repository->lastError()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -179,9 +208,8 @@ void ProfilesWindow::editSelectedProfile()
|
||||
|
||||
void ProfilesWindow::deleteSelectedProfile()
|
||||
{
|
||||
const std::optional<qint64> profileId = selectedProfileId();
|
||||
QListWidgetItem* currentItem = m_profilesList->currentItem();
|
||||
if (!profileId.has_value() || currentItem == nullptr) {
|
||||
const std::optional<Profile> selected = selectedProfile();
|
||||
if (!selected.has_value()) {
|
||||
QMessageBox::information(this,
|
||||
QStringLiteral("Delete Profile"),
|
||||
QStringLiteral("Select a profile first."));
|
||||
@@ -191,7 +219,7 @@ void ProfilesWindow::deleteSelectedProfile()
|
||||
const QMessageBox::StandardButton confirm = QMessageBox::question(
|
||||
this,
|
||||
QStringLiteral("Delete Profile"),
|
||||
QStringLiteral("Delete profile '%1'?").arg(currentItem->text()),
|
||||
QStringLiteral("Delete profile '%1'?").arg(selected->name),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::No);
|
||||
|
||||
@@ -199,10 +227,13 @@ void ProfilesWindow::deleteSelectedProfile()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_repository->deleteProfile(profileId.value())) {
|
||||
if (!m_repository->deleteProfile(selected->id)) {
|
||||
QMessageBox::warning(this,
|
||||
QStringLiteral("Delete Profile"),
|
||||
QStringLiteral("Failed to delete profile."));
|
||||
QStringLiteral("Failed to delete profile: %1")
|
||||
.arg(m_repository->lastError().isEmpty()
|
||||
? QStringLiteral("unknown error")
|
||||
: m_repository->lastError()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -215,7 +246,24 @@ void ProfilesWindow::openSessionForItem(QListWidgetItem* item)
|
||||
return;
|
||||
}
|
||||
|
||||
auto* session = new SessionWindow(item->text());
|
||||
const QVariant value = item->data(Qt::UserRole);
|
||||
if (!value.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const qint64 id = value.toLongLong();
|
||||
const std::optional<Profile> profile = m_repository->getProfile(id);
|
||||
if (!profile.has_value()) {
|
||||
QMessageBox::warning(this,
|
||||
QStringLiteral("Connect"),
|
||||
QStringLiteral("Failed to load profile for session: %1")
|
||||
.arg(m_repository->lastError().isEmpty()
|
||||
? QStringLiteral("profile not found")
|
||||
: m_repository->lastError()));
|
||||
return;
|
||||
}
|
||||
|
||||
auto* session = new SessionWindow(profile.value());
|
||||
session->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
m_sessionWindows.emplace_back(session);
|
||||
|
||||
Reference in New Issue
Block a user