Abhijit Apte | 1 Feb 09:51
Picon

Re: Refined patch for wishlist 178232: List all objects within a rectangle

Hi,

I've implemented a draft of the implementation of combining the list functionality along-side the detail dialog. So in essence, we'll have only one dialog which will operate in two modes -- Detailed and Summary.
1) When a popup menu is invoked on a sky object and "Details..." option is selected from the popup menu, the detail dialog will open in "Detailed" mode by default. User has the option to switch to the "Summary" view also.
2) When a right-click drag selection happens, the objects from the rectangle are shown in the detail dialog. This time, the detail dialog will open in "Summary" mode.

P.S: Attached few screenshots.
Alexey, Thanks for your inputs! it works out quite well.

There are some minor bugs which I'm yet to fix. I'll send the cleaner patch later.

Rgds
-Abhi

On Sat, Jan 30, 2010 at 9:45 PM, Abhijit Apte <abhijit.apte <at> gmail.com> wrote:

> P.S Attached 2 previews of the solution that could integrate both the list
> view and details view. [If "Show Details" checkbox is checked, then the
> detail dialog contents will be shown, otherwise, the simple list with
> multiple columns will be shown].

Yes. I mean something like that


Ok I'll give it a try.

_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel
Abhijit Apte | 1 Feb 19:45
Picon

Re: Refined patch for wishlist 178232: List all objects within a rectangle

Hi Alexey/Akarsh,

On Mon, Feb 1, 2010 at 2:21 PM, Abhijit Apte <abhijit.apte <at> gmail.com> wrote:
I've implemented a draft of the implementation of combining the list functionality along-side the detail dialog. So in essence, we'll have only one dialog which will operate in two modes -- Detailed and Summary.
1) When a popup menu is invoked on a sky object and "Details..." option is selected from the popup menu, the detail dialog will open in "Detailed" mode by default. User has the option to switch to the "Summary" view also.
2) When a right-click drag selection happens, the objects from the rectangle are shown in the detail dialog. This time, the detail dialog will open in "Summary" mode.
 
Here's the patch, I managed to fix most of the bugs I noticed while testing.
Right now, I've not modified DetailDialog (dialogs/detaildialog.cpp and dialogs/detaildialog.h) and instead merged (copied) all of its code into dialogs/objectlist.cpp and dialogs/objectlist.h
Pl. review and apply the patch and suggest me if you've any comments.

Still to do:
1) Move all the modified code of dialogs/objectlist.* back to dialogs/detaildialog.* and remove dialogs/objectlist.* files
2) Update the CMakeLists.txt to reflect the changes of step 1.

Rgds
-Abhi

Index: colorscheme.cpp
===================================================================
--- colorscheme.cpp	(revision 1062995)
+++ colorscheme.cpp	(working copy)
 <at>  <at>  -72,6 +72,7  <at>  <at> 
     appendItem("AngularRuler",     i18n("Angular Distance Ruler"), "#445566");
     appendItem("ObsListColor",     i18n("Observing List Label"),   "#FF0000");
     appendItem("SatColor",         i18n("Satellite Track"),        "#007777");
+    appendItem("BoxHighlightColor",i18n("Box highlight color"),    "#EFF5FB");
 
     //Load colors from config object
     loadFromConfig();
Index: kstarsinit.cpp
===================================================================
--- kstarsinit.cpp	(revision 1062995)
+++ kstarsinit.cpp	(working copy)
 <at>  <at>  -530,6 +530,12  <at>  <at> 
     eWriter = new EquipmentWriter();
     oAdd = new ObserverAdd;
 
+    // Initialize the sky object list
+#if 0
+    skyObjectList = new SkyObjectList( this );
+#endif
+    skyObjectList = new SkyObjectList( NULL, data()->ut(), data()->geo(), this );
+
     //Do not start the clock if "--paused" specified on the cmd line
     if ( StartClockRunning )
         data()->clock()->start();
Index: dialogs/objectlist.cpp
===================================================================
--- dialogs/objectlist.cpp	(revision 0)
+++ dialogs/objectlist.cpp	(revision 0)
 <at>  <at>  -0,0 +1,1268  <at>  <at> 
