UserAle 1.0.4: New events and removed drag drop timer. Details in changelog.
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index cb28ff9..1fe6500 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -3,6 +3,17 @@
 Changelog
 =========
 
+1.0.4 (2016-08-04)
+------------------
+* New events UserAle is tracking:
+
+	* ``mousemove``
+	* ``resize``
+	* ``scroll``
+
+* Remove timer from ``dragdrop`` log due to incorrect time being recorded.
+* Session id is autogenerated if not passed into configuration.
+
 1.0.3 (2016-08-02)
 ------------------
 * New events UserAle is tracking:
diff --git a/docs/source/conf.py b/docs/source/conf.py
index da06dce..5b2b3bf 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -13,6 +13,8 @@
 import sys
 import os
 
+from userale.version import __version__
+
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
@@ -59,9 +61,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = u'1.0.3'
+version = __version__
 # The full version, including alpha/beta/rc tags.
-release = u'1.0.3'
+release = __version__
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst
index d40703b..1a8f8a2 100644
--- a/docs/source/quickstart.rst
+++ b/docs/source/quickstart.rst
@@ -39,7 +39,7 @@
 	    app = QApplication(sys.argv)    
 	    ex = TestApplication()
 	    # Initiate UserAle
-	    ale = Ale (output="mouse.log", user="testUser", version="0.0.1")
+	    ale = Ale (output="mouse.log", user="testUser", toolversion="0.0.1")
 	    # install globally
 	    app.installEventFilter (ale)
 
@@ -51,7 +51,7 @@
 ::
 
 	# Initiate UserAle
-	ale = Ale (output="mouse.log", user="testUser", version="0.0.1")
+	ale = Ale (output="mouse.log", user="testUser", toolversion="0.0.1")
 	# install globally
 	app.installEventFilter (ale)
 
diff --git a/userale/ale.py b/userale/ale.py
index 81ca35e..ec7f9fb 100644
--- a/userale/ale.py
+++ b/userale/ale.py
@@ -18,6 +18,7 @@
 from PyQt5.QtCore import QObject, QEvent
 import datetime
 import logging
+import uuid
 
 _ = StructuredMessage
 
@@ -28,7 +29,8 @@
                  interval=5000,
                  user=None,
                  session=None,
-                 version=None,
+                 toolname=None,
+                 toolversion=None,
                  keylog=False,
                  resolution=500,
                  shutoff=[]):
@@ -36,10 +38,11 @@
         :param output: [str] The file or url path to which logs will be sent
         :param interval: [int] The minimum time interval in ms betweeen batch transmission of logs
         :param user: [str] Identifier for the user of the application
-        :param session: [str] Optional session tag to track same user with multiple sessions
-        :param version: [str] The application version
+        :param session: [str] Session tag to track same user with multiple sessions. If a session is not provided, one will be created
+        :param toolname: [str] The application name
+        :param toolversion: [str] The application version
         :param keylog: [bool] Should detailed key logs be recorded. Default is False
-        :param resolution: [int] Delay in ms between instances of high frequency logs like mouseovers, scrolls, etc
+        :param resolution: [int] Delay in ms between instances of high frequency logs like movemoves, scrolls, etc
         :param shutoff: [list] Turn off logging for specific events
     
         An example log will appear like this:
