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

List:       kde-panel-devel
Subject:    Re: [PATCH] Review request for plasma marble wallpaper (playground)
From:       Sascha Peilicke <sasch.pe () gmx ! de>
Date:       2008-12-18 19:05:15
Message-ID: 200812182005.18559.sasch.pe () gmx ! de
[Download RAW message or body]

[Attachment #2 (multipart/signed)]

[Attachment #4 (multipart/mixed)]


On Wednesday 17 December 2008 12:53:30 Frederik Gladhorn wrote:
> Hi Sascha,
> thanks for looking at the marble wallpaper - that's much appreciated from
> my side :)
> I have had no time to look at the patch at all yet, will do so on the
> weekend.
I attached a more current one here :-)

>
> On Monday 15 December 2008 21:41:16 Sascha Peilicke wrote:
> > For Frederic Gladhorn and FYI.
> >
> >
> > This patch adds/changes a lot of features to the marble plasma wallpaper
> > in playground.
> >
> > Re-enabled the stars plugin as current Marble trunk doesn't seem to crash
> > on it any further.
>
> Seems good to me, I enabled it again here and have had no trouble with it
> lately.
>
> > Moved to a more generic support for globe rotation schemes to allow
> > something like "hover on home location" or free rotation (with the marble
> > navigation plugin).
> >
> > Mouse interaction was removed completely, this caused all sort of weird
> > troubles when interacting with plasma widgets (instead rotates the globe
> > or vice versa). Mouse scrolling previously used for zooming the globe is
> > also otherwise reserved for switching workspaces. Instead the user can
> > enable the marble navigation widget to zoom/rotate the globe.
>
> I had not a single weird interaction - you just need to differentiate
> between applet and wallpaper and you'll be fine.
> This is the change that I don't agree with. For me the wallpaper is all
> about being fancy-interactive-hotness and it's sole purpose is to brag
> about KDE hotness with it.
> Many people hate the wheel on workspace option, I don't have a strong
> opinion either way, but I think the wheel is much better used to zoom here.
> This wallpaper doesn't bring speed or a faster work flow - it is just a
> toy, so people using the wheel to switch desktops won't use this wallpaper
> I guess. My problem with the marble navigation widgets is that they clutter
> the desktop. I want to see that globe thingy, not lots of controls.
> Maybe a checkbox to enable mouse interaction? More options ftw...?
Yeap, this seems to need a bit more discussion, here's what I currently have:

4 rotation modes, 2 already known (follow sun, custom rot), + hover on home + 
free movement. free movement basically means no movement + a checkbox which 
enables the marble navigation widget. I agree that it would be a bit clumsy to 
be shown all the time, so this is more intented to be enabled, move the globe 
in place, disable it and enjoy. A bonus is that the nav widget can be 
customized, so I stripped it down a bit, this is what it looks like when 
enabled:

http://img150.imageshack.us/img150/4710/marblenavwidgetwc3.png

> I started it to show a friend who had something similar once upon a time in
> some proprietary environment how flexible and great our frameworks are.
> I'd even like to open a browser with the placemarks - same as marble does.
> Wikipedia ftw.
Would be great to have, this would be the real semantic desktop ^^

> > Reworked the configuration screen to show only options which make sense
> > together. This means some values are shown and hidden based on selected
> > globe rotation behavior, marble theme etc. More generic "show placemarks"
> > instead of "show night, show citylights, show places" to not present too
> > much config detail to the user.
>
> Very good, I just threw in every marble option I could find ;) making it
> more understandable is a good idea.
>
> > Maybe we should also change the name from "The Earth" to something more
> > descriptive or just "Marble globe" to advertise this great technology ^^
>
> See Aarons reply, I'm fine with Globe, I'm a little against putting Marble
> here.
Updated the desktop file accordingly.


-- 
Sascha Peilicke
http://saschpe.wordpress.com

["marble-wallpaper-mod.patch" (text/x-patch)]

Index: marble/config.ui
===================================================================
--- marble/config.ui	(revision 897996)
+++ marble/config.ui	(working copy)
@@ -1,11 +1,11 @@
 <ui version="4.0" >
- <class>PatternSettingsWidget</class>
- <widget class="QWidget" name="PatternSettingsWidget" >
+ <class>MarbleSettingsWidget</class>
+ <widget class="QWidget" name="MarbleSettingsWidget" >
   <property name="geometry" >
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>357</width>
+    <width>358</width>
     <height>331</height>
    </rect>
   </property>
@@ -115,27 +115,44 @@
      </item>
     </widget>
    </item>
-   <item row="3" column="1" >
-    <widget class="QRadioButton" name="followSun" >
+   <item row="5" column="0" >
+    <widget class="QLabel" name="label_7" >
      <property name="text" >
-      <string>&amp;Follow sun position</string>
+      <string>Rotation:</string>
      </property>
-     <property name="checked" >
-      <bool>true</bool>
+     <property name="alignment" >
+      <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
      </property>
     </widget>
    </item>
-   <item row="4" column="1" >
-    <widget class="QRadioButton" name="rotateAutomatically" >
-     <property name="text" >
-      <string>&amp;Rotate automatically</string>
-     </property>
+   <item row="5" column="1" >
+    <widget class="KComboBox" name="movement" >
+     <item>
+      <property name="text" >
+       <string>Follow the sun</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>Hover above home location</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>Custom rotation</string>
+      </property>
+     </item>
+     <item>
+      <property name="text" >
+       <string>Custom placement</string>
+      </property>
+     </item>
     </widget>
    </item>
-   <item row="5" column="1" >
+   <item row="8" column="1" >
     <layout class="QGridLayout" name="gridLayout" >
      <item row="0" column="0" >
-      <widget class="QLabel" name="label_3" >
+      <widget class="QLabel" name="labelRotationLon" >
        <property name="sizePolicy" >
         <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
          <horstretch>0</horstretch>
@@ -149,7 +166,7 @@
         </size>
        </property>
        <property name="text" >