+#include <KLocale>
+
+#include <QStandardItemModel>
+#include <QSortFilterProxyModel>
+
+#include <QLineEdit>
+#include <QPixmap>
+#include <QRegExp>
+#include <QTextStream>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QTreeWidgetItem>
+
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <kpushbutton.h>
+#include <klineedit.h>
+#include <ktoolinvocation.h>
+#include <ktemporaryfile.h>
+#include <kio/netaccess.h>
+
+#include "kstars.h"
+#include "kstarsdata.h"
+#include "kstarsdatetime.h"
+#include "geolocation.h"
+#include "ksutils.h"
+#include "skymap.h"
+#include "skyobjects/skyobject.h"
+#include "skyobjects/starobject.h"
+#include "skyobjects/deepskyobject.h"
+#include "skyobjects/ksplanetbase.h"
+#include "skyobjects/ksmoon.h"
+#include "thumbnailpicker.h"
+#include "Options.h"
+#include "skycomponents/constellationboundary.h"
+#include "objectlist.h"
+#include "detaildialog.h"
+
+#include <config-kstars.h>
+
+#ifdef HAVE_INDI_H
+#include "indi/indielement.h"
+#include "indi/indiproperty.h"
+#include "indi/indidevice.h"
+#include "indi/indimenu.h"
+#include "indi/devicemanager.h"
+#include "indi/indistd.h"
+#endif
+
+SkyObjectList::SkyObjectList( 
+                       SkyObject* o, 
+                       const KStarsDateTime& _dt,
+                       GeoLocation* _geo,
+                       KStars* _ks )
+                      : KPageDialog( (QWidget*)_ks ),
+                        selectedObject( o ),
+                        ut(_dt),
+                        geo(_geo),
+		        ks( _ks ),
+                        Data( NULL ),
+                        Pos( NULL ),
+			Links( NULL ),
+			Adv( NULL ),
+			Log( NULL )
+{
+    QWidget* widget = new QWidget( this );
+    ui.setupUi( widget );
+
+    setMainWidget( widget );
+
+    setCaption( i18n( "Sky objects' list" ) );
+    //setButtons( KDialog::Ok | KDialog::Cancel );
+    setButtons( KDialog::Close );
+    
+    pageWidget = new KPageWidget( ui.framePage );
+    pageWidget->setFaceType( KPageView::Tabbed );
+    pageWidget->setBackgroundRole( QPalette::Base );
+    
+    titlePalette = pageWidget->palette();
+    titlePalette.setColor( backgroundRole(), pageWidget->palette().color( QPalette::Active, QPalette::Highlight ) );
+    titlePalette.setColor( foregroundRole(), pageWidget->palette().color( QPalette::Active, QPalette::HighlightedText ) );
+
+    //Create thumbnail image
+    Thumbnail = new QPixmap( 200, 200 );
+
+    m_Model = new QStandardItemModel( 0, 5, this );
+    m_Model->setHorizontalHeaderLabels( QStringList() << i18n( "Name" )
+            << i18nc( "Right Ascension", "RA" ) << i18nc( "Declination", "Dec" )
+	            << i18nc( "Magnitude", "Mag" ) << i18n( "Type" ) );
+    m_SortModel = new QSortFilterProxyModel( this );
+    m_SortModel->setSourceModel( m_Model );
+    m_SortModel->setDynamicSortFilter( true );
+
+    ui.comboBoxObjects->setModel( m_Model );
+
+    ui.tableView->setModel( m_SortModel );
+    ui.tableView->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding ) );
+    ui.tableView->setSelectionMode( QAbstractItemView::SingleSelection );
+    ui.tableView->setEditTriggers( QAbstractItemView::NoEditTriggers );
+    ui.tableView->horizontalHeader()->setStretchLastSection( true );
+    ui.tableView->horizontalHeader()->setResizeMode( QHeaderView::ResizeToContents );
+    
+    if( selectedObject )
+    {
+	addObject( selectedObject );
+	ui.radioButtonDetailed->setChecked( true );
+        createGeneralTab();
+        createPositionTab( ut, geo );
+        createLinksTab();
+        createAdvancedTab();
+        createLogTab();
+	//showDetails( Qt::Checked );
+	showDetails( true );
+	//pageWidget->show();
+    }
+    else
+        ui.radioButtonDetailed->setChecked( false );
+
+    connect( ui.tableView, SIGNAL( doubleClicked( const QModelIndex& ) ),
+             this, SLOT( slotCenterObject() ) );
+    connect( ui.tableView->selectionModel(),
+            SIGNAL( selectionChanged(const QItemSelection&, const QItemSelection&) ),
+            this, SLOT( slotNewSelection() ) );
+    
+    connect( ui.comboBoxObjects, 
+             SIGNAL( currentIndexChanged(int) ), 
+	     this, SLOT( comboBoxIndexChanged( int ) ) );
+    
+    connect( ui.radioButtonDetailed,
+             SIGNAL( clicked(bool) ),
+	     this, SLOT( showDetails( bool ) ) );
+    
+    connect( ui.radioButtonSummary,
+             SIGNAL( clicked(bool) ),
+	     this, SLOT( showSummary( bool ) ) );
+    
+}
+
+void SkyObjectList::addObject( SkyObject* obj )
+{
+    m_ObjectList.append( obj );
+    selectedObject = obj;
+    SkyPoint p = obj->recomputeCoords( ut, geo );
+    QString smag = "--";
+    if (  - 30.0 < obj->mag() && obj->mag() < 90.0 ) smag = QString::number( obj->mag(), 'g', 2 ); // The lower limit to avoid display of unrealistic comet magnitudes
+
+    QList<QStandardItem*> itemList;
+    itemList << new QStandardItem( obj->translatedName() )
+             << new QStandardItem( p.ra()->toHMSString() )
+	     << new QStandardItem( p.dec()->toDMSString() )
+	     << new QStandardItem( smag )
+	     << new QStandardItem( obj->typeName() );
+    
+    m_Model->appendRow( itemList );
+    ui.tableView->resizeColumnsToContents();
+}
+
+void SkyObjectList::addObject( DeepSkyObject*& obj )
+{
+    m_ObjectList.append( obj );
+    selectedObject = obj;
+    SkyPoint p = obj->recomputeCoords( ut, geo );
+    QString smag = "--";
+    if (  - 30.0 < obj->mag() && obj->mag() < 90.0 ) smag = QString::number( obj->mag(), 'g', 2 ); // The lower limit to avoid display of unrealistic comet magnitudes
+
+    QList<QStandardItem*> itemList;
+    itemList << new QStandardItem( obj->translatedName() )
+             << new QStandardItem( p.ra()->toHMSString() )
+	     << new QStandardItem( p.dec()->toDMSString() )
+	     << new QStandardItem( smag )
+	     << new QStandardItem( obj->typeName() );
+    
+    m_Model->appendRow( itemList );
+    ui.tableView->resizeColumnsToContents();
+}
+
+void SkyObjectList::removeAll()
+{
+    kDebug() << "model rowcount = " << m_Model->rowCount() << endl;
+    m_SortModel->removeRows(0,m_SortModel->rowCount());
+    m_Model->removeRows(0,m_Model->rowCount());
+    m_SortModel->setSourceModel( m_Model );
+    ui.tableView->selectionModel()->clear();
+    ui.tableView->clearSelection();
+    ui.tableView->resizeColumnsToContents();
+    m_ObjectList.clear();
+    selectedObject = NULL;
+}
+
+SkyObjectList::~SkyObjectList()
+{
+}
+
+void SkyObjectList::slotNewSelection()
+{
+    QString newName;
+    QModelIndexList selectedItems = m_SortModel->mapSelectionToSource( ui.tableView->selectionModel()->selection() ).indexes();
+    //When one object is selected
+    if ( selectedItems.size() == m_Model->columnCount() ) 
+    {
+        newName = selectedItems[0].data().toString();
+        kDebug() << "selected row is " << selectedItems[0].row() << endl; 
+	kDebug() << "source row is " << m_SortModel->mapToSource( selectedItems[0] ).row() << endl;
+	ui.comboBoxObjects->setCurrentIndex( selectedItems[0].row() );
+        //Find the selected object in the obsList,
+        //then break the loop.  Now obsList.current()
+        //points to the new selected object (until now it was the previous object)
+        SkyObject* o;
+        foreach ( o, objectList() ) 
+        {
+            if ( o->translatedName() == newName ) 
+            {
+                selectedObject = o;
+	        if( ui.radioButtonDetailed->isChecked() )
+	            showDetails( true );
+		//cleanupDetailView();
+                break;
+            }
+        }
+    }
+}
+
+void SkyObjectList::cleanupDetailView()
+{
+    kDebug() << Q_FUNC_INFO << endl;
+    while( pageWidget->currentPage() )
+        pageWidget->removePage(pageWidget->currentPage());
+    delete pageWidget;
+    //delete Data; delete Pos; delete Links; delete Adv; delete Log;
+    Data = NULL; Pos = NULL; Links = NULL; Adv = NULL; Log = NULL;
+    pageWidget = new KPageWidget( ui.framePage );
+    pageWidget->setFaceType( KPageView::Tabbed );
+    pageWidget->setBackgroundRole( QPalette::Base );
+}
+
+void SkyObjectList::comboBoxIndexChanged( int _index )
+{
+    QComboBox* comboBox = qobject_cast<QComboBox*>(sender());
+    QModelIndex itemToSelect = m_SortModel->mapFromSource( comboBox->model()->index( _index, 0 ) );
+    ui.tableView->setCurrentIndex( itemToSelect );
+
+    QString newName = comboBox->itemData(_index).toString();
+    
+    SkyObject* o;
+    foreach ( o, objectList() ) 
+    {
+        if ( o->translatedName() == newName ) 
+        {
+            selectedObject = o;
+	    //cleanupDetailView();
+	    if( ui.radioButtonDetailed->isChecked() )
+	        showDetails( true );
+            break;
+        }
+    }
+}
+
+void SkyObjectList::showDetails( bool state )
+{
+    kDebug() << Q_FUNC_INFO << endl;
+    if( state )
+    {
+        kDebug() << "state is checked!" << endl;
+        ui.tableView->setVisible( false );
+	ui.radioButtonSummary->setChecked( false );
+	cleanupDetailView();
+        if( selectedObject )
+        {
+            createGeneralTab();
+            createPositionTab( ut, geo );
+            createLinksTab();
+            createAdvancedTab();
+            createLogTab();
+            pageWidget->show();
+        }
+    }
+    else if( state == Qt::Unchecked )
+    {
+        ui.tableView->setVisible( true );
+	ui.radioButtonSummary->setChecked( true );
+	pageWidget->hide();
+        kDebug() << "state is unchecked!" << endl;
+    }
+}
+
+void SkyObjectList::showSummary( bool state )
+{
+    showDetails( !state );
+}
+
+void SkyObjectList::slotCenterObject() 
+{
+    ks->map()->setClickedObject( currentObject() );
+    ks->map()->setClickedPoint( currentObject() );
+    ks->map()->slotCenter();
+    //pageWidget->show();
+}
+
+void SkyObjectList::createGeneralTab()
+{
+    if( Data )
+        return;
+    Data = new DataWidget(pageWidget);
+    pageWidget->addPage( Data, i18n("General") );
+
+    Data->Names->setPalette( titlePalette );
+
+    //Connections
+    connect( Data->ObsListButton, SIGNAL( clicked() ), this, SLOT( addToObservingList() ) );
+    connect( Data->CenterButton, SIGNAL( clicked() ), this, SLOT( centerMap() ) );
+    #ifdef HAVE_INDI_H
+    connect( Data->ScopeButton, SIGNAL( clicked() ), this, SLOT( centerTelescope() ) );
+    #else
+    Data->ScopeButton->setEnabled(false);
+    #endif
+    connect( Data->Image, SIGNAL( clicked() ), this, SLOT( updateThumbnail() ) );
+
+    Data->IllumLabel->setVisible( false );
+
+    //Show object thumbnail image
+    showThumbnail();
+
+    //Fill in the data fields
+    //Contents depend on type of object
+    StarObject *s = 0L;
+    DeepSkyObject *dso = 0L;
+    KSPlanetBase *ps = 0L;
+    QString pname, oname, objecttyp, constellationname;
+
+    switch ( selectedObject->type() ) {
+    case SkyObject::STAR:
+        s = (StarObject *)selectedObject;
+
+        Data->Names->setText( s->longname() );
+
+        if( s->getHDIndex() != 0 ) {
+            if( !s->longname().isEmpty() )
+                Data->Names->setText( s->longname() + QString( ", HD%1" ).arg( QString::number( s->getHDIndex() ) ) );
+            else
+                Data->Names->setText( QString( ", HD%1" ).arg( QString::number( s->getHDIndex() ) ) );
+        }
+        objecttyp = s->sptype() + ' ' + i18n("star");
+        Data->Magnitude->setText( i18nc( "number in magnitudes", "%1 mag" ,
+                                         KGlobal::locale()->formatNumber( s->mag(), 1 ) ) );  //show to tenths place
+
+        //The thumbnail image is empty, and isn't clickable for stars
+        //Also, don't show the border around the Image QFrame.
+        Data->Image->setFrameStyle( QFrame::NoFrame );
+        disconnect( Data->Image, SIGNAL( clicked() ), this, SLOT( updateThumbnail() ) );
+
+        //distance
+        if ( s->distance() > 2000. || s->distance() < 0. )  // parallax < 0.5 mas
+            Data->Distance->setText( QString(i18nc("larger than 2000 parsecs", "> 2000 pc") ) );
+        else if ( s->distance() > 50.0 ) //show to nearest integer
+            Data->Distance->setText( i18nc( "number in parsecs", "%1 pc" ,
+                                            KGlobal::locale()->formatNumber( s->distance(), 0 ) ) );
+        else if ( s->distance() > 10.0 ) //show to tenths place
+            Data->Distance->setText( i18nc( "number in parsecs", "%1 pc" ,
+                                            KGlobal::locale()->formatNumber( s->distance(), 1 ) ) );
+        else //show to hundredths place
+            Data->Distance->setText( i18nc( "number in parsecs", "%1 pc" ,
+                                            KGlobal::locale()->formatNumber( s->distance(), 2 ) ) );
+
+        //Note multiplicity/variablility in angular size label
+        Data->AngSizeLabel->setText( QString() );
+        Data->AngSize->setText( QString() );
+        Data->AngSizeLabel->setFont( Data->AngSize->font() );
+        if ( s->isMultiple() && s->isVariable() ) {
+            Data->AngSizeLabel->setText( i18nc( "the star is a multiple star", "multiple" ) + ',' );
+            Data->AngSize->setText( i18nc( "the star is a variable star", "variable" ) );
+        } else if ( s->isMultiple() )
+            Data->AngSizeLabel->setText( i18nc( "the star is a multiple star", "multiple" ) );
+        else if ( s->isVariable() )
+            Data->AngSizeLabel->setText( i18nc( "the star is a variable star", "variable" ) );
+
+        break; //end of stars case
+
+    case SkyObject::ASTEROID:  //[fall through to planets]
+    case SkyObject::COMET: //[fall through to planets]
+    case SkyObject::MOON: //[fall through to planets]
+    case SkyObject::PLANET:
+        ps = (KSPlanetBase *)selectedObject;
+
+        Data->Names->setText( ps->longname() );
+        //Type is "G5 star" for Sun
+        if ( ps->name() == "Sun" )
+            objecttyp = i18n("G5 star");
+        else if ( ps->name() == "Moon" )
+            objecttyp = ps->translatedName();
+        else if ( ps->name() == i18n("Pluto") || ps->name() == "Ceres" || ps->name() == "Eris" ) // TODO: Check if Ceres / Eris have translations and i18n() them
+            objecttyp = i18n("Dwarf planet");
+        else
+            objecttyp = ps->typeName();
+
+        //Magnitude: The moon displays illumination fraction instead
+        if ( selectedObject->name() == "Moon" ) {
+            Data->IllumLabel->setVisible( true );
+            Data->Illumination->setText( QString("%1 %").arg( KGlobal::locale()->formatNumber( ((KSMoon *)selectedObject)->illum()*100., 0 ) ) );
+        }
+
+        Data->Magnitude->setText( i18nc( "number in magnitudes", "%1 mag" ,
+                                         KGlobal::locale()->formatNumber( ps->mag(), 1 ) ) );  //show to tenths place
+        //Distance from Earth.  The moon requires a unit conversion
+        if ( ps->name() == "Moon" ) {
+            Data->Distance->setText( i18nc("distance in kilometers", "%1 km",
+                                           KGlobal::locale()->formatNumber( ps->rearth()*AU_KM ) ) );
+        } else {
+            Data->Distance->setText( i18nc("distance in Astronomical Units", "%1 AU",
+                                           KGlobal::locale()->formatNumber( ps->rearth() ) ) );
+        }
+
+        //Angular size; moon and sun in arcmin, others in arcsec
+        if ( ps->angSize() ) {
+            if ( ps->name() == "Sun" || ps->name() == "Moon" )
+                Data->AngSize->setText( i18nc("angular size in arcminutes", "%1 arcmin",
+                                              KGlobal::locale()->formatNumber( ps->angSize() ) ) ); // Needn't be a plural form because sun / moon will never contract to 1 arcminute
+            else
+                Data->AngSize->setText( i18nc("angular size in arcseconds","%1 arcsec",
+                                              KGlobal::locale()->formatNumber( ps->angSize()*60.0 ) ) ); 
+        } else {
+            Data->AngSize->setText( "--" );
+        }
+
+        break; //end of planets/comets/asteroids case
+
+    default: //deep-sky objects
+        dso = (DeepSkyObject *)selectedObject;
+
+        //Show all names recorded for the object
+        if ( ! dso->longname().isEmpty() && dso->longname() != dso->name() ) {
+            pname = dso->translatedLongName();
+            oname = dso->translatedName();
+        } else {
+            pname = dso->translatedName();
+        }
+
+        if ( ! dso->translatedName2().isEmpty() ) {
+            if ( oname.isEmpty() ) oname = dso->translatedName2();
+            else oname += ", " + dso->translatedName2();
+        }
+
+        if ( dso->ugc() != 0 ) {
+            if ( ! oname.isEmpty() ) oname += ", ";
+            oname += "UGC " + QString::number( dso->ugc() );
+        }
+        if ( dso->pgc() != 0 ) {
+            if ( ! oname.isEmpty() ) oname += ", ";
+            oname += "PGC " + QString::number( dso->pgc() );
+        }
+
+        if ( ! oname.isEmpty() ) pname += ", " + oname;
+        Data->Names->setText( pname );
+
+        objecttyp = dso->typeName();
+
+        if ( dso->mag() > 90.0 )
+            Data->Magnitude->setText( "--" );
+        else
+            Data->Magnitude->setText( i18nc( "number in magnitudes", "%1 mag" ,
+                                             KGlobal::locale()->formatNumber( dso->mag(), 1 ) ) );  //show to tenths place
+
+        //No distances at this point...
+        Data->Distance->setText( "--" );
+
+        //Only show decimal place for small angular sizes
+        if ( dso->a() > 10.0 )
+            Data->AngSize->setText( i18nc("angular size in arcminutes", "%1 arcmin",
+                                          KGlobal::locale()->formatNumber(dso->a(), 0 ) ) );
+        else if ( dso->a() )
+            Data->AngSize->setText( i18nc("angular size in arcminutes", "%1 arcmin",
+                                          KGlobal::locale()->formatNumber( dso->a(), 1 ) ) );
+        else
+            Data->AngSize->setText( "--" );
+
+        break;
+    }
+
+    //Common to all types:
+    if ( selectedObject->type() == SkyObject::CONSTELLATION )
+        Data->ObjectTypeInConstellation->setText( ConstellationBoundary::Instance()->constellationName( selectedObject ) );
+    else
+        Data->ObjectTypeInConstellation->setText( 
+            i18nc("%1 type of sky object (planet, asteroid etc), %2 name of a constellation", "%1 in %2", objecttyp, 
+                  ConstellationBoundary::Instance()->constellationName( selectedObject ) ) );
+}
+
+void SkyObjectList::createPositionTab( const KStarsDateTime &ut, GeoLocation *geo ) {
+    Pos = new PositionWidget(pageWidget);
+    pageWidget->addPage( Pos,  i18n("Position") );
+
+    Pos->CoordTitle->setPalette( titlePalette );
+    Pos->RSTTitle->setPalette( titlePalette );
+
+    //Coordinates Section:
+    //Don't use KLocale::formatNumber() for the epoch string,
+    //because we don't want a thousands-place separator!
+    QString sEpoch = QString::number( ut.epoch(), 'f', 1 );
+    //Replace the decimal point with localized decimal symbol
+    sEpoch.replace( '.', KGlobal::locale()->decimalSymbol() );
+
+    Pos->RALabel->setText( i18n( "RA (%1):", sEpoch ) );
+    Pos->DecLabel->setText( i18n( "Dec (%1):", sEpoch ) );
+    Pos->RA->setText( selectedObject->ra()->toHMSString() );
+    Pos->Dec->setText( selectedObject->dec()->toDMSString() );
+    Pos->Az->setText( selectedObject->az()->toDMSString() );
+    dms a( selectedObject->alt()->Degrees() );
+    if ( Options::useAltAz() && Options::useRefraction() )
+        a = KStars::Instance()->map()->refract( selectedObject->alt(), true ); //true: compute apparent alt from true alt
+    Pos->Alt->setText( a.toDMSString() );
+
+    //Hour Angle can be negative, but dms HMS expressions cannot.
+    //Here's a kludgy workaround:
+    dms lst = geo->GSTtoLST( ut.gst() );
+    dms ha( lst.Degrees() - selectedObject->ra()->Degrees() );
+    QChar sgn('+');
+    if ( ha.Hours() > 12.0 ) {
+        ha.setH( 24.0 - ha.Hours() );
+        sgn = '-';
+    }
+    Pos->HA->setText( QString("%1%2").arg(sgn).arg( ha.toHMSString() ) );
+
+    //Airmass is approximated as the secant of the zenith distance,
+    //equivalent to 1./sin(Alt).  Beware of Inf at Alt=0!
+    if ( selectedObject->alt()->Degrees() > 0.0 )
+        Pos->Airmass->setText( KGlobal::locale()->formatNumber(
+                                   1./sin( selectedObject->alt()->radians() ), 2 ) );
+    else
+        Pos->Airmass->setText( "--" );
+
+    //Rise/Set/Transit Section:
+
+    //Prepare time/position variables
+    QTime rt = selectedObject->riseSetTime( ut, geo, true ); //true = use rise time
+    dms raz = selectedObject->riseSetTimeAz( ut, geo, true ); //true = use rise time
+
+    //If transit time is before rise time, use transit time for tomorrow
+    QTime tt = selectedObject->transitTime( ut, geo );
+    dms talt = selectedObject->transitAltitude( ut, geo );
+    if ( tt < rt ) {
+        tt = selectedObject->transitTime( ut.addDays( 1 ), geo );
+        talt = selectedObject->transitAltitude( ut.addDays( 1 ), geo );
+    }
+
+    //If set time is before rise time, use set time for tomorrow
+    QTime st = selectedObject->riseSetTime(  ut, geo, false ); //false = use set time
+    dms saz = selectedObject->riseSetTimeAz( ut, geo, false ); //false = use set time
+    if ( st < rt ) {
+        st = selectedObject->riseSetTime( ut.addDays( 1 ), geo, false ); //false = use set time
+        saz = selectedObject->riseSetTimeAz( ut.addDays( 1 ), geo, false ); //false = use set time
+    }
+
+    if ( rt.isValid() ) {
+        Pos->TimeRise->setText( QString().sprintf( "%02d:%02d", rt.hour(), rt.minute() ) );
+        Pos->TimeSet->setText( QString().sprintf( "%02d:%02d", st.hour(), st.minute() ) );
+        Pos->AzRise->setText( raz.toDMSString() );
+        Pos->AzSet->setText( saz.toDMSString() );
+    } else {
+        if ( selectedObject->alt()->Degrees() > 0.0 ) {
+            Pos->TimeRise->setText( i18n( "Circumpolar" ) );
+            Pos->TimeSet->setText( i18n( "Circumpolar" ) );
+        } else {
+            Pos->TimeRise->setText( i18n( "Never rises" ) );
+            Pos->TimeSet->setText( i18n( "Never rises" ) );
+        }
+
+        Pos->AzRise->setText( i18nc( "Not Applicable", "N/A" ) );
+        Pos->AzSet->setText( i18nc( "Not Applicable", "N/A" ) );
+    }
+
+    Pos->TimeTransit->setText( QString().sprintf( "%02d:%02d", tt.hour(), tt.minute() ) );
+    Pos->AltTransit->setText( talt.toDMSString() );
+
+    // Restore the position and other time-dependent parameters
+    selectedObject->recomputeCoords( ut, geo );
+
+}
+
+void SkyObjectList::createLinksTab()
+{
+    if( Links )
+        return;
+    // don't create a link tab for an unnamed star
+    if (selectedObject->name() == QString("star"))
+        return;
+
+    Links = new LinksWidget( pageWidget );
+    pageWidget->addPage( Links, i18n( "Links" ) );
+
+    Links->InfoTitle->setPalette( titlePalette );
+    Links->ImagesTitle->setPalette( titlePalette );
+
+    foreach ( const QString &s, selectedObject->InfoTitle() )
+        Links->InfoTitleList->addItem( i18nc( "Image/info menu item (should be translated)", s.toLocal8Bit() ) );
+
+    //Links->InfoTitleList->setCurrentRow(0);
+
+    foreach ( const QString &s, selectedObject->ImageTitle() )
+        Links->ImageTitleList->addItem( i18nc( "Image/info menu item (should be translated)", s.toLocal8Bit() ) );
+
+     updateButtons();
+
+    // Signals/Slots
+    connect( Links->ViewButton, SIGNAL(clicked()), this, SLOT( viewLink() ) );
+    connect( Links->AddLinkButton, SIGNAL(clicked()), KStars::Instance()->map(), SLOT( addLink() ) );
+    connect( Links->EditLinkButton, SIGNAL(clicked()), this, SLOT( editLinkDialog() ) );
+    connect( Links->RemoveLinkButton, SIGNAL(clicked()), this, SLOT( removeLinkDialog() ) );
+
+    // When an item is selected in info list, selected items are cleared image list.
+    connect( Links->InfoTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT( setCurrentLink(QListWidgetItem*) ) );
+    connect( Links->InfoTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), Links->ImageTitleList, SLOT( clearSelection() ) );
+
+    // vice versa
+    connect( Links->ImageTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT( setCurrentLink(QListWidgetItem*) ) );
+    connect( Links->ImageTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), Links->InfoTitleList, SLOT( clearSelection() ));
+
+    connect( Links->InfoTitleList, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT( viewLink() ) );
+    connect( Links->ImageTitleList, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT( viewLink() ) );
+
+    connect( Links->InfoTitleList, SIGNAL(itemSelectionChanged ()), this, SLOT( updateButtons() ) );
+    connect( Links->ImageTitleList, SIGNAL(itemSelectionChanged ()), this, SLOT( updateButtons() ));
+
+    connect( KStars::Instance()->map(), SIGNAL(linkAdded()), this, SLOT( updateLists() ) );
+}
+
+void SkyObjectList::createAdvancedTab()
+{
+    if( Adv )
+        return;
+    // Don't create an adv tab for an unnamed star or if advinterface file failed loading
+    // We also don't need adv dialog for solar system objects.
+    if (selectedObject->name() == QString("star") ||
+            KStarsData::Instance()->ADVtreeList.isEmpty() ||
+            selectedObject->type() == SkyObject::PLANET ||
+            selectedObject->type() == SkyObject::COMET ||
+            selectedObject->type() == SkyObject::ASTEROID )
+        return;
+
+    Adv = new DatabaseWidget( pageWidget );
+    pageWidget->addPage( Adv,  i18n( "Advanced" ) );
+
+    connect( Adv->ADVTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(viewADVData()));
+
+    populateADVTree();
+}
+
+void SkyObjectList::createLogTab()
+{
+    if( Log )
+        return;
+    //Don't create a a log tab for an unnamed star
+    if ( selectedObject->name() == QString("star") )
+        return;
+
+    // Log Tab
+    Log = new LogWidget( pageWidget );
+    pageWidget->addPage( Log,  i18n( "Log" ) );
+
+    Log->LogTitle->setPalette( titlePalette );
+
+    if ( selectedObject->userLog().isEmpty() )
+        Log->UserLog->setText(i18n("Record here observation logs and/or data on %1.", selectedObject->translatedName()));
+    else
+        Log->UserLog->setText(selectedObject->userLog());
+
+    //Automatically save the log contents when the widget loses focus
+    connect( Log->UserLog, SIGNAL( focusOut() ), this, SLOT( saveLogData() ) );
+}
+
+
+void SkyObjectList::setCurrentLink(QListWidgetItem *it)
+{
+    m_CurrentLink = it;
+}
+
+void SkyObjectList::viewLink()
+{
+    QString URL;
+
+    if (m_CurrentLink == NULL) return;
+
+    if ( m_CurrentLink->listWidget() == Links->InfoTitleList ) {
+        URL = QString( selectedObject->InfoList().at( Links->InfoTitleList->row(m_CurrentLink) ) );
+    }
+    else if ( m_CurrentLink->listWidget() == Links->ImageTitleList ) {
+        URL = QString( selectedObject->ImageList().at( Links->ImageTitleList->row(m_CurrentLink) ) );
+    }
+
+    if ( !URL.isEmpty() )
+        KToolInvocation::invokeBrowser(URL);
+}
+
+void SkyObjectList::updateLists()
+{
+    Links->InfoTitleList->clear();
+    Links->ImageTitleList->clear();
+
+    foreach ( const QString &s, selectedObject->InfoTitle() )
+        Links->InfoTitleList->addItem( s );
+
+    foreach ( const QString &s, selectedObject->ImageTitle() )
+        Links->ImageTitleList->addItem( s );
+
+    updateButtons();
+}
+
+void SkyObjectList::updateButtons()
+{
+
+    bool anyLink=false;
+    if (!Links->InfoTitleList->selectedItems().isEmpty() || !Links->ImageTitleList->selectedItems().isEmpty())
+        anyLink = true;
+
+    // Buttons could be disabled if lists are initially empty, we enable and disable them here
+    // depending on the current status of the list.
+    Links->ViewButton->setEnabled(anyLink);
+    Links->EditLinkButton->setEnabled(anyLink);
+    Links->RemoveLinkButton->setEnabled(anyLink);
+}
+
+void SkyObjectList::editLinkDialog()
+{
+    int type=0, row=0;
+    QString search_line, replace_line, currentItemTitle, currentItemURL;
+
+    if (m_CurrentLink == NULL) return;
+
+    KDialog editDialog( this );
+    editDialog.setCaption( i18n("Edit Link") );
+    editDialog.setButtons( KDialog::Ok | KDialog::Cancel );
+    QFrame editFrame( &editDialog );
+
+    if ( m_CurrentLink->listWidget() == Links->InfoTitleList )
+    {
+        row = Links->InfoTitleList->row( m_CurrentLink );
+
+        currentItemTitle = m_CurrentLink->text();
+        currentItemURL = selectedObject->InfoTitle().at( row );
+        search_line = selectedObject->name();
+        search_line += ':';
+        search_line += currentItemTitle;
+        search_line += ':';
+        search_line += currentItemURL;
+        type       = 0;
+    }
+    else if ( m_CurrentLink->listWidget() == Links->ImageTitleList )
+    {
+        row = Links->ImageTitleList->row( m_CurrentLink );
+
+        currentItemTitle = m_CurrentLink->text();
+        currentItemURL = selectedObject->ImageTitle().at( row ); 
+        search_line = selectedObject->name();
+        search_line += ':';
+        search_line += currentItemTitle;
+        search_line += ':';
+        search_line += currentItemURL;
+        type 	   = 1;
+    }
+    else return;
+
+    QLineEdit editNameField(&editFrame);
+    editNameField.setObjectName("nameedit");
+    editNameField.home(false);
+    editNameField.setText(currentItemTitle);
+    QLabel editLinkURL(i18n("URL:"), &editFrame);
+    QLineEdit editLinkField(&editFrame);
+    editLinkField.setObjectName("urledit");
+    editLinkField.home(false);
+    editLinkField.setText(currentItemURL);
+    QVBoxLayout vlay(&editFrame);
+    vlay.setObjectName("vlay");
+    QHBoxLayout editLinkLayout(&editFrame);
+    editLinkLayout.setObjectName("editlinklayout");
+    editLinkLayout.addWidget(&editLinkURL);
+    editLinkLayout.addWidget(&editLinkField);
+    vlay.addWidget( &editNameField );
+    vlay.addLayout( &editLinkLayout );
+    editDialog.setMainWidget( &editFrame );
+
+    bool go( true );
+    // If user presses cancel then skip the action
+    if ( editDialog.exec() != QDialog::Accepted )
+        go = false;
+
+    // If nothing changed, skip th action
+    if (editLinkField.text() == currentItemURL && editNameField.text() == currentItemTitle)
+        go = false;
+
+    if ( go ) {
+        replace_line = selectedObject->name() + ':' + editNameField.text() + ':' + editLinkField.text();
+
+        // Info Link
+        if (type==0) {
+            selectedObject->InfoTitle().replace(row, editNameField.text());
+            selectedObject->InfoList().replace(row, editLinkField.text());
+
+        // Image Links
+        } else {
+            selectedObject->ImageTitle().replace(row, editNameField.text());
+            selectedObject->ImageList().replace(row, editLinkField.text());
+        }
+
+        // Update local files
+        updateLocalDatabase(type, search_line, replace_line);
+
+        // Set focus to the same item again
+        if (type == 0)
+            Links->InfoTitleList->setCurrentRow(row);
+        else
+            Links->ImageTitleList->setCurrentRow(row);
+    }
+}
+
+void SkyObjectList::removeLinkDialog()
+{
+    int type=0, row=0;
+    QString currentItemURL, currentItemTitle, LineEntry, TempFileName, FileLine;
+    QFile URLFile;
+    KTemporaryFile TempFile;
+    TempFile.setAutoRemove(false);
+    TempFile.open();
+    TempFileName = TempFile.fileName();
+
+    if (m_CurrentLink == NULL) return;
+
+    if ( m_CurrentLink->listWidget() == Links->InfoTitleList )
+    {
+        row = Links->InfoTitleList->row( m_CurrentLink );
+        currentItemTitle = m_CurrentLink->text();
+        currentItemURL   = selectedObject->InfoList()[row];
+        LineEntry = selectedObject->name();
+        LineEntry += ':';
+        LineEntry += currentItemTitle;
+        LineEntry += ':';
+        LineEntry += currentItemURL;
+        type       = 0;
+    }
+    else if ( m_CurrentLink->listWidget() == Links->ImageTitleList )
+    {
+        row = Links->ImageTitleList->row( m_CurrentLink );
+        currentItemTitle = m_CurrentLink->text();
+        currentItemURL   = selectedObject->ImageList()[row];
+        LineEntry = selectedObject->name();
+        LineEntry += ':';
+        LineEntry += currentItemTitle;
+        LineEntry += ':';
+        LineEntry += currentItemURL;
+        type 	   = 1;
+    }
+    else return;
+
+    if (KMessageBox::warningContinueCancel( 0, i18n("Are you sure you want to remove the %1 link?", currentItemTitle), i18n("Delete Confirmation"),KStandardGuiItem::del())!=KMessageBox::Continue)
+        return;
+
+    if (type ==0)
+    {
+        selectedObject->InfoTitle().removeAt(row);
+        selectedObject->InfoList().removeAt(row);
+    }
+    else
+    {
+        selectedObject->ImageTitle().removeAt(row);
+        selectedObject->ImageList().removeAt(row);
+    }
+
+    // Remove link from file
+    updateLocalDatabase(type, LineEntry);
+
+    // Set focus to the 1st item in the list
+    if (type == 0)
+        Links->InfoTitleList->clearSelection();
+    else
+        Links->ImageTitleList->clearSelection();
+
+}
+
+void SkyObjectList::updateLocalDatabase(int type, const QString &search_line, const QString &replace_line)
+{
+    QString TempFileName, file_line;
+    QFile URLFile;
+    KTemporaryFile TempFile;
+    TempFile.setAutoRemove(false);
+    TempFile.open();
+    QTextStream *temp_stream=NULL, *out_stream=NULL;
+    bool replace = !replace_line.isEmpty();
+
+    if (search_line.isEmpty())
+        return;
+
+    TempFileName = TempFile.fileName();
+
+    switch (type)
+    {
+        // Info Links
+    case 0:
+        // Get name for our local info_url file
+        URLFile.setFileName( KStandardDirs::locateLocal( "appdata", "info_url.dat" ) );
+        break;
+
+        // Image Links
+    case 1:
+        // Get name for our local info_url file
+        URLFile.setFileName( KStandardDirs::locateLocal( "appdata", "image_url.dat" ) );
+        break;
+    }
+
+    // Copy URL file to temp file
+    KIO::file_copy(KUrl::fromPath(URLFile.fileName()), KUrl::fromPath(TempFileName), -1, KIO::Overwrite | KIO::HideProgressInfo );
+
+
+    if ( !URLFile.open( QIODevice::WriteOnly) )
+    {
+        kDebug() << "SkyObjectList: Failed to open " << URLFile.fileName();
+        kDebug() << "KStars cannot save to user database";
+        return;
+    }
+
+    // Get streams;
+    temp_stream = new QTextStream(&TempFile);
+    out_stream  = new QTextStream(&URLFile);
+
+    while (!temp_stream->atEnd())
+    {
+        file_line = temp_stream->readLine();
+        // If we find a match, either replace, or remove (by skipping).
+        if (file_line == search_line)
+        {
+            if (replace)
+                (*out_stream) << replace_line << endl;
+            else
+                continue;
+        }
+        else
+            (*out_stream) << file_line << endl;
+    }
+
+    URLFile.close();
+    delete(temp_stream);
+    delete(out_stream);
+
+    updateLists();
+
+}
+
+void SkyObjectList::populateADVTree()
+{
+    QTreeWidgetItem *parent = NULL, *temp = NULL;
+
+    // We populate the tree iterativley, keeping track of parents as we go
+    // This solution is more efficient than the previous recursion algorithm.
+    foreach (ADVTreeData *item, KStarsData::Instance()->ADVtreeList)
+    {
+
+        switch (item->Type)
+        {
+            // Top Level
+        case 0:
+            temp = new QTreeWidgetItem(parent, QStringList(item->Name));
+            if (parent == NULL)
+                Adv->ADVTree->addTopLevelItem(temp);
+            parent = temp;
+
+            break;
+
+            // End of top level
+        case 1:
+            if (parent != NULL) parent = parent->parent();
+            break;
+
+            // Leaf
+        case 2:
+            new QTreeWidgetItem(parent, QStringList(item->Name));
+            break;
+        }
+    }
+
+}
+
+void  SkyObjectList::viewADVData()
+{
+    QString link;
+    QTreeWidgetItem * current = Adv->ADVTree->currentItem();
+
+    //If the item has children or is invalid, do nothing
+    if ( !current || current->childCount()>0 )  return;
+
+    foreach (ADVTreeData *item, KStarsData::Instance()->ADVtreeList)
+    {
+        if (item->Name == current->text(0))
+        {
+            link = item->Link;
+            link = parseADVData(link);
+            KToolInvocation::invokeBrowser(link);
+            return;
+        }
+    }
+}
+
+QString SkyObjectList::parseADVData( const QString &inlink )
+{
+    QString link = inlink;
+    QString subLink;
+    int index;
+
+    if ( (index = link.indexOf("KSOBJ")) != -1)
+    {
+        link.remove(index, 5);
+        link = link.insert(index, selectedObject->name());
+    }
+
+    if ( (index = link.indexOf("KSRA")) != -1)
+    {
+        link.remove(index, 4);
+        subLink.sprintf("%02d%02d%02d", selectedObject->ra0()->hour(), selectedObject->ra0()->minute(), selectedObject->ra0()->second());
+        subLink = subLink.insert(2, "%20");
+        subLink = subLink.insert(7, "%20");
+
+        link = link.insert(index, subLink);
+    }
+    if ( (index = link.indexOf("KSDEC")) != -1)
+    {
+        link.remove(index, 5);
+        if (selectedObject->dec()->degree() < 0)
+        {
+            subLink.sprintf("%03d%02d%02d", selectedObject->dec0()->degree(), selectedObject->dec0()->arcmin(), selectedObject->dec0()->arcsec());
+            subLink = subLink.insert(3, "%20");
+            subLink = subLink.insert(8, "%20");
+        }
+        else
+        {
+            subLink.sprintf("%02d%02d%02d", selectedObject->dec0()->degree(), selectedObject->dec0()->arcmin(), selectedObject->dec0()->arcsec());
+            subLink = subLink.insert(0, "%2B");
+            subLink = subLink.insert(5, "%20");
+            subLink = subLink.insert(10, "%20");
+        }
+        link = link.insert(index, subLink);
+    }
+
+    return link;
+}
+
+void SkyObjectList::saveLogData() {
+    selectedObject->saveUserLog( Log->UserLog->toPlainText() );
+}
+
+void SkyObjectList::addToObservingList() {
+    KStars::Instance()->observingList()->slotAddObject( selectedObject );
+}
+
+void SkyObjectList::centerMap() {
+    SkyMap* map = KStars::Instance()->map();
+    map->setClickedObject( selectedObject );
+    map->slotCenter();
+}
+
+void SkyObjectList::centerTelescope()
+{
+#ifdef HAVE_INDI_H
+    INDI_D *indidev(NULL);
+    INDI_P *prop(NULL), *onset(NULL);
+    INDI_E *RAEle(NULL), *DecEle(NULL), *AzEle(NULL), *AltEle(NULL), *ConnectEle(NULL), *nameEle(NULL);
+    bool useJ2000( false);
+    int selectedCoord(0);
+    SkyPoint sp;
+    SkyMap* map = KStars::Instance()->map();
+    
+    // Find the first device with EQUATORIAL_EOD_COORD or EQUATORIAL_COORD and with SLEW element
+    // i.e. the first telescope we find!
+
+    INDIMenu *imenu = KStars::Instance()->indiMenu();
+    for ( int i=0; i < imenu->managers.size() ; i++ )
+    {
+        for ( int j=0; j < imenu->managers.at(i)->indi_dev.size(); j++ )
+        {
+            indidev = imenu->managers.at(i)->indi_dev.at(j);
+            indidev->stdDev->currentObject = NULL;
+            prop = indidev->findProp("EQUATORIAL_EOD_COORD_REQUEST");
+            if (prop == NULL)
+            {
+                prop = indidev->findProp("EQUATORIAL_EOD_COORD");
+                if (prop == NULL)
+                {
+                    prop = indidev->findProp("HORIZONTAL_COORD");
+                    if (prop == NULL)
+                        continue;
+                    else
+                        selectedCoord = 1;		/* Select horizontal */
+                }
+                else
+                    useJ2000 = true;
+            }
+
+            ConnectEle = indidev->findElem("CONNECT");
+            if (!ConnectEle) continue;
+
+            if (ConnectEle->state == PS_OFF)
+            {
+                KMessageBox::error(0, i18n("Telescope %1 is offline. Please connect and retry again.", indidev->label));
+                return;
+            }
+
+            switch (selectedCoord)
+            {
+                // Equatorial
+            case 0:
+                if (prop->perm == PP_RO) continue;
+                RAEle  = prop->findElement("RA");
+                if (!RAEle) continue;
+                DecEle = prop->findElement("DEC");
+                if (!DecEle) continue;
+                break;
+
+                // Horizontal
+            case 1:
+                if (prop->perm == PP_RO) continue;
+                AzEle = prop->findElement("AZ");
+                if (!AzEle) continue;
+                AltEle = prop->findElement("ALT");
+                if (!AltEle) continue;
+                break;
+            }
+
+            onset = indidev->findProp("ON_COORD_SET");
+            if (!onset) continue;
+
+            onset->activateSwitch("SLEW");
+
+            indidev->stdDev->currentObject = selectedObject;
+
+            /* Send object name if available */
+            if (indidev->stdDev->currentObject)
+            {
+                nameEle = indidev->findElem("OBJECT_NAME");
+                if (nameEle && nameEle->pp->perm != PP_RO)
+                {
+                    nameEle->write_w->setText(indidev->stdDev->currentObject->name());
+                    nameEle->pp->newText();
+                }
+            }
+
+            switch (selectedCoord)
+            {
+            case 0:
+                if (indidev->stdDev->currentObject)
+                    sp.set (indidev->stdDev->currentObject->ra(), indidev->stdDev->currentObject->dec());
+                else
+                    sp.set (map->clickedPoint()->ra(), map->clickedPoint()->dec());
+
+                if (useJ2000)
+                    sp.apparentCoord(KStarsData::Instance()->ut().djd(), (long double) J2000);
+
+                RAEle->write_w->setText(QString("%1:%2:%3").arg(sp.ra()->hour()).arg(sp.ra()->minute()).arg(sp.ra()->second()));
+                DecEle->write_w->setText(QString("%1:%2:%3").arg(sp.dec()->degree()).arg(sp.dec()->arcmin()).arg(sp.dec()->arcsec()));
+
+                break;
+
+            case 1:
+                if (indidev->stdDev->currentObject)
+                {
+                    sp.setAz(*indidev->stdDev->currentObject->az());
+                    sp.setAlt(*indidev->stdDev->currentObject->alt());
+                }
+                else
+                {
+                    sp.setAz(*map->clickedPoint()->az());
+                    sp.setAlt(*map->clickedPoint()->alt());
+                }
+
+                AzEle->write_w->setText(QString("%1:%2:%3").arg(sp.az()->degree()).arg(sp.az()->arcmin()).arg(sp.az()->arcsec()));
+                AltEle->write_w->setText(QString("%1:%2:%3").arg(sp.alt()->degree()).arg(sp.alt()->arcmin()).arg(sp.alt()->arcsec()));
+
+                break;
+            }
+
+            prop->newText();
+
+            return;
+        }
+    }
+
+    // We didn't find any telescopes
+    KMessageBox::sorry(0, i18n("KStars did not find any active telescopes."));
+#endif
+}
+
+void SkyObjectList::showThumbnail() {
+    //No image if object is a star
+    if ( selectedObject->type() == SkyObject::STAR ||
+         selectedObject->type() == SkyObject::CATALOG_STAR ) {
+        Thumbnail->scaled( Data->Image->width(), Data->Image->height() );
+        Thumbnail->fill( Data->DataFrame->palette().color( QPalette::Window ) );
+        Data->Image->setPixmap( *Thumbnail );
+        return;
+    }
+
+    //Try to load the object's image from disk
+    //If no image found, load "no image" image
+    //If that isn't found, make it blank.
+    QFile file;
+    QString fname = "thumb-" + selectedObject->name().toLower().remove( ' ' ) + ".png";
+    if ( KSUtils::openDataFile( file, fname ) ) {
+        file.close();
+        Thumbnail->load( file.fileName(), "PNG" );
+    } else if ( KSUtils::openDataFile( file, "noimage.png" ) ) {
+        file.close();
+        Thumbnail->load( file.fileName(), "PNG" );
+    } else {
+        Thumbnail->scaled( Data->Image->width(), Data->Image->height() );
+        Thumbnail->fill( Data->DataFrame->palette().color( QPalette::Window ) );
+    }
+
+    Data->Image->setPixmap( *Thumbnail );
+}
+
+void SkyObjectList::updateThumbnail() {
+    QPointer<ThumbnailPicker> tp = new ThumbnailPicker( selectedObject, *Thumbnail, this );
+
+    if ( tp->exec() == QDialog::Accepted ) {
+        QString fname = KStandardDirs::locateLocal( "appdata", "thumb-" + selectedObject->name().toLower().remove( ' ' ) + ".png" );
+
+        Data->Image->setPixmap( *(tp->image()) );
+
+        //If a real image was set, save it.
+        //If the image was unset, delete the old image on disk.
+        if ( tp->imageFound() ) {
+            Data->Image->pixmap()->save( fname, "PNG" );
+            *Thumbnail = *(Data->Image->pixmap());
+        } else {
+            QFile f;
+            f.setFileName( fname );
+            f.remove();
+        }
+    }
+    delete tp;
+}
+
+#if 0
+
+DataWidget::DataWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+    DataFrame->setBackgroundRole( QPalette::Base );
+}
+
+PositionWidget::PositionWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+    CoordFrame->setBackgroundRole( QPalette::Base );
+    RSTFrame->setBackgroundRole( QPalette::Base );
+}
+
+LinksWidget::LinksWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+}
+
+DatabaseWidget::DatabaseWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+}
+
+LogWidget::LogWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+}
+#endif
+
+#include "objectlist.moc"
+
Index: dialogs/objectlist.ui
===================================================================
--- dialogs/objectlist.ui	(revision 0)
+++ dialogs/objectlist.ui	(revision 0)
 <at>  <at>  -0,0 +1,160  <at>  <at> 
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>formSkyObjectList</class>
+ <widget class="QWidget" name="formSkyObjectList">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>600</width>
+    <height>400</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>600</width>
+    <height>400</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Object List</string>
+  </property>
+  <widget class="QWidget" name="verticalLayoutWidget">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>10</y>
+     <width>571</width>
+     <height>371</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>View mode</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="radioButtonDetailed">
+        <property name="text">
+         <string>&amp;Detailed</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+        <attribute name="buttonGroup">
+         <string>buttonGroupViewMode</string>
+        </attribute>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="radioButtonSummary">
+        <property name="text">
+         <string>&amp;Summary</string>
+        </property>
+        <attribute name="buttonGroup">
+         <string>buttonGroupViewMode</string>
+        </attribute>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QLabel" name="label">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="layoutDirection">
+         <enum>Qt::RightToLeft</enum>
+        </property>
+        <property name="text">
+         <string>Select sky object</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Maximum</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxObjects"/>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <widget class="QTableView" name="tableView">
+      <property name="alternatingRowColors">
+       <bool>true</bool>
+      </property>
+      <property name="selectionMode">
+       <enum>QAbstractItemView::ExtendedSelection</enum>
+      </property>
+      <property name="selectionBehavior">
+       <enum>QAbstractItemView::SelectRows</enum>
+      </property>
+      <property name="gridStyle">
+       <enum>Qt::DotLine</enum>
+      </property>
+      <property name="sortingEnabled">
+       <bool>true</bool>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QFrame" name="framePage">
+      <property name="frameShape">
+       <enum>QFrame::NoFrame</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Plain</enum>
+      </property>
+      <property name="lineWidth">
+       <number>0</number>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+ <buttongroups>
+  <buttongroup name="buttonGroupViewMode"/>
+ </buttongroups>
+</ui>
Index: dialogs/objectlist.h
===================================================================
--- dialogs/objectlist.h	(revision 0)
+++ dialogs/objectlist.h	(revision 0)
 <at>  <at>  -0,0 +1,169  <at>  <at> 
