diff --git a/build_num b/build_num index e5311a19a..aa94f891f 100644 --- a/build_num +++ b/build_num @@ -1 +1 @@ -#define BUILD_NUM 3205 +#define BUILD_NUM 3211 diff --git a/doc/ChangeLog b/doc/ChangeLog index 251338cdd..e1180a2a5 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,11 @@ +2010-08-05 Vadim Kurland + + * ProjectPanel_events.cpp (event): fixed #1660 "Crash when + cut-and-pasting firewall between libraries". GUI crashed if user + performed the following sequence: cut an object, switch to a + different object library, try to paste using keyboard shortcut + Ctrl-V while library object was selected in the tree. + 2010-08-04 Vadim Kurland * IPTImporter.cpp (IPTImporter::finalize): fixed #1664 "Policy diff --git a/src/gui/FWBTree.cpp b/src/gui/FWBTree.cpp index 7d1304847..4b7686288 100644 --- a/src/gui/FWBTree.cpp +++ b/src/gui/FWBTree.cpp @@ -484,7 +484,8 @@ void FWBTree::getStandardSlotForObject(const QString &objType, * this method finds standard system folder for an object of a given * type in a given library. This method implemented our standard tree * structure (the one that is created in the method createNewLibrary) - */FWObject* FWBTree::getStandardSlotForObject(FWObject* lib,const QString &objType) + */ +FWObject* FWBTree::getStandardSlotForObject(FWObject* lib,const QString &objType) { QString path = systemGroupPaths[objType]; diff --git a/src/gui/FWWindow.cpp b/src/gui/FWWindow.cpp index 01e5e0935..ad5cf1fed 100644 --- a/src/gui/FWWindow.cpp +++ b/src/gui/FWWindow.cpp @@ -539,8 +539,10 @@ void FWWindow::startupLoad() stdlg->run(); } - prepareFileMenu(); - updateGlobalToolbar(); + QCoreApplication::postEvent(mw, new updateGUIStateEvent()); + + //prepareFileMenu(); + //updateGlobalToolbar(); //prepareRulesMenu(); } @@ -573,8 +575,10 @@ void FWWindow::fileNew() if (proj->fileNew()) { showSub(proj.get()); - prepareFileMenu(); - updateGlobalToolbar(); + QCoreApplication::postEvent(mw, new updateGUIStateEvent()); + + //prepareFileMenu(); + //updateGlobalToolbar(); //prepareRulesMenu(); proj.release(); } @@ -650,9 +654,11 @@ void FWWindow::fileOpen() updateOpenRecentMenu(file_name); // reset actions, including Save() which should now // be inactive - prepareFileMenu(); + QCoreApplication::postEvent(mw, new updateGUIStateEvent()); + + //prepareFileMenu(); //prepareRulesMenu(); - updateGlobalToolbar(); + //updateGlobalToolbar(); QCoreApplication::postEvent(this, new updateSubWindowTitlesEvent()); } else @@ -726,9 +732,11 @@ void FWWindow::fileClose() // reset actions, including Save() which should now // be inactive - prepareFileMenu(); + QCoreApplication::postEvent(mw, new updateGUIStateEvent()); + + //prepareFileMenu(); //prepareRulesMenu(); - updateGlobalToolbar(); + //updateGlobalToolbar(); } if (fwbdebug) qDebug("subWindowList().size()=%d", @@ -1037,9 +1045,11 @@ void FWWindow::subWindowActivated(QMdiSubWindow *subwindow) ProjectPanel *pp = dynamic_cast(subwindow->widget()); if (pp) { - prepareFileMenu(); + QCoreApplication::postEvent(mw, new updateGUIStateEvent()); + + //prepareFileMenu(); //prepareRulesMenu(); - updateGlobalToolbar(); + //updateGlobalToolbar(); pp->setActive(); if (isEditorVisible()) openEditor(pp->getSelectedObject()); @@ -1125,80 +1135,87 @@ bool FWWindow::event(QEvent *event) switch (event->type() - QEvent::User) { - case OPEN_OBJECT_IN_EDITOR_EVENT: + case UPDATE_GUI_STATE_EVENT: + prepareFileMenu(); + prepareEditMenu(); + updateGlobalToolbar(); + // do not return, let ProjectPanel process the same event as well + break; + + case OPEN_OBJECT_IN_EDITOR_EVENT: + { + if (pp && obj) { - if (pp && obj) + openEditor(obj); + // pp->editObject(obj); + pp->mdiWindow->update(); + } + ev->accept(); + return true; + } + + case OPEN_OPT_OBJECT_IN_EDITOR_EVENT: + { + if (pp && obj) + { + openOptEditor( + obj, + dynamic_cast(event)->opt_code); + // pp->editObject(obj); + pp->mdiWindow->update(); + } + ev->accept(); + return true; + } + + case UPDATE_SUBWINDOW_TITLES_EVENT: + { + QMap short_name_counters; + QMap short_titles; + QMap long_titles; + + foreach(QMdiSubWindow* sw, m_mainWindow->m_space->subWindowList()) + { + ProjectPanel * pp = dynamic_cast(sw->widget()); + if (pp!=NULL) { - openEditor(obj); - // pp->editObject(obj); - pp->mdiWindow->update(); + // string returned by getPageTitle() may also + // include RCS revision number. Compare only + // file name, without the path and rev number + // to make sure we show long paths for two + // subwindows where file names are identical, + // regardless of the RCS revision number. + QString file_name = pp->getFileName(); // full path + QFileInfo fi(file_name); + QString short_name = fi.fileName(); + int c = short_name_counters[short_name]; + short_name_counters[short_name] = c + 1; + + short_titles[sw] = pp->getPageTitle(false); + long_titles[sw] = pp->getPageTitle(true); + + if (fwbdebug) + qDebug() << "Subwindow " << sw + << "file_name " << file_name + << "short_name " << short_name + << "short_name_counter " << c + << "short_title " << short_titles[sw] + << "long_title " << long_titles[sw]; + } - ev->accept(); - return true; } - case OPEN_OPT_OBJECT_IN_EDITOR_EVENT: + foreach(QMdiSubWindow* sw, m_mainWindow->m_space->subWindowList()) { - if (pp && obj) - { - openOptEditor( - obj, - dynamic_cast(event)->opt_code); - // pp->editObject(obj); - pp->mdiWindow->update(); - } - ev->accept(); - return true; - } - - case UPDATE_SUBWINDOW_TITLES_EVENT: - { - QMap short_name_counters; - QMap short_titles; - QMap long_titles; - - foreach(QMdiSubWindow* sw, m_mainWindow->m_space->subWindowList()) - { - ProjectPanel * pp = dynamic_cast(sw->widget()); - if (pp!=NULL) - { - // string returned by getPageTitle() may also - // include RCS revision number. Compare only - // file name, without the path and rev number - // to make sure we show long paths for two - // subwindows where file names are identical, - // regardless of the RCS revision number. - QString file_name = pp->getFileName(); // full path - QFileInfo fi(file_name); - QString short_name = fi.fileName(); - int c = short_name_counters[short_name]; - short_name_counters[short_name] = c + 1; - - short_titles[sw] = pp->getPageTitle(false); - long_titles[sw] = pp->getPageTitle(true); - - if (fwbdebug) - qDebug() << "Subwindow " << sw - << "file_name " << file_name - << "short_name " << short_name - << "short_name_counter " << c - << "short_title " << short_titles[sw] - << "long_title " << long_titles[sw]; - - } - } - - foreach(QMdiSubWindow* sw, m_mainWindow->m_space->subWindowList()) - { - QString short_name = short_titles[sw]; - if (short_name_counters[short_name] > 1) - sw->setWindowTitle(long_titles[sw]); - else - sw->setWindowTitle(short_titles[sw]); - } - ev->accept(); - return true; + QString short_name = short_titles[sw]; + if (short_name_counters[short_name] > 1) + sw->setWindowTitle(long_titles[sw]); + else + sw->setWindowTitle(short_titles[sw]); } + ev->accept(); + return true; + } } // dispatch event to all projectpanel windows diff --git a/src/gui/FWWindow_wrappers.cpp b/src/gui/FWWindow_wrappers.cpp index 19d0e3189..c83e35f3a 100644 --- a/src/gui/FWWindow_wrappers.cpp +++ b/src/gui/FWWindow_wrappers.cpp @@ -95,7 +95,9 @@ void FWWindow::fileSave() if (activeProject()) { activeProject()->fileSave(); - prepareFileMenu(); + QCoreApplication::postEvent(this, new updateGUIStateEvent()); + + //prepareFileMenu(); } } @@ -104,7 +106,9 @@ void FWWindow::fileSaveAs() if (activeProject()) { activeProject()->fileSaveAs(); - prepareFileMenu(); + QCoreApplication::postEvent(this, new updateGUIStateEvent()); + + //prepareFileMenu(); } } @@ -115,7 +119,9 @@ void FWWindow::fileCommit() activeProject()->fileCommit(); // reset actions, including Save() which should now // be inactive - prepareFileMenu(); + QCoreApplication::postEvent(this, new updateGUIStateEvent()); + + //prepareFileMenu(); } } @@ -128,9 +134,11 @@ void FWWindow::fileDiscard() if (activeProject()) { activeProject()->fileDiscard(); - prepareFileMenu(); + QCoreApplication::postEvent(this, new updateGUIStateEvent()); + + //prepareFileMenu(); //prepareRulesMenu(); - updateGlobalToolbar(); + //updateGlobalToolbar(); } } @@ -139,7 +147,9 @@ void FWWindow::fileAddToRCS() if (activeProject()) { activeProject()->fileAddToRCS(); - prepareFileMenu(); + QCoreApplication::postEvent(this, new updateGUIStateEvent()); + + //prepareFileMenu(); } } @@ -168,9 +178,11 @@ void FWWindow::fileImport() if (activeProject()) { activeProject()->fileImport(); - prepareFileMenu(); + QCoreApplication::postEvent(this, new updateGUIStateEvent()); + + //prepareFileMenu(); //prepareRulesMenu(); - updateGlobalToolbar(); + //updateGlobalToolbar(); } } diff --git a/src/gui/GroupObjectDialog.cpp b/src/gui/GroupObjectDialog.cpp index 0907af46b..79b83c132 100644 --- a/src/gui/GroupObjectDialog.cpp +++ b/src/gui/GroupObjectDialog.cpp @@ -518,13 +518,29 @@ void GroupObjectDialog::validate(bool *res) void GroupObjectDialog::applyChanges() { - if (fwbdebug) qDebug("GroupObjectDialog::applyChanges"); + if (fwbdebug) + qDebug() << "GroupObjectDialog::applyChanges" + << "checkpoint 1" + << "root->isDirty()=" << obj->getRoot()->isDirty(); std::auto_ptr cmd( new FWCmdChange(m_project, obj)); FWObject* new_state = cmd->getNewState(); string oldname = obj->getName(); - new_state->setName( string(m_dialog->obj_name->text().toUtf8().constData()) ); + string newname = string(m_dialog->obj_name->text().toUtf8().constData()); + if (oldname != newname) + { + if (fwbdebug) + qDebug() << "oldname=" << oldname.c_str() + << "newname=" << newname.c_str(); + new_state->setName(newname); + } + + if (fwbdebug) + qDebug() << "GroupObjectDialog::applyChanges" + << "checkpoint 2" + << "root->isDirty()=" << obj->getRoot()->isDirty(); + new_state->setComment( string(m_dialog->comment->toPlainText().toUtf8().constData()) ); diff --git a/src/gui/ObjectManipulator.cpp b/src/gui/ObjectManipulator.cpp index 2c115d499..76b991f9d 100644 --- a/src/gui/ObjectManipulator.cpp +++ b/src/gui/ObjectManipulator.cpp @@ -827,6 +827,19 @@ void ObjectManipulator::getMenuState(bool haveMoveTargets, { if (fwbdebug) qDebug("ObjectManipulator::getMenuState"); + inDeletedObjects = false; + + if (m_project->db() == NULL) + { + dupMenuItem = false; + moveMenuItem = false; + copyMenuItem = false; + pasteMenuItem = false; + delMenuItem = false; + newMenuItem = false; + return; + } + dupMenuItem = true; moveMenuItem = true; copyMenuItem = true; @@ -834,8 +847,6 @@ void ObjectManipulator::getMenuState(bool haveMoveTargets, delMenuItem = true; newMenuItem = true; - inDeletedObjects = false; - FWObject *del_obj_library = m_project->db()->findInIndex( FWObjectDatabase::DELETED_OBJECTS_ID); @@ -1000,6 +1011,11 @@ FWObject* ObjectManipulator::prepareForInsertion(FWObject *target, FWObject *obj FWObject *ta = target; if (IPv4::isA(ta) || IPv6::isA(ta)) ta = ta->getParent(); + + if (Library::isA(target)) + ta = FWBTree().getStandardSlotForObject(target, + obj->getTypeName().c_str()); + QString err; if (! FWBTree().validateForInsertion(ta, obj, err)) { @@ -1275,6 +1291,8 @@ void ObjectManipulator::changeFirstNotSystemLib() void ObjectManipulator::libChanged(int ln) { + if (fwbdebug) qDebug() << "ObjectManipulator::libChanged ln=" << ln; + previous_lib_index = ln; QTreeWidget *lv = idxToTrees[ln]; @@ -1289,29 +1307,33 @@ void ObjectManipulator::libChanged(int ln) else assert(FALSE); } - //currentObj = otvi->getFWObject(); + showObjectInTree( otvi ); -// Experiment: switching libraries does not open new lib in the editor +// switching libraries does not open new lib in the editor // if (mw->isEditorVisible()) mw->openEditor(getSelectedObject()); - updateCreateObjectMenu( idxToLibs[ln] ); + //updateCreateObjectMenu( idxToLibs[ln] ); + + QCoreApplication::postEvent(mw, new updateGUIStateEvent()); + return; } void ObjectManipulator::updateCreateObjectMenu(FWObject* lib) { - bool f = + bool f = lib == NULL || lib->getId()==FWObjectDatabase::TEMPLATE_LIB_ID || lib->getId()==FWObjectDatabase::DELETED_OBJECTS_ID || lib->isReadOnly(); - emit libraryAccessChanged(!f); - m_objectManipulator->newButton->setEnabled( !f ); + bool new_object_op_possible = !f; + emit libraryAccessChanged(new_object_op_possible); + m_objectManipulator->newButton->setEnabled(new_object_op_possible); QAction *noa = (QAction*)(mw->findChild("newObjectAction")); - noa->setEnabled( !f ); + noa->setEnabled(new_object_op_possible); } -FWObject* ObjectManipulator::getCurrentLib() +FWObject* ObjectManipulator::getCurrentLib() { int idx = m_objectManipulator->libs->currentIndex(); if (idx == -1 ) return NULL; diff --git a/src/gui/ObjectManipulator.h b/src/gui/ObjectManipulator.h index 3530cd62d..b57059631 100644 --- a/src/gui/ObjectManipulator.h +++ b/src/gui/ObjectManipulator.h @@ -126,7 +126,6 @@ class ObjectManipulator : public QWidget int getIdxForLib(libfwbuilder::FWObject*); void removeLib(int idx); - void updateCreateObjectMenu(libfwbuilder::FWObject* lib); void makeNameUnique(libfwbuilder::FWObject* p,libfwbuilder::FWObject* obj); @@ -325,8 +324,10 @@ public: void autoRenameChildren(libfwbuilder::FWObject *obj, const QString &oldName); - void updateObjectInTree(libfwbuilder::FWObject *obj, bool subtree=false); + void updateObjectInTree(libfwbuilder::FWObject *obj, bool subtree=false); + void updateCreateObjectMenu(libfwbuilder::FWObject* lib); + ObjectTreeView* getCurrentObjectTree(); libfwbuilder::FWObject* getSelectedObject(); diff --git a/src/gui/ProjectPanel_events.cpp b/src/gui/ProjectPanel_events.cpp index e861d993a..ccfe88924 100644 --- a/src/gui/ProjectPanel_events.cpp +++ b/src/gui/ProjectPanel_events.cpp @@ -75,6 +75,13 @@ bool ProjectPanel::event(QEvent *event) << "object:" << ((obj!=NULL) ? QString::fromUtf8(obj->getName().c_str()) : ""); + if (event_code == UPDATE_GUI_STATE_EVENT && mdiWindow != NULL) + { + m_panel->om->updateCreateObjectMenu(getCurrentLib()); + ev->accept(); + return true; + } + if ((rcs && rcs->getFileName() == data_file) || (!rcs && data_file.isEmpty())) { @@ -115,10 +122,6 @@ bool ProjectPanel::event(QEvent *event) // This event does not trigger any updates in the UI, // this purely data structure update event. - mw->prepareFileMenu(); - mw->prepareEditMenu(); - mw->updateGlobalToolbar(); - FWObject *p = obj; while (p && Firewall::cast(p)==NULL) p = p->getParent(); Firewall *f = Firewall::cast(p); @@ -129,10 +132,12 @@ bool ProjectPanel::event(QEvent *event) { f->updateLastModifiedTimestamp(); QCoreApplication::postEvent( - mw, new updateObjectInTreeEvent(data_file, - f->getId())); + mw, new updateObjectInTreeEvent(data_file, f->getId())); } registerModifiedObject(obj); + + QCoreApplication::postEvent(mw, new updateGUIStateEvent()); + ev->accept(); return true; } @@ -405,6 +410,7 @@ bool ProjectPanel::event(QEvent *event) } ev->accept(); return true; + } } return false; diff --git a/src/gui/ProjectPanel_file_ops.cpp b/src/gui/ProjectPanel_file_ops.cpp index 0772b12b1..003d32963 100644 --- a/src/gui/ProjectPanel_file_ops.cpp +++ b/src/gui/ProjectPanel_file_ops.cpp @@ -1436,7 +1436,9 @@ void ProjectPanel::save() db()->setDirty(false); // and reset actions, including Save() which should now // be inactive - mw->prepareFileMenu(); + QCoreApplication::postEvent(mw, new updateGUIStateEvent()); + + //mw->prepareFileMenu(); } else { QApplication::setOverrideCursor(QCursor( Qt::WaitCursor)); diff --git a/src/gui/events.h b/src/gui/events.h index f0d2133e1..655f9ea76 100644 --- a/src/gui/events.h +++ b/src/gui/events.h @@ -65,7 +65,8 @@ enum EVENT_CODES { CLOSE_OBJECT_EVENT , OBJECT_NAME_CHANGED_EVENT, OPEN_LIBRARY_FOR_OBJECT_EVENT, - UPDATE_SUBWINDOW_TITLES_EVENT + UPDATE_SUBWINDOW_TITLES_EVENT, + UPDATE_GUI_STATE_EVENT }; @@ -358,6 +359,19 @@ public: {} }; +/* + * This event is processed by FWWindow class and updates all menus and + * toolbar buttins + */ +class updateGUIStateEvent : public fwbUpdateEvent { +public: + updateGUIStateEvent() : + fwbUpdateEvent("", -1, + QEvent::Type(QEvent::User + UPDATE_GUI_STATE_EVENT), + "updateGUIStateEvent") + {} +}; +