-        <string>L&amp;ongitude Rotation:</string>
+        <string>Longitude rotation:</string>
        </property>
        <property name="alignment" >
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -161,21 +178,12 @@
      </item>
      <item row="0" column="1" >
       <widget class="QDoubleSpinBox" name="rotationLon" >
-       <property name="sizePolicy" >
-        <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
        <property name="wrapping" >
         <bool>true</bool>
        </property>
        <property name="alignment" >
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
        </property>
-       <property name="specialValueText" >
-        <string>No rotation</string>
-       </property>
        <property name="suffix" >
         <string> </string>
        </property>
@@ -194,7 +202,7 @@
       </widget>
      </item>
      <item row="1" column="0" >
-      <widget class="QLabel" name="label_6" >
+      <widget class="QLabel" name="labelRotationLat" >
        <property name="sizePolicy" >
         <sizepolicy vsizetype="Minimum" hsizetype="Preferred" >
          <horstretch>0</horstretch>
@@ -208,7 +216,7 @@
         </size>
        </property>
        <property name="text" >
-        <string>L&amp;atitude Rotation:</string>
+        <string>Latitude rotation:</string>
        </property>
        <property name="alignment" >
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -220,21 +228,12 @@
      </item>
      <item row="1" column="1" >
       <widget class="QDoubleSpinBox" name="rotationLat" >
-       <property name="sizePolicy" >
-        <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
        <property name="wrapping" >
         <bool>true</bool>
        </property>
        <property name="alignment" >
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
        </property>
-       <property name="specialValueText" >
-        <string>No rotation</string>
-       </property>
        <property name="suffix" >
         <string> </string>
        </property>
@@ -252,8 +251,22 @@
        </property>
       </widget>
      </item>
-     <item row="2" column="0" >
-      <widget class="QLabel" name="label_4" >
+     <item row="2" column="0" colspan="2" >
+      <widget class="KPushButton" name="homeLocation" >
+       <property name="text" >
+        <string>Set current position as home</string>
+       </property>
+      </widget>
+     </item>
+     <item row="3" column="0" colspan="2" >
+      <widget class="QCheckBox" name="navigationEnabled" >
+       <property name="text" >
+        <string>Enable navigation widget</string>
+       </property>
+      </widget>
+     </item>
+     <item row="4" column="0" >
+      <widget class="QLabel" name="labelTimeout" >
        <property name="sizePolicy" >
         <sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
          <horstretch>0</horstretch>
@@ -267,7 +280,7 @@
         </size>
        </property>
        <property name="text" >
-        <string>Update &amp;Interval:</string>
+        <string>Update every:</string>
        </property>
        <property name="alignment" >
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -277,64 +290,42 @@
        </property>
       </widget>
      </item>
-     <item row="2" column="1" >
+     <item row="4" column="1" >
       <widget class="KIntNumInput" name="timeout" >
-       <property name="sizePolicy" >
-        <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="focusPolicy" >
-        <enum>Qt::WheelFocus</enum>
-       </property>
        <property name="value" >
         <number>10</number>
        </property>
        <property name="minimum" >
-        <number>0</number>
+        <number>1</number>
        </property>
        <property name="maximum" >
-        <number>100000</number>
+        <number>3600</number>
        </property>
        <property name="suffix" >
-        <string>s</string>
+        <string> seconds</string>
        </property>
-       <property name="specialValueText" >
-        <string>No updates</string>
-       </property>
       </widget>
      </item>
     </layout>
    </item>
-   <item row="6" column="1" >
-    <widget class="QCheckBox" name="showCities" >
-     <property name="text" >
-      <string>Show &amp;cities</string>
+   <item row="9" column="1" >
+    <widget class="Line" name="line" >
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
      </property>
     </widget>
    </item>
-   <item row="7" column="1" >
-    <widget class="QCheckBox" name="showNight" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
+   <item row="13" column="1" >
+    <widget class="QCheckBox" name="showPlacemarks" >
+     <property name="toolTip" >
+      <string>Determines whether all kind of placemarks are shown or not.</string>
      </property>
      <property name="text" >
-      <string>Shade the night half of the earth</string>
+      <string>Show &amp;placemarks</string>
      </property>
     </widget>
    </item>
-   <item row="8" column="1" >
-    <widget class="QCheckBox" name="showClouds" >
-     <property name="text" >
-      <string>Show c&amp;louds</string>
-     </property>
-    </widget>
-   </item>
-   <item row="9" column="0" colspan="2" >
+   <item row="14" column="1" >
     <spacer name="verticalSpacer" >
      <property name="orientation" >
       <enum>Qt::Vertical</enum>
@@ -360,18 +351,19 @@
    <extends>QWidget</extends>
    <header>knuminput.h</header>
   </customwidget>
+  <customwidget>
+   <class>KPushButton</class>
+   <extends>QPushButton</extends>
+   <header>kpushbutton.h</header>
+  </customwidget>
  </customwidgets>
  <tabstops>
   <tabstop>themeList</tabstop>
   <tabstop>projection</tabstop>
   <tabstop>quality</tabstop>
-  <tabstop>followSun</tabstop>
-  <tabstop>rotateAutomatically</tabstop>
   <tabstop>rotationLon</tabstop>
   <tabstop>rotationLat</tabstop>
   <tabstop>timeout</tabstop>
-  <tabstop>showCities</tabstop>
-  <tabstop>showClouds</tabstop>
  </tabstops>
  <resources/>
  <connections/>
