Bug 130142 - Kplato corrupts it's data (XML files)
Summary: Kplato corrupts it's data (XML files)
Status: RESOLVED FIXED
Alias: None
Product: kplato
Classification: Unmaintained
Component: general (other bugs)
Version First Reported In: unspecified
Platform: Unlisted Binaries Linux
: NOR normal
Target Milestone: ---
Assignee: Dag Andersen
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-07-02 13:17 UTC by Marcin Kurzyna
Modified: 2006-07-06 16:32 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marcin Kurzyna 2006-07-02 13:17:18 UTC
Version:            (using KDE KDE 3.5.3)
Installed from:    Unspecified Linux
Compiler:          gcc 3.3.6 
OS:                Linux

kplato often assigns same id to different tasks which corrupts XML files makeing them unreadable (on read crashes: bug#129275).

Also when editing a more complex project (lots of tasks, sub-tasks, milestones, etc) kplato looses resource<->calendar binding thus gantt chart reports unspecified resources errors.

I can't figure out a reproduction path - it happens randomly. Sometimes working with backup and reassigning same tasks again works fine (after initial corrupt).
Comment 1 Dag Andersen 2006-07-06 11:29:15 UTC
SVN commit 558898 by danders:

Fix problem with unique task ids not being unique.
Tasks with ids that allready exists will not be loaded anymore.
Needs some gui for this (as for all other loading failures).
(Note: this is for koffice 1.6)

Identical task ids could be produced like this:
1. create 2 tasks (T1, T2),
2. indent T2 under T1,
3. unindent T2.

The id of task T2 is now not registered in the project
so the next task created will get the same id as T2.

CCBUG:130142


 M  +25 -33    kptcommand.cc  
 M  +5 -2      kptcommand.h  
 M  +10 -9     kptnode.cc  
 M  +69 -8     kptproject.cc  
 M  +7 -4      kptproject.h  
 M  +6 -2      kpttask.cc  
Comment 2 Dag Andersen 2006-07-06 14:37:47 UTC
SVN commit 558997 by danders:

Fix problem with calendar lost/incorrect references both between
calendars (parent/child) and between resources and calendars.
(Note: this is for koffice 1.6)

CCBUG:130142


 M  +3 -2      kptcalendar.cc  
 M  +1 -1      kptcalendarlistdialog.cc  
 M  +10 -0     kptproject.cc  
 M  +2 -4      kptproject.h  
 M  +6 -2      kptresource.cc  


--- branches/koffice/1.6/koffice/kplato/kptcalendar.cc #558996:558997
@@ -523,7 +523,8 @@
     delete m_weekdays; 
 }
 Calendar::Calendar(Calendar *calendar)
-    : m_days() {
+    : m_project(0),
+      m_days() {
     m_days.setAutoDelete(true);
     copy(*calendar);
 }
@@ -569,7 +570,7 @@
     }
     Calendar *c = findCalendar();
     if (c == this) {
-        //kdDebug()<<k_funcinfo<<"My id found, remove it"<<endl;
+        kdDebug()<<k_funcinfo<<"My id found, remove it"<<endl;
         removeId();
     } else if (c) {
         //can happen when making a copy
--- branches/koffice/1.6/koffice/kplato/kptcalendarlistdialog.cc #558996:558997
@@ -173,7 +173,7 @@
     QPtrListIterator<Calendar> it = list;
     for (; it.current(); ++it) {
         Calendar *c = new Calendar(it.current());
-        c->setProject(&p);
+        //c->setProject(&p);
         new CalendarListViewItem(*dia, dia->calendarList, c, it.current());
     }
     dia->setBaseCalendars();
--- branches/koffice/1.6/koffice/kplato/kptproject.cc #558996:558997
@@ -1068,6 +1068,16 @@
     return sch;
 }
 
