[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[vidalia-svn] r4074: Add a StatusEventWidget subclass of QTreeWidget that catches (in vidalia/trunk/src/vidalia: . log res res/16x16 res/32x32 res/48x48)



Author: edmanm
Date: 2009-08-28 01:36:43 -0400 (Fri, 28 Aug 2009)
New Revision: 4074

Added:
   vidalia/trunk/src/vidalia/log/StatusEventItem.cpp
   vidalia/trunk/src/vidalia/log/StatusEventItem.h
   vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.cpp
   vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.h
   vidalia/trunk/src/vidalia/log/StatusEventWidget.cpp
   vidalia/trunk/src/vidalia/log/StatusEventWidget.h
   vidalia/trunk/src/vidalia/res/32x32/dialog-ok-apply.png
   vidalia/trunk/src/vidalia/res/32x32/dialog-warning.png
   vidalia/trunk/src/vidalia/res/32x32/script-error.png
   vidalia/trunk/src/vidalia/res/32x32/security-low.png
   vidalia/trunk/src/vidalia/res/32x32/security-medium.png
   vidalia/trunk/src/vidalia/res/48x48/chronometer.png
   vidalia/trunk/src/vidalia/res/48x48/network-connect.png
Modified:
   vidalia/trunk/src/vidalia/CMakeLists.txt
   vidalia/trunk/src/vidalia/res/16x16/system-help.png
   vidalia/trunk/src/vidalia/res/vidalia.qrc
Log:

Add a StatusEventWidget subclass of QTreeWidget that catches Tor status
events and displays them using a custom item delegate for painting.
Also add initial support for the main general and client status events and
a handful of new icons used when displaying those events in the
StatusEventWidget.


Modified: vidalia/trunk/src/vidalia/CMakeLists.txt
===================================================================
--- vidalia/trunk/src/vidalia/CMakeLists.txt	2009-08-28 05:32:01 UTC (rev 4073)
+++ vidalia/trunk/src/vidalia/CMakeLists.txt	2009-08-28 05:36:43 UTC (rev 4074)
@@ -163,12 +163,17 @@
   log/LogTreeItem.cpp
   log/LogTreeWidget.cpp
   log/MessageLog.cpp
+  log/StatusEventItem.cpp
+  log/StatusEventItemDelegate.cpp
+  log/StatusEventWidget.cpp
 )
 qt4_wrap_cpp(vidalia_SRCS
   log/LogFile.h
   log/LogHeaderView.h
   log/LogTreeWidget.h
   log/MessageLog.h
+  log/StatusEventItemDelegate.h
+  log/StatusEventWidget.h
 )
 
 ## Network map sources

Added: vidalia/trunk/src/vidalia/log/StatusEventItem.cpp
===================================================================
--- vidalia/trunk/src/vidalia/log/StatusEventItem.cpp	                        (rev 0)
+++ vidalia/trunk/src/vidalia/log/StatusEventItem.cpp	2009-08-28 05:36:43 UTC (rev 4074)
@@ -0,0 +1,66 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file StatusEventItem.cpp
+** \version $Id$
+** \brief Represents a single status event item in a StatusEventWidget
+*/
+
+#include "StatusEventItem.h"
+
+#include <QTime>
+#include <QPixmap>
+#include <QString>
+
+StatusEventItem::StatusEventItem(QTreeWidget *parent)
+  : QTreeWidgetItem(parent, QTreeWidgetItem::UserType)
+{
+}
+
+void
+StatusEventItem::setTimestamp(const QTime &timestamp)
+{
+  setData(0, TimestampRole, timestamp);
+}
+
+void
+StatusEventItem::setIcon(const QPixmap &pixmap)
+{
+  setData(0, IconRole, pixmap);
+}
+
+void
+StatusEventItem::setTitle(const QString &title)
+{
+  setData(0, TitleRole, title);
+}
+
+void
+StatusEventItem::setDescription(const QString &description)
+{
+  setData(0, DescriptionRole, description);
+}
+
+void
+StatusEventItem::setHelpUrl(const QString &url)
+{
+  setData(0, HelpUrlRole, url);
+}
+
+bool
+StatusEventItem::operator<(const QTreeWidgetItem &other) const
+{
+  QTime a = data(0, TimestampRole).toTime();
+  QTime b = other.data(0, TimestampRole).toTime();
+
+  return (a < b);
+}
+


