[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-pim
Subject:    [Kde-pim] karm logging patch
From:       Mark Bucciarelli <mark () easymailings ! com>
Date:       2003-04-28 3:44:29
[Download RAW message or body]

The attached path makes it possible to (almost) reconstruct task 
history from the karm log file.  It:

(1) logs task renames
(2) logs the change in time when someone resets total or session time.

It's a lot of code, mainly because I decided to create a KarmEvent 
base class and then implement subclasses for each type of event that 
gets logged.  It's over-designed, but that's probably because I'm 
just getting warmed up with c++.  

Anyway, it's a cleaner design.  If the events are ever supposed to 
trigger something other than an XML log entry, you can just add a new 
toSomething() method to each event.  Also, new events (for example, 
delete_task, add_task) will not touch any existing code, just require 
a new subclass.

I also made a few mods to the TODO list based on what I read in the 
sources.

I'll wait to hear from Tomas before applying.

Mark

P.S. How come the following code doesn't compile?

QString s = "something about " + "binary operator and const char[17]";







["karmlogging.patch" (text/x-diff)]

? karmlogging.patch
Index: TODO
===================================================================
RCS file: /home/kde/kdepim/karm/TODO,v
retrieving revision 1.6
diff -u -p -r1.6 TODO
--- TODO	13 Jan 2003 01:40:44 -0000	1.6
+++ TODO	28 Apr 2003 03:50:40 -0000
@@ -1,4 +1,5 @@
-* times can be negative - does that make any sense?
+$Id:  $
+
 * one can adjust subtask *and* task times which has the effect that times
   won't add up any more - does that make sense?
 * add notes to logentries
@@ -10,6 +11,11 @@
 * mainwindow: move tray signals into tray.cpp
 * formatTime has nothing to do in TaskView?
 * "#ifndef header"s are inconsistent
+* mainwindow.cpp: before loading view, check whether the file exists
+  and if not, create a blank one and ask wheter we want to add a task.
+* add mouse double-click action (start new timer, stop old) to "Configure
+  Shortcuts" dialog.
+
 * Willi:
 --------
   * If one starts karm and installs some desktop tracking tasks nothing
Index: logging.cpp
===================================================================
RCS file: /home/kde/kdepim/karm/logging.cpp,v
retrieving revision 1.2
diff -u -p -r1.2 logging.cpp
--- logging.cpp	13 Jan 2003 01:49:51 -0000	1.2
+++ logging.cpp	28 Apr 2003 03:50:41 -0000
@@ -8,11 +8,134 @@
 #include <qregexp.h>
 #include <iostream>
 
-#define LOG_START				1
-#define LOG_STOP				2
-#define LOG_NEW_TOTAL_TIME		3
-#define LOG_NEW_SESSION_TIME	4
+#define QS(c) QString::fromLatin1(c)
+
+//
+//                               E V E N T S
+//
+QString KarmEvent::escapeXML( QString string ) {
+
+	QString result = QString(string);
+	result.replace( QRegExp(QS("&")),  QS("&amp;")  );
+	result.replace( QRegExp(QS("<")),  QS("&lt;")   );
+	result.replace( QRegExp(QS(">")),  QS("&gt;")   );
+	result.replace( QRegExp(QS("'")),  QS("&apos;") );
+	result.replace( QRegExp(QS("\"")), QS("&quot;") );
+	// protect also our task-separator
+	result.replace( QRegExp(QS("/")),  QS("&slash;") );
+
+	return result;
+}
+
+// common stuff
+void KarmEvent::loadCommonFields( Task *task) {
+	eventTime =  QDateTime::currentDateTime();
+
+	QListViewItem *item = task;
+	fullName = escapeXML(task->name());
+	while( ( item = item->parent() ) )
+	{
+		fullName = escapeXML(((Task *)item)->name()) 
+				+ fullName.prepend('/');
+	}
+}
+
+// start
+StartEvent::StartEvent( Task *task ) {
+	loadCommonFields(task);
+}
+
+QString StartEvent::toXML() {
+    // There's got to be an easier way to concatenate strings ...
+    QString s;
+    QTextStream ts( &s, IO_WriteOnly);
+
+	ts << "<starting"
+            << " task=\"" << fullName << "\""
+            << " date=\"" << eventTime.toString() << "\""
+            << " />\n";
+    return (s);
+}
+
+// stop
+StopEvent::StopEvent( Task *task ) {
+	loadCommonFields(task);
+}
+
+QString StopEvent::toXML() {
+    QString s;
+    QTextStream ts( &s, IO_WriteOnly);
+
+	ts << "<stopping"
+            << " task=\"" << fullName << "\""
+            << " date=\"" << eventTime.toString() << "\""
+            << " />\n";
+    return (s);
+}
+
+// rename
+RenameEvent::RenameEvent( Task *task, QString& old ) {
+	loadCommonFields(task);
+    oldName = old;
+}
+
+QString RenameEvent::toXML() {
+    QString s;
+    QTextStream ts( &s, IO_WriteOnly);
+
+	ts << "<renaming"
+            << " task=\"" << fullName << "\""
+            << " date=\"" << eventTime.toString() << "\""
+            << " old_name=\"" << oldName << "\""
+            << " />\n";
+    return (s);
+}
+
+// set session
+SessionTimeEvent::SessionTimeEvent( Task *task, long total, long change) {
+	loadCommonFields(task);
+    delta = change;
+    newTotal = total;
+}
+
+QString SessionTimeEvent::toXML() {
+    QString s;
+    QTextStream ts( &s, IO_WriteOnly);
+
+	ts << "<new_session_time"
+            << " task=\"" << fullName << "\"" 
+            << " date=\"" << eventTime.toString() << "\""
+            << " new_total=\"" << newTotal << "\""
+            << " change=\"" << delta << "\""
+            << " />" << endl;
 
+    return (s);
+}
+
+// set total
+TotalTimeEvent::TotalTimeEvent( Task *task, long total, long change) {
+	loadCommonFields(task);
+    delta = change;
+    newTotal = total;
+}
+
+QString TotalTimeEvent::toXML() {
+    QString s;
+    QTextStream ts( &s, IO_WriteOnly);
+
+	ts << "<new_total_time"
+            << " task=\"" << fullName << "\"" 
+            << " date=\"" << eventTime.toString() << "\""
+            << " new_total=\"" << newTotal << "\""
+            << " change=\"" << delta << "\""
+            << " />" << endl;
+
+    return (s);
+}
+
+//
+//                              L O G G I N G
+//
 Logging *Logging::_instance = 0;
 
 Logging::Logging()
@@ -20,27 +143,31 @@ Logging::Logging()
 	_preferences = Preferences::instance();
 }
 
