1
0
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:
Theron Tock 2011-06-16 14:49:06 -07:00
parent aacc4016cd
commit 54f6bae48f
14 changed files with 392 additions and 214 deletions

View File

@ -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 -->

View File

@ -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 -->

View File

@ -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)
{

View File

@ -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;
}
}

View File

@ -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

View File

@ -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)

View File

@ -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();

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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();

View File

@ -1203,7 +1203,6 @@ bool RuleSetModel::isGroup(const QModelIndex &index) const
void RuleSetModel::resetAllSizes()
{
qDebug() << "resetAllSizes()";
emit layoutAboutToBeChanged ();
root->resetAllSizes();
emit layoutChanged ();