+#ifndef OBJECTLIST_H
+#define OBJECTLIST_H
+
+#include <QPixmap>
+#include <QMouseEvent>
+#include <QFocusEvent>
+#include <QHBoxLayout>
+#include <QTabWidget>
+#include <QPushButton>
+#include <QPalette>
+
+#include <kpagedialog.h>
+#include <ktextedit.h>
+
+#include <KDialog>
+#include <QAbstractTableModel>
+#include <QSortFilterProxyModel>
+
+#include "../skyobjects/skyobject.h"
+#include "kstarsdatetime.h"
+#include "skyobjects/skyobject.h"
+#include "skyobjects/deepskyobject.h"
+
+#include "ui_objectlist.h"
+//UI headers
+#include "ui_details_data.h"
+#include "ui_details_position.h"
+#include "ui_details_links.h"
+#include "ui_details_database.h"
+#include "ui_details_log.h"
+
+class GeoLocation;
+class QHBoxLayout;
+class QLineEdit;
+class QListWidgetItem;
+class QPixmap;
+class QString;
+class QStringList;
+class KStars;
+class KStarsDateTime;
+
+class KSAlmanac;
+class QSortFilterProxyModel;
+class QStandardItemModel;
+class KStars;
+class KStarsDateTime;
+class GeoLocation;
+
+
+class DataWidget;
+class PositionWidget;
+class LinksWidget;
+class DatabaseWidget;
+class LogWidget;
+
+#if 0
+struct ADVTreeData
+{
+    QString Name;
+    QString Link;
+    int Type;
+};
+#endif
+
+class SkyObjectList : public KPageDialog
+{
+    Q_OBJECT
+    public:
+        SkyObjectList( SkyObject* o, const KStarsDateTime& _dt, GeoLocation* _geo, KStars* parent = 0 );
+	~SkyObjectList();
+	inline QPixmap* thumbnail() { return Thumbnail; }
+
+	void addObject( SkyObject* );
+	void addObject( DeepSkyObject*& );
+	void removeAll();
+	//~SkyObjectList();
+        SkyObject* currentObject() const { return selectedObject; }
+        QList<SkyObject*>& objectList() { return m_ObjectList; }
+    public slots:
+        void slotNewSelection();
+        void slotCenterObject();
+	void comboBoxIndexChanged( int );
+	//void showDetails(int);
+	void showDetails(bool);
+	void showSummary(bool);
+
+	void addToObservingList();
+	void centerMap();
+	void centerTelescope();
+	void showThumbnail();
+	void updateThumbnail();
+	void viewLink();
+	void setCurrentLink(QListWidgetItem *it);
+	void updateLists();
+	void editLinkDialog();
+	void removeLinkDialog();
+	void viewADVData();
+	void saveLogData();
+	void updateButtons();
+
+    private:
+        KStars *ks;
+        KStarsDateTime ut;
+	GeoLocation *geo;
+        Ui::formSkyObjectList ui;
+        QList<SkyObject*> m_ObjectList;
+        //SkyObject *m_CurrentObject;
+	QStandardItemModel *m_Model;
+	QSortFilterProxyModel *m_SortModel;
+
+	void createGeneralTab();
+	void createPositionTab( const KStarsDateTime &ut, GeoLocation *geo );
+	void createLinksTab();
+	void createAdvancedTab();
+	void createLogTab();
+	void populateADVTree();
+	QString parseADVData( const QString &link );
+	void updateLocalDatabase(int type, const QString &search_line, const QString &replace_line = QString());
+	void cleanupDetailView();
+
+	SkyObject *selectedObject;
+	QPalette titlePalette;
+	QListWidgetItem *m_CurrentLink;
+	QPixmap *Thumbnail;
+	int currentItemIndex;
+	QStringList dataList;
+
+	DataWidget *Data;
+	PositionWidget *Pos;
+	LinksWidget *Links;
+	DatabaseWidget *Adv;
+	LogWidget *Log;
+
+	KPageWidget* pageWidget;
+};
+
+#if 0
+class DataWidget : public QFrame, public Ui::DetailsData
+{
+public:
+    DataWidget( QWidget *parent=0 );
+};
+
+class PositionWidget : public QFrame, public Ui::DetailsPosition
+{
+public:
+    PositionWidget( QWidget *parent=0 );
+};
+
+class LinksWidget : public QFrame, public Ui::DetailsLinks
+{
+public:
+    LinksWidget( QWidget *parent=0 );
+};
+
+class DatabaseWidget : public QFrame, public Ui::DetailsDatabase
+{
+public:
+    DatabaseWidget( QWidget *parent=0 );
+};
+
+class LogWidget : public QFrame, public Ui::DetailsLog
+{
+public:
+    LogWidget( QWidget *parent=0 );
+};
+#endif
+
+#endif
Index: skymap.cpp
===================================================================
--- skymap.cpp	(revision 1062995)
+++ skymap.cpp	(working copy)
 <at>  <at>  -44,11 +44,17  <at>  <at> 
 #include "imageviewer.h"
 #include "dialogs/detaildialog.h"
 #include "dialogs/addlinkdialog.h"
+#include "dialogs/objectlist.h"
 #include "kspopupmenu.h"
 #include "simclock.h"
 #include "skyobjects/skyobject.h"
 #include "skyobjects/ksplanetbase.h"
 #include "widgets/infoboxwidget.h"
+#include "skycomponents/skymesh.h"
+#include "skycomponents/skycomponent.h"
+#include "skycomponents/starcomponent.h"
+#include "skycomponents/deepskycomponent.h"
+#include "skyobjects/starobject.h"
 
 #ifdef HAVE_XPLANET
 #include <KProcess>
 <at>  <at>  -684,7 +690,8  <at>  <at> 
         KMessageBox::sorry( this, i18n("No object selected."), i18n("Object Details") );
         return;
     }
-    DetailDialog* detail = new DetailDialog( clickedObject(), data->ut(), data->geo(), KStars::Instance() );
+    //DetailDialog* detail = new DetailDialog( clickedObject(), data->ut(), data->geo(), KStars::Instance() );
+    SkyObjectList* detail = new SkyObjectList( clickedObject(), data->ut(), data->geo(), KStars::Instance() );
     detail->setAttribute(Qt::WA_DeleteOnClose);
     detail->show();
 }
 <at>  <at>  -1561,6 +1568,125  <at>  <at> 
     return p.x() < -100000.0;
 }
 