Property changes on: vidalia/trunk/src/vidalia/log/StatusEventItem.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: vidalia/trunk/src/vidalia/log/StatusEventItem.h
===================================================================
--- vidalia/trunk/src/vidalia/log/StatusEventItem.h	                        (rev 0)
+++ vidalia/trunk/src/vidalia/log/StatusEventItem.h	2009-08-28 05:36:43 UTC (rev 4074)
@@ -0,0 +1,83 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file StatusEventItem.cpp
+** \version $Id$
+** \brief Represents a single status event item in a StatusEventWidget
+*/
+
+#ifndef _STATUSEVENTITEM_H
+#define _STATUSEVENTITEM_H
+
+#include <QTreeWidgetItem>
+
+class QTime;
+class QPixmap;
+class QString;
+
+class StatusEventItem : public QTreeWidgetItem
+{
+public:
+  /** QModelIndex data roles used to store information with this status
+   * event item, allowing it to be retrieved by StatusEventItemDelegate for
+   * painting.
+   */
+  enum DataRole {
+    IconRole = Qt::UserRole,
+    TimestampRole,
+    TitleRole,
+    DescriptionRole,
+    HelpUrlRole,
+  };
+
+  /** Default constructor.
+   */
+  StatusEventItem(QTreeWidget *parent = 0);
+
+  /** Sets the <b>timestamp</b> at which this status event occurred.
+   */
+  void setTimestamp(const QTime &timestamp);
+
+  /** Sets the icon to be drawn along with this status event to <b>pixmap</b>.
+   */
+  void setIcon(const QPixmap &pixmap);
+
+  /** Sets the <b>title</b> text for this status event. The title is a short
+   * (fewer than 10 words or so) summary of the event.
+   */
+  void setTitle(const QString &title);
+
+  /** Sets the detailed <b>description</b> text for this status event. The
+   * text should explain what the event means to the user, and any corrective
+   * action they might need to take.
+   */
+  void setDescription(const QString &description);
+
+  /** Sets the help topic URL that contains more information about this
+   * particular status event.
+   * \sa helpUrl
+   */
+  void setHelpUrl(const QString &url);
+
+  /** Returns the help topic URL associated with this event item.
+   * \sa setHelpUrl
+   */
+  void helpUrl() const;
+
+  /** Overloaded comparison operator that allows sorting StatusEventItem
+   * objects based on timestamp. Returns true if <i>this</i> StatusEventItem
+   * occurred before <b>other</b>.
+   */
+  virtual bool operator<(const QTreeWidgetItem &other) const;
+};
+
+#endif
+


