changeset 17654:f5950975a172

community news dock widget and other user info in GUI * news-dock-widget.h, news-dock-widget.cc: New files. * libgui/src/module.mk: Update file lists. * configure.ac: Check for QtWebKit module. * default-qt-settings.in: Update default geometry. * main-window.cc, main-window.h (main_window::news_window): New data member. (main_window::dock_widget_list): Include it in the list. (main_window::display_release_notes, main_window::display_url_in_window, main_window::construct_news_menu): New functions. (main_window::construct): Add news_window dock widget. (main_window::construct_menu_bar): Call construct_news_menu. (main_window::construct_window_menu): New items for Showing news window and menu.
author John W. Eaton <jwe@octave.org>
date Mon, 07 Oct 2013 21:13:11 -0400
parents d8d71c89fff2
children e89f6dcb37f0
files configure.ac libgui/default-qt-settings.in libgui/src/main-window.cc libgui/src/main-window.h libgui/src/module.mk libgui/src/news-dock-widget.cc libgui/src/news-dock-widget.h
diffstat 7 files changed, 308 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac
+++ b/configure.ac
@@ -2623,16 +2623,16 @@
 
 if test $build_gui = yes; then
   ## Check for Qt libraries
-  PKG_CHECK_MODULES(QT, [QtCore, QtGui, QtNetwork],
+  PKG_CHECK_MODULES(QT, [QtCore, QtGui, QtNetwork, QtWebKit],
     [],
     [AC_MSG_WARN([Qt libraries not found -- disabling GUI])
      build_gui=no])
 
   if test $build_gui = yes; then
     ## Retrieve Qt compilation and linker flags
-    QT_CPPFLAGS="`$PKG_CONFIG --cflags-only-I QtCore QtGui QtNetwork`"
-    QT_LDFLAGS="`$PKG_CONFIG --libs-only-L QtCore QtGui QtNetwork`"
-    QT_LIBS="`$PKG_CONFIG --libs-only-l QtCore QtGui QtNetwork`"
+    QT_CPPFLAGS="`$PKG_CONFIG --cflags-only-I QtCore QtGui QtNetwork QtWebKit`"
+    QT_LDFLAGS="`$PKG_CONFIG --libs-only-L QtCore QtGui QtNetwork QtWebKit`"
+    QT_LIBS="`$PKG_CONFIG --libs-only-l QtCore QtGui QtNetwork QtWebKit`"
 
     ## Check for Qt4
     if ! `$PKG_CONFIG --atleast-version=4.0.0 QtCore`; then
--- a/libgui/default-qt-settings.in
+++ b/libgui/default-qt-settings.in
@@ -28,40 +28,49 @@
 cursorType=ibeam
 
 [MainWindow]
-geometry="@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\x14\0\0\0'\0\0\x4;\0\0\x3\x4\0\0\0\x1e\0\0\0\x45\0\0\x4\x31\0\0\x2\xfa\0\0\0\0\0\0)"
-windowState="@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x1\0\0\x4\x14\0\0\x2]\xfc\x2\0\0\0\x1\xfc\0\0\0\x42\0\0\x2]\0\0\x1\xa7\0\xff\xff\xff\xfc\x1\0\0\0\x2\xfc\0\0\0\0\0\0\x1y\0\0\0X\0\xff\xff\xff\xfc\x2\0\0\0\x3\xfb\0\0\0\x1e\0\x46\0i\0l\0\x65\0s\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\x42\0\0\0\xc0\0\0\0\x97\0\xff\xff\xff\xfb\0\0\0\x1a\0W\0o\0r\0k\0s\0p\0\x61\0\x63\0\x65\0V\0i\0\x65\0w\x1\0\0\x1\b\0\0\0\xce\0\0\0q\0\xff\xff\xff\xfb\0\0\0\"\0H\0i\0s\0t\0o\0r\0y\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\x1\xdc\0\0\0\xc3\0\0\0\x93\0\xff\xff\xff\xfc\0\0\x1\x7f\0\0\x2\x95\0\0\x1,\0\xff\xff\xff\xfa\0\0\0\0\x2\0\0\0\x3\xfb\0\0\0$\0T\0\x65\0r\0m\0i\0n\0\x61\0l\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\xe1\0\xff\xff\xff\xfb\0\0\0\x14\0\x46\0i\0l\0\x65\0\x45\0\x64\0i\0t\0o\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0k\0\xff\xff\xff\xfb\0\0\0.\0\x44\0o\0\x63\0u\0m\0\x65\0n\0t\0\x61\0t\0i\0o\0n\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\xba\0\xff\xff\xff\0\0\0\0\0\0\x2]\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\x2\0\0\0\x1\0\0\0\x16\0M\0\x61\0i\0n\0T\0o\0o\0l\0\x42\0\x61\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0)"
-current_directory_list=/scratch/jwe/build/octave
+geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xff\xfa\0\0\0\x13\0\0\x4\xc1\0\0\x3\xb4\0\0\0\x4\0\0\0\x31\0\0\x4\xb7\0\0\x3\xaa\0\0\0\0\0\0)
+windowState="@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x1\0\0\x4\xb4\0\0\x3#\xfc\x2\0\0\0\x1\xfc\0\0\0@\0\0\x3#\0\0\x1\x7f\0\xff\xff\xff\xfc\x1\0\0\0\x2\xfc\0\0\0\0\0\0\x2\x1c\0\0\0\xb4\0\xff\xff\xff\xfc\x2\0\0\0\x3\xfb\0\0\0\x1e\0\x46\0i\0l\0\x65\0s\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0@\0\0\x1#\0\0\0\x89\0\xff\xff\xff\xfb\0\0\0\x1a\0W\0o\0r\0k\0s\0p\0\x61\0\x63\0\x65\0V\0i\0\x65\0w\x1\0\0\x1i\0\0\0\xd4\0\0\0\x63\0\xff\xff\xff\xfb\0\0\0\"\0H\0i\0s\0t\0o\0r\0y\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\x2\x43\0\0\x1 \0\0\0\x87\0\xff\xff\xff\xfc\0\0\x2\"\0\0\x2\x92\0\0\x1,\0\xff\xff\xff\xfc\x2\0\0\0\x2\xfb\0\0\0\x1c\0N\0\x65\0w\0s\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0@\0\0\0\xdb\0\0\0\x14\0\xff\xff\xff\xfc\0\0\x1!\0\0\x2\x42\0\0\0\xfb\x1\0\0\x1e\xfa\0\0\0\0\x2\0\0\0\x3\xfb\0\0\0$\0T\0\x65\0r\0m\0i\0n\0\x61\0l\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\xdc\0\xff\xff\xff\xfb\0\0\0\x14\0\x46\0i\0l\0\x65\0\x45\0\x64\0i\0t\0o\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\x64\0\xff\xff\xff\xfb\0\0\0.\0\x44\0o\0\x63\0u\0m\0\x65\0n\0t\0\x61\0t\0i\0o\0n\0\x44\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\xae\0\xff\xff\xff\0\0\0\0\0\0\x3#\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1\0\0\0\x2\0\0\0\x1\0\0\0\x16\0M\0\x61\0i\0n\0T\0o\0o\0l\0\x42\0\x61\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0)"
 
 [DockWidgets]
-TerminalDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\x1\x7f\0\0\0\x42\0\0\x4\x13\0\0\x2\x7f\0\0\x1\x7f\0\0\0\x42\0\0\x4\x13\0\0\x2\x7f\0\0\0\0\0\0)
+NewsDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0)
+TerminalDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfd\xa8\xff\xff\xfd\xee\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfd\xa8\xff\xff\xfd\xee\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0)
 TerminalDockWidgetFloating=false
 TerminalDockWidgetVisible=true
-WorkspaceView=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x1\b\0\0\x1x\0\0\x1\xd5\0\0\0\0\0\0\x1\b\0\0\x1x\0\0\x1\xd5\0\0\0\0\0\0)
+WorkspaceView=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x1i\0\0\x2\x1b\0\0\x2<\0\0\0\0\0\0\x1i\0\0\x2\x1b\0\0\x2<\0\0\0\0\0\0)
 WorkspaceViewFloating=false
 WorkspaceViewVisible=true
-HistoryDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x1\xdc\0\0\x1x\0\0\x2\x9e\0\0\0\0\0\0\x1\xdc\0\0\x1x\0\0\x2\x9e\0\0\0\0\0\0)
+HistoryDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\x2\x43\0\0\x2\x1b\0\0\x3\x62\0\0\0\0\0\0\x2\x43\0\0\x2\x1b\0\0\x3\x62\0\0\0\0\0\0)
 HistoryDockWidgetFloating=false
 HistoryDockWidgetVisible=true
-FilesDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\x42\0\0\x1x\0\0\x1\x1\0\0\0\0\0\0\0\x42\0\0\x1x\0\0\x1\x1\0\0\0\0\0\0)
+FilesDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0@\0\0\x2\x1b\0\0\x1\x62\0\0\0\0\0\0\0@\0\0\x2\x1b\0\0\x1\x62\0\0\0\0\0\0)
 FilesDockWidgetFloating=false
 FilesDockWidgetVisible=true
-DocumentationDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfb\xb3\xff\xff\xfb\xb1\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfb\xb3\xff\xff\xfb\xb1\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0)
+DocumentationDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfd\x31\xff\xff\xfd^\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfd\x31\xff\xff\xfd^\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0)
 DocumentationDockWidgetFloating=false
 DocumentationDockWidgetVisible=true
-FileEditor=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfb\xb3\xff\xff\xfb\xb1\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfb\xb3\xff\xff\xfb\xb1\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0)
+FileEditor=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfc\x18\xff\xff\xfc|\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfc\x18\xff\xff\xfc|\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0)
 FileEditorFloating=false
 FileEditorVisible=true
+HistoryDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0)
+FilesDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0)
+DocumentationDockWidget_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\xff\xff\xfd\xa8\xff\xff\xfd\xee\xff\xff\xfe\v\xff\xff\xfe\v\xff\xff\xfd\xa8\xff\xff\xfd\xee\xff\xff\xfe\v\xff\xff\xfe\v\0\0\0\0\0\0)
+FileEditor_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x1\xf3\0\0\x1\x8f\0\0\0\0\0\0\0\0\0\0\x1\xf3\0\0\x1\x8f\0\0\0\0\0\0)
+WorkspaceView_floating_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\x63\0\0\0\x1d\0\0\0\0\0\0)
+NewsDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\x2\"\0\0\0@\0\0\x4\xb3\0\0\x1\x1a\0\0\x2\"\0\0\0@\0\0\x4\xb3\0\0\x1\x1a\0\0\0\0\0\0)
+NewsDockWidgetFloating=false
+NewsDockWidgetVisible=true
+TerminalDockWidget=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\x2\"\0\0\x1!\0\0\x4\xb3\0\0\x3\x43\0\0\x2\"\0\0\x1!\0\0\x4\xb3\0\0\x3\x43\0\0\0\0\0\0)
 
 [workspaceview]
 local_collapsed=false
 global_collapsed=false
 persistent_collapsed=false
-column_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1\xf4\0\0\0\x5\x1\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x1\0\0\x1\xf4\0\0\0\x5\0\0\0\0)
+column_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x2\x12\0\0\0\x5\x1\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x2\0\0\x1\x90\0\0\0\x4\0\0\0\0\0\0\0\x82\0\0\0\x1\0\0\0\0)
 
 [filesdockwidget]
 sort_files_by_column=0
 sort_files_by_order=0
-column_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x4\xe\0\0\0\x3\0\0\0\x3\0\0\0\x64\0\0\0\x2\0\0\0\x64\0\0\0\x1\0\0\0\x64\0\0\x1\x63\0\0\0\x4\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x2\0\0\x1\x63\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\0)
+column_state=@ByteArray(\0\0\0\xff\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x4\xe\0\0\0\x3\0\0\0\x3\0\0\0\x64\0\0\0\x2\0\0\0\x64\0\0\0\x1\0\0\0\x64\0\0\x2\v\0\0\0\x4\x1\x1\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x64\xff\xff\xff\xff\0\0\0\x81\0\0\0\0\0\0\0\x2\0\0\x2\v\0\0\0\x1\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\0)
 showFilenames=true
 showFileSize=false
 showFileType=false
