QTタスクバートレイアイコンプログラムを実現


  •  int main(intargc,char*argv[])
  • {
  •     QApplication app(argc, argv);
  •     app.setApplicationName(app.translate("main",
  •                                          "Weather Tray Icon"));
  •     app.setOrganizationName("Qtrac Ltd.");
  •     app.setOrganizationDomain("qtrac.eu");
  • #ifdef Q_WS_MAC
  •     app.setCursorFlashTime(0);
  • #endif
  •     app.setQuitOnLastWindowClosed(false);
  •     if (int error = enableNetworkProxying())
  •         return error;
  •  
  •     WeatherTrayIcon weatherTrayIcon;
  •     weatherTrayIcon.show();
  •     return app.exec();
  • }
  •  11      ,                      ,                     
  • int enableNetworkProxying()
  • {
  •     AQP::OptionParser parser(qApp->arguments(), qApp->translate(
  •             "main",
  •             "usage: {program} [options]

    "
  •             "To use a proxy server set the host and port,
    "
  •             "and if required the username, password, and proxy "
  •             "type.

    Version
    1.0.0 Copyright (c) 2010 Qtrac Ltd. "
  •             "All rights reserved.
    "
    ));
  •     AQP::StringOptionPtr typeOpt = parser.addStringOption(
  •             "t", "type");
  •     typeOpt->setHelp(qApp->translate("main", "proxy type"));
  •     typeOpt->setDefaultValue("socks5");
  •     typeOpt->setAcceptableValues(QStringList() << "socks5" << "http");
  •     AQP::StringOptionPtr hostOpt = parser.addStringOption(
  •             "H", "host");
  •     hostOpt->setHelp(qApp->translate("main",
  •             "hostname, e.g., www.example.com"));
  •     AQP::IntegerOptionPtr portOpt = parser.addIntegerOption(
  •             "p", "port");
  •     portOpt->setHelp(qApp->translate("main",
  •             "port number, e.g., 1080"));
  •     AQP::StringOptionPtr userOpt = parser.addStringOption(
  •             "u", "username");
  •     userOpt->setHelp(qApp->translate("main", "username"));
  •     AQP::StringOptionPtr passwordOpt = parser.addStringOption(
  •             "P", "password");
  •     passwordOpt->setHelp(qApp->translate("main", "password"));
  •     if (!parser.parse())
  •         return 2;
  •  
  •     if (parser.hasValue("host")) {
  •         QNetworkProxy proxy;
  •         proxy.setType(parser.string("type") == "socks5"
  •                 ? QNetworkProxy::Socks5Proxy
  •                 : QNetworkProxy::HttpProxy);
  •         proxy.setHostName(parser.string("host"));
  •         if (parser.hasValue("port"))
  •             proxy.setPort(parser.integer("port"));
  •         if (parser.hasValue("username"))
  •             proxy.setUser(parser.string("username"));
  •         if (parser.hasValue("password"))
  •             proxy.setPassword(parser.string("password"));
  •         QNetworkProxy::setApplicationProxy(proxy);
  •     }
  •     return 0;
  • }
  •  32    ,                  .      ,   ,   ,   ,  
                    .       socket    QAbstractSocket::setProxy
                WeatherTrayIcon 
     
  • class WeatherTrayIcon : public QSystemTrayIcon
  • {
  •     Q_OBJECT
  •  
  • public:
  •     explicit WeatherTrayIcon();
  •  
  • private slots:
  •     void requestXml();
  •     void readXml(QNetworkReply *reply);
  •     void readIcon(QNetworkReply *reply);
  •     void setAirport(QAction *action);
  •  
  • private:
  •     void createContextMenu();
  •     void populateToolTip(QDomDocument *document);
  •     QString toolTipField(const QString &name,
  •             const QString &htmlColor, const QString &value,
  •             bool appendBr=true);
  •     QString textForTag(const QString &tag, QDomDocument *document);
  •  
  •     QMenu menu;
  •     QNetworkAccessManager *networkXmlAccess;
  •     QNetworkAccessManager *networkIconAccess;
  •     QString airport;
  •     QCache<QUrl, QIcon> iconCache;
  •     int retryDelaySec;
  • };
  •        Qt    QSystemTrayIcon   .       QObject   .
      ,              .
     25  airport        
     26  iconCache      URL                 
      ,            ,         WeatherTrayIcon();
  • WeatherTrayIcon::WeatherTrayIcon()
  •     : QSystemTrayIcon(), retryDelaySec(1)
  • {
  •     setIcon(QIcon(":/rss.png"));
  •     createContextMenu();
  •  
  •     networkXmlAccess = new QNetworkAccessManager(this);
  •     networkIconAccess = new QNetworkAccessManager(this);
  •     connect(networkXmlAccess, SIGNAL(finished(QNetworkReply*)),
  •             this, SLOT(readXml(QNetworkReply*)));
  •     connect(networkIconAccess, SIGNAL(finished(QNetworkReply*)),
  •             this, SLOT(readIcon(QNetworkReply*)));
  •  
  •     QTimer::singleShot(0, this, SLOT(requestXml()));
  • }
  •                  .
           
               ,           
           ,     
        requestXml()  
       requestXml()     ,   createContextMenu()         
  • void WeatherTrayIcon::createContextMenu()
  • {
  •     QStringList airports;
  •     airports << "Austin-Bergstrom International Airport (KAUS)"
  •              << "Chicago/Ohare (KORD)"
  •              << "Dallas / Fort Worth International Airport (KDFW)"
  •              << "Detroit City Airport (KDET)"
  •              << "Houston Intercontinental Airport (KIAH)"
  •              << "Indianapolis International Airport (KIND)"
  •              << "Jacksonville International Airport (KJAX)"
  •              << "Los Angeles Intl Airport (KLAX)"
  •              << "New York/John F. Kennedy Intl Airport (KJFK)"
  •              << "Philadelphia International Airport (KPHL)"
  •              << "Phoenix/Sky Harbor (KPHX)"
  •              << "Port Columbus International Airport (KCMH)"
  •              << "San Antonio International Airport (KSAT)"
  •              << "San Diego/Brown Fld (KSDM)"
  •              << "San Francisco Intl Airport (KSFO)"
  •              << "San Jose International Airport (KSJC)";
  •     QSettings settings;
  •     airport = settings.value("airport", QVariant(airports.at(0)))
  •                              .toString();
  •  
  •     QActionGroup *group = new QActionGroup(this);
  •     foreach (const QString &anAirport, airports) {
  •         QAction *action = menu.addAction(anAirport);
  •         group->addAction(action);
  •         action->setCheckable(true);
  •         action->setChecked(anAirport == airport);
  •         action->setData(anAirport);
  •     }
  •     connect(group, SIGNAL(triggered(QAction*)),
  •             this, SLOT(setAirport(QAction*)));
  •     menu.addSeparator();
  •     menu.addAction(QIcon(":/exit.png"), tr("E&xit"), qApp,
  •                    SLOT(quit()));
  •  
  •     AQP::accelerateMenu(&menu);
  •     setContextMenu(&menu);
  • }
  •                  ,          ,         
    foreach               ,  action  action  ,    action  
          QSystemTrayIcon   
     
  • void WeatherTrayIcon::requestXml()
  • {
  •     QString airportId = airport.right(6);
  •     if (airportId.startsWith("(") && airportId.endsWith(")")) {
  •         QString url = QString("http://www.weather.gov/xml/"
  •                 "current_obs/%1.xml").arg(airportId.mid(1, 4));
  •         networkXmlAccess->get(QNetworkRequest(QUrl(url)));
  •     }
  •     setToolTip(tr("Failed to connect to network.
    "
  •             "A proxy can be set on the command line:
    "
  •             "weathertrayicon --help"));
  • }
  • networkXmlAccess QNetworkRequest      get  ,                        
  • void WeatherTrayIcon::readXml(QNetworkReply *reply)
  • {
  •     if (reply->error() != QNetworkReply::NoError) {
  •         setToolTip(tr("Failed to retrieve weather data:
    %1"
    )
  •                    .arg(reply->errorString()));
  •         QTimer::singleShot(retryDelaySec * 1000,
  •                            this, SLOT(requestXml()));
  •         retryDelaySec <<= 1;
  •         if (retryDelaySec > 60 * 60)
  •             retryDelaySec = 1;
  •         return;
  •     }
  •     retryDelaySec = 1;
  •     QDomDocument document;
  •     if (document.setContent(reply))
  •         populateToolTip(&document);
  •     QTimer::singleShot(60 * 60 * 1000, this, SLOT(requestXml()));
  • }
  •                     ,               
  • void WeatherTrayIcon::readIcon(QNetworkReply *reply)
  • {
  •     QUrl redirect = reply->attribute(
  •             QNetworkRequest::RedirectionTargetAttribute).toUrl();
  •     if (redirect.isValid())
  •         networkIconAccess->get(QNetworkRequest(redirect));
  •     else {
  •         QByteArray ba(reply->readAll());
  •         QPixmap pixmap;
  •         if (pixmap.loadFromData(ba)) {
  •             QIcon *icon = new QIcon(pixmap);
  •             setIcon(*icon);
  •             iconCache.insert(reply->request().url(), icon);
  •         }
  •     }
  • }
  •                   ,                     
        reply           , QPixmap    ,    QIcon,    Icon,   iconCache 
     
         ,  <<Qt     >>,          
    
     :          .          http://shop71746057.taobao.com/