Re: Refined patch for wishlist 178232: List all objects within a rectangle
Abhijit Apte <abhijit.apte <at> gmail.com>
2010-02-02 19:40:15 GMT
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>&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>&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