+bool Project::removeCalendarId(const QString &id) {
+    kdDebug()<<k_funcinfo<<"id="<<id<<endl;
+    return calendarIdDict.remove(id); 
+}
+
+void Project::insertCalendarId(const QString &id, const Calendar *calendar) { 
+    kdDebug()<<k_funcinfo<<"id="<<id<<": "<<calendar->name()<<endl;
+    calendarIdDict.insert(id, calendar);
+}
+        
 #ifndef NDEBUG
 void Project::printDebug(bool children, QCString indent) {
 
--- branches/koffice/1.6/koffice/kplato/kptproject.h #558996:558997
@@ -205,11 +205,9 @@
     virtual Calendar *findCalendar(const QString &id) const 
         { return id.isEmpty() ? 0 : calendarIdDict.find(id); }
     /// Remove the calendar with identity id from the register
-    virtual bool removeCalendarId(const QString &id) 
-        { return calendarIdDict.remove(id); }
+    virtual bool removeCalendarId(const QString &id);
     /// Insert the calendar with identity id
-    virtual void insertCalendarId(const QString &id, const Calendar *calendar)
-        { calendarIdDict.insert(id, calendar); }
+    virtual void insertCalendarId(const QString &id, const Calendar *calendar);
     
     /**
      * Setting a project to be baselined means the project data can not be edited anymore.
--- branches/koffice/1.6/koffice/kplato/kptresource.cc #558996:558997
@@ -322,8 +322,12 @@
 }
 
 Calendar *Resource::calendar(bool local) const {
-    if ( local == false && m_calendar == 0 && project() != 0)
+    if (!local && project() != 0 && (m_calendar == 0 || m_calendar->isDeleted())) {
         return project()->defaultCalendar();
+    }
+    if (m_calendar && m_calendar->isDeleted()) {
+        return 0;
+    }
     return m_calendar;
 }
 
@@ -366,7 +370,7 @@
     QDomElement me = element.ownerDocument().createElement("resource");
     element.appendChild(me);
 
-    if (m_calendar)
+    if (calendar(true))
         me.setAttribute("calendar-id", m_calendar->id());
     me.setAttribute("id", m_id);
     me.setAttribute("name", m_name);
Comment 3 Dag Andersen 2006-07-06 15:43:30 UTC
SVN commit 559031 by danders:

Fix problem with unique task ids not being unique.
(Note: this is for koffice 1.5)
To lessen the risk for regressions, this is a simpler 
(more hacky, though) solution than for 1.6.

CCBUG:130142


 M  +8 -8      kptcommand.cc  
 M  +41 -4     kptnode.cc  
 M  +4 -0      kptnode.h  
 M  +10 -0     kptproject.cc  
 M  +2 -4      kptproject.h  


--- branches/koffice/1.5/koffice/kplato/kptcommand.cc #559030:559031
@@ -658,8 +658,8 @@
 }
 void NodeIndentCmd::unexecute() {
     if (m_newindex != -1) {
-        m_newparent->delChildNode(m_newindex, false);
-        m_oldparent->insertChildNode(m_oldindex, &m_node);
+        m_newparent->delChildNode_NoId(m_newindex, false);
+        m_oldparent->insertChildNode_NoId(m_oldindex, &m_node);
         m_node.setParent(m_oldparent);
         m_newindex = -1;
     }
@@ -687,8 +687,8 @@
 }
 void NodeUnindentCmd::unexecute() {
     if (m_newindex != -1) {
-        m_newparent->delChildNode(m_newindex, false);
-        m_oldparent->insertChildNode(m_oldindex, &m_node);
+        m_newparent->delChildNode_NoId(m_newindex, false);
+        m_oldparent->insertChildNode_NoId(m_oldindex, &m_node);
         m_node.setParent(m_oldparent);
         m_newindex = -1;
     }
@@ -712,8 +712,8 @@
 }
 void NodeMoveUpCmd::unexecute() {
     if (m_newindex != -1) {
-        m_node.getParent()->delChildNode(m_newindex, false);
-        m_node.getParent()->insertChildNode(m_oldindex, &m_node);
+        m_node.getParent()->delChildNode_NoId(m_newindex, false);
+        m_node.getParent()->insertChildNode_NoId(m_oldindex, &m_node);
         m_newindex = -1;
     }
     
@@ -736,8 +736,8 @@
 }
 void NodeMoveDownCmd::unexecute() {
     if (m_newindex != -1) {
-        m_node.getParent()->delChildNode(m_newindex, false);
-        m_node.getParent()->insertChildNode(m_oldindex, &m_node);
+        m_node.getParent()->delChildNode_NoId(m_newindex, false);
+        m_node.getParent()->insertChildNode_NoId(m_oldindex, &m_node);
         m_newindex = -1;
     }
     
--- branches/koffice/1.5/koffice/kplato/kptnode.cc #559030:559031
@@ -117,6 +117,17 @@
     return 0;
 }
 
+//HACK
+void Node::delChildNode_NoId( Node *node, bool remove) {
+    //kdDebug()<<k_funcinfo<<"find="<<m_nodes.findRef(node)<<endl;
+    if ( m_nodes.findRef(node) != -1 ) {
+        if(remove)
+            m_nodes.remove();
+        else
+            m_nodes.take();
+    }
+}
+
 void Node::delChildNode( Node *node, bool remove) {
     //kdDebug()<<k_funcinfo<<"find="<<m_nodes.findRef(node)<<endl;
     if ( m_nodes.findRef(node) != -1 ) {
@@ -128,6 +139,14 @@
     }
 }
 
+//HACK
+void Node::delChildNode_NoId( int number, bool remove) {
+    if(remove)
+        m_nodes.remove(number);
+    else
+        m_nodes.take(number);
+}
+
 void Node::delChildNode( int number, bool remove) {
     Node *n = m_nodes.at(number);
     if (n)
@@ -138,21 +157,39 @@
         m_nodes.take(number);
 }
 
+//HACK
+void Node::insertChildNode_NoId( unsigned int index, Node *node) {
+    m_nodes.insert(index,node);
+    node->setParent(this);
+}
+
 void Node::insertChildNode( unsigned int index, Node *node) {
+    node->setParent(this);
     if (!node->setId(node->id())) {
         kdError()<<k_funcinfo<<node->name()<<" Not unique id: "<<m_id<<endl;
     }
     m_nodes.insert(index,node);
-    node->setParent(this);
 }
 
 void Node::addChildNode( Node *node, Node *after) {
     int index = m_nodes.findRef(after);
+    node->setParent(this);
+    if (!node->setId(node->id())) {
+         kdError()<<k_funcinfo<<node->name()<<" Not unique id: "<<m_id<<endl;
+    }
     if (index == -1) {
-        if (!node->setId(node->id())) {
-            kdError()<<k_funcinfo<<node->name()<<" Not unique id: "<<m_id<<endl;
-        }
         m_nodes.append(node);
+        
+        return;
+    }
+    m_nodes.insert(index+1, node);
+}
+
+//HACK
+void Node::addChildNode_NoId( Node *node, Node *after) {
+    int index = m_nodes.findRef(after);
+    if (index == -1) {
+        m_nodes.append(node);
         node->setParent(this);
         return;
     }
--- branches/koffice/1.5/koffice/kplato/kptnode.h #559030:559031
@@ -103,9 +103,13 @@
     const QPtrList<Node> &childNodeIterator() const { return m_nodes; }
     int numChildren() const { return m_nodes.count(); }
     virtual void addChildNode(Node *node, Node *after=0);
+    virtual void addChildNode_NoId(Node *node, Node *after=0); //HACK
     virtual void insertChildNode(unsigned int index, Node *node);
+    virtual void insertChildNode_NoId(unsigned int index, Node *node); //HACK
     void delChildNode(Node *node, bool remove=true);
+    void delChildNode_NoId(Node *node, bool remove=true); //HACK
     void delChildNode(int number, bool remove=true);
+    void delChildNode_NoId(int number, bool remove=true); //HACK
     Node* getChildNode(int number) { return m_nodes.at(number); }
     const Node* getChildNode(int number) const;
 	int findChildNode( Node* node );
--- branches/koffice/1.5/koffice/kplato/kptproject.cc #559030:559031
@@ -753,6 +753,16 @@
     return QString("%1").arg(i);
 }
 
+bool Project::removeId(const QString &id) {
+    kdDebug()<<k_funcinfo<<"id="<<id<<endl;
+    return (m_parent ? m_parent->removeId(id) : nodeIdDict.remove(id)); 
+}
+    /// Insert the node with identity id
+void Project::insertId(const QString &id, const Node *node) {
+    kdDebug()<<k_funcinfo<<"id="<<id<<": "<<node->name()<<endl;
+    m_parent ? m_parent->insertId(id, node) : nodeIdDict.insert(id, node);
+}
+
 ResourceGroup *Project::group(QString id) {
     return findResourceGroup(id);
 }
--- branches/koffice/1.5/koffice/kplato/kptproject.h #559030:559031
@@ -173,11 +173,9 @@
     virtual Node *findNode(const QString &id) const 
         { return (m_parent ? m_parent->findNode(id) : nodeIdDict.find(id)); }
     /// Remove the node with identity id from the register
-    virtual bool removeId(const QString &id) 
-        { return (m_parent ? m_parent->removeId(id) : nodeIdDict.remove(id)); }
+    virtual bool removeId(const QString &id);
     /// Insert the node with identity id
-    virtual void insertId(const QString &id, const Node *node)
-        { m_parent ? m_parent->insertId(id, node) : nodeIdDict.insert(id, node); }
+    virtual void insertId(const QString &id, const Node *node);
     QString uniqueNodeId(int seed=1);
     
     ResourceGroup *findResourceGroup(const QString &id) const 
Comment 4 Dag Andersen 2006-07-06 16:28:08 UTC
SVN commit 559066 by danders:

Fix problem with calendar lost/incorrect references both between
calendars (parent/child) and between resources and calendars.
(Note: this is for koffice 1.5)
Ported from 1.6.
CCBUG:130142



 M  +2 -1      kptcalendar.cc  
 M  +1 -1      kptcalendarlistdialog.cc  
 M  +10 -0     kptproject.cc  
 M  +2 -4      kptproject.h  
 M  +6 -2      kptresource.cc  


--- branches/koffice/1.5/koffice/kplato/kptcalendar.cc #559065:559066
@@ -523,7 +523,8 @@
     delete m_weekdays; 
 }
 Calendar::Calendar(Calendar *calendar)
-    : m_days() {
+    : m_project(0),
+      m_days() {
     m_days.setAutoDelete(true);
     copy(*calendar);
 }
--- branches/koffice/1.5/koffice/kplato/kptcalendarlistdialog.cc #559065:559066
@@ -173,7 +173,7 @@
     QPtrListIterator<Calendar> it = list;
     for (; it.current(); ++it) {
         Calendar *c = new Calendar(it.current());
-        c->setProject(&p);
+        //c->setProject(&p);
         new CalendarListViewItem(*dia, dia->calendarList, c, it.current());
     }
     dia->setBaseCalendars();
--- branches/koffice/1.5/koffice/kplato/kptproject.cc #559065:559066
@@ -1022,6 +1022,16 @@
     return sch;
 }
 
+bool Project::removeCalendarId(const QString &id) {
+    kdDebug()<<k_funcinfo<<"id="<<id<<endl;
+    return calendarIdDict.remove(id); 
+}
+
+void Project::insertCalendarId(const QString &id, const Calendar *calendar) { 
+    kdDebug()<<k_funcinfo<<"id="<<id<<": "<<calendar->name()<<endl;
+    calendarIdDict.insert(id, calendar);
+}
+        
 #ifndef NDEBUG
 void Project::printDebug(bool children, QCString indent) {
 
--- branches/koffice/1.5/koffice/kplato/kptproject.h #559065:559066
@@ -200,11 +200,9 @@
     virtual Calendar *findCalendar(const QString &id) const 
         { return id.isEmpty() ? 0 : calendarIdDict.find(id); }
     /// Remove the calendar with identity id from the register
-    virtual bool removeCalendarId(const QString &id) 
-        { return calendarIdDict.remove(id); }
+    virtual bool removeCalendarId(const QString &id);
     /// Insert the calendar with identity id
-    virtual void insertCalendarId(const QString &id, const Calendar *calendar)
-        { calendarIdDict.insert(id, calendar); }
+    virtual void insertCalendarId(const QString &id, const Calendar *calendar);
     
     /**
      * Setting a project to be baselined means the project data can not be edited anymore.
--- branches/koffice/1.5/koffice/kplato/kptresource.cc #559065:559066
@@ -322,8 +322,12 @@
 }
 
 Calendar *Resource::calendar(bool local) const {
-    if ( local == false && m_calendar == 0 && project() != 0)
+    if (!local && project() != 0 && (m_calendar == 0 || m_calendar->isDeleted())) {
         return project()->defaultCalendar();
+    }
+    if (m_calendar && m_calendar->isDeleted()) {
+        return 0;
+    }
     return m_calendar;
 }
 
@@ -366,7 +370,7 @@
     QDomElement me = element.ownerDocument().createElement("resource");
     element.appendChild(me);
 
-    if (m_calendar)
+    if (calendar(true))
         me.setAttribute("calendar-id", m_calendar->id());
     me.setAttribute("id", m_id);
     me.setAttribute("name", m_name);
Comment 5 Dag Andersen 2006-07-06 16:32:57 UTC
*** Bug has been marked as fixed ***.