// ************************************************************************* // // Copyleft 2004-2007 Bruno PAGES . // // ************************************************************************* // // Copyleft 2004-2007 Bruno PAGES . // // This file is part of the BOUML Uml Toolkit. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public 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. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // e-mail : bouml@free.fr // home : http://bouml.free.fr // // ************************************************************************* #ifdef WIN32 #pragma warning (disable: 4150) #endif #include #include #include #include #include #include "BrowserView.h" #include "BrowserNode.h" #include "BrowserRelation.h" #include "BrowserSimpleRelation.h" #include "SimpleRelationData.h" #include "BrowserAttribute.h" #include "BrowserClassInstance.h" #include "BasicData.h" #include "BrowserPackage.h" #include "BrowserView.h" #include "UmlWindow.h" #include "MyInputDialog.h" #include "BasicDialog.h" #include "UmlGlobal.h" #include "myio.h" #include "ToolCom.h" #include "SaveProgress.h" #include "strutil.h" #include "DialogUtil.h" #include "mu.h" #ifdef WIN32 #define strcasecmp _stricmp #endif QList BrowserNode::marked_list; static BrowserPackage * UndefinedNodePackage; bool BrowserNode::show_stereotypes = TRUE; unsigned BrowserNode::edition_number; // to solve problem on some windows configurations bool BrowserNode::popup_menu_active; // indicate saving progress SaveProgress * BrowserNode::save_progress; int BrowserNode::must_be_saved_counter; int BrowserNode::already_saved; BrowserNode::BrowserNode(QString s, BrowserView * parent) : QListViewItem(parent, s), name(s), is_deleted(FALSE), is_modified(FALSE), is_new(TRUE), is_read_only(FALSE), is_edited(FALSE), is_marked(FALSE), is_saveable(TRUE), is_defined(FALSE) { } BrowserNode::BrowserNode(QString s, BrowserNode * parent) : QListViewItem(parent, s), name(s), is_deleted(FALSE), is_modified(FALSE), is_new(TRUE), is_read_only(FALSE), is_edited(FALSE), is_marked(FALSE), is_saveable(TRUE), is_defined(FALSE) { // move it at end QListViewItem * child = parent->firstChild(); while (child->nextSibling()) child = child->nextSibling(); if (child != this) moveItem(child); } BrowserNode::BrowserNode() : QListViewItem(UndefinedNodePackage, ""), is_deleted(FALSE), is_modified(FALSE), is_new(TRUE), is_read_only(FALSE), is_edited(FALSE), is_marked(FALSE), is_saveable(TRUE), is_defined(FALSE) { } BrowserNode::~BrowserNode() { // in case it is the current commented object UmlWindow::set_commented(0); if (is_marked) marked_list.removeRef(this); } void BrowserNode::delete_it() { if (! deletedp()) { if (UndefinedNodePackage == 0) { // not during a read QString warning; if (!delete_internal(warning)) { warning = full_name() + " cannot be deleted because :" + warning; warn(warning); } else // mark modified to not delete the associated file(s) // on exit if no save was done before is_modified = TRUE; } else { // during a read : no check is_deleted = TRUE; if (is_marked) { marked_list.removeRef(this); is_marked = FALSE; } if (is_writable()) package_modified(); if (get_data() != 0) get_data()->delete_it(); // delete the sub elts QListViewItem * child; for (child = firstChild(); child != 0; child = child->nextSibling()) if (! ((BrowserNode *) child)->deletedp()) ((BrowserNode *) child)->delete_it(); setOpen(FALSE); must_be_deleted(); } } } bool BrowserNode::delete_internal(QString & warning) { if (deletedp()) return TRUE; if (!is_writable() && !root_permission()) { warning += "\n " + full_name() + " is read-only"; return FALSE; } static QList targetof; static bool made = FALSE; bool made_here; if (!made) { made = TRUE; made_here = TRUE; referenced_by(targetof); } else made_here = FALSE; bool ro = FALSE; if (!root_permission()) { QListIterator it(targetof); BrowserNode * r; while ((r = it.current()) != 0) { if (!r->is_writable()) { ro = TRUE; warning += "\n " + full_name() + ((r->get_type() == UmlComponent) ? " referenced bu the read-only component " : " is the target of the read-only relation ") + r->full_name(); } ++it; } } if (made_here) { made = FALSE; targetof.clear(); } if (ro) return FALSE; // sub elts QListViewItem * child; bool ok = TRUE; for (child = firstChild(); child != 0; child = child->nextSibling()) ok &= ((BrowserNode *) child)->delete_internal(warning); if (ok) { is_deleted = TRUE; if (is_marked) { marked_list.removeRef(this); is_marked = FALSE; } get_data()->delete_it(); repaint(); package_modified(); } return ok; } const char * BrowserNode::get_comment() const { return comment; } void BrowserNode::set_comment(const char * c) { comment = c; } void BrowserNode::referenced_by(QList & l) { BrowserSimpleRelation::compute_referenced_by(l, this); } AType BrowserNode::class_association() const { AType r; return r; } const char * BrowserNode::constraint() const { return ""; } // undelete entry operation void BrowserNode::undelete(bool rec) { QString warning; QString renamed; if (undelete(rec, warning, renamed) && rec) { // Redo it because now all classes are undeleted but it is // possible that some relations was not undeleted because // at least one of the two extremities was not undeleted warning = QString::null; undelete(rec, warning, renamed); } if (!warning.isEmpty()) warning = "