Index: marble/marble.cpp
===================================================================
--- marble/marble.cpp	(revision 897996)
+++ marble/marble.cpp	(working copy)
@@ -1,5 +1,6 @@
 /*
-Copyright 2008 Frederik Gladhorn <gladhorn@kde.org>
+Copyright (C) 2008 by Frederik Gladhorn <gladhorn@kde.org>
+Copyright (C) 2008 by Sascha Peilicke <sasch.pe@gmx.de>
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as
@@ -20,41 +21,38 @@
 
 #include "marble.h"
 
+#include <marble/GeoPainter.h>
+#include <marble/MapThemeManager.h>
+#include <marble/MarbleAbstractFloatItem.h>
+#include <marble/MarbleMap.h>
+#include <marble/MarbleRenderPlugin.h>
+#include <marble/SunLocator.h>
+#include <marble/ViewParams.h>
+
 #include <KDebug>
 
-#include <GeoPainter.h>
-#include <ViewParams.h>
-#include <ViewportParams.h>
-#include <MarbleModel.h>
-#include <MarbleRenderPlugin.h>
-#include <SunLocator.h>
-#include <MapThemeManager.h>
-
-#include <QGraphicsSceneWheelEvent>
+#include <QGraphicsSceneMouseEvent>
 #include <QStandardItemModel>
 
-#include <KDebug>
-
-#define DRAGTHRESHOLD 3
-
+#define HOME_LON_CONFIG_KEY "homeLon"
+#define HOME_LAT_CONFIG_KEY "homeLat"
 #define MAP_THEME_CONFIG_KEY "mapTheme"
-#define DISTANCE_CONFIG_KEY "distance"
+#define NAVIGATION_CONFIG_KEY "navigationEnabled"
+#define MOVEMENT_CONFIG_KEY "movement"
+#define POSITION_DIST_CONFIG_KEY "positionDistance"
+#define POSITION_LON_CONFIG_KEY "positionLongitude"
+#define POSITION_LAT_CONFIG_KEY "positionLatitude"
 #define PROJECTION_CONFIG_KEY "projection"
-#define TIMEOUT_CONFIG_KEY "timeout"
-#define FOLLOW_SUN_CONFIG_KEY "followSun"
-#define ROTATION_LON_CONFIG_KEY "rotateLon"
-#define ROTATION_LAT_CONFIG_KEY "rotateLat"
-#define POSITION_LON_CONFIG_KEY "positionLon"
-#define POSITION_LAT_CONFIG_KEY "positionLat"
-#define SHOW_CITIES_CONFIG_KEY "showCities"
-#define SHOW_CLOUDS_CONFIG_KEY "showClouds"
-#define SHOW_NIGHT_CONFIG_KEY "showNight"
 #define QUALITY_CONFIG_KEY "quality"
+#define ROTATION_LON_CONFIG_KEY "rotateLongitude"
+#define ROTATION_LAT_CONFIG_KEY "rotateLatitude"
+#define ROTATION_TIMEOUT_CONFIG_KEY "rotationTimeout"
+#define SHOW_PLACEMARKS_CONFIG_KEY "showPlacemarks"
 
 namespace Marble {
 
-MarbleWallpaper::MarbleWallpaper(QObject * parent, const QVariantList & args )
-    : Plasma::Wallpaper(parent, args), m_timer(0), m_map(0), m_leftPressed(false), \
m_dirty(true) +MarbleWallpaper::MarbleWallpaper(QObject *parent, const QVariantList \
&args) +    : Plasma::Wallpaper(parent, args), m_navItem(0), m_map(0), \
m_rotationTimer(0), m_dirty(true)  {
     KGlobal::locale()->insertCatalog("Marble");
 }
@@ -64,74 +62,68 @@
     delete m_map;
 }
 
-void MarbleWallpaper::init(const KConfigGroup & config)
+void MarbleWallpaper::init(const KConfigGroup &config)
 {
+    m_movement = static_cast<Movement>(config.readEntry(MOVEMENT_CONFIG_KEY, \
static_cast<int>(FollowSun))); +    m_mapTheme = \
config.readEntry(MAP_THEME_CONFIG_KEY, \
QString::fromLatin1("earth/bluemarble/bluemarble.dgml")); +    m_navigationEnabled = \
config.readEntry(NAVIGATION_CONFIG_KEY, false); +    m_positionDist = \
config.readEntry(POSITION_DIST_CONFIG_KEY, 2000.0); +    m_positionLon = \
config.readEntry(POSITION_LON_CONFIG_KEY, 0.0); +    m_positionLat = \
config.readEntry(POSITION_LAT_CONFIG_KEY, 0.0); +    m_projection = \
static_cast<Projection>(config.readEntry(PROJECTION_CONFIG_KEY, \
static_cast<int>(Spherical))); +    m_quality = \
static_cast<MapQuality>(config.readEntry(QUALITY_CONFIG_KEY, \
static_cast<int>(Normal))); +    m_rotationLat = \
config.readEntry(ROTATION_LAT_CONFIG_KEY, 0.0); +    m_rotationLon = \
config.readEntry(ROTATION_LON_CONFIG_KEY, 0.10); +    m_rotationTimeout = \
config.readEntry(ROTATION_TIMEOUT_CONFIG_KEY, 10000); +    m_showPlacemarks = \
config.readEntry(SHOW_PLACEMARKS_CONFIG_KEY, true); +
     m_map = new MarbleMap();
-    m_mapTheme=config.readEntry(MAP_THEME_CONFIG_KEY, \
                QString::fromLatin1("earth/bluemarble/bluemarble.dgml"));
-    m_map->setMapThemeId(m_mapTheme);
 
-    m_projection = static_cast<Projection>(config.readEntry(PROJECTION_CONFIG_KEY,
-                                                    static_cast<int>(Spherical)));
-    m_map->setProjection( m_projection );
-    m_showCities = config.readEntry(SHOW_CITIES_CONFIG_KEY, false);
-    m_showClouds = config.readEntry(SHOW_CLOUDS_CONFIG_KEY, false);
-    m_showNight = config.readEntry(SHOW_NIGHT_CONFIG_KEY, false);
+    // Set either saved home or default home value
+    qreal lon, lat; int zoom;
+    m_map->home(lon, lat, zoom);
+    m_map->setHome(config.readEntry(HOME_LON_CONFIG_KEY, lon),
+                   config.readEntry(HOME_LAT_CONFIG_KEY, lat));
 
-    m_followSun = config.readEntry(FOLLOW_SUN_CONFIG_KEY, true);
-    if (m_followSun) {
-        m_map->centerOn(m_map->sunLocator()->getLon(), \
                m_map->sunLocator()->getLat());
-    } else {
-        //Set how we want the map to look
-        m_map->centerOn(config.readEntry(POSITION_LON_CONFIG_KEY, 0.0),  \
                config.readEntry(POSITION_LAT_CONFIG_KEY, 0.0));
-    }
-
-    m_map->setShowCompass    ( false );
-    m_map->setShowScaleBar   ( false );
-    m_map->setShowGrid       ( false );
-    m_map->sunLocator()->setShow(true);
+    m_map->setMapThemeId(m_mapTheme);
+    m_map->setProjection(m_projection);
+    m_map->setShowCompass(false);
+    m_map->setShowGrid(false);
+    m_map->setShowScaleBar(false);
     m_map->sunLocator()->setCitylights(true);
+    m_map->sunLocator()->setShow(true);
 
-    m_map->setDistance(config.readEntry(DISTANCE_CONFIG_KEY, 5000.0));
-    m_rotationLon = config.readEntry(ROTATION_LON_CONFIG_KEY, 0.10);
-    m_rotationLat = config.readEntry(ROTATION_LAT_CONFIG_KEY, 0.0);
-    m_timeout = config.readEntry(TIMEOUT_CONFIG_KEY, 10000);
-    m_quality = static_cast<MapQuality>(config.readEntry(QUALITY_CONFIG_KEY,
-                                                   static_cast<int>(Normal)));
-
-    foreach( MarbleRenderPlugin* item, m_map->model()->renderPlugins() ) {
-        /* //FIXME:stars plugin crashes
-        if(item->nameId() == "stars") {
-            item->setVisible( true );
-        } else {
-            item->setVisible( false );
-        } */
-        item->setVisible( false );
+    foreach (MarbleAbstractFloatItem *item, m_map->floatItems()) {
+        if (m_navigationEnabled && item->nameId() == "navigation") {
+            m_navItem = item;
+            // Note: Try to make the marble navigation float item look nice and
+            //       slim to not interfere too much with other Plasma content.
+            m_navItem->setBackground(Qt::NoBrush);
+            m_navItem->setBorderStyle(Qt::NoPen);
+        }
     }
 
