selectionpopup.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:18k
源码类别:

OpenGL

开发平台:

Visual C++

  1. /***************************************************************************
  2.                           selectionpopup.cpp  -  description
  3.                              -------------------
  4.     begin                : 2003-05-06
  5.     copyright            : (C) 2002 by Christophe Teyssier
  6.     email                : chris@teyssier.org
  7.  ***************************************************************************/
  8. /***************************************************************************
  9.  *                                                                         *
  10.  *   This program is free software; you can redistribute it and/or modify  *
  11.  *   it under the terms of the GNU General Public License as published by  *
  12.  *   the Free Software Foundation; either version 2 of the License, or     *
  13.  *   (at your option) any later version.                                   *
  14.  *                                                                         *
  15.  ***************************************************************************/
  16. #include <libintl.h>
  17. #include <sstream>
  18. #include <fstream>
  19. #include <algorithm>
  20. #include "selectionpopup.h"
  21. #include <qlabel.h>
  22. #include <klocale.h>
  23. #include <kurl.h>
  24. #include <krun.h>
  25. #include "celutil/utf8.h"
  26. #include "celestia/celestiacore.h"
  27. #include "celengine/axisarrow.h"
  28. #include "celengine/planetgrid.h"
  29. SelectionPopup::SelectionPopup(QWidget* parent, CelestiaCore* _appCore, Selection _sel):
  30. KPopupMenu(parent),
  31.  appCore(_appCore),
  32.  sel(_sel),
  33.  baseId(0)
  34. {
  35. }
  36. SelectionPopup::~SelectionPopup() {
  37. }
  38. void SelectionPopup::init()
  39. {
  40.     QPalette pal( palette() );
  41.     pal.setColor( QPalette::Normal, QColorGroup::Background, QColor( "White" ) );
  42.     pal.setColor( QPalette::Normal, QColorGroup::Foreground, QColor( "Black" ) );
  43.     pal.setColor( QPalette::Inactive, QColorGroup::Foreground, QColor( "Black" ) );
  44.     QFont rsFont = font();
  45.     rsFont.setPointSize( rsFont.pointSize() - 2 );
  46.     Simulation *sim = appCore->getSimulation();
  47.     Vec3d v = sel.getPosition(sim->getTime()) - sim->getObserver().getPosition();
  48.     if (sel.body() != NULL)
  49.     {
  50.         insertTitle(QString::fromUtf8(sel.body()->getName(true).c_str()), 0, 0);
  51.         insert(this, sel);
  52.     }
  53.     else if (sel.star() != NULL)
  54.     {
  55.         std::string name = sim->getUniverse()->getStarCatalog()->getStarName(*sel.star());
  56.         double distance = v.length() * 1e-6;
  57.         char buff[50];
  58.         ostringstream o;
  59.         setlocale(LC_NUMERIC, "");
  60.         if (abs(distance) >= astro::AUtoLightYears(1000.0f))
  61.             sprintf(buff, "%'.3f %s", distance, _("ly"));
  62.         else if (abs(distance) >= astro::kilometersToLightYears(10000000.0))
  63.             sprintf(buff, "%'.3f %s", astro::lightYearsToAU(distance), _("au"));
  64.         else if (abs(distance) > astro::kilometersToLightYears(1.0f))
  65.             sprintf(buff, "%'.3f km", astro::lightYearsToKilometers(distance));
  66.         else
  67.             sprintf(buff, "%'.3f m", astro::lightYearsToKilometers(distance) * 1000.0f);
  68.         o << i18n("Distance: ") << QString::fromUtf8(buff) << "n";
  69.         o << i18n("Abs (app) mag: ");
  70.         sprintf(buff, "%'.2f (%.2f)",
  71.                    sel.star()->getAbsoluteMagnitude(),
  72.                    astro::absToAppMag(sel.star()->getAbsoluteMagnitude(),
  73.                                       (float) distance));
  74.         o << QString::fromUtf8(buff) << "n";
  75.         o << i18n("Class: ");
  76.         sprintf(buff, "%s", sel.star()->getSpectralType());
  77.         o << QString::fromUtf8(buff) << "n";
  78.         o << i18n("Surface Temp: ");
  79.         sprintf(buff, "%'.0f K", sel.star()->getTemperature());
  80.         o << QString::fromUtf8(buff) << "n";
  81.         o << i18n("Radius: ");
  82.         sprintf(buff, "%'.2f %s", sel.star()->getRadius() / 696000.0f, _("Rsun"));
  83.         o << QString::fromUtf8(buff);
  84.         setlocale(LC_NUMERIC, "C");
  85.         QLabel *starDetails = new QLabel(QString(o.str().c_str()), this);
  86.         starDetails->setPalette(pal);
  87.         starDetails->setFont(rsFont);
  88.         insertTitle(QString::fromUtf8(ReplaceGreekLetterAbbr(name).c_str()), 0, 0);
  89.         insertItem(starDetails);
  90.         insertSeparator();
  91.         insert(this, sel);
  92.     }
  93.     else if (sel.deepsky() != NULL)
  94.     {
  95.         insertTitle(QString::fromUtf8(sim->getUniverse()->getDSOCatalog()->getDSOName(sel.deepsky()).c_str()), 0);
  96.         insert(this, sel);
  97.     }
  98.     if (sim->getUniverse() != NULL)
  99.     {
  100.         MarkerList* markers = sim->getUniverse()->getMarkers();
  101.         if (markers->size() > 0)
  102.         {
  103.             KPopupMenu *markMenu = new KPopupMenu(this);
  104.             int j=1;
  105.             for (std::vector<Marker>::iterator i = markers->begin(); i < markers->end(); i++)
  106.             {
  107.                 KPopupMenu *objMenu = new KPopupMenu(this);
  108.                 insert(objMenu, (*i).object(), false);
  109.                 markMenu->insertItem(QString::fromUtf8(getSelectionName((*i).object())), objMenu);
  110.                 j++;
  111.             }
  112.             insertItem(i18n("Marked objects"), markMenu);
  113.         }
  114.     }
  115. }
  116. void SelectionPopup::process(int id)
  117. {
  118.     if (id < 0) return;
  119.     Simulation *sim = appCore->getSimulation();
  120.     sel = getSelectionFromId(id);
  121.     int actionId = id - baseId;
  122.     if (actionId == 1) {
  123.         sim->setSelection(sel);
  124.         return;
  125.     }
  126.     if (actionId == 2) {
  127.         sim->setSelection(sel);
  128.         appCore->charEntered('c');
  129.         return;
  130.     }
  131.     if (actionId == 3) {
  132.         sim->setSelection(sel);
  133.         appCore->charEntered('g');
  134.         return;
  135.     }
  136.     if (actionId == 4) {
  137.         sim->setSelection(sel);
  138.         appCore->charEntered('f');
  139.         return;
  140.     }
  141.     if (actionId == 5) {
  142.         sim->setSelection(sel);
  143.         appCore->charEntered('y');
  144.         return;
  145.     }
  146.     if (actionId == 6) {
  147.         QString url;
  148.         if (sel.body() != NULL)
  149.         {
  150.             url = QString(sel.body()->getInfoURL().c_str());
  151.             if (url == "")
  152.             {
  153.                 QString name = QString(sel.body()->getName().c_str()).lower();
  154.                 url = QString("http://www.nineplanets.org/") + name + ".html";
  155.             }
  156.         }
  157.         else if (sel.star() != NULL)
  158.         {
  159.             if (sel.star()->getCatalogNumber() != 0)
  160.                 url = QString("http://simbad.u-strasbg.fr/sim-id.pl?protocol=html&Ident=HIP %1")
  161.                       .arg(sel.star()->getCatalogNumber() & ~0xf0000000);
  162.             else
  163.                 url = QString("http://www.nineplanets.org/sun.html");
  164.         }
  165.         else if (sel.deepsky() != NULL)
  166.         {
  167.             url = QString(sel.deepsky()->getInfoURL().c_str());
  168.             if (url == "")
  169.                 url = QString("http://simbad.u-strasbg.fr/sim-id.pl?protocol=html&Ident=%1")
  170.                       .arg(sim->getUniverse()->getDSOCatalog()->getDSOName(sel.deepsky()).c_str());
  171.         }
  172.         KRun::runURL(url, "text/html");
  173.         return;
  174.     }
  175.     if (actionId == 7)
  176.     {
  177.         if (sim->getUniverse() != NULL)
  178.             sim->getUniverse()->unmarkObject(sel, 1);
  179.         return;
  180.     }
  181.     if (actionId == 8)
  182.     {
  183.         sim->getUniverse()->unmarkAll();
  184.         return;
  185.     }
  186.     if (actionId >= 10 && actionId < 25)
  187.     {
  188.         if (sim->getUniverse() != NULL)
  189.         {
  190.             MarkerRepresentation markerRep((MarkerRepresentation::Symbol) (actionId - 1), 10.0f, Color(0.0f, 1.0f, 0.0f, 0.9f));
  191.             sim->getUniverse()->markObject(sel, markerRep, 1);
  192.         }
  193.         return;
  194.     }
  195.     if (actionId >=25 && actionId < 31 && sel.body() != NULL) 
  196.     {
  197.         switch(actionId)
  198.         {
  199.         case 25:
  200. appCore->toggleReferenceMark("body axes");
  201.             break;
  202.         case 26:
  203. appCore->toggleReferenceMark("frame axes");
  204.             break;
  205.         case 27:
  206. appCore->toggleReferenceMark("sun direction");
  207.             break;
  208.         case 28:
  209. appCore->toggleReferenceMark("velocity vector");
  210.             break;
  211. case 29:
  212. appCore->toggleReferenceMark("planetographic grid");
  213.     break;
  214. case 30:
  215. appCore->toggleReferenceMark("terminator");
  216.     break;
  217.         }
  218.     }
  219.     if (actionId == 31) {
  220.         sim->getActiveObserver()->setDisplayedSurface("");
  221.         return;
  222.     }
  223.     if (actionId > 31) {
  224.         std::vector<std::string>* altSurfaces = sel.body()->getAlternateSurfaceNames();
  225.         if (altSurfaces != NULL && (int) altSurfaces->size() > actionId - 32)
  226.         {
  227.             sim->getActiveObserver()->setDisplayedSurface((*altSurfaces)[actionId - 32]);
  228.         }
  229.     }
  230. }
  231. const char* SelectionPopup::getSelectionName(const Selection& sel) const
  232. {
  233.     if (sel.body() != NULL)
  234.         return sel.body()->getName(true).c_str();
  235.     else if (sel.star() != NULL)
  236.         return ReplaceGreekLetterAbbr(appCore->getSimulation()->getUniverse()->getStarCatalog()->getStarName(*(sel.star()))).c_str();
  237.     else if (sel.deepsky() != NULL)
  238.         return appCore->getSimulation()->getUniverse()->getDSOCatalog()->getDSOName(sel.deepsky()).c_str();
  239.     return "";
  240. }
  241. Selection SelectionPopup::getSelectionFromId(int id)
  242. {
  243.     for(std::vector< std::pair<int, Selection> >::const_iterator i = baseIds.begin() + 1;
  244.         i != baseIds.end();
  245.         ++i) {
  246.         if ((*i).first > id) {
  247.             baseId = (*(i-1)).first;
  248.             return (*(i-1)).second;
  249.         }
  250.     }
  251.     baseId = baseIds.back().first;
  252.     return baseIds.back().second;
  253. }
  254. void SelectionPopup::insert(KPopupMenu *popup, Selection sel, bool showSubObjects)
  255. {
  256.     baseIds.push_back(make_pair(baseId, sel));
  257.     int locBaseId = baseId;
  258.     popup->insertItem(i18n("&Select"), baseId + 1);
  259.     popup->insertItem(i18n("&Center"), baseId + 2);
  260.     popup->insertItem(i18n("&Goto"), baseId + 3);
  261.     popup->insertItem(i18n("&Follow"), baseId + 4);
  262.     if (sel.star() == NULL && sel.deepsky() == NULL)
  263.         popup->insertItem(i18n("S&ynch Orbit"), baseId + 5);
  264.     popup->insertItem(i18n("&Info"), baseId + 6);
  265.     if (baseId == 0)
  266.         popup->insertItem(i18n("Unmark &All"), baseId + 8);
  267.     if (appCore->getSimulation()->getUniverse()->isMarked(sel, 1))
  268.     {
  269.         popup->insertItem(i18n("&Unmark"), baseId + 7);
  270.     }
  271.     else
  272.     {
  273.         KPopupMenu *markMenu = new KPopupMenu(this);
  274.         markMenu->insertItem(i18n("Diamond"), baseId + 10);
  275.         markMenu->insertItem(i18n("Triangle"), baseId + 11);
  276.         markMenu->insertItem(i18n("Square"), baseId + 12);
  277.         markMenu->insertItem(i18n("Filled Square"), baseId + 13);
  278.         markMenu->insertItem(i18n("Plus"), baseId + 14);
  279.         markMenu->insertItem(i18n("X"), baseId + 15);
  280.         markMenu->insertItem(i18n("Left Arrow"), baseId + 16);
  281.         markMenu->insertItem(i18n("Right Arrow"), baseId + 17);
  282.         markMenu->insertItem(i18n("Up Arrow"), baseId + 18);
  283.         markMenu->insertItem(i18n("Down Arrow"), baseId + 19);
  284.         markMenu->insertItem(i18n("Circle"), baseId + 20);
  285.         markMenu->insertItem(i18n("Disk"), baseId + 21);
  286.         popup->insertItem(i18n("&Mark"), markMenu);
  287.     }
  288.     if (sel.body() != NULL) {
  289.         KPopupMenu *refVectorMenu = new KPopupMenu(this);
  290.         refVectorMenu->setCheckable(true);
  291.         popup->insertItem(i18n("&Reference Vectors"), refVectorMenu);
  292.         refVectorMenu->insertItem(i18n("Show Body Axes"), baseId + 25);
  293.         refVectorMenu->setItemChecked(baseId + 25, sel.body()->findReferenceMark("body axes"));
  294.         refVectorMenu->insertItem(i18n("Show Frame Axes"), baseId + 26);
  295.         refVectorMenu->setItemChecked(baseId + 26, sel.body()->findReferenceMark("frame axes"));
  296.         refVectorMenu->insertItem(i18n("Show Sun Direction"), baseId + 27);
  297.         refVectorMenu->setItemChecked(baseId + 27, sel.body()->findReferenceMark("sun direction"));
  298.         refVectorMenu->insertItem(i18n("Show Velocity Vector"), baseId + 28);
  299.         refVectorMenu->setItemChecked(baseId + 28, sel.body()->findReferenceMark("velocity vector"));
  300.         refVectorMenu->insertItem(i18n("Show Planetographic Grid"), baseId + 29);
  301.         refVectorMenu->setItemChecked(baseId + 29, sel.body()->findReferenceMark("planetographic grid"));
  302.         refVectorMenu->insertItem(i18n("Show Terminator"), baseId + 30);
  303.         refVectorMenu->setItemChecked(baseId + 30, sel.body()->findReferenceMark("terminator"));
  304.     }
  305.     baseId += 31;
  306.     if (showSubObjects && sel.body() != NULL)
  307.     {
  308.         std::vector<std::string>* altSurfaces = sel.body()->getAlternateSurfaceNames();
  309.         if (altSurfaces != NULL)
  310.         {
  311.             if (!altSurfaces->empty())
  312.             {
  313.                 KPopupMenu *surfaces = new KPopupMenu(this);
  314.                 surfaces->insertItem(i18n("Normal"), locBaseId + 31);
  315.                 int j=0;
  316.                 for (std::vector<std::string>::const_iterator i = altSurfaces->begin();
  317.                      i < altSurfaces->end(); i++, j++)
  318.                 {
  319.                     surfaces->insertItem(QString((*i).c_str()), locBaseId + 32 + j);
  320.                 }
  321.                 baseId += 7 + j;
  322.                 popup->insertItem(i18n("&Alternate Surfaces"), surfaces);
  323.             }
  324.             delete altSurfaces;
  325.         }
  326.         const PlanetarySystem* satellites = sel.body()->getSatellites();
  327.         if (satellites != NULL && satellites->getSystemSize() != 0)
  328.         {
  329.             insertPlanetaryMenu(popup, getSelectionName(sel), satellites);
  330.         }
  331.     }
  332.     else if (showSubObjects && sel.star() != NULL)
  333.     {
  334.         Simulation *sim = appCore->getSimulation();
  335.         SolarSystemCatalog* solarSystemCatalog = sim->getUniverse()->getSolarSystemCatalog();
  336.         SolarSystemCatalog::iterator iter = solarSystemCatalog->find(sel.star()->getCatalogNumber());
  337.         if (iter != solarSystemCatalog->end())
  338.         {
  339.             SolarSystem* solarSys = iter->second;
  340.             insertPlanetaryMenu(popup, getSelectionName(sel), solarSys->getPlanets());
  341.         }
  342.     }
  343. }
  344. struct BodyComparePredicate
  345. {
  346.     bool operator()(Body* a, Body* b)
  347.     {
  348.         return (a->getName(true).compare(b->getName(true)) < 0);
  349.     }
  350. };
  351. void SelectionPopup::insertPlanetaryMenu(KPopupMenu* popup, const string& parentName, const PlanetarySystem* psys) {
  352.     std::vector<Body*> asteroids;
  353.     std::vector<Body*> comets;
  354.     std::vector<Body*> invisibles;
  355.     std::vector<Body*> moons;
  356.     std::vector<Body*> planets;
  357.     std::vector<Body*> spacecraft;
  358.     std::vector<Body*> smallBodies;
  359.     std::vector<Body*> dwarfPlanets;
  360.     std::vector<std::vector<Body*>* > objects;
  361.     std::vector<std::string> menuNames;
  362.     // Add each vector of PlanetarySystem bodies to a vector to iterate over
  363.     objects.push_back(&asteroids);
  364.     menuNames.push_back(QString::fromUtf8(_("Asteroids")));
  365.     objects.push_back(&comets);
  366.     menuNames.push_back(QString::fromUtf8(_("Comets")));
  367.     objects.push_back(&moons);
  368.     menuNames.push_back(QString::fromUtf8(_("Moons")));
  369.     objects.push_back(&planets);
  370.     menuNames.push_back(QString::fromUtf8(_("Planets")));
  371.     objects.push_back(&spacecraft);
  372.     menuNames.push_back(QString::fromUtf8(_("Spacecraft")));
  373.     objects.push_back(&smallBodies);
  374.     menuNames.push_back(QString::fromUtf8(_("Small Bodies")));
  375.     objects.push_back(&dwarfPlanets);
  376.     menuNames.push_back(QString::fromUtf8(_("Dwarf Planets")));
  377.     for (int i = 0; i < psys->getSystemSize(); i++) {
  378.         Body* body = psys->getBody(i);
  379.         switch(body->getClassification()) {
  380.         case Body::Asteroid:
  381.             asteroids.push_back(body);
  382.             break;
  383.         case Body::Comet:
  384.             comets.push_back(body);
  385.             break;
  386.         case Body::Moon:
  387.             moons.push_back(body);
  388.             break;
  389.         case Body::Planet:
  390.             planets.push_back(body);
  391.             break;
  392.         case Body::Spacecraft:
  393.             spacecraft.push_back(body);
  394.             break;
  395.         case Body::SmallBody:
  396.             smallBodies.push_back(body);
  397.             break;
  398.         case Body::DwarfPlanet:
  399.             dwarfPlanets.push_back(body);
  400.             break;
  401.         case Body::Invisible:
  402.         case Body::Barycenter:
  403.             break;
  404.         }
  405.     }
  406.     // Count how many submenus we need to create
  407.     int numSubMenus = 0;
  408.     int nonEmpty = 0;
  409.     for (std::vector<std::vector<Body*>* >::const_iterator obj = objects.begin();
  410.          obj != objects.end();
  411.          ++obj) {
  412.         if ((*obj)->size() > 0) {
  413.             numSubMenus++;
  414.             nonEmpty = obj - objects.begin();
  415.         }
  416.     }
  417.     if (numSubMenus == 0) return;
  418.     KPopupMenu *submenu = new KPopupMenu(this);
  419.     popup->insertSeparator();
  420.     if (numSubMenus > 1)
  421.         popup->insertItem(i18n("Orbiting Bodies"), submenu);
  422.     else
  423.         popup->insertItem(menuNames[nonEmpty], submenu);
  424.     std::vector<std::string>::const_iterator menuName = menuNames.begin();
  425.     BodyComparePredicate pred;
  426.     for (std::vector<std::vector<Body*>* >::const_iterator obj = objects.begin();
  427.          obj != objects.end();
  428.          ++obj) {
  429.         // Only generate a submenu if the vector is not empty
  430.         if ((*obj)->size() > 0) {
  431.             // Don't create a submenu for a single item
  432.             if ((*obj)->size() == 1) {
  433.                 std::vector<Body*>::const_iterator it = (*obj)->begin();
  434.                 Selection s(*it);
  435.                 KPopupMenu *objMenu = new KPopupMenu(this);
  436.                 insert(objMenu, s);
  437.                 submenu->insertItem(QString::fromUtf8((*it)->getName(true).c_str()), objMenu);
  438.             } else {
  439.                 // Skip sorting if we are dealing with the planets in our own Solar System.
  440.                  if (parentName != "Sol" || *menuName != QString::fromUtf8(_("Planets")))
  441.                      std::sort((*obj)->begin(), (*obj)->end(), pred);
  442.                 if (numSubMenus > 1) {
  443.                     // Add items to submenu
  444.                     KPopupMenu* objMenu = new KPopupMenu(this);
  445.                     for(std::vector<Body*>::const_iterator it = (*obj)->begin(); it != (*obj)->end(); ++it) {
  446.                         Selection s(*it);
  447.                         KPopupMenu *menu = new KPopupMenu(this);
  448.                         insert(menu, s);
  449.                         objMenu->insertItem(QString::fromUtf8((*it)->getName(true).c_str()), menu);
  450.                     }
  451.                     submenu->insertItem(*menuName, objMenu);
  452.                 } else {
  453.                     // Just add items to the popup
  454.                     for(std::vector<Body*>::const_iterator it = (*obj)->begin(); it != (*obj)->end(); ++it) {
  455.                         Selection s(*it);
  456.                         KPopupMenu *menu = new KPopupMenu(this);
  457.                         insert(menu, s);
  458.                         submenu->insertItem(QString::fromUtf8((*it)->getName(true).c_str()), menu);
  459.                     }
  460.                 }
  461.             }
  462.         }
  463.         menuName++;
  464.     }
  465. }