Property changes on: vidalia/trunk/src/vidalia/log/StatusEventItem.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.cpp
===================================================================
--- vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.cpp	                        (rev 0)
+++ vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.cpp	2009-08-28 05:36:43 UTC (rev 4074)
@@ -0,0 +1,180 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file StatusEventItemDelegate.cpp
+** \version $Id$
+** \brief Handles custom painting of items in a StatusEventWidget
+*/
+
+#include "StatusEventItemDelegate.h"
+#include "StatusEventItem.h"
+
+#include "Vidalia.h"
+
+#include <QPainter>
+#include <QTextLine>
+#include <QTextLayout>
+
+StatusEventItemDelegate::StatusEventItemDelegate(QObject *parent)
+  : QItemDelegate(parent)
+{
+  _helpIcon = QPixmap(":/images/16x16/system-help.png");
+}
+
+void
+StatusEventItemDelegate::paint(QPainter *painter,
+                               const QStyleOptionViewItem &option,
+                               const QModelIndex &index) const
+{
+  QItemDelegate::paint(painter, option, index);
+
+  painter->save();
+  if (option.state & QStyle::State_Selected)
+    painter->setPen(option.palette.highlightedText().color());
+
+  QPixmap icon  = index.data(StatusEventItem::IconRole).value<QPixmap>();
+  QTime tstamp  = index.data(StatusEventItem::TimestampRole).toTime();
+  QString title = index.data(StatusEventItem::TitleRole).toString();
+  QString text  = index.data(StatusEventItem::DescriptionRole).toString();
+  QFont font    = option.font;
+  QFontMetrics fm = option.fontMetrics;
+
+  /* XXX: Handle right-to-left layouts here. */
+  QRect iconRect(option.rect.x(),
+                 option.rect.y(),
+                 qMax(fm.width(tstamp.toString()), icon.width()) + 16,
+                 option.rect.height());
+  QRect textRect(iconRect.topRight(), option.rect.bottomRight());
+
+  // Draw the status icon
+  QPoint center = iconRect.center();
+  int x = center.x() - (icon.width() / 2.0);
+  int y = center.y() - ((icon.height() + fm.lineSpacing()) / 2.0);
+  painter->drawPixmap(x, y, icon);
+
+  // Draw the timestamp text underneath the status icon
+  x = iconRect.x();
+  y = y + icon.height();
+  painter->drawText(x, y,
+                    iconRect.width(),
+                    fm.lineSpacing(),
+                    Qt::AlignCenter,
+                    tstamp.toString());
+
+  // Draw the event's title in a bold font. If the current item has an
+  // associated help URL, draw the little "?" icon to the right of the
+  // title text
+  font.setBold(true);
+  painter->setFont(font);
+  if (! index.data(StatusEventItem::HelpUrlRole).isNull()) {
+    // Draw the little "?" icon in the corner of the list item and
+    // account for it when eliding the title
+    title = fm.elidedText(title,
+                          Qt::ElideRight,
+                          textRect.width() - _helpIcon.width() - 24);
+
+    x = textRect.topRight().x() - _helpIcon.width() - 8;
+    y = textRect.y() + 8;
+    painter->drawPixmap(x, y, _helpIcon);
+  } else {
+    title = fm.elidedText(title, Qt::ElideRight, textRect.width() - 16);
+  }
+  painter->drawText(textRect.x(),
+                    textRect.y() + 8,
+                    textRect.width(),
+                    fm.lineSpacing(),
+                    Qt::AlignVCenter | Qt::AlignLeft, title);
+
+  // Draw the rest of the event text, up to a maximum of 2 lines for
+  // unselected items or 5 lines for selected items. Any extra text will
+  // be elided.
+  font.setBold(false);
+  painter->setFont(font);
+  if (option.state & QStyle::State_Selected)
+    text = layoutText(text, font, textRect.width(), 6).join("\n");
+  else
+    text = layoutText(text, font, textRect.width(), 3).join("\n");
+
+  x = textRect.x();
+  y = textRect.y() + 8 + fm.leading() + fm.lineSpacing();
+  painter->drawText(x, y,
+                    textRect.width(),
+                    textRect.height() - (y - textRect.y()),
+                    Qt::AlignTop | Qt::AlignLeft, text);
+
+  painter->restore();
+}
+
+QSize
+StatusEventItemDelegate::sizeHint(const QStyleOptionViewItem &option,
+                                  const QModelIndex &index) const
+{
+  int iconHeight, iconWidth;
+  int textWidth, textHeight;
+  QFontMetrics fontMetrics = option.fontMetrics;
+
+  QPixmap icon = index.data(StatusEventItem::IconRole).value<QPixmap>();
+  QString text = index.data(StatusEventItem::DescriptionRole).toString();
+  QTime tstamp = index.data(StatusEventItem::TimestampRole).toTime();
+
+  iconHeight = icon.height() + fontMetrics.lineSpacing() + 16;
+  iconWidth  = qMax(fontMetrics.width(tstamp.toString()), icon.width()) + 16;
+  textWidth  = option.rect.width() - iconWidth;
+
+  if (option.state & QStyle::State_Selected)
+    layoutText(text, option.font, textWidth, 6, &textHeight);
+  else
+    layoutText(text, option.font, textWidth, 3, &textHeight);
+  textHeight += 8 + fontMetrics.leading() + fontMetrics.lineSpacing();
+
+  return QSize(option.rect.width(), qMax(iconHeight, textHeight));
+}
+
+QStringList
+StatusEventItemDelegate::layoutText(const QString &text,
+                                    const QFont &font,
+                                    int maxLineWidth,
+                                    int maxLines,
+                                    int *textHeight)
+{
+  QTextLayout textLayout(text, font);
+  QFontMetrics fontMetrics(font);
+  QStringList lines;
+  qreal height = 0.0;
+
+  textLayout.beginLayout();
+  while (lines.length() < maxLines) {
+    QTextLine line = textLayout.createLine();
+    if (! line.isValid())
+      break;
+    if (maxLines <= 0 || lines.length() < maxLines-1) {
+      // Wrap the current line at or below the maximum line width
+      line.setLineWidth(maxLineWidth);
+      lines.append(text.mid(line.textStart(), line.textLength()));
+    } else {
+      // Set the line width beyond the max line width, and then elide it
+      // so the user has a visible indication that the full message is
+      // longer than what is visible.
+      line.setLineWidth(2 * maxLineWidth);
+      lines.append(fontMetrics.elidedText(text.mid(line.textStart()),
+                                          Qt::ElideRight,
+                                          maxLineWidth));
+    }
+    height += fontMetrics.leading() + line.height();
+  }
+  textLayout.endLayout();
+
+  if (textHeight)
+    *textHeight = qRound(height);
+
+  return lines;
+}
+