+void SkyMap::showObjectsInRectangle()
+{
+    if( (secondRClickPos-firstRClickPos).manhattanLength() < QApplication::startDragDistance() )
+    {
+        if( clickedObject() )
+        {
+        // Rightclick release happened within the drag limits
+        // Got to populate info about a single clicked object
+            clickedObject()->showPopupMenu( pmenu, QCursor::pos() );
+            kDebug() << "clicked object is non-null" << endl;
+        }
+	else
+	{
+            // Rightclick release happened within the drag limits
+            // Got to populate info with unknown object since there was
+            // no clicked object in the region
+            SkyObject object( 
+                        SkyObject::TYPE_UNKNOWN, 
+                        clickedPoint()->ra()->Hours(), 
+                        clickedPoint()->dec()->Degrees() );
+            
+            pmenu->createEmptyMenu( &object );
+            pmenu->popup( QCursor::pos() );
+	}
+    }
+    else
+    {
+	SkyMesh* skymesh = SkyMesh::Instance();
+        // "firstPoint" and "secondPoint" act as reference skypoints.
+        // In order to form a virtual rectangle using the two, the other 2 vertices of
+        // rectangle have to be found. For skypoints, the (x,y) are determined by
+        // the Right ascension (RA) and Declinations.
+        // Find the Point3(RA, Dec) and Point4(RA, Dec) 
+        dms thirdRA(secondPoint.ra()->Degrees()), thirdDec(firstPoint.dec()->Degrees());
+        dms fourthRA(firstPoint.ra()->Degrees()), fourthDec(secondPoint.dec()->Degrees());
+        SkyPoint thirdPoint(thirdRA, thirdDec), fourthPoint( fourthRA, fourthDec );
+        
+        // The skylist below is a QVector<SkyPoint*>'s instance 
+        // Stores the skypoints of virtual rectangle in that order
+        // i.e. the following:
+        // 
+        //       firstPoint  .______________. thirdPoint
+        //                   |              |
+        //                   |              |
+        //      fourthPoint  .______________. secondPoint
+        //
+        SkyList skylist;
+        skylist.push_back( &firstPoint );
+        skylist.push_back( &thirdPoint );
+        skylist.push_back( &secondPoint );
+        skylist.push_back( &fourthPoint );
+        
+        // 
+        const IndexHash& indexHash = skymesh->indexPoly( &skylist );
+        
+        // If the list of stars is non-empty, empty it first before refilling
+        KStars* stars = KStars::Instance();
+        stars->objectList()->removeAll();
+        
+        for( IndexHash::const_iterator iter = indexHash.constBegin(); 
+            iter != indexHash.constEnd(); 
+            iter++ )
+        {
+            Trixel trixel = iter.key();
+            StarComponent* starComponent = StarComponent::Instance();
+            
+            if( starComponent )
+            {
+                StarList* starList = starComponent->starsInTrixel( trixel );
+                if( starList )
+                {
+                    for( int i = 0; i < starList->size(); i++ )
+                    {
+                        StarObject* currentStar = starList->at( i );
+                        if( !currentStar )
+                            continue;
+                        
+                        if( currentStar->name() != QString("star") )
+                            // Add the star to the list to be shown
+                            stars->objectList()->addObject( currentStar );
+                    }
+                }
+            }
+
+	    DeepSkyList* dsoList = data->skyComposite()->deepSkyComponent()->objectListInTrixel( trixel );
+	    if( dsoList )
+	    {
+	        for( QVector<DeepSkyObject*>::iterator dso = dsoList->begin();
+		     dso != dsoList->end();
+		     dso++ )
+		{
+		    DeepSkyObject* dsClone = (*dso)->clone();
+		    stars->objectList()->addObject( dsClone );
+		}
+	    }
+        }
+            
+        // Display the list that was formed from the iterations above
+        // If no sky objects are found, the list will be empty
+        stars->objectList()->show();
+        
+	// FIXME: The following block of code is for showing the rectangle formed
+	// by the right-button drag of the mouse. Although, the rectangle
+	// is getting properly painted with dotted line, immediately thereafter
+	// SkyMap::paintEvent() is getting triggered because of which the
+	// painted rectangle vanishes off. Got to find out a way for this!!!
+        
+	repaint();
+	QApplication::flush();
+	QPainter painter;
+        setAttribute(Qt::WA_PaintOutsidePaintEvent,true );
+        painter.begin( this );
+        QColor color = data->colorScheme()->colorNamed( "BoxHighlightColor" );
+        painter.setPen( QPen(QBrush(color), 1, Qt::DotLine ) );
+        painter.drawRect( QRectF( firstRClickPos, secondRClickPos ) );
+        painter.end();
+    }
+}
+
 #ifdef HAVE_XPLANET
 void SkyMap::startXplanet( const QString & outputFile ) {
     QString year, month, day, hour, minute, seconde, fov;
Index: kstarsdata.h
===================================================================
--- kstarsdata.h	(revision 1062995)
+++ kstarsdata.h	(working copy)
 <at>  <at>  -90,6 +90,7  <at>  <at> 
     friend class DetailDialog;
     // FIXME: uses geoList and changes it.
     friend class LocationDialog;
+    friend class SkyObjectList;
 
     static KStarsData* Create( );
 
Index: skymap.h
===================================================================
--- skymap.h	(revision 1062995)
+++ skymap.h	(working copy)
 <at>  <at>  -24,6 +24,7  <at>  <at> 
 
 #include "skyobjects/skypoint.h"
 #include "skyobjects/skyline.h"
+#include "dialogs/objectlist.h"
 
 #include <config-kstars.h>
 
 <at>  <at>  -467,6 +468,8  <at>  <at> 
     	*/
     void drawObjectLabels( QList<SkyObject*>& labelObjects, QPainter &psky );
 
+    void showObjectsInRectangle();
+
 public slots:
     //DEBUG_KIO_JOB
     void slotJobResult( KJob *j );
 <at>  <at>  -864,6 +867,8  <at>  <at> 
     SkyPoint  Focus, ClickedPoint, FocusPoint, MousePoint, Destination;
     SkyObject *ClickedObject, *FocusObject, *TransientObject;
 
+    SkyObjectList* skyObjectList;
+
     SkyLine AngularRuler; //The line for measuring angles in the map
     QRect ZoomRect; //The manual-focus circle.
 
 <at>  <at>  -880,6 +885,12  <at>  <at> 
     //QUATERNION
     Quaternion m_rotAxis;
 
+    // To record the first and second right click positions 
+    // and their corresponding sky points to find the starlist
+    // in the rectangle formed
+    QPointF firstRClickPos, secondRClickPos;
+    SkyPoint firstPoint, secondPoint;
+
     static SkyMap* pinstance;
 
 };
Index: kstars.h
===================================================================
--- kstars.h	(revision 1062995)
+++ kstars.h	(working copy)
 <at>  <at>  -25,6 +25,7  <at>  <at> 
 #include "tools/observinglist.h"
 #include "comast/equipmentwriter.h"
 #include "comast/observeradd.h"
+#include "dialogs/objectlist.h"
 
 // forward declaration is enough. We only need pointers
 class QPalette;
 <at>  <at>  -125,6 +126,8  <at>  <at> 
 
     ObservingList* observingList() { return obsList; }
 