Some items cannot be undeleted :\n

    " + warning + "

"; if (! renamed.isEmpty()) { warning += "

Some items are renamed :\n

    " + renamed + "

"; } if (!warning.isEmpty()) warn(warning); } // undelete internal processing bool BrowserNode::undelete(bool rec, QString & warning, QString & renamed) { bool result; if (deletedp()) { // undelete the node QString s = name; bool ren = FALSE; while (((BrowserNode *)parent()) ->wrong_child_name(s, get_type(), allow_spaces(), allow_empty())) { s = "_" + s; ren = TRUE; } is_deleted = FALSE; is_modified = TRUE; get_data()->undelete(warning, renamed); if (ren) { set_name(s); renamed += QString("
  • ") + full_name() + "\n"; } result = TRUE; package_modified(); } else result = FALSE; if (rec) { // undelete the sub elts QListViewItem * child; for (child = firstChild(); child != 0; child = child->nextSibling()) result |= ((BrowserNode *) child)->undelete(rec, warning, renamed); } if (result) repaint(); return result; } bool BrowserNode::in_edition() const { return !is_edited; } void BrowserNode::edit_start() { edition_number += 1; is_edited = TRUE; } void BrowserNode::edit_end() { edition_number -= 1; is_edited = FALSE; } bool BrowserNode::is_writable() const { return !is_read_only; } void BrowserNode::set_name(const char * s) { bool firsttime = name.isEmpty(); if ((s == 0) ? !firsttime : (name != s)) { name = s; if (! firsttime) // else set by BrowserNode::post_load() update_stereotype(); } } // void BrowserNode::update_stereotype(bool rec) { BasicData * data = get_data(); if (data != 0) { const char * stereotype = data->get_stereotype(); setText(0, (show_stereotypes && stereotype[0]) ? QString("<<") + toUnicode(stereotype) + ">> " + name : QString((const char *) name)); } if (rec) { QListViewItem * child; for (child = firstChild(); child != 0; child = child->nextSibling()) ((BrowserNode *) child)->update_stereotype(TRUE); } } const char * BrowserNode::get_stereotype() const { return get_data()->get_stereotype(); } bool BrowserNode::toggle_show_stereotypes() { show_stereotypes = !show_stereotypes; BrowserNode * prj = BrowserView::get_project(); if (prj != 0) prj->update_stereotype(TRUE); return show_stereotypes; } void BrowserNode::paintCell(QPainter * p, const QColorGroup & cg, int column, int width, int alignment) { const QColor & bg = p->backgroundColor(); if (is_marked) { p->setBackgroundMode(::Qt::OpaqueMode); p->setBackgroundColor(UmlRedColor); } p->setFont((is_writable()) ? BoldFont : NormalFont); QListViewItem::paintCell(p, cg, column, width, alignment); if (is_marked) { p->setBackgroundMode(::Qt::TransparentMode); p->setBackgroundColor(bg); } } void BrowserNode::pre_load() { UndefinedNodePackage = new BrowserPackage("", BrowserView::get_project(), -1); } void BrowserNode::post_load() { signal_unconsistencies(); QList wrong; BrowserRelation::post_load(); BrowserAttribute::post_load(); BrowserClassInstance::post_load(); QListViewItem * child; for (child = UndefinedNodePackage->firstChild(); child; child = child->nextSibling()) ((BrowserNode *) child)->delete_it(); delete UndefinedNodePackage; UndefinedNodePackage = 0; BrowserView::get_project()->update_stereotype(TRUE); } void BrowserNode::must_be_deleted() { if (parent() != UndefinedNodePackage) { parent()->takeItem(this); UndefinedNodePackage->insertItem(this); } } void BrowserNode::set_parent(QListViewItem * p) { parent()->takeItem(this); p->insertItem(this); // move it at end QListViewItem * child = p->firstChild(); while (child->nextSibling()) child = child->nextSibling(); if (child != this) moveItem(child); } void BrowserNode::on_close() { // does nothing } BrowserNode * BrowserNode::get_container(UmlCode k) const { BrowserNode * p = (BrowserNode *) this; while ((p != 0) && (p->get_type() != k)) p = (BrowserNode *) p->parent(); return p; } BrowserNode * BrowserNode::container(UmlCode c) const { // currently only for class, state machine and activity BrowserNode * p = (BrowserNode *) parent(); return (p == 0) ? 0 : p->container(c); } // QString BrowserNode::full_name(bool, bool) const { return name; } void BrowserNode::modified() { package_modified(); repaint(); } void BrowserNode::on_delete() { // does nothing at this level } void BrowserNode::get_classdiagramsettings(ClassDiagramSettings & d) const { ((BrowserNode *) parent())->get_classdiagramsettings(d); } void BrowserNode::get_usecasediagramsettings(UseCaseDiagramSettings & d) const { ((BrowserNode *) parent())->get_usecasediagramsettings(d); } void BrowserNode::get_sequencediagramsettings(SequenceDiagramSettings & d) const { ((BrowserNode *) parent())->get_sequencediagramsettings(d); } void BrowserNode::get_collaborationdiagramsettings(CollaborationDiagramSettings & d) const { ((BrowserNode *) parent())->get_collaborationdiagramsettings(d); } void BrowserNode::get_objectdiagramsettings(ObjectDiagramSettings & d) const { ((BrowserNode *) parent())->get_objectdiagramsettings(d); } void BrowserNode::get_statediagramsettings(StateDiagramSettings & d) const { ((BrowserNode *) parent())->get_statediagramsettings(d); } void BrowserNode::get_activitydiagramsettings(ActivityDiagramSettings & d) const { ((BrowserNode *) parent())->get_activitydiagramsettings(d); } void BrowserNode::get_componentdiagramsettings(ComponentDiagramSettings & d) const { ((BrowserNode *) parent())->get_componentdiagramsettings(d); } void BrowserNode::get_deploymentdiagramsettings(DeploymentDiagramSettings & d) const { ((BrowserNode *) parent())->get_deploymentdiagramsettings(d); } UmlColor BrowserNode::get_color(UmlCode who) const { return ((BrowserNode *) parent())->get_color(who); } bool BrowserNode::get_shadow(UmlCode who) const { return ((BrowserNode *) parent())->get_shadow(who); } bool BrowserNode::get_draw_all_relations(UmlCode who) const { return ((BrowserNode *) parent())->get_draw_all_relations(who); } UmlVisibility BrowserNode::get_visibility(UmlCode who) const { return ((BrowserNode *) parent())->get_visibility(who); } bool BrowserNode::get_classinstwritehorizontally(UmlCode k) const { return ((BrowserNode *) parent())->get_classinstwritehorizontally(k); } void BrowserNode::get_componentdrawingsettings(bool depl, ComponentDrawingSettings & result) const { ((BrowserNode *) parent())->get_componentdrawingsettings(depl, result); } void BrowserNode::get_statedrawingsettings(StateDrawingSettings & result) const { ((BrowserNode *) parent())->get_statedrawingsettings(result); } void BrowserNode::get_activitydrawingsettings(ActivityDrawingSettings & result) const { ((BrowserNode *) parent())->get_activitydrawingsettings(result); } bool BrowserNode::get_auto_label_position(UmlCode who) const { return ((BrowserNode *) parent())->get_auto_label_position(who); } bool BrowserNode::get_write_label_horizontally(UmlCode who) const { return ((BrowserNode *) parent())->get_write_label_horizontally(who); } bool BrowserNode::get_show_trans_definition(UmlCode who) const { return ((BrowserNode *) parent())->get_show_trans_definition(who); } bool BrowserNode::get_show_opaque_action_definition(UmlCode who) const { return ((BrowserNode *) parent())->get_show_opaque_action_definition(who); } DrawingLanguage BrowserNode::get_language(UmlCode who) const { return ((BrowserNode *) parent())->get_language(who); } void BrowserNode::package_settings(bool &, ShowContextMode &) const { // never called } // QString BrowserNode::drag_key() const { return QString::number(get_type()); } QString BrowserNode::drag_postfix() const { return QString::null; } void BrowserNode::DragMoveEvent(QDragMoveEvent * e) { ((BrowserNode *) parent())->DragMoveInsideEvent(e); } void BrowserNode::DropEvent(QDropEvent * e) { ((BrowserNode *) parent())->DropAfterEvent(e, this); } void BrowserNode::DragMoveInsideEvent(QDragMoveEvent * e) { e->ignore(); } void BrowserNode::DropAfterEvent(QDropEvent * e, BrowserNode *) { e->ignore(); msg_critical("Error", "Forbiden"); } // void BrowserNode::open(bool) { // does nothing } BasicData * BrowserNode::add_relation(UmlCode t, BrowserNode * end) { SimpleRelationData * d = new SimpleRelationData(t); BrowserSimpleRelation * br = new BrowserSimpleRelation(this, d); d->set_start_end(br, end); br->modified(); // updates name return d; } void BrowserNode::edit(const char * s, const QStringList & default_stereotypes) { if (!is_edited) { static QSize previous_size[UmlCodeSup]; (new BasicDialog(get_data(), s, default_stereotypes, previous_size[get_type()])) ->show(); } } // // returns all parents and grand parents for NON class QList BrowserNode::parents() const { QList l; QListViewItem * child; for (child = firstChild(); child != 0; child = child->nextSibling()) { BrowserNode * ch = ((BrowserNode *) child); switch (ch->get_type()) { case UmlInherit: if (! ch->deletedp()) l.append(((SimpleRelationData *) ch->get_data()) ->get_end_node()); default: break; } } return l; } // check inheritance const char * BrowserNode::check_inherit(const BrowserNode * new_parent) const { QList all_parents; QList notyet = parents(); if (notyet.findRef(new_parent) != -1) return "already generalize / realize"; notyet.append(new_parent); do { BrowserNode * cl = notyet.getFirst(); notyet.removeFirst(); if (cl == this) return "can't have circular generalization / realization"; if (all_parents.findRef(cl) == -1) { all_parents.append(cl); QList grand_parents = cl->parents(); for (cl = grand_parents.first(); cl; cl = grand_parents.next()) if (notyet.findRef(cl) == -1) notyet.append(cl); } } while (! notyet.isEmpty()); return 0; } // // only simple items are duplicated, and they are duplicated // recurssively : #define SIMPLE_DUPLICATION void BrowserNode::mark_menu(QPopupMenu & m, const char * s, int bias) const { if (! is_marked) { m.insertSeparator(); m.setWhatsThis(m.insertItem("Mark", bias), QString("to mark the ") + s + ""); if (!marked_list.isEmpty()) { bool parents_marked = FALSE; const BrowserNode * bn = this; while (bn != BrowserView::get_project()) { bn = (BrowserNode *) bn->parent(); if (bn->is_marked) { parents_marked = TRUE; break; } } bool moveable = TRUE; #ifndef SIMPLE_DUPLICATION bool rec = FALSE; #endif QListIterator it(marked_list); for (; (bn = it.current()) != 0; ++it) { if ((bn == BrowserView::get_project()) || !((BrowserNode *) bn->parent())->is_writable()) { moveable = FALSE; #ifndef SIMPLE_DUPLICATION } if (bn->firstChild() != 0) { rec = TRUE; #else break; #endif } } bool duplicable_into = TRUE; bool duplicable_after = TRUE; bool into = may_contains_them(marked_list, duplicable_into) && is_writable(); bool after = (this != BrowserView::get_project()) && ((BrowserNode *) parent())->is_writable() && ((BrowserNode *) parent())->may_contains_them(marked_list, duplicable_after); if (!parents_marked) { if (moveable) { if (into) m.setWhatsThis(m.insertItem("Move marked into", bias + 3), QString("to move the marked items into ") + s + ""); if (after) m.setWhatsThis(m.insertItem("Move marked after", bias + 4), QString("to move the marked items after ") + s + ""); } } if (into && duplicable_into) { m.setWhatsThis(m.insertItem("Duplicate marked into", bias + 5), QString("to duplicate the marked items into ") + s + ""); #ifndef SIMPLE_DUPLICATION if (rec && !parents_marked) m.setWhatsThis(m.insertItem("Duplicate recursivelly marked into", bias + 6), QString("to recurcivelly duplicate the marked items into ") + s + ""); #endif } if (after && duplicable_after) { m.setWhatsThis(m.insertItem("Duplicate marked after", bias + 7), QString("to duplicate the marked items after ") + s + ""); #ifndef SIMPLE_DUPLICATION if (rec && !parents_marked) m.setWhatsThis(m.insertItem("Duplicate marked recursivelly after", bias + 8), QString("to recurcivelly duplicate the marked items after ") + s + ""); #endif } } } else { m.insertSeparator(); m.setWhatsThis(m.insertItem("Unmark", bias + 1), QString("to unmark the ") + s + ""); if (!marked_list.isEmpty()) m.setWhatsThis(m.insertItem("Unmark all", bias + 2), QString("to unmark all the marked items")); } } void BrowserNode::mark_shortcut(QString s, int & index, int bias) { if (! is_marked) { if (s == "Mark") index = bias; } else { if (s == "Unmark") index = bias + 1; } if (s == "Unmark all") index = bias + 2; } bool BrowserNode::may_contains_them(const QList &, bool &) const { return FALSE; } bool BrowserNode::may_contains_it(BrowserNode * bn) const { // for the type point of view bn is legal for 'this' UmlCode type = bn->get_type(); QString s = (const char *) bn->name; for (QListViewItem * child = firstChild(); child; child = child->nextSibling()) { if (!((BrowserNode *) child)->deletedp() && ((BrowserNode *) child)->same_name(s, type)) return FALSE; } return TRUE; } void BrowserNode::mark_management(int choice) { BrowserNode * bn; switch (choice) { case 0: // mark is_marked = TRUE; marked_list.append(this); repaint(); return; case 1: // unmark is_marked = FALSE; marked_list.removeRef(this); repaint(); return; case 2: // unmark all for (bn = marked_list.first(); bn != 0; bn = marked_list.next()) { bn->is_marked = FALSE; bn->repaint(); } marked_list.clear(); return; case 3: // move into for (bn = marked_list.last(); bn != 0; bn = marked_list.prev()) move(bn, 0); break; case 4: // move after { BrowserNode * p = (BrowserNode *) parent(); for (bn = marked_list.last(); bn != 0; bn = marked_list.prev()) p->move(bn, this); } break; case 5: // duplicate into for (bn = marked_list.last(); bn != 0; bn = marked_list.prev()) move(bn->duplicate(this), 0); break; #ifndef SIMPLE_DUPLICATION case 6: // duplicate recursivelly into break; #endif case 7: // duplicate after { BrowserNode * p = (BrowserNode *) parent(); for (bn = marked_list.last(); bn != 0; bn = marked_list.prev()) p->move(bn->duplicate(p), this); } break; #ifndef SIMPLE_DUPLICATION case 8: // duplicate recursivelly after break; #endif } } void BrowserNode::move(BrowserNode * bn, BrowserNode * after) { BrowserNode * old_parent = (BrowserNode *) bn->parent(); if (after) bn->moveItem(after); else { old_parent->takeItem(bn); insertItem(bn); } package_modified(); if (old_parent != this) { old_parent->package_modified(); bn->modified(); } } void BrowserNode::toggle_mark() { if (is_marked) { is_marked = FALSE; marked_list.removeRef(this); } else { is_marked = TRUE; marked_list.append(this); } repaint(); } // bool BrowserNode::may_contains(BrowserNode * bn, bool rec) const { // for the type point of view bn is legal for 'this' if (((BrowserNode *) bn->parent()) == this) return TRUE; QString s = (const char *) bn->name; if (! s.isEmpty()) { UmlCode type = bn->get_type(); for (QListViewItem * child = firstChild(); child; child = child->nextSibling()) { if (!((BrowserNode *) child)->deletedp() && (child != bn) && ((BrowserNode *) child)->same_name(s, type)) return FALSE; } } if (!rec) return TRUE; const BrowserNode * pa = this; for (;;) { if (pa == 0) return TRUE; else if (pa == bn) // cannot move a parent in a child ! return FALSE; pa = ((BrowserNode *) pa->parent()); } } // void BrowserNode::children(BrowserNodeList & nodes, UmlCode kind1, UmlCode kind2) const { QListViewItem * child; for (child = firstChild(); child; child = child->nextSibling()) if (!((BrowserNode *) child)->is_deleted && ((((BrowserNode *) child)->get_type() == kind1) || (((BrowserNode *) child)->get_type() == kind2))) nodes.append((BrowserNode *) child); } bool BrowserNode::enter_child_name(QString & r, const QString & msg, UmlCode type, bool allow_spaces, bool allow_empty) { for (;;) { bool ok = FALSE; r = MyInputDialog::getText("Uml", msg, QString::null, ok); if (ok) { if (wrong_child_name(r, type, allow_spaces, allow_empty)) msg_critical("Error", r + "\n\nillegal name or already used"); else return TRUE; } else return FALSE; } } bool BrowserNode::enter_child_name(QString & r, const QString & msg, UmlCode type, BrowserNodeList nodes, BrowserNode ** old, bool allow_spaces, bool allow_empty, bool existing) { if (existing && nodes.isEmpty()) { msg_warning("Error", "nothing available"); return FALSE; } QStringList list; nodes.full_names(list); list.prepend(QString::null); *old = 0; for (;;) { bool ok = FALSE; r = (list.count() == 1) ? MyInputDialog::getText("Uml", msg, QString::null, ok) : MyInputDialog::getText("Uml", msg, list, QString::null, existing, ok); if (! ok) return FALSE; if (!r.isEmpty()) { int index = list.findIndex(r); if (index != -1) { *old = nodes.at(index - 1); return TRUE; } } if (wrong_child_name(r, type, allow_spaces, allow_empty)) msg_critical("Error", r + "\n\nillegal name or already used"); else return TRUE; } } bool BrowserNode::wrong_child_name(const QString & s, UmlCode type, bool allow_spaces, bool allow_empty) const { if (s.isEmpty()) return !allow_empty; const char * str = s; switch (type) { case UmlExtraMember: // always right, synonymous allowed return FALSE; case UmlOperation: if (strncmp(str, "operator", 8) == 0) // skip character check break; if (*str == '~') str += 1; // no break ! default: if (type <= UmlClass) { while (*str) { char c = *str++; if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || ((c >= '0') && (c <= '9')) || (c == '_')) ; else if ((strchr("()&^[]%|!+-*/=>", c) != 0) || (((c == ' ') || (c == '\t') || (c == '\r')) && !allow_spaces)) return TRUE; else if (c == '<') { if (type == UmlClass) // suppose it is a valid template break; else return TRUE; } } } } // check unicity for (QListViewItem * child = firstChild(); child; child = child->nextSibling()) if (!((BrowserNode *) child)->deletedp() && ((BrowserNode *) child)->same_name(s, type)) return TRUE; return FALSE; } bool BrowserNode::allow_spaces() const { return TRUE; } bool BrowserNode::allow_empty() const { return FALSE; } bool BrowserNode::same_name(const QString & s, UmlCode type) const { return ((get_type() == type) && (name == s)); } void BrowserNode::select_in_browser() { BrowserView::select(this); } // unicode const QStringList & BrowserNode::default_stereotypes(UmlCode, const BrowserNode *) const { static QStringList empty; return empty; } BrowserNode * BrowserNode::get_associated() const { // cannot have associated diagram/view return (BrowserNode *) this; } void BrowserNode::package_modified() { ((BrowserNode *) parent())->package_modified(); } bool BrowserNode::api_compatible(unsigned) const { return TRUE; } bool BrowserNode::tool_cmd(ToolCom * com, const char * args) { switch ((unsigned char) args[-1]) { case applyCmd: com->write_unsigned(ToolCom::run(args, this)); break; case createCmd: // unvalid creation com->write_id(0); break; case parentCmd: if (this != BrowserView::get_project()) ((BrowserNode *) parent())->write_id(com); else com->write_id(0); break; case childrenCmd: { unsigned v = com->api_format(); unsigned n = 0; QListViewItem * child; for (child = firstChild(); child != 0; child = child->nextSibling()) if (!((BrowserNode *) child)->deletedp() && ((BrowserNode *) child)->api_compatible(v)) n += 1; com->write_unsigned(n); for (child = firstChild(); child != 0; child = child->nextSibling()) if (!((BrowserNode *) child)->deletedp() && ((BrowserNode *) child)->api_compatible(v)) ((BrowserNode *) child)->write_id(com); } break; case getDefCmd: case getUmlDefCmd: case getCppDefCmd: case getJavaDefCmd: case getPhpDefCmd: case getIdlDefCmd: get_data()->send_uml_def(com, this, comment); break; case isWritableCmd: com->write_bool(!is_read_only); break; case supportFileCmd: // goes up to the package return ((BrowserNode *) parent())->tool_cmd(com, args); case isOpenCmd: com->write_bool(isOpen()); break; case referencedByCmd: { QList targetof; referenced_by(targetof); // remove duplicats targetof.sort(); BrowserNode * bn; targetof.first(); while ((bn = targetof.current()) != 0) if (bn == targetof.next()) targetof.remove(); com->write_unsigned(targetof.count()); for (bn = targetof.first(); bn != 0; bn = targetof.next()) bn->write_id(com); } break; case setCoupleValueCmd: if (is_read_only && !root_permission()) com->write_ack(FALSE); else { set_value(args, args + strlen(args) + 1); package_modified(); com->write_ack(TRUE); } break; case setDescriptionCmd: if (is_read_only && !root_permission()) com->write_ack(FALSE); else { set_comment(args); package_modified(); com->write_ack(TRUE); } break; case setNameCmd: if (is_read_only && !root_permission()) com->write_ack(FALSE); else { if (name != args) { if (((BrowserNode *) parent())->wrong_child_name(args, get_type(), allow_spaces(), allow_empty())) { com->write_ack(FALSE); return TRUE; } else { set_name(args); update_stereotype(); package_modified(); get_data()->modified(); } } com->write_ack(TRUE); } break; case setOpenCmd: BrowserView::select(this); setOpen(*args); com->write_ack(TRUE); break; case setMarkedCmd: if (*args) { if (this == BrowserView::get_project()) com->write_ack(FALSE); else { if (!is_marked) toggle_mark(); com->write_ack(TRUE); } } else { if (is_marked) toggle_mark(); com->write_ack(TRUE); } break; case moveAfterCmd: if (is_read_only && !root_permission()) com->write_ack(FALSE); else { BrowserNode * after = (BrowserNode *) com->get_id(args); if (after == 0) { QListViewItem * it = parent(); if (it == 0) com->write_ack(FALSE); else { it->takeItem(this); it->insertItem(this); com->write_ack(TRUE); package_modified(); } } else if ((after->parent() != parent()) || (after == this)) { com->write_ack(FALSE); } else { moveItem(after); com->write_ack(TRUE); package_modified(); } } break; case moveInCmd: // plug-out upgrade, limited checks if (is_read_only && !root_permission()) com->write_ack(FALSE); else { BrowserNode * newparent = (BrowserNode *) com->get_id(args); BrowserNode * oldparent = (BrowserNode *) parent(); if ((newparent == oldparent) || (newparent == this)) { com->write_ack(FALSE); } else { oldparent->takeItem(this); newparent->insertItem(this); com->write_ack(TRUE); oldparent->package_modified(); package_modified(); } } break; case old_deleteCmd: case deleteCmd: if (is_read_only && !root_permission()) com->write_ack(FALSE); else { delete_it(); package_modified(); com->write_ack(TRUE); } break; default: return FALSE; } return TRUE; } void BrowserNode::member_cpp_def(const QString &, const QString &, QString & s, bool) const { s += "MUST NOT BE CALLED\n"; } void BrowserNode::write_id(ToolCom * com) { com->write_id(this, get_type() - UmlRelations, name); } void BrowserNode::init_save_counter() { if (! deletedp()) { must_be_saved_counter += 1; QListViewItem * child = firstChild(); while (child != 0) { ((BrowserNode *) child)->init_save_counter(); child = child->nextSibling(); } } } bool BrowserNode::save_open_list(QTextStream & st) { if (!isOpen()) return FALSE; bool have_open_child = FALSE; for (QListViewItem * child = firstChild(); child != 0; child = child->nextSibling()) { BrowserNode * ch = ((BrowserNode *) child); if (!ch->deletedp()) have_open_child |= ch->save_open_list(st); } if (! have_open_child) { QString warning; st << " "; save(st, TRUE, warning); st << '\n'; } return TRUE; } void BrowserNode::save_progress_closed() { save_progress = 0; } void BrowserNode::save(QTextStream & st) const { if (save_progress != 0) save_progress->setProgress(already_saved++); HaveKeyValueData::save(st); if (! comment.isEmpty()) { nl_indent(st); st << "comment "; save_string(comment, st); } } void BrowserNode::read(char * & st, char * & k) { HaveKeyValueData::read(st, k); if (!strcmp(k, "comment")) { comment = read_string(st); k = read_keyword(st); } is_new = FALSE; } void BrowserNode::save_stereotypes(QTextStream & st, QStringList relations_stereotypes[]) { int r; for (r = 0; r != UmlRelations; r += 1) { QStringList & list = relations_stereotypes[r]; if (! list.isEmpty()) { nl_indent(st); st << " " << stringify((UmlCode) r); save_unicode_string_list(list, st); } } nl_indent(st); st << "end"; nl_indent(st); } void BrowserNode::read_stereotypes(char * & st, QStringList relations_stereotypes[]) { int r; for (r = 0; r != UmlRelations; r += 1) relations_stereotypes[r].clear(); char * k; while (strcmp((k = read_keyword(st)), "end")) { QStringList & list = relations_stereotypes[relation_type(k)]; list.clear(); read_unicode_string_list(list, st); } } void BrowserNode::renumber(int phase) { for (QListViewItem * child = firstChild(); child != 0; child = child->nextSibling()) ((BrowserNode *) child)->renumber(phase); } // manage unconsistencies static QString UnconsistencyDeletedMsg; static QString UnconsistencyFixedMsg; static QList ModifiedPackages; void BrowserNode::signal_unconsistencies() { QString pfix = "

    Warning, the model is not consistent because some elements have\n" "the same internal identifier.

    \n" "

    Users working on the sale project have the same BOUML_ID,\n" "or you had change the model files, or used Project synchro\n" "without following the mandatory rules

    \n"; QString msg; if (!UnconsistencyDeletedMsg.isEmpty()) msg = pfix + "

    These elements was removed :

    \n
      " + UnconsistencyDeletedMsg + "
    \n"; if (!UnconsistencyFixedMsg.isEmpty()) { if (UnconsistencyDeletedMsg.isEmpty()) msg = pfix; msg += "

    The internal identifier of these elements was changed,\n" "but I can't garanty the references to them are the right one,\n" "check your model :

    \n
      " + UnconsistencyFixedMsg + "
    \n"; do_change_shared_ids(); do ModifiedPackages.take(0)->is_modified = TRUE; while (! ModifiedPackages.isEmpty()); } if (! msg.isEmpty()) { UnconsistencyDeletedMsg = UnconsistencyFixedMsg = QString::null; warn(msg); } } void BrowserNode::unconsistent_fixed(const char * what, BrowserNode * newone) { UnconsistencyFixedMsg += QString("
  • ") + what + QString(" ") + quote(full_name()) + QString(" and ") + quote(newone->full_name()) + QString("
  • \n"); BrowserNode * bn = this; while (bn->get_type() != UmlPackage) bn = (BrowserNode *) bn->parent(); if (ModifiedPackages.findRef(bn) == -1) ModifiedPackages.append(bn); } void BrowserNode::unconsistent_removed(const char * what, BrowserNode * newone) { UnconsistencyDeletedMsg += QString("
  • ") + what + QString(" ") + quote(full_name()) + QString(" and ") + quote(newone->full_name()) + QString("
  • \n"); // deletion managed elsewhere } // void BrowserNodeList::search(BrowserNode * bn, UmlCode k, const QString & s, bool cs, bool even_deleted, bool for_name) { QListViewItem * child; for (child = bn->firstChild(); child != 0; child = child->nextSibling()) { if (even_deleted || !((BrowserNode *) child)->deletedp()) { BrowserNode * ch = (BrowserNode *) child; if (((k == UmlCodeSup) || ((k == UmlRelations) ? IsaRelation(ch->get_type()) : (ch->get_type() == k))) && (s.isEmpty() || (QString((for_name) ? ch->get_name() : ch->get_comment()) .find(s, 0, cs) != -1))) append((BrowserNode *) child); search((BrowserNode *) child, k, s, cs, even_deleted, for_name); } } } void BrowserNodeList::search_ddb(BrowserNode * bn, UmlCode k, const QString & s, bool cs, bool even_deleted) { QListViewItem * child; for (child = bn->firstChild(); child != 0; child = child->nextSibling()) { if (even_deleted || !((BrowserNode *) child)->deletedp()) { BrowserNode * ch = (BrowserNode *) child; if (((k == UmlCodeSup) || ((k == UmlRelations) ? IsaRelation(ch->get_type()) : (ch->get_type() == k))) && (s.isEmpty() || ch->get_data()->decldefbody_contain(s, cs, ch))) append(ch); search_ddb(ch, k, s, cs, even_deleted); } } } int BrowserNodeList::compareItems(QCollection::Item item1, QCollection::Item item2) { return QString(((BrowserNode *) item1)->get_name()) .compare(((BrowserNode *) item2)->get_name()); } void BrowserNodeList::names(QStringList & list) const { list.clear(); QListIterator it(*this); while (it.current() != 0) { const char * s = it.current()->get_name(); list.append(((s == 0) || (*s == 0)) ? "" : s); ++it; } } void BrowserNodeList::full_names(QStringList & list) const { list.clear(); QListIterator it(*this); while (it.current() != 0) { list.append(it.current()->full_name(TRUE)); ++it; } } void BrowserNodeList::full_defs(QStringList & list) const { list.clear(); QListIterator it(*this); while (it.current() != 0) { list.append(it.current()->get_data()->definition(TRUE)); ++it; } }