]> jfr.im git - irc/kvirc/kvirc-scripts.git/commitdiff
Sample newsticker script ported to the 4.0.0 addon system
authorSzymon Tomasz Stefanek <redacted>
Tue, 22 Jun 2010 02:58:52 +0000 (02:58 +0000)
committerSzymon Tomasz Stefanek <redacted>
Tue, 22 Jun 2010 02:58:52 +0000 (02:58 +0000)
28 files changed:
newsticker4/init.kvs [new file with mode: 0644]
newsticker4/pics/newsticker_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_32.png [new file with mode: 0644]
newsticker4/pics/newsticker_auto_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_close_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_configure_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_first_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_last_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_next_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_next_unread_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_noauto_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_prev_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_say2_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_say_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_source_disabled_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_source_enabled_16.png [new file with mode: 0644]
newsticker4/pics/newsticker_viewonline_16.png [new file with mode: 0644]
newsticker4/src/actions.kvs [new file with mode: 0644]
newsticker4/src/aliases.kvs [new file with mode: 0644]
newsticker4/src/configuration.kvs [new file with mode: 0644]
newsticker4/src/controller.kvs [new file with mode: 0644]
newsticker4/src/main.kvs [new file with mode: 0644]
newsticker4/src/qtwrapper.kvs [new file with mode: 0644]
newsticker4/src/rssentry.kvs [new file with mode: 0644]
newsticker4/src/rssentrylist.kvs [new file with mode: 0644]
newsticker4/src/rssreader.kvs [new file with mode: 0644]
newsticker4/src/source.kvs [new file with mode: 0644]
newsticker4/src/window.kvs [new file with mode: 0644]

