Ask user what to do if objects with unselected dependency get copied
This commit is contained in:
parent
d58f317bc5
commit
33fbb0ed8d
|
@ -64,6 +64,7 @@ recompute path. Also enables more complicated dependencies beyond trees.
|
|||
#include <boost/graph/graphviz.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QCryptographicHash>
|
||||
|
@ -1135,6 +1136,58 @@ std::vector<App::DocumentObject*> Document::getInList(const DocumentObject* me)
|
|||
return result;
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*>
|
||||
Document::getDependencyList(const std::vector<App::DocumentObject*>& objs) const
|
||||
{
|
||||
DependencyList DepList;
|
||||
std::map<DocumentObject*,Vertex> ObjectMap;
|
||||
std::map<Vertex,DocumentObject*> VertexMap;
|
||||
|
||||
// Filling up the adjacency List
|
||||
for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) {
|
||||
// add the object as Vertex and remember the index
|
||||
Vertex v = add_vertex(DepList);
|
||||
ObjectMap[It->second] = v;
|
||||
VertexMap[v] = It->second;
|
||||
}
|
||||
// add the edges
|
||||
for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) {
|
||||
std::vector<DocumentObject*> OutList = It->second->getOutList();
|
||||
for (std::vector<DocumentObject*>::const_iterator It2=OutList.begin();It2!=OutList.end();++It2) {
|
||||
if (*It2)
|
||||
add_edge(ObjectMap[It->second],ObjectMap[*It2],DepList);
|
||||
}
|
||||
}
|
||||
|
||||
std::list<Vertex> make_order;
|
||||
DependencyList::out_edge_iterator j, jend;
|
||||
|
||||
try {
|
||||
// this sort gives the execute
|
||||
boost::topological_sort(DepList, std::front_inserter(make_order));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
return std::vector<App::DocumentObject*>();
|
||||
}
|
||||
|
||||
//std::vector<App::DocumentObject*> out;
|
||||
boost::unordered_set<App::DocumentObject*> out;
|
||||
for (std::vector<App::DocumentObject*>::const_iterator it = objs.begin(); it != objs.end(); ++it) {
|
||||
std::map<DocumentObject*,Vertex>::iterator jt = ObjectMap.find(*it);
|
||||
// ok, object is part of this graph
|
||||
if (jt != ObjectMap.end()) {
|
||||
for (boost::tie(j, jend) = boost::out_edges(jt->second, DepList); j != jend; ++j) {
|
||||
out.insert(VertexMap[boost::target(*j, DepList)]);
|
||||
}
|
||||
out.insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> ary;
|
||||
ary.insert(ary.end(), out.begin(), out.end());
|
||||
return ary;
|
||||
}
|
||||
|
||||
void Document::_rebuildDependencyList(void)
|
||||
{
|
||||
d->VertexObjectList.clear();
|
||||
|
@ -1164,21 +1217,6 @@ void Document::recompute()
|
|||
// updates the dependency graph
|
||||
_rebuildDependencyList();
|
||||
|
||||
//DependencyList DepList;
|
||||
//std::map<DocumentObject*,Vertex> VertexObjectList;
|
||||
|
||||
//// Filling up the adjacency List
|
||||
//for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It)
|
||||
// // add the object as Vertex and remember the index
|
||||
// VertexObjectList[It->second] = add_vertex(DepList);
|
||||
//// add the edges
|
||||
//for (std::map<std::string,DocumentObject*>::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) {
|
||||
// std::vector<DocumentObject*> OutList = It->second->getOutList();
|
||||
// for (std::vector<DocumentObject*>::const_iterator It2=OutList.begin();It2!=OutList.end();++It2)
|
||||
// if (*It2)
|
||||
// add_edge(VertexObjectList[It->second],VertexObjectList[*It2],DepList);
|
||||
//}
|
||||
|
||||
std::list<Vertex> make_order;
|
||||
DependencyList::out_edge_iterator j, jend;
|
||||
|
||||
|
|
|
@ -265,6 +265,10 @@ public:
|
|||
bool checkOnCycle(void);
|
||||
/// get a list of all objects linking to the given object
|
||||
std::vector<App::DocumentObject*> getInList(const DocumentObject* me) const;
|
||||
/// Get a complete list of all objects the given objects depend on. The list
|
||||
/// also contains the given objects!
|
||||
std::vector<App::DocumentObject*> getDependencyList
|
||||
(const std::vector<App::DocumentObject*>&) const;
|
||||
// set Changed
|
||||
//void setChanged(DocumentObject* change);
|
||||
//@}
|
||||
|
|
|
@ -841,7 +841,6 @@ void StdCmdCopy::activated(int iMsg)
|
|||
{
|
||||
bool done = getGuiApplication()->sendMsgToActiveView("Copy");
|
||||
if (!done) {
|
||||
WaitCursor wc;
|
||||
QMimeData * mimeData = getMainWindow()->createMimeDataFromSelection();
|
||||
QClipboard* cb = QApplication::clipboard();
|
||||
cb->setMimeData(mimeData);
|
||||
|
@ -911,24 +910,42 @@ StdCmdDuplicateSelection::StdCmdDuplicateSelection()
|
|||
void StdCmdDuplicateSelection::activated(int iMsg)
|
||||
{
|
||||
std::vector<SelectionSingleton::SelObj> sel = Selection().getCompleteSelection();
|
||||
std::vector<App::DocumentObject*> obj;
|
||||
obj.reserve(sel.size());
|
||||
std::map< App::Document*, std::vector<App::DocumentObject*> > objs;
|
||||
for (std::vector<SelectionSingleton::SelObj>::iterator it = sel.begin(); it != sel.end(); ++it) {
|
||||
if (it->pObject) {
|
||||
obj.push_back(it->pObject);
|
||||
if (it->pObject && it->pObject->getDocument()) {
|
||||
objs[it->pObject->getDocument()].push_back(it->pObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (obj.empty())
|
||||
if (objs.empty())
|
||||
return;
|
||||
|
||||
Base::FileInfo fi(Base::FileInfo::getTempFileName());
|
||||
{
|
||||
std::vector<App::DocumentObject*> sel; // selected
|
||||
std::vector<App::DocumentObject*> all; // object sub-graph
|
||||
for (std::map< App::Document*, std::vector<App::DocumentObject*> >::iterator it = objs.begin(); it != objs.end(); ++it) {
|
||||
std::vector<App::DocumentObject*> dep = it->first->getDependencyList(it->second);
|
||||
sel.insert(sel.end(), it->second.begin(), it->second.end());
|
||||
all.insert(all.end(), dep.begin(), dep.end());
|
||||
}
|
||||
|
||||
if (all.size() > sel.size()) {
|
||||
int ret = QMessageBox::question(getMainWindow(),
|
||||
qApp->translate("Std_DuplicateSelection","Object dependencies"),
|
||||
qApp->translate("Std_DuplicateSelection","The selected objects have a dependency to unselected objects.\n"
|
||||
"Do you want to duplicate them, too?"),
|
||||
QMessageBox::Yes,QMessageBox::No);
|
||||
if (ret == QMessageBox::Yes) {
|
||||
sel = all;
|
||||
}
|
||||
}
|
||||
|
||||
// save stuff to file
|
||||
Base::ofstream str(fi, std::ios::out | std::ios::binary);
|
||||
App::Document* doc = obj.front()->getDocument();
|
||||
App::Document* doc = sel.front()->getDocument();
|
||||
MergeDocuments mimeView(doc);
|
||||
doc->exportObjects(obj, str);
|
||||
doc->exportObjects(sel, str);
|
||||
str.close();
|
||||
}
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <algorithm>
|
||||
# include <QApplication>
|
||||
# include <QBuffer>
|
||||
# include <QByteArray>
|
||||
|
@ -63,6 +64,7 @@
|
|||
#include "MainWindow.h"
|
||||
#include "Application.h"
|
||||
#include "Assistant.h"
|
||||
#include "WaitCursor.h"
|
||||
|
||||
#include "Action.h"
|
||||
#include "Command.h"
|
||||
|
@ -1403,21 +1405,39 @@ void MainWindow::dragEnterEvent (QDragEnterEvent * e)
|
|||
|
||||
QMimeData * MainWindow::createMimeDataFromSelection () const
|
||||
{
|
||||
std::vector<SelectionSingleton::SelObj> sel = Selection().getCompleteSelection();
|
||||
unsigned int memsize=1000; // ~ for the meta-information
|
||||
std::vector<App::DocumentObject*> obj;
|
||||
obj.reserve(sel.size());
|
||||
for (std::vector<SelectionSingleton::SelObj>::iterator it = sel.begin(); it != sel.end(); ++it) {
|
||||
if (it->pObject) {
|
||||
obj.push_back(it->pObject);
|
||||
memsize += it->pObject->getMemSize();
|
||||
std::vector<SelectionSingleton::SelObj> selobj = Selection().getCompleteSelection();
|
||||
std::map< App::Document*, std::vector<App::DocumentObject*> > objs;
|
||||
for (std::vector<SelectionSingleton::SelObj>::iterator it = selobj.begin(); it != selobj.end(); ++it) {
|
||||
if (it->pObject && it->pObject->getDocument()) {
|
||||
objs[it->pObject->getDocument()].push_back(it->pObject);
|
||||
}
|
||||
}
|
||||
|
||||
// get a pointer to a document
|
||||
if (obj.empty()) return 0;
|
||||
App::Document* doc = obj.front()->getDocument();
|
||||
if (!doc) return 0;
|
||||
if (objs.empty())
|
||||
return 0;
|
||||
|
||||
std::vector<App::DocumentObject*> sel; // selected
|
||||
std::vector<App::DocumentObject*> all; // object sub-graph
|
||||
for (std::map< App::Document*, std::vector<App::DocumentObject*> >::iterator it = objs.begin(); it != objs.end(); ++it) {
|
||||
std::vector<App::DocumentObject*> dep = it->first->getDependencyList(it->second);
|
||||
sel.insert(sel.end(), it->second.begin(), it->second.end());
|
||||
all.insert(all.end(), dep.begin(), dep.end());
|
||||
}
|
||||
|
||||
if (all.size() > sel.size()) {
|
||||
int ret = QMessageBox::question(getMainWindow(),
|
||||
tr("Object dependencies"),
|
||||
tr("The selected objects have a dependency to unselected objects.\n"
|
||||
"Do you want to copy them, too?"),
|
||||
QMessageBox::Yes,QMessageBox::No);
|
||||
if (ret == QMessageBox::Yes) {
|
||||
sel = all;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int memsize=1000; // ~ for the meta-information
|
||||
for (std::vector<App::DocumentObject*>::iterator it = sel.begin(); it != sel.end(); ++it)
|
||||
memsize += (*it)->getMemSize();
|
||||
|
||||
// if less than ~10 MB
|
||||
bool use_buffer=(memsize < 0xA00000);
|
||||
|
@ -1429,22 +1449,25 @@ QMimeData * MainWindow::createMimeDataFromSelection () const
|
|||
use_buffer = false;
|
||||
}
|
||||
|
||||
WaitCursor wc;
|
||||
QString mime;
|
||||
if (use_buffer) {
|
||||
mime = QLatin1String("application/x-documentobject");
|
||||
Base::ByteArrayOStreambuf buf(res);
|
||||
std::ostream str(&buf);
|
||||
// need this instance to call MergeDocuments::Save()
|
||||
App::Document* doc = sel.front()->getDocument();
|
||||
MergeDocuments mimeView(doc);
|
||||
doc->exportObjects(obj, str);
|
||||
doc->exportObjects(sel, str);
|
||||
}
|
||||
else {
|
||||
mime = QLatin1String("application/x-documentobject-file");
|
||||
static Base::FileInfo fi(Base::FileInfo::getTempFileName());
|
||||
Base::ofstream str(fi, std::ios::out | std::ios::binary);
|
||||
// need this instance to call MergeDocuments::Save()
|
||||
App::Document* doc = sel.front()->getDocument();
|
||||
MergeDocuments mimeView(doc);
|
||||
doc->exportObjects(obj, str);
|
||||
doc->exportObjects(sel, str);
|
||||
str.close();
|
||||
res = fi.filePath().c_str();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user