+    updateRenderPlugins();
     widgetChanged();
 }
 
-QWidget * MarbleWallpaper::createConfigurationInterface(QWidget * parent)
+QWidget *MarbleWallpaper::createConfigurationInterface(QWidget *parent)
 {
-    QWidget * configWidget = new QWidget(parent);
+    QWidget *configWidget = new QWidget(parent);
     m_ui.setupUi(configWidget);
-    m_ui.timeout->setValue(m_timeout/1000);
-    m_ui.rotationLon->setValue(m_rotationLon);
-    m_ui.rotationLat->setValue(m_rotationLat);
-    m_ui.showCities->setChecked(m_showCities);
-    m_ui.showClouds->setChecked(m_showClouds);
-    m_ui.showNight-> setChecked(m_showNight);
-    m_ui.rotateAutomatically-> setChecked(!m_followSun);
-    m_ui.rotationLon->setEnabled(!m_followSun);
-    m_ui.rotationLat->setEnabled(!m_followSun);
+    m_ui.movement->setCurrentIndex(static_cast<int>(m_movement));
+    m_ui.navigationEnabled->setChecked(m_navigationEnabled);
     m_ui.projection->setCurrentIndex(static_cast<int>(m_projection));
-    //the first MapQuality value is wireframe, which we don't show in the list
+    // The first MapQuality value is wireframe, which we don't show in the list
     m_ui.quality->setCurrentIndex(static_cast<int>(m_quality) - 1);
+    m_ui.rotationLon->setValue(m_rotationLon);
+    m_ui.rotationLat->setValue(m_rotationLat);
+    m_ui.showPlacemarks->setChecked(m_showPlacemarks);
+    m_ui.timeout->setValue(m_rotationTimeout / 1000);
 
     MapThemeManager themeManager;
     themeManager.updateMapThemeModel();
-    int rows = themeManager.mapThemeModel()->rowCount();
-    for (int i = 0; i< rows; i++) {
+    for (int i = 0; i < themeManager.mapThemeModel()->rowCount(); i++) {
         QModelIndex index = themeManager.mapThemeModel()->index(i, 0, \
                QModelIndex());
         QString theme = themeManager.mapThemeModel()->data(index, \
                Qt::DisplayRole).toString();
         QIcon icon = qvariant_cast<QIcon>(themeManager.mapThemeModel()->data(index, \
Qt::DecorationRole)); @@ -142,234 +134,227 @@
             m_ui.themeList->setCurrentIndex(i);
         }
     }
-    connect(m_ui.themeList, SIGNAL(currentIndexChanged(int)), \
SLOT(changeTheme(int)));  
+    // Trigger setting initial movement configuration
+    updateMovement(static_cast<int>(m_movement));
+
+    connect(m_ui.homeLocation, SIGNAL(clicked(int)), SLOT(updateHomeLocation()));
+    connect(m_ui.navigationEnabled, SIGNAL(stateChanged(int)), \
SLOT(updateSettings())); +    connect(m_ui.movement, \
                SIGNAL(currentIndexChanged(int)), SLOT(updateMovement(int)));
     connect(m_ui.projection, SIGNAL(currentIndexChanged(int)), \
                SLOT(updateSettings()));
     connect(m_ui.quality, SIGNAL(currentIndexChanged(int)), SLOT(updateSettings()));
-    connect(m_ui.timeout, SIGNAL(valueChanged(int)), SLOT(updateSettings()));
     connect(m_ui.rotationLon, SIGNAL(valueChanged(double)), SLOT(updateSettings()));
     connect(m_ui.rotationLat, SIGNAL(valueChanged(double)), SLOT(updateSettings()));
-    connect(m_ui.showCities, SIGNAL(stateChanged(int)), SLOT(updateSettings()));
-    connect(m_ui.showClouds, SIGNAL(stateChanged(int)), SLOT(updateSettings()));
-    connect(m_ui.showNight, SIGNAL(stateChanged(int)), SLOT(updateSettings()));
-    connect(m_ui.followSun, SIGNAL(toggled(bool)), SLOT(updateSettings()));
+    connect(m_ui.showPlacemarks, SIGNAL(stateChanged(int)), SLOT(updateSettings()));
+    connect(m_ui.themeList, SIGNAL(currentIndexChanged(int)), \
SLOT(changeTheme(int))); +    connect(m_ui.timeout, SIGNAL(valueChanged(int)), \
SLOT(updateSettings()));  
     return configWidget;
 }
 