+    SkyObjectList* objectList() { return skyObjectList; }
+
     Execute* getExecute();
 
     /** <at> return pointer to the INDI driver
 <at>  <at>  -660,6 +663,7  <at>  <at> 
 
     //FIXME: move to KStarsData
     ObservingList *obsList;
+    SkyObjectList* skyObjectList;
     EquipmentWriter *eWriter;
     ObserverAdd *oAdd;
     Execute *execute;
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 1062995)
+++ CMakeLists.txt	(working copy)
 <at>  <at>  -276,6 +276,7  <at>  <at> 
   dialogs/focusdialog.cpp
   dialogs/fovdialog.cpp
   dialogs/locationdialog.cpp
+  dialogs/objectlist.cpp
   dialogs/timedialog.cpp
 )
 
 <at>  <at>  -291,6 +292,7  <at>  <at> 
   dialogs/focusdialog.ui
   dialogs/fovdialog.ui
   dialogs/locationdialog.ui
+  dialogs/objectlist.ui
   dialogs/wizwelcome.ui
   dialogs/wizlocation.ui
   dialogs/wizdownload.ui
Index: skymapevents.cpp
===================================================================
--- skymapevents.cpp	(revision 1062995)
+++ skymapevents.cpp	(working copy)
 <at>  <at>  -613,7 +613,32  <at>  <at> 
         zoomOutOrMagStep( e->modifiers() );
 }
 
-void SkyMap::mouseReleaseEvent( QMouseEvent * ) {
+void SkyMap::mouseReleaseEvent( QMouseEvent * e ) {
+    if ( e->button() == Qt::RightButton ) {
+        kDebug() << "right click position after drag = " << QCursor::pos() << endl;
+	secondRClickPos = QCursor::pos();
+
+	// The new point after drag has to be recorded and saved for future use
+        setMousePoint( fromScreen( e->pos(), data->lst(), data->geo()->lat() ) );
+        mousePoint()->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
+        setClickedPoint( mousePoint() );
+        clickedPoint()->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
+	secondPoint = ClickedPoint;
+
+	//
+	// Once the first and second points (before and after drag respectively) 
+	// have been successfully recorded, show the sky objects formed in the rectangle 
+	// If the first and second points are the same, the information about that
+	// sky point has to be shown in popup menu; otherwise an attempt has to be
+	// made to find all the sky objects in the virtual rectangle formed by the 
+	// first and second skypoints. showObjectsInRectangle() function takes care 
+	// of both these scenarios.
+	//
+	showObjectsInRectangle();
+        
+	return;
+    }
+
     if ( ZoomRect.isValid() ) {
         //Zoom in on center of Zoom Circle, by a factor equal to the ratio
         //of the sky pixmap's width to the Zoom Circle's diameter
 <at>  <at>  -686,6 +711,11  <at>  <at> 
         setClickedPoint( mousePoint() );
         clickedPoint()->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
 
+	// Store this skypoint for future use 
+	// in case mouse is right-click dragged 
+	firstPoint = ClickedPoint;
+
+
         //Find object nearest to clickedPoint()
         double maxrad = 1000.0/Options::zoomFactor();
         setClickedObject( data->skyComposite()->objectNearest( clickedPoint(), maxrad ) );
 <at>  <at>  -693,8 +723,10  <at>  <at> 
         if ( clickedObject() ) {
             setClickedPoint( clickedObject() );
 
+            kDebug() << "moving the showing of popup menu from mousePressEvent() to mouseReleaseEvent()" << endl;
             if ( e->button() == Qt::RightButton ) {
-                clickedObject()->showPopupMenu( pmenu, QCursor::pos() );
+		firstRClickPos = QCursor::pos();
+                kDebug() << "first right click position before drag = " << firstRClickPos << endl;
             }
 
             if ( kstars && e->button() == Qt::LeftButton ) {
 <at>  <at>  -711,9 +743,8  <at>  <at> 
                     kstars->statusBar()->changeItem( i18n( "Empty sky" ), 0 );
                 break;
             case Qt::RightButton: {
-                SkyObject o( SkyObject::TYPE_UNKNOWN, clickedPoint()->ra()->Hours(), clickedPoint()->dec()->Degrees() );
-                pmenu->createEmptyMenu( &o );
-                pmenu->popup( QCursor::pos() );
+		firstRClickPos = QCursor::pos();
+                kDebug() << "first right click position before drag = " << firstRClickPos << endl;
                 break;
                 }
             default: ;
Index: skycomponents/deepskycomponent.h
===================================================================
--- skycomponents/deepskycomponent.h	(revision 1062995)
+++ skycomponents/deepskycomponent.h	(working copy)
 <at>  <at>  -122,6 +122,8  <at>  <at> 
 
     virtual SkyObject* objectNearest( SkyPoint *p, double &maxrad );
     QList<DeepSkyObject*>& objectList() { return m_DeepSkyList; }
+    
+    DeepSkyList* objectListInTrixel( Trixel trixel ) const;
 
     void clear();
 
Index: skycomponents/starcomponent.cpp
===================================================================
--- skycomponents/starcomponent.cpp	(revision 1062995)
+++ skycomponents/starcomponent.cpp	(working copy)
 <at>  <at>  -649,6 +649,12  <at>  <at> 
     stardata->mag = bswap_16( stardata->mag );
     stardata->bv_index = bswap_16( stardata->bv_index );
 }
+
+StarList* StarComponent::starsInTrixel( Trixel trixel )
+{
+    return m_starIndex->at( trixel );
+}
+
 /*
 void StarComponent::printDebugInfo() {
 
Index: skycomponents/deepskycomponent.cpp
===================================================================
--- skycomponents/deepskycomponent.cpp	(revision 1062995)
+++ skycomponents/deepskycomponent.cpp	(working copy)
 <at>  <at>  -197,6 +197,9  <at>  <at> 
         }
 
         Trixel trixel = m_skyMesh->index( (SkyPoint*) o );
+	// Append the DeepSkyObject to m_DeepSkyIndex regardless
+	// of types. 
+	appendIndex( o, &m_DeepSkyIndex, trixel );
 
         //Assign object to general DeepSkyObjects list,
         //and a secondary list based on its catalog.
 <at>  <at>  -289,6 +292,10  <at>  <at> 
     dsIndex->value( trixel )->append( o );
 }
 
+DeepSkyList* DeepSkyComponent::objectListInTrixel( Trixel trixel ) const
+{
+    return (m_DeepSkyIndex.contains( trixel )? m_DeepSkyIndex.value( trixel ) : NULL);
+}
 
 void DeepSkyComponent::draw( QPainter& psky )
 {
Index: skycomponents/skymapcomposite.h
===================================================================
--- skycomponents/skymapcomposite.h	(revision 1062995)
+++ skycomponents/skymapcomposite.h	(working copy)
 <at>  <at>  -199,6 +199,8  <at>  <at> 
 
     QList<SkyComponent*> customCatalogs();
 
+    DeepSkyComponent* deepSkyComponent() const { return m_DeepSky; }
+
 signals:
     void progressText( const QString &message );
 
Index: skycomponents/starcomponent.h
===================================================================
--- skycomponents/starcomponent.h	(revision 1062995)
+++ skycomponents/starcomponent.h	(working copy)
 <at>  <at>  -167,6 +167,8  <at>  <at> 
     // deepStarData fields
     static void byteSwap( starData *stardata );
 
+    StarList* starsInTrixel( Trixel trixel );
+
 private:
     SkyMesh*       m_skyMesh;
     StarIndex*     m_starIndex;
_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel
THEMIS ORAIOP | 1 Feb 20:32
Picon
Favicon

Bugs

Hello,
my name is Efthymis Oraiopoulos and I am studying Informatics at Aristotle University of Thessaloniki, Greece.
Due to software engineer lesson, I have to contribute to an open source software program, by finding bugs.
I found the following in KStars:
1)    223542
2)    223558
3)    223559
4)    223562
5)    223565
6)    223566
7)    223900
8)    223901
9)    223909

it would be nice if you can check them and confirm them (or not), so I can verify my University-exercise.

Thank you very much.

__________________________________________________
Χρησιμοποιείτε Yahoo!;
Βαρεθήκατε τα ενοχλητικά μηνύματα (spam); Το Yahoo! Mail διαθέτει την καλύτερη δυνατή προστασία κατά των ενοχλητικών μηνυμάτων
http://mail.yahoo.gr
_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel
Khudyakov Alexey | 1 Feb 23:57
Picon
Gravatar

Re: Refined patch for wishlist 178232: List all objects within a rectangle

В сообщении от Понедельник 01 февраля 2010 21:45:34 Abhijit Apte написал:
> Hi Alexey/Akarsh,
> 
> On Mon, Feb 1, 2010 at 2:21 PM, Abhijit Apte <abhijit.apte <at> gmail.com> wrote:
> > I've implemented a draft of the implementation of combining the list
> > functionality along-side the detail dialog. So in essence, we'll have
> > only one dialog which will operate in two modes -- Detailed and Summary.
> > 1) When a popup menu is invoked on a sky object and "Details..." option
> > is selected from the popup menu, the detail dialog will open in
> > "Detailed" mode by default. User has the option to switch to the
> > "Summary" view also. 2) When a right-click drag selection happens, the
> > objects from the rectangle are shown in the detail dialog. This time, the
> > detail dialog will open in "Summary" mode.
> 
> Here's the patch, I managed to fix most of the bugs I noticed while
>  testing. Right now, I've not modified DetailDialog
>  (dialogs/detaildialog.cpp and dialogs/detaildialog.h) and instead merged
>  (copied) all of its code into dialogs/objectlist.cpp and
>  dialogs/objectlist.h
> Pl. review and apply the patch and suggest me if you've any comments.
> 

1. Patch fails to apply cleanly to current svn head. Please update it. Also 
compilation fails so I cannot try your last patch.

2. Current convention is to use 4 space for indentation and do not use tabs at 
all. Please fix it.

3. Currently you search for objects in skymap.cpp. I think it outright bad 
design. You have to enumerate all components by hands. This is error prone and 
changes in skycomponents are likely break your code. 

I think better solution is to add function to SkyComponent to search for 
objects and use virtual dispatch. Here is some example code. 

-- Code snippet ---

class SkyComponent {
public:
    // Function which returns list of objects in given area.
    QList<SkyObject*> findObjectInArea(Area area)  {
        QList<SkyObject*> list;
        objectsInArea(list, area)
        return list;
    }
private:
    // This is worker function. It adds objects to list if they are in the
    // area. It should be reimplemented in subclasses.
    virtual void objectsInArea(QList<SkyObject*>&, Area);
};
----------------

4. Are there code from DetailsDialog in the SkyObjectList? If it's the case 
just drop it. It's completely fine to have missing functionality for some time 
and add it gradually. It's much easier to reason about code that way. 

5. Patch is huge. It would be nice if you split it into several smaller ones. 
More below.

== Workflow

Here is some suggestion about workflow you might fin useful. In my experience 
it's quite difficult to write big feature in one big patch. Usually it could be 
separated in many smaller patches. Also it's difficult to review big patch with 
many changes. 

I know two tools which allows to work with multiple patches.

* Mercurial queues. It allows to work on stack of patches. One can 
add/remove/change/rearrange patches and constantly update patches againist svn 
head. Very handy if you mostly work on one feature.

* git-svn. It's easier to work on multiple features (git's branches are 
wonderful) but harder to change locally commited patch. Also it's still 
possible. 
_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel
Abhijit Apte | 2 Feb 08:54
Picon

Re: Refined patch for wishlist 178232: List all objects within a rectangle

Hi Alexey,

Thanks so much for your detailed comments, will look into them when I find time.

I know two tools which allows to work with multiple patches.

* Mercurial queues. It allows to work on stack of patches. One can
add/remove/change/rearrange patches and constantly update patches againist svn
head. Very handy if you mostly work on one feature.

I know of hg but have never tried it out so far. :-)
 
* git-svn. It's easier to work on multiple features (git's branches are
wonderful) but harder to change locally commited patch. Also it's still
possible.

Yeah, git is very good compared to svn, hope KDE moves all its repos to git very soon :D

Rgds
-Abhi
_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel
Yiannis Belias | 2 Feb 11:46
Picon

Exporting to video

Hi all,
  Just FYI. Yesterday I made a video simulation[0] of the upcoming lunar occultation of pleiades
for my local astronomy club. So I used ktars and I'd like to share a few things with you.

1. I used the script builder for start, but I found out I would have to use a more "spiced up"
shell script[attatched] for this job. (To tell the truth, I was expecting something more javascript like...)
2. I had to use for loops with explicit dates to increase the time interval. It would be much
better if I could just step forward for a specified time step.
3. I found out that when the kstars window was smaller than the capture window, the output
frames were blank[white] at that region. (Don't scratch your heads - *netbook* :) )
4. The whole process of creating about 1000 frames is really slow.
5. I didn't find a way to display the time/date info from within kstars, so I used the convert
utility from imagemagick.
6. The stars motion as you can see on the video is a bit "funky" :) I had antialiasing
switched off though.

I don't know if kstars was made with exporting videos in mind, but it actually worked!
So, thank's for a great program :)

Cheers!
Yiannis

[0] http://www.youtube.com/watch?v=zjsxu1bSbXE

--
Yiannis Belias  <jonnyb <at> hol.gr>                    `
Homepage [http://users.hol.gr/~jonnyb/video] '              .
GNU+LINUX:                                            '           '
IN A WORLD WITHOUT FENCES WHO NEEDS GATES?      .                     *
Attachment (moon_occultation.kstars): application/x-shellscript, 1254 bytes
_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel
Abhijit Apte | 2 Feb 20:40
Picon

Re: Refined patch for wishlist 178232: List all objects within a rectangle

Hi Alexey,

My comments inlined.

1. Patch fails to apply cleanly to current svn head. Please update it. Also
compilation fails so I cannot try your last patch.

Attached updated patch (this compiles this against the svn head -- commit 1083977). I think you/somebody have committed some changes into dialogs/detaildialog.cpp which were to be pull into dialogs/objectlist.cpp.

2. Current convention is to use 4 space for indentation and do not use tabs at
all. Please fix it.

Sure, would take care of it next time onward, actually problem is with 'set autoindent' and 'set cindent' of vim. :-(
 
3. Currently you search for objects in skymap.cpp. I think it outright bad
design. You have to enumerate all components by hands. This is error prone and
changes in skycomponents are likely break your code.

So, are you suggesting to distribute (move) the code which does the searching of objects to the respective components (i.e. the worker function you suggested below)?
 
I think better solution is to add function to SkyComponent to search for
objects and use virtual dispatch. Here is some example code.

-- Code snippet ---

class SkyComponent {
public:
   // Function which returns list of objects in given area.
   QList<SkyObject*> findObjectInArea(Area area)  {
       QList<SkyObject*> list;
       objectsInArea(list, area)
       return list;
   }
private:
   // This is worker function. It adds objects to list if they are in the
   // area. It should be reimplemented in subclasses.
   virtual void objectsInArea(QList<SkyObject*>&, Area);
};
----------------
 
Even if we implemented the way you've suggest, we'll still have to invoke the findObjectInArea() for each component (like StarComponent, DeepSkyComponent etc -- see below) from skymap.cpp right??

StarComponent* starComp;
StarList listOfStars = starComp->findObjectInArea(myarea);
DeepSkyComponent* deepSkyComp;
QList<DeepSkyObject*> listOfDSO = deepSkyComp->findObjectInArea(myarea);
//.. similarly for planets, etc???

Pl. shed more light on point#3 as this is little unclear to me. :P

4. Are there code from DetailsDialog in the SkyObjectList? If it's the case
just drop it. It's completely fine to have missing functionality for some time
and add it gradually. It's much easier to reason about code that way.

Yes, absolutely! Since, the detailed tabbed representation was to be merged with the list view (as per your earlier comments), I had to merge the entire code of DetailsDialog (detailsdialog.cpp and detailsdialog.h) into SkyObjectList (objectlist.cpp and objectlist.h).

The reason I did this was, going further, deprecate the existing detaildialog.* with objectlist.* and rename the latter SkyObjectList to DetailDialog.

5. Patch is huge. It would be nice if you split it into several smaller ones.
More below.

Yeah agree, didn't want to make it this huge, but as I went on making changes, realized there were far too many files that I had to modify than actually thought. :-)
 
Rgds
-Abhi
Index: colorscheme.cpp
===================================================================
--- colorscheme.cpp	(revision 1084185)
+++ colorscheme.cpp	(working copy)
 <at>  <at>  -72,6 +72,7  <at>  <at> 
     appendItem("AngularRuler",     i18n("Angular Distance Ruler"), "#445566");
     appendItem("ObsListColor",     i18n("Observing List Label"),   "#FF0000");
     appendItem("SatColor",         i18n("Satellite Track"),        "#007777");
+    appendItem("BoxHighlightColor",i18n("Box highlight color"),    "#EFF5FB");
 
     //Load colors from config object
     loadFromConfig();
Index: kstarsinit.cpp
===================================================================
--- kstarsinit.cpp	(revision 1084185)
+++ kstarsinit.cpp	(working copy)
 <at>  <at>  -531,6 +531,12  <at>  <at> 
     eWriter = new EquipmentWriter();
     oAdd = new ObserverAdd;
 
+    // Initialize the sky object list
+#if 0
+    skyObjectList = new SkyObjectList( this );
+#endif
+    skyObjectList = new SkyObjectList( NULL, data()->ut(), data()->geo(), this );
+
     //Do not start the clock if "--paused" specified on the cmd line
     if ( StartClockRunning )
         data()->clock()->start();
Index: dialogs/objectlist.cpp
===================================================================
--- dialogs/objectlist.cpp	(revision 0)
+++ dialogs/objectlist.cpp	(revision 0)
 <at>  <at>  -0,0 +1,1271  <at>  <at> 
+#include <KLocale>
+
+#include <QStandardItemModel>
+#include <QSortFilterProxyModel>
+
+#include <QLineEdit>
+#include <QPixmap>
+#include <QRegExp>
+#include <QTextStream>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QTreeWidgetItem>
+
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <kpushbutton.h>
+#include <klineedit.h>
+#include <ktoolinvocation.h>
+#include <ktemporaryfile.h>
+#include <kio/netaccess.h>
+
+#include "kstars.h"
+#include "kstarsdata.h"
+#include "kstarsdatetime.h"
+#include "geolocation.h"
+#include "ksutils.h"
+#include "skymap.h"
+#include "skyobjects/skyobject.h"
+#include "skyobjects/starobject.h"
+#include "skyobjects/deepskyobject.h"
+#include "skyobjects/ksplanetbase.h"
+#include "skyobjects/ksmoon.h"
+#include "thumbnailpicker.h"
+#include "Options.h"
+#include "objectlist.h"
+#include "detaildialog.h"
+
+#include <config-kstars.h>
+
+#ifdef HAVE_INDI_H
+#include "indi/indielement.h"
+#include "indi/indiproperty.h"
+#include "indi/indidevice.h"
+#include "indi/indimenu.h"
+#include "indi/devicemanager.h"
+#include "indi/indistd.h"
+#endif
+
+#include "skycomponents/constellationboundarylines.h"
+#include "skycomponents/skymapcomposite.h"
+
+SkyObjectList::SkyObjectList( 
+                       SkyObject* o, 
+                       const KStarsDateTime& _dt,
+                       GeoLocation* _geo,
+                       KStars* _ks )
+                      : KPageDialog( (QWidget*)_ks ),
+                        selectedObject( o ),
+                        ut(_dt),
+                        geo(_geo),
+		        ks( _ks ),
+                        Data( NULL ),
+                        Pos( NULL ),
+			Links( NULL ),
+			Adv( NULL ),
+			Log( NULL )
+{
+    QWidget* widget = new QWidget( this );
+    ui.setupUi( widget );
+
+    setMainWidget( widget );
+
+    setCaption( i18n( "Sky objects' list" ) );
+    //setButtons( KDialog::Ok | KDialog::Cancel );
+    setButtons( KDialog::Close );
+    
+    pageWidget = new KPageWidget( ui.framePage );
+    pageWidget->setFaceType( KPageView::Tabbed );
+    pageWidget->setBackgroundRole( QPalette::Base );
+    
+    titlePalette = pageWidget->palette();
+    titlePalette.setColor( backgroundRole(), pageWidget->palette().color( QPalette::Active, QPalette::Highlight ) );
+    titlePalette.setColor( foregroundRole(), pageWidget->palette().color( QPalette::Active, QPalette::HighlightedText ) );
+
+    //Create thumbnail image
+    Thumbnail = new QPixmap( 200, 200 );
+
+    m_Model = new QStandardItemModel( 0, 5, this );
+    m_Model->setHorizontalHeaderLabels( QStringList() << i18n( "Name" )
+            << i18nc( "Right Ascension", "RA" ) << i18nc( "Declination", "Dec" )
+	            << i18nc( "Magnitude", "Mag" ) << i18n( "Type" ) );
+    m_SortModel = new QSortFilterProxyModel( this );
+    m_SortModel->setSourceModel( m_Model );
+    m_SortModel->setDynamicSortFilter( true );
+
+    ui.comboBoxObjects->setModel( m_Model );
+
+    ui.tableView->setModel( m_SortModel );
+    ui.tableView->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding ) );
+    ui.tableView->setSelectionMode( QAbstractItemView::SingleSelection );
+    ui.tableView->setEditTriggers( QAbstractItemView::NoEditTriggers );
+    ui.tableView->horizontalHeader()->setStretchLastSection( true );
+    ui.tableView->horizontalHeader()->setResizeMode( QHeaderView::ResizeToContents );
+    
+    if( selectedObject )
+    {
+	addObject( selectedObject );
+	ui.radioButtonDetailed->setChecked( true );
+        createGeneralTab();
+        createPositionTab( ut, geo );
+        createLinksTab();
+        createAdvancedTab();
+        createLogTab();
+	//showDetails( Qt::Checked );
+	showDetails( true );
+	//pageWidget->show();
+    }
+    else
+        ui.radioButtonDetailed->setChecked( false );
+
+    connect( ui.tableView, SIGNAL( doubleClicked( const QModelIndex& ) ),
+             this, SLOT( slotCenterObject() ) );
+    connect( ui.tableView->selectionModel(),
+            SIGNAL( selectionChanged(const QItemSelection&, const QItemSelection&) ),
+            this, SLOT( slotNewSelection() ) );
+    
+    connect( ui.comboBoxObjects, 
+             SIGNAL( currentIndexChanged(int) ), 
+	     this, SLOT( comboBoxIndexChanged( int ) ) );
+    
+    connect( ui.radioButtonDetailed,
+             SIGNAL( clicked(bool) ),
+	     this, SLOT( showDetails( bool ) ) );
+    
+    connect( ui.radioButtonSummary,
+             SIGNAL( clicked(bool) ),
+	     this, SLOT( showSummary( bool ) ) );
+    
+}
+
+void SkyObjectList::addObject( SkyObject* obj )
+{
+    m_ObjectList.append( obj );
+    selectedObject = obj;
+    SkyPoint p = obj->recomputeCoords( ut, geo );
+    QString smag = "--";
+    if (  - 30.0 < obj->mag() && obj->mag() < 90.0 ) smag = QString::number( obj->mag(), 'g', 2 ); // The lower limit to avoid display of unrealistic comet magnitudes
+
+    QList<QStandardItem*> itemList;
+    itemList << new QStandardItem( obj->translatedName() )
+             << new QStandardItem( p.ra()->toHMSString() )
+	     << new QStandardItem( p.dec()->toDMSString() )
+	     << new QStandardItem( smag )
+	     << new QStandardItem( obj->typeName() );
+    
+    m_Model->appendRow( itemList );
+    ui.tableView->resizeColumnsToContents();
+}
+
+void SkyObjectList::addObject( DeepSkyObject*& obj )
+{
+    m_ObjectList.append( obj );
+    selectedObject = obj;
+    SkyPoint p = obj->recomputeCoords( ut, geo );
+    QString smag = "--";
+    if (  - 30.0 < obj->mag() && obj->mag() < 90.0 ) smag = QString::number( obj->mag(), 'g', 2 ); // The lower limit to avoid display of unrealistic comet magnitudes
+
+    QList<QStandardItem*> itemList;
+    itemList << new QStandardItem( obj->translatedName() )
+             << new QStandardItem( p.ra()->toHMSString() )
+	     << new QStandardItem( p.dec()->toDMSString() )
+	     << new QStandardItem( smag )
+	     << new QStandardItem( obj->typeName() );
+    
+    m_Model->appendRow( itemList );
+    ui.tableView->resizeColumnsToContents();
+}
+
+void SkyObjectList::removeAll()
+{
+    kDebug() << "model rowcount = " << m_Model->rowCount() << endl;
+    m_SortModel->removeRows(0,m_SortModel->rowCount());
+    m_Model->removeRows(0,m_Model->rowCount());
+    m_SortModel->setSourceModel( m_Model );
+    ui.tableView->selectionModel()->clear();
+    ui.tableView->clearSelection();
+    ui.tableView->resizeColumnsToContents();
+    m_ObjectList.clear();
+    selectedObject = NULL;
+}
+
+SkyObjectList::~SkyObjectList()
+{
+}
+
+void SkyObjectList::slotNewSelection()
+{
+    QString newName;
+    QModelIndexList selectedItems = m_SortModel->mapSelectionToSource( ui.tableView->selectionModel()->selection() ).indexes();
+    //When one object is selected
+    if ( selectedItems.size() == m_Model->columnCount() ) 
+    {
+        newName = selectedItems[0].data().toString();
+        kDebug() << "selected row is " << selectedItems[0].row() << endl; 
+	kDebug() << "source row is " << m_SortModel->mapToSource( selectedItems[0] ).row() << endl;
+	ui.comboBoxObjects->setCurrentIndex( selectedItems[0].row() );
+        //Find the selected object in the obsList,
+        //then break the loop.  Now obsList.current()
+        //points to the new selected object (until now it was the previous object)
+        SkyObject* o;
+        foreach ( o, objectList() ) 
+        {
+            if ( o->translatedName() == newName ) 
+            {
+                selectedObject = o;
+	        if( ui.radioButtonDetailed->isChecked() )
+	            showDetails( true );
+		//cleanupDetailView();
+                break;
+            }
+        }
+    }
+}
+
+void SkyObjectList::cleanupDetailView()
+{
+    kDebug() << Q_FUNC_INFO << endl;
+    while( pageWidget->currentPage() )
+        pageWidget->removePage(pageWidget->currentPage());
+    delete pageWidget;
+    //delete Data; delete Pos; delete Links; delete Adv; delete Log;
+    Data = NULL; Pos = NULL; Links = NULL; Adv = NULL; Log = NULL;
+    pageWidget = new KPageWidget( ui.framePage );
+    pageWidget->setFaceType( KPageView::Tabbed );
+    pageWidget->setBackgroundRole( QPalette::Base );
+}
+
+void SkyObjectList::comboBoxIndexChanged( int _index )
+{
+    QComboBox* comboBox = qobject_cast<QComboBox*>(sender());
+    QModelIndex itemToSelect = m_SortModel->mapFromSource( comboBox->model()->index( _index, 0 ) );
+    ui.tableView->setCurrentIndex( itemToSelect );
+
+    QString newName = comboBox->itemData(_index).toString();
+    
+    SkyObject* o;
+    foreach ( o, objectList() ) 
+    {
+        if ( o->translatedName() == newName ) 
+        {
+            selectedObject = o;
+	    //cleanupDetailView();
+	    if( ui.radioButtonDetailed->isChecked() )
+	        showDetails( true );
+            break;
+        }
+    }
+}
+
+void SkyObjectList::showDetails( bool state )
+{
+    kDebug() << Q_FUNC_INFO << endl;
+    if( state )
+    {
+        kDebug() << "state is checked!" << endl;
+        ui.tableView->setVisible( false );
+	ui.radioButtonSummary->setChecked( false );
+	cleanupDetailView();
+        if( selectedObject )
+        {
+            createGeneralTab();
+            createPositionTab( ut, geo );
+            createLinksTab();
+            createAdvancedTab();
+            createLogTab();
+            pageWidget->show();
+        }
+    }
+    else if( state == Qt::Unchecked )
+    {
+        ui.tableView->setVisible( true );
+	ui.radioButtonSummary->setChecked( true );
+	pageWidget->hide();
+        kDebug() << "state is unchecked!" << endl;
+    }
+}
+
+void SkyObjectList::showSummary( bool state )
+{
+    showDetails( !state );
+}
+
+void SkyObjectList::slotCenterObject() 
+{
+    ks->map()->setClickedObject( currentObject() );
+    ks->map()->setClickedPoint( currentObject() );
+    ks->map()->slotCenter();
+    //pageWidget->show();
+}
+
+void SkyObjectList::createGeneralTab()
+{
+    if( Data )
+        return;
+    Data = new DataWidget(pageWidget);
+    pageWidget->addPage( Data, i18n("General") );
+
+    Data->Names->setPalette( titlePalette );
+
+    //Connections
+    connect( Data->ObsListButton, SIGNAL( clicked() ), this, SLOT( addToObservingList() ) );
+    connect( Data->CenterButton, SIGNAL( clicked() ), this, SLOT( centerMap() ) );
+    #ifdef HAVE_INDI_H
+    connect( Data->ScopeButton, SIGNAL( clicked() ), this, SLOT( centerTelescope() ) );
+    #else
+    Data->ScopeButton->setEnabled(false);
+    #endif
+    connect( Data->Image, SIGNAL( clicked() ), this, SLOT( updateThumbnail() ) );
+
+    Data->IllumLabel->setVisible( false );
+
+    //Show object thumbnail image
+    showThumbnail();
+
+    //Fill in the data fields
+    //Contents depend on type of object
+    StarObject *s = 0L;
+    DeepSkyObject *dso = 0L;
+    KSPlanetBase *ps = 0L;
+    QString pname, oname, objecttyp, constellationname;
+
+    switch ( selectedObject->type() ) {
+    case SkyObject::STAR:
+        s = (StarObject *)selectedObject;
+
+        Data->Names->setText( s->longname() );
+
+        if( s->getHDIndex() != 0 ) {
+            if( !s->longname().isEmpty() )
+                Data->Names->setText( s->longname() + QString( ", HD%1" ).arg( QString::number( s->getHDIndex() ) ) );
+            else
+                Data->Names->setText( QString( ", HD%1" ).arg( QString::number( s->getHDIndex() ) ) );
+        }
+        objecttyp = s->sptype() + ' ' + i18n("star");
+        Data->Magnitude->setText( i18nc( "number in magnitudes", "%1 mag" ,
+                                         KGlobal::locale()->formatNumber( s->mag(), 1 ) ) );  //show to tenths place
+
+        //The thumbnail image is empty, and isn't clickable for stars
+        //Also, don't show the border around the Image QFrame.
+        Data->Image->setFrameStyle( QFrame::NoFrame );
+        disconnect( Data->Image, SIGNAL( clicked() ), this, SLOT( updateThumbnail() ) );
+
+        //distance
+        if ( s->distance() > 2000. || s->distance() < 0. )  // parallax < 0.5 mas
+            Data->Distance->setText( QString(i18nc("larger than 2000 parsecs", "> 2000 pc") ) );
+        else if ( s->distance() > 50.0 ) //show to nearest integer
+            Data->Distance->setText( i18nc( "number in parsecs", "%1 pc" ,
+                                            KGlobal::locale()->formatNumber( s->distance(), 0 ) ) );
+        else if ( s->distance() > 10.0 ) //show to tenths place
+            Data->Distance->setText( i18nc( "number in parsecs", "%1 pc" ,
+                                            KGlobal::locale()->formatNumber( s->distance(), 1 ) ) );
+        else //show to hundredths place
+            Data->Distance->setText( i18nc( "number in parsecs", "%1 pc" ,
+                                            KGlobal::locale()->formatNumber( s->distance(), 2 ) ) );
+
+        //Note multiplicity/variablility in angular size label
+        Data->AngSizeLabel->setText( QString() );
+        Data->AngSize->setText( QString() );
+        Data->AngSizeLabel->setFont( Data->AngSize->font() );
+        if ( s->isMultiple() && s->isVariable() ) {
+            Data->AngSizeLabel->setText( i18nc( "the star is a multiple star", "multiple" ) + ',' );
+            Data->AngSize->setText( i18nc( "the star is a variable star", "variable" ) );
+        } else if ( s->isMultiple() )
+            Data->AngSizeLabel->setText( i18nc( "the star is a multiple star", "multiple" ) );
+        else if ( s->isVariable() )
+            Data->AngSizeLabel->setText( i18nc( "the star is a variable star", "variable" ) );
+
+        break; //end of stars case
+
+    case SkyObject::ASTEROID:  //[fall through to planets]
+    case SkyObject::COMET: //[fall through to planets]
+    case SkyObject::MOON: //[fall through to planets]
+    case SkyObject::PLANET:
+        ps = (KSPlanetBase *)selectedObject;
+
+        Data->Names->setText( ps->longname() );
+        //Type is "G5 star" for Sun
+        if ( ps->name() == "Sun" )
+            objecttyp = i18n("G5 star");
+        else if ( ps->name() == "Moon" )
+            objecttyp = ps->translatedName();
+        else if ( ps->name() == i18n("Pluto") || ps->name() == "Ceres" || ps->name() == "Eris" ) // TODO: Check if Ceres / Eris have translations and i18n() them
+            objecttyp = i18n("Dwarf planet");
+        else
+            objecttyp = ps->typeName();
+
+        //Magnitude: The moon displays illumination fraction instead
+        if ( selectedObject->name() == "Moon" ) {
+            Data->IllumLabel->setVisible( true );
+            Data->Illumination->setText( QString("%1 %").arg( KGlobal::locale()->formatNumber( ((KSMoon *)selectedObject)->illum()*100., 0 ) ) );
+        }
+
+        Data->Magnitude->setText( i18nc( "number in magnitudes", "%1 mag" ,
+                                         KGlobal::locale()->formatNumber( ps->mag(), 1 ) ) );  //show to tenths place
+        //Distance from Earth.  The moon requires a unit conversion
+        if ( ps->name() == "Moon" ) {
+            Data->Distance->setText( i18nc("distance in kilometers", "%1 km",
+                                           KGlobal::locale()->formatNumber( ps->rearth()*AU_KM ) ) );
+        } else {
+            Data->Distance->setText( i18nc("distance in Astronomical Units", "%1 AU",
+                                           KGlobal::locale()->formatNumber( ps->rearth() ) ) );
+        }
+
+        //Angular size; moon and sun in arcmin, others in arcsec
+        if ( ps->angSize() ) {
+            if ( ps->name() == "Sun" || ps->name() == "Moon" )
+                Data->AngSize->setText( i18nc("angular size in arcminutes", "%1 arcmin",
+                                              KGlobal::locale()->formatNumber( ps->angSize() ) ) ); // Needn't be a plural form because sun / moon will never contract to 1 arcminute
+            else
+                Data->AngSize->setText( i18nc("angular size in arcseconds","%1 arcsec",
+                                              KGlobal::locale()->formatNumber( ps->angSize()*60.0 ) ) ); 
+        } else {
+            Data->AngSize->setText( "--" );
+        }
+
+        break; //end of planets/comets/asteroids case
+
+    default: //deep-sky objects
+        dso = (DeepSkyObject *)selectedObject;
+
+        //Show all names recorded for the object
+        if ( ! dso->longname().isEmpty() && dso->longname() != dso->name() ) {
+            pname = dso->translatedLongName();
+            oname = dso->translatedName();
+        } else {
+            pname = dso->translatedName();
+        }
+
+        if ( ! dso->translatedName2().isEmpty() ) {
+            if ( oname.isEmpty() ) oname = dso->translatedName2();
+            else oname += ", " + dso->translatedName2();
+        }
+
+        if ( dso->ugc() != 0 ) {
+            if ( ! oname.isEmpty() ) oname += ", ";
+            oname += "UGC " + QString::number( dso->ugc() );
+        }
+        if ( dso->pgc() != 0 ) {
+            if ( ! oname.isEmpty() ) oname += ", ";
+            oname += "PGC " + QString::number( dso->pgc() );
+        }
+
+        if ( ! oname.isEmpty() ) pname += ", " + oname;
+        Data->Names->setText( pname );
+
+        objecttyp = dso->typeName();
+
+        if ( dso->mag() > 90.0 )
+            Data->Magnitude->setText( "--" );
+        else
+            Data->Magnitude->setText( i18nc( "number in magnitudes", "%1 mag" ,
+                                             KGlobal::locale()->formatNumber( dso->mag(), 1 ) ) );  //show to tenths place
+
+        //No distances at this point...
+        Data->Distance->setText( "--" );
+
+        //Only show decimal place for small angular sizes
+        if ( dso->a() > 10.0 )
+            Data->AngSize->setText( i18nc("angular size in arcminutes", "%1 arcmin",
+                                          KGlobal::locale()->formatNumber(dso->a(), 0 ) ) );
+        else if ( dso->a() )
+            Data->AngSize->setText( i18nc("angular size in arcminutes", "%1 arcmin",
+                                          KGlobal::locale()->formatNumber( dso->a(), 1 ) ) );
+        else
+            Data->AngSize->setText( "--" );
+
+        break;
+    }
+
+    //Common to all types:
+    if ( selectedObject->type() == SkyObject::CONSTELLATION )
+        Data->ObjectTypeInConstellation->setText(
+            KStarsData::Instance()->skyComposite()->getConstellationBoundary()->constellationName( selectedObject ) );
+    else
+        Data->ObjectTypeInConstellation->setText( 
+            i18nc("%1 type of sky object (planet, asteroid etc), %2 name of a constellation", "%1 in %2", objecttyp, 
+                  KStarsData::Instance()->skyComposite()->getConstellationBoundary()->constellationName( selectedObject ) ) );
+}
+
+void SkyObjectList::createPositionTab( const KStarsDateTime &ut, GeoLocation *geo ) {
+    Pos = new PositionWidget(pageWidget);
+    pageWidget->addPage( Pos,  i18n("Position") );
+
+    Pos->CoordTitle->setPalette( titlePalette );
+    Pos->RSTTitle->setPalette( titlePalette );
+
+    //Coordinates Section:
+    //Don't use KLocale::formatNumber() for the epoch string,
+    //because we don't want a thousands-place separator!
+    QString sEpoch = QString::number( ut.epoch(), 'f', 1 );
+    //Replace the decimal point with localized decimal symbol
+    sEpoch.replace( '.', KGlobal::locale()->decimalSymbol() );
+
+    Pos->RALabel->setText( i18n( "RA (%1):", sEpoch ) );
+    Pos->DecLabel->setText( i18n( "Dec (%1):", sEpoch ) );
+    Pos->RA->setText( selectedObject->ra()->toHMSString() );
+    Pos->Dec->setText( selectedObject->dec()->toDMSString() );
+    Pos->Az->setText( selectedObject->az()->toDMSString() );
+    dms a( selectedObject->alt()->Degrees() );
+    if ( Options::useAltAz() && Options::useRefraction() )
+        a = KStars::Instance()->map()->refract( selectedObject->alt(), true ); //true: compute apparent alt from true alt
+    Pos->Alt->setText( a.toDMSString() );
+
+    //Hour Angle can be negative, but dms HMS expressions cannot.
+    //Here's a kludgy workaround:
+    dms lst = geo->GSTtoLST( ut.gst() );
+    dms ha( lst.Degrees() - selectedObject->ra()->Degrees() );
+    QChar sgn('+');
+    if ( ha.Hours() > 12.0 ) {
+        ha.setH( 24.0 - ha.Hours() );
+        sgn = '-';
+    }
+    Pos->HA->setText( QString("%1%2").arg(sgn).arg( ha.toHMSString() ) );
+
+    //Airmass is approximated as the secant of the zenith distance,
+    //equivalent to 1./sin(Alt).  Beware of Inf at Alt=0!
+    if ( selectedObject->alt()->Degrees() > 0.0 )
+        Pos->Airmass->setText( KGlobal::locale()->formatNumber(
+                                   1./sin( selectedObject->alt()->radians() ), 2 ) );
+    else
+        Pos->Airmass->setText( "--" );
+
+    //Rise/Set/Transit Section:
+
+    //Prepare time/position variables
+    QTime rt = selectedObject->riseSetTime( ut, geo, true ); //true = use rise time
+    dms raz = selectedObject->riseSetTimeAz( ut, geo, true ); //true = use rise time
+
+    //If transit time is before rise time, use transit time for tomorrow
+    QTime tt = selectedObject->transitTime( ut, geo );
+    dms talt = selectedObject->transitAltitude( ut, geo );
+    if ( tt < rt ) {
+        tt = selectedObject->transitTime( ut.addDays( 1 ), geo );
+        talt = selectedObject->transitAltitude( ut.addDays( 1 ), geo );
+    }
+
+    //If set time is before rise time, use set time for tomorrow
+    QTime st = selectedObject->riseSetTime(  ut, geo, false ); //false = use set time
+    dms saz = selectedObject->riseSetTimeAz( ut, geo, false ); //false = use set time
+    if ( st < rt ) {
+        st = selectedObject->riseSetTime( ut.addDays( 1 ), geo, false ); //false = use set time
+        saz = selectedObject->riseSetTimeAz( ut.addDays( 1 ), geo, false ); //false = use set time
+    }
+
+    if ( rt.isValid() ) {
+        Pos->TimeRise->setText( QString().sprintf( "%02d:%02d", rt.hour(), rt.minute() ) );
+        Pos->TimeSet->setText( QString().sprintf( "%02d:%02d", st.hour(), st.minute() ) );
+        Pos->AzRise->setText( raz.toDMSString() );
+        Pos->AzSet->setText( saz.toDMSString() );
+    } else {
+        if ( selectedObject->alt()->Degrees() > 0.0 ) {
+            Pos->TimeRise->setText( i18n( "Circumpolar" ) );
+            Pos->TimeSet->setText( i18n( "Circumpolar" ) );
+        } else {
+            Pos->TimeRise->setText( i18n( "Never rises" ) );
+            Pos->TimeSet->setText( i18n( "Never rises" ) );
+        }
+
+        Pos->AzRise->setText( i18nc( "Not Applicable", "N/A" ) );
+        Pos->AzSet->setText( i18nc( "Not Applicable", "N/A" ) );
+    }
+
+    Pos->TimeTransit->setText( QString().sprintf( "%02d:%02d", tt.hour(), tt.minute() ) );
+    Pos->AltTransit->setText( talt.toDMSString() );
+
+    // Restore the position and other time-dependent parameters
+    selectedObject->recomputeCoords( ut, geo );
+
+}
+
+void SkyObjectList::createLinksTab()
+{
+    if( Links )
+        return;
+    // don't create a link tab for an unnamed star
+    if (selectedObject->name() == QString("star"))
+        return;
+
+    Links = new LinksWidget( pageWidget );
+    pageWidget->addPage( Links, i18n( "Links" ) );
+
+    Links->InfoTitle->setPalette( titlePalette );
+    Links->ImagesTitle->setPalette( titlePalette );
+
+    foreach ( const QString &s, selectedObject->InfoTitle() )
+        Links->InfoTitleList->addItem( i18nc( "Image/info menu item (should be translated)", s.toLocal8Bit() ) );
+
+    //Links->InfoTitleList->setCurrentRow(0);
+
+    foreach ( const QString &s, selectedObject->ImageTitle() )
+        Links->ImageTitleList->addItem( i18nc( "Image/info menu item (should be translated)", s.toLocal8Bit() ) );
+
+     updateButtons();
+
+    // Signals/Slots
+    connect( Links->ViewButton, SIGNAL(clicked()), this, SLOT( viewLink() ) );
+    connect( Links->AddLinkButton, SIGNAL(clicked()), KStars::Instance()->map(), SLOT( addLink() ) );
+    connect( Links->EditLinkButton, SIGNAL(clicked()), this, SLOT( editLinkDialog() ) );
+    connect( Links->RemoveLinkButton, SIGNAL(clicked()), this, SLOT( removeLinkDialog() ) );
+
+    // When an item is selected in info list, selected items are cleared image list.
+    connect( Links->InfoTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT( setCurrentLink(QListWidgetItem*) ) );
+    connect( Links->InfoTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), Links->ImageTitleList, SLOT( clearSelection() ) );
+
+    // vice versa
+    connect( Links->ImageTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT( setCurrentLink(QListWidgetItem*) ) );
+    connect( Links->ImageTitleList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), Links->InfoTitleList, SLOT( clearSelection() ));
+
+    connect( Links->InfoTitleList, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT( viewLink() ) );
+    connect( Links->ImageTitleList, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT( viewLink() ) );
+
+    connect( Links->InfoTitleList, SIGNAL(itemSelectionChanged ()), this, SLOT( updateButtons() ) );
+    connect( Links->ImageTitleList, SIGNAL(itemSelectionChanged ()), this, SLOT( updateButtons() ));
+
+    connect( KStars::Instance()->map(), SIGNAL(linkAdded()), this, SLOT( updateLists() ) );
+}
+
+void SkyObjectList::createAdvancedTab()
+{
+    if( Adv )
+        return;
+    // Don't create an adv tab for an unnamed star or if advinterface file failed loading
+    // We also don't need adv dialog for solar system objects.
+    if (selectedObject->name() == QString("star") ||
+            KStarsData::Instance()->ADVtreeList.isEmpty() ||
+            selectedObject->type() == SkyObject::PLANET ||
+            selectedObject->type() == SkyObject::COMET ||
+            selectedObject->type() == SkyObject::ASTEROID )
+        return;
+
+    Adv = new DatabaseWidget( pageWidget );
+    pageWidget->addPage( Adv,  i18n( "Advanced" ) );
+
+    connect( Adv->ADVTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(viewADVData()));
+
+    populateADVTree();
+}
+
+void SkyObjectList::createLogTab()
+{
+    if( Log )
+        return;
+    //Don't create a a log tab for an unnamed star
+    if ( selectedObject->name() == QString("star") )
+        return;
+
+    // Log Tab
+    Log = new LogWidget( pageWidget );
+    pageWidget->addPage( Log,  i18n( "Log" ) );
+
+    Log->LogTitle->setPalette( titlePalette );
+
+    if ( selectedObject->userLog().isEmpty() )
+        Log->UserLog->setText(i18n("Record here observation logs and/or data on %1.", selectedObject->translatedName()));
+    else
+        Log->UserLog->setText(selectedObject->userLog());
+
+    //Automatically save the log contents when the widget loses focus
+    connect( Log->UserLog, SIGNAL( focusOut() ), this, SLOT( saveLogData() ) );
+}
+
+
+void SkyObjectList::setCurrentLink(QListWidgetItem *it)
+{
+    m_CurrentLink = it;
+}
+
+void SkyObjectList::viewLink()
+{
+    QString URL;
+
+    if (m_CurrentLink == NULL) return;
+
+    if ( m_CurrentLink->listWidget() == Links->InfoTitleList ) {
+        URL = QString( selectedObject->InfoList().at( Links->InfoTitleList->row(m_CurrentLink) ) );
+    }
+    else if ( m_CurrentLink->listWidget() == Links->ImageTitleList ) {
+        URL = QString( selectedObject->ImageList().at( Links->ImageTitleList->row(m_CurrentLink) ) );
+    }
+
+    if ( !URL.isEmpty() )
+        KToolInvocation::invokeBrowser(URL);
+}
+
+void SkyObjectList::updateLists()
+{
+    Links->InfoTitleList->clear();
+    Links->ImageTitleList->clear();
+
+    foreach ( const QString &s, selectedObject->InfoTitle() )
+        Links->InfoTitleList->addItem( s );
+
+    foreach ( const QString &s, selectedObject->ImageTitle() )
+        Links->ImageTitleList->addItem( s );
+
+    updateButtons();
+}
+
+void SkyObjectList::updateButtons()
+{
+
+    bool anyLink=false;
+    if (!Links->InfoTitleList->selectedItems().isEmpty() || !Links->ImageTitleList->selectedItems().isEmpty())
+        anyLink = true;
+
+    // Buttons could be disabled if lists are initially empty, we enable and disable them here
+    // depending on the current status of the list.
+    Links->ViewButton->setEnabled(anyLink);
+    Links->EditLinkButton->setEnabled(anyLink);
+    Links->RemoveLinkButton->setEnabled(anyLink);
+}
+
+void SkyObjectList::editLinkDialog()
+{
+    int type=0, row=0;
+    QString search_line, replace_line, currentItemTitle, currentItemURL;
+
+    if (m_CurrentLink == NULL) return;
+
+    KDialog editDialog( this );
+    editDialog.setCaption( i18n("Edit Link") );
+    editDialog.setButtons( KDialog::Ok | KDialog::Cancel );
+    QFrame editFrame( &editDialog );
+
+    if ( m_CurrentLink->listWidget() == Links->InfoTitleList )
+    {
+        row = Links->InfoTitleList->row( m_CurrentLink );
+
+        currentItemTitle = m_CurrentLink->text();
+        currentItemURL = selectedObject->InfoTitle().at( row );
+        search_line = selectedObject->name();
+        search_line += ':';
+        search_line += currentItemTitle;
+        search_line += ':';
+        search_line += currentItemURL;
+        type       = 0;
+    }
+    else if ( m_CurrentLink->listWidget() == Links->ImageTitleList )
+    {
+        row = Links->ImageTitleList->row( m_CurrentLink );
+
+        currentItemTitle = m_CurrentLink->text();
+        currentItemURL = selectedObject->ImageTitle().at( row ); 
+        search_line = selectedObject->name();
+        search_line += ':';
+        search_line += currentItemTitle;
+        search_line += ':';
+        search_line += currentItemURL;
+        type 	   = 1;
+    }
+    else return;
+
+    QLineEdit editNameField(&editFrame);
+    editNameField.setObjectName("nameedit");
+    editNameField.home(false);
+    editNameField.setText(currentItemTitle);
+    QLabel editLinkURL(i18n("URL:"), &editFrame);
+    QLineEdit editLinkField(&editFrame);
+    editLinkField.setObjectName("urledit");
+    editLinkField.home(false);
+    editLinkField.setText(currentItemURL);
+    QVBoxLayout vlay(&editFrame);
+    vlay.setObjectName("vlay");
+    QHBoxLayout editLinkLayout(&editFrame);
+    editLinkLayout.setObjectName("editlinklayout");
+    editLinkLayout.addWidget(&editLinkURL);
+    editLinkLayout.addWidget(&editLinkField);
+    vlay.addWidget( &editNameField );
+    vlay.addLayout( &editLinkLayout );
+    editDialog.setMainWidget( &editFrame );
+
+    bool go( true );
+    // If user presses cancel then skip the action
+    if ( editDialog.exec() != QDialog::Accepted )
+        go = false;
+
+    // If nothing changed, skip th action
+    if (editLinkField.text() == currentItemURL && editNameField.text() == currentItemTitle)
+        go = false;
+
+    if ( go ) {
+        replace_line = selectedObject->name() + ':' + editNameField.text() + ':' + editLinkField.text();
+
+        // Info Link
+        if (type==0) {
+            selectedObject->InfoTitle().replace(row, editNameField.text());
+            selectedObject->InfoList().replace(row, editLinkField.text());
+
+        // Image Links
+        } else {
+            selectedObject->ImageTitle().replace(row, editNameField.text());
+            selectedObject->ImageList().replace(row, editLinkField.text());
+        }
+
+        // Update local files
+        updateLocalDatabase(type, search_line, replace_line);
+
+        // Set focus to the same item again
+        if (type == 0)
+            Links->InfoTitleList->setCurrentRow(row);
+        else
+            Links->ImageTitleList->setCurrentRow(row);
+    }
+}
+
+void SkyObjectList::removeLinkDialog()
+{
+    int type=0, row=0;
+    QString currentItemURL, currentItemTitle, LineEntry, TempFileName, FileLine;
+    QFile URLFile;
+    KTemporaryFile TempFile;
+    TempFile.setAutoRemove(false);
+    TempFile.open();
+    TempFileName = TempFile.fileName();
+
+    if (m_CurrentLink == NULL) return;
+
+    if ( m_CurrentLink->listWidget() == Links->InfoTitleList )
+    {
+        row = Links->InfoTitleList->row( m_CurrentLink );
+        currentItemTitle = m_CurrentLink->text();
+        currentItemURL   = selectedObject->InfoList()[row];
+        LineEntry = selectedObject->name();
+        LineEntry += ':';
+        LineEntry += currentItemTitle;
+        LineEntry += ':';
+        LineEntry += currentItemURL;
+        type       = 0;
+    }
+    else if ( m_CurrentLink->listWidget() == Links->ImageTitleList )
+    {
+        row = Links->ImageTitleList->row( m_CurrentLink );
+        currentItemTitle = m_CurrentLink->text();
+        currentItemURL   = selectedObject->ImageList()[row];
+        LineEntry = selectedObject->name();
+        LineEntry += ':';
+        LineEntry += currentItemTitle;
+        LineEntry += ':';
+        LineEntry += currentItemURL;
+        type 	   = 1;
+    }
+    else return;
+
+    if (KMessageBox::warningContinueCancel( 0, i18n("Are you sure you want to remove the %1 link?", currentItemTitle), i18n("Delete Confirmation"),KStandardGuiItem::del())!=KMessageBox::Continue)
+        return;
+
+    if (type ==0)
+    {
+        selectedObject->InfoTitle().removeAt(row);
+        selectedObject->InfoList().removeAt(row);
+    }
+    else
+    {
+        selectedObject->ImageTitle().removeAt(row);
+        selectedObject->ImageList().removeAt(row);
+    }
+
+    // Remove link from file
+    updateLocalDatabase(type, LineEntry);
+
+    // Set focus to the 1st item in the list
+    if (type == 0)
+        Links->InfoTitleList->clearSelection();
+    else
+        Links->ImageTitleList->clearSelection();
+
+}
+
+void SkyObjectList::updateLocalDatabase(int type, const QString &search_line, const QString &replace_line)
+{
+    QString TempFileName, file_line;
+    QFile URLFile;
+    KTemporaryFile TempFile;
+    TempFile.setAutoRemove(false);
+    TempFile.open();
+    QTextStream *temp_stream=NULL, *out_stream=NULL;
+    bool replace = !replace_line.isEmpty();
+
+    if (search_line.isEmpty())
+        return;
+
+    TempFileName = TempFile.fileName();
+
+    switch (type)
+    {
+        // Info Links
+    case 0:
+        // Get name for our local info_url file
+        URLFile.setFileName( KStandardDirs::locateLocal( "appdata", "info_url.dat" ) );
+        break;
+
+        // Image Links
+    case 1:
+        // Get name for our local info_url file
+        URLFile.setFileName( KStandardDirs::locateLocal( "appdata", "image_url.dat" ) );
+        break;
+    }
+
+    // Copy URL file to temp file
+    KIO::file_copy(KUrl::fromPath(URLFile.fileName()), KUrl::fromPath(TempFileName), -1, KIO::Overwrite | KIO::HideProgressInfo );
+
+
+    if ( !URLFile.open( QIODevice::WriteOnly) )
+    {
+        kDebug() << "SkyObjectList: Failed to open " << URLFile.fileName();
+        kDebug() << "KStars cannot save to user database";
+        return;
+    }
+
+    // Get streams;
+    temp_stream = new QTextStream(&TempFile);
+    out_stream  = new QTextStream(&URLFile);
+
+    while (!temp_stream->atEnd())
+    {
+        file_line = temp_stream->readLine();
+        // If we find a match, either replace, or remove (by skipping).
+        if (file_line == search_line)
+        {
+            if (replace)
+                (*out_stream) << replace_line << endl;
+            else
+                continue;
+        }
+        else
+            (*out_stream) << file_line << endl;
+    }
+
+    URLFile.close();
+    delete(temp_stream);
+    delete(out_stream);
+
+    updateLists();
+
+}
+
+void SkyObjectList::populateADVTree()
+{
+    QTreeWidgetItem *parent = NULL, *temp = NULL;
+
+    // We populate the tree iterativley, keeping track of parents as we go
+    // This solution is more efficient than the previous recursion algorithm.
+    foreach (ADVTreeData *item, KStarsData::Instance()->ADVtreeList)
+    {
+
+        switch (item->Type)
+        {
+            // Top Level
+        case 0:
+            temp = new QTreeWidgetItem(parent, QStringList(item->Name));
+            if (parent == NULL)
+                Adv->ADVTree->addTopLevelItem(temp);
+            parent = temp;
+
+            break;
+
+            // End of top level
+        case 1:
+            if (parent != NULL) parent = parent->parent();
+            break;
+
+            // Leaf
+        case 2:
+            new QTreeWidgetItem(parent, QStringList(item->Name));
+            break;
+        }
+    }
+
+}
+
+void  SkyObjectList::viewADVData()
+{
+    QString link;
+    QTreeWidgetItem * current = Adv->ADVTree->currentItem();
+
+    //If the item has children or is invalid, do nothing
+    if ( !current || current->childCount()>0 )  return;
+
+    foreach (ADVTreeData *item, KStarsData::Instance()->ADVtreeList)
+    {
+        if (item->Name == current->text(0))
+        {
+            link = item->Link;
+            link = parseADVData(link);
+            KToolInvocation::invokeBrowser(link);
+            return;
+        }
+    }
+}
+
+QString SkyObjectList::parseADVData( const QString &inlink )
+{
+    QString link = inlink;
+    QString subLink;
+    int index;
+
+    if ( (index = link.indexOf("KSOBJ")) != -1)
+    {
+        link.remove(index, 5);
+        link = link.insert(index, selectedObject->name());
+    }
+
+    if ( (index = link.indexOf("KSRA")) != -1)
+    {
+        link.remove(index, 4);
+        subLink.sprintf("%02d%02d%02d", selectedObject->ra0()->hour(), selectedObject->ra0()->minute(), selectedObject->ra0()->second());
+        subLink = subLink.insert(2, "%20");
+        subLink = subLink.insert(7, "%20");
+
+        link = link.insert(index, subLink);
+    }
+    if ( (index = link.indexOf("KSDEC")) != -1)
+    {
+        link.remove(index, 5);
+        if (selectedObject->dec()->degree() < 0)
+        {
+            subLink.sprintf("%03d%02d%02d", selectedObject->dec0()->degree(), selectedObject->dec0()->arcmin(), selectedObject->dec0()->arcsec());
+            subLink = subLink.insert(3, "%20");
+            subLink = subLink.insert(8, "%20");
+        }
+        else
+        {
+            subLink.sprintf("%02d%02d%02d", selectedObject->dec0()->degree(), selectedObject->dec0()->arcmin(), selectedObject->dec0()->arcsec());
+            subLink = subLink.insert(0, "%2B");
+            subLink = subLink.insert(5, "%20");
+            subLink = subLink.insert(10, "%20");
+        }
+        link = link.insert(index, subLink);
+    }
+
+    return link;
+}
+
+void SkyObjectList::saveLogData() {
+    selectedObject->saveUserLog( Log->UserLog->toPlainText() );
+}
+
+void SkyObjectList::addToObservingList() {
+    KStars::Instance()->observingList()->slotAddObject( selectedObject );
+}
+
+void SkyObjectList::centerMap() {
+    SkyMap* map = KStars::Instance()->map();
+    map->setClickedObject( selectedObject );
+    map->slotCenter();
+}
+
+void SkyObjectList::centerTelescope()
+{
+#ifdef HAVE_INDI_H
+    INDI_D *indidev(NULL);
+    INDI_P *prop(NULL), *onset(NULL);
+    INDI_E *RAEle(NULL), *DecEle(NULL), *AzEle(NULL), *AltEle(NULL), *ConnectEle(NULL), *nameEle(NULL);
+    bool useJ2000( false);
+    int selectedCoord(0);
+    SkyPoint sp;
+    SkyMap* map = KStars::Instance()->map();
+    
+    // Find the first device with EQUATORIAL_EOD_COORD or EQUATORIAL_COORD and with SLEW element
+    // i.e. the first telescope we find!
+
+    INDIMenu *imenu = KStars::Instance()->indiMenu();
+    for ( int i=0; i < imenu->managers.size() ; i++ )
+    {
+        for ( int j=0; j < imenu->managers.at(i)->indi_dev.size(); j++ )
+        {
+            indidev = imenu->managers.at(i)->indi_dev.at(j);
+            indidev->stdDev->currentObject = NULL;
+            prop = indidev->findProp("EQUATORIAL_EOD_COORD_REQUEST");
+            if (prop == NULL)
+            {
+                prop = indidev->findProp("EQUATORIAL_EOD_COORD");
+                if (prop == NULL)
+                {
+                    prop = indidev->findProp("HORIZONTAL_COORD");
+                    if (prop == NULL)
+                        continue;
+                    else
+                        selectedCoord = 1;		/* Select horizontal */
+                }
+                else
+                    useJ2000 = true;
+            }
+
+            ConnectEle = indidev->findElem("CONNECT");
+            if (!ConnectEle) continue;
+
+            if (ConnectEle->state == PS_OFF)
+            {
+                KMessageBox::error(0, i18n("Telescope %1 is offline. Please connect and retry again.", indidev->label));
+                return;
+            }
+
+            switch (selectedCoord)
+            {
+                // Equatorial
+            case 0:
+                if (prop->perm == PP_RO) continue;
+                RAEle  = prop->findElement("RA");
+                if (!RAEle) continue;
+                DecEle = prop->findElement("DEC");
+                if (!DecEle) continue;
+                break;
+
+                // Horizontal
+            case 1:
+                if (prop->perm == PP_RO) continue;
+                AzEle = prop->findElement("AZ");
+                if (!AzEle) continue;
+                AltEle = prop->findElement("ALT");
+                if (!AltEle) continue;
+                break;
+            }
+
+            onset = indidev->findProp("ON_COORD_SET");
+            if (!onset) continue;
+
+            onset->activateSwitch("SLEW");
+
+            indidev->stdDev->currentObject = selectedObject;
+
+            /* Send object name if available */
+            if (indidev->stdDev->currentObject)
+            {
+                nameEle = indidev->findElem("OBJECT_NAME");
+                if (nameEle && nameEle->pp->perm != PP_RO)
+                {
+                    nameEle->write_w->setText(indidev->stdDev->currentObject->name());
+                    nameEle->pp->newText();
+                }
+            }
+
+            switch (selectedCoord)
+            {
+            case 0:
+                if (indidev->stdDev->currentObject)
+                    sp.set (indidev->stdDev->currentObject->ra(), indidev->stdDev->currentObject->dec());
+                else
+                    sp.set (map->clickedPoint()->ra(), map->clickedPoint()->dec());
+
+                if (useJ2000)
+                    sp.apparentCoord(KStarsData::Instance()->ut().djd(), (long double) J2000);
+
+                RAEle->write_w->setText(QString("%1:%2:%3").arg(sp.ra()->hour()).arg(sp.ra()->minute()).arg(sp.ra()->second()));
+                DecEle->write_w->setText(QString("%1:%2:%3").arg(sp.dec()->degree()).arg(sp.dec()->arcmin()).arg(sp.dec()->arcsec()));
+
+                break;
+
+            case 1:
+                if (indidev->stdDev->currentObject)
+                {
+                    sp.setAz(*indidev->stdDev->currentObject->az());
+                    sp.setAlt(*indidev->stdDev->currentObject->alt());
+                }
+                else
+                {
+                    sp.setAz(*map->clickedPoint()->az());
+                    sp.setAlt(*map->clickedPoint()->alt());
+                }
+
+                AzEle->write_w->setText(QString("%1:%2:%3").arg(sp.az()->degree()).arg(sp.az()->arcmin()).arg(sp.az()->arcsec()));
+                AltEle->write_w->setText(QString("%1:%2:%3").arg(sp.alt()->degree()).arg(sp.alt()->arcmin()).arg(sp.alt()->arcsec()));
+
+                break;
+            }
+
+            prop->newText();
+
+            return;
+        }
+    }
+
+    // We didn't find any telescopes
+    KMessageBox::sorry(0, i18n("KStars did not find any active telescopes."));
+#endif
+}
+
+void SkyObjectList::showThumbnail() {
+    //No image if object is a star
+    if ( selectedObject->type() == SkyObject::STAR ||
+         selectedObject->type() == SkyObject::CATALOG_STAR ) {
+        Thumbnail->scaled( Data->Image->width(), Data->Image->height() );
+        Thumbnail->fill( Data->DataFrame->palette().color( QPalette::Window ) );
+        Data->Image->setPixmap( *Thumbnail );
+        return;
+    }
+
+    //Try to load the object's image from disk
+    //If no image found, load "no image" image
+    //If that isn't found, make it blank.
+    QFile file;
+    QString fname = "thumb-" + selectedObject->name().toLower().remove( ' ' ) + ".png";
+    if ( KSUtils::openDataFile( file, fname ) ) {
+        file.close();
+        Thumbnail->load( file.fileName(), "PNG" );
+    } else if ( KSUtils::openDataFile( file, "noimage.png" ) ) {
+        file.close();
+        Thumbnail->load( file.fileName(), "PNG" );
+    } else {
+        Thumbnail->scaled( Data->Image->width(), Data->Image->height() );
+        Thumbnail->fill( Data->DataFrame->palette().color( QPalette::Window ) );
+    }
+
+    Data->Image->setPixmap( *Thumbnail );
+}
+
+void SkyObjectList::updateThumbnail() {
+    QPointer<ThumbnailPicker> tp = new ThumbnailPicker( selectedObject, *Thumbnail, this );
+
+    if ( tp->exec() == QDialog::Accepted ) {
+        QString fname = KStandardDirs::locateLocal( "appdata", "thumb-" + selectedObject->name().toLower().remove( ' ' ) + ".png" );
+
+        Data->Image->setPixmap( *(tp->image()) );
+
+        //If a real image was set, save it.
+        //If the image was unset, delete the old image on disk.
+        if ( tp->imageFound() ) {
+            Data->Image->pixmap()->save( fname, "PNG" );
+            *Thumbnail = *(Data->Image->pixmap());
+        } else {
+            QFile f;
+            f.setFileName( fname );
+            f.remove();
+        }
+    }
+    delete tp;
+}
+
+#if 0
+
+DataWidget::DataWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+    DataFrame->setBackgroundRole( QPalette::Base );
+}
+
+PositionWidget::PositionWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+    CoordFrame->setBackgroundRole( QPalette::Base );
+    RSTFrame->setBackgroundRole( QPalette::Base );
+}
+
+LinksWidget::LinksWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+}
+
+DatabaseWidget::DatabaseWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+}
+
+LogWidget::LogWidget( QWidget *p ) : QFrame( p )
+{
+    setupUi( this );
+}
+#endif
+
+#include "objectlist.moc"
+
Index: dialogs/objectlist.ui
===================================================================
--- dialogs/objectlist.ui	(revision 0)
+++ dialogs/objectlist.ui	(revision 0)
 <at>  <at>  -0,0 +1,160  <at>  <at> 
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>formSkyObjectList</class>
+ <widget class="QWidget" name="formSkyObjectList">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>600</width>
+    <height>400</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>600</width>
+    <height>400</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Object List</string>
+  </property>
+  <widget class="QWidget" name="verticalLayoutWidget">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>10</y>
+     <width>571</width>
+     <height>371</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>View mode</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="radioButtonDetailed">
+        <property name="text">
+         <string>&amp;Detailed</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+        <attribute name="buttonGroup">
+         <string>buttonGroupViewMode</string>
+        </attribute>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="radioButtonSummary">
+        <property name="text">
+         <string>&amp;Summary</string>
+        </property>
+        <attribute name="buttonGroup">
+         <string>buttonGroupViewMode</string>
+        </attribute>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QLabel" name="label">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="layoutDirection">
+         <enum>Qt::RightToLeft</enum>
+        </property>
+        <property name="text">
+         <string>Select sky object</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Maximum</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <widget class="QComboBox" name="comboBoxObjects"/>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <widget class="QTableView" name="tableView">
+      <property name="alternatingRowColors">
+       <bool>true</bool>
+      </property>
+      <property name="selectionMode">
+       <enum>QAbstractItemView::ExtendedSelection</enum>
+      </property>
+      <property name="selectionBehavior">
+       <enum>QAbstractItemView::SelectRows</enum>
+      </property>
+      <property name="gridStyle">
+       <enum>Qt::DotLine</enum>
+      </property>
+      <property name="sortingEnabled">
+       <bool>true</bool>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QFrame" name="framePage">
+      <property name="frameShape">
+       <enum>QFrame::NoFrame</enum>
+      </property>
+      <property name="frameShadow">
+       <enum>QFrame::Plain</enum>
+      </property>
+      <property name="lineWidth">
+       <number>0</number>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <resources/>
+ <connections/>
+ <buttongroups>
+  <buttongroup name="buttonGroupViewMode"/>
+ </buttongroups>
+</ui>
Index: dialogs/objectlist.h
===================================================================
--- dialogs/objectlist.h	(revision 0)
+++ dialogs/objectlist.h	(revision 0)
 <at>  <at>  -0,0 +1,169  <at>  <at> 