@@ -49,15 +52,16 @@
             {
                 'target': 'testLineEdit',
                 'path': ['Example', 'testLineEdit'],
-                'clientTime': ,
+                'clientTime': '2016-08-03 16:12:03.460573',
                 'location': {'x': 82, 'y': 0},
                 'type': 'mousemove',
                 'userAction': 'true',
-                'details' : [],
+                'details' : {},
                 'userId': 'userABC1234',
-                'session': '765487cf34ert8dede5a562e4f3a7e12',
-                'toolVersion': 'myApplication',
-                'useraleVersion': '1.0.0 alpha'
+                'session': '5ee42ccc-852c-44d9-a937-28d7901e4ead',
+                'toolName': 'myApplication',
+                'toolVersion': '3.5.0',
+                'useraleVersion': '1.0.0'
             }
         """
 
@@ -67,7 +71,10 @@
         self.output = output
         self.interval = interval
         self.user = user
-        self.version = version
+        # Autogenerate session id if session is not configured
+        self.session = session if session is not None else str (uuid.uuid4 ())
+        self.toolname = toolname
+        self.toolversion = toolversion
         self.keylog = keylog
         self.resolution = resolution
         self.shutoff = shutoff
@@ -81,10 +88,6 @@
                                 filename=self.output,
                                 format='%(message)s')
 
-        # Drag/Drop - track duration
-        self.dd = 0
-        self.timer = False
-
         # Mapping of all events to methods
         self.map = {
             QEvent.MouseButtonPress: {'mousedown': self.handleMouseEvents},
@@ -97,7 +100,10 @@
             QEvent.DragMove: {'dragmove': self.handleDragEvents},
             QEvent.Drop: {'dragdrop': self.handleDragEvents},
             QEvent.KeyPress: {'keypress': self.handleKeyEvents},
-            QEvent.KeyRelease: {'keyrelease': self.handleKeyEvents}
+            QEvent.KeyRelease: {'keyrelease': self.handleKeyEvents},
+            QEvent.Move: {'move': self.handleMoveEvents},
+            QEvent.Resize: {'resize': self.handleResizeEvents},
+            QEvent.Scroll: {'scroll': self.handleScrollEvents}
         }
 
         # Turn on/off keylogging & remove specific filters
@@ -106,10 +112,10 @@
             if name in self.shutoff or (not self.keylog and (name == 'keypress' or name == 'keyrelease')):
                 del self.map [key]
 
-    def eventFilter(self, object, event):
+    def eventFilter (self, object, event):
         '''
         :param object: [QObject] The object being watched.
-        :param event: [QEvent] 
+        :param event: [QEvent] The event triggered by a user action.
         :return: [bool] Return true in order to filter the event out (stop it from being handled further). Otherwise return false.
         
         Filters events for the watched object (in this case, QApplication)
@@ -118,16 +124,31 @@
         data = None
         t = event.type ()
 
-        if len (object.children ()) > 0 and t in self.map:
+        # if self.__valid (object) and t in self.map:
+        # if len (object.children ()) > 0 and t in self.map:
+        if t in self.map:
             name = list (self.map [t].keys())[0]
             method = list (self.map [t].values())[0]
             data = method (name, event, object)
 
-        # self.logs.append (data)
         if data is not None:
             self.logger.info (_(data))
         return super(Ale, self).eventFilter (object, event)
 
+    def __valid (self, object):
+        # Parent is none?
+        #   capture it
+        # Parent exists - don't capture/capture Child/current object
+        
+        # Solo node
+        if object.parent () is None and len (object.children ()) == 0:
+            return True
+
+        # Leaf node
+        if object.parent () is not None and len (object.children ()) == 0:
+            return True
+        return False
+
     def getSelector (self, object):
         """
         :param object: [QObject] The base class for all Qt objects.
@@ -135,7 +156,7 @@
 
         Get target object's name (object defined by user or object's meta class name)
         """
-
+        
         return object.objectName () if object.objectName () else object.staticMetaObject.className ()
 
     def getLocation (self, event):
@@ -182,9 +203,6 @@
         :return: [dict] A userale log describing a mouse event.
 
         Returns the userale log representing all mouse event data. 
-
-        .. code-block:: python
-
         """
         
         return self.__create_msg (event_type, event, object)
@@ -213,20 +231,11 @@
         """
 
         details = {}
-        if event_type == 'dragenter':
-            if self.timer == False:
-                # Only start the timer on the first dragenter encountered
-                self.dd = datetime.datetime.now ()
-                self.timer = True
-            details = {"source" : self.getSelector (event.source())}
-        elif event_type == 'dragdrop':
-            details = {"elapsed" : str (datetime.datetime.now () - self.dd),
-                       "source" : self.getSelector (event.source())}
-            self.dd = 0
-            self.timer = False
-        else:
-            # drag move/leave event - ignore
-            pass
+
+        try:
+            details ["source"] = self.getSelector (event.source())      
+        except:
+            details ["source"] = None
 
         return self.__create_msg (event_type, event, object, details=details)
 
@@ -239,9 +248,9 @@
 
         Returns the userale log representing all move events. 
         """
-
-        pass
-
+        details = {"oldPos" : {"x" : event.oldPos ().x (), "y" : event.oldPos ().y ()}}
+        return self.__create_msg (event_type, event, object, details=details)
+        
     def handleResizeEvents (self, event_type, event, object):
         """
         :param event_type: [str] The string representation of the type of event being triggered by the user.
@@ -251,8 +260,9 @@
 
         Returns the userale log representing all resize events. 
         """
-
-        pass
+        details = {"size" : {"height" : event.size ().height (), "width" : event.size ().width ()},
+                   "oldSize":  {"height" : event.oldSize ().height (), "width" : event.oldSize ().width ()}}
+        return self.__create_msg (event_type, event, object, details=details)
 
     def handleScrollEvents (self, event_type, event, object):
         """
@@ -263,8 +273,7 @@
 
         Returns the userale log representing all scroll events. 
         """
-
-        pass
+        return self.__create_msg (event_type, event, object)
 
     def __create_msg (self, event_type, event, object, details={}):
         """
@@ -281,7 +290,8 @@
             'details' : details,
             'userId': self.user,
             'session': self.session,
-            'toolVersion': self.version,
+            'toolName': self.toolname,
+            'toolVersion': self.toolversion,
             'useraleVersion': __version__
         }
 
diff --git a/userale/version.py b/userale/version.py
index fd3afff..8fb4bc6 100644
--- a/userale/version.py
+++ b/userale/version.py
@@ -18,4 +18,4 @@
 and parsed by ``setup.py``.
 """
 
-__version__ = "1.0.3"
\ No newline at end of file
+__version__ = "1.0.4"
\ No newline at end of file