-void MarbleWallpaper::save(KConfigGroup & config)
+void MarbleWallpaper::save(KConfigGroup &config)
 {
     if (!m_map) {
-        // when switching the background containment, this is called with m_map==0 \
for some reason +        // When switching the background containment, this is called \
with m_map==0 for some reason  return;
     }
+
+    qreal lon, lat; int zoom;
+    m_map->home(lon, lat, zoom);
+    config.writeEntry(HOME_LAT_CONFIG_KEY, lat);
+    config.writeEntry(HOME_LON_CONFIG_KEY, lon);
+    config.writeEntry(NAVIGATION_CONFIG_KEY, m_navigationEnabled);
     config.writeEntry(MAP_THEME_CONFIG_KEY, m_map->mapThemeId());
+    config.writeEntry(MOVEMENT_CONFIG_KEY, static_cast<int>(m_movement));
+    config.writeEntry(POSITION_DIST_CONFIG_KEY, m_positionDist);
+    config.writeEntry(POSITION_LAT_CONFIG_KEY, m_map->centerLatitude());
+    config.writeEntry(POSITION_LON_CONFIG_KEY, m_map->centerLongitude());
     config.writeEntry(PROJECTION_CONFIG_KEY, static_cast<int>(m_projection));
     config.writeEntry(QUALITY_CONFIG_KEY, static_cast<int>(m_quality));
-    config.writeEntry(TIMEOUT_CONFIG_KEY, m_timeout);
-    config.writeEntry(FOLLOW_SUN_CONFIG_KEY, m_followSun);
-    config.writeEntry(POSITION_LON_CONFIG_KEY, m_map->centerLongitude());
-    config.writeEntry(POSITION_LAT_CONFIG_KEY, m_map->centerLatitude());
-    config.writeEntry(DISTANCE_CONFIG_KEY, m_map->distance());
-    config.writeEntry(ROTATION_LON_CONFIG_KEY, m_rotationLon);
     config.writeEntry(ROTATION_LAT_CONFIG_KEY, m_rotationLat);
-    config.writeEntry(SHOW_CITIES_CONFIG_KEY, m_showCities);
-    config.writeEntry(SHOW_CLOUDS_CONFIG_KEY, m_showClouds);
-    config.writeEntry(SHOW_NIGHT_CONFIG_KEY, m_showNight);
+    config.writeEntry(ROTATION_LON_CONFIG_KEY, m_rotationLon);
+    config.writeEntry(ROTATION_TIMEOUT_CONFIG_KEY, m_rotationTimeout);
+    config.writeEntry(SHOW_PLACEMARKS_CONFIG_KEY, m_showPlacemarks);
 }
 