+#ifndef OBJECTLIST_H
+#define OBJECTLIST_H
+
+#include <QPixmap>
+#include <QMouseEvent>
+#include <QFocusEvent>
+#include <QHBoxLayout>
+#include <QTabWidget>
+#include <QPushButton>
+#include <QPalette>
+
+#include <kpagedialog.h>
+#include <ktextedit.h>
+
+#include <KDialog>
+#include <QAbstractTableModel>
+#include <QSortFilterProxyModel>
+
+#include "../skyobjects/skyobject.h"
+#include "kstarsdatetime.h"
+#include "skyobjects/skyobject.h"
+#include "skyobjects/deepskyobject.h"
+
+#include "ui_objectlist.h"
+//UI headers
+#include "ui_details_data.h"
+#include "ui_details_position.h"
+#include "ui_details_links.h"
+#include "ui_details_database.h"
+#include "ui_details_log.h"
+
+class GeoLocation;
+class QHBoxLayout;
+class QLineEdit;
+class QListWidgetItem;
+class QPixmap;
+class QString;
+class QStringList;
+class KStars;
+class KStarsDateTime;
+
+class KSAlmanac;
+class QSortFilterProxyModel;
+class QStandardItemModel;
+class KStars;
+class KStarsDateTime;
+class GeoLocation;
+
+
+class DataWidget;
+class PositionWidget;
+class LinksWidget;
+class DatabaseWidget;
+class LogWidget;
+
+#if 0
+struct ADVTreeData
+{
+    QString Name;
+    QString Link;
+    int Type;
+};
+#endif
+
+class SkyObjectList : public KPageDialog
+{
+    Q_OBJECT
+    public:
+        SkyObjectList( SkyObject* o, const KStarsDateTime& _dt, GeoLocation* _geo, KStars* parent = 0 );
+	~SkyObjectList();
+	inline QPixmap* thumbnail() { return Thumbnail; }
+
+	void addObject( SkyObject* );
+	void addObject( DeepSkyObject*& );
+	void removeAll();
+	//~SkyObjectList();
+        SkyObject* currentObject() const { return selectedObject; }
+        QList<SkyObject*>& objectList() { return m_ObjectList; }
+    public slots:
+        void slotNewSelection();
+        void slotCenterObject();
+	void comboBoxIndexChanged( int );
+	//void showDetails(int);
+	void showDetails(bool);
+	void showSummary(bool);
+
+	void addToObservingList();
+	void centerMap();
+	void centerTelescope();
+	void showThumbnail();
+	void updateThumbnail();
+	void viewLink();
+	void setCurrentLink(QListWidgetItem *it);
+	void updateLists();
+	void editLinkDialog();
+	void removeLinkDialog();
+	void viewADVData();
+	void saveLogData();
+	void updateButtons();
+
+    private:
+        KStars *ks;
+        KStarsDateTime ut;
+	GeoLocation *geo;
+        Ui::formSkyObjectList ui;
+        QList<SkyObject*> m_ObjectList;
+        //SkyObject *m_CurrentObject;
+	QStandardItemModel *m_Model;
+	QSortFilterProxyModel *m_SortModel;
+
+	void createGeneralTab();
+	void createPositionTab( const KStarsDateTime &ut, GeoLocation *geo );
+	void createLinksTab();
+	void createAdvancedTab();
+	void createLogTab();
+	void populateADVTree();
+	QString parseADVData( const QString &link );
+	void updateLocalDatabase(int type, const QString &search_line, const QString &replace_line = QString());
+	void cleanupDetailView();
+
+	SkyObject *selectedObject;
+	QPalette titlePalette;
+	QListWidgetItem *m_CurrentLink;
+	QPixmap *Thumbnail;
+	int currentItemIndex;
+	QStringList dataList;
+
+	DataWidget *Data;
+	PositionWidget *Pos;
+	LinksWidget *Links;
+	DatabaseWidget *Adv;
+	LogWidget *Log;
+
+	KPageWidget* pageWidget;
+};
+
+#if 0
+class DataWidget : public QFrame, public Ui::DetailsData
+{
+public:
+    DataWidget( QWidget *parent=0 );
+};
+
+class PositionWidget : public QFrame, public Ui::DetailsPosition
+{
+public:
+    PositionWidget( QWidget *parent=0 );
+};
+
+class LinksWidget : public QFrame, public Ui::DetailsLinks
+{
+public:
+    LinksWidget( QWidget *parent=0 );
+};
+
+class DatabaseWidget : public QFrame, public Ui::DetailsDatabase
+{
+public:
+    DatabaseWidget( QWidget *parent=0 );
+};
+
+class LogWidget : public QFrame, public Ui::DetailsLog
+{
+public:
+    LogWidget( QWidget *parent=0 );
+};
+#endif
+
+#endif
Index: skymap.cpp
===================================================================
--- skymap.cpp	(revision 1084185)
+++ skymap.cpp	(working copy)
 <at>  <at>  -44,11 +44,17  <at>  <at> 
 #include "imageviewer.h"
 #include "dialogs/detaildialog.h"
 #include "dialogs/addlinkdialog.h"