Property changes on: vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.h
===================================================================
--- vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.h	                        (rev 0)
+++ vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.h	2009-08-28 05:36:43 UTC (rev 4074)
@@ -0,0 +1,71 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file StatusEventItemDelegate.h
+** \version $Id$
+** \brief Handles custom painting of items in a StatusEventWidget
+*/
+
+#ifndef _STATUSEVENTITEMDELEGATE_H
+#define _STATUSEVENTITEMDELEGATE_H
+
+#include <QItemDelegate>
+#include <QPixmap>
+
+class QStringList;
+
+class StatusEventItemDelegate : public QItemDelegate
+{
+  Q_OBJECT
+
+public:
+  /** Default constructor.
+   */
+  StatusEventItemDelegate(QObject *parent = 0);
+
+  /** Paints a status event item for <b>index</b> using the given paint
+   * device <b>painter</b> and current style <b>option</b>s.
+   */
+  virtual void paint(QPainter *painter,
+                     const QStyleOptionViewItem &option,
+                     const QModelIndex &index) const;
+
+  /** Returns a QSize representing the desired dimensions needed to paint
+   * a status event item for <b>index</b> using the specified style
+   * <b>option</b>s.
+   */
+  virtual QSize sizeHint(const QStyleOptionViewItem &option,
+                         const QModelIndex &index) const;
+
+protected:
+  /** Splits <b>text</b> at <b>maxLineWidth</b> pixels computed using the
+   * font dimensions given by <b>fontMetrics</b> and returns a QStringList
+   * containing at most <b>maxLines</b> of text. If the number of wrapped
+   * lines is greater than or equal to <b>maxLines</b>, the last line of 
+   * text will be elided. If <b>maxLines</b> is less than or equal to 0, no
+   * eliding will be done. If <b>textHeight</b> is not NULL, it will be set
+   * to the height (in pixels) required to display the returned wrapped
+   * lines.
+   */
+  static QStringList layoutText(const QString &text,
+                                const QFont &fontMetrics,
+                                int maxLineWidth,
+                                int maxLines = -1,
+                                int *textHeight = 0);
+
+private:
+  /** Small icon image drawn in the upper-right (or upper-left in RTL
+   * layouts) for status events that have associated help URLs. */
+  QPixmap _helpIcon;
+};
+
+#endif
+