-void MarbleWallpaper::paint(QPainter * painter, const QRectF & exposedRect)
+void MarbleWallpaper::paint(QPainter *painter, const QRectF &exposedRect)
 {
-    // check if geometry changed
+    // Check if geometry changed
     if (m_pixmap.size() != boundingRect().size().toSize()) {
         m_dirty = true;
     }
-    // update the pixmap
-    if(m_dirty) {
+    // Update the pixmap
+    if (m_dirty) {
         renderPixmap();
     }
-    // draw the requested part of the pixmap
-    painter->drawPixmap( exposedRect, m_pixmap, exposedRect );
+    // Draw the requested part of the pixmap
+    painter->drawPixmap(exposedRect, m_pixmap, exposedRect);
 }
 
-void MarbleWallpaper::renderPixmap()
+void MarbleWallpaper::mousePressEvent(QGraphicsSceneMouseEvent *event)
 {
-    if (m_pixmap.size() != boundingRect().size().toSize()) {
-        m_pixmap = QPixmap(boundingRect().size().toSize());
-        renderPixmap();
+    if (event->buttons() == Qt::LeftButton && m_navigationEnabled && m_movement == \
FreeMovement) { +        //TODO: Implement mouse interaction with navigation float \
item +        //TODO: Make sure the user scrolls not to far!
+        event->accept();
     }
-    if (m_pixmap.size().isEmpty()) {
-        return;
+}
+
+void MarbleWallpaper::widgetChanged()
+{
+    m_map->setProjection(m_projection);
+    m_map->setShowCities(m_showPlacemarks);
+    m_map->setShowOtherPlaces(m_showPlacemarks);
+    m_map->setShowPlaces(m_showPlacemarks);
+
+    if (m_rotationTimer) {
+        m_rotationTimer->stop();
+        disconnect(m_rotationTimer);
     }
-    m_map->setSize(m_pixmap.size());
-    m_pixmap.fill(QColor( 0x00, 0x00, 0x00, 0xFF ));
-    GeoPainter gp( &m_pixmap, m_map->viewParams()->viewport(),
-                   m_quality, true );
-    QRect mapRect( 0, 0, m_map->width(), m_map->height() );
-    m_map->paint(gp, mapRect );
-    m_dirty = false;
+    if (m_rotationTimeout && (m_rotationLon || m_rotationLat) &&
+                             (m_movement == FollowSun || m_movement == \
CustomRotate)) { +        if (!m_rotationTimer) {
+            m_rotationTimer = new QTimer(this);
+            m_rotationTimer->setInterval(m_rotationTimeout);
+            connect(m_rotationTimer, SIGNAL(timeout()), SLOT(rotate()));
+        }
+        m_rotationTimer->start();
+    }
+
+    updateRenderPlugins();
+    m_dirty = true;
+    emit update(boundingRect());
 }
 
 void MarbleWallpaper::rotate()
 {
-    m_map->sunLocator()->update();
-    if (m_followSun) {
+    kDebug() << "ROTATE NOW";
+    if (m_movement == FollowSun) {
+        m_map->sunLocator()->update();
         if (m_map->sunLocator()->getLon() == m_map->centerLongitude()) {
             return;
         }
         m_map->centerOn(m_map->sunLocator()->getLon(), \
                m_map->sunLocator()->getLat());
-    } else {
+        kDebug() << "ROTATED around SUN";
+    } else if (m_movement == CustomRotate) {
         m_map->rotateBy(m_rotationLon, m_rotationLat);
+        kDebug() << "ROTATED around SUN";
+    } else {
+        return;
     }
     m_dirty = true;
     emit update(boundingRect());
 }
 
-void MarbleWallpaper::changeTheme(int index)
-{
-    m_mapTheme = m_ui.themeList->itemData(index).toString();
-    m_map->setMapThemeId(m_mapTheme);
-
-    foreach( MarbleRenderPlugin* item, m_map->model()->renderPlugins() ) {
-        //FIXME: only have one place to switch off themes
-        item->setVisible( false );
-    }
-
-    m_dirty = true;
-    emit update(boundingRect());
-}
-
 void MarbleWallpaper::updateSettings()
 {
+    m_navigationEnabled = m_ui.navigationEnabled->isChecked();
     m_projection = static_cast<Projection>(m_ui.projection->currentIndex());
-    //the first MapQuality value is wireframe, which we don't show in the list
-    m_quality = static_cast<MapQuality>(m_ui.quality->currentIndex() + 1);
-    m_timeout = m_ui.timeout->value()*1000;
     m_rotationLon = m_ui.rotationLon->value();
     m_rotationLat = m_ui.rotationLat->value();
-    m_showCities = m_ui.showCities->isChecked();
-    m_showClouds = m_ui.showClouds->isChecked();
-    m_showNight  = m_ui.showNight-> isChecked();
-    m_followSun = m_ui.followSun->isChecked();
-    m_ui.rotationLon->setEnabled(!m_followSun);
-    m_ui.rotationLat->setEnabled(!m_followSun);
+    // The first MapQuality value is wireframe, which we don't show in the list
+    m_quality = static_cast<MapQuality>(m_ui.quality->currentIndex() + 1);
+    m_showPlacemarks = m_ui.showPlacemarks->isChecked();
+    m_rotationTimeout = m_ui.timeout->value() * 1000;
 
     widgetChanged();
 }
 
-void MarbleWallpaper::widgetChanged()
+void MarbleWallpaper::changeTheme(int index)
 {
-    m_map->setShowPlaces     ( m_showCities );
-    m_map->setShowCities     ( m_showCities );
-    m_map->setShowOtherPlaces( m_showCities );
-    m_map->setShowClouds     ( m_showClouds );
-    m_map->setProjection( m_projection );
-    
-    if(m_showNight) {
-        m_map->sunLocator()->setShow(true);
-        m_map->sunLocator()->setCitylights(true);
-    } else {
-        m_map->sunLocator()->setShow(false);
-        m_map->sunLocator()->setCitylights(false);
-    }
-
-    if (m_timer) {
-        m_timer->stop();
-        disconnect(m_timer);
-    }
-
-    if (m_timeout && (m_rotationLon || m_rotationLat || m_followSun || m_showNight)) \
                {
-        if (!m_timer) {
-            m_timer = new QTimer(this);
-        }
-        m_timer->setInterval(m_timeout);
-        connect(m_timer, SIGNAL(timeout()), SLOT(rotate()));
-        m_timer->start();
-    }
+    m_mapTheme = m_ui.themeList->itemData(index).toString();
+    m_map->setMapThemeId(m_mapTheme);
+    updateRenderPlugins();
     m_dirty = true;
     emit update(boundingRect());
 }
 
-void MarbleWallpaper::wheelEvent(QGraphicsSceneWheelEvent *event)
+void MarbleWallpaper::updateRenderPlugins()
 {
-    // dispatch the event
-    event->accept();
-    m_map->zoomViewBy( (int)(event->delta() / 3) );
-    m_dirty = true;
-    emit update(boundingRect());
+    foreach (MarbleRenderPlugin *item, m_map->renderPlugins()) {
+        if (item->nameId() == "stars") {
+            item->setVisible(true); item->setEnabled(true);
+        } else if (m_navigationEnabled && m_movement == FreeMovement && \
item->nameId() == "navigation") { +            item->setVisible(true); \
item->setEnabled(true); +        } else {
+            item->setVisible(false); item->setEnabled(false);
+        }
+    }
 }
 
-void MarbleWallpaper::mouseMoveEvent (QGraphicsSceneMouseEvent *event)
+void MarbleWallpaper::updateMovement(int index)
 {
-    if ( m_leftPressed == true ) {
-        event->accept();
-        int polarity = m_map->viewParams()->viewport()->polarity();
+    // Set wallpaper viewpoint on the globe based on movement scheme
+    switch (index) {
+        case 0: // Movement::FollowSun
+            m_ui.homeLocation->setVisible(false);
+            m_ui.navigationEnabled->setVisible(false);
+            m_ui.rotationLat->setVisible(false); \
m_ui.labelRotationLat->setVisible(false); +            \
m_ui.rotationLon->setVisible(false); m_ui.labelRotationLon->setVisible(false); +      \
m_ui.timeout->setVisible(true); m_ui.labelTimeout->setVisible(true);  
-        qreal  radius = (qreal)(m_map->radius());
-        int     deltax = event->screenPos().x() - m_leftPressedX;
-        int     deltay = event->screenPos().y() - m_leftPressedY;
+            m_movement = FollowSun;
+            m_map->centerOn(m_map->sunLocator()->getLon(), \
m_map->sunLocator()->getLat()); +            m_map->setDistance(m_positionDist);
+            break;
+        case 1: // Movement::HoverAboveHome:
+            m_ui.navigationEnabled->setVisible(false);
+            m_ui.rotationLat->setVisible(false); \
m_ui.labelRotationLat->setVisible(false); +            \
m_ui.rotationLon->setVisible(false); m_ui.labelRotationLon->setVisible(false); +      \
m_ui.timeout->setVisible(false); m_ui.labelTimeout->setVisible(false); +            \
m_ui.homeLocation->setVisible(true);  
-        // only start dragging after a certain distance
-        if ( abs(deltax) <= DRAGTHRESHOLD
-                && abs(deltay) <= DRAGTHRESHOLD ) {
-            return;
-        }
+            m_movement = HoverAboveHome;
+            m_map->goHome();
+            m_map->setDistance(m_positionDist);
+            break;
+        case 2: // Movement::CustomRotate
+            m_ui.homeLocation->setVisible(false);
+            m_ui.navigationEnabled->setVisible(false);
+            m_ui.rotationLat->setVisible(true); \
m_ui.labelRotationLat->setVisible(true); +            \
m_ui.rotationLon->setVisible(true); m_ui.labelRotationLon->setVisible(true); +        \
m_ui.timeout->setVisible(true); m_ui.labelTimeout->setVisible(true);  
-        qreal direction = 1;
-        // Choose spin direction by taking into account whether we
-        // drag above or below the visible pole.
-        if ( m_projection == Spherical ) {
-            if ( polarity > 0 ) {
+            m_movement = CustomRotate;
+            m_map->centerOn(m_positionLon, m_positionLat);
+            m_map->setDistance(m_positionDist);
+            break;
+        case 3: // Movement::FreeMovement
+            m_ui.rotationLat->setVisible(false); \
m_ui.labelRotationLat->setVisible(false); +            \
m_ui.rotationLon->setVisible(false); m_ui.labelRotationLon->setVisible(false); +      \
m_ui.homeLocation->setVisible(false); +            m_ui.timeout->setVisible(false); \
m_ui.labelTimeout->setVisible(false); +            \
m_ui.navigationEnabled->setVisible(true);  
-                if ( event->screenPos().y() < ( - m_map->northPoleY()
-                                + m_map->height() / 2 ) )
-                    direction = -1;
-            }
-            else {
-                if (event->screenPos().y() > ( + m_map->northPoleY()
-                                    + m_map->height() / 2 ) )
-                    direction = -1;
-            }
-        }
-        m_map->centerOn( RAD2DEG * (qreal)(m_leftPressedTranslationX)
-                            - 90.0 * direction * deltax / radius,
-                            RAD2DEG * (qreal)(m_leftPressedTranslationY)
-                            + 90.0 * deltay / radius );
-
-        m_dirty = true;
-        emit update(boundingRect());
+            m_movement = FreeMovement;
+            break;
     }
 }
 
-void MarbleWallpaper::mousePressEvent (QGraphicsSceneMouseEvent *event)
+void MarbleWallpaper::updateHomeLocation()
 {
-    if (event->buttons() == Qt::LeftButton)
-    {
-        m_leftPressed = true;
-
-        // On the single event of a mouse button press these
-        // values get stored, to enable us to e.g. calculate the
-        // distance of a mouse drag while the mouse button is
-        // still down.
-        m_leftPressedX = event->screenPos().x();
-        m_leftPressedY = event->screenPos().y();
-
-        // Calculate translation of center point
-        m_leftPressedTranslationX =  m_map->centerLongitude() * DEG2RAD;
-        m_leftPressedTranslationY =  m_map->centerLatitude() * DEG2RAD;
-
-        event->accept();
-    }
+    m_map->setHome(m_map->centerLongitude(), m_map->centerLatitude());
 }
 
-void MarbleWallpaper::mouseReleaseEvent (QGraphicsSceneMouseEvent *event)
+void MarbleWallpaper::renderPixmap()
 {
-    m_leftPressed = false;
-    event->accept();
+    if (m_pixmap.size() != boundingRect().size().toSize()) {
+        m_pixmap = QPixmap(boundingRect().size().toSize());
+        renderPixmap();
+    }
+    if (m_pixmap.size().isEmpty()) {
+        return;
+    }
+    m_map->setSize(m_pixmap.size());
+    m_pixmap.fill(QColor(0x00, 0x00, 0x00, 0xFF));
+    GeoPainter gp(&m_pixmap, m_map->viewParams()->viewport(), m_quality, true);
+    QRect mapRect(0, 0, m_map->width(), m_map->height());
+    m_map->paint(gp, mapRect);
+    m_dirty = false;
 }
 
-} // Marble
+} // Marble namespace
 
-#include "marble.moc"
+#include "moc_marble.cpp"
 
 // vim: sw=4 sts=4 et tw=100
Index: marble/marble.h
===================================================================
--- marble/marble.h	(revision 897996)
+++ marble/marble.h	(working copy)
@@ -1,5 +1,6 @@
 /*
-Copyright 2008 Frederik Gladhorn <gladhorn@kde.org>
+Copyright (C) 2008 by Frederik Gladhorn <gladhorn@kde.org>
+Copyright (C) 2008 by Sascha Peilicke <sasch.pe@gmx.de>
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as
@@ -18,94 +19,92 @@
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#ifndef MARBLE_H
-#define MARBLE_H
+#ifndef MARBLE_WALLPAPER_H
+#define MARBLE_WALLPAPER_H
 
-#include <marble/MarbleMap.h>
+#include "ui_config.h"
+
 #include <marble/global.h>
 
 #include <Plasma/Wallpaper>
-#include <QColor>
 
-#include "ui_config.h"
-
 namespace Marble {
 
+class MarbleAbstractFloatItem;
+class MarbleMap;
+
+/**
+ *
+ */
 class MarbleWallpaper : public Plasma::Wallpaper
 {
-Q_OBJECT
+    Q_OBJECT
 public:
-    MarbleWallpaper(QObject * parent, const QVariantList & args);
+    enum Movement {
+        FollowSun = 0,          //< Rotate by following the sun
+        HoverAboveHome,         //< Hover above home location
+        CustomRotate,           //< Rotate by configured values
+        FreeMovement,           //< Allow user navigation
+    };
+
+    MarbleWallpaper(QObject *parent, const QVariantList &args);
     ~MarbleWallpaper();
-    void setBoundingRect(const QRectF &boundingRect);
 
-    QWidget * createConfigurationInterface(QWidget * parent);
-    void save(KConfigGroup & config);
-    void paint(QPainter * painter, const QRectF & exposedRect);
-    virtual void wheelEvent (QGraphicsSceneWheelEvent *event);
-    virtual void mouseMoveEvent (QGraphicsSceneMouseEvent *event);
-    virtual void mousePressEvent (QGraphicsSceneMouseEvent *event);
-    virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent *event);
+    QWidget *createConfigurationInterface(QWidget *parent);
+    void save(KConfigGroup &config);
+    void paint(QPainter *painter, const QRectF &exposedRect);
 
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+
 protected:
-    void init(const KConfigGroup & config);
+    void init(const KConfigGroup &config);
 
 private slots:
-    /// redraw
+    /// Redraw
     void widgetChanged();
-    /// called by the timer for rotation
+    /// Called by the timer for rotation
     void rotate();
-    /// changes from the settings dialog
+    /// Changes from the settings dialog
     void updateSettings();
-    /// change the map theme
-    void changeTheme(int index);
+    /// Change the map theme
+    void changeTheme(int);
+    /// Updates marble render plugins
+    void updateRenderPlugins();
+    /// Updates configuration screen based on current 'movement'
+    void updateMovement(int);
+    /// Updates the 'home' location
+    void updateHomeLocation();
 
 private:
     void renderPixmap();
 
-    Ui_PatternSettingsWidget m_ui;
+    Ui_MarbleSettingsWidget m_ui;
+    MarbleAbstractFloatItem *m_navItem;
 
-    // type of projection
-    Projection m_projection;
+    MarbleMap *m_map;                   // Marble parameters for GeoPainter
+    Projection m_projection;            // Type of projection
+    MapQuality m_quality;               // Painting quality
+    Movement m_movement;                // Current movement/rotation scheme
 
-    // painting quality
-    MapQuality m_quality;
+    qreal m_positionDist;               // Last saved distance
+    qreal m_positionLon;                // Last saved position lon
+    qreal m_positionLat;                // Last saved position lat
 
-    QTimer *m_timer;
-    int m_timeout;
+    qreal m_rotationLon;                // Used for follow sun and custom rotate
+    qreal m_rotationLat;                // Used for follow sun and custom rotate
+    int m_rotationTimeout;              // Timer timeout interval for rot
+    QTimer *m_rotationTimer;            // Rotation timer
 
-    // if true, always update with the sun's position
-    bool m_followSun;
-    qreal m_rotationLon;
-    qreal m_rotationLat;
-    bool m_showCities;
-    bool m_showClouds;
-    bool m_showNight;
+    bool m_navigationEnabled;           // Visibility flag for navig. widget
+    bool m_showPlacemarks;              // Visibility flag for all placemarks
 
-    // size of the background
-    QSize m_size;
-    // marble parameters for GeoPainter
-    MarbleMap *m_map;
-
-    // cached wallpaper
-    QPixmap m_pixmap;
-    // theme of the map
-    QString m_mapTheme;
-
-    // flag - left mouse button is pressed
-    bool     m_leftPressed;
-    // position of last button press
-    int      m_leftPressedX;
-    int      m_leftPressedY;
-    qreal   m_leftPressedTranslationX;
-    qreal   m_leftPressedTranslationY;
-
-    // flag to keep track of dirty state to update m_pixmap
-    bool m_dirty;
+    QPixmap m_pixmap;                   // Cached wallpaper
+    QString m_mapTheme;                 // Theme of the map
+    bool m_dirty;                       // Dirty state flag to update m_pixmap
 };
 
 K_EXPORT_PLASMA_WALLPAPER(marble, MarbleWallpaper)
 
-}
+} // Marble namespace
 
 #endif