-void Logging::start( Task * task)
-{
-	log(task, LOG_START);
+void Logging::start( Task *task) {
+    KarmEvent* event = new StartEvent(task);
+    log(event);
+}
+void Logging::stop( Task *task) {
+    KarmEvent* event = new StopEvent(task);
+    log(event);
 }
 
-void Logging::stop( Task * task)
-{
-	log(task, LOG_STOP);
+void Logging::newTotalTime( Task *task, long minutes, long change) {
+    KarmEvent* event = new TotalTimeEvent(task, minutes, change);
+    log(event);
 }
 
-// when time is reset...
-void Logging::newTotalTime( Task * task, long minutes)
-{
-	log(task, LOG_NEW_TOTAL_TIME, minutes);
+void Logging::newSessionTime( Task *task, long minutes, long change) {
+    KarmEvent* event = new SessionTimeEvent(task, minutes, change);
+    log(event);
 }
-void Logging::newSessionTime( Task * task, long minutes)
-{
-	log(task, LOG_NEW_SESSION_TIME, minutes);
+
+void Logging::rename( Task *task, QString& oldName) {
+    KarmEvent* event = new RenameEvent(task, oldName);
+    log(event);
 }
 
-void Logging::log( Task * task, short type, long minutes)
+void Logging::log( KarmEvent* event)
 {
 
 	if(_preferences->timeLogging()) {
@@ -48,28 +175,7 @@ void Logging::log( Task * task, short ty
 
 		if ( f.open( IO_WriteOnly | IO_Append) ) {
 			QTextStream out( &f );        // use a text stream
-
-			if( type == LOG_START) {
-				out << "<starting         ";
-			} else if( type == LOG_STOP ) {
-				out << "<stopping         ";
-			} else if( type == LOG_NEW_TOTAL_TIME) {
-				out << "<new_total_time   ";
-			} else if( type == LOG_NEW_SESSION_TIME) {
-				out << "<new_session_time ";
-			} else {
-				std::cerr << "Programming error!";
-			}
-
-			out << "task=\"" << constructTaskName(task) << "\" "
-			    << "date=\"" << QDateTime::currentDateTime().toString() << "\" ";
-			  
-			if ( type == LOG_NEW_TOTAL_TIME || type == LOG_NEW_SESSION_TIME) {
-				out << "new_total=\"" << minutes  << "\" ";
-			}
-			
-			out << "/>\n";
-
+			out << event->toXML();
 			f.close();
 		} else {
 			std::cerr << "Couldn't write to time-log file";
@@ -85,36 +191,7 @@ Logging *Logging::instance()
   return _instance;
 }
 
-QString Logging::constructTaskName(Task *task)
-{
-	QListViewItem *item = task;
-	
-	QString name = escapeXML(task->name());
-	
-	while( ( item = item->parent() ) )
-	{
-		name = escapeXML(((Task *)item)->name()) + name.prepend('/');
-	}
-
-	return name;
-}
-
-// why the hell do I need to do this?!?
-#define QS(c) QString::fromLatin1(c)
-
-QString Logging::escapeXML( QString string)
-{
-	QString result = QString(string);
-	result.replace( QRegExp(QS("&")),  QS("&amp;")  );
-	result.replace( QRegExp(QS("<")),  QS("&lt;")   );
-	result.replace( QRegExp(QS(">")),  QS("&gt;")   );
-	result.replace( QRegExp(QS("'")),  QS("&apos;") );
-	result.replace( QRegExp(QS("\"")), QS("&quot;") );
-	// protect also our task-separator
-	result.replace( QRegExp(QS("/")),  QS("&slash;") );
-
-	return result;
-}
 
 Logging::~Logging() {
 }
+
Index: logging.h
===================================================================
RCS file: /home/kde/kdepim/karm/logging.h,v
retrieving revision 1.2
diff -u -p -r1.2 logging.h
--- logging.h	13 Jan 2003 01:49:51 -0000	1.2
+++ logging.h	28 Apr 2003 03:50:41 -0000
@@ -3,19 +3,70 @@
 
 #include "preferences.h"
 #include <qstring.h>
+#include <qdatetime.h>
 
 class Task;
 
-/**
- * Log changes to a file.
- */
+class KarmEvent {
+protected:
+	QString name;
+	// full name includes all parents
+	QString fullName;
+	QDateTime eventTime;
+	void loadCommonFields( Task *task);
+
+	// this really doesn't belong here ...
+  QString escapeXML( QString string);
+public:
+  virtual QString toXML(void) =0;
+  // needed to avoid compiler warnings about subclasses having
+  // "virtual functions but non-virtual destructor."
+  virtual ~KarmEvent () {};
+};
+
+class StartEvent: public KarmEvent {
+public:
+	StartEvent( Task *task);
+	QString toXML();
+};
+
+class StopEvent: public KarmEvent {
+public:
+	StopEvent ( Task *task);
+	QString toXML();
+};
+
+class RenameEvent: public KarmEvent {
+private:
+  QString oldName;
+public:
+	RenameEvent( Task *task, QString& old);
+	QString toXML();
+};
+
+class SessionTimeEvent: public KarmEvent {
+private:
+  long newTotal, delta;
+public:
+	SessionTimeEvent( Task *task, long newTotal, long delta);
+	QString toXML();
+};
+
+class TotalTimeEvent: public KarmEvent {
+private:
+  long newTotal, delta;
+public:
+	TotalTimeEvent( Task *task, long newTotal, long delta );
+	QString toXML();
+};
+
 
 class Logging {
 
 private:
   Preferences *_preferences;
   static Logging *_instance;
-  void log( Task *task, short type, long minutes = 0);
+  void log( KarmEvent* event );
 
 public:
   static Logging *instance();
@@ -23,14 +74,10 @@ public:
   ~Logging();
   void start( Task *task);
   void stop( Task *task);
-  void newTotalTime( Task *task, long minutes);
-  void newSessionTime( Task *task, long minutes);
-  QString constructTaskName(Task *task);
-  QString escapeXML( QString string);
-
+  void rename( Task *task, QString& oldName);
+  void newTotalTime( Task *task, long minutes, long change);
+  void newSessionTime( Task *task, long minutes, long change);
 };
 
-#endif
-
-
 
+#endif
Index: task.cpp
===================================================================
RCS file: /home/kde/kdepim/karm/task.cpp,v
retrieving revision 1.19
diff -u -p -r1.19 task.cpp
--- task.cpp	24 Jan 2003 04:44:37 -0000	1.19
+++ task.cpp	28 Apr 2003 03:50:43 -0000
@@ -95,23 +95,27 @@ bool Task::isRunning() const
 
 void Task::setName( const QString& name )
 {
+  QString oldname = _name;
   _name = name;
+  _logging->rename( this, oldname );
   update();
 }
 
 void Task::setTotalTime ( long minutes )
 {
+  long oldtime = _totalTime;
   _totalTime = minutes;
   noNegativeTimes();
-  _logging->newTotalTime( this, _totalTime );
+  _logging->newTotalTime( this, _totalTime, (_totalTime - oldtime) );
   update();
 }
 
 void Task::setSessionTime ( long minutes )
 {
+  long oldtime = _sessionTime;
   _sessionTime = minutes;
   noNegativeTimes();
-  _logging->newSessionTime( this, _sessionTime );
+  _logging->newSessionTime( this, _sessionTime, (_sessionTime - oldtime) );
   update();
 }
 


_______________________________________________
kde-pim mailing list
kde-pim@mail.kde.org
http://mail.kde.org/mailman/listinfo/kde-pim
kde-pim home page at http://pim.kde.org/


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic