Update 1: I have recently found out that WT communicates using TCP (HTTP), if that helps anyone.
The title says it all, is it possible to run 2 different WT applications or projects on the same port? I know WT has come control over how the application is hosted with its start up parameters as follows. I am using Visual Studio 2010 and the parameters below are entered in the debugging->command arguments box as follows:
--http-address=0.0.0.0 --http-port=8080 --deploy-path=/hello --docroot=.
The above parameters will require that the user opens a web page at
http://127.0.0.1:8080/hello
So I though, hey what if I host another project with the below parameters
--http-address=0.0.0.0 --http-port=8080 --deploy-path=/world --docroot=.
so then I would need to connect to
http://127.0.0.1:8080/world
The above actually does not work, it only hosts the first application that connects, and the second will not connect until the first shuts down. So this brings me here. Are there any other ways to run multiple WT applications on the same port?
Thank you in advance for any help!
Yes, you can achieve that but you will need to create your own WRun and use addEntryPoint. This is actually mentioned in the tutorial and goes as follows:
Inside WRun()
WRun() is actually a convenience function which creates and configures a WServer instance. If you want more control, for example if you have multiple “entry points”, or want to control the server starting and stopping, you can use the WServer API directly instead.
Here you have an example, both applications are the Hello World application, but notice that they have different titles and different messages on the buttons and when you press them. You can find another implementation of WRun on src/http/Serve.C and src/Wt/WServer.
two_helloworlds.cc
#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WLineEdit>
#include <Wt/WPushButton>
#include <Wt/WText>
#include <Wt/WException>
#include <Wt/WLogger>
#include <Wt/WServer>
class HelloApplication : public Wt::WApplication
{
public:
HelloApplication(const Wt::WEnvironment& env, const std::string& title);
private:
Wt::WLineEdit *nameEdit_;
Wt::WText *greeting_;
void greet();
};
HelloApplication::HelloApplication(const Wt::WEnvironment& env, const std::string& title)
: Wt::WApplication(env)
{
setTitle(title);
root()->addWidget(new Wt::WText("Your name, please ? "));
nameEdit_ = new Wt::WLineEdit(root());
Wt::WPushButton *button = new Wt::WPushButton("Greet me.", root());
root()->addWidget(new Wt::WBreak());
greeting_ = new Wt::WText(root());
button->clicked().connect(this, &HelloApplication::greet);
}
void HelloApplication::greet()
{ greeting_->setText("Hello there, " + nameEdit_->text());
}
class GoodbyeApplication : public Wt::WApplication{
public:
GoodbyeApplication(const Wt::WEnvironment& env, const std::string& title);
private: Wt::WLineEdit *nameEdit_;
Wt::WText *greeting_;
void greet();
};
GoodbyeApplication::GoodbyeApplication(const Wt::WEnvironment& env, const std::string& title)
: Wt::WApplication(env)
{
setTitle(title);
root()->addWidget(new Wt::WText("Your name, please ? "));
nameEdit_ = new Wt::WLineEdit(root());
Wt::WPushButton *button = new Wt::WPushButton("Say goodbye.", root());
root()->addWidget(new Wt::WBreak());
greeting_ = new Wt::WText(root());
button->clicked().connect(this, &GoodbyeApplication::greet);
}
void GoodbyeApplication::greet()
{
greeting_->setText("Goodbye, " + nameEdit_->text());
}
Wt::WApplication *createApplication(const Wt::WEnvironment& env)
{
return new HelloApplication(env, "First app");
}
Wt::WApplication *createSecondApplication(const Wt::WEnvironment& env)
{
return new GoodbyeApplication(env, "Second app");
}
int YourWRun(int argc, char *argv[], Wt::ApplicationCreator createApplication, Wt::ApplicationCreator createSecondApplication)
{
try {
// use argv[0] as the application name to match a suitable entry
// in the Wt configuration file, and use the default configuration
// file (which defaults to /etc/wt/wt_config.xml unless the environment
// variable WT_CONFIG_XML is set)
Wt::WServer server(argv[0],"");
// WTHTTP_CONFIGURATION is e.g. "/etc/wt/wthttpd"
server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION);
// add a single entry point, at the default location (as determined
// by the server configuration's deploy-path)
server.addEntryPoint(Wt::Application, createApplication);
server.addEntryPoint(Wt::Application, createSecondApplication,"/second");
if (server.start()) {
int sig = Wt::WServer::waitForShutdown(argv[0]);
std::cerr << "Shutdown (signal = " << sig << ")" << std::endl;
server.stop();
/*
if (sig == SIGHUP)
WServer::restart(argc, argv, environ);
*/
}
} catch (Wt::WServer::Exception& e) {
std::cerr << e.what() << "\n";
return 1;
} catch (std::exception& e) {
std::cerr << "exception: " << e.what() << "\n";
return 1;
}
}
int main(int argc, char **argv)
{
return YourWRun(argc, argv, &createApplication, &createSecondApplication);
}
Compile it with
g++ -g -o two_helloworlds two_helloworlds.cc -I/usr/local/include -L/usr/local/lib -lwthttp -lwt -lboost_random -lboost_regex -lboost_signals -lboost_system -lboost_thread -lboost_filesystem -lboost_program_options -lboost_date_time
and execute with
./two_helloworlds --docroot . --http-address 0.0.0.0 --http-port 8080
on localhost:8080 you will access one of the applications and on localhost:8080/second you will access the other.
Related
I have the need to gather which application has focus. For this, my approach is to: list windows, get the one with focus, and finally, check which process and application shows it. If there were some: getWindowWithFocus(), it would be fantastic.
Requirements:
The program is implemented in C++, but could interface with objective-C if needed.
The program will run with root privileges.
The list of windows listed must include all users applications.
The returned window allows to get properties, such as it process and if it has UI-focus.
Ideally, no 3rd party tool is used, only standard libraries (STL, Unix APIs and macOS APIs, eventually Qt/Boost).
Must support HSierra to Big-Sur.
I managed to list all windows, but now I am struggling in detecting if a window has or not the focus.
The question:
Which API function can be used to check if a window has focus or not? Any sample?
Any better approach to this problem?
Previous research:
I created a POC/sample which list all windows, including some of it properties.
CGWindowListCopyWindowInfo
https://developer.apple.com/documentation/coregraphics/1455137-cgwindowlistcopywindowinfo?language=objc
DISCLAIM: this is a POC, just for demonstration, and miss required code quality for proper projects. For example, CFObjects are not released with the consequent memory leak.
#include <CoreFoundation/CoreFoundation.h>
#include <CoreGraphics/CGWindow.h> // CoreGraphics
#include <iostream>
int main()
{
CFArrayRef ref = CGWindowListCopyWindowInfo(kCGNullWindowID, 0);
CFIndex nameCount = CFArrayGetCount( ref );
std::cout << "NumCounts: " << nameCount << " windows" << std::endl;
for( int i = 0; i < nameCount ; ++i )
{
std::cerr << " -------- " << std::endl;
CFDictionaryRef dict = (CFDictionaryRef)CFArrayGetValueAtIndex( ref, i );
auto printKeys = [](const void* key, const void* value, void* context)
{
CFShow(key);
std::cerr << " ";
CFShow(value);
};
CFDictionaryApplyFunction(dict, printKeys, nullptr);
// Process PID can be extracted with key:kCGWindowOwnerPID
// DOES THIS WINDOW HAS FOCUS?
}
}
Here is an example, based on this solution, wrapped in C++ (well, actually mostly C).
The only found problem with it is, it must run in main thread, which is not convenient, but this is another topic.
main.cpp:
#include "focus_oc_wrapper.hpp"
#include <thread>
int main(int argc, const char * argv[])
{
FocusDetector::AppFocus focus;
focus.run();
//std::thread threadListener(&FocusDetector::AppFocus::run, &focus); //Does not works
//if (threadListener.joinable())
//{
// threadListener.join();
//}
}
focus_oc_wrapper.hpp
namespace FocusDetector
{
struct AppFocusImpl;
struct AppFocus
{
AppFocusImpl* impl=nullptr;
AppFocus() noexcept;
~AppFocus();
void run();
};
}
focus_oc_wrapper.mm
#include "focus_oc_wrapper.hpp"
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import "focus_oc.h"
namespace FocusDetector
{
struct AppFocusImpl
{
OCAppFocus* wrapped=nullptr;
};
AppFocus::AppFocus() noexcept: impl(new AppFocusImpl)
{
impl->wrapped = [[OCAppFocus alloc] init];
}
AppFocus::~AppFocus()
{
if (impl)
{
[impl->wrapped release];
}
delete impl;
}
void AppFocus::run()
{
[NSApplication sharedApplication];
[NSApp setDelegate:impl->wrapped];
[NSApp run];
}
}
focus_oc.h
#import <Foundation/Foundation.h>
#interface OCAppFocus : NSObject <NSApplicationDelegate>
{
NSRunningApplication *currentApp;
}
#property (retain) NSRunningApplication *currentApp;
#end
#implementation OCAppFocus
#synthesize currentApp;
- (id)init
{
if ((self = [super init]))
{
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:#selector(activeAppDidChange:)
name:NSWorkspaceDidActivateApplicationNotification object:nil];
}
return self;
}
- (void)dealloc
{
[[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
[super dealloc];
}
- (void)activeAppDidChange:(NSNotification *)notification
{
self.currentApp = [[notification userInfo] objectForKey:NSWorkspaceApplicationKey];
NSLog(#"App: %#", [currentApp localizedName]);
NSLog(#"Bundle: %#", [currentApp bundleIdentifier]);
NSLog(#"Exec Url: %#", [currentApp executableURL]);
NSLog(#"PID: %d", [currentApp processIdentifier]);
}
#end
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum OS X deployment version")
project("focus_detection")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreFoundation -framework AppKit")
set ( TESTCPP main.cpp focus_oc_wrapper.mm )
add_executable( ${PROJECT_NAME} ${TESTCPP} )
I have looked at Stellarium (software for viewing sky like it is now) code on GitHub for a while. I want to write once soon a program like that, so I started learning C++. I looked at the code and wanted to know what these parts do. And then I asked myself a question: "Where does Stellarium code start?" I want to know in which part of code Stellarium first runs, or in which part of code Stellarium gets a call for running.
P.S.
I am just a beginner in C++. I don't understand it perfectly, so don't be angry at me if I don't know everything and if I missed my question.
Stellarium 'starts' in the 'src' folder, in main.cpp file.
Script:
/*
* Stellarium
* Copyright (C) 2002 Fabien Chereau
* Copyright (C) 2012 Timothy Reaves
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*/
#include "StelMainView.hpp"
#include "StelSplashScreen.hpp"
#include "StelTranslator.hpp"
#include "StelLogger.hpp"
#include "StelFileMgr.hpp"
#include "CLIProcessor.hpp"
#include "StelIniParser.hpp"
#include "StelUtils.hpp"
#ifndef DISABLE_SCRIPTING
#include "StelScriptOutput.hpp"
#endif
#include <QDebug>
#ifndef USE_QUICKVIEW
#include <QApplication>
#include <QMessageBox>
#include <QStyleFactory>
#else
#include <QGuiApplication>
#endif
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QFontDatabase>
#include <QGuiApplication>
#include <QSettings>
#include <QString>
#include <QStringList>
#include <QTextStream>
#include <QTranslator>
#include <QNetworkDiskCache>
#include <QThread>
#include <clocale>
#ifdef Q_OS_WIN
#include <Windows.h>
//we use WIN32_LEAN_AND_MEAN so this needs to be included
//to use timeBeginPeriod/timeEndPeriod
#include <mmsystem.h>
// Default to High Performance Mode on machines with hybrid graphics
// Details: https://stackoverflow.com/questions/44174859/how-to-give-an-option-to-select-graphics-adapter-in-a-directx-11-application
extern "C"
{
#ifdef _MSC_VER
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 0x00000001;
#else
__attribute__((dllexport)) DWORD NvOptimusEnablement = 0x00000001;
__attribute__((dllexport)) int AmdPowerXpressRequestHighPerformance = 0x00000001;
#endif
}
#else
extern "C"
{
int NvOptimusEnablement = 1;
int AmdPowerXpressRequestHighPerformance = 1;
}
#endif //Q_OS_WIN
//! #class CustomQTranslator
//! Provides custom i18n support.
class CustomQTranslator : public QTranslator
{
using QTranslator::translate;
public:
virtual bool isEmpty() const { return false; }
//! Overrides QTranslator::translate().
//! Calls StelTranslator::qtranslate().
//! #param context Qt context string - IGNORED.
//! #param sourceText the source message.
//! #param comment optional parameter
virtual QString translate(const char *context, const char *sourceText, const char *disambiguation = Q_NULLPTR, int n = -1) const
{
Q_UNUSED(context);
Q_UNUSED(n);
return StelTranslator::globalTranslator->qtranslate(sourceText, disambiguation);
}
};
//! Copies the default configuration file.
//! This function copies the default_cfg.ini file to config.ini (or other
//! name specified on the command line located in the user data directory.
void copyDefaultConfigFile(const QString& newPath)
{
QString defaultConfigFilePath = StelFileMgr::findFile("data/default_cfg.ini");
if (defaultConfigFilePath.isEmpty())
qFatal("ERROR copyDefaultConfigFile failed to locate data/default_cfg.ini. Please check your installation.");
QFile::copy(defaultConfigFilePath, newPath);
if (!StelFileMgr::exists(newPath))
{
qFatal("ERROR copyDefaultConfigFile failed to copy file %s to %s. You could try to copy it by hand.",
qPrintable(defaultConfigFilePath), qPrintable(newPath));
}
QFile::setPermissions(newPath, QFile::permissions(newPath) | QFileDevice::WriteOwner);
}
//! Removes all items from the cache.
void clearCache()
{
QNetworkDiskCache* cacheMgr = new QNetworkDiskCache();
cacheMgr->setCacheDirectory(StelFileMgr::getCacheDir());
cacheMgr->clear(); // Removes all items from the cache.
}
// Main stellarium procedure
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(mainRes);
Q_INIT_RESOURCE(guiRes);
#ifdef Q_OS_WIN
// Fix for the speeding system clock bug on systems that use ACPI
// See http://support.microsoft.com/kb/821893
UINT timerGrain = 1;
if (timeBeginPeriod(timerGrain) == TIMERR_NOCANDO)
{
// If this is too fine a grain, try the lowest value used by a timer
timerGrain = 5;
if (timeBeginPeriod(timerGrain) == TIMERR_NOCANDO)
timerGrain = 0;
}
#endif
// Seed the PRNG
qsrand(QDateTime::currentMSecsSinceEpoch());
QCoreApplication::setApplicationName("stellarium");
QCoreApplication::setApplicationVersion(StelUtils::getApplicationVersion());
QCoreApplication::setOrganizationDomain("stellarium.org");
QCoreApplication::setOrganizationName("stellarium");
// Support high DPI pixmaps and fonts
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
#if (QT_VERSION>=QT_VERSION_CHECK(5, 6, 0))
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
#endif
#if defined(Q_OS_MAC)
QFileInfo appInfo(QString::fromUtf8(argv[0]));
QDir appDir(appInfo.absolutePath());
appDir.cdUp();
QCoreApplication::addLibraryPath(appDir.absoluteFilePath("PlugIns"));
#elif defined(Q_OS_WIN)
QFileInfo appInfo(QString::fromUtf8(argv[0]));
QCoreApplication::addLibraryPath(appInfo.absolutePath());
#endif
QGuiApplication::setDesktopSettingsAware(false);
#ifndef USE_QUICKVIEW
QApplication::setStyle(QStyleFactory::create("Fusion"));
// The QApplication MUST be created before the StelFileMgr is initialized.
QApplication app(argc, argv);
#else
QGuiApplication::setDesktopSettingsAware(false);
QGuiApplication app(argc, argv);
#endif
// QApplication sets current locale, but
// we need scanf()/printf() and friends to always work in the C locale,
// otherwise configuration/INI file parsing will be erroneous.
setlocale(LC_NUMERIC, "C");
// Solution for bug: https://bugs.launchpad.net/stellarium/+bug/1498616
qputenv("QT_HARFBUZZ", "old");
// Init the file manager
StelFileMgr::init();
SplashScreen::present();
// Log command line arguments.
QString argStr;
QStringList argList;
for (int i=0; i<argc; ++i)
{
argList << argv[i];
argStr += QString("%1 ").arg(argv[i]);
}
// add contents of STEL_OPTS environment variable.
QString envStelOpts(qgetenv("STEL_OPTS").constData());
if (envStelOpts.length()>0)
{
argList+= envStelOpts.split(" ");
argStr += " " + envStelOpts;
}
//save the modified arg list as an app property for later use
qApp->setProperty("stelCommandLine", argList);
// Parse for first set of CLI arguments - stuff we want to process before other
// output, such as --help and --version
CLIProcessor::parseCLIArgsPreConfig(argList);
#ifdef Q_OS_WIN
if (qApp->property("onetime_angle_mode").isValid())
{
app.setAttribute(Qt::AA_UseOpenGLES, true);
}
if (qApp->property("onetime_mesa_mode").isValid())
{
app.setAttribute(Qt::AA_UseSoftwareOpenGL, true);
}
#endif
// Start logging.
StelLogger::init(StelFileMgr::getUserDir()+"/log.txt");
StelLogger::writeLog(argStr);
// OK we start the full program.
// Print the console splash and get on with loading the program
QString versionLine = QString("This is %1 - %2").arg(StelUtils::getApplicationName()).arg(STELLARIUM_URL);
QString copyrightLine = QString("Copyright (C) %1 Fabien Chereau et al.").arg(COPYRIGHT_YEARS);
int maxLength = qMax(versionLine.size(), copyrightLine.size());
qDebug() << qPrintable(QString(" %1").arg(QString().fill('-', maxLength+2)));
qDebug() << qPrintable(QString("[ %1 ]").arg(versionLine.leftJustified(maxLength, ' ')));
qDebug() << qPrintable(QString("[ %1 ]").arg(copyrightLine.leftJustified(maxLength, ' ')));
qDebug() << qPrintable(QString(" %1").arg(QString().fill('-', maxLength+2)));
qDebug() << "Writing log file to:" << QDir::toNativeSeparators(StelLogger::getLogFileName());
qDebug() << "File search paths:";
int n=0;
for (const auto& i : StelFileMgr::getSearchPaths())
{
qDebug() << " " << n << ". " << QDir::toNativeSeparators(i);
++n;
}
// Now manage the loading of the proper config file
QString configName;
try
{
configName = CLIProcessor::argsGetOptionWithArg(argList, "-c", "--config-file", "config.ini").toString();
}
catch (std::runtime_error& e)
{
qWarning() << "WARNING: while looking for --config-file option: " << e.what() << ". Using \"config.ini\"";
configName = "config.ini";
}
QString configFileFullPath = StelFileMgr::findFile(configName, StelFileMgr::Flags(StelFileMgr::Writable|StelFileMgr::File));
if (configFileFullPath.isEmpty())
{
configFileFullPath = StelFileMgr::findFile(configName, StelFileMgr::New);
if (configFileFullPath.isEmpty())
qFatal("Could not create configuration file %s.", qPrintable(configName));
}
QSettings* confSettings = Q_NULLPTR;
if (StelFileMgr::exists(configFileFullPath))
{
confSettings = new QSettings(configFileFullPath, StelIniFormat, Q_NULLPTR);
// Implement "restore default settings" feature.
bool restoreDefaultConfigFile = false;
if (CLIProcessor::argsGetOption(argList, "", "--restore-defaults"))
restoreDefaultConfigFile=true;
else
restoreDefaultConfigFile = confSettings->value("main/restore_defaults", false).toBool();
if (!restoreDefaultConfigFile)
{
QString version = confSettings->value("main/version", "0.0.0").toString();
if (version!=QString(PACKAGE_VERSION))
{
QTextStream istr(&version);
char tmp;
int v1=0;
int v2=0;
istr >> v1 >> tmp >> v2;
// Config versions less than 0.6.0 are not supported, otherwise we will try to use it
if (v1==0 && v2<6)
{
// The config file is too old to try an importation
qDebug() << "The current config file is from a version too old for parameters to be imported ("
<< (version.isEmpty() ? "<0.6.0" : version) << ").\n"
<< "It will be replaced by the default config file.";
restoreDefaultConfigFile = true;
}
else
{
qDebug() << "Attempting to use an existing older config file.";
confSettings->setValue("main/version", QString(PACKAGE_VERSION)); // Upgrade version of config.ini
clearCache();
qDebug() << "Clear cache and update config.ini...";
}
}
}
if (restoreDefaultConfigFile)
{
if (confSettings)
delete confSettings;
QString backupFile(configFileFullPath.left(configFileFullPath.length()-3) + QString("old"));
if (QFileInfo(backupFile).exists())
QFile(backupFile).remove();
QFile(configFileFullPath).rename(backupFile);
copyDefaultConfigFile(configFileFullPath);
confSettings = new QSettings(configFileFullPath, StelIniFormat);
qWarning() << "Resetting defaults config file. Previous config file was backed up in " << QDir::toNativeSeparators(backupFile);
clearCache();
}
}
else
{
qDebug() << "Config file " << QDir::toNativeSeparators(configFileFullPath) << " does not exist. Copying the default file.";
copyDefaultConfigFile(configFileFullPath);
confSettings = new QSettings(configFileFullPath, StelIniFormat);
}
Q_ASSERT(confSettings);
qDebug() << "Config file is: " << QDir::toNativeSeparators(configFileFullPath);
#ifndef DISABLE_SCRIPTING
QString outputFile = StelFileMgr::getUserDir()+"/output.txt";
if (confSettings->value("main/use_separate_output_file", false).toBool())
outputFile = StelFileMgr::getUserDir()+"/output-"+QDateTime::currentDateTime().toString("yyyyMMdd-HHmmss")+".txt";
StelScriptOutput::init(outputFile);
#endif
// Override config file values from CLI.
CLIProcessor::parseCLIArgsPostConfig(argList, confSettings);
// Add the DejaVu font that we use everywhere in the program
const QString& fName = StelFileMgr::findFile("data/DejaVuSans.ttf");
if (!fName.isEmpty())
QFontDatabase::addApplicationFont(fName);
QString fileFont = confSettings->value("gui/base_font_file", "").toString();
if (!fileFont.isEmpty())
{
const QString& afName = StelFileMgr::findFile(QString("data/%1").arg(fileFont));
if (!afName.isEmpty() && !afName.contains("file not found"))
QFontDatabase::addApplicationFont(afName);
else
qWarning() << "ERROR while loading custom font " << QDir::toNativeSeparators(fileFont);
}
// Set the default application font and font size.
// Note that style sheet will possibly override this setting.
#ifdef Q_OS_WIN
// Let's try avoid ugly font rendering on Windows.
// Details: https://sourceforge.net/p/stellarium/discussion/278769/thread/810a1e5c/
QString baseFont = confSettings->value("gui/base_font_name", "Verdana").toString();
QFont tmpFont(baseFont);
tmpFont.setStyleHint(QFont::AnyStyle, QFont::OpenGLCompatible);
#else
QString baseFont = confSettings->value("gui/base_font_name", "DejaVu Sans").toString();
QFont tmpFont(baseFont);
#endif
tmpFont.setPixelSize(confSettings->value("gui/gui_font_size", 13).toInt());
QGuiApplication::setFont(tmpFont);
// Initialize translator feature
StelTranslator::init(StelFileMgr::getInstallationDir() + "/data/iso639-1.utf8");
// Use our custom translator for Qt translations as well
CustomQTranslator trans;
app.installTranslator(&trans);
StelMainView mainWin(confSettings);
mainWin.show();
SplashScreen::finish(&mainWin);
app.exec();
mainWin.deinit();
delete confSettings;
StelLogger::deinit();
#ifdef Q_OS_WIN
if(timerGrain)
timeEndPeriod(timerGrain);
#endif //Q_OS_WIN
return 0;
}
Thanks for all effort.
P.S.
I know that question was very unclear, but I couldn't do it better.
I have a problem with connection to a web service with ssl protocol. I was trying to connect with specyfied WebService using open libraries QtSoap. Since now I have been searching any solution of error which I have mentioned in the topic, but not found any for linux-mint system. Only one I have seen, which people confirmed were for Windows here 1 and here 2. I have certificate for this webService which contains a key.
My pice of code:
#include "qtsoap.h"
...
int main(int argc, char **argv)
{
...
QtSoapMessage message;
QSsl::SslProtocol protocol = QSsl::SslV2;
message.addHeaderItem(new QtSoapSimpleType(QtSoapQName("tagName"),"tagValue"));
...
message.setMethod("method", "WSAddress");
message.addMethodArgument("attr", "", value);
...
QtSoapHttpTransport http;
http.setHost("ipaddress", true, port);
http.setAction("http://tempuri.org/IDataService/DARTGetReservationData");
http.submitRequest(message, "path", protocol, "certificatePath");
}
I have made some changes in a library if You have already noticed in submitRequest, adding specyfied SslProtocol and certificatePath. Here is a sorce:
void QtSoapHttpTransport::submitRequest(QNetworkRequest &networkReq, QtSoapMessage &request, const QString &path, QSsl::SslProtocol ssl, QString certificatePath)
{
networkReq.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("text/xml;charset=utf-8"));
networkReq.setRawHeader("SOAPAction", soapAction.toLatin1());
url.setPath(path);
networkReq.setUrl(url);
QSslConfiguration sslConf = networkReq.sslConfiguration();
soapResponse.clear();
if(certificatePath != NULL)
{
QFile sslCertificateFile(certificatePath);
if (sslCertificateFile.open(QIODevice::ReadOnly))
{
QSslCertificate certif(&sslCertificateFile);
if (certif.isNull())
{
qDebug() << "Failed to load certificate";
}
sslConf.setLocalCertificate(certif);
sslConf.setPrivateKey(certif.publicKey());
qDebug() << "certif version=" << certif.version() << ", serial=" << certif.serialNumber()
<< ", issuer=" << certif.issuerInfo(QSslCertificate::Organization)
<< " and subject=" << certif.subjectInfo(QSslCertificate::CommonName);
QSslKey key(certif.publicKey());
qDebug() << "key isNull ? " << key.isNull();
sslConf.setPrivateKey(key);
sslCertificateFile.close();
}
else
qDebug() << "Cannot open certificate";
}
if(ssl != NULL)
sslConf.setProtocol(ssl);
networkReq.setSslConfiguration(sslConf);
networkRep = networkMgr.post(networkReq, request.toXmlString().toUtf8().constData());
}
One more thing related to this modified libraries. I added some headers to:
#include <QSslCertificate>
#include <QSsl>
#include <QSslConfiguration>
#include <QSslKey>
#include <QFile>
I guess that there is missing something in my *.pro file, but I do not know what it could be. So I added it below
QT += core network xml
QT -= gui
TARGET = SSLConnectionTest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp \
qtsoap.cpp
HEADERS += \
qtsoap.h
Another thing that could be wrong is there is missing some other libraries which I don't know. I hope someone have found solution of this problem?
Sorry for my poor english.
Is there a way to check if a cable is not unplugged by using Qt ?
I know the Ip adress that I want to contact, at first I was thinking of doing a ping request on this Ip Adress, but it seems to be too much complicated for this simple task.
So I'm thinking that maybe, there is a simple function able to do this in QNetwork library.
I search on the Internet but all the solutions are not testing one particular IP.
Thanks for your help.
Is there a way to check if a cable is not unplugged by using Qt ?
You can achieve this for specified interface using QNetworkSession:
QNetworkConfigurationManager nwManager (this);
for (;;QThread::sleep (1) ) {
bool isConfigurationFound {false};
for (auto & configuration : nwManager.allConfigurations (/*QNetworkConfiguration::Active*/) ) {
// Name depends on the environment: "Wired connection 1", "McDonaldsFreeWiFi", "Home", "eth0", "eth1", etc...
if (isConfigurationFound = (configuration.name () == "eth0") ) {
QNetworkSession session (configuration, this);
session.open ();
session.waitForOpened (/*timeout*/);
qDebug () << "Session info:";
qDebug () << "- usage: " << (session.isOpen () ? "Opened" : "Closed");
qDebug () << "- state: " << (session.state () == QNetworkSession::Connected ? "Connected" : "Not connected");
break;
}
}
qDebug () << (isConfigurationFound ? "" : "Configuration not found.");
}
If you launch this code with connected cable you get:
"Session info:"
"- usage: Opened;"
"- state: Connected;"
If you unplugged cable you get:
"Session info:"
"- usage: Closed"
"- state: Not connected"
Here is full example (also available at GitLab):
CMakeLists.txt
cmake_minimum_required (VERSION 2.8.8)
project (NaQt)
find_package (Qt5Network)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set (NaQt_SOURCES ${PROJECT_SOURCE_DIR}/main.cpp)
set (NaQt_HEADERS ${PROJECT_SOURCE_DIR}/NetworkAnalyzer.h)
qt5_wrap_cpp (NaQt_HEADERS_MOC ${NaQt_HEADERS})
add_executable (
naqt
${NaQt_SOURCES}
${NaQt_HEADERS_MOC}
)
target_link_libraries (
naqt
Qt5::Core
Qt5::Network
)
main.cpp
#include <QtCore>
#include "NetworkAnalyzer.h"
int main (int argc, char * argv [])
{
QCoreApplication application (argc, argv);
NetworkAnalyzer networkAnalyzer (& application);
return application.exec ();
}
NetworkAnalyzer.h
#ifndef QT_NETWORK_ANALYZER_H
#define QT_NETWORK_ANALYZER_H
#include <QThread>
#include <QNetworkConfigurationManager>
#include <QNetworkSession>
#include <QDebug>
class NetworkAnalyzer : public QObject
{
Q_OBJECT
public:
NetworkAnalyzer (QObject * parent = nullptr)
{
QNetworkConfigurationManager nwManager (this);
for (;;QThread::sleep (1) ) {
bool isConfigurationFound {false};
for (auto & configuration : nwManager.allConfigurations (/*QNetworkConfiguration::Active*/) ) {
// Name depends on the environment: "Wired connection 1", "McDonaldsFreeWiFi", "Home", "eth0", "eth1", etc...
if (isConfigurationFound = (configuration.name () == "eth0") ) {
QNetworkSession session (configuration, this);
session.open ();
session.waitForOpened (/*timeout*/);
qDebug () << "Session info:";
qDebug () << "- usage: " << (session.isOpen () ? "Opened" : "Closed");
qDebug () << "- state: " << (session.state () == QNetworkSession::Connected ? "Connected" : "Not connected");
break;
}
}
qDebug () << (isConfigurationFound ? "" : "Configuration not found.");
}
}
};
#endif//QT_NETWORK_ANALYZER_H
Try opening a socket to the specified IP address on a predefined port :
QTcpSocket tester;
tester.connectToHost(address, port);
if(tester.waitForConnected(3000)) {
//Remote host is online
} else {
//Remote host is offline
}
Use QT's QNetworkAccessManager class which provides networkAccessibleChanged Signal
and connect a slot to it
connect(&networkAccessManager, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(onNetworkAccessibilityChanged(QNetworkAccessManager::NetworkAccessibility)));
it emits signal telling when the ethernet cable is unplugged
I have just started a development using wt(with c++ binding). And i have could done till now, is reading a very few documentation and a little no of sample programs(written in c++ and wt).
After that I installed wt on my machine amd tried to run one one of those demo programs.
hello.cc
#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WLineEdit>
#include <Wt/WPushButton>
#include <Wt/WText>
class HelloApplication : public Wt::WApplication
{
public:
HelloApplication(const Wt::WEnvironment& env);
private:
Wt::WLineEdit *nameEdit_;
Wt::WText *greeting_;
void greet();
};
HelloApplication::HelloApplication(const Wt::WEnvironment& env)
: Wt::WApplication(env)
{
setTitle("Hello world");
root()->addWidget(new Wt::WText("Your name, please ? "));
nameEdit_ = new Wt::WLineEdit(root());
Wt::WPushButton *button = new Wt::WPushButton("Greet me.", root());
root()->addWidget(new Wt::WBreak());
greeting_ = new Wt::WText(root());
button->clicked().connect(this, &HelloApplication::greet);
}
void HelloApplication::greet()
{
greeting_->setText("Hello there, " + nameEdit_->text());
}
Wt::WApplication *createApplication(const Wt::WEnvironment& env)
{
return new HelloApplication(env);
}
int main(int argc, char **argv)
{
return Wt::WRun(argc, argv, &createApplication);
}
I complied this code
g++ -o hello hello.cc -lwthttp -lwt
It was compiled successfully.Then I could run this server application successfully to run it on localhost
[manmatha#manmatha Lab]$ su
Password:
[root#manmatha Lab]# ./hello --docroot . --http-address 127.0.0.1 --http-port 9090
[2013-Jun-14 13:58:08.585419] 5066-[info] "WServer/wthttp:initializing built-in wthttpd"
[2013-Jun-14 13:58:08.590955] 5066-[info] "wthttp:started server: http://127.0.0.1:9090"
problem is when I type
localhost::9090
on the address bar of the internet browser on local machine., anything does not show up.
In this context , my specific question is how to start a wt client??
Thanx in advannce
try 127.0.0.1:9090
You specified 127.0.0.1 on the command line so type it in the browser's address bar.
This is a specific of the Wt embedded http server.
You have to mention the --deploy-path variable in your command line arguments. Try this
--http-address 127.0.0.1 --http-port 9090 --deploy-path=/hello --docroot=.
In the browser type http://localhost:9090/hello