--- a/libgui/src/main-window.cc
+++ b/libgui/src/main-window.cc
@@ -40,6 +40,8 @@
 #include <QMessageBox>
 #include <QIcon>
 
+#include <QWebView>
+
 #include <utility>
 
 #ifdef HAVE_QSCINTILLA
@@ -69,6 +71,7 @@
   : QMainWindow (p),
     _workspace_model (new workspace_model ()),
     status_bar (new QStatusBar ()),
+    news_window (new news_dock_widget (this)),
     command_window (new terminal_dock_widget (this)),
     history_window (new history_dock_widget (this)),
     file_browser_window (new files_dock_widget (this)),
@@ -93,6 +96,7 @@
   // to its original pipe to capture error messages at exit.
 
   delete editor_window;     // first one for dialogs of modified editor-tabs
+  delete news_window;
   delete command_window;
   delete workspace_window;
   delete doc_browser_window;
@@ -247,6 +251,29 @@
 }
 
 void
+main_window::display_release_notes (void)
+{
+  display_url_in_window (QUrl ("file://" OCTAVE_OCTETCDIR "/NEWS"));
+}
+
+void
+main_window::display_url_in_window (const QUrl& url)
+{
+  QWidget *w = new QWidget;
+
+  QTextBrowser *browser = new QTextBrowser (w);
+  browser->setSource (url);
+
+  QVBoxLayout *vlayout = new QVBoxLayout;
+  vlayout->addWidget (browser);
+
+  w->setLayout (vlayout);
+  w->show ();
+  w->raise ();
+  w->activateWindow ();
+}
+
+void
 main_window::open_bug_tracker_page (void)
 {
   QDesktopServices::openUrl (QUrl ("http://octave.org/bugs.html"));
@@ -863,6 +890,7 @@
                   | QMainWindow::AllowNestedDocks
                   | QMainWindow::AllowTabbedDocks);
 
+  addDockWidget (Qt::RightDockWidgetArea, news_window);
   addDockWidget (Qt::RightDockWidgetArea, command_window);
   addDockWidget (Qt::RightDockWidgetArea, doc_browser_window);
   tabifyDockWidget (command_window, doc_browser_window);
@@ -1021,6 +1049,8 @@
   construct_window_menu (menu_bar);
 
   construct_help_menu (menu_bar);
+
+  construct_news_menu (menu_bar);
 }
 
 void
@@ -1266,6 +1296,9 @@
   QAction *show_documentation_action = construct_window_menu_item
     (window_menu, tr ("Show Documentation"), true, ctrl_shift + Qt::Key_5);
 
+  QAction *show_news_action = construct_window_menu_item
+    (window_menu, tr ("Show News Window"), true, ctrl_shift + Qt::Key_6);
+
   window_menu->addSeparator ();
 
   QAction *command_window_action = construct_window_menu_item
@@ -1286,6 +1319,9 @@
   QAction *documentation_action = construct_window_menu_item
     (window_menu, tr ("Documentation"), false, ctrl + Qt::Key_5);
 
+  QAction *news_action = construct_window_menu_item
+    (window_menu, tr ("News"), false, ctrl + Qt::Key_6);
+
   window_menu->addSeparator ();
 
   QAction *reset_windows_action
@@ -1323,6 +1359,9 @@
            show_editor_action, SLOT (setChecked (bool)));
 #endif
 
+  connect (show_news_action, SIGNAL (toggled (bool)),
+           news_window, SLOT (setVisible (bool)));
+
   connect (show_documentation_action, SIGNAL (toggled (bool)),
            doc_browser_window, SLOT (setVisible (bool)));
 
@@ -1346,6 +1385,9 @@
            editor_window, SLOT (focus ()));
 #endif
 
+  connect (news_action, SIGNAL (triggered ()),
+           news_window, SLOT (focus ()));
+
   connect (documentation_action, SIGNAL (triggered ()),
            doc_browser_window, SLOT (focus ()));
 
@@ -1420,6 +1462,24 @@
 }
 
 void
