Add dialog for link insertion when selection buffer is empty
This commit is contained in:
@@ -490,6 +490,7 @@ SET(Gui_UIC_SRCS
|
||||
InputVector.ui
|
||||
Placement.ui
|
||||
TaskTransform.ui
|
||||
TaskCommandLink.ui
|
||||
TextureMapping.ui
|
||||
TaskView/TaskAppearance.ui
|
||||
TaskView/TaskOrientation.ui
|
||||
@@ -578,6 +579,7 @@ SET(Dialog_CPP_SRCS
|
||||
TaskDlgRelocation.cpp
|
||||
Dialogs/DlgCheckableMessageBox.cpp
|
||||
TaskTransform.cpp
|
||||
TaskCommandLink.cpp
|
||||
Dialogs/DlgUndoRedo.cpp
|
||||
InputVector.cpp
|
||||
Placement.cpp
|
||||
@@ -620,6 +622,7 @@ SET(Dialog_HPP_SRCS
|
||||
Dialogs/DlgVersionMigrator.h
|
||||
TaskDlgRelocation.h
|
||||
TaskTransform.h
|
||||
TaskCommandLink.h
|
||||
Dialogs/DlgUndoRedo.h
|
||||
InputVector.h
|
||||
Placement.h
|
||||
|
||||
+53
-41
@@ -34,9 +34,11 @@
|
||||
#include "Action.h"
|
||||
#include "Application.h"
|
||||
#include "Command.h"
|
||||
#include "Control.h"
|
||||
#include "Document.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Selection.h"
|
||||
#include "TaskCommandLink.h"
|
||||
#include "Tree.h"
|
||||
#include "ViewProviderDocumentObject.h"
|
||||
#include "WaitCursor.h"
|
||||
@@ -280,6 +282,51 @@ void StdCmdLinkMake::activated(int)
|
||||
return;
|
||||
}
|
||||
|
||||
auto exec = [=](std::vector<App::DocumentObject*> objs) {
|
||||
doc->openTransaction(QT_TRANSLATE_NOOP("Command", "Make link"));
|
||||
try {
|
||||
if (objs.empty()) {
|
||||
std::string name = doc->getUniqueObjectName("Link");
|
||||
Command::doCommand(
|
||||
Command::Doc,
|
||||
"App.getDocument('%s').addObject('App::Link','%s')",
|
||||
doc->getName(),
|
||||
name.c_str()
|
||||
);
|
||||
Selection().addSelection(doc->getName(), name.c_str());
|
||||
}
|
||||
else {
|
||||
for (auto obj : objs) {
|
||||
std::string name = doc->getUniqueObjectName("Link");
|
||||
Command::doCommand(
|
||||
Command::Doc,
|
||||
"App.getDocument('%s').addObject('App::Link','%s').setLink(App.getDocument("
|
||||
"'%s'"
|
||||
").%s)",
|
||||
doc->getName(),
|
||||
name.c_str(),
|
||||
obj->getDocument()->getName(),
|
||||
obj->getNameInDocument()
|
||||
);
|
||||
setLinkLabel(obj, doc->getName(), name.c_str());
|
||||
Selection().addSelection(doc->getName(), name.c_str());
|
||||
}
|
||||
}
|
||||
Selection().selStackPush();
|
||||
doc->commitTransaction();
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
doc->abortTransaction();
|
||||
QMessageBox::critical(
|
||||
getMainWindow(),
|
||||
QObject::tr("Create link failed"),
|
||||
QString::fromLatin1(e.what())
|
||||
);
|
||||
e.reportException();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
std::set<App::DocumentObject*> objs;
|
||||
for (auto& sel : Selection().getCompleteSelection()) {
|
||||
if (sel.pObject && sel.pObject->isAttachedToDocument()) {
|
||||
@@ -287,48 +334,13 @@ void StdCmdLinkMake::activated(int)
|
||||
}
|
||||
}
|
||||
|
||||
Selection().selStackPush();
|
||||
Selection().clearCompleteSelection();
|
||||
|
||||
Command::openCommand(QT_TRANSLATE_NOOP("Command", "Make link"));
|
||||
try {
|
||||
if (objs.empty()) {
|
||||
std::string name = doc->getUniqueObjectName("Link");
|
||||
Command::doCommand(
|
||||
Command::Doc,
|
||||
"App.getDocument('%s').addObject('App::Link','%s')",
|
||||
doc->getName(),
|
||||
name.c_str()
|
||||
);
|
||||
Selection().addSelection(doc->getName(), name.c_str());
|
||||
}
|
||||
else {
|
||||
for (auto obj : objs) {
|
||||
std::string name = doc->getUniqueObjectName("Link");
|
||||
Command::doCommand(
|
||||
Command::Doc,
|
||||
"App.getDocument('%s').addObject('App::Link','%s').setLink(App.getDocument('%s'"
|
||||
").%s)",
|
||||
doc->getName(),
|
||||
name.c_str(),
|
||||
obj->getDocument()->getName(),
|
||||
obj->getNameInDocument()
|
||||
);
|
||||
setLinkLabel(obj, doc->getName(), name.c_str());
|
||||
Selection().addSelection(doc->getName(), name.c_str());
|
||||
}
|
||||
}
|
||||
Selection().selStackPush();
|
||||
Command::commitCommand();
|
||||
if (objs.empty()) {
|
||||
Gui::Control().showDialog(new TaskCommandLinkDialog(exec));
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Command::abortCommand();
|
||||
QMessageBox::critical(
|
||||
getMainWindow(),
|
||||
QObject::tr("Create link failed"),
|
||||
QString::fromLatin1(e.what())
|
||||
);
|
||||
e.reportException();
|
||||
else {
|
||||
Selection().selStackPush();
|
||||
Selection().clearCompleteSelection();
|
||||
exec(std::vector<App::DocumentObject*>(objs.begin(), objs.end()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2026 Théo Veilleux-Trinh <theo.veilleux.trinh@proton.me>*
|
||||
* *
|
||||
* 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 "TaskCommandLink.h"
|
||||
|
||||
#include "ui_TaskCommandLink.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "Document.h"
|
||||
#include "ViewProvider.h"
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/Document.h>
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
TaskCommandLink::TaskCommandLink()
|
||||
: ui(new Ui_TaskCommandLinkDialog())
|
||||
{
|
||||
proxy = new QWidget(this);
|
||||
ui->setupUi(proxy);
|
||||
ui->objectsList->header()->hide();
|
||||
ui->objectsList->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
|
||||
|
||||
this->groupLayout()->addWidget(proxy);
|
||||
|
||||
buildObjectsList();
|
||||
}
|
||||
TaskCommandLink::~TaskCommandLink()
|
||||
{
|
||||
delete proxy;
|
||||
delete ui;
|
||||
}
|
||||
std::vector<App::DocumentObject*> TaskCommandLink::selectedObjects()
|
||||
{
|
||||
auto selected = ui->objectsList->selectedItems();
|
||||
std::vector<App::DocumentObject*> dst;
|
||||
dst.reserve(selected.size());
|
||||
|
||||
for (auto sel : selected) {
|
||||
dst.push_back(sel->data(0, Qt::UserRole).value<App::DocumentObject*>());
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
void processObjectsHelper(std::vector<App::DocumentObject*> objs, QTreeWidgetItem* item)
|
||||
{
|
||||
for (auto obj : objs) {
|
||||
auto objItem = new QTreeWidgetItem(item);
|
||||
|
||||
objItem->setText(0, obj->Label.getValue());
|
||||
objItem->setData(0, Qt::UserRole, QVariant::fromValue(obj));
|
||||
|
||||
Gui::ViewProvider* vp = nullptr;
|
||||
if (auto doc = Application::Instance->getDocument(obj->getDocument())) {
|
||||
vp = doc->getViewProvider(obj);
|
||||
}
|
||||
if (vp) {
|
||||
objItem->setIcon(0, vp->getIcon());
|
||||
processObjectsHelper(vp->claimChildren(), objItem);
|
||||
}
|
||||
else {
|
||||
objItem->setIcon(0, QIcon());
|
||||
}
|
||||
}
|
||||
}
|
||||
void TaskCommandLink::buildObjectsList()
|
||||
{
|
||||
ui->objectsList->clear();
|
||||
|
||||
auto allDocuments = App::GetApplication().getDocuments();
|
||||
bool collapse = true;
|
||||
std::map<QTreeWidgetItem*, App::Document*> docItemMap;
|
||||
|
||||
for (auto doc : allDocuments) {
|
||||
auto docItem = new QTreeWidgetItem();
|
||||
std::string itemName = doc->Label.getValue();
|
||||
|
||||
docItem->setText(0, QString::fromStdString(itemName));
|
||||
docItem->setIcon(0, QIcon(QStringLiteral(":/icons/Document.svg")));
|
||||
docItem->setFlags(docItem->flags() & ~Qt::ItemIsSelectable); // Can't link a whole document
|
||||
|
||||
docItemMap[docItem] = doc;
|
||||
|
||||
ui->objectsList->addTopLevelItem(docItem);
|
||||
|
||||
processObjectsHelper(Application::Instance->getDocument(doc)->getTreeRootObjects(), docItem);
|
||||
|
||||
if (collapse) {
|
||||
ui->objectsList->collapseAll();
|
||||
}
|
||||
else {
|
||||
ui->objectsList->expandToDepth(0);
|
||||
}
|
||||
}
|
||||
ui->objectsList->selectedItems();
|
||||
}
|
||||
|
||||
// dialog
|
||||
|
||||
TaskCommandLinkDialog::TaskCommandLinkDialog(
|
||||
std::function<void(std::vector<App::DocumentObject*>)> executor_
|
||||
)
|
||||
: executor(executor_)
|
||||
{
|
||||
commandLink = new TaskCommandLink();
|
||||
Content.push_back(commandLink);
|
||||
}
|
||||
void TaskCommandLinkDialog::open()
|
||||
{}
|
||||
bool TaskCommandLinkDialog::accept()
|
||||
{
|
||||
executor(commandLink->selectedObjects());
|
||||
return true;
|
||||
}
|
||||
} // namespace Gui
|
||||
@@ -0,0 +1,80 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2026 Théo Veilleux-Trinh <theo.veilleux.trinh@proton.me>*
|
||||
* *
|
||||
* 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 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "TaskView/TaskDialog.h"
|
||||
#include "TaskView/TaskView.h"
|
||||
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace App
|
||||
{
|
||||
class DocumentObject;
|
||||
}
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
class Document;
|
||||
class Ui_TaskCommandLinkDialog;
|
||||
|
||||
class TaskCommandLink: public Gui::TaskView::TaskBox
|
||||
{
|
||||
public:
|
||||
TaskCommandLink();
|
||||
~TaskCommandLink();
|
||||
|
||||
std::vector<App::DocumentObject*> selectedObjects();
|
||||
|
||||
private:
|
||||
void buildObjectsList();
|
||||
|
||||
private:
|
||||
Ui_TaskCommandLinkDialog* ui {nullptr};
|
||||
QWidget* proxy {nullptr};
|
||||
};
|
||||
|
||||
class TaskCommandLinkDialog: public Gui::TaskView::TaskDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskCommandLinkDialog(std::function<void(std::vector<App::DocumentObject*>)> executor_);
|
||||
~TaskCommandLinkDialog() override = default;
|
||||
|
||||
QDialogButtonBox::StandardButtons getStandardButtons() const override
|
||||
{
|
||||
return QDialogButtonBox::Ok | QDialogButtonBox::Cancel;
|
||||
}
|
||||
|
||||
void open() override;
|
||||
bool accept() override;
|
||||
|
||||
private:
|
||||
TaskCommandLink* commandLink {nullptr};
|
||||
Gui::Document* document {nullptr};
|
||||
std::function<void(std::vector<App::DocumentObject*>)> executor;
|
||||
};
|
||||
} // namespace Gui
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gui::TaskCommandLinkDialog</class>
|
||||
<widget class="QWidget" name="Gui::TaskCommandLinkDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>340</width>
|
||||
<height>212</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Insert</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTreeWidget" name="objectsList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user