Files
create/src/Gui/OriginManagerDialog.cpp
forbes 87a0af0b0f phase 1: copy Kindred-only files onto upstream/main (FreeCAD 1.2.0-dev)
Wholesale copy of all Kindred Create additions that don't conflict with
upstream FreeCAD code:

- kindred-icons/ (1444 Catppuccin Mocha SVG icon overrides)
- src/Mod/Create/ (Kindred Create workbench)
- src/Gui/ Kindred source files (FileOrigin, OriginManager,
  OriginSelectorWidget, CommandOrigin, BreadcrumbToolBar, EditingContext)
- src/Gui/Icons/ (Kindred branding and silo icons)
- src/Gui/PreferencePacks/KindredCreate/
- src/Gui/Stylesheets/ (KindredCreate.qss, images_dark-light/)
- package/ (rattler-build recipe)
- docs/ (architecture, guides, specifications)
- .gitea/ (CI workflows, issue templates)
- mods/silo, mods/ztools submodules
- .gitmodules (Kindred submodule URLs)
- resources/ (kindred-create.desktop, kindred-create.xml)
- banner-logo-light.png, CONTRIBUTING.md
2026-02-13 14:03:58 -06:00

248 lines
8.3 KiB
C++

/***************************************************************************
* Copyright (c) 2025 Kindred Systems *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QMessageBox>
#include "OriginManagerDialog.h"
#include "OriginManager.h"
#include "FileOrigin.h"
#include "BitmapFactory.h"
#include "Application.h"
#include "Command.h"
namespace Gui {
OriginManagerDialog::OriginManagerDialog(QWidget* parent)
: QDialog(parent)
{
setupUi();
populateOriginList();
updateButtonStates();
}
OriginManagerDialog::~OriginManagerDialog() = default;
void OriginManagerDialog::setupUi()
{
setWindowTitle(tr("Manage File Origins"));
setMinimumSize(450, 350);
auto* mainLayout = new QVBoxLayout(this);
// Description
auto* descLabel = new QLabel(tr("Configure file origins for storing and retrieving documents."));
descLabel->setWordWrap(true);
mainLayout->addWidget(descLabel);
// Origin list
m_originList = new QListWidget(this);
m_originList->setIconSize(QSize(24, 24));
m_originList->setSelectionMode(QAbstractItemView::SingleSelection);
connect(m_originList, &QListWidget::itemSelectionChanged,
this, &OriginManagerDialog::onOriginSelectionChanged);
connect(m_originList, &QListWidget::itemDoubleClicked,
this, &OriginManagerDialog::onOriginDoubleClicked);
mainLayout->addWidget(m_originList);
// Action buttons
auto* actionLayout = new QHBoxLayout();
m_addButton = new QPushButton(tr("Add Silo..."));
m_addButton->setIcon(BitmapFactory().iconFromTheme("list-add"));
connect(m_addButton, &QPushButton::clicked, this, &OriginManagerDialog::onAddSilo);
actionLayout->addWidget(m_addButton);
m_editButton = new QPushButton(tr("Edit..."));
m_editButton->setIcon(BitmapFactory().iconFromTheme("document-edit"));
connect(m_editButton, &QPushButton::clicked, this, &OriginManagerDialog::onEditOrigin);
actionLayout->addWidget(m_editButton);
m_removeButton = new QPushButton(tr("Remove"));
m_removeButton->setIcon(BitmapFactory().iconFromTheme("list-remove"));
connect(m_removeButton, &QPushButton::clicked, this, &OriginManagerDialog::onRemoveOrigin);
actionLayout->addWidget(m_removeButton);
actionLayout->addStretch();
m_defaultButton = new QPushButton(tr("Set as Default"));
connect(m_defaultButton, &QPushButton::clicked, this, &OriginManagerDialog::onSetDefault);
actionLayout->addWidget(m_defaultButton);
mainLayout->addLayout(actionLayout);
// Dialog buttons
m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
mainLayout->addWidget(m_buttonBox);
}
void OriginManagerDialog::populateOriginList()
{
m_originList->clear();
auto* mgr = OriginManager::instance();
std::string currentId = mgr->currentOriginId();
for (const std::string& originId : mgr->originIds()) {
FileOrigin* origin = mgr->getOrigin(originId);
if (!origin) {
continue;
}
auto* item = new QListWidgetItem(m_originList);
item->setIcon(origin->icon());
QString displayText = QString::fromStdString(origin->name());
// Add connection status for remote origins
if (origin->requiresAuthentication()) {
ConnectionState state = origin->connectionState();
switch (state) {
case ConnectionState::Connected:
displayText += tr(" [Connected]");
break;
case ConnectionState::Connecting:
displayText += tr(" [Connecting...]");
break;
case ConnectionState::Disconnected:
displayText += tr(" [Disconnected]");
break;
case ConnectionState::Error:
displayText += tr(" [Error]");
break;
}
}
// Mark default origin
if (originId == currentId) {
displayText += tr(" (Default)");
QFont font = item->font();
font.setBold(true);
item->setFont(font);
}
item->setText(displayText);
item->setData(Qt::UserRole, QString::fromStdString(originId));
item->setToolTip(QString::fromStdString(origin->name()));
}
}
void OriginManagerDialog::updateButtonStates()
{
FileOrigin* origin = selectedOrigin();
bool hasSelection = (origin != nullptr);
bool isLocal = hasSelection && (origin->id() == "local");
bool isDefault = hasSelection && (origin->id() == OriginManager::instance()->currentOriginId());
// Can't edit or remove local origin
m_editButton->setEnabled(hasSelection && !isLocal);
m_removeButton->setEnabled(hasSelection && !isLocal);
m_defaultButton->setEnabled(hasSelection && !isDefault);
}
FileOrigin* OriginManagerDialog::selectedOrigin() const
{
QListWidgetItem* item = m_originList->currentItem();
if (!item) {
return nullptr;
}
std::string originId = item->data(Qt::UserRole).toString().toStdString();
return OriginManager::instance()->getOrigin(originId);
}
void OriginManagerDialog::onAddSilo()
{
Application::Instance->commandManager().runCommandByName("Silo_Settings");
}
void OriginManagerDialog::onEditOrigin()
{
FileOrigin* origin = selectedOrigin();
if (!origin || origin->id() == "local") {
return;
}
Application::Instance->commandManager().runCommandByName("Silo_Settings");
}
void OriginManagerDialog::onRemoveOrigin()
{
FileOrigin* origin = selectedOrigin();
if (!origin || origin->id() == "local") {
return;
}
QString name = QString::fromStdString(origin->name());
QMessageBox::StandardButton reply = QMessageBox::question(this,
tr("Remove Origin"),
tr("Are you sure you want to remove '%1'?\n\n"
"This will not delete any files, but you will need to reconfigure "
"the connection to use this origin again.").arg(name),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No);
if (reply == QMessageBox::Yes) {
std::string originId = origin->id();
OriginManager::instance()->unregisterOrigin(originId);
populateOriginList();
updateButtonStates();
}
}
void OriginManagerDialog::onSetDefault()
{
FileOrigin* origin = selectedOrigin();
if (!origin) {
return;
}
OriginManager::instance()->setCurrentOrigin(origin->id());
populateOriginList();
updateButtonStates();
}
void OriginManagerDialog::onOriginSelectionChanged()
{
updateButtonStates();
}
void OriginManagerDialog::onOriginDoubleClicked(QListWidgetItem* item)
{
if (!item) {
return;
}
std::string originId = item->data(Qt::UserRole).toString().toStdString();
if (originId != "local") {
onEditOrigin();
}
}
} // namespace Gui