+#include "dialogs/objectlist.h"
 #include "kspopupmenu.h"
 #include "simclock.h"
 #include "skyobjects/skyobject.h"
 #include "skyobjects/ksplanetbase.h"
 #include "skycomponents/skymapcomposite.h"
+#include "skycomponents/skymesh.h"
+#include "skycomponents/skycomponent.h"
+#include "skycomponents/starcomponent.h"
+#include "skycomponents/deepskycomponent.h"
+#include "skyobjects/starobject.h"
 #include "widgets/infoboxwidget.h"
 
 #ifdef HAVE_XPLANET
 <at>  <at>  -685,7 +691,8  <at>  <at> 
         KMessageBox::sorry( this, i18n("No object selected."), i18n("Object Details") );
         return;
     }
-    DetailDialog* detail = new DetailDialog( clickedObject(), data->ut(), data->geo(), KStars::Instance() );
+    //DetailDialog* detail = new DetailDialog( clickedObject(), data->ut(), data->geo(), KStars::Instance() );
+    SkyObjectList* detail = new SkyObjectList( clickedObject(), data->ut(), data->geo(), KStars::Instance() );
     detail->setAttribute(Qt::WA_DeleteOnClose);
     detail->show();
 }
 <at>  <at>  -1513,6 +1520,125  <at>  <at> 
     return p.x() < -100000.0;
 }
 
+void SkyMap::showObjectsInRectangle()
+{
+    if( (secondRClickPos-firstRClickPos).manhattanLength() < QApplication::startDragDistance() )
+    {
+        if( clickedObject() )
+        {
+        // Rightclick release happened within the drag limits
+        // Got to populate info about a single clicked object
+            clickedObject()->showPopupMenu( pmenu, QCursor::pos() );
+            kDebug() << "clicked object is non-null" << endl;
+        }
+	else
+	{
+            // Rightclick release happened within the drag limits
+            // Got to populate info with unknown object since there was
+            // no clicked object in the region
+            SkyObject object( 
+                        SkyObject::TYPE_UNKNOWN, 
+                        clickedPoint()->ra()->Hours(), 
+                        clickedPoint()->dec()->Degrees() );
+            
+            pmenu->createEmptyMenu( &object );
+            pmenu->popup( QCursor::pos() );
+	}
+    }
+    else
+    {
+	SkyMesh* skymesh = SkyMesh::Instance();
+        // "firstPoint" and "secondPoint" act as reference skypoints.
+        // In order to form a virtual rectangle using the two, the other 2 vertices of
+        // rectangle have to be found. For skypoints, the (x,y) are determined by
+        // the Right ascension (RA) and Declinations.
+        // Find the Point3(RA, Dec) and Point4(RA, Dec) 
+        dms thirdRA(secondPoint.ra()->Degrees()), thirdDec(firstPoint.dec()->Degrees());
+        dms fourthRA(firstPoint.ra()->Degrees()), fourthDec(secondPoint.dec()->Degrees());
+        SkyPoint thirdPoint(thirdRA, thirdDec), fourthPoint( fourthRA, fourthDec );
+        
+        // The skylist below is a QVector<SkyPoint*>'s instance 
+        // Stores the skypoints of virtual rectangle in that order
+        // i.e. the following:
+        // 
+        //       firstPoint  .______________. thirdPoint
+        //                   |              |
+        //                   |              |
+        //      fourthPoint  .______________. secondPoint
+        //
+        SkyList skylist;
+        skylist.push_back( &firstPoint );
+        skylist.push_back( &thirdPoint );
+        skylist.push_back( &secondPoint );
+        skylist.push_back( &fourthPoint );
+        
+        // 
+        const IndexHash& indexHash = skymesh->indexPoly( &skylist );
+        
+        // If the list of stars is non-empty, empty it first before refilling
+        KStars* stars = KStars::Instance();
+        stars->objectList()->removeAll();
+        
+        for( IndexHash::const_iterator iter = indexHash.constBegin(); 
+            iter != indexHash.constEnd(); 
+            iter++ )
+        {
+            Trixel trixel = iter.key();
+            StarComponent* starComponent = StarComponent::Instance();
+            
+            if( starComponent )
+            {
+                StarList* starList = starComponent->starsInTrixel( trixel );
+                if( starList )
+                {
+                    for( int i = 0; i < starList->size(); i++ )
+                    {
+                        StarObject* currentStar = starList->at( i );
+                        if( !currentStar )
+                            continue;
+                        
+                        if( currentStar->name() != QString("star") )
+                            // Add the star to the list to be shown
+                            stars->objectList()->addObject( currentStar );
+                    }
+                }
+            }
+
+	    DeepSkyList* dsoList = data->skyComposite()->deepSkyComponent()->objectListInTrixel( trixel );
+	    if( dsoList )
+	    {
+	        for( QVector<DeepSkyObject*>::iterator dso = dsoList->begin();
+		     dso != dsoList->end();
+		     dso++ )
+		{
+		    DeepSkyObject* dsClone = (*dso)->clone();
+		    stars->objectList()->addObject( dsClone );
+		}
+	    }
+        }
+            
+        // Display the list that was formed from the iterations above
+        // If no sky objects are found, the list will be empty
+        stars->objectList()->show();
+        
+	// FIXME: The following block of code is for showing the rectangle formed
+	// by the right-button drag of the mouse. Although, the rectangle
+	// is getting properly painted with dotted line, immediately thereafter
+	// SkyMap::paintEvent() is getting triggered because of which the
+	// painted rectangle vanishes off. Got to find out a way for this!!!
+        
+	repaint();
+	QApplication::flush();
+	QPainter painter;
+        setAttribute(Qt::WA_PaintOutsidePaintEvent,true );
+        painter.begin( this );
+        QColor color = data->colorScheme()->colorNamed( "BoxHighlightColor" );
+        painter.setPen( QPen(QBrush(color), 1, Qt::DotLine ) );
+        painter.drawRect( QRectF( firstRClickPos, secondRClickPos ) );
+        painter.end();
+    }
+}
+
 #ifdef HAVE_XPLANET
 void SkyMap::startXplanet( const QString & outputFile ) {
     QString year, month, day, hour, minute, seconde, fov;
Index: kstarsdata.h
===================================================================
--- kstarsdata.h	(revision 1084185)
+++ kstarsdata.h	(working copy)
 <at>  <at>  -90,6 +90,7  <at>  <at> 
     friend class DetailDialog;
     // FIXME: uses geoList and changes it.
     friend class LocationDialog;
+    friend class SkyObjectList;
 
     static KStarsData* Create( );
 
Index: skymap.h
===================================================================
--- skymap.h	(revision 1084185)
+++ skymap.h	(working copy)
 <at>  <at>  -24,6 +24,7  <at>  <at> 
 
 #include "skyobjects/skypoint.h"
 #include "skyobjects/skyline.h"
+#include "dialogs/objectlist.h"
 
 #include <config-kstars.h>
 
 <at>  <at>  -441,6 +442,8  <at>  <at> 
     	*/
     void drawObjectLabels( QList<SkyObject*>& labelObjects, QPainter &psky );
 
+    void showObjectsInRectangle();
+
 public slots:
     //DEBUG_KIO_JOB
     void slotJobResult( KJob *j );
 <at>  <at>  -838,6 +841,8  <at>  <at> 
     SkyPoint  Focus, ClickedPoint, FocusPoint, MousePoint, Destination;
     SkyObject *ClickedObject, *FocusObject, *TransientObject;
 
+    SkyObjectList* skyObjectList;
+
     SkyLine AngularRuler; //The line for measuring angles in the map
     QRect ZoomRect; //The manual-focus circle.
 
 <at>  <at>  -854,6 +859,12  <at>  <at> 
     //QUATERNION
     Quaternion m_rotAxis;
 
+    // To record the first and second right click positions 
+    // and their corresponding sky points to find the starlist
+    // in the rectangle formed
+    QPointF firstRClickPos, secondRClickPos;
+    SkyPoint firstPoint, secondPoint;
+
     static SkyMap* pinstance;
 
 };