Index: marble/plasma-wallpaper-marble.desktop
===================================================================
--- marble/plasma-wallpaper-marble.desktop	(revision 897996)
+++ marble/plasma-wallpaper-marble.desktop	(working copy)
@@ -1,16 +1,8 @@
 [Desktop Entry]
-Name=The Earth
-Name[de]=Die Erde
-Name[el]=Η Γη
-Name[gl]=A Terra
-Name[km]=ផែនដី
-Name[nds]=De Eer
-Name[pa]=ਧਰਤੀ
-Name[pt]=A Terra
-Name[pt_BR]=A Terra
-Name[sv]=Jorden
-Name[uk]=Земля
-Name[x-test]=xxThe Earthxx
+Name=Globe
+Name[de]=Globus
+Name[fr]=Globe
+Name[x-test]=xxGlobexx
 Type=Service
 Icon=marble
 ServiceTypes=Plasma/Wallpaper
Index: marble/CMakeLists.txt
===================================================================
--- marble/CMakeLists.txt	(revision 897996)
+++ marble/CMakeLists.txt	(working copy)
@@ -1,15 +1,12 @@
 project(plasma-wallpaper-marble)
 
-include_directories(
-    ${MARBLE_INCLUDE_DIR}
-    )
+include_directories(${MARBLE_INCLUDE_DIR})
 
 set(marble_SRCS
     marble.cpp
 )
 
 kde4_add_ui_files(marble_SRCS config.ui)
-
 kde4_add_plugin(plasma_wallpaper_marble ${marble_SRCS})
 
 target_link_libraries(plasma_wallpaper_marble
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 897996)
+++ CMakeLists.txt	(working copy)
@@ -1,6 +1,17 @@
+project(playground-plasma-wallpapers)
+
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
+
+find_package(KDE4 REQUIRED)
+find_package(Plasma REQUIRED)
 find_package(Marble)
 
+include(KDE4Defaults)
+include(MacroOptionalAddSubdirectory)
 
+add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
+include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES})
+
 add_subdirectory(mandelbrot)
 add_subdirectory(pattern)
 if( NOT WIN32 )


["signature.asc" (application/pgp-signature)]

_______________________________________________
Plasma-devel mailing list
Plasma-devel@kde.org
https://mail.kde.org/mailman/listinfo/plasma-devel


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

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