+main_window::construct_news_menu (QMenuBar *p)
+{
+  QMenu *news_menu = p->addMenu (tr ("&News"));
+
+  QAction *release_notes_action
+    = news_menu->addAction (tr ("Release Notes"));
+
+  QAction *current_news_action
+    = news_menu->addAction (tr ("Community News"));
+
+  connect (release_notes_action, SIGNAL (triggered ()),
+           this, SLOT (display_release_notes ()));
+
+  connect (current_news_action, SIGNAL (triggered ()),
+           news_window, SLOT (show ()));
+}
+
+void
 main_window::construct_tool_bar (void)
 {
   _main_tool_bar = addToolBar ("Main");
--- a/libgui/src/main-window.h
+++ b/libgui/src/main-window.h
@@ -51,6 +51,7 @@
 #include "workspace-view.h"
 #include "history-dock-widget.h"
 #include "files-dock-widget.h"
+#include "news-dock-widget.h"
 #include "terminal-dock-widget.h"
 #include "documentation-dock-widget.h"
 #include "octave-qt-link.h"
@@ -108,6 +109,7 @@
   void new_file (const QString& commands = QString ());
   void open_file (const QString& file_name = QString ());
   void open_online_documentation_page (void);
+  void display_release_notes (void);
   void open_bug_tracker_page (void);
   void open_octave_packages_page (void);
   void open_agora_page (void);
@@ -216,8 +218,12 @@
   void construct_help_menu (QMenuBar *p);
   void construct_documentation_menu (QMenu *p);
 
+  void construct_news_menu (QMenuBar *p);
+
   void construct_tool_bar (void);
 
+  void display_url_in_window (const QUrl& url);
+
   void establish_octave_link (void);
 
   void save_workspace_callback (const std::string& file);
@@ -263,6 +269,7 @@
   QStatusBar *status_bar;
 
   // Subwindows.
+  news_dock_widget *news_window;
   terminal_dock_widget *command_window;
   history_dock_widget *history_window;
   files_dock_widget *file_browser_window;
@@ -272,6 +279,7 @@
   QList<octave_dock_widget *> dock_widget_list ()
   {
     QList<octave_dock_widget *> list = QList<octave_dock_widget *> ();
+    list.append (static_cast<octave_dock_widget *> (news_window));
     list.append (static_cast<octave_dock_widget *> (command_window));
     list.append (static_cast<octave_dock_widget *> (history_window));
     list.append (static_cast<octave_dock_widget *> (file_browser_window));
@@ -284,6 +292,7 @@
   }
 
   QToolBar *_main_tool_bar;
+
   QMenu *_debug_menu;
 
   QAction *_debug_continue;
--- a/libgui/src/module.mk
+++ b/libgui/src/module.mk
@@ -85,6 +85,7 @@
   src/moc-main-window.cc \
   src/moc-octave-qt-link.cc \
   src/moc-settings-dialog.cc \
+  src/moc-news-dock-widget.cc \
   src/moc-terminal-dock-widget.cc \
   src/moc-color-picker.cc \
   src/moc-welcome-wizard.cc \
@@ -125,6 +126,7 @@
   src/qtinfo/webinfo.h \
   src/resource-manager.h \
   src/settings-dialog.h \
+  src/news-dock-widget.h \
   src/terminal-dock-widget.h \
   src/color-picker.h \
   src/welcome-wizard.h \
@@ -151,6 +153,7 @@
   src/qtinfo/webinfo.cc \
   src/resource-manager.cc \
   src/settings-dialog.cc \
+  src/news-dock-widget.cc \
   src/terminal-dock-widget.cc \
   src/color-picker.cc \
   src/welcome-wizard.cc \
new file mode 100644
--- /dev/null
+++ b/libgui/src/news-dock-widget.cc
@@ -0,0 +1,137 @@
+/*
+
+Copyright (C) 2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <iostream>
+
+#include <QVBoxLayout>
+#include <QThread>
+
+#include "news-dock-widget.h"
+
+#include "Array.h"
+#include "str-vec.h"
+#include "url-transfer.h"
+
+#include "version.h"
+
+news_dock_widget::news_dock_widget (QWidget *p)
+  : octave_dock_widget (p), news_browser (new QWebView (p))
+{
+  news_browser->setObjectName ("OctaveNews");
+
+  setObjectName ("NewsDockWidget");
+  setWindowIcon (QIcon (":/icons/logo.png"));
+  set_title (tr ("Community News"));
+
+  setWidget (news_browser);
+
+  load_news ();
+}
+
+void
+news_dock_widget::load_news (void)
+{
+  QString base_url = "http://octave.org";
+  QString page = "community-news.html";
+
+  QThread *worker_thread = new QThread;
+
+  news_reader *reader = new news_reader (base_url, page);
+
+  reader->moveToThread (worker_thread);
+
+  connect (reader, SIGNAL (display_news_signal (const QString&, const QUrl&)),
+           this, SLOT (display_news (const QString&, const QUrl&)));
+
+  connect (worker_thread, SIGNAL (started (void)), reader, SLOT (process ()));
+
+  connect (reader, SIGNAL (finished (void)), worker_thread, SLOT (quit ()));
+
+  connect (reader, SIGNAL (finished (void)), reader, SLOT (deleteLater ()));
+
+  connect (worker_thread, SIGNAL (finished (void)),
+           worker_thread, SLOT (deleteLater ()));
+
+  worker_thread->start ();
+}
+
+static const char fixed_news[] = "<html>\n\
+<body>\n\
+<p>\n\
+This window will be used to inform you about Octave community events.\n\
+Octave may show it to you even if you've chosen hide the window by\n\
+default.  We'll try not to bother you too much, but we do want to keep\n\
+you up to date with the latest information about important bug fixes,\n\
+new releases, or any other news that all Octave users should be aware of.\n\
+</p>\n\
+<p>\n\
+Currently, Octave's community news source seems to be unavailable.\n\
+For the latest news, please check\n\
+<a href=\"http://octave.org/community-news.html\">http://octave.org/community-news.html</a>\n\
+when you have a connection to the web.\n\
+</p>\n\
+<p>\n\
+<small><em>&mdash; The Octave Developers, " OCTAVE_RELEASE_DATE "</em></small>\n\
+</body>\n\
+</html>\n";
+
+void
+news_dock_widget::display_news (const QString& news, const QUrl& base_url)
+{
+  if (news.contains ("this-is-the-gnu-octave-community-news-page"))
+    {
+      news_browser->setHtml (news, base_url);
+
+      if (news.contains ("critical-news-event") && ! isVisible ())
+        setVisible (true);
+    }
+  else
+    news_browser->setHtml (fixed_news);
+}
+
+void
+news_reader::process (void)
+{
+  // Run this part in a separate thread so Octave can continue to run
+  // while we wait for the page to load.  Then emit the signal to
+  // display it when we have the page contents.
+
+  QString url = base_url + "/" + page;
+  std::ostringstream buf;
+  url_transfer octave_dot_org (url.toStdString (), buf);
+
+  Array<std::string> param;
+  octave_dot_org.http_get (param);
+
+  QString html_text;
+
+  if (octave_dot_org.good ())
+    html_text = QString::fromStdString (buf.str ());
+
+  emit display_news_signal (html_text, QUrl (base_url));
+
+  emit finished ();
+}
new file mode 100644
--- /dev/null
+++ b/libgui/src/news-dock-widget.h
@@ -0,0 +1,75 @@
+/*
+
+Copyright (C) 2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef NEWSDOCKWIDGET_H
+#define NEWSDOCKWIDGET_H
+
+#include <QBasicTimer>
+#include <QWebView>
+
+#include "octave-dock-widget.h"
+
+class news_dock_widget : public octave_dock_widget
+{
+  Q_OBJECT
+
+public:
+
+  news_dock_widget (QWidget *parent = 0);
+
+  void load_news (void);
+
+protected slots:
+
+  void display_news (const QString& news, const QUrl& base_url);
+
+private:
+
+  QWebView *news_browser;
+};
+
+class news_reader : public QObject
+{
+  Q_OBJECT
+ 
+public:
+
+  news_reader (const QString& xbase_url, const QString& xpage)
+    : QObject (), base_url (xbase_url), page (xpage) { }
+ 
+public slots:
+
+    void process (void);
+ 
+signals:
+
+  void display_news_signal (const QString& news, const QUrl& base_url);
+
+  void finished (void);
+ 
+private:
+
+  QString base_url;
+  QString page;
+};
+
+#endif // NEWSDOCKWIDGET_H