Index: kstars.h
===================================================================
--- kstars.h	(revision 1084185)
+++ kstars.h	(working copy)
 <at>  <at>  -25,6 +25,7  <at>  <at> 
 #include "tools/observinglist.h"
 #include "comast/equipmentwriter.h"
 #include "comast/observeradd.h"
+#include "dialogs/objectlist.h"
 
 // forward declaration is enough. We only need pointers
 class QPalette;
 <at>  <at>  -125,6 +126,8  <at>  <at> 
 
     ObservingList* observingList() { return obsList; }
 
+    SkyObjectList* objectList() { return skyObjectList; }
+
     Execute* getExecute();
 
     /** <at> return pointer to the INDI driver
 <at>  <at>  -660,6 +663,7  <at>  <at> 
 
     //FIXME: move to KStarsData
     ObservingList *obsList;
+    SkyObjectList* skyObjectList;
     EquipmentWriter *eWriter;
     ObserverAdd *oAdd;
     Execute *execute;
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 1084185)
+++ CMakeLists.txt	(working copy)
 <at>  <at>  -265,6 +265,7  <at>  <at> 
   dialogs/focusdialog.cpp
   dialogs/fovdialog.cpp
   dialogs/locationdialog.cpp
+  dialogs/objectlist.cpp
   dialogs/timedialog.cpp
 )
 
 <at>  <at>  -280,6 +281,7  <at>  <at> 
   dialogs/focusdialog.ui
   dialogs/fovdialog.ui
   dialogs/locationdialog.ui
+  dialogs/objectlist.ui
   dialogs/wizwelcome.ui
   dialogs/wizlocation.ui
   dialogs/wizdownload.ui
Index: skymapevents.cpp
===================================================================
--- skymapevents.cpp	(revision 1084185)
+++ skymapevents.cpp	(working copy)
 <at>  <at>  -616,7 +616,32  <at>  <at> 
         zoomOutOrMagStep( e->modifiers() );
 }
 
-void SkyMap::mouseReleaseEvent( QMouseEvent * ) {
+void SkyMap::mouseReleaseEvent( QMouseEvent * e ) {
+    if ( e->button() == Qt::RightButton ) {
+        kDebug() << "right click position after drag = " << QCursor::pos() << endl;
+	secondRClickPos = QCursor::pos();
+
+	// The new point after drag has to be recorded and saved for future use
+        setMousePoint( fromScreen( e->pos(), data->lst(), data->geo()->lat() ) );
+        mousePoint()->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
+        setClickedPoint( mousePoint() );
+        clickedPoint()->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
+	secondPoint = ClickedPoint;
+
+	//
+	// Once the first and second points (before and after drag respectively) 
+	// have been successfully recorded, show the sky objects formed in the rectangle 
+	// If the first and second points are the same, the information about that
+	// sky point has to be shown in popup menu; otherwise an attempt has to be
+	// made to find all the sky objects in the virtual rectangle formed by the 
+	// first and second skypoints. showObjectsInRectangle() function takes care 
+	// of both these scenarios.
+	//
+	showObjectsInRectangle();
+        
+	return;
+    }
+
     if ( ZoomRect.isValid() ) {
         //Zoom in on center of Zoom Circle, by a factor equal to the ratio
         //of the sky pixmap's width to the Zoom Circle's diameter
 <at>  <at>  -689,6 +714,11  <at>  <at> 
         setClickedPoint( mousePoint() );
         clickedPoint()->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
 
+	// Store this skypoint for future use 
+	// in case mouse is right-click dragged 
+	firstPoint = ClickedPoint;
+
+
         //Find object nearest to clickedPoint()
         double maxrad = 1000.0/Options::zoomFactor();
         setClickedObject( data->skyComposite()->objectNearest( clickedPoint(), maxrad ) );
 <at>  <at>  -696,8 +726,10  <at>  <at> 
         if ( clickedObject() ) {
             setClickedPoint( clickedObject() );
 
+            kDebug() << "moving the showing of popup menu from mousePressEvent() to mouseReleaseEvent()" << endl;
             if ( e->button() == Qt::RightButton ) {
-                clickedObject()->showPopupMenu( pmenu, QCursor::pos() );
+		firstRClickPos = QCursor::pos();
+                kDebug() << "first right click position before drag = " << firstRClickPos << endl;
             }
 
             if ( kstars && e->button() == Qt::LeftButton ) {
 <at>  <at>  -714,9 +746,8  <at>  <at> 
                     kstars->statusBar()->changeItem( i18n( "Empty sky" ), 0 );
                 break;
             case Qt::RightButton: {
-                SkyObject o( SkyObject::TYPE_UNKNOWN, clickedPoint()->ra()->Hours(), clickedPoint()->dec()->Degrees() );
-                pmenu->createEmptyMenu( &o );
-                pmenu->popup( QCursor::pos() );
+		firstRClickPos = QCursor::pos();
+                kDebug() << "first right click position before drag = " << firstRClickPos << endl;
                 break;
                 }
             default: ;
Index: skycomponents/starcomponent.cpp
===================================================================
--- skycomponents/starcomponent.cpp	(revision 1084185)
+++ skycomponents/starcomponent.cpp	(working copy)
 <at>  <at>  -639,6 +639,12  <at>  <at> 
     stardata->mag = bswap_16( stardata->mag );
     stardata->bv_index = bswap_16( stardata->bv_index );
 }
+
+StarList* StarComponent::starsInTrixel( Trixel trixel )
+{
+    return m_starIndex->at( trixel );
+}
+
 /*
 void StarComponent::printDebugInfo() {
 
Index: skycomponents/deepskycomponent.h
===================================================================
--- skycomponents/deepskycomponent.h	(revision 1084185)
+++ skycomponents/deepskycomponent.h	(working copy)
 <at>  <at>  -122,6 +122,7  <at>  <at> 
     virtual SkyObject* objectNearest( SkyPoint *p, double &maxrad );
 
     const QList<DeepSkyObject*>& objectList() const { return m_DeepSkyList; }
+    DeepSkyList* objectListInTrixel( Trixel trixel ) const;
 
     void clear();
 
Index: skycomponents/deepskycomponent.cpp
===================================================================
--- skycomponents/deepskycomponent.cpp	(revision 1084185)
+++ skycomponents/deepskycomponent.cpp	(working copy)
 <at>  <at>  -189,6 +189,9  <at>  <at> 
         }
 
         Trixel trixel = m_skyMesh->index( (SkyPoint*) o );
+	// Append the DeepSkyObject to m_DeepSkyIndex regardless
+	// of types. 
+	appendIndex( o, &m_DeepSkyIndex, trixel );
 
         //Assign object to general DeepSkyObjects list,
         //and a secondary list based on its catalog.
 <at>  <at>  -281,6 +284,10  <at>  <at> 
     dsIndex->value( trixel )->append( o );
 }
 
+DeepSkyList* DeepSkyComponent::objectListInTrixel( Trixel trixel ) const
+{
+    return (m_DeepSkyIndex.contains( trixel )? m_DeepSkyIndex.value( trixel ) : NULL);
+}
 
 void DeepSkyComponent::draw( QPainter& psky )
 {
Index: skycomponents/skymapcomposite.h
===================================================================
--- skycomponents/skymapcomposite.h	(revision 1084185)
+++ skycomponents/skymapcomposite.h	(working copy)
 <at>  <at>  -179,6 +179,8  <at>  <at> 
 
     ConstellationBoundaryLines* getConstellationBoundary() { return m_CBoundLines; }
 
+    DeepSkyComponent* deepSkyComponent() const { return m_DeepSky; }
+
 signals:
     void progressText( const QString &message );
 
Index: skycomponents/starcomponent.h
===================================================================
--- skycomponents/starcomponent.h	(revision 1084185)
+++ skycomponents/starcomponent.h	(working copy)
 <at>  <at>  -124,6 +124,8  <at>  <at> 
     // deepStarData fields
     static void byteSwap( starData *stardata );
 
+    StarList* starsInTrixel( Trixel trixel );
+
 private:
     /** <at> short Read data for stars which will remain static in the memory
      *
_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel
Abhijit Apte | 2 Feb 20:55
Picon

Re: Refined patch for wishlist 178232: List all objects within a rectangle

Another point, I forgot to mention it in my last mail..
In skymap.cpp (Pl. refer to patch):
(1) we find the trixels which are needed to cover the rectangular region of selection (right-click drag)
(2) once we have the trixels, we iterate thru the set of trixels to find the stars and deep sky objects.

As per your inputs, we might even think of moving the code which does (1) to a new public method in SkyMesh. What do your take?

On Wed, Feb 3, 2010 at 1:10 AM, Abhijit Apte <abhijit.apte <at> gmail.com> wrote:
Hi Alexey,

My comments inlined.

1. Patch fails to apply cleanly to current svn head. Please update it. Also
compilation fails so I cannot try your last patch.

Attached updated patch (this compiles this against the svn head -- commit 1083977). I think you/somebody have committed some changes into dialogs/detaildialog.cpp which were to be pull into dialogs/objectlist.cpp.

2. Current convention is to use 4 space for indentation and do not use tabs at
all. Please fix it.

Sure, would take care of it next time onward, actually problem is with 'set autoindent' and 'set cindent' of vim. :-(
 
3. Currently you search for objects in skymap.cpp. I think it outright bad
design. You have to enumerate all components by hands. This is error prone and
changes in skycomponents are likely break your code.

So, are you suggesting to distribute (move) the code which does the searching of objects to the respective components (i.e. the worker function you suggested below)?
 
I think better solution is to add function to SkyComponent to search for
objects and use virtual dispatch. Here is some example code.

-- Code snippet ---

class SkyComponent {
public:
   // Function which returns list of objects in given area.
   QList<SkyObject*> findObjectInArea(Area area)  {
       QList<SkyObject*> list;
       objectsInArea(list, area)
       return list;
   }
private:
   // This is worker function. It adds objects to list if they are in the
   // area. It should be reimplemented in subclasses.
   virtual void objectsInArea(QList<SkyObject*>&, Area);
};
----------------
 
Even if we implemented the way you've suggest, we'll still have to invoke the findObjectInArea() for each component (like StarComponent, DeepSkyComponent etc -- see below) from skymap.cpp right??

StarComponent* starComp;
StarList listOfStars = starComp->findObjectInArea(myarea);
DeepSkyComponent* deepSkyComp;
QList<DeepSkyObject*> listOfDSO = deepSkyComp->findObjectInArea(myarea);
//.. similarly for planets, etc???

Pl. shed more light on point#3 as this is little unclear to me. :P

4. Are there code from DetailsDialog in the SkyObjectList? If it's the case
just drop it. It's completely fine to have missing functionality for some time
and add it gradually. It's much easier to reason about code that way.

Yes, absolutely! Since, the detailed tabbed representation was to be merged with the list view (as per your earlier comments), I had to merge the entire code of DetailsDialog (detailsdialog.cpp and detailsdialog.h) into SkyObjectList (objectlist.cpp and objectlist.h).

The reason I did this was, going further, deprecate the existing detaildialog.* with objectlist.* and rename the latter SkyObjectList to DetailDialog.

5. Patch is huge. It would be nice if you split it into several smaller ones.
More below.

Yeah agree, didn't want to make it this huge, but as I went on making changes, realized there were far too many files that I had to modify than actually thought. :-)
 
Rgds
-Abhi

_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel
Khudyakov Alexey | 2 Feb 22:12
Picon
Gravatar

Re: Refined patch for wishlist 178232: List all objects within a rectangle

В сообщении от Вторник 02 февраля 2010 22:40:15 Abhijit Apte написал:
> Hi Alexey,
> 

> 1. Patch fails to apply cleanly to current svn head. Please update it. Also
> 
> > compilation fails so I cannot try your last patch.
> 
> Attached updated patch (this compiles this against the svn head -- commit
> 1083977 <http://websvn.kde.org/?view=revision&revision=1083977>). I think
> you/somebody have committed some changes into dialogs/detaildialog.cpp
>  which were to be pull into dialogs/objectlist.cpp.
> 
I'll try it tomorrow.

> > 3. Currently you search for objects in skymap.cpp. I think it outright
> > bad design. You have to enumerate all components by hands. This is error
> > prone and
> > changes in skycomponents are likely break your code.
> 
> So, are you suggesting to distribute (move) the code which does the
> searching of objects to the respective components (i.e. the worker function
> you suggested below)?
> 
Exactly. Idea is to keep all code related to some thing in one rather then 
spreaded all over codebase. It easier to work with it that way.

> > I think better solution is to add function to SkyComponent to search for
> > objects and use virtual dispatch. Here is some example code.
> >
> 
> Even if we implemented the way you've suggest, we'll still have to invoke
> the findObjectInArea() for each component (like StarComponent,
> DeepSkyComponent etc -- see below) from skymap.cpp right??
> 
> StarComponent* starComp;
> StarList listOfStars = starComp->findObjectInArea(myarea);
> DeepSkyComponent* deepSkyComp;
> QList<DeepSkyObject*> listOfDSO = deepSkyComp->findObjectInArea(myarea);
> //.. similarly for planets, etc???
> 
> Pl. shed more light on point#3 as this is little unclear to me. :P
> 
No we shouldn't. SkyComposites will handle all calls to components. All is 
needed is to call:
> skyComposite()->findObjectsInArea(myarea)
It will find all objects

You can check implementation of functions `objectNearest' and `findByName' in 
SkyComposite. They provide similar functionalty.

1) call SkyMapComposite::findObjectInArea(...)
2) it calls SkyMapsComposite::objectsInArea(...)
3) which in turn calls all the subcomponents and subcomposites.

Downside of this approach is that you get list of SkyObject* and all 
infomation about types is lost. It's price of uniformity and nothing could be 
done about it. 

If one wants to type information back he could use RTTI, dynamic_cast and 
things like that.

> Another point, I forgot to mention it in my last mail..
> In skymap.cpp (Pl. refer to patch):
> (1) we find the trixels which are needed to cover the rectangular region of
> selection (right-click drag)
> (2) once we have the trixels, we iterate thru the set of trixels to find the
> stars and deep sky objects.
>
> As per your inputs, we might even think of moving the code which does (1) to
> a new public method in SkyMesh. What do your take?

If you think that this function is useful implement it (-:

> 4. Are there code from DetailsDialog in the SkyObjectList? If it's the case
> 
> > just drop it. It's completely fine to have missing functionality for some
> > time
> > and add it gradually. It's much easier to reason about code that way.
> 
> Yes, absolutely! Since, the detailed tabbed representation was to be merged
> with the list view (as per your earlier comments), I had to merge the
>  entire code of DetailsDialog (detailsdialog.cpp and detailsdialog.h) into
>  SkyObjectList (objectlist.cpp and objectlist.h).
> 
> The reason I did this was, going further, deprecate the existing
> detaildialog.* with objectlist.* and rename the latter SkyObjectList to
> DetailDialog.
> 
I think you shouldn't merge _entire_ details dialog. Old code will interfere 
with your work. (It is "will" not "could" judging from my experience). 

Probably it's better to put minimal stubs just to makething compile and run. 
After that old code could be pulled gradually one feature after another. Point 
is to make process controlled and understandable.

Also it offers opportunity to clean up existing code. It is far from 
perfection.

This approach has added benefit. I could commit patches to SVN without having 
complete dialog. 

> 5. Patch is huge. It would be nice if you split it into several smaller
> 
> > ones.
> > More below.
> >
> > Yeah agree, didn't want to make it this huge, but as I went on making
> 
> changes, realized there were far too many files that I had to modify than
> actually thought. :-)
> 
This how it goes all the time. You begin to work on small feature and end up 
with huge patch. "Complexity managing" is just about such thing. Programmer 
has to work actively againist such thing. 

There is one candidate for separate patch already. It is code for searching 
for objects. 
_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel
Khudyakov Alexey | 2 Feb 22:30
Picon
Gravatar

Re: Exporting to video

Hi Yannis.

В сообщении от Вторник 02 февраля 2010 13:46:27 Yiannis Belias написал:
> Hi all,
>   Just FYI. Yesterday I made a video simulation[0] of the upcoming lunar
>  occultation of pleiades for my local astronomy club. So I used ktars and
>  I'd like to share a few things with you.
> 
Thank you for feedback. 

> 1. I used the script builder for start, but I found out I would have to use
>  a more "spiced up" shell script[attatched] for this job. (To tell the
>  truth, I was expecting something more javascript like...) 
>
I think you confim my suspicions about general uselessness of script builder. 
No ifs no loops no control structues at all. Pretty useless.

I'll write more in-depth e-mail on the subject later.

>  2. I had to use
>  for loops with explicit dates to increase the time interval. It would be
>  much better if I could just step forward for a specified time step.
>
Such function could be added.

> 3. I found out that when the kstars window was smaller than the capture
>  window, the output frames were blank[white] at that region. (Don't scratch
>  your heads - *netbook* :) )

>  4. The whole process of creating about 1000
>  frames is really slow.
>
Rendering is painfully slow. On my laptop it takes about a second to render 
screen with maximum stellar density. This should be improved but I don't know 
how.

>  5. I didn't find a way to display the time/date
>  info from within kstars, so I used the convert utility from imagemagick.
>
Yes there isn't function to do this.

> 6. The stars motion as you can see on the video is a bit "funky" :) I had
>  antialiasing switched off though.
> 
Without antialiasing stars positions are rounded to integer pixels. I think 
this could be fixed.

Curently stars are rendered using pixmaps. There are cached pixmap for stars 
of diferent size and color. It is possible to generate pixmaps for stars for 
each subpixel offset. This could be a speed advantage. I came up with such 
scheme to speed up drawing without sacrificing antialiasing.

There is a drawback. Cache grows up significantly. If images are generated for 
0.25 offset cache become 16x bigger. But this is not a big deal I presume.
_______________________________________________
Kstars-devel mailing list
Kstars-devel <at> kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel

Gmane