diff --git a/newsticker4/init.kvs b/newsticker4/init.kvs
new file mode 100644 (file)
index 0000000..1f7d5ec
--- /dev/null
@@ -0,0 +1,26 @@
+# script newsticker for KVIrc :)
+# Written by Szymon Stefanek (2006)
+
+
+# register the script: this must be the first instruction executed
+# since it will abort with an error when a greater version is already installed
+addon.register("newsticker","1.2.0",$tr("Newsticker: The RSS News Reader","newsticker"),$tr("Displays RSS news feeds from various sources","newsticker"),"3.2.0.99.20051230",newsticker_32.png)
+{
+       # This is our uninstall callback: it will be called by KVIrc when addon.uninstall is invoked
+       newsticker::uninstallfiles
+}
+
+addon.setconfigurecallback(newsticker)
+{
+       newsticker::configure
+}
+
+
+include "src/main.kvs"
+
+
+# make sure any previous instance is closed
+newsticker::close
+# show it up :)
+newsticker::show
+
diff --git a/newsticker4/pics/newsticker_16.png b/newsticker4/pics/newsticker_16.png
new file mode 100644 (file)
index 0000000..0cac216
Binary files /dev/null and b/newsticker4/pics/newsticker_16.png differ
diff --git a/newsticker4/pics/newsticker_32.png b/newsticker4/pics/newsticker_32.png
new file mode 100644 (file)
index 0000000..eabf8cb
Binary files /dev/null and b/newsticker4/pics/newsticker_32.png differ
diff --git a/newsticker4/pics/newsticker_auto_16.png b/newsticker4/pics/newsticker_auto_16.png
new file mode 100644 (file)
index 0000000..5035d9e
Binary files /dev/null and b/newsticker4/pics/newsticker_auto_16.png differ
diff --git a/newsticker4/pics/newsticker_close_16.png b/newsticker4/pics/newsticker_close_16.png
new file mode 100644 (file)
index 0000000..6323241
Binary files /dev/null and b/newsticker4/pics/newsticker_close_16.png differ
diff --git a/newsticker4/pics/newsticker_configure_16.png b/newsticker4/pics/newsticker_configure_16.png
new file mode 100644 (file)
index 0000000..f9c503e
Binary files /dev/null and b/newsticker4/pics/newsticker_configure_16.png differ
diff --git a/newsticker4/pics/newsticker_first_16.png b/newsticker4/pics/newsticker_first_16.png
new file mode 100644 (file)
index 0000000..4c8b73a
Binary files /dev/null and b/newsticker4/pics/newsticker_first_16.png differ
diff --git a/newsticker4/pics/newsticker_last_16.png b/newsticker4/pics/newsticker_last_16.png
new file mode 100644 (file)
index 0000000..805f764
Binary files /dev/null and b/newsticker4/pics/newsticker_last_16.png differ
diff --git a/newsticker4/pics/newsticker_next_16.png b/newsticker4/pics/newsticker_next_16.png
new file mode 100644 (file)
index 0000000..24a89b5
Binary files /dev/null and b/newsticker4/pics/newsticker_next_16.png differ
diff --git a/newsticker4/pics/newsticker_next_unread_16.png b/newsticker4/pics/newsticker_next_unread_16.png
new file mode 100644 (file)
index 0000000..c3d1a06
Binary files /dev/null and b/newsticker4/pics/newsticker_next_unread_16.png differ
diff --git a/newsticker4/pics/newsticker_noauto_16.png b/newsticker4/pics/newsticker_noauto_16.png
new file mode 100644 (file)
index 0000000..faa19ed
Binary files /dev/null and b/newsticker4/pics/newsticker_noauto_16.png differ
diff --git a/newsticker4/pics/newsticker_prev_16.png b/newsticker4/pics/newsticker_prev_16.png
new file mode 100644 (file)
index 0000000..6992aa7
Binary files /dev/null and b/newsticker4/pics/newsticker_prev_16.png differ
diff --git a/newsticker4/pics/newsticker_say2_16.png b/newsticker4/pics/newsticker_say2_16.png
new file mode 100644 (file)
index 0000000..c310fe2
Binary files /dev/null and b/newsticker4/pics/newsticker_say2_16.png differ
diff --git a/newsticker4/pics/newsticker_say_16.png b/newsticker4/pics/newsticker_say_16.png
new file mode 100644 (file)
index 0000000..dab56c9
Binary files /dev/null and b/newsticker4/pics/newsticker_say_16.png differ
diff --git a/newsticker4/pics/newsticker_source_disabled_16.png b/newsticker4/pics/newsticker_source_disabled_16.png
new file mode 100644 (file)
index 0000000..ab43352
Binary files /dev/null and b/newsticker4/pics/newsticker_source_disabled_16.png differ
diff --git a/newsticker4/pics/newsticker_source_enabled_16.png b/newsticker4/pics/newsticker_source_enabled_16.png
new file mode 100644 (file)
index 0000000..03ef9a5
Binary files /dev/null and b/newsticker4/pics/newsticker_source_enabled_16.png differ
diff --git a/newsticker4/pics/newsticker_viewonline_16.png b/newsticker4/pics/newsticker_viewonline_16.png
new file mode 100644 (file)
index 0000000..03ef9a5
Binary files /dev/null and b/newsticker4/pics/newsticker_viewonline_16.png differ
diff --git a/newsticker4/src/actions.kvs b/newsticker4/src/actions.kvs
new file mode 100644 (file)
index 0000000..f1687c6
--- /dev/null
@@ -0,0 +1,5 @@
+action.create -t="tools" (newsticker::toggle,$tr("Show Newsticker","newsticker"),$tr("Shows the Newsticker Window","newsticker"),"newsticker_32.png","newsticker_16.png")
+{
+       newsticker::show
+}
+
diff --git a/newsticker4/src/aliases.kvs b/newsticker4/src/aliases.kvs
new file mode 100644 (file)
index 0000000..9b8e968
--- /dev/null
@@ -0,0 +1,45 @@
+alias(newsticker::close)
+{
+       # On versions of KVIrc that support it, be nice and
+       # Avoid global namespace pollution: use $object.instances()
+       # to implement the singleton
+       if($version("s") >= "20061110")
+       {
+               %aInstances = $objects.instances(newsticker::window)
+               if(%aInstances)
+               {
+                       # There should be only one.. but well...
+                       foreach(%x,%aInstances)
+                               delete %x
+               }
+       } else {
+               if($objects.exists(%G_NewstickerWindowHandle))
+                       delete %G_NewstickerWindowHandle
+               unset %G_NewstickerWindowHandle
+       }
+}
+
+alias(newsticker::show)
+{
+       if($version("s") >= "20061110")
+       {
+               if($objects.instances(newsticker::window)) 
+               {
+                       %dock=$objects.instances(newsticker::window)[0]
+                       if (%dock->$isVisible()) return
+                       %dock->$dock(l)
+                       %dock->$show()
+                       return          
+               }
+               %h = $new(newsticker::window,0,"newsticker")
+               %h->$dock(l)
+               %h->$show()
+       } else {
+               if($objects.exists(%G_NewstickerWindowHandle))return
+               %G_NewstickerWindowHandle = $new(newsticker::window,0,"newsticker")
+               %G_NewstickerWindowHandle->$dock(l)
+               %G_NewstickerWindowHandle->$show()
+       }
+}
+
+
diff --git a/newsticker4/src/configuration.kvs b/newsticker4/src/configuration.kvs
new file mode 100644 (file)
index 0000000..3823b07
--- /dev/null
@@ -0,0 +1,760 @@
+class(newsticker::core::configuration::sourceeditor,dialog)
+{
+       constructor()
+       {
+               if ($str.contains($features(),"QT4"))@$setWindowTitle($tr("Edit source","newsticker"))
+                 else @$setWindowTitle($tr("Edit source","newsticker"))
+               %l = $new(layout,$this)
+
+               %lb = $new(label,$this)
+               %lb->$setText($tr("Source Name:","newsticker"))
+               %l->$addWidget(%lb,0,0)
+
+               @%m_hSourceNameEdit = $new(lineedit,$this)
+               %l->$addMultiCellWidget(@%m_hSourceNameEdit,0,0,1,3)
+
+               %lb = $new(label,$this)
+               %lb->$setText($tr("Source Url:","newsticker"))
+               %l->$addWidget(%lb,1,0)
+
+               @%m_hSourceUrlEdit = $new(lineedit,$this)
+               %l->$addMultiCellWidget(@%m_hSourceUrlEdit,1,1,1,3)
+
+               %lb = $new(label,$this)
+               %lb->$setText($tr("Language:","newsticker"))
+               %l->$addWidget(%lb,2,0)
+
+               @%m_hSourceLanguageEdit = $new(lineedit,$this)
+               %l->$addMultiCellWidget(@%m_hSourceLanguageEdit,2,2,1,3)
+
+               %lb = $new(label,$this)
+               %lb->$setText($tr("Category:","newsticker"))
+               %l->$addWidget(%lb,3,0)
+
+               @%m_hSourceTopicEdit = $new(lineedit,$this)
+               %l->$addMultiCellWidget(@%m_hSourceTopicEdit,3,3,1,3)
+
+               @%m_hSourceUseNotfierCheck = $new(checkbox,$this)
+               @%m_hSourceUseNotfierCheck->$setText($tr("Use notifier","newsticker"))
+               @%m_hSourceUseNotfierCheck->$settooltip($tr("Use the notifier window to inform about news","newsticker"))
+               %l->$addMultiCellWidget(@%m_hSourceUseNotfierCheck,4,4,0,3)
+
+               %b = $new(button,$this)
+               %b->$setText($tr("Cancel","newsticker"))
+               objects.connect %b "clicked" $this "cancelClicked"
+               %l->$addWidget(%b,6,2)
+
+               %b = $new(button,$this)
+               %b->$setText($tr("OK","newsticker"))
+               objects.connect %b "clicked" $this "okClicked"
+               %l->$addWidget(%b,6,3)
+               
+               %l->$setMargin(9)
+               %l->$setSpacing(3)
+
+               %l->$setRowStretch(4,100)
+               if ($str.contains($features(),"QT4")) %l->$setColumnStretch(1,100)
+                 else %l->$setColumnStretch(1,100)
+       }
+
+       edit($0 = source,$1 = bIsNew)
+       {
+               @%m_bIsNewItem = $1
+               @%m_hSource = $0
+               @%m_hSourceNameEdit->$setText($0->$text(0))
+               @%m_hSourceUseNotfierCheck->$setChecked($str.equal($tr("Yes","newsticker"),$0->$text(1)))
+               @%m_hSourceLanguageEdit->$setText($0->$text(2))
+               @%m_hSourceTopicEdit->$setText($0->$text(3))
+               @%m_hSourceUrlEdit->$setText($0->$text(4))
+       }
+
+       destructor()
+       {
+       }
+       
+       closeEvent()
+       {
+               delete $this
+       }
+       
+       cancelClicked()
+       {
+               if(@%m_bIsNewItem)
+               {
+                       // new item cancelled
+                       if($objects.exists(@%m_hSource))
+                               delete @%m_hSource
+               }
+
+               delete $this
+       }
+       
+       errorMessage($0 = msg)
+       {
+               dialog.message($tr("Error","newsticker"),$0,"critical",$tr("Ok","Newsticker"))
+               {
+                       /* just do nothing */
+               }
+       }
+       
+       commit()
+       {
+               if(!$objects.exists(@%m_hSource))
+               {
+                       $$->$errorMessage($tr("Oops.. internal error: the listviewitem object no longer exists","newsticker"))
+                       return $false
+               }
+               %n = @%m_hSourceNameEdit->$text()
+               if(%n == "")%n = $tr("Unnamed","newsticker")
+               %u = @%m_hSourceUrlEdit->$text()
+               if(%u == "")
+               {
+                       $$->$errorMessage($tr("The url can't be empty!","newsticker"))
+                       return $false
+               }
+               if(!$str.match("http://*",%u,"e"))
+               {
+                       $$->$errorMessage($tr("The url must start with http://","newsticker"))
+                       return $false
+               }
+               %l = @%m_hSourceLanguageEdit->$text()
+               %t = @%m_hSourceTopicEdit->$text()
+               @%m_hSource->$setText(0,%n)
+               if(@%m_hSourceUseNotfierCheck->$isChecked()){
+                       @%m_hSource->$setText(1,$tr("Yes","newsticker"))
+//                     @%m_hSource->$setpixmap(1,11)
+               } else {
+                       @%m_hSource->$setText(1,$tr("No","newsticker"))
+//                     @%m_hSource->$setpixmap(1,$null)
+               }
+               @%m_hSource->$setText(2,%l)
+               @%m_hSource->$setText(3,%t)
+               @%m_hSource->$setText(4,%u)
+               return $true;
+       }
+       
+       okClicked()
+       {
+               if(!$$->$commit())return $false
+               delete $this
+       }
+}
+
+
+class(newsticker::core::configuration::dialog,dialog)
+{
+       internal createListViewItem($0 = name,$1 = url,$2 = topic,$3 = lang,$4 = enabled,$5 = use notifier,$6 = last notification)
+       {
+               %lvi = $new(listviewitem,@%m_hListView)
+               if ($str.contains($features(),"QT4"))
+                       %lvi->$setFlags(editable,selectable,enabled,userCheckable)
+               else %lvi->$setCheckable($true);
+               if($4)
+               {
+                       %lvi->$setPixmap(0,"newsticker_source_enabled_16.png")
+                       %lvi->$setChecked($true);
+               } else {
+                       %lvi->$setPixmap(0,"newsticker_source_disabled_16.png")
+                       %lvi->$setChecked($false)
+               }
+               %lvi->$setText(0,$0)
+               if($5){
+//                     %lvi->$setixmap(1,11)
+                       %lvi->$setChecked($true);
+                       %lvi->$setText(1,$tr("Yes","newsticker"))
+               } else {
+//                     %lvi->$setPixmap(1,$null)
+                       %lvi->$setText(1,$tr("No","newsticker"))
+               }
+               %lvi->$setText(2,$3)
+               %lvi->$setText(3,$2)
+               %lvi->$setText(4,$1)
+               %lvi->%lastNotification = $6
+               return %lvi
+       }
+
+       internal fillSourceListView()
+       {
+               @%m_hListView->$clear()
+       
+               %c = $newsticker::core::configuration()
+               %l = %c->$sourceList()
+               
+               if(!%l->$moveFirst())return;
+               do {
+                       %s = %l->$current()
+                       $$->$createListViewItem(%s->$name(),%s->$url(),%s->$topic(),%s->$language(),%s->$enabled(),%s->$useNotifier(),%s->$lastNotification())
+               } while(%l->$moveNext())
+       }
+       
+       internal commit()
+       {
+               %l = $new(list)
+
+               %lvi = @%m_hListView->$firstChild()
+               while(%lvi)
+               {
+                       %s = $new(newsticker::core::configuration::source,%l)
+               #       debug "got item data:" %lvi->$text(0),%lvi->$text(3),%lvi->$text(1),%lvi->$text(2),%lvi->$isChecked()
+                       %s->$set(%lvi->$text(0),%lvi->$text(4),%lvi->$text(2),%lvi->$text(3),%lvi->$isChecked(),$($tr("Yes","newsticker") == %lvi->$text(1)),%lvi->%lastNotification)
+                       %l->$append(%s)
+                       if ($str.contains($features(),"QT4")) %lvi = @%m_hListView->$nextSibling()
+                       else %lvi = %lvi->$nextSibling()
+               }
+
+               %c = $newsticker::core::configuration()
+               %c->$setSourceList(%l)
+               %c->$setStripHtmlTags(@%m_hStripHtmlTagsCheck->$isChecked())
+               %c->$setRemoveFeedFiles(@%m_hRemoveFeedFilesCheck->$isChecked())
+               %c->$setFeedRefetchTimeoutInSeconds(@%m_hFeedRefetchTimeoutInSecondsLineEdit->$text())
+               return $true
+       }
+
+       internal createSourcesPage()
+       {
+               %w = $new(widget,@%m_hTabWidget)
+               
+               %l = $new(layout,%w)
+
+               @%m_hListView = $new(listviewwrapper,%w)
+               %l->$addMultiCellWidget(@%m_hListView,0,0,0,4)
+
+               @%m_hListView->$addColumn($tr("Name","newsticker"),230)
+               @%m_hListView->$addColumn($tr("Use notifier","newsticker"),120)
+               @%m_hListView->$addColumn($tr("Language","newsticker"),120)
+               @%m_hListView->$addColumn($tr("Topic","newsticker"),120)
+               @%m_hListView->$addColumn($tr("Url","newsticker"),300)
+               @%m_hListView->$setAllColumnsShowFocus($true)
+               objects.connect @%m_hListView "selectionChanged" $this "sourceListSelectionChanged"
+
+               @%m_hLoadDefaultsButton = $new(button,%w)
+               @%m_hLoadDefaultsButton->$setText($tr("Defaults","newsticker"))
+               %l->$addWidget(@%m_hLoadDefaultsButton,1,0)
+               objects.connect @%m_hLoadDefaultsButton "clicked"  $this "loadDefaultsClicked"
+
+               @%m_hAddButton = $new(button,%w)
+               @%m_hAddButton->$setText($tr("New...","newsticker"))
+               %l->$addWidget(@%m_hAddButton,1,2)
+               objects.connect @%m_hAddButton "clicked"  $this "addClicked"
+
+               @%m_hRemoveButton = $new(button,%w)
+               @%m_hRemoveButton->$setText($tr("Remove","newsticker"))
+               %l->$addWidget(@%m_hRemoveButton,1,3)
+               objects.connect @%m_hRemoveButton "clicked"  $this "removeClicked"
+
+               @%m_hEditButton = $new(button,%w)
+               @%m_hEditButton->$setText($tr("Edit...","newsticker"))
+               %l->$addWidget(@%m_hEditButton,1,4)
+               objects.connect @%m_hEditButton "clicked"  $this "editClicked"
+
+               @%m_hTabWidget->$addTab(%w,$tr("Sources","newsticker"))
+
+               %l->$setMargin(5)
+               %l->$setSpacing(2)
+               %l->$setRowStretch(0,100)
+               if ($str.contains($features(),"QT4"))
+               {
+                     %l->$setColumnStretch(1,0)
+                     %l->$setColumnStretch(1,100)
+                     %l->$setColumnStretch(2,0)
+                     %l->$setColumnStretch(3,0)
+                     %l->$setColumnStretch(4,0)
+               }
+               else{
+                     %l->$setColumnStretch(1,0)
+                     %l->$setColumnStretch(1,100)
+                     %l->$setColumnStretch(2,0)
+                     %l->$setColumnStretch(3,0)
+                     %l->$setColumnStretch(4,0)
+             }
+       }
+
+       internal createOtherPage()
+       {
+               %w = $new(widget,@%m_hTabWidget)
+               
+               %l = $new(layout,%w)
+
+               @%m_hTabWidget->$addTab(%w,$tr("Other","newsticker"))
+
+               @%m_hStripHtmlTagsCheck = $new(checkbox,%w)
+               @%m_hStripHtmlTagsCheck->$setText($tr("Strip Html Tags","newsticker"))
+               %l->$addMultiCellWidget(@%m_hStripHtmlTagsCheck,0,0,0,3)
+
+               @%m_hRemoveFeedFilesCheck = $new(checkbox,%w)
+               @%m_hRemoveFeedFilesCheck->$setText($tr("Remove Downloaded RSS Feed Files","newsticker"))
+               %l->$addMultiCellWidget(@%m_hRemoveFeedFilesCheck,1,1,0,3)
+               
+               %label = $new(label,%w)
+               %label->$setText($tr("Refetch RSS Feeds After","newsticker"))
+               %l->$addMultiCellWidget(%label,2,2,0,1)
+               
+               @%m_hFeedRefetchTimeoutInSecondsLineEdit = $new(lineedit,%w)
+               @%m_hFeedRefetchTimeoutInSecondsLineEdit->$setInputMask("99000")
+               %l->$addMultiCellWidget(@%m_hFeedRefetchTimeoutInSecondsLineEdit,2,2,2,2)
+
+               %label = $new(label,%w)
+               %label->$setText("  "$tr("seconds","newsticker"))
+               %l->$addMultiCellWidget(%label,2,2,3,3)
+
+               %l->$setMargin(15)
+               %l->$setSpacing(4)
+               if ($str.contains($features(),"QT4")) %l->$setColumnStretch(0,1)
+               else %l->$setColumnStretch(0,1)
+               %l->$setRowStretch(5,1)
+       }
+
+       constructor()
+       {
+               if ($str.contains($features(),"QT4"))@$setWindowTitle($tr("Newsticker Configuration","newsticker"))
+                 else @$setWindowTitle($tr("Newsticker Configuration","newsticker"))
+               %l = $new(layout,$this)
+
+               @%m_hTabWidget = $new(tabwidget,$this)
+               
+               $$->$createSourcesPage()
+               $$->$createOtherPage()
+               // FIXME: an "about" page ?
+               
+               %l->$addMultiCellWidget(@%m_hTabWidget,0,0,0,2)
+
+               %b = $new(button,$this)
+               %b->$setText($tr("Cancel","newsticker"))
+               %b->$setMinimumWidth(80)
+               objects.connect %b "clicked" $this "cancelClicked"
+               %l->$addWidget(%b,1,1)
+
+               %b = $new(button,$this)
+               %b->$setMinimumWidth(80)
+               %b->$setText($tr("OK","newsticker"))
+               objects.connect %b "clicked" $this "okClicked"
+               %l->$addWidget(%b,1,2)
+               
+               %l->$setMargin(5)
+               %l->$setSpacing(2)
+               %l->$setRowStretch(0,100)
+               if ($str.contains($features(),"QT4"))
+               {
+                     %l->$setColumnStretch(0,100)
+                     %l->$setColumnStretch(1,0)
+                     %l->$setColumnStretch(2,0)
+               }
+               else{
+                     %l->$setColumnStretch(0,100)
+                     %l->$setColumnStretch(1,0)
+                     %l->$setColumnStretch(2,0)
+               }
+               $$->$display()
+               
+               $$->$sourceListSelectionChanged()
+       }
+
+       display()
+       {
+               %c = $newsticker::core::configuration()
+               # debug "DISPLAY CALLED"
+               $$->$fillSourceListView()
+               @%m_hStripHtmlTagsCheck->$setChecked(%c->$stripHtmlTags())
+               @%m_hRemoveFeedFilesCheck->$setChecked(%c->$removeFeedFiles())
+               @%m_hFeedRefetchTimeoutInSecondsLineEdit->$setText(%c->$feedRefetchTimeoutInSeconds())
+               
+       }
+       
+       destructor()
+       {
+               %G_newstickerConfigurationDialog = $null
+               # debug "CONFIGURATION DIALOG DESTRUCTOR CALLED"
+       }
+       
+       sourceListSelectionChanged()
+       {
+               @%m_hRemoveButton->$setEnabled(@%m_hListView->$selectedItem())
+               @%m_hEditButton->$setEnabled(@%m_hListView->$selectedItem())
+       }
+
+       addClicked()
+       {
+               %d = $new(newsticker::core::configuration::sourceeditor,$this)
+               %d->$edit($$->$createListViewItem($tr("New RSS Source","newsticker"),$tr("http://url.to.your.rss.feed","newsticker"),"General","EN",$false,$false),$true)
+               %d->$show()
+       }
+       
+       removeClicked()
+       {
+               %lvi = @%m_hListView->$selectedItem()
+               if(!%lvi)return
+               delete %lvi
+       }
+       
+       editClicked()
+       {
+               %lvi = @%m_hListView->$selectedItem()
+               if(!%lvi)return
+               %d = $new(newsticker::core::configuration::sourceeditor,$this)
+               %d->$edit(%lvi,$false)
+               %d->$show()
+       }
+       
+       loadDefaultsClicked()
+       {
+               if(!$$->$commit())return
+               %c = $newsticker::core::configuration()
+               %c->$loadDefaults()
+               $$->$display()
+       }
+
+       okClicked()
+       {
+               if(!$$->$commit())return
+               %c = $newsticker::core::configuration()
+               %c->$save()
+               %c->$configurationDialogCommitted()
+               delete $this
+       }
+       
+       cancelClicked()
+       {
+               delete $this
+       }
+       
+       internal closeEvent()
+       {
+               delete $this
+       }
+}
+
+
+class(newsticker::core::configuration::source)
+{
+       //@%m_szUrl
+       //@%m_szName
+       //@%m_bEnabled
+       //@%m_szLanguage
+       //@%m_szTopic
+       //@%m_bUseNotifier
+       //@%m_tLastNotification
+
+       url(){ return @%m_szUrl; }
+       name(){ return @%m_szName; }
+       enabled(){ return @%m_bEnabled; }
+       language(){ return @%m_szLanguage; }
+       topic(){ return @%m_szTopic; }
+       useNotifier(){ return @%m_bUseNotifier; }
+       lastNotification(){ return @%m_tLastNotification; }
+
+       setLastNotification($0 = date)
+       {
+               @%m_tLastNotification = $0
+       }
+
+       set($0 = name,$1 = url,$2 = language,$3 = topic,$4 = enabled,$5 = use notifier,$6 = last notification)
+       {
+               @%m_szName = $0
+               @%m_szUrl = $1
+               @%m_szLanguage = $2
+               @%m_szTopic = $3
+               @%m_bEnabled = $4
+               @%m_bUseNotifier = $5
+               @%m_tLastNotification = $6
+       }
+}
+#debug creating class configuration 2
+if ($classDefined(newsticker::core::configuration)) objects.killClass newsticker::core::configuration
+class(newsticker::core::configuration)
+{
+       // @%m_lSources list of newsticker::core::configuration::source, owned
+       // @%m_bStripHtmlTags
+       // @%m_bRemoveFeedFiles
+       // @%m_uFeedRefetchTimeoutInSeconds
+
+       constructor()
+       {
+               @%m_lSources = $null
+               $$->$load()
+       }
+       
+       destructor()
+       {
+               if(@%m_lSources)delete @%m_lSources
+       }
+       
+       findSourceByName($0 = name)
+       {
+               if(!@%m_lSources)return $nothing
+               if(!@%m_lSources->$moveFirst())return $nothing
+               do {
+                       %s = @%m_lSources->$current()
+                       if(%s->$name() == $0)return %s
+               } while(@%m_lSources->$moveNext())
+               return $nothing
+       }
+
+       internal createSource($0 = name,$1 = url,$2 = language,$3 = topic,$4 = enabled,$5 = use notifier,$6 = last notification)
+       {
+               %s = $new(newsticker::core::configuration::source,@%m_lSources)
+               %s->$set($0,$1,$2,$3,$4,$5,$6)
+               @%m_lSources->$append(%s)
+       }
+
+       internal createSourceIfNotExists($0 = name,$1 = url,$2 = language,$3 = topic,$4 = enabled,$5 = use notifier)
+       {
+               if($$->$findSourceByName($0))return
+               $$->$createSource($0,$1,$2,$3,$4,$5,"0001/01/01 00:00")
+       }
+       
+       loadDefaults()
+       {
+               $$->$createSourceIfNotExists("Slashdot","http://rss.slashdot.org/Slashdot/slashdot","EN","Technology",$true,$false)
+               $$->$createSourceIfNotExists("ANSA.it - English News","http://www.ansa.it/main/notizie/awnplus/english/synd/ansait_awnplus_english_medsynd_Today_Idx.xml","EN","Geneal",$false)
+               $$->$createSourceIfNotExists("ANSA.it - Top News","http://www.ansa.it/main/notizie/awnplus/topnews/synd/ansait_awnplus_topnews_medsynd_Today_Idx.xml","IT","General",$false,$false)
+               $$->$createSourceIfNotExists("ANSA.it - Sport","http://www.ansa.it/main/notizie/awnplus/sport/synd/ansait_awnplus_sport_medsynd_Today_Idx.xml","IT","Sport",$false,$false)
+               $$->$createSourceIfNotExists("KDE dot News","http://www.kde.org/dotkdeorg.rdf","EN","Technology",$false,$false)
+               $$->$createSourceIfNotExists("Yahoo - Top Stories","http://rss.news.yahoo.com/rss/topstories","EN","General",$false,$false)
+               $$->$createSourceIfNotExists("Yahoo - Technology","http://rss.news.yahoo.com/rss/tech","EN","Technology",$false,$false)
+               $$->$createSourceIfNotExists("Yahoo - NASA/Spaceshuttle","http://rss.news.yahoo.com/rss/nasashuttle","EN","Space",$false,$false)
+               $$->$createSourceIfNotExists("Yahoo - World","http://rss.news.yahoo.com/rss/world","EN","General",$false,$false)
+               
+               // Super thnx to Etherea for hunting up all these sources :)
+
+               $$->$createSourceIfNotExists("PosterWire","http://www.posterwire.com/rss","EN","Movies",$false,$false)
+               $$->$createSourceIfNotExists("Moving Image Archive","http://www.archive.org/services/collection-rss.php?mediatype=movies","EN","Movies",$false,$false)
+               $$->$createSourceIfNotExists("Alternative Film guide","http://www.altfg.com/blog/wp-feed.php","EN","Movies",$false,$false)
+               $$->$createSourceIfNotExists("ODEO PODCast","http://odeo.com/tag/cinema/rss.xml","EN","Movies POD",$false,$false)
+               $$->$createSourceIfNotExists("Cineblog.it","http://www.cineblog.it/rss2.xml","IT","Movies",$false,$false)
+               $$->$createSourceIfNotExists("Topix.net","http://rss.topix.net/rss/arts/cinema.xml","EN","Movies",$false,$false)
+               $$->$createSourceIfNotExists("The Movie Show","http://movie.thepodcastnetwork.com/feed/","EN","Movies POD",$false,$false)
+               $$->$createSourceIfNotExists("FilmFocus News","http://www.filmfocus.co.uk/rss/filmfocus-news.asp","EN","Movies",$false,$false)
+               $$->$createSourceIfNotExists("FilmFocus Home Entertainment","http://www.filmfocus.co.uk/rss/filmfocus-home.asp","EN","Movies",$false,$false)
+               $$->$createSourceIfNotExists("FilmFocus Interviews","http://www.filmfocus.co.uk/rss/filmfocus-interviews.asp","EN","Movies",$false,$false)
+               $$->$createSourceIfNotExists("FilmFocus Competition","http://www.filmfocus.co.uk/rss/filmfocus-competitions.asp","EN","Movies",$false,$false)
+               $$->$createSourceIfNotExists("iTunes Classical","http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStore.woa/wpa/MRSS/newreleases/sf=143441/genre=100000000/limit=10/rss.xml","EN","Music",$false,$false)
+               $$->$createSourceIfNotExists("Early Music","http://em.oxfordjournals.org/rss/current.xml","EN","Music",$false,$false)
+               $$->$createSourceIfNotExists("MSN Top Music","http://entertainment.msn.com/services/rss.aspx?chartname=topsongs","EN","Music",$false,$false)
+               $$->$createSourceIfNotExists("MSN Top Albums","http://entertainment.msn.com/services/rss.aspx?chartname=topalbums","EN","Music",$false,$false)
+               $$->$createSourceIfNotExists("MSN Top Artist","http://entertainment.msn.com/services/rss.aspx?chartname=topartists","EN","Music",$false,$false)
+               $$->$createSourceIfNotExists("Yahoo! Music News","http://rss.news.yahoo.com/rss/music","EN","Music",$false,$false)
+               $$->$createSourceIfNotExists("Yahoo! Digital Music News","http://rss.news.yahoo.com/rss/digitalmusic","EN","Music",$false,$false)
+               $$->$createSourceIfNotExists("Rolling Stones Music News","http://www.rollingstone.com/rssxml/music_news.xml?pageid=rs.page.news.story&pageregion=rssfeeds","EN","Music",$false,$false)
+               $$->$createSourceIfNotExists("BBC Entertainment","http://news.bbc.co.uk/rss/newsonline_uk_edition/entertainment/music/rss.xml","EN","Entertainment",$false,$false)
+               $$->$createSourceIfNotExists("NY Times Europe News","http://www.nytimes.com/services/xml/rss/nyt/Europe.xml","EN","Entertainment",$false,$false)
+               $$->$createSourceIfNotExists("MusiqueLibre.org POD","http://www.musique-libre.org/podcast.php?q=last","FR","Music",$false,$false)
+               $$->$createSourceIfNotExists("About: Heavy Metal","http://z.about.com/6/g/heavymetal/b/index.xml","EN","Music",$false,$false)
+               $$->$createSourceIfNotExists("Anime.org.uk: Anime!","http://www.anime.org.uk/aorguk.nsf/news.rss","EN","Anime",$false,$false)
+               $$->$createSourceIfNotExists("TheOtaku.com","http://rss.theotaku.com/feeds.php?action=retrieve&channel=news","EN","Anime",$false,$false)
+               $$->$createSourceIfNotExists("Anime News Network","http://www.animenewsnetwork.com/newsfeed/rss.xml","EN","Anime",$false,$false)
+               $$->$createSourceIfNotExists("Stock Repository","http://www.flickr.com/groups_feed.gne?id=49503068103@N01&format=rss_200","EN","Stock",$false,$false)
+               $$->$createSourceIfNotExists("Yahoo! Stock Quotes","http://rss.news.yahoo.com/rss/stocks","EN","Stock",$false,$false)
+               $$->$createSourceIfNotExists("CBS5 Entertainment","http://cbs5.com/entertainment/resources_rss.xml","EN","Entertainment",$false,$false)
+               $$->$createSourceIfNotExists("ABC Entertainment","http://my.abcnews.go.com/rsspublic/entertainment_rss20.xml","EN","Entertainment",$false,$false)
+               $$->$createSourceIfNotExists("CNN.com Showbiz","http://rss.cnn.com/rss/cnn_showbiz.rss","EN","Entertainment",$false,$false)
+               $$->$createSourceIfNotExists("Reuters: Entertainment","http://www.microsite.reuters.com/rss/Entertainment","EN","Entertainment",$false,$false)
+               $$->$createSourceIfNotExists("Science@NASA","http://www.nasa.gov/rss/science_at_nasa.rss","EN","Science",$false,$false)
+               $$->$createSourceIfNotExists("NASA: Breaking News","http://www.nasa.gov/rss/breaking_news.rss","EN","Science",$false,$false)
+               $$->$createSourceIfNotExists("NASA: Image of the Day","http://www.nasa.gov/rss/image_of_the_day.rss","EN","Science",$false,$false)
+               $$->$createSourceIfNotExists("Heral Tribune INTL","http://www.iht.com/rss/frontpage.xml","EN","News",$false,$false)
+               $$->$createSourceIfNotExists("Medical News Today","http://www.medicalnewstoday.com/medicalnews.xml","EN","News",$false,$false)
+               $$->$createSourceIfNotExists("Yahoo! Sport News","http://rss.news.yahoo.com/rss/sports","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("Reuters: Football News","http://www.microsite.reuters.co.uk/rss/uk/worldFootballNews","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: Tennis","http://www.eurosport.com/z/tennis/rss.xml","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: Tennis US Open","http://www.eurosport.com/z/tennis/us-open/2005/rss.xml","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: Tennis Wimbledon","http://www.eurosport.com/z/tennis/wimbledon/2005/rss.xml","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: F1","http://www.eurosport.com/z/formula1/rss.xml","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: Champions League","http://www.eurosport.com/z/football/uefa-champions-league/2005-2006/rss.xml","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: Uefa Cup","http://www.eurosport.com/z/football/uefa-cup1/2005-2006/rss.xml","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: MotoGP","http://www.eurosport.com/z/motorcycling/rss.xml","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: Indy","http://www.eurosport.com/z/indycar/rss.xml","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: Torino 2006","http://www.eurosport.com/z/crosscountryskiing/rss.xml","EN","Sport",$false,$false)
+               $$->$createSourceIfNotExists("EuroSport: Hockey","http://www.eurosport.com/z/icehockey/rss.xml","EN","Sport",$false,$false)
+
+               // :)
+               $$->$createSourceIfNotExists("KVIrc/CVS","http://cia.navi.cx/stats/project/kvirc/.rss","EN","Technology",$true,$false)
+
+               @%m_bStripHtmlTags = $true
+               @%m_bRemoveFeedFiles = $true
+               @%m_uFeedRefetchTimeoutInSeconds = 300; // 5 minutes
+       }
+       
+       internal load()
+       {
+               if(@%m_lSources)delete @%m_lSources
+               @%m_lSources = $new(list,0,standardList)
+
+               %c = $config.open("newsticker.kvc","r")
+
+               %n = $config.read(%c,"SourceCount",0)
+
+               config.setsection %c Sources
+
+               for(%i=0;%i<%n;%i++)
+               {
+                       %name = $config.read(%c,"Name"%i,"")
+                       %useNotifier = $config.read(%c,"UseNotifier"%i,$false)
+                       %url = $config.read(%c,"Url"%i,"")
+                       %lang = $config.read(%c,"Language"%i,"")
+                       %topic = $config.read(%c,"Topic"%i,"")
+                       %enabled = $config.read(%c,"Enabled"%i,$false)
+                       %lastNotification = $config.read(%c,"LastNotification"%i,"")
+                       if(%url && %name)
+                       {
+                               if(%lang == "")%lang = "EN"
+                               if(%topic == "")%topic = "General"
+                               if(%lastNotification == "")%lastNotification = "0001/01/01 00:00"
+                               $$->$createSource(%name,%url,%lang,%topic,%enabled,%useNotifier,%lastNotification)
+                       }
+               }
+
+               config.setsection %c "KVIrc"
+
+               @%m_bStripHtmlTags = $config.read(%c,"StripHtmlTags",$true)
+               @%m_bRemoveFeedFiles = $config.read(%c,"RemoveFeedFiles",$true)
+               @$setFeedRefetchTimeoutInSeconds($config.read(%c,"FeedRefetchTimeoutInSeconds",300))
+
+               %v = $config.read(%c,"Version",0)
+               if(%v < 10)
+               {
+                       $$->$loadDefaults()
+               }
+
+               config.close %c
+       }
+       
+       sourceList()
+       {
+       return @%m_lSources
+       }
+       
+       stripHtmlTags()
+       {
+               return @%m_bStripHtmlTags;
+       }
+       
+       setStripHtmlTags($0 = bStrip)
+       {
+               @%m_bStripHtmlTags = $0
+       }
+       
+       removeFeedFiles()
+       {
+               return @%m_bRemoveFeedFiles;
+       }
+       
+       setRemoveFeedFiles($0 = bRemove)
+       {
+               @%m_bRemoveFeedFiles = $0
+       }
+       
+       feedRefetchTimeoutInSeconds()
+       {
+               return @%m_uFeedRefetchTimeoutInSeconds
+       }
+       
+       setFeedRefetchTimeoutInSeconds($0 = uSecs)
+       {
+               @%m_uFeedRefetchTimeoutInSeconds = $0
+               if(!$str.isUnsignedNumber(@%m_uFeedRefetchTimeoutInSeconds))
+                       @%m_uFeedRefetchTimeoutInSeconds = 300
+               else {
+                       // need a reasonable minimum: fetching news in less than two minutes is simply senseless
+                       if(@%m_uFeedRefetchTimeoutInSeconds < 120)
+                               @%m_uFeedRefetchTimeoutInSeconds = 120
+               }
+       }
+       
+       setSourceList($0 = new source list)
+       {
+               if(@%m_lSources)delete @%m_lSources
+               @%m_lSources = $0
+       }
+       
+       configurationDialogCommitted()
+       {
+               $$->$emit("configurationChanged")
+       }
+       
+       save()
+       {
+               %c = $config.open("newsticker.kvc")
+               
+               #debug "Writing configuration"
+
+               if(@%m_lSources)
+               {
+                       %n = @%m_lSources->$count()
+                       config.write %c "SourceCount" %n
+                       config.clearsection %c "Sources"
+                       config.setsection %c "Sources"
+                       %i = 0
+                       if(@%m_lSources->$moveFirst())
+                       {
+                               do {
+                                       %s = @%m_lSources->$current()
+                                       config.write %c "Name"%i %s->$name()
+                                       config.write %c "Url"%i %s->$url()
+                                       config.write %c "Language"%i %s->$language()
+                                       config.write %c "Topic"%i %s->$topic()
+                                       config.write %c "Enabled"%i %s->$enabled()
+                                       config.write %c "UseNotifier"%i %s->$useNotifier()
+                                       config.write %c "LastNotification"%i %s->$lastNotification()
+                                       %i++
+                               } while(@%m_lSources->$moveNext())
+                       }
+               } else {
+                       config.write %c "SourceCount" 0
+               }
+
+               config.setsection %c "KVIrc"
+               config.write %c "StripHtmlTags" @%m_bStripHtmlTags
+               config.write %c "RemoveFeedFiles" @%m_bRemoveFeedFiles
+               config.write %c "FeedRefetchTimeoutInSeconds" @%m_uFeedRefetchTimeoutInSeconds
+
+               config.write %c "Version" 10
+
+               config.close %c
+       }
+
+       saveLastNotification($0 = rss entry)
+       {
+               %c = $config.open("newsticker.kvc")
+               config.setsection %c "Sources"
+               foreach(%key, $config.keylist(%c))
+               {
+                       if($str.match("Name*",%key,e) && $0->$source() == $config.read(%c,%key))
+                       {
+                               config.write %c "LastNotification"$str.rightfromfirst(%key,"Name") $0->$date()
+                               break
+                       }
+               }
+               config.close %c
+
+               if(@%m_lSources->$moveFirst())
+               {
+                       do {
+                               %s = @%m_lSources->$current()
+                               if($0->$source() == %s->$name())
+                               {
+                                       %s->$setLastNotification($0->$date())
+                                       break
+                               }
+                       } while(@%m_lSources->$moveNext())
+               }
+                       
+       }
+
+}
+
+alias(newsticker::core::configuration)
+{
+       if($objects.exists(%G_newstickerConfiguration))
+               return %G_newstickerConfiguration
+       %G_newstickerConfiguration = $new(newsticker::core::configuration)
+       return %G_newstickerConfiguration
+}
+
+alias(newsticker::configure)
+{
+       if($objects.exists(%G_newstickerConfigurationDialog))
+               return
+       %G_newstickerConfigurationDialog = $new(newsticker::core::configuration::dialog)
+       %G_newstickerConfigurationDialog->$show()
+}
+
diff --git a/newsticker4/src/controller.kvs b/newsticker4/src/controller.kvs
new file mode 100644 (file)
index 0000000..8bad4d8
--- /dev/null
@@ -0,0 +1,119 @@
+class(newsticker::controller)
+{
+       constructor()
+       {
+               @%m_eState = "Idle"; // can be "Idle" or "Fetching" for now...
+               // the list of sources.
+               // each source is a child of the list, so it will be destroyed with it
+               // eventually a child of $this object, will be destroyed with us
+               @%m_lSources = $null; 
+               @%m_lNews = $new(newsticker::rss::entrylist)
+               $$->$configurationChanged()
+               // this will be automatically killed when this object dies
+               @%m_iHeartbeatTimer = @$startTimer(10000)
+               %c = $newsticker::core::configuration()
+               objects.connect %c "configurationChanged" $this "configurationChanged"
+       }
+       
+       destructor()
+       {
+               delete @%m_lNews
+               if(@%m_lSources)delete @%m_lSources
+       }
+       
+       internal createSource($0 = name,$1 = url,$2 = use notifier, $3 = last notification)
+       {
+               %s = $new(newsticker::source,@%m_lSources)
+               %s->$setName($0)
+               %s->$setUrl($1)
+               %s->$setNotify($2)
+               %s->$setLastNotification($3)
+               %s->$setController($this)
+               objects.connect %s "newDataAvailable" $this "sourceNewDataAvailable"
+               return %s
+       }
+
+       newsList()
+       {
+               return @%m_lNews
+       }
+
+       configurationChanged()
+       {
+               %c = $newsticker::core::configuration()
+
+               if(@%m_lSources)delete @%m_lSources;
+               @%m_lSources = $new(list,$this)
+
+               %l = %c->$sourceList()
+               if(%l->$moveFirst())
+               {
+                       do {
+                               %s = %l->$current()
+                               if(%s->$enabled())
+                                       @%m_lSources->$append(@$createSource(%s->$name(),%s->$url(),%s->$useNotifier(),%s->$lastNotification()))
+                       } while(%l->$moveNext())
+               }
+               
+               delete @%m_lNews
+               @%m_lNews = $new(newsticker::rss::entrylist)
+               // emit our "changed" signal...
+               $$->$sourceNewDataAvailable()
+       }
+
+       notified($0 = entry)
+       {
+               if(@%m_lSources && @%m_lSources->$moveFirst())
+               {
+                       do {
+                               %s = @%m_lSources->$current()
+                               if($0->$source() == %s->$name())
+                               {
+                                       %s->$setLastNotification($0->$date())
+                                       break
+                               }
+                       } while(@%m_lSources->$moveNext())
+               }
+       }
+
+       internal tryToFetchNews()
+       {
+               if(@%m_lSources->$moveFirst())
+               {
+                       %now = $unixtime
+                       %uTimeout = $newsticker::core::configuration()->$feedRefetchTimeoutInSeconds()
+                       do {
+                               %src = @%m_lSources->$current();
+                               if(%src->$isIdle())
+                               {
+                                       if((%now - %src->$lastFetched()) > %uTimeout)
+                                       {
+                                               // more than 5 minutes passed since last fetch: refetch again
+                                               // and put it at the end of the list
+                                               %src->$fetch()
+                                               @%m_lSources->$removeCurrent()
+                                               @%m_lSources->$append(%src)
+                                               return
+                                       }
+                               }
+                       } while(@%m_lSources->$moveNext());
+               }
+       }
+
+       sourceNewDataAvailable()
+       {
+               // @%m_lNews has changed...
+               $this->$emit("newDataAvailable")
+       }
+
+       internal timerEvent($0 = timer id)
+       {
+               if($0 == @%m_iHeartbeatTimer)
+               {
+                       # debug "Heartbeat"
+                       // this is our heartbeat
+                       @$tryToFetchNews()
+               }
+       }
+}
+
diff --git a/newsticker4/src/main.kvs b/newsticker4/src/main.kvs
new file mode 100644 (file)
index 0000000..033fb8d
--- /dev/null
@@ -0,0 +1,10 @@
+include "actions.kvs"
+include "aliases.kvs"
+include "configuration.kvs"
+include "controller.kvs"
+include "qtwrapper.kvs"
+include "rssentry.kvs"
+include "rssentrylist.kvs"
+include "rssreader.kvs"
+include "source.kvs"
+include "window.kvs"
diff --git a/newsticker4/src/qtwrapper.kvs b/newsticker4/src/qtwrapper.kvs
new file mode 100644 (file)
index 0000000..84f0f41
--- /dev/null
@@ -0,0 +1,45 @@
+class(listviewwrapper,listview)
+{
+       constructor()
+       {
+               if ($str.contains($features(),"QT4")) {@%qt4=$true;@%idx=0;}
+               else @%qt4=$false
+       
+       }
+       selectedItem()
+       {
+               if (!@%qt4)
+               {
+                       return @$listview::selectedItem()
+               }
+               else
+               {
+               return @$listview::selectedItems()[0]
+               }
+       }
+       nextSibling()
+       {
+               if (!@%qt4)
+               {
+                       return @$listview::nextSibling()
+               }
+               else
+               {
+               @%idx++
+               return @$listview::topLevelItem(@%idx)
+               }
+       }
+       firstChild()
+       {
+               if (!@%qt4)
+               {
+                       return @$listview::firstChild()
+               }
+               else
+               {
+               return @$listview::topLevelItem(0)
+               }
+
+       }
+}
+    
\ No newline at end of file
diff --git a/newsticker4/src/rssentry.kvs b/newsticker4/src/rssentry.kvs
new file mode 100644 (file)
index 0000000..ba7af58
--- /dev/null
@@ -0,0 +1,107 @@
+class(newsticker::rss::entry,object)
+{
+       // var %m_szTitle
+       // var %m_szLink
+       // var %m_szDescription
+       // var %m_szDate
+       // var %m_szSource
+       // var %m_bUnread
+       // var %m_bNotified
+
+       isUnread()
+       {
+               return @%m_bUnread
+       }
+
+       isNotified()
+       {
+               return @%m_bNotified
+       }
+
+       setUnread($0 = bUnread)
+       {
+               @%m_bUnread = $0
+       }
+
+       setNotified($0 = bNotified)
+       {
+               @%m_bNotified = $0
+       }
+
+       setSource($0 = source)
+       {
+               @%m_szSource = $0
+       }
+
+       setDate($0 = date)
+       {
+               @%m_szDate = $0
+       }
+       
+       setTitle($0 = title)
+       {
+               @%m_szTitle = $0
+       }
+       
+       setLink($0 = link)
+       {
+               @%m_szLink = $0
+       }
+       
+       setDescription($0 = description)
+       {
+               @%m_szDescription = $0
+       }
+
+       set($0 = title,$1 = link,$2 = description,$3 = date,$4 = source,$5 = unread,$6 = notified)
+       {
+               @%m_szTitle = $0
+               @%m_szLink = $1
+               @%m_szDescription = $2
+               @%m_szDate = $3
+               @%m_szSource = $4
+               @%m_bUnread = $5
+               @%m_bNotified = $6
+       }
+
+       copyFrom($0 = other rssentry)
+       {
+               if($0 == $null)
+                       $$->$set("","","","","",$false)
+               else
+                       $$->$set($0->$title(),$0->$link(),$0->$description(),$0->$date(),$0->$source(),$0->$isUnread(),$0->$isNotified())
+       }
+       
+       source()
+       {
+               return @%m_szSource
+       }
+       
+       title()
+       {
+               return @%m_szTitle
+       }
+       
+       link()
+       {
+               return @%m_szLink
+       }
+       
+       description()
+       {
+               return @%m_szDescription
+       }
+
+       date()
+       {
+               return @%m_szDate
+       }
+
+       dump()
+       {
+               # debug "TITLE:" @%m_szTitle
+               # debug "LINK:" @%m_szLink
+               # debug "DESCRIPTION:" @%m_szDescription
+       }
+}
+
diff --git a/newsticker4/src/rssentrylist.kvs b/newsticker4/src/rssentrylist.kvs
new file mode 100644 (file)
index 0000000..32fe981
--- /dev/null
@@ -0,0 +1,117 @@
+class(newsticker::rss::entrylist,list)
+{
+       // var @%m_uUnreadCount
+       
+       constructor()
+       {
+               @%m_uUnreadCount = 0
+       }
+       
+       destructor()
+       {
+               @$clear()
+       }
+       
+       unreadCount()
+       {
+               return @%m_uUnreadCount
+       }
+       
+       decreaseUnreadCount()
+       {
+               @%m_uUnreadCount--
+       }
+       destructor()
+       {
+               #debug dentro il distruttore
+               @$clear()
+       }
+       
+       clear()
+       {
+               @%m_uUnreadCount = 0
+               if(@$moveFirst())
+               {
+                       do {
+                               delete @$current()
+                       } while(@$moveNext())
+               }
+               @$list::clear()
+       }
+       
+       inSort($0 = newsticker::rss::entry)
+       {
+               if($0->$isUnread())@%m_uUnreadCount++
+               if(!@$moveFirst())
+               {
+                       @$append($0)
+                       return
+               }
+               
+               %idx = 0
+               do {
+                       %r = @$current();
+                       if(%r->$date() > $0->$date())
+                       {
+                               @$insert(%idx,$0)
+                               return
+                       }
+                       %idx++
+               } while(@$moveNext())
+               # debug "IN SORT: APPENDING"
+               @$append($0)
+       }
+       
+       removeBySource($0 = sourcename)
+       {
+               # debug "REMOVE BY SOURCE "$0
+               if(!@$moveFirst())return
+
+               %idx = 0
+               %toremoveidx = 0
+               do {
+                       if(@$current()->$source() == $0)
+                       {
+                               %toremove[%toremoveidx] = %idx
+                               %toremoveidx++
+                               #debug "GOT ONE TO REMOVE"
+                       }
+                       %idx++
+               } while(@$moveNext())
+               
+               %hUnread = $hash();
+
+               if(%toremoveidx == 0)return %hUnread
+               
+               for(%idx = $(%toremoveidx - 1);%idx >= 0;%idx--)
+               {
+                       #debug "REMOVING THAT ONE"
+                       %r = @$at(%toremove[%idx])
+                       if(%r != $null)
+                       {
+                               %hUnread{%r->$date()}{isUnread} = %r->$isUnread()
+                               %hUnread{%r->$date()}{isNotified} = %r->$isNotified()
+                               if(%r->$isUnread())@%m_uUnreadCount--
+                               #debug "...REALLY REMOVING"
+                               delete %r
+                               @$remove(%toremove[%idx])
+                       }
+               }
+               
+               return %hUnread
+       }
+
+       firstUnNotified()
+       {
+
+               if(!@$moveFirst())return $null
+
+               do {
+                       if(!@$current()->$isNotified())
+                               return @$current()
+               } while(@$moveNext())
+
+               return $null
+       }
+
+}
diff --git a/newsticker4/src/rssreader.kvs b/newsticker4/src/rssreader.kvs
new file mode 100644 (file)
index 0000000..208a539
--- /dev/null
@@ -0,0 +1,252 @@
+class(newsticker::rss::reader,xmlreader)
+{
+       constructor()
+       {
+               @%m_lItems = $null
+       }
+
+       destructor()
+       {
+       }
+
+       run($0 = data to parse,$1 = list to insert into,$2 = sourcename,$3 = unread hash by date,$4 = notify?,$5 = last notification,$6 = quiet)
+       {
+               #debug "PARSING("$0")"
+               @%m_lItems = $1
+               @%m_szSource = $2
+               @%m_hUnreadItems = $3
+               @%m_bNotify = $4
+               @%m_tLastNotification = $5
+               if(!$this->$parse($0))
+               {
+                       if(!$6)
+                               debug "[RSS]["$2"] Error: " $this->$lastError()
+                       return $false
+               }
+               @%m_lItems = $null;
+               return $true
+       }
+
+       internal onDocumentStart()
+       {
+               @%m_eState = "Nothing"
+               @%m_szLastTitle = ""
+               @%m_szLastLink = ""
+               @%m_szLastDescription = ""
+               @%m_szLastDate = ""
+               return $true;
+       }
+               
+       internal onWarning($0 = text)
+       {
+               // debug "WARNING:" $0
+               return $true;
+       }
+       
+       internal onText($0 = text)
+       {
+               switch(@%m_eState)
+               {
+                       case("InsideTitle"):
+                               @%m_szLastTitle .= $0
+                       break;
+                       case("InsideLink"):
+                               @%m_szLastLink .= $0
+                       break;
+                       case("InsideDescription"):
+                       {
+                               %tmp = $0
+                               %tmp =~ s/<.+\/>//g
+                               @%m_szLastDescription .= %tmp
+                       }
+                       break;
+                       case("InsideDate"):
+                       {
+                               #debug "Date text" $0
+                               @%m_szLastDate = $0
+                       }
+                       break;
+               }
+               return $true;
+       }
+       
+       internal parseDate($0 = date)
+       {
+               // FIXME: this does not account to the timezone... which is hopeless in fact...
+               // supported formats:
+               //   YYYY-MM-DDThh:mm:ss.sTZD
+               //   YYYY-MM-DD hh:mm:ss
+               //   YYYY/MM/DD hh:mm:ss
+               //   Day, DD Month YYYY hh:mm:ss (+0700)
+               //   Mon, 30 Jan 2006 11:28:46 GMT
+
+               %days = $array("Mon","Tue","Wed","Thu","Fri","Sat","Sun")
+               for(%i=0;%i<7;%i++)
+               {
+                       if($str.find(@%m_szLastDate,%days[%i]) >= 0)
+                               break;
+               }
+
+               if(%i < 7)
+               {
+                       // probably Day, DD Month YYYY hh:mm:ss (+XYZ)
+                       %arry = $str.split(" ",@%m_szLastDate,"n")
+                       %months = $array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")
+                       for(%i = 0;%i < 12;%i++)
+                       {
+                               if($str.find(%arry[2],%months[%i]) >= 0)
+                                       break;
+                       }
+                       %month = $(%i+1)
+                       %hms = $str.split(":",%arry[4])
+                       %ret = %arry[3]"/"$(%month / 10)$(%month % 10)"/"%arry[1] %hms[0]":"%hms[1]
+               } else {
+                       if($str.find(@%m_szLastDate,"T") > 0)
+                               %tmp = $str.split("T",@%m_szLastDate,"n")
+                       else
+                               %tmp = $str.split(" ",@%m_szLastDate,"n")
+                       %ymd = $str.split("-",%tmp[0])
+                       %hms = $str.split(":",%tmp[1])
+                       %ret = %ymd[0]"/"%ymd[1]"/"%ymd[2]" "%hms[0]":"%hms[1]
+               }
+
+               return %ret
+       }
+       
+       internal storeLastItem()
+       {
+               // We create each rssentry as child of the list of items
+               // so the children will be destroyed when the parent list is.
+               // a nice way of emulating the autoDelete() feature of QLists :)
+               %r = $new(newsticker::rss::entry,@%m_lItems)
+               
+               %c = $newsticker::core::configuration()
+               
+               #debug "DATE: " @%m_szLastDate
+               if(@%m_szLastDate == "")
+               {
+                       @%m_szLastDate = $date("Y/m/d H:M") @%m_lItems->$count()
+               } else {
+                       @%m_szLastDate = $$->$parseDate(@%m_szLastDate)
+               }
+
+               if($isSet(@%m_hUnreadItems{@%m_szLastDate}))
+               {
+                       %bUnread = @%m_hUnreadItems{@%m_szLastDate}{isUnread}
+                       %bNotified = @%m_hUnreadItems{@%m_szLastDate}{isNotified}
+               } else {
+                       %bUnread = $true
+                       // If must not be notified, let's assumed it is already notified
+                       if(!@%m_bNotify)
+                               %bNotified=$true
+                       else
+                               %bNotified=$false
+               }
+               %bNotified = $(%bNotified || (@%m_tLastNotification >=  @%m_szLastDate) )
+
+               if(@%m_szLastDescription == "")
+                       @%m_szLastDescription = @%m_szLastTitle
+               
+               // make sure that the last description does not contain hidden html... it looks ugly
+               //debug "DESCRIPTION ORIG:" @%m_szLastDescription
+               //@%m_szLastDescription =~ s/&lt;.*&gt;//gm
+               if(%c->$stripHtmlTags())
+                       @%m_szLastDescription =~ s/<.*>//gm
+               
+               //debug "DESCRIPTION NOW:" @%m_szLastDescription
+               //@%m_szLastDescription =~ s/&lt;a href=&quot;.*&gt;//gm
+               //@%m_szLastDescription =~ s/&lt;img src=&quot;.*&gt;//gm
+               
+               %r->$set(@%m_szLastTitle,@%m_szLastLink,@%m_szLastDescription,@%m_szLastDate,@%m_szSource,%bUnread,%bNotified)
+
+               #debug "GOT ITEM -- TITLE:" %r->$title() "-- LINK:" %r->$link() "-- SOURCE:" %r->$source();
+               #debug "-- DESCRIPTION:" %r->$description()
+               #debug "-- DATE:" %r->$date()
+               @%m_szLastTitle = ""
+               @%m_szLastLink = ""
+               @%m_szLastDescription = ""
+               @%m_szLastDate = ""
+               @%m_lItems->$inSort(%r)
+               return $true;
+       }
+
+       internal onElementStart($0 = qualified name,...)
+       {
+               if(@%m_eState == "Nothing")
+               {
+                       if($0 == "item")
+                       {
+                               @%m_eState = "InsideItem"
+                               return $true
+                       }
+               } else {
+                       switch($0)
+                       {
+                               case("title"):
+                                       @%m_eState = "InsideTitle"
+                               break;
+                               case("link"):
+                                       @%m_eState = "InsideLink"
+                               break;
+                               case("description"):
+                                       @%m_eState = "InsideDescription"
+                               break;
+                               case("date"):
+                               {
+                                       #debug "got date element date"
+                                       @%m_eState = "InsideDate"
+                               }
+                               break;
+                               case("dc:date"):
+                               {
+                                       #debug "got date element dc:date"
+                                       @%m_eState = "InsideDate"
+                               }
+                               break;
+                               case("pubDate"):
+                               {
+                                       #debug "got date element pubDate"
+                                       @%m_eState = "InsideDate"
+                               }
+                               break;
+                       }
+               }
+               return $true;
+       }
+       
+       internal onElementEnd($0 = qualified name,...)
+       {
+               if(@%m_eState != "Nothing")
+               {
+                       switch($0)
+                       {
+                               case("item"):
+                               {
+                                       $this->$storeLastItem()
+                                       @%m_eState = "Nothing"
+                               }
+                               break;
+                               case("title"):
+                                       @%m_eState = "InsideItem"
+                               break;
+                               case("link"):
+                                       @%m_eState = "InsideItem"
+                               break;
+                               case("description"):
+                                       @%m_eState = "InsideItem"
+                               break;
+                               case("date"):
+                                       @%m_eState = "InsideItem"
+                               break;
+                               case("dc:date"):
+                                       @%m_eState = "InsideItem"
+                               break;
+                               case("pubDate"):
+                                       @%m_eState = "InsideItem"
+                               break;
+                       }
+               }
+               return $true;
+       }
+}
+
diff --git a/newsticker4/src/source.kvs b/newsticker4/src/source.kvs
new file mode 100644 (file)
index 0000000..4d39146
--- /dev/null
@@ -0,0 +1,135 @@
+class(newsticker::source)
+{
+       // @%m_szName (the name of this source)
+       // @%m_szUrl (the url of for this source object)
+       // @%m_tLastFetched (timestamp of last fetch of this uri)
+       // @%m_eState (state enumeration: "Idle" or "Fetching")
+       // @%m_hController (handle to the controller)
+       constructor()
+       {
+               @%m_szName = ""
+               @%m_szUrl = ""
+               @%m_bNotify = $false
+               @%m_tLastFetched = 0
+               @%m_tLastNotification = "0001/01/01 00:00"
+               @%m_eState = "Idle"
+       }
+
+       setController($0 = hController)
+       {
+               @%m_hController = $0
+       }
+
+       name()
+       {
+               return @%m_szName
+       }
+       
+       setName($0 = name)
+       {
+               @%m_szName = $0
+       }
+       
+       url()
+       {
+               return @%m_szUrl
+       }
+       
+       setUrl($0 = url)
+       {
+               @%m_szUrl = $0
+       }
+
+       notify()
+       {
+               return @%m_bNotify
+       }
+
+       setNotify($0 = notify?)
+       {
+               @%m_bNotify = $0
+       }
+
+       lastNotification()
+       {
+               return @%m_tLastNotification
+       }
+
+       setLastNotification($0 = time)
+       {
+               @%m_tLastNotification = $0
+       }
+       
+       lastFetched()
+       {
+               return @%m_tLastFetched
+       }
+
+       isIdle()
+       {
+               return $(@%m_eState == "Idle")
+       }
+       
+       isFetching()
+       {
+               return $(@%m_eState == "Fetching")
+       }
+       
+       state()
+       {
+               return @%m_eState
+       }
+
+       fetch()
+       {
+               #debug "Fetching from url" @%m_szUrl
+               @%m_eState = "Fetching"
+               http.asyncget --winctrl="h" --quiet --no-output --clear --auto-file-name --identifier=$this (@%m_szUrl)
+               {
+                       # debug "Get completed: $0 $1 $2 $3"
+                       // $0 = status
+                       // $1 = remote url
+                       // $2 = local file
+                       // $3 = magic identifier
+                       
+                       if($objects.exists($3))
+                       {
+                               // the newsticker controller still exists
+                               $3->$fetchTerminated($0,$1,$2)
+                       } else {
+                               # This can happen when editing the configuration
+                               # Just ignore: will refetch soon anyway.
+                               
+                               # debug "Opss.. the master object of this get is dead ?"
+                       }
+               }
+       }
+       
+       fetchTerminated($0 = status,$1 = remote uri,$2 = local file)
+       {
+               # debug "Fetch terminated"
+               @%m_eState = "Idle"
+               @%m_tLastFetched = $unixtime
+               if($0)
+               {
+                       // fetch succesfull
+                       // parse it
+                       %r = $new(newsticker::rss::reader)
+                       %l = @%m_hController->$newsList()
+                       # debug "FETCH TERMINATED: REMOVING BY SOURCE"
+                       %hUnread = %l->$removeBySource(@%m_szName)
+                       # debug "RUNNING PARSER"
+                       #if(%r->$run($file.read("/root/download/test.rss"),%l,@%m_szName,%hUnread,@%m_bNotify,@%m_tLastNotification,$false))
+                       if(%r->$run($file.read($2),%l,@%m_szName,%hUnread,@%m_bNotify,@%m_tLastNotification,$false))
+                       {
+                               # debug "Document parsed"
+                               $this->$emit("newDataAvailable",$this)
+                               if($newsticker::core::configuration()->$removeFeedFiles())
+                                       file.remove -q $2
+                       }
+                       // otherwise leave the file in place, so we can analyze it :D
+                       delete %r
+               }
+       }
+}
+
diff --git a/newsticker4/src/window.kvs b/newsticker4/src/window.kvs
new file mode 100644 (file)
index 0000000..d802e84
--- /dev/null
@@ -0,0 +1,434 @@
+class(newsticker::window,dockwindow)
+{
+       // @%m_szCurrentEntrySource
+       // @%m_szCurrentEntryDate
+       // @%m_iCurrentEntryIndex
+       
+       createToolButton($0 = $image)
+       {
+               %tb = $new(toolbutton,@%m_hContainer)
+               %tb->$setImage($0)
+               %tb->$setUsesBigPixmap($false)
+               %tb->$setUsesTextLabel($false)
+               %tb->$setAutoRaise($true)
+               %tb->$setMaximumWidth(24)
+               %tb->$setMaximumHeight(24)
+               return %tb
+       }
+       
+       constructor()
+       {
+               if ($str.contains($features(),"QT4"))@$setWindowTitle($tr("Newsticker","newsticker"))
+                 else @$setWindowTitle($tr("Newsticker","newsticker"))
+               @%m_hCurrentEntry = $new(newsticker::rss::entry)
+               @%m_bAutoDisplay = $true
+               @%m_tLastDisplayedEntryTimestamp = 0
+
+               @%m_hController = $new(newsticker::controller,$this)
+               objects.connect @%m_hController "newDataAvailable" $this "newDataAvailable"
+
+               @$setAllowedDockAreas("lrfm");
+               if (!$str.contains($features(),"QT4")) @$setResizeEnabled($true);
+
+               @%m_hContainer = $new(widget,$this)
+               %l = $new(layout,@%m_hContainer)
+
+               @%m_hTextBrowser = $new(textbrowser,@%m_hContainer)
+               %l->$addMultiCellWidget(@%m_hTextBrowser,0,0,0,5)
+               objects.connect @%m_hTextBrowser "linkClicked" $this "linkClicked"
+
+               @%m_hFirstButton = $$->$createToolButton("newsticker_first_16.png")
+               @%m_hFirstButton->$setToolTip($tr("Show the first available news entry","newsticker"))
+               %l->$addWidget(@%m_hFirstButton,1,0)
+               objects.connect @%m_hFirstButton "clicked" $this "firstClicked"
+
+               @%m_hPrevButton = $$->$createToolButton("newsticker_prev_16.png")
+               @%m_hPrevButton->$setToolTip($tr("Show previous news entry","newsticker"))
+               %l->$addWidget(@%m_hPrevButton,1,1)
+               objects.connect @%m_hPrevButton "clicked" $this "prevClicked"
+
+               @%m_hDisplayLabel = $new(label,@%m_hContainer)
+               @%m_hDisplayLabel->$setAlignment(Center,VCenter)
+               %l->$addMultiCellWidget(@%m_hDisplayLabel,1,2,2,2)
+
+               @%m_hNextUnreadButton = $$->$createToolButton("newsticker_next_unread_16.png")
+               @%m_hNextUnreadButton->$setToolTip($tr("Show the next unread news entry","newsticker"))
+               %l->$addWidget(@%m_hNextUnreadButton,1,3)
+               objects.connect @%m_hNextUnreadButton "clicked" $this "nextUnreadClicked"
+
+               @%m_hNextButton = $$->$createToolButton("newsticker_next_16.png")
+               @%m_hNextButton->$setToolTip($tr("Show the next news entry","newsticker"))
+               %l->$addWidget(@%m_hNextButton,1,4)
+               objects.connect @%m_hNextButton "clicked" $this "nextClicked"
+
+               @%m_hLastButton = $$->$createToolButton("newsticker_last_16.png")
+               @%m_hLastButton->$setToolTip($tr("Show the last available news entry","newsticker"))
+               %l->$addWidget(@%m_hLastButton,1,5)
+               objects.connect @%m_hLastButton "clicked" $this "lastClicked"
+
+               @%m_hCloseButton = $$->$createToolButton("newsticker_close_16.png");
+               @%m_hCloseButton->$setToolTip($tr("Close the Newsticker","newsticker"))
+               %l->$addWidget(@%m_hCloseButton,2,0)
+               objects.connect @%m_hCloseButton "clicked" $this "closeClicked"
+
+               @%m_hConfigureButton = $$->$createToolButton("newsticker_configure_16.png");
+               @%m_hConfigureButton->$setToolTip($tr("Configure the Newsticker","newsticker"))
+               %l->$addWidget(@%m_hConfigureButton,2,1)
+               objects.connect @%m_hConfigureButton "clicked" $this "configureClicked"
+
+               @%m_hAutoButton = $$->$createToolButton("newsticker_auto_16.png");
+               @%m_hAutoButton->$setToolTip($tr("Automatic slide-show of news. If you keep it on, the news will be displayed passively, for 30 seconds each one.","newsticker"))
+               %l->$addWidget(@%m_hAutoButton,2,3)
+               objects.connect @%m_hAutoButton "clicked" $this "autoClicked"
+
+               @%m_hViewOnlineButton = $$->$createToolButton("newsticker_viewonline_16.png");
+               @%m_hViewOnlineButton->$setToolTip($tr("View the current article online","newsticker"))
+               %l->$addWidget(@%m_hViewOnlineButton,2,4)
+               objects.connect @%m_hViewOnlineButton "clicked" $this "viewOnlineClicked"
+
+               @%m_hSayButton = $$->$createToolButton("newsticker_say_16.png");
+               @%m_hSayButton->$setToolTip($tr("Advertise the current news entry to the current channel or query","newsticker"))
+               %l->$addWidget(@%m_hSayButton,2,5)
+               objects.connect @%m_hSayButton "clicked" $this "sayClicked"
+
+               if ($str.contains($features(),"QT4"))
+               {
+                     %l->$setColumnStretch(0,0)
+                     %l->$setColumnStretch(1,0)
+                     %l->$setColumnStretch(2,5)
+                     %l->$setColumnStretch(3,0)
+                     %l->$setColumnStretch(4,0)
+                     %l->$setColumnStretch(5,0)
+               }
+               else{
+                     %l->$setColumnStretch(0,0)
+                     %l->$setColumnStretch(1,0)
+                     %l->$setColumnStretch(2,5)
+                     %l->$setColumnStretch(3,0)
+                     %l->$setColumnStretch(4,0)
+                     %l->$setColumnStretch(5,0)
+               }
+               %l->$setRowStretch(0,500)
+               %l->$setRowStretch(1,0)
+               %l->$setRowStretch(2,0)
+
+               @$addWidget(@%m_hContainer)
+
+               // trigger it once
+               @$newDataAvailable()
+               
+               $$->$startTimer(5000)
+       }
+
+       destructor()
+       {
+               if($objects.exists(@%m_hCurrentEntry))
+                       delete @%m_hCurrentEntry
+       }
+
+       timerEvent()
+       {
+               # debug "TIMER EVENT"
+               $$->$checkNotify()
+               if(!@%m_bAutoDisplay)return
+               # debug "AUTO DISPLAY IS ON"
+               $$->$checkAutoDisplay()
+       }
+       
+       linkClicked($0 = link)
+       {
+               #debug "LINK CLICKED:" $0
+       }
+
+       checkAutoDisplay()
+       {
+               # debug "CHECK AUTO DISPLAY"
+               if(($unixtime - @%m_tLastDisplayedEntryTimestamp) < 30)return
+               # debug "MOVING RIGHT"
+
+               %l = @%m_hController->$newsList()
+               if(@%m_iCurrentEntryIndex < (%l->$count()-1))
+                       $$->$nextClicked()
+               else
+                       $$->$firstClicked()
+       }
+
+       checkNotify()
+       {
+               %e = @%m_hController->$newsList()->$firstUnNotified()
+               if(%e == $null)return
+               notifier.message -t=20 -i=newsticker_16.png "[%e->$source()] %e->$title()"
+               %e->$setNotified($true)
+               %c = $newsticker::core::configuration()
+               %c->$saveLastNotification(%e)
+               @%m_hController->$notified(%e)
+       }
+       
+       updateLabelAndButtons($0 = cur index,$1 = total count,$2 = unread count)
+       {
+               %txt = "<font style=\"font-size:10pt;\">"
+               if($1 < 1)
+               {
+                       %txt .= $tr("No news (yet)","newsticker")
+                       @%m_hFirstButton->$setEnabled($false)
+                       @%m_hPrevButton->$setEnabled($false)
+                       @%m_hNextButton->$setEnabled($false)
+                       @%m_hNextUnreadButton->$setEnabled($false)
+                       @%m_hLastButton->$setEnabled($false)
+                       @%m_hSayButton->$setEnabled($false)
+                       @%m_hAutoButton->$setEnabled($false)
+                       @%m_hViewOnlineButton->$setEnabled($false)
+               } else {
+                       if($0 >= 0)
+                               %txt .= $($0 + 1) $tr("of","newsticker") $1 "<br>"$2 $tr("unread","newsticker")
+                       else
+                               %txt .= ? $tr("of","newsticker") $1 "<br>"$2 $tr("unread","newsticker")
+
+                       @%m_hFirstButton->$setEnabled($($0 > 0))
+                       @%m_hPrevButton->$setEnabled($($0 > 0))
+                       @%m_hNextButton->$setEnabled($($0 < ($1 - 1)))
+                       @%m_hNextUnreadButton->$setEnabled($($2 > 0))
+                       @%m_hLastButton->$setEnabled($($0 < ($1 - 1)))
+                       @%m_hSayButton->$setEnabled($true)
+                       @%m_hAutoButton->$setEnabled($true)
+                       @%m_hViewOnlineButton->$setEnabled($true)
+               }
+               @%m_hDisplayLabel->$setText(%txt"</font>")
+       }
+
+       displayEntry($0 = rssentry)
+       {
+               @%m_hCurrentEntry->$copyFrom($0)
+
+               if($0 == $null)
+               {
+                       @%m_hTextBrowser->$setText("No data available...")
+                       @%m_szCurrentEntrySource = ""
+                       @%m_szCurrentEntryDate = ""
+                       return
+               }
+       
+               @%m_szCurrentEntrySource = $0->$source()
+               @%m_szCurrentEntryDate = $0->$date()
+       
+       
+               %h = "<html>"
+               %h .= "<title>"$0->$title()"</title>"
+       
+               %h .= "<body>"
+       
+               %h .=  "<table width=\"100%\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">"
+               
+               //%h .=  "<tr><td bgcolor=\"#808080\"><font size=\"7\" color=\"#c0c0c0\">"$0->$source()"</font></td></tr>" 
+               //%h .=  "<tr><td bgcolor=\"#e0e0e0\"><font size=\"7\" color=\"#000000\"><b>"$0->$title()"</b></font></td></tr>" 
+               //%h .= "<tr><td bgcolor=\"#f0f0f0\"><font size=\"7\">"$0->$date()"</font></td></tr>"
+
+               if($0->$isUnread())
+               {
+                       %bgColor = "#c05050"
+                       $0->$setUnread($false)
+                       @%m_hController->$newsList()->$decreaseUnreadCount()
+               } else {
+                       %bgColor = "#505050"
+               }
+                       
+
+               %h .=  "<tr><td bgcolor=\"#aaaaaa\"><font color=\"#d2d2d2\" style=\"font-size:10pt;\">"$0->$source()"</font></td></tr>" 
+               %h .=  "<tr><td bgcolor=\""%bgColor"\"><font color=\"#ffffff\" style=\"font-size:11pt;\"><b>"$0->$title()"</b></font></td></tr>" 
+               %h .= "<tr><td bgcolor=\"#f0f0f0\"><font color=\"#909090\" style=\"font-size:8pt;\">"$0->$date()"</font></td></tr>"
+
+               %h .= "<tr><td><font style=\"font-size:10pt;\">"$0->$description()"</font></td></tr>"
+               %h .= "</table>"
+
+               %h .= "</body>"
+
+               %h .= "</html>"
+
+               @%m_hTextBrowser->$setText(%h)
+               
+       }
+
+       sayClicked()
+       {
+               if(@%m_hCurrentEntry->$title() == "")return
+               say -r=$active "["@%m_hCurrentEntry->$source()"]:" @%m_hCurrentEntry->$title() "("@%m_hCurrentEntry->$link()")"
+       }
+       
+       configureClicked()
+       {
+               newsticker::configure
+       }
+       
+       closeClicked()
+       {
+               dialog.message($tr("Confirm close","newsticker"),$tr("Do you really want to close the Newsticker ?","newsticker"),"information",$tr("Yes","newsticker"),$tr("No","newsticker"))
+               {
+                       if($0 == 0)newsticker::close
+               }
+       }
+       
+       viewOnlineClicked()
+       {
+               if(@%m_hCurrentEntry->$link() != "")
+                       openurl @%m_hCurrentEntry->$link()
+       }
+       
+       autoClicked()
+       {
+               @%m_bAutoDisplay = $(!@%m_bAutoDisplay)
+               if(@%m_bAutoDisplay)
+                       @%m_hAutoButton->$setImage("newsticker_auto_16.png")
+               else
+                       @%m_hAutoButton->$setImage("newsticker_noauto_16.png")
+               @%m_tLastDisplayedEntryTimestamp = $unixtime
+       }
+
+       firstClicked()
+       {
+               if(@%m_iCurrentEntryIndex >= 0)%idx = 0
+               else return
+
+               %l = @%m_hController->$newsList()
+
+               %r = %l->$at(%idx)
+               if(%r == $null)return
+
+               @$displayEntry(%r)
+
+               @%m_iCurrentEntryIndex = %idx
+
+               @$updateLabelAndButtons(@%m_iCurrentEntryIndex,%l->$count(),%l->$unreadCount())
+               @%m_tLastDisplayedEntryTimestamp = $unixtime
+       }
+
+       prevClicked()
+       {
+               if(@%m_iCurrentEntryIndex >= 0)
+               {
+                       if(@%m_iCurrentEntryIndex > 0)
+                               %idx = $(@%m_iCurrentEntryIndex - 1)
+                       else
+                               return
+               } else {
+                       %idx = 0
+               }
+
+               %l = @%m_hController->$newsList()
+
+               %r = %l->$at(%idx)
+               if(%r == $null)return
+
+               @$displayEntry(%r)
+
+               @%m_iCurrentEntryIndex = %idx
+
+               @$updateLabelAndButtons(@%m_iCurrentEntryIndex,%l->$count(),%l->$unreadCount())
+               @%m_tLastDisplayedEntryTimestamp = $unixtime
+       }
+
+       nextClicked()
+       {
+               if(@%m_iCurrentEntryIndex >= 0)
+               {
+                       %idx = $(@%m_iCurrentEntryIndex + 1)
+               } else {
+                       %idx = 0
+               }
+
+               %l = @%m_hController->$newsList()
+
+               %r = %l->$at(%idx)
+               if(%r == $null)return
+
+               @$displayEntry(%r)
+
+               @%m_iCurrentEntryIndex = %idx
+
+               @$updateLabelAndButtons(@%m_iCurrentEntryIndex,%l->$count(),%l->$unreadCount())
+               @%m_tLastDisplayedEntryTimestamp = $unixtime
+       }
+
+       nextUnreadClicked()
+       {
+               %l = @%m_hController->$newsList();
+               
+               if(%l->$unreadCount() < 1)return
+
+               if(@%m_iCurrentEntryIndex >= 0)
+               {
+                       %start = @%m_iCurrentEntryIndex
+               } else {
+                       %start = 0
+               }
+
+               %idx = $(%start+1)
+
+               while(1)
+               {
+                       if(%idx == %start)return; // looped once: no way
+                       if(%idx >= %l->$count())%idx = 0; // ran beyond the end
+                       %r = %l->$at(%idx)
+                       if(%r == $null)return
+                       if(%r->$isUnread())break
+                       %idx++
+               }
+
+               @$displayEntry(%r)
+
+               @%m_iCurrentEntryIndex = %idx
+
+               @$updateLabelAndButtons(@%m_iCurrentEntryIndex,%l->$count(),%l->$unreadCount())
+               @%m_tLastDisplayedEntryTimestamp = $unixtime
+       }
+
+       lastClicked()
+       {
+               %l = @%m_hController->$newsList()
+
+               if((@%m_iCurrentEntryIndex < %l->$count()) && (%l->$count() > 0))
+               {
+                       %idx = $(%l->$count() - 1)
+               } else {
+                       %idx = 0
+               }
+
+               %r = %l->$at(%idx)
+               if(%r == $null)return
+
+               @$displayEntry(%r)
+
+               @%m_iCurrentEntryIndex = %idx
+
+               @$updateLabelAndButtons(@%m_iCurrentEntryIndex,%l->$count(),%l->$unreadCount())
+               @%m_tLastDisplayedEntryTimestamp = $unixtime
+       }
+       
+       findCurrentIndex()
+       {
+               %l = @%m_hController->$newsList()
+               if(!%l->$moveFirst())return -1
+               %idx = 0
+               do {
+                       if(%l->$current()->$source() == @%m_szCurrentEntrySource)
+                       {
+                               if(%l->$current()->$date() == @%m_szCurrentEntryDate)
+                               {
+                                       return %idx
+                               }
+                       }
+                       %idx++
+               } while(%l->$moveNext())
+               return -1
+       }
+       
+       newDataAvailable()
+       {
+               @%m_iCurrentEntryIndex = @$findCurrentIndex()
+               %l = @%m_hController->$newsList()
+               @$updateLabelAndButtons(@%m_iCurrentEntryIndex,%l->$count(),%l->$unreadCount())
+               if(@%m_bAutoDisplay)$$->$checkAutoDisplay()
+       }
+}
+
+