Property changes on: vidalia/trunk/src/vidalia/log/StatusEventItemDelegate.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: vidalia/trunk/src/vidalia/log/StatusEventWidget.cpp
===================================================================
--- vidalia/trunk/src/vidalia/log/StatusEventWidget.cpp	                        (rev 0)
+++ vidalia/trunk/src/vidalia/log/StatusEventWidget.cpp	2009-08-28 05:36:43 UTC (rev 4074)
@@ -0,0 +1,266 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file StatusEventWidget.h
+** \version $Id$
+** \brief Displays information on Tor status events
+*/
+
+#include "StatusEventWidget.h"
+#include "StatusEventItem.h"
+#include "StatusEventItemDelegate.h"
+#include "Vidalia.h"
+
+#include "TorEvents.h"
+
+#include <QTime>
+#include <QPainter>
+#include <QPixmap>
+#include <QStringList>
+#include <QObject>
+#include <QHeaderView>
+
+StatusEventWidget::StatusEventWidget(QWidget *parent)
+  : QTreeWidget(parent)
+{
+  TorControl *tc = Vidalia::torControl();
+  tc->setEvent(TorEvents::GeneralStatus);
+  tc->setEvent(TorEvents::ClientStatus);
+  tc->setEvent(TorEvents::ServerStatus);
+
+  connect(tc, SIGNAL(authenticated()), this, SLOT(authenticated()));
+  connect(tc, SIGNAL(disconnected()), this, SLOT(disconnected()));
+  connect(tc, SIGNAL(dangerousTorVersion(tc::TorVersionStatus, QString,
+                                         QStringList)),
+         this, SLOT(dangerousTorVersion(tc::TorVersionStatus, QString,
+                                        QStringList)));
+  connect(tc, SIGNAL(circuitEstablished()), this, SLOT(circuitEstablished()));
+  connect(tc, SIGNAL(bug(QString)), this, SLOT(bug(QString)));
+  connect(tc, SIGNAL(clockSkewed(int, QString)),
+          this, SLOT(clockSkewed(int, QString)));
+  connect(tc, SIGNAL(dangerousPort(quint16, bool)),
+          this, SLOT(dangerousPort(quint16, bool)));
+
+  setItemDelegate(new StatusEventItemDelegate(this));
+}
+
+void
+StatusEventWidget::retranslateUi()
+{
+  /* XXX: We need to store the untranslated text for each of the status
+   *      event items, iterate through all items in the list, and then
+   *      retranslate them. The trick is that some of the messages are
+   *      generated dynamically based on data sent by Tor (which is NOT
+   *      translated). Those messages we can't retranslate correctly
+   *      without also storing the variables used to generate the message.
+   */
+}
+
+void
+StatusEventWidget::setMaximumItemCount(int maximumItemCount)
+{
+  _maximumItemCount = maximumItemCount;
+
+  QTreeWidgetItem *item;
+  Qt::SortOrder order = header()->sortIndicatorOrder();
+  while (topLevelItemCount() > _maximumItemCount) {
+    if (order == Qt::AscendingOrder)
+      item = takeTopLevelItem(0);
+    else
+      item = takeTopLevelItem(topLevelItemCount()-1);
+    if (item)
+      delete item;
+  }
+}
+
+int
+StatusEventWidget::maximumItemCount() const
+{
+  return _maximumItemCount;
+}
+
+void
+StatusEventWidget::addNotification(const QPixmap &icon,
+                                   const QString &title,
+                                   const QString &description,
+                                   const QString &helpUrl)
+{
+  // Check if we first need to remove the oldest item in the list in order
+  // to avoid exceeding the maximum number of notification items
+  if (topLevelItemCount() == maximumItemCount()) {
+    QTreeWidgetItem *item;
+    if (header()->sortIndicatorOrder() == Qt::AscendingOrder)
+      item = takeTopLevelItem(0);
+    else
+      item = takeTopLevelItem(topLevelItemCount()-1);
+    if (item)
+      delete item;
+  }
+
+  // Create the new notification item
+  StatusEventItem *item = new StatusEventItem(this);
+  item->setTimestamp(QTime::currentTime());
+  item->setIcon(icon);
+  item->setTitle(title);
+  item->setDescription(description);
+  item->setHelpUrl(helpUrl);
+
+  // Add the new item to the list and ensure it is visible
+  addTopLevelItem(item);
+  scrollToItem(item, QAbstractItemView::EnsureVisible);
+}
+
+QPixmap
+StatusEventWidget::addBadgeToPixmap(const QPixmap &pixmap,
+                                    const QPixmap &badge)
+{
+  QPixmap out = pixmap;
+  QPainter painter(&out);
+  painter.drawPixmap(pixmap.width() - badge.width(),
+                     pixmap.height() - badge.height(),
+                     badge);
+  return out;
+}
+
+void
+StatusEventWidget::authenticated()
+{
+  QString version = Vidalia::torControl()->getTorVersionString();
+  QPixmap icon = addBadgeToPixmap(QPixmap(":/images/48x48/tor-logo.png"),
+                                  QPixmap(":/images/32x32/dialog-ok-apply.png"));
+  addNotification(icon,
+    tr("The Tor Software is Running"),
+    tr("You are currently running version \"%1\" of the Tor software.")
+                                                            .arg(version));
+}
+
+void
+StatusEventWidget::disconnected()
+{
+  QPixmap icon = addBadgeToPixmap(QPixmap(":/images/48x48/tor-logo.png"),
+                                  QPixmap(":/images/32x32/edit-delete.png"));
+
+  addNotification(icon,
+    tr("The Tor Software is not Running"),
+    tr("Click \"Start Tor\" in the Vidalia Control Panel to restart the Tor "
+       "software. If Tor exited unexpectedly, select the \"Advanced\" tab "
+       "above for details about any errors encountered."));
+}
+
+void
+StatusEventWidget::dangerousTorVersion(tc::TorVersionStatus reason,
+                                     const QString &version,
+                                     const QStringList &recommended)
+{
+  Q_UNUSED(recommended);
+  QString description;
+  QPixmap icon;
+
+  if (reason == tc::UnrecommendedTorVersion) {
+    icon = addBadgeToPixmap(QPixmap(":/images/48x48/tor-logo.png"),
+                            QPixmap(":/images/32x32/security-medium.png"));
+
+    description = 
+      tr("You are currently running version \"%1\" of the Tor software, which "
+         "is no longer recommended. Please upgrade to the most recent version "
+         "of the software, which may contain important security, reliability "
+         "and performance fixes.").arg(version);
+  } else if (reason == tc::ObsoleteTorVersion) {
+    icon = addBadgeToPixmap(QPixmap(":/images/48x48/tor-logo.png"),
+                            QPixmap(":/images/32x32/security-low.png"));
+
+    description =
+      tr("You are currently running version \"%1\" of the Tor software, which "
+         "likely no longer works with the current Tor network. Please upgrade "
+         "to the most recent version of the software, which may contain "
+         "important security, reliability and performance fixes.").arg(version);
+  }
+
+  addNotification(icon, tr("Your Tor Software is Out-of-date"), description);
+}
+
+void
+StatusEventWidget::circuitEstablished()
+{
+  addNotification(QPixmap(":/images/48x48/network-connect.png"),
+    tr("Connected to the Tor Network"),
+    tr("We were able to successfully establish a connection to the Tor "
+       "network. You can now configure your applications to use the Internet "
+       "anonymously."));
+}
+
+void
+StatusEventWidget::bug(const QString &description)
+{
+  QString bugsUrl = "https://bugs.torproject.org/";;
+  QPixmap icon = addBadgeToPixmap(QPixmap(":/images/48x48/tor-logo.png"),
+                                  QPixmap(":/images/32x32/script-error.png"));
+  addNotification(icon,
+    tr("Tor Software Error"),
+    tr("The Tor software encountered an internal bug. Please report the "
+       "following error message to the Tor developers at bugs.torproject.org: "
+       "\"%1\"").arg(description));
+}
+
+void
+StatusEventWidget::clockSkewed(int skew, const QString &source)
+{
+  Q_UNUSED(source);
+  QString description;
+  QPixmap icon = addBadgeToPixmap(QPixmap(":/images/48x48/chronometer.png"),
+                                  QPixmap(":/images/48x48/dialog-warning.png"));
+  
+  if (skew < 0) {
+    description = 
+      tr("Tor has determined that your computer's clock may be set to %1 "
+         "seconds in the past. If your clock is not correct, Tor will not be "
+         "able to function. Please verify your computer displays the correct "
+         "time.").arg(qAbs(skew));
+  } else {
+    description = 
+      tr("Tor has determined that your computer's clock may be set to %1 "
+         "seconds in the future. If your clock is not correct, Tor will not be "
+         "able to function. Please verify your computer displays the correct "
+         "time.").arg(qAbs(skew));
+  }
+  addNotification(icon, tr("Your Computer's Clock is Potentially Incorrect"),
+                  description);
+}
+
+void
+StatusEventWidget::dangerousPort(quint16 port, bool rejected)
+{
+  QPixmap icon;
+  QString description;
+
+  if (rejected) {
+    icon = addBadgeToPixmap(QPixmap(":/images/48x48/applications-internet.png"),
+                            QPixmap(":/images/32x32/security-low.png"));
+
+    description =
+      tr("One of the applications on your computer may have attempted to "
+         "make an unencrypted connection through Tor to port %1. Sending "
+         "unencrypted information over the Tor network is dangerous and not "
+         "recommended. For your protection, Tor has automatically closed this "
+         "connection.");
+  } else {
+    icon = addBadgeToPixmap(QPixmap(":/images/48x48/applications-internet.png"),
+                            QPixmap(":/images/32x32/security-medium.png"));
+    description =
+      tr("One of the applications on your computer may have attempted to "
+         "make an unencrypted connection through Tor to port %1. Sending "
+         "unencrypted information over the Tor network is dangerous and not "
+         "recommended.");
+  }
+
+  addNotification(icon, tr("Potentially Dangerous Connection!"), description);
+}
+


