mirror of
https://github.com/fwbuilder/fwbuilder
synced 2026-03-21 02:37:16 +01:00
Added support for user-defined folders. It's just a ui/display thing.
The FWObject has a property "folder" that controls which sub-folder to display in. The placement of the object in the tree doesn't change even when placed into a user-defined folder. Turned on drag/drop in the object tree so that objects can be moved into these new folders (however, disabled dragging of system folders).
This commit is contained in:
parent
aacc4016cd
commit
54f6bae48f
@ -67,6 +67,7 @@
|
||||
comment %STRING; #IMPLIED
|
||||
id ID #REQUIRED
|
||||
ro %BOOLEAN; #IMPLIED
|
||||
folder %STRING; #IMPLIED
|
||||
'>
|
||||
|
||||
<!-- Standard attributes for all system nodes -->
|
||||
@ -112,7 +113,8 @@
|
||||
|
||||
<!ELEMENT ServiceGroup (( ServiceGroup | IPService | ICMPService | ICMP6Service | TCPService | UDPService | CustomService | ServiceRef | TagService | UserService)*)>
|
||||
<!ATTLIST ServiceGroup
|
||||
%STD_ATTRIBUTES;
|
||||
%STD_ATTRIBUTES;
|
||||
subfolders %STRING; #IMPLIED
|
||||
>
|
||||
|
||||
<!--
|
||||
@ -127,7 +129,8 @@
|
||||
|
||||
<!ELEMENT ObjectGroup ((ObjectGroup|DynamicGroup|Host|Firewall|Cluster|Network|NetworkIPv6|IPv4|IPv6|DNSName|AddressTable|AddressRange|ObjectRef)*)>
|
||||
<!ATTLIST ObjectGroup
|
||||
%STD_ATTRIBUTES;
|
||||
%STD_ATTRIBUTES;
|
||||
subfolders %STRING; #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT SelectionCriteria EMPTY>
|
||||
@ -611,7 +614,8 @@ some can't (ipfilter, IOS, PIX)
|
||||
|
||||
<!ELEMENT IntervalGroup ((IntervalGroup|Interval|IntervalRef)*)>
|
||||
<!ATTLIST IntervalGroup
|
||||
%STD_ATTRIBUTES;
|
||||
%STD_ATTRIBUTES;
|
||||
subfolders %STRING; #IMPLIED
|
||||
>
|
||||
|
||||
<!-- Reference to time interval -->
|
||||
|
||||
@ -67,6 +67,7 @@
|
||||
comment %STRING; #IMPLIED
|
||||
id ID #REQUIRED
|
||||
ro %BOOLEAN; #IMPLIED
|
||||
folder %STRING; #IMPLIED
|
||||
'>
|
||||
|
||||
<!-- Standard attributes for all system nodes -->
|
||||
@ -112,7 +113,8 @@
|
||||
|
||||
<!ELEMENT ServiceGroup (( ServiceGroup | IPService | ICMPService | ICMP6Service | TCPService | UDPService | CustomService | ServiceRef | TagService | UserService)*)>
|
||||
<!ATTLIST ServiceGroup
|
||||
%STD_ATTRIBUTES;
|
||||
%STD_ATTRIBUTES;
|
||||
subfolders %STRING; #IMPLIED
|
||||
>
|
||||
|
||||
<!--
|
||||
@ -127,7 +129,8 @@
|
||||
|
||||
<!ELEMENT ObjectGroup ((ObjectGroup|DynamicGroup|Host|Firewall|Cluster|Network|NetworkIPv6|IPv4|IPv6|DNSName|AddressTable|AddressRange|ObjectRef)*)>
|
||||
<!ATTLIST ObjectGroup
|
||||
%STD_ATTRIBUTES;
|
||||
%STD_ATTRIBUTES;
|
||||
subfolders %STRING; #IMPLIED
|
||||
>
|
||||
|
||||
<!ELEMENT SelectionCriteria EMPTY>
|
||||
@ -611,7 +614,8 @@ some can't (ipfilter, IOS, PIX)
|
||||
|
||||
<!ELEMENT IntervalGroup ((IntervalGroup|Interval|IntervalRef)*)>
|
||||
<!ATTLIST IntervalGroup
|
||||
%STD_ATTRIBUTES;
|
||||
%STD_ATTRIBUTES;
|
||||
subfolders %STRING; #IMPLIED
|
||||
>
|
||||
|
||||
<!-- Reference to time interval -->
|
||||
|
||||
@ -64,27 +64,6 @@ string FWObject::NOT_FOUND="";
|
||||
//#define TI_DEBUG
|
||||
|
||||
|
||||
static void
|
||||
parseKeywordsFromString(set<string> &keywords, set<string> &allKeywords,
|
||||
const string &str)
|
||||
{
|
||||
if (str.empty()) return;
|
||||
string::size_type pos = 0;
|
||||
for ( ; ; ) {
|
||||
string::size_type delim = str.find(',', pos);
|
||||
if (delim == string::npos) {
|
||||
keywords.insert(str.substr(pos));
|
||||
allKeywords.insert(str.substr(pos));
|
||||
break;
|
||||
} else {
|
||||
keywords.insert(str.substr(pos, delim - pos));
|
||||
allKeywords.insert(str.substr(pos, delim - pos));
|
||||
pos = delim + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FWObject::fromXML(xmlNodePtr root) throw(FWException)
|
||||
{
|
||||
assert(root!=NULL);
|
||||
@ -111,12 +90,23 @@ void FWObject::fromXML(xmlNodePtr root) throw(FWException)
|
||||
FREEXMLBUFF(n);
|
||||
}
|
||||
|
||||
if (dbroot != 0) {
|
||||
n = FROMXMLCAST(xmlGetProp(root, TOXMLCAST("keywords")));
|
||||
if (n != 0) {
|
||||
parseKeywordsFromString(keywords, dbroot->keywords, n);
|
||||
FREEXMLBUFF(n);
|
||||
}
|
||||
n = FROMXMLCAST(xmlGetProp(root, TOXMLCAST("keywords")));
|
||||
if (n != 0) {
|
||||
keywords = stringToSet(n);
|
||||
dbroot->keywords.insert(keywords.begin(), keywords.end());
|
||||
FREEXMLBUFF(n);
|
||||
}
|
||||
|
||||
n = FROMXMLCAST(xmlGetProp(root, TOXMLCAST("subfolders")));
|
||||
if (n != 0) {
|
||||
setStr("subfolders", n);
|
||||
FREEXMLBUFF(n);
|
||||
}
|
||||
|
||||
n = FROMXMLCAST(xmlGetProp(root, TOXMLCAST("folder")));
|
||||
if (n != 0) {
|
||||
setStr("folder", n);
|
||||
FREEXMLBUFF(n);
|
||||
}
|
||||
|
||||
n=FROMXMLCAST(xmlGetProp(root,TOXMLCAST("ro")));
|
||||
@ -160,20 +150,6 @@ xmlNodePtr FWObject::toXML(xmlNodePtr xml_parent_node) throw(FWException)
|
||||
return toXML(xml_parent_node, true);
|
||||
}
|
||||
|
||||
static string keywordsAsString(const set<string> &keywords)
|
||||
{
|
||||
if (keywords.empty()) return "";
|
||||
set<string>::const_iterator iter = keywords.begin();
|
||||
string ret = *iter;
|
||||
++iter;
|
||||
while (iter != keywords.end()) {
|
||||
ret += ",";
|
||||
ret += *iter;
|
||||
++iter;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmlNodePtr FWObject::toXML(xmlNodePtr parent, bool process_children)
|
||||
throw(FWException)
|
||||
{
|
||||
@ -195,7 +171,7 @@ xmlNodePtr FWObject::toXML(xmlNodePtr parent, bool process_children)
|
||||
|
||||
if (!keywords.empty()) {
|
||||
xmlNewProp(me, TOXMLCAST("keywords"),
|
||||
STRTOXMLCAST(keywordsAsString(keywords)));
|
||||
STRTOXMLCAST(setToString(keywords)));
|
||||
}
|
||||
|
||||
for(map<string, string>::const_iterator i=data.begin(); i!=data.end(); ++i)
|
||||
@ -669,7 +645,7 @@ void FWObject::remStr(const string &name)
|
||||
|
||||
void FWObject::setStr(const string &name, const string &val)
|
||||
{
|
||||
if (name[0]!='.') checkReadOnly();
|
||||
if (name[0]!='.' && name != "folder") checkReadOnly();
|
||||
string old_val = data[name];
|
||||
if (old_val != val)
|
||||
{
|
||||
|
||||
@ -228,4 +228,40 @@ string stringify(const vector<string>& parts, const string& delimiter)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
set<string> stringToSet(const string &str)
|
||||
{
|
||||
set<string> ret;
|
||||
size_t lastpos = 0;
|
||||
for ( ; ; ) {
|
||||
size_t pos = str.find(',', lastpos);
|
||||
if (pos == string::npos) {
|
||||
if (lastpos < str.size()) {
|
||||
ret.insert(str.substr(lastpos));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
ret.insert(str.substr(lastpos, pos - lastpos));
|
||||
lastpos = pos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string setToString(const set<string> &s)
|
||||
{
|
||||
string ret;
|
||||
set<string>::const_iterator iter;
|
||||
bool first = true;
|
||||
for (iter = s.begin(); iter != s.end(); ++iter) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
ret += ",";
|
||||
}
|
||||
ret += *iter;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <dirent.h>
|
||||
@ -109,8 +110,11 @@ namespace libfwbuilder
|
||||
* Strip identifier from string 'in' and return as string.
|
||||
*/
|
||||
std::string strip(const std::string& in, const std::string& identifier);
|
||||
|
||||
/* Convert from string <-> set<string>, using comma as delim */
|
||||
std::set<std::string> stringToSet(const std::string &str);
|
||||
std::string setToString(const std::set<std::string> &s);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -405,6 +405,13 @@ static void addKeywordsMenu(ObjectManipulator *om, QMenu *menu)
|
||||
|
||||
void ObjectManipulator::contextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
if (popup_menu == NULL)
|
||||
{
|
||||
popup_menu = new QMenu(this);
|
||||
popup_menu->setObjectName("objectTreeContextMenu");
|
||||
} else
|
||||
popup_menu->clear();
|
||||
|
||||
/* in extended selection mode there may be several selected items */
|
||||
|
||||
QTreeWidget *objTreeView = getCurrentObjectTree();
|
||||
@ -417,19 +424,24 @@ void ObjectManipulator::contextMenuRequested(const QPoint &pos)
|
||||
ObjectTreeViewItem *otvi=dynamic_cast<ObjectTreeViewItem*>(item);
|
||||
if (otvi==NULL) return; // happens when user clicks outside an item
|
||||
|
||||
FWObject *obj = otvi->getFWObject();
|
||||
if (obj == 0) {
|
||||
assert(otvi->getUserFolderParent() != 0);
|
||||
QAction *action =
|
||||
popup_menu->addAction(tr("Remove"), this, SLOT(removeUserFolder()));
|
||||
if (otvi->childCount() > 0) {
|
||||
action->setEnabled(false);
|
||||
}
|
||||
popup_menu->exec(QCursor::pos());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!getCurrentObjectTree()->isSelected(otvi->getFWObject()))
|
||||
openObjectInTree( otvi, true );
|
||||
|
||||
//if (currentObj==NULL) currentObj=otvi->getFWObject();
|
||||
FWObject *currentObj = getSelectedObject();
|
||||
|
||||
if (popup_menu == NULL)
|
||||
{
|
||||
popup_menu = new QMenu(this);
|
||||
popup_menu->setObjectName("objectTreeContextMenu");
|
||||
} else
|
||||
popup_menu->clear();
|
||||
|
||||
if (item->childCount() > 0)
|
||||
{
|
||||
if (item->isExpanded())
|
||||
@ -535,7 +547,7 @@ void ObjectManipulator::contextMenuRequested(const QPoint &pos)
|
||||
|
||||
if (getCurrentObjectTree()->getNumSelected()==1)
|
||||
{
|
||||
|
||||
bool addSubfolder = false;
|
||||
if ( (Firewall::isA(currentObj) || Host::isA(currentObj)) &&
|
||||
! currentObj->isReadOnly() )
|
||||
{
|
||||
@ -639,16 +651,21 @@ void ObjectManipulator::contextMenuRequested(const QPoint &pos)
|
||||
popup_menu, StateSyncClusterGroup::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Firewalls")
|
||||
if (currentObj->getPath(true)=="Firewalls") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, Firewall::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Clusters")
|
||||
if (currentObj->getPath(true)=="Clusters") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, Cluster::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Objects/Addresses")
|
||||
{
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, IPv4::TYPENAME));
|
||||
AddObjectActions.append(
|
||||
@ -657,26 +674,33 @@ void ObjectManipulator::contextMenuRequested(const QPoint &pos)
|
||||
|
||||
if (currentObj->getPath(true)=="Objects/DNS Names")
|
||||
{
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, DNSName::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Objects/Address Tables")
|
||||
{
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, AddressTable::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Objects/Address Ranges")
|
||||
if (currentObj->getPath(true)=="Objects/Address Ranges") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, AddressRange::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Objects/Hosts")
|
||||
if (currentObj->getPath(true)=="Objects/Hosts") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, Host::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Objects/Networks")
|
||||
{
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, Network::TYPENAME));
|
||||
AddObjectActions.append(
|
||||
@ -684,51 +708,76 @@ void ObjectManipulator::contextMenuRequested(const QPoint &pos)
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Objects/Groups") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, ObjectGroup::TYPENAME));
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, DynamicGroup::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Services/Custom")
|
||||
if (currentObj->getPath(true)=="Services/Custom") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, CustomService::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Services/IP")
|
||||
if (currentObj->getPath(true)=="Services/IP") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, IPService::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Services/ICMP")
|
||||
{
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, ICMPService::TYPENAME));
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, ICMP6Service::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Services/TCP")
|
||||
if (currentObj->getPath(true)=="Services/TCP") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, TCPService::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Services/UDP")
|
||||
if (currentObj->getPath(true)=="Services/UDP") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, UDPService::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Services/TagServices")
|
||||
if (currentObj->getPath(true)=="Services/TagServices") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, TagService::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Services/Groups")
|
||||
if (currentObj->getPath(true)=="Services/Groups") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, ServiceGroup::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Services/Users")
|
||||
if (currentObj->getPath(true)=="Services/Users") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, UserService::TYPENAME));
|
||||
}
|
||||
|
||||
if (currentObj->getPath(true)=="Time")
|
||||
if (currentObj->getPath(true)=="Time") {
|
||||
addSubfolder = true;
|
||||
AddObjectActions.append(
|
||||
addNewObjectMenuItem(popup_menu, Interval::TYPENAME));
|
||||
}
|
||||
|
||||
if (addSubfolder) {
|
||||
QAction *action = popup_menu->addAction(tr("New Subfolder"), this,
|
||||
SLOT(addSubfolderSlot()));
|
||||
action->setData(currentObj->getId());
|
||||
AddObjectActions.append(action);
|
||||
}
|
||||
|
||||
popup_menu->addSeparator();
|
||||
|
||||
@ -742,7 +791,7 @@ void ObjectManipulator::contextMenuRequested(const QPoint &pos)
|
||||
findID->setEnabled( !FWBTree().isStandardFolder(currentObj));
|
||||
whereUsedID->setEnabled( !FWBTree().isStandardFolder(currentObj));
|
||||
}
|
||||
|
||||
|
||||
popup_menu->addSeparator();
|
||||
popup_menu->addAction( tr("Group"), this, SLOT( groupObjects() ) )
|
||||
->setDisabled(getCurrentObjectTree()->getNumSelected()==1);
|
||||
@ -855,7 +904,7 @@ void ObjectManipulator::contextMenuRequested(const QPoint &pos)
|
||||
|
||||
// if (inDeletedObjects) movID->setText( tr("Undelete...") );
|
||||
|
||||
popup_menu->exec( objTreeView->mapToGlobal( pos ) );
|
||||
popup_menu->exec(QCursor::pos());
|
||||
}
|
||||
|
||||
bool ObjectManipulator::getDeleteMenuState(FWObject *obj)
|
||||
|
||||
@ -190,6 +190,10 @@ public slots:
|
||||
|
||||
void selectionChanged(QTreeWidgetItem *cur);
|
||||
|
||||
void removeUserFolder();
|
||||
void moveItems(ObjectTreeViewItem *dest,
|
||||
const std::list<libfwbuilder::FWObject *> &items);
|
||||
|
||||
/**
|
||||
* open object obj in the editor. Does not open editor panel
|
||||
* if it is closed. Asks FWWindow permission to own editor.
|
||||
@ -268,6 +272,7 @@ public slots:
|
||||
virtual void simulateInstall();
|
||||
virtual void findWhereUsedSlot();
|
||||
|
||||
void addSubfolderSlot();
|
||||
void addNewKeywordSlot();
|
||||
void processKeywordSlot();
|
||||
|
||||
|
||||
@ -743,3 +743,66 @@ void ObjectManipulator::processKeywordSlot()
|
||||
doKeyword(getCurrentObjectTree()->getSelectedObjects(), (list[0] == "add"),
|
||||
list[1].toUtf8().constData(), m_project);
|
||||
}
|
||||
|
||||
|
||||
void ObjectManipulator::addSubfolderSlot()
|
||||
{
|
||||
const QAction *qAct = dynamic_cast<const QAction *>(sender());
|
||||
if (qAct == 0) return;
|
||||
|
||||
FWObject *obj = getCurrentObjectTree()->getCurrentObject();
|
||||
assert(obj->getId() == qAct->data().toInt());
|
||||
|
||||
QString folder = QInputDialog::getText(0, tr("Add Subfolder"),
|
||||
tr("Enter new subfolder name"));
|
||||
folder = folder.simplified();
|
||||
if (folder.isEmpty()) return;
|
||||
if (fwbdebug) {
|
||||
qDebug() << "ObjectManipulator::addSubfolder: " << folder;
|
||||
}
|
||||
|
||||
set<string> folders = stringToSet(obj->getStr("subfolders"));
|
||||
folders.insert(folder.toUtf8().constData());
|
||||
string encoded = setToString(folders);
|
||||
|
||||
obj->setStr("subfolders", encoded);
|
||||
|
||||
QTreeWidgetItem *item = getCurrentObjectTree()->currentItem();
|
||||
ObjectTreeViewItem *sub = new ObjectTreeViewItem(item);
|
||||
sub->setUserFolderParent(obj);
|
||||
sub->setUserFolderName(folder);
|
||||
sub->setText(0, folder);
|
||||
sub->setIcon(0, QIcon(LoadPixmap(":/Icons/SystemGroup/icon-tree")));
|
||||
refreshSubtree(item, sub);
|
||||
}
|
||||
|
||||
|
||||
void ObjectManipulator::removeUserFolder()
|
||||
{
|
||||
ObjectTreeViewItem *item = dynamic_cast<ObjectTreeViewItem *>
|
||||
(getCurrentObjectTree()->currentItem());
|
||||
if (item == 0 || item->getUserFolderParent() == 0) return;
|
||||
ObjectTreeViewItem *parent = dynamic_cast<ObjectTreeViewItem *>
|
||||
(item->parent());
|
||||
assert(parent != 0);
|
||||
|
||||
FWObject *parentObj = parent->getFWObject();
|
||||
set<string> folders = stringToSet(parentObj->getStr("subfolders"));
|
||||
folders.erase(item->getUserFolderName().toUtf8().constData());
|
||||
parentObj->setStr("subfolders", setToString(folders));
|
||||
|
||||
QList<QTreeWidgetItem *> children = item->takeChildren();
|
||||
while (!children.isEmpty()) {
|
||||
ObjectTreeViewItem *child = dynamic_cast<ObjectTreeViewItem *>
|
||||
(children.takeFirst());
|
||||
assert(child != 0);
|
||||
child->getFWObject()->setStr("folder", "");
|
||||
parent->addChild(child);
|
||||
}
|
||||
|
||||
parent->removeChild(item);
|
||||
delete item;
|
||||
|
||||
refreshSubtree(parent, 0);
|
||||
|
||||
}
|
||||
|
||||
@ -242,7 +242,11 @@ ObjectTreeViewItem* ObjectManipulator::insertObject(ObjectTreeViewItem *itm,
|
||||
|
||||
nitm->setIcon( 0, QIcon(pm) );
|
||||
// nitm->setIcon( 1, QIcon(pm) );
|
||||
nitm->setFlags(nitm->flags() | Qt::ItemIsDragEnabled);
|
||||
if (FWBTree().isSystem(obj)) {
|
||||
nitm->setFlags(nitm->flags() & ~Qt::ItemIsDragEnabled);
|
||||
} else {
|
||||
nitm->setFlags(nitm->flags() | Qt::ItemIsDragEnabled);
|
||||
}
|
||||
|
||||
nitm->setProperty("type", obj->getTypeName().c_str() );
|
||||
nitm->setFWObject( obj );
|
||||
@ -271,6 +275,20 @@ void ObjectManipulator::insertSubtree(ObjectTreeViewItem *itm, FWObject *obj)
|
||||
|
||||
if (FWBTree().isStandardFolder(obj)) nitm->setExpanded( st->getExpandTree());
|
||||
|
||||
QMap<QString,ObjectTreeViewItem *> folders;
|
||||
set<string> subfolders = stringToSet(obj->getStr("subfolders"));
|
||||
set<string>::const_iterator iter;
|
||||
for (iter = subfolders.begin(); iter != subfolders.end(); ++iter) {
|
||||
ObjectTreeViewItem *sub = new ObjectTreeViewItem(nitm);
|
||||
sub->setUserFolderParent(obj);
|
||||
QString name = QString::fromUtf8((*iter).c_str());
|
||||
sub->setUserFolderName(name);
|
||||
sub->setText(0, name);
|
||||
sub->setIcon(0, QIcon(LoadPixmap(":/Icons/SystemGroup/icon-tree")));
|
||||
|
||||
folders[name] = sub;
|
||||
}
|
||||
|
||||
if (Cluster::isA(obj))
|
||||
{
|
||||
for (FWObjectTypedChildIterator it = obj->findByType(StateSyncClusterGroup::TYPENAME);
|
||||
@ -313,12 +331,17 @@ void ObjectManipulator::insertSubtree(ObjectTreeViewItem *itm, FWObject *obj)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (list<FWObject*>::iterator m=obj->begin(); m!=obj->end(); m++)
|
||||
{
|
||||
FWObject *o1=*m;
|
||||
if (FWReference::cast(o1)!=NULL) continue;
|
||||
insertSubtree( nitm, o1 );
|
||||
|
||||
ObjectTreeViewItem *item = 0;
|
||||
QString folder = QString::fromUtf8(o1->getStr("folder").c_str());
|
||||
item = folders.value(folder);
|
||||
if (item == 0) item = nitm;
|
||||
|
||||
insertSubtree( item, o1 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,16 +614,15 @@ void ObjectManipulator::addLib(FWObject *lib)
|
||||
SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*) ),
|
||||
this, SLOT(selectionChanged(QTreeWidgetItem*)));
|
||||
|
||||
connect(objTreeView, SIGNAL(moveItems_sign(ObjectTreeViewItem *, const std::list<libfwbuilder::FWObject *> &)),
|
||||
this, SLOT(moveItems(ObjectTreeViewItem *, const std::list<libfwbuilder::FWObject *> &)));
|
||||
|
||||
ObjectTreeViewItem *itm1=new ObjectTreeViewItem( objTreeView );
|
||||
|
||||
itm1->setLib("");
|
||||
itm1->setExpanded(TRUE);
|
||||
|
||||
/* need to enable dragging in order to avoid object highlighting in
|
||||
* the tree when user drags mouse cursor */
|
||||
|
||||
itm1->setFlags(itm1->flags() | Qt::ItemIsDragEnabled);
|
||||
itm1->setFlags(itm1->flags() & ~Qt::ItemIsDragEnabled);
|
||||
|
||||
itm1->setText( 0, getTreeLabel(lib, 0) );
|
||||
itm1->setText( 1, getTreeLabel(lib, 1) );
|
||||
@ -682,3 +704,30 @@ void ObjectManipulator::refreshSubtree(QTreeWidgetItem *parent, QTreeWidgetItem
|
||||
getCurrentObjectTree()->update();
|
||||
}
|
||||
|
||||
void ObjectManipulator::moveItems(ObjectTreeViewItem *dest,
|
||||
const list<FWObject *> &items)
|
||||
{
|
||||
string folder;
|
||||
QTreeWidgetItem *destItem;
|
||||
if (dest->getUserFolderParent() != 0) {
|
||||
folder = dest->getUserFolderName().toUtf8().constData();
|
||||
destItem = dest;
|
||||
} else {
|
||||
folder = dest->getFWObject()->getStr("folder");
|
||||
if (FWBTree().isSystem(dest->getFWObject())) {
|
||||
destItem = dest;
|
||||
} else {
|
||||
destItem = dest->parent();
|
||||
}
|
||||
}
|
||||
|
||||
list<FWObject *>::const_iterator iter;
|
||||
for (iter = items.begin(); iter != items.end(); ++iter) {
|
||||
(*iter)->setStr("folder", folder);
|
||||
ObjectTreeViewItem *item = allItems[*iter];
|
||||
item->parent()->removeChild(item);
|
||||
destItem->addChild(item);
|
||||
}
|
||||
|
||||
refreshSubtree(destItem, 0);
|
||||
}
|
||||
|
||||
@ -43,6 +43,9 @@
|
||||
#include "fwbuilder/Firewall.h"
|
||||
#include "fwbuilder/Group.h"
|
||||
#include "fwbuilder/Interface.h"
|
||||
#include "fwbuilder/NAT.h"
|
||||
#include "fwbuilder/Routing.h"
|
||||
#include "fwbuilder/Policy.h"
|
||||
#include "fwbuilder/Resources.h"
|
||||
|
||||
#include <QAbstractItemView>
|
||||
@ -98,7 +101,7 @@ ObjectTreeView::ObjectTreeView(ProjectPanel* project,
|
||||
|
||||
setExpandsOnDoubleClick(false);
|
||||
|
||||
// setAcceptDrops( TRUE );
|
||||
setDragEnabled(true);
|
||||
item_before_drag_started=NULL;
|
||||
lastSelected = NULL;
|
||||
second_click = false;
|
||||
@ -329,17 +332,18 @@ void ObjectTreeView::focusOutEvent(QFocusEvent* ev)
|
||||
void ObjectTreeView::updateTreeIcons()
|
||||
{
|
||||
QTreeWidgetItemIterator it(this);
|
||||
while ( *it )
|
||||
for ( ; *it; ++it)
|
||||
{
|
||||
QTreeWidgetItem *itm = *it;
|
||||
ObjectTreeViewItem *otvi = dynamic_cast<ObjectTreeViewItem*>(itm);
|
||||
FWObject *obj = otvi->getFWObject();
|
||||
|
||||
/* We can have obj==0 if it's a user-create subfolder */
|
||||
if (obj == 0) continue;
|
||||
|
||||
QPixmap pm_obj;
|
||||
IconSetter::setObjectIcon(obj, &pm_obj, 0);
|
||||
itm->setIcon(0, pm_obj );
|
||||
|
||||
++it;
|
||||
}
|
||||
update();
|
||||
}
|
||||
@ -349,10 +353,11 @@ void ObjectTreeView::startDrag(Qt::DropActions supportedActions)
|
||||
QTreeWidgetItem *ovi = currentItem();
|
||||
if (ovi==NULL) return;
|
||||
|
||||
ObjectTreeViewItem *otvi=dynamic_cast<ObjectTreeViewItem*>(ovi);
|
||||
|
||||
FWObject *current_obj = getCurrentObject();
|
||||
|
||||
/* User-defined folders can't be dragged */
|
||||
if (current_obj == 0) return;
|
||||
|
||||
if (fwbdebug) qDebug("ObjectTreeView::startDrag: this: %p current_obj: %s",
|
||||
this, current_obj->getName().c_str());
|
||||
|
||||
@ -450,10 +455,6 @@ void ObjectTreeView::startDrag(Qt::DropActions supportedActions)
|
||||
if (fwbdebug) qDebug("ObjectTreeView::dragObject() this=%p visible=%d",
|
||||
this,visible);
|
||||
|
||||
FWObject *edit_obj = mw->getOpenedEditor();
|
||||
|
||||
if (fwbdebug) qDebug("ObjectTreeView::dragObject() returns !NULL");
|
||||
|
||||
drag->start(supportedActions);
|
||||
}
|
||||
|
||||
@ -463,79 +464,87 @@ void ObjectTreeView::dragEnterEvent( QDragEnterEvent *ev)
|
||||
ev->setDropAction(Qt::MoveAction);
|
||||
}
|
||||
|
||||
bool ObjectTreeView::isCurrReadOnly(QDragMoveEvent *ev)
|
||||
{
|
||||
// the tree can accept drop only if it goes into a group and if that group
|
||||
// validates the object and tree is not read-only
|
||||
QTreeWidgetItem *ovi = itemAt(ev->pos());
|
||||
|
||||
ObjectTreeViewItem *otvi=dynamic_cast<ObjectTreeViewItem*>(ovi);
|
||||
FWObject *trobj;
|
||||
if (otvi && (trobj = otvi->getFWObject()))
|
||||
return trobj->isReadOnly();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjectTreeView::dragMoveEvent( QDragMoveEvent *ev)
|
||||
{
|
||||
QWidget *fromWidget = ev->source();
|
||||
|
||||
// The source of DnD object must be the same instance of fwbuilder
|
||||
if (!fromWidget)
|
||||
{
|
||||
ev->setAccepted(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isCurrReadOnly(ev) ||
|
||||
!ev->mimeData()->hasFormat(FWObjectDrag::FWB_MIME_TYPE))
|
||||
{
|
||||
if (!fromWidget || fromWidget != this) {
|
||||
notWanted:
|
||||
ev->setAccepted(false);
|
||||
return;
|
||||
}
|
||||
|
||||
list<FWObject*> dragol;
|
||||
if (!FWObjectDrag::decode(ev, dragol))
|
||||
ev->setAccepted(false);
|
||||
for (list<FWObject*>::iterator i=dragol.begin();i!=dragol.end(); ++i)
|
||||
{
|
||||
FWObject *dragobj = *i;
|
||||
assert(dragobj!=NULL);
|
||||
ObjectTreeViewItem *dest =
|
||||
dynamic_cast<ObjectTreeViewItem *>(itemAt(ev->pos()));
|
||||
if (dest == 0) goto notWanted;
|
||||
|
||||
if (FWBTree().isSystem(dragobj))
|
||||
{
|
||||
// can not drop system folder anywhere
|
||||
ev->setAccepted(false);
|
||||
return;
|
||||
}
|
||||
list<FWObject*> objs;
|
||||
if (!FWObjectDrag::decode(ev, objs)) goto notWanted;
|
||||
|
||||
// see #1976 do not allow pasting object that has been deleted
|
||||
if (dragobj->getLibrary()->getId() == FWObjectDatabase::DELETED_OBJECTS_ID)
|
||||
{
|
||||
ev->setAccepted(false);
|
||||
return;
|
||||
bool dragIsNoop = true;
|
||||
list<FWObject *>::const_iterator iter;
|
||||
for (iter = objs.begin(); iter != objs.end(); ++iter) {
|
||||
FWObject *dragobj = *iter;
|
||||
assert(dragobj != 0);
|
||||
|
||||
if (Interface::cast(dragobj) != 0 ||
|
||||
Interface::cast(dragobj->getParent()) != 0 ||
|
||||
Policy::cast(dragobj) != 0 ||
|
||||
NAT::cast(dragobj) != 0 ||
|
||||
Routing::cast(dragobj) != 0) goto notWanted;
|
||||
|
||||
/* See if destination is a user folder */
|
||||
if (dest->getUserFolderParent() != 0) {
|
||||
/* Dragged object has to match parent of user folder */
|
||||
if (dest->getUserFolderParent() != dragobj->getParent()) {
|
||||
goto notWanted;
|
||||
}
|
||||
|
||||
/* Are we dragging within the same user folder? */
|
||||
if (dest->getUserFolderName() !=
|
||||
QString::fromUtf8(dragobj->getStr("folder").c_str())) {
|
||||
dragIsNoop = false;
|
||||
}
|
||||
} else {
|
||||
/* OK to drag onto parent itself, or object that shares parent */
|
||||
if (dragobj->getParent() != dest->getFWObject() &&
|
||||
dragobj->getParent() != dest->getFWObject()->getParent()) {
|
||||
goto notWanted;
|
||||
}
|
||||
|
||||
/* Are we dragging to a new place? */
|
||||
if ((FWBTree().isSystem(dest->getFWObject()) &&
|
||||
dragobj->getStr("folder") != "") ||
|
||||
(dest->getFWObject()->getStr("folder") !=
|
||||
dragobj->getStr("folder"))) {
|
||||
dragIsNoop = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dragIsNoop) goto notWanted;
|
||||
|
||||
ev->setDropAction(Qt::MoveAction);
|
||||
ev->setAccepted(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* See ticket #483: d&d of objects inside the tree should not be allowed
|
||||
*/
|
||||
|
||||
void ObjectTreeView::dropEvent(QDropEvent *ev)
|
||||
{
|
||||
ev->setAccepted(false);
|
||||
return;
|
||||
}
|
||||
ObjectTreeViewItem *dest =
|
||||
dynamic_cast<ObjectTreeViewItem *>(itemAt(ev->pos()));
|
||||
if (dest == 0) {
|
||||
notWanted:
|
||||
ev->setAccepted(false);
|
||||
return;
|
||||
}
|
||||
|
||||
FWObject *ObjectTreeView::getDropTarget(QDropEvent *ev, FWObject*)
|
||||
{
|
||||
QTreeWidgetItem *ovi = itemAt(ev->pos());
|
||||
list<FWObject*> objs;
|
||||
if (!FWObjectDrag::decode(ev, objs)) goto notWanted;
|
||||
|
||||
ObjectTreeViewItem *otvi = dynamic_cast<ObjectTreeViewItem*>(ovi);
|
||||
if (otvi) return otvi->getFWObject();
|
||||
else return NULL;
|
||||
emit moveItems_sign(dest, objs);
|
||||
ev->setAccepted(true);
|
||||
}
|
||||
|
||||
void ObjectTreeView::dragLeaveEvent( QDragLeaveEvent *ev)
|
||||
@ -547,6 +556,9 @@ void ObjectTreeView::dragLeaveEvent( QDragLeaveEvent *ev)
|
||||
|
||||
void ObjectTreeView::mouseMoveEvent( QMouseEvent * e )
|
||||
{
|
||||
/* This stops highlighting of stuff in the tree when the user
|
||||
clicks and tries to drag something non-draggable. */
|
||||
if (state() == DragSelectingState) return;
|
||||
QTreeWidget::mouseMoveEvent(e);
|
||||
if (e==NULL) return;
|
||||
}
|
||||
@ -745,6 +757,9 @@ void ObjectTreeView::itemSelectionChanged()
|
||||
QTreeWidgetItem *itm = (*it);
|
||||
ObjectTreeViewItem *otvi = dynamic_cast<ObjectTreeViewItem*>(itm);
|
||||
|
||||
FWObject *obj = otvi->getFWObject();
|
||||
if (obj == 0) continue;
|
||||
|
||||
selectedObjects.push_back(otvi->getFWObject());
|
||||
|
||||
if (fwbdebug) qDebug(
|
||||
@ -783,14 +798,14 @@ void ObjectTreeView::ExpandTreeItems(const set<int> &ids)
|
||||
qDebug() << "ObjectTreeView::ExpandTreeItems()";
|
||||
|
||||
QTreeWidgetItemIterator it(this);
|
||||
while ( *it )
|
||||
for ( ; *it; ++it)
|
||||
{
|
||||
QTreeWidgetItem *itm = *it;
|
||||
ObjectTreeViewItem *otvi=dynamic_cast<ObjectTreeViewItem*>(itm);
|
||||
FWObject *obj = otvi->getFWObject();
|
||||
if (obj == 0) continue;
|
||||
if (ids.count(obj->getId()))
|
||||
itm->setExpanded(true);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
@ -852,10 +867,9 @@ void ObjectTreeView::setFilter(QString text)
|
||||
if (fwbdebug)
|
||||
qDebug() << "ObjectTreeView::setFilter " << text;
|
||||
|
||||
QTreeWidgetItemIterator wit(this);
|
||||
while (*wit)
|
||||
{
|
||||
for (QTreeWidgetItemIterator wit(this); *wit; ++wit) {
|
||||
ObjectTreeViewItem *otvi = dynamic_cast<ObjectTreeViewItem *>(*wit);
|
||||
if (otvi->getUserFolderParent() != 0) continue;
|
||||
FWObject *obj = otvi->getFWObject();
|
||||
|
||||
if (filterMatches(text, otvi, obj)) {
|
||||
@ -869,8 +883,6 @@ void ObjectTreeView::setFilter(QString text)
|
||||
} else {
|
||||
(*wit)->setHidden(true);
|
||||
}
|
||||
|
||||
++wit;
|
||||
}
|
||||
|
||||
if (!text.isEmpty()) this->expandAll();
|
||||
|
||||
@ -45,6 +45,7 @@ namespace libfwbuilder {
|
||||
};
|
||||
|
||||
class ProjectPanel;
|
||||
class ObjectTreeViewItem;
|
||||
|
||||
class ObjectTreeView : public QTreeWidget
|
||||
{
|
||||
@ -66,11 +67,6 @@ class ObjectTreeView : public QTreeWidget
|
||||
std::vector<libfwbuilder::FWObject*> selectedObjects;
|
||||
ProjectPanel* m_project;
|
||||
|
||||
|
||||
bool isCurrReadOnly(QDragMoveEvent *ev);
|
||||
libfwbuilder::FWObject *getDropTarget(
|
||||
QDropEvent *ev, libfwbuilder::FWObject* dragobj);
|
||||
|
||||
QSet<QTreeWidgetItem*> resolveChildren(QTreeWidgetItem*);
|
||||
|
||||
QSet<QTreeWidgetItem*> resolveParents(QTreeWidgetItem*);
|
||||
@ -169,6 +165,8 @@ protected:
|
||||
void objectDropped_sign(libfwbuilder::FWObject *);
|
||||
void deleteObject_sign(libfwbuilder::FWObject *);
|
||||
void contextMenuRequested_sign(const QPoint&);
|
||||
void moveItems_sign(ObjectTreeViewItem *dest,
|
||||
const std::list<libfwbuilder::FWObject *> &items);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -80,59 +80,31 @@ QVariant ObjectTreeViewItem::data(int column, int role) const
|
||||
return QTreeWidgetItem::data(column, role);
|
||||
}
|
||||
|
||||
bool ObjectTreeViewItem::operator<( const QTreeWidgetItem & other ) const
|
||||
|
||||
static int getRank(FWObject *obj)
|
||||
{
|
||||
int rank1 = -1;
|
||||
int rank2 = -1;
|
||||
const ObjectTreeViewItem * otvi =
|
||||
dynamic_cast<const ObjectTreeViewItem*>(& other);
|
||||
/* User-defined folders are first */
|
||||
if (obj == 0) return 0;
|
||||
|
||||
if (Interface::cast(obj) != 0) return 5;
|
||||
if (Policy::cast(obj) != 0) return 2;
|
||||
if (NAT::cast(obj) != 0) return 3;
|
||||
if (Routing::cast(obj) != 0) return 4;
|
||||
|
||||
if (otvi->objptr==NULL) return true ;
|
||||
if (objptr==NULL) return true ;
|
||||
|
||||
if (Interface::cast(otvi->objptr)!=NULL)
|
||||
{
|
||||
rank1=3;
|
||||
}
|
||||
if (Policy::cast(otvi->objptr)!=NULL)
|
||||
{
|
||||
rank1=0;
|
||||
}
|
||||
if (NAT::cast(otvi->objptr)!=NULL)
|
||||
{
|
||||
rank1=1;
|
||||
}
|
||||
if (Routing::cast(otvi->objptr)!=NULL)
|
||||
{
|
||||
rank1=2;
|
||||
}
|
||||
if (Interface::cast(objptr)!=NULL)
|
||||
{
|
||||
rank2=3;
|
||||
}
|
||||
if (Policy::cast(objptr)!=NULL)
|
||||
{
|
||||
rank2=0;
|
||||
}
|
||||
if (NAT::cast(objptr)!=NULL)
|
||||
{
|
||||
rank2=1;
|
||||
}
|
||||
if (Routing::cast(objptr)!=NULL)
|
||||
{
|
||||
rank2=2;
|
||||
}
|
||||
|
||||
if (rank1==rank2)
|
||||
{
|
||||
QString s1 = objptr->getName().c_str();
|
||||
QString s2 = otvi->objptr->getName ().c_str();
|
||||
//return ( s1 < s2);
|
||||
return ( s1.toLower() < s2.toLower());
|
||||
}
|
||||
if (rank1>rank2)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool ObjectTreeViewItem::operator<(const QTreeWidgetItem &other) const
|
||||
{
|
||||
const ObjectTreeViewItem *otvi =
|
||||
dynamic_cast<const ObjectTreeViewItem*>(&other);
|
||||
|
||||
int rank1 = getRank(otvi->objptr);
|
||||
int rank2 = getRank(objptr);
|
||||
|
||||
if (rank1 == rank2)
|
||||
return text(0).toLower() < otvi->text(0).toLower();
|
||||
|
||||
return rank1 > rank2;
|
||||
}
|
||||
|
||||
@ -43,21 +43,28 @@ class ObjectTreeView;
|
||||
class ObjectTreeViewItem : public QTreeWidgetItem {
|
||||
|
||||
libfwbuilder::FWObject *objptr;
|
||||
libfwbuilder::FWObject *userFolderParent;
|
||||
QString userFolderName;
|
||||
QMap<QString, QString> props;
|
||||
QString lib;
|
||||
|
||||
public:
|
||||
|
||||
ObjectTreeViewItem(QTreeWidget *parent) : QTreeWidgetItem(parent) {
|
||||
objptr=NULL;
|
||||
}
|
||||
ObjectTreeViewItem(QTreeWidget *parent) :
|
||||
QTreeWidgetItem(parent), objptr(0), userFolderParent(0) {}
|
||||
|
||||
ObjectTreeViewItem(QTreeWidgetItem *parent) : QTreeWidgetItem(parent){
|
||||
objptr=NULL;
|
||||
}
|
||||
ObjectTreeViewItem(QTreeWidgetItem *parent) :
|
||||
QTreeWidgetItem(parent), objptr(0), userFolderParent(0) {}
|
||||
|
||||
libfwbuilder::FWObject *getFWObject() const { return objptr; }
|
||||
libfwbuilder::FWObject *getUserFolderParent() { return userFolderParent; }
|
||||
void setFWObject(libfwbuilder::FWObject *obj) { objptr=obj; }
|
||||
void setUserFolderParent(libfwbuilder::FWObject *obj) {
|
||||
userFolderParent = obj;
|
||||
}
|
||||
|
||||
void setUserFolderName(const QString &name) { userFolderName = name; }
|
||||
const QString &getUserFolderName() { return userFolderName; }
|
||||
|
||||
ObjectTreeView* getTree();
|
||||
|
||||
|
||||
@ -1203,7 +1203,6 @@ bool RuleSetModel::isGroup(const QModelIndex &index) const
|
||||
|
||||
void RuleSetModel::resetAllSizes()
|
||||
{
|
||||
qDebug() << "resetAllSizes()";
|
||||
emit layoutAboutToBeChanged ();
|
||||
root->resetAllSizes();
|
||||
emit layoutChanged ();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user