Some checks failed
Build and Test / build (push) Has been cancelled
- OriginSelectorWidget: use BitmapFactoryInst::mergePixmap() instead of BitmapFactory::mergePixmap() since BitmapFactory is a function, not a class - OriginManager: use Console().log() instead of Console().Log() which does not exist on ConsoleSingleton
271 lines
8.4 KiB
C++
271 lines
8.4 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 <QApplication>
|
|
|
|
#include "OriginSelectorWidget.h"
|
|
#include "OriginManager.h"
|
|
#include "OriginManagerDialog.h"
|
|
#include "FileOrigin.h"
|
|
#include "BitmapFactory.h"
|
|
|
|
|
|
namespace Gui {
|
|
|
|
OriginSelectorWidget::OriginSelectorWidget(QWidget* parent)
|
|
: QToolButton(parent)
|
|
, m_menu(nullptr)
|
|
, m_originActions(nullptr)
|
|
, m_manageAction(nullptr)
|
|
{
|
|
setupUi();
|
|
connectSignals();
|
|
rebuildMenu();
|
|
updateDisplay();
|
|
}
|
|
|
|
OriginSelectorWidget::~OriginSelectorWidget()
|
|
{
|
|
disconnectSignals();
|
|
}
|
|
|
|
void OriginSelectorWidget::setupUi()
|
|
{
|
|
setPopupMode(QToolButton::InstantPopup);
|
|
setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
|
setMinimumWidth(70);
|
|
setMaximumWidth(120);
|
|
|
|
// Create menu
|
|
m_menu = new QMenu(this);
|
|
setMenu(m_menu);
|
|
|
|
// Create action group for exclusive selection
|
|
m_originActions = new QActionGroup(this);
|
|
m_originActions->setExclusive(true);
|
|
|
|
// Connect action group to selection handler
|
|
connect(m_originActions, &QActionGroup::triggered,
|
|
this, &OriginSelectorWidget::onOriginActionTriggered);
|
|
}
|
|
|
|
void OriginSelectorWidget::connectSignals()
|
|
{
|
|
auto* mgr = OriginManager::instance();
|
|
|
|
// Connect to OriginManager fastsignals
|
|
m_connRegistered = mgr->signalOriginRegistered.connect(
|
|
[this](const std::string& id) { onOriginRegistered(id); }
|
|
);
|
|
m_connUnregistered = mgr->signalOriginUnregistered.connect(
|
|
[this](const std::string& id) { onOriginUnregistered(id); }
|
|
);
|
|
m_connChanged = mgr->signalCurrentOriginChanged.connect(
|
|
[this](const std::string& id) { onCurrentOriginChanged(id); }
|
|
);
|
|
}
|
|
|
|
void OriginSelectorWidget::disconnectSignals()
|
|
{
|
|
m_connRegistered.disconnect();
|
|
m_connUnregistered.disconnect();
|
|
m_connChanged.disconnect();
|
|
}
|
|
|
|
void OriginSelectorWidget::onOriginRegistered(const std::string& /*originId*/)
|
|
{
|
|
// Rebuild menu to include new origin
|
|
rebuildMenu();
|
|
}
|
|
|
|
void OriginSelectorWidget::onOriginUnregistered(const std::string& /*originId*/)
|
|
{
|
|
// Rebuild menu to remove origin
|
|
rebuildMenu();
|
|
}
|
|
|
|
void OriginSelectorWidget::onCurrentOriginChanged(const std::string& /*originId*/)
|
|
{
|
|
// Update display and menu checkmarks
|
|
updateDisplay();
|
|
|
|
// Update checked state in menu
|
|
auto* mgr = OriginManager::instance();
|
|
std::string currentId = mgr->currentOriginId();
|
|
|
|
for (QAction* action : m_originActions->actions()) {
|
|
std::string actionId = action->data().toString().toStdString();
|
|
action->setChecked(actionId == currentId);
|
|
}
|
|
}
|
|
|
|
void OriginSelectorWidget::onOriginActionTriggered(QAction* action)
|
|
{
|
|
if (!action) {
|
|
return;
|
|
}
|
|
|
|
std::string originId = action->data().toString().toStdString();
|
|
auto* mgr = OriginManager::instance();
|
|
|
|
// Check if origin requires connection
|
|
FileOrigin* origin = mgr->getOrigin(originId);
|
|
if (origin && origin->requiresAuthentication()) {
|
|
ConnectionState state = origin->connectionState();
|
|
if (state == ConnectionState::Disconnected || state == ConnectionState::Error) {
|
|
// Try to connect
|
|
if (!origin->connect()) {
|
|
// Connection failed - don't switch
|
|
// Revert the checkmark to current origin
|
|
std::string currentId = mgr->currentOriginId();
|
|
for (QAction* a : m_originActions->actions()) {
|
|
a->setChecked(a->data().toString().toStdString() == currentId);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
mgr->setCurrentOrigin(originId);
|
|
}
|
|
|
|
void OriginSelectorWidget::onManageOriginsClicked()
|
|
{
|
|
OriginManagerDialog dialog(this);
|
|
dialog.exec();
|
|
|
|
// Refresh the menu in case origins changed
|
|
rebuildMenu();
|
|
updateDisplay();
|
|
}
|
|
|
|
void OriginSelectorWidget::updateDisplay()
|
|
{
|
|
FileOrigin* origin = OriginManager::instance()->currentOrigin();
|
|
if (!origin) {
|
|
setText(tr("No Origin"));
|
|
setIcon(QIcon());
|
|
setToolTip(QString());
|
|
return;
|
|
}
|
|
|
|
setText(QString::fromStdString(origin->nickname()));
|
|
setIcon(iconForOrigin(origin));
|
|
setToolTip(QString::fromStdString(origin->name()));
|
|
}
|
|
|
|
void OriginSelectorWidget::rebuildMenu()
|
|
{
|
|
m_menu->clear();
|
|
|
|
// Remove old actions from action group
|
|
for (QAction* action : m_originActions->actions()) {
|
|
m_originActions->removeAction(action);
|
|
}
|
|
|
|
auto* mgr = OriginManager::instance();
|
|
std::string currentId = mgr->currentOriginId();
|
|
|
|
// Add origin entries
|
|
for (const std::string& originId : mgr->originIds()) {
|
|
FileOrigin* origin = mgr->getOrigin(originId);
|
|
if (!origin) {
|
|
continue;
|
|
}
|
|
|
|
QAction* action = m_menu->addAction(
|
|
iconForOrigin(origin),
|
|
QString::fromStdString(origin->nickname())
|
|
);
|
|
action->setCheckable(true);
|
|
action->setChecked(originId == currentId);
|
|
action->setData(QString::fromStdString(originId));
|
|
action->setToolTip(QString::fromStdString(origin->name()));
|
|
|
|
m_originActions->addAction(action);
|
|
}
|
|
|
|
// Add separator and manage action
|
|
m_menu->addSeparator();
|
|
|
|
m_manageAction = m_menu->addAction(
|
|
BitmapFactory().iconFromTheme("preferences-system"),
|
|
tr("Manage Origins...")
|
|
);
|
|
connect(m_manageAction, &QAction::triggered,
|
|
this, &OriginSelectorWidget::onManageOriginsClicked);
|
|
}
|
|
|
|
QIcon OriginSelectorWidget::iconForOrigin(FileOrigin* origin) const
|
|
{
|
|
if (!origin) {
|
|
return QIcon();
|
|
}
|
|
|
|
QIcon baseIcon = origin->icon();
|
|
|
|
// For origins that require authentication, overlay connection status
|
|
if (origin->requiresAuthentication()) {
|
|
ConnectionState state = origin->connectionState();
|
|
|
|
switch (state) {
|
|
case ConnectionState::Connected:
|
|
// No overlay needed - use base icon
|
|
break;
|
|
|
|
case ConnectionState::Connecting:
|
|
// TODO: Animated connecting indicator
|
|
break;
|
|
|
|
case ConnectionState::Disconnected:
|
|
// Overlay disconnected indicator
|
|
{
|
|
QPixmap overlay = BitmapFactory().pixmapFromSvg(
|
|
"dagViewFail", QSizeF(8, 8));
|
|
if (!overlay.isNull()) {
|
|
baseIcon = BitmapFactoryInst::mergePixmap(
|
|
baseIcon, overlay, BitmapFactoryInst::BottomRight);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ConnectionState::Error:
|
|
// Overlay error indicator
|
|
{
|
|
QPixmap overlay = BitmapFactory().pixmapFromSvg(
|
|
"Warning", QSizeF(8, 8));
|
|
if (!overlay.isNull()) {
|
|
baseIcon = BitmapFactoryInst::mergePixmap(
|
|
baseIcon, overlay, BitmapFactoryInst::BottomRight);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return baseIcon;
|
|
}
|
|
|
|
} // namespace Gui
|