Property changes on: vidalia/trunk/src/vidalia/log/StatusEventWidget.cpp
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: vidalia/trunk/src/vidalia/log/StatusEventWidget.h
===================================================================
--- vidalia/trunk/src/vidalia/log/StatusEventWidget.h	                        (rev 0)
+++ vidalia/trunk/src/vidalia/log/StatusEventWidget.h	2009-08-28 05:36:43 UTC (rev 4074)
@@ -0,0 +1,120 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file StatusEventWidget.h
+** \version $Id$
+** \brief Displays information on Tor status events
+*/
+
+#ifndef _STATUSEVENTWIDGET_H
+#define _STATUSEVENTWIDGET_H
+
+#include <QTreeWidget>
+
+#include "TorControl.h"
+
+class QPixmap;
+class QString;
+class QStringList;
+
+class StatusEventWidget : public QTreeWidget
+{
+  Q_OBJECT
+
+public:
+  /** Default constructor.
+   */
+  StatusEventWidget(QWidget *parent = 0);
+
+  /** Sets the maximum number of status event items displayed to
+   * <b>maximumItemCount</b>. If the current number of items displayed
+   * exceeds <b>maximumItemCount</b>, the oldest items will be removed until
+   * topLevelItemCount() is equal to the new limit.
+   */
+  void setMaximumItemCount(int maximumItemCount);
+
+  /** Returns the maximum number of status items that can be displayed in 
+   * this StatusEventWidget.
+   */
+  int maximumItemCount() const;
+
+protected:
+  /** Called when the user has changed the UI display language in Vidalia
+   * indicating all the displayed text widgets need to be updated to
+   * display their value in the newly chosen language.
+   */
+  virtual void retranslateUi();
+
+private slots:
+  /** Called when the control socket is connected and authenticated. */
+  void authenticated();
+
+  /** Called when the controller has disconnected from Tor */
+  void disconnected();
+
+  /** Indicates that Tor has decided the user's Tor software <b>version</b>
+   * is no longer recommended for some <b>reason</b>. <b>recommended</b> is
+   * a list of Tor software versions that are considered current.
+   */
+  void dangerousTorVersion(tc::TorVersionStatus reason,
+                           const QString &version,
+                           const QStringList &recommended);
+
+  /** Indicates Tor has been able to successfully establish one or more
+   * circuits.
+   */
+  void circuitEstablished();
+
+  /** Emitted when Tor has encountered an internal bug. <b>reason</b> is
+   * Tor's description of the bug.
+   */
+  void bug(const QString &reason);
+
+  /** Indicates that Tor has determined the client's clock is potentially
+   * skewed by <b>skew</b> seconds relative to <b>source</b>.
+   */
+  void clockSkewed(int skew, const QString &source);
+
+  /** Called when the user attempts to establish a connection to some
+   * destination on port <b>port</b>, which is a port known to use
+   * plaintext connections (as determined by Tor's WarnPlaintextPorts and
+   * RejectPlaintextPorts torrc options). <b>rejected</b> indicates whether
+   * Tor rejected the connection or permitted it to connect anyway.
+   */
+  void dangerousPort(quint16 port, bool rejected);
+
+private:
+  /** Adds a new status event notification item to the widget. The item will
+   * be drawn using the specified <b>icon</b>, short event <b>title</b>,
+   * and a longer detailed <b>description</b>. If <b>helpUrl</b> is not
+   * empty, the item will also have a clickable question mark icon in the
+   * corner.
+   */
+  void addNotification(const QPixmap &icon,
+                       const QString &title,
+                       const QString &description,
+                       const QString &helpUrl = QString());
+
+  /** Creates a new QPixmap using <b>pixmap</b> as the main image and
+   * overlays <b>badge</b> in the lower-right corner of the image.
+   */
+  static QPixmap addBadgeToPixmap(const QPixmap &pixmap,
+                                  const QPixmap &badge);
+
+  /** Maximum number of event notifications contained in the StatusEventWidget
+   * at any given time.
+   * \sa setMaximumItemCount()
+   */
+  int _maximumItemCount;
+};
+
+#endif
+


