1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-03-23 11:47:24 +01:00
fwbuilder/src/libgui/ObjectManipulator_slots.cpp
Vadim Kurland bbf03ad49c see #2561 operation of making an interface a subinterface should be
performed using undo/redo command. Also, this should take care of
inconvenient scrolling of the object tree after this operation.
2011-07-09 16:42:37 -07:00

538 lines
16 KiB
C++

/*
Firewall Builder
Copyright (C) 2003 NetCitadel, LLC
Author: Vadim Kurland vadim@fwbuilder.org
$Id$
This program is free software which we release under the GNU General Public
License. You may redistribute and/or modify this program under the terms
of that license as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program 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 General Public License for more details.
To get a copy of the GNU General Public License, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../../config.h"
#include "global.h"
#include "platforms.h"
#include "events.h"
#include "listOfLibrariesModel.h"
#include "ObjectManipulator.h"
#include "ObjectEditor.h"
#include "ObjectTreeViewItem.h"
#include "ObjectTreeView.h"
#include "newGroupDialog.h"
#include "FWObjectClipboard.h"
#include "FindObjectWidget.h"
#include "interfaceProperties.h"
#include "interfacePropertiesObjectFactory.h"
#include "FWCmdChange.h"
#include "FWCmdAddObject.h"
#include "FWBTree.h"
#include "FWWindow.h"
#include "ProjectPanel.h"
#include "ConfirmDeleteObjectDialog.h"
#include "FWCmdMoveObject.h"
#include "fwbuilder/Cluster.h"
#include "fwbuilder/FWObject.h"
#include "fwbuilder/IPv6.h"
#include "fwbuilder/Library.h"
#include "fwbuilder/Policy.h"
#include "fwbuilder/Resources.h"
#include <QMessageBox>
#include <QTextEdit>
#include <QTime>
#include <QtDebug>
#include <QUndoStack>
#include <memory>
#include <algorithm>
using namespace std;
using namespace libfwbuilder;
void ObjectManipulator::undeleteLibrary()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
FWObject *obj = getCurrentObjectTree()->getSelectedObjects().front();
if (obj==NULL) return;
// check that obj is in Deleted objects library. We do not show menu item
// "Undelete" if it isnt, but will double check anyway
if (Library::isA(obj) &&
obj->getParent()->getId()==FWObjectDatabase::DELETED_OBJECTS_ID)
{
map<int, set<FWObject*> > reference_holders;
FWCmdMoveObject *cmd = new FWCmdMoveObject(
m_project,
obj->getParent(),
obj->getRoot(),
obj,
reference_holders,
QString("Undelete library object"),
0);
m_project->undoStack->push(cmd);
}
}
/*
* moveObj is a slot called from the context menu
*/
void ObjectManipulator::moveObj(QAction* action)
{
int libid = action->data().toInt();
if (getCurrentObjectTree()->getNumSelected()==0) return;
ObjectTreeView* ot=getCurrentObjectTree();
ot->freezeSelection(true);
FWObject *obj;
FWObject *targetLib = libs_model->getLibrary(libid);
vector<FWObject*> so = getCurrentObjectTree()->getSimplifiedSelection();
for (vector<FWObject*>::iterator i=so.begin(); i!=so.end(); ++i)
{
obj= *i;
if (fwbdebug)
{
qDebug("ObjectManipulator::moveObj obj=%p obj: %s",
obj, obj->getName().c_str() );
}
if (Library::isA(obj))
{
/* We can only move library to the root of the tree. This case only
* happens when user tries to undelete a library.
*/
moveObject(m_project->db(),obj);
} else
{
if (obj->isChildOf(targetLib)) continue;
if ( FWBTree().isSystem(obj) ||
Interface::isA(obj) ||
Interface::isA(obj->getParent())) continue;
moveObject(targetLib, obj);
}
QCoreApplication::postEvent(
mw, new dataModifiedEvent(m_project->getFileName(), obj->getId()));
}
ot->freezeSelection(false);
}
void ObjectManipulator::copyObj()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
FWObject *obj;
FWObjectClipboard::obj_clipboard->clear();
vector<FWObject*> so = getCurrentObjectTree()->getSimplifiedSelection();
for (vector<FWObject*>::iterator i=so.begin(); i!=so.end(); ++i)
{
obj = *i;
if ( ! FWBTree().isSystem(obj) )
{
// while obj is still part of the tree, do some clean up
// to avoid problems in the future. Create
// InterfaceOptions objects for interfaces because we'll
// need them for various validations during paste
// operation.
Interface *intf = Interface::cast(obj);
if (intf) intf->getOptionsObject();
FWObjectClipboard::obj_clipboard->add(obj, m_project);
mw->showStatusBarMessage(
tr("Copy object '%1' to clipboard'").arg(
QString::fromUtf8(obj->getName().c_str())));
}
}
}
void ObjectManipulator::cutObj()
{
// Start macro to hide the name of the undo command created in
// delObj. Normally its name is "Delete object".
FWCmdMacro* macro = new FWCmdMacro(tr("Cut object"));
copyObj();
delObj(macro); // works with the list getCurrentObjectTree()->getSelectedObjects()
m_project->undoStack->push(macro);
}
void ObjectManipulator::pasteObj()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
FWObject *target_object = getCurrentObjectTree()->getSelectedObjects().front();
if (target_object==NULL) return;
vector<std::pair<int,ProjectPanel*> >::iterator i;
int idx = 0;
FWObject *last_object = NULL;
map<int,int> map_ids;
if (fwbdebug)
{
qDebug() << "**************** pasteObj loop starts";
qDebug() << "Target object: " << target_object->getPath().c_str();
}
// If we copy many objects in the following loop, and some of them
// are groups that refer other objects in the same batch, then it
// is possible that an object would be copied by
// FWObjectDatabase::recursivelyCopySubtree() by the way of a
// reference from a group, and then the same object is found in
// the list of objects to be copied AGAIN. Since this object is
// already present in the target object tree by the time it needs
// to be copied again, actuallyPasteTo() chooses the path for
// copying of objects inside the same tree and creates a copy. To
// avoid this, prepare a list of objects to be copied before copy
// operation starts.
list<FWObject*> copy_objects;
for (i= FWObjectClipboard::obj_clipboard->begin();
i!=FWObjectClipboard::obj_clipboard->end(); ++i)
{
FWObject *co = FWObjectClipboard::obj_clipboard->getObjectByIdx(idx);
copy_objects.push_back(co);
idx++;
}
for (list<FWObject*>::iterator i=copy_objects.begin(); i!=copy_objects.end(); ++i)
{
FWObject *co = *i;
if (fwbdebug)
qDebug("Copy object %s (id=%d, root=%p)",
co->getName().c_str(), co->getId(), co->getRoot());
if (map_ids.count(co->getId()) > 0)
continue;
// Check if we have already copied the same object before
QString buff;
buff.sprintf(".copy_of_%p", co->getRoot());
string dedup_attribute = buff.toAscii().constData();
buff.sprintf("%d", co->getId());
QByteArray bytes = buff.toAscii();
FWObject *n_obj =
target_object->getRoot()->findObjectByAttribute(dedup_attribute,
bytes.constData());
if (n_obj) continue;
last_object = actuallyPasteTo(target_object, co, map_ids);
}
if (fwbdebug) qDebug("**************** pasteObj loop done");
}
void ObjectManipulator::duplicateObj(QAction *action)
{
int libid = action->data().toInt();
if (getCurrentObjectTree()->getNumSelected()==0) return;
ObjectTreeView* ot=getCurrentObjectTree();
ot->freezeSelection(true);
FWObject *obj;
FWObject *nobj = NULL;
vector<FWObject*> so = getCurrentObjectTree()->getSimplifiedSelection();
for (vector<FWObject*>::iterator i=so.begin(); i!=so.end(); ++i)
{
obj= *i;
if ( FWBTree().isSystem(obj) || Interface::isA(obj) ) continue;
FWObject *cl = libs_model->getLibrary(libid);
nobj = duplicateObject(cl, obj);
}
if (nobj) editObject(nobj);
ot->freezeSelection(false);
}
/*
* Note: this slot gets controlwhen user presses "Delete" key in
* addition to menu items activation
*/
void ObjectManipulator::delObj(QUndoCommand* macro)
{
if (fwbdebug)
qDebug("ObjectManipulator::delObj selected %d objects ",
getCurrentObjectTree()->getNumSelected());
if (getCurrentObjectTree()->getNumSelected()==0) return;
FWObject *current_library = getCurrentLib();
if (current_library->getId() == FWObjectDatabase::STANDARD_LIB_ID)
return;
FWObject *obj;
vector<FWObject*> so = getCurrentObjectTree()->getSimplifiedSelection();
vector<FWObject*> so2;
for (vector<FWObject*>::iterator i=so.begin(); i!=so.end(); ++i)
{
bool del_obj_status = getDeleteMenuState(*i);
if (fwbdebug)
qDebug("ObjectManipulator::delObj object: %s del_obj_status=%d",
(*i)->getName().c_str(), del_obj_status);
if (del_obj_status) so2.push_back(*i);
}
if (so2.size()==0) return;
if (so2.size() > 1 || ! Library::isA(so2.front()))
{
QApplication::setOverrideCursor( QCursor( Qt::WaitCursor) );
ConfirmDeleteObjectDialog * dlg = new ConfirmDeleteObjectDialog(this);
dlg->load(so2);
QApplication::restoreOverrideCursor();
if(dlg->exec()==QDialog::Rejected ) return;
}
/* need to work with a copy of the list of selected objects because
* some of the methods we call below clear list
* getCurrentObjectTree()->getSelectedObjects()
*/
try
{
for (vector<FWObject*>::iterator i=so2.begin(); i!=so2.end(); ++i)
{
obj= *i;
if ( ! FWBTree().isSystem(obj) )
{
if (Library::isA(obj))
{
list<FWObject*> ll=m_project->db()->getByType(Library::TYPENAME);
if (ll.size()==1) return;
if (QMessageBox::warning(
this,"Firewall Builder",
tr(
"When you delete a library, all objects that belong to it\n"
"disappear from the tree and all groups and rules that reference them.\n"
"Do you still want to delete library %1?")
.arg(QString::fromUtf8(obj->getName().c_str())),
tr("&Yes"), tr("&No"), QString::null,
0, 1 )!=0 ) continue;
}
if (mw->isEditorVisible() && mw->getOpenedEditor()==obj)
mw->hideEditor();
deleteObject(obj, macro);
}
}
}
catch(FWException &ex)
{
}
}
void ObjectManipulator::dumpObj()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
FWObject *obj=getCurrentObjectTree()->getSelectedObjects().front();
if (obj==NULL) return;
obj->dump(true,false);
}
void ObjectManipulator::compile()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
vector<FWObject*> so = getCurrentObjectTree()->getSimplifiedSelection();
set<Firewall*> fo;
filterFirewallsFromSelection(so, fo);
if (fwbdebug)
qDebug("ObjectManipulator::compile filtered %d firewalls",
int(fo.size()));
m_project->compile(fo);
}
void ObjectManipulator::install()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
vector<FWObject*> so = getCurrentObjectTree()->getSimplifiedSelection();
set<Firewall*> fo;
filterFirewallsFromSelection(so,fo);
m_project->install(fo);
}
void ObjectManipulator::inspect()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
vector<FWObject*> so = getCurrentObjectTree()->getSimplifiedSelection();
set<Firewall*> fws;
filterFirewallsFromSelection(so,fws);
set<Firewall*> fwset;
foreach(Firewall *fw, fws)
if (Cluster::isA(fw))
{
std::list<Firewall*> cfws;
Cluster::cast(fw)->getMembersList(cfws);
foreach(Firewall *f, cfws)
fwset.insert(f);
}
else
{
fwset.insert(fw);
}
m_project->inspect(fwset);
}
void ObjectManipulator::find()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
FWObject *obj=getCurrentObjectTree()->getSelectedObjects().front();
if (obj==NULL) return;
m_project->setFDObject(obj);
}
void ObjectManipulator::findObject()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
FWObject *obj=getCurrentObjectTree()->getSelectedObjects().front();
if (obj==NULL) return;
mw->findObject( obj );
}
void ObjectManipulator::back()
{
if (!history.empty())
{
FWObject *obj = NULL;
current_history_item--;
if ( current_history_item != history.end())
{
ObjectTreeViewItem* otvi = current_history_item->item();
int obj_id = current_history_item->id();
obj = m_project->db()->findInIndex(obj_id);
if ( obj != NULL)
{
openObjectInTree( otvi, false );
if (mw->isEditorVisible()) editSelectedObject();
}
} else
{
current_history_item = history.begin();
}
}
}
void ObjectManipulator::forward()
{
if (!history.empty())
{
FWObject *obj = NULL;
current_history_item++;
if ( current_history_item != history.end())
{
ObjectTreeViewItem* otvi = current_history_item->item();
int obj_id = current_history_item->id();
obj = m_project->db()->findInIndex(obj_id);
if ( obj != NULL)
{
openObjectInTree( otvi, false );
if (mw->isEditorVisible()) editSelectedObject();
}
} else
{
current_history_item = history.end();
current_history_item--;
}
}
}
void ObjectManipulator::findWhereUsedSlot()
{
if (getCurrentObjectTree()->getNumSelected()==0) return;
FWObject *obj = getCurrentObjectTree()->getSelectedObjects().front();
if (obj==NULL) return;
mw->findWhereUsed(obj, m_project);
}
void ObjectManipulator::makeSubinterface(QAction *act)
{
int intf_id = act->data().toInt();
FWObject *new_parent_interface = m_project->db()->findInIndex(intf_id);
assert(new_parent_interface!=NULL);
if (getCurrentObjectTree()->getNumSelected()==0) return;
ObjectTreeView* ot = getCurrentObjectTree();
ot->freezeSelection(true);
FWObject *obj;
vector<FWObject*> so = getCurrentObjectTree()->getSimplifiedSelection();
for (vector<FWObject*>::iterator i=so.begin(); i!=so.end(); ++i)
{
obj = *i;
if (obj->getParent() == new_parent_interface) continue;
if (fwbdebug)
qDebug() << "ObjectManipulator::makeSubinterface"
<< "obj=" << obj
<< obj->getName().c_str()
<< "new parent:" << new_parent_interface->getName().c_str();
// new_parent_interface->reparent(obj);
map<int, set<FWObject*> > reference_holders;
FWCmdMoveObject *cmd = new FWCmdMoveObject(
m_project,
obj->getParent(),
new_parent_interface,
obj,
reference_holders,
QString("Make an interface a subinterface"),
0);
m_project->undoStack->push(cmd);
}
ot->freezeSelection(false);
}