Property changes on: vidalia/trunk/src/vidalia/log/StatusEventWidget.h
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: vidalia/trunk/src/vidalia/res/16x16/system-help.png
===================================================================
(Binary files differ)

Added: vidalia/trunk/src/vidalia/res/32x32/dialog-ok-apply.png
===================================================================
(Binary files differ)


Property changes on: vidalia/trunk/src/vidalia/res/32x32/dialog-ok-apply.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: vidalia/trunk/src/vidalia/res/32x32/dialog-warning.png
===================================================================
(Binary files differ)


Property changes on: vidalia/trunk/src/vidalia/res/32x32/dialog-warning.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: vidalia/trunk/src/vidalia/res/32x32/script-error.png
===================================================================
(Binary files differ)


Property changes on: vidalia/trunk/src/vidalia/res/32x32/script-error.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: vidalia/trunk/src/vidalia/res/32x32/security-low.png
===================================================================
(Binary files differ)


Property changes on: vidalia/trunk/src/vidalia/res/32x32/security-low.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: vidalia/trunk/src/vidalia/res/32x32/security-medium.png
===================================================================
(Binary files differ)


Property changes on: vidalia/trunk/src/vidalia/res/32x32/security-medium.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: vidalia/trunk/src/vidalia/res/48x48/chronometer.png
===================================================================
(Binary files differ)


Property changes on: vidalia/trunk/src/vidalia/res/48x48/chronometer.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: vidalia/trunk/src/vidalia/res/48x48/network-connect.png
===================================================================
(Binary files differ)


Property changes on: vidalia/trunk/src/vidalia/res/48x48/network-connect.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: vidalia/trunk/src/vidalia/res/vidalia.qrc
===================================================================
--- vidalia/trunk/src/vidalia/res/vidalia.qrc	2009-08-28 05:32:01 UTC (rev 4073)
+++ vidalia/trunk/src/vidalia/res/vidalia.qrc	2009-08-28 05:36:43 UTC (rev 4074)
@@ -52,10 +52,13 @@
     <qresource prefix="/images">
         <file>32x32/applications-internet.png</file>
         <file>32x32/applications-system.png</file>
+        <file>32x32/dialog-ok-apply.png</file>
+        <file>32x32/dialog-warning.png</file>
         <file>32x32/document-save.png</file>
         <file>32x32/document-save-all.png</file>
         <file>32x32/edit-clear.png</file>
         <file>32x32/edit-copy.png</file>
+        <file>32x32/edit-delete.png</file>
         <file>32x32/edit-find.png</file>
         <file>32x32/edit-select-all.png</file>
         <file>32x32/format-justify-fill.png</file>
@@ -69,6 +72,9 @@
         <file>32x32/preferences-system.png</file>
         <file>32x32/preferences-system-network.png</file>
         <file>32x32/preferences-system-network-sharing.png</file>
+        <file>32x32/script-error.png</file>
+        <file>32x32/security-low.png</file>
+        <file>32x32/security-medium.png</file>
         <file>32x32/services.png</file>
         <file>32x32/system-help.png</file>
         <file>32x32/system-software-update.png</file>
@@ -88,12 +94,15 @@
     </qresource>
     <qresource prefix="/images">
         <file>48x48/applications-internet.png</file>
+        <file>48x48/chronometer.png</file>
         <file>48x48/dialog-password.png</file>
         <file>48x48/media-playback-start.png</file>
         <file>48x48/media-playback-stop.png</file>
         <file>48x48/modem.png</file>
+        <file>48x48/network-connect.png</file>
         <file>48x48/network-workgroup.png</file>
         <file>48x48/preferences-system-network-sharing.png</file>
+        <file>48x48/tor-logo.png</file>
         <file>48x48/tor-off.png</file>
         <file>48x48/tor-on.png</file>
         <file>48x48/tor-starting.png</file>