Browse Source

Merge pull request #517 from anon5/openssl

Android i2pd armeabi-v7a with Qt
pull/520/head
orignal 9 years ago committed by GitHub
parent
commit
07cc547bab
  1. 4
      .gitignore
  2. 8
      ClientContext.cpp
  3. 7
      DaemonLinux.cpp
  4. 19
      HTTP.cpp
  5. 10
      HTTPServer.cpp
  6. 8
      I2PControl.cpp
  7. 8
      Reseed.cpp
  8. 8
      RouterContext.cpp
  9. 10
      build/.gitignore
  10. 2
      qt/.gitignore
  11. 59
      qt/i2pd_qt/docs/patch_openssl_so_libs.html
  12. 167
      qt/i2pd_qt/i2pd_qt.pro
  13. 21
      qt/i2pd_qt/main.cpp
  14. 14
      qt/i2pd_qt/mainwindow.cpp
  15. 22
      qt/i2pd_qt/mainwindow.h
  16. 21
      qt/i2pd_qt/mainwindow.ui
  17. 19
      qt/i2pd_qt/to_string.h

4
.gitignore vendored

@ -5,6 +5,10 @@ router.keys @@ -5,6 +5,10 @@ router.keys
i2p
libi2pd.so
netDb
/i2pd
/libi2pd.a
/libi2pdclient.a
# Autotools
autom4te.cache

8
ClientContext.cpp

@ -8,6 +8,12 @@ @@ -8,6 +8,12 @@
#include "Identity.h"
#include "ClientContext.h"
#ifdef ANDROID
# include "to_string.h"
#else
# define to_string(x) std::to_string(x)
#endif
namespace i2p
{
namespace client
@ -292,7 +298,7 @@ namespace client @@ -292,7 +298,7 @@ namespace client
template<typename Section, typename Type>
std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
{
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value));
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), to_string (value));
}
template<typename Section>

7
DaemonLinux.cpp

@ -74,9 +74,11 @@ namespace i2p @@ -74,9 +74,11 @@ namespace i2p
}
// point std{in,out,err} descriptors to /dev/null
#ifndef ANDROID
stdin = freopen("/dev/null", "r", stdin);
stdout = freopen("/dev/null", "w", stdout);
stderr = freopen("/dev/null", "w", stderr);
#endif
}
// Pidfile
@ -92,7 +94,12 @@ namespace i2p @@ -92,7 +94,12 @@ namespace i2p
LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno));
return false;
}
#ifndef ANDROID
if (lockf(pidFH, F_TLOCK, 0) != 0)
#else
//TODO ANDROID actually need to read man for this, blindly took a solution from <https://forum.qt.io/topic/27872/qtjsondb-build-failed-for-android/2>. -anon5
if (fcntl(pidFH, 1, 0) < 0)
#endif
{
LogPrint(eLogError, "Daemon: could not lock pid file ", pidfile, ": ", strerror(errno));
return false;

19
HTTP.cpp

@ -10,6 +10,13 @@ @@ -10,6 +10,13 @@
#include <algorithm>
#include <ctime>
#ifdef ANDROID
# include "to_string.h"
# include <errno.h>
#else
# define to_string(x) std::to_string(x)
#endif
namespace i2p {
namespace http {
const std::vector<std::string> HTTP_METHODS = {
@ -180,7 +187,11 @@ namespace http { @@ -180,7 +187,11 @@ namespace http {
out += user + "@";
}
if (port) {
out += host + ":" + std::to_string(port);
#ifndef ANDROID
out += host + ":" + to_string(port);
#else
out += host + ":" + tostr::to_string(port);
#endif
} else {
out += host;
}
@ -338,7 +349,11 @@ namespace http { @@ -338,7 +349,11 @@ namespace http {
if (status == "OK" && code != 200)
status = HTTPCodeToStatus(code); // update
if (body.length() > 0 && headers.count("Content-Length") == 0)
add_header("Content-Length", std::to_string(body.length()).c_str());
#ifndef ANDROID
add_header("Content-Length", to_string(body.length()).c_str());
#else
add_header("Content-Length", tostr::to_string(body.length()).c_str());
#endif
/* build response */
std::stringstream ss;
ss << version << " " << code << " " << status << CRLF;

10
HTTPServer.cpp

@ -25,6 +25,12 @@ @@ -25,6 +25,12 @@
// For image and info
#include "version.h"
#ifdef ANDROID
# include "to_string.h"
#else
# define to_string(x) std::to_string(x)
#endif
namespace i2p {
namespace http {
const char *itoopieFavicon =
@ -230,8 +236,8 @@ namespace http { @@ -230,8 +236,8 @@ namespace http {
clientTunnelCount += i2p::tunnel::tunnels.CountInboundTunnels();
size_t transitTunnelCount = i2p::tunnel::tunnels.CountTransitTunnels();
s << "<b>Client Tunnels:</b> " << std::to_string(clientTunnelCount) << " ";
s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n";
s << "<b>Client Tunnels:</b> " << to_string(clientTunnelCount) << " ";
s << "<b>Transit Tunnels:</b> " << to_string(transitTunnelCount) << "<br>\r\n";
}
void ShowJumpServices (std::stringstream& s, const std::string& address)

8
I2PControl.cpp

@ -25,6 +25,12 @@ @@ -25,6 +25,12 @@
#include "version.h"
#include "I2PControl.h"
#ifdef ANDROID
# include "to_string.h"
#else
# define to_string(x) std::to_string(x)
#endif
namespace i2p
{
namespace client
@ -315,7 +321,7 @@ namespace client @@ -315,7 +321,7 @@ namespace client
}
InsertParam (results, "API", api);
results << ",";
std::string token = std::to_string(i2p::util::GetSecondsSinceEpoch ());
std::string token = to_string(i2p::util::GetSecondsSinceEpoch ());
m_Tokens.insert (token);
InsertParam (results, "Token", token);
}

8
Reseed.cpp

@ -17,6 +17,12 @@ @@ -17,6 +17,12 @@
#include "util.h"
#ifdef ANDROID
# include "to_string.h"
#else
# define to_string(x) std::to_string(x)
#endif
namespace i2p
{
namespace data
@ -373,7 +379,7 @@ namespace data @@ -373,7 +379,7 @@ namespace data
boost::asio::io_service service;
boost::system::error_code ecode;
auto it = boost::asio::ip::tcp::resolver(service).resolve (
boost::asio::ip::tcp::resolver::query (u.host_, std::to_string (u.port_)), ecode);
boost::asio::ip::tcp::resolver::query (u.host_, to_string (u.port_)), ecode);
if (!ecode)
{
boost::asio::ssl::context ctx(service, boost::asio::ssl::context::sslv23);

8
RouterContext.cpp

@ -12,6 +12,12 @@ @@ -12,6 +12,12 @@
#include "Family.h"
#include "RouterContext.h"
#ifdef ANDROID
# include "to_string.h"
#else
# define to_string(x) std::to_string(x)
#endif
namespace i2p
{
RouterContext context;
@ -56,7 +62,7 @@ namespace i2p @@ -56,7 +62,7 @@ namespace i2p
routerInfo.AddNTCPAddress (host.c_str(), port);
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC
routerInfo.SetProperty ("netId", std::to_string (I2PD_NET_ID));
routerInfo.SetProperty ("netId", to_string (I2PD_NET_ID));
routerInfo.SetProperty ("router.version", I2P_VERSION);
routerInfo.CreateBuffer (m_Keys);
m_RouterInfo.SetRouterIdentity (GetIdentity ());

10
build/.gitignore vendored

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
# Various generated files
/CMakeFiles/
/i2pd
/libi2pd.a
/libi2pdclient.a
/cmake_install.cmake
/CMakeCache.txt
/CPackConfig.cmake
/CPackSourceConfig.cmake
/install_manifest.txt

2
qt/.gitignore vendored

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
/build-i2pd_qt-Android_armeabi_v7a_GCC_4_9_Qt_5_6_0-Debug/
/build-i2pd_qt-Desktop_Qt_5_6_0_GCC_64bit-Debug/

59
qt/i2pd_qt/docs/patch_openssl_so_libs.html

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="ru" class=" ya-page_js_yes"><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<h1 id="blog_title" style="font-size:14pt; font-weight:normal; margin:0px">
OpenSSL под Android в Qt
</h1> <div class="smallfont shade"> <span class="shade">Запись от <a href="http://www.cyberforum.ru/blogs/748276/">Wyn</a> размещена 18.01.2016 в 18:22</span> </div> <script type="text/javascript" src="./patch_openssl_so_libs_files/blog_ajax_tag.js"></script> <div class="smallfont" id="blogtagcontainer_4086"> <span class="shade">Метки</span> <span id="blogtaglist_4086"><a href="http://www.cyberforum.ru/blog.php?tag=android&amp;u=748276">android</a>, <a href="http://www.cyberforum.ru/blog.php?tag=openssl&amp;u=748276">openssl</a>, <a href="http://www.cyberforum.ru/blog.php?tag=qt&amp;u=748276">qt</a></span> </div> <div style="clear:both; margin-top:4px"></div> <hr size="1" style="color:#AAAAAA; background-color:#AAAAAA; margin-bottom:10px"> <div id="blog_message" style="margin-bottom:10px"><!-- google_ad_section_start --><!-- google_ad_section_start -->Мини-руководство по тому, как быстро скомпилировать OpenSSL для Android и связать его с проектом Qt.<br>
Для Linux.<br> <br>
Вначале действия полностью идентичны <a rel="nofollow" href="https://wiki.openssl.org/index.php/Android" target="_blank" title="https://wiki.openssl.org/index.php/Android">"расово-верному" руководству по компилянию OpenSSL для Android</a>:<br>
Качаем исходники openssl нужной версии с их сайта, качаем setenv-android.sh(все ссылки на закачку выше по ссылке).<br>
Ложим их в одну папку. Запускаем консоль, переходим в ней в эту самую папку.<br>
Далее:<br> <div style="margin: 5px 10px 5px 30px"><table class="bash"><thead><tr><td colspan="2" class="head">Bash<a href="http://www.cyberforum.ru/#" style="float: right; color: rgb(96, 96, 96); font-weight: normal;">Выделить код</a></td></tr></thead><tbody><tr class="li1"><td><div id="52254522" style="overflow: auto; width: 805px; height: 73px"><table><tbody><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">$ <span class="kw2">rm</span> <span class="re5">-rf</span> openssl-1.0.1g<span class="sy0">/</span> &nbsp; <span class="co0"># удаляем исходники(вместо версии 1.0.1g - подставляем свою), если они уже были распакованы</span>
$ <span class="kw2">tar</span> xzf openssl-1.0.1g.tar.gz &nbsp; &nbsp;<span class="co0"># распаковываем исходники в подпапку</span>
$ <span class="kw2">chmod</span> a+x setenv-android.sh &nbsp; &nbsp;<span class="co0"># разрешаем setenv-android.sh исполняться</span></pre></td></tr></tbody></table></div></td></tr></tbody></table></div>Редактируем setenv-android.sh, настраивая там _ANDROID_EABI, _ANDROID_ARCH, _ANDROID_API на нужные значения.<br>
Дальше возвращаемся в консоль:<br> <div style="margin: 5px 10px 5px 30px"><table class="bash"><thead><tr><td colspan="2" class="head">Bash<a href="http://www.cyberforum.ru/#" style="float: right; color: rgb(96, 96, 96); font-weight: normal;">Выделить код</a></td></tr></thead><tbody><tr class="li1"><td><div id="701353202" style="overflow: auto; width: 805px; height: 201px"><table><tbody><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1">$ <span class="kw3">export</span> <span class="re2">ANDROID_NDK_ROOT</span>=путь_до_ANDROID_NDK <span class="co0"># указываем путь до Android NDK для setenv-android.sh</span>
$ . .<span class="sy0">/</span>setenv-android.sh <span class="co0"># запускаем скрипт, чтобы он нам в окружение проставил необходимые далее переменные</span>
$ <span class="kw3">cd</span> openssl-1.0.1g<span class="sy0">/</span>
$ <span class="kw2">perl</span> <span class="re5">-pi</span> <span class="re5">-e</span> <span class="st_h">'s/install: all install_docs install_sw/install: install_docs install_sw/g'</span> Makefile.org
<span class="co0"># конфигурируем</span>
$ .<span class="sy0">/</span>config shared no-ssl2 no-ssl3 no-comp no-hw no-engine <span class="re5">--openssldir</span>=<span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>ssl<span class="sy0">/</span><span class="re1">$ANDROID_API</span>
<span class="co0"># собираем</span>
$ <span class="kw2">make</span> depend
$ <span class="kw2">make</span> all
<span class="co0"># устанавливаем</span>
$ <span class="kw2">sudo</span> <span class="re5">-E</span> <span class="kw2">make</span> <span class="kw2">install</span> <span class="re2">CC</span>=<span class="re1">$ANDROID_TOOLCHAIN</span><span class="sy0">/</span>arm-linux-androideabi-gcc <span class="re2">RANLIB</span>=<span class="re1">$ANDROID_TOOLCHAIN</span><span class="sy0">/</span>arm-linux-androideabi-ranlib</pre></td></tr></tbody></table></div></td></tr></tbody></table></div>И тут начинается интересное. Андроид не принимает versioned shared object (это *.so.x и подобные). Казалось бы 2016 год, космические корабли уже давно бороздят просторы Большого театра, но вот те на. <br> <br>
Однако, есть обходной приём - нужно заменить *.so.x.x.x на *_x_x_x.so. Простым переименованием файлов данную проблему здесь, разумеется, не решить. Нужно лезть внутрь и переименовывать soname и внутренние ссылки на другие versioned shared object. В интернете есть много способов по подобному переименованию. Большинство из них обещают райскую жизнь с rpl, забывая упомянуть, что утилита уже давно отпета и закопана на большинстве дистрибутивов. Или хитро-хитро редактируют makefile, что в итоге на место левой руки собирается правая нога. В целом множество путей из разряда "как потратить много времени на полную фигню". <br> <br>
В итоге предлагаю решить данную проблему методом топора:<br>
Качаем hex-редактор, если ещё нет(в моём случае таковым оказался Okteta). Запускаем его из под рута(kdesu okteta), открываем в нём файлы openssldir/lib/libcrypto.so.1.0.0. Заменяем(ctrl+r) в нём символы ".so.1.0.0" на char "_1_0_0.so". Проделываем тоже самое с libssl.so.1.0.0. Всё, теперь осталось только переименовать сами файлы(в libcrypto_1_0_0.so и libssl_1_0_0.so) и поправить ссылки libssl.so и libcrypto.so, чтобы они вели на них.<br> <br>
Чтобы подключить и использовать данную библиотеку в проекте нужно добавить в .pro:<br> <div style="margin: 5px 10px 5px 30px"><table class="bash"><thead><tr><td colspan="2" class="head">Bash<a href="http://www.cyberforum.ru/#" style="float: right; color: rgb(96, 96, 96); font-weight: normal;">Выделить код</a></td></tr></thead><tbody><tr class="li1"><td><div id="304166412" style="overflow: auto; width: 805px; height: 105px"><table><tbody><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">android: <span class="br0">{</span>
&nbsp; &nbsp; INCLUDEPATH += <span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>ssl<span class="sy0">/</span>android-<span class="nu0">21</span><span class="sy0">/</span>include
&nbsp; &nbsp; LIBS += -L<span class="sy0">/</span>usr<span class="sy0">/</span>local<span class="sy0">/</span>ssl<span class="sy0">/</span>android-<span class="nu0">21</span><span class="sy0">/</span>lib
<span class="br0">}</span>
LIBS += <span class="re5">-lcrypto</span></pre></td></tr></tbody></table></div></td></tr></tbody></table></div>А затем в настройках проекта, в Buld/Build Steps/Bulild Android Apk добавить libcrypto_1_0_0.so и libssl_1_0_0.so в список Additional Libraries.<br> <br>
На этом всё.
<br>
<p><small>Original: http://www.cyberforum.ru/blogs/748276/blog4086.html</small></p>
</body></html>

167
qt/i2pd_qt/i2pd_qt.pro

@ -0,0 +1,167 @@ @@ -0,0 +1,167 @@
#-------------------------------------------------
#
# Project created by QtCreator 2016-06-14T04:53:04
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = i2pd_qt
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
../../HTTPServer.cpp ../../I2PControl.cpp ../../UPnP.cpp ../../Daemon.cpp ../../Config.cpp \
../../AddressBook.cpp \
../../api.cpp \
../../Base.cpp \
../../BOB.cpp \
../../ClientContext.cpp \
../../Crypto.cpp \
../../DaemonLinux.cpp \
../../DaemonWin32.cpp \
../../Datagram.cpp \
../../Destination.cpp \
../../Family.cpp \
../../FS.cpp \
../../Garlic.cpp \
../../HTTP.cpp \
../../HTTPProxy.cpp \
../../I2CP.cpp \
../../I2NPProtocol.cpp \
../../I2PEndian.cpp \
../../I2PService.cpp \
../../I2PTunnel.cpp \
../../Identity.cpp \
../../LeaseSet.cpp \
../../Log.cpp \
../../NetDb.cpp \
../../NetDbRequests.cpp \
../../NTCPSession.cpp \
../../Profiling.cpp \
../../Reseed.cpp \
../../RouterContext.cpp \
../../RouterInfo.cpp \
../../SAM.cpp \
../../Signature.cpp \
../../SOCKS.cpp \
../../SSU.cpp \
../../SSUData.cpp \
../../SSUSession.cpp \
../../stdafx.cpp \
../../Streaming.cpp \
../../TransitTunnel.cpp \
../../Transports.cpp \
../../Tunnel.cpp \
../../TunnelEndpoint.cpp \
../../TunnelGateway.cpp \
../../TunnelPool.cpp \
../../util.cpp \
../../../android-ifaddrs/ifaddrs.c
HEADERS += mainwindow.h \
../../HTTPServer.h ../../I2PControl.h ../../UPnP.h ../../Daemon.h ../../Config.h \
to_string.h \
../../AddressBook.h \
../../api.h \
../../Base.h \
../../BOB.h \
../../ClientContext.h \
../../Crypto.h \
../../Datagram.h \
../../Destination.h \
../../Family.h \
../../FS.h \
../../Garlic.h \
../../HTTP.h \
../../HTTPProxy.h \
../../I2CP.h \
../../I2NPProtocol.h \
../../I2PEndian.h \
../../I2PService.h \
../../I2PTunnel.h \
../../Identity.h \
../../LeaseSet.h \
../../LittleBigEndian.h \
../../Log.h \
../../NetDb.h \
../../NetDbRequests.h \
../../NTCPSession.h \
../../Profiling.h \
../../Queue.h \
../../Reseed.h \
../../RouterContext.h \
../../RouterInfo.h \
../../SAM.h \
../../Signature.h \
../../SOCKS.h \
../../SSU.h \
../../SSUData.h \
../../SSUSession.h \
../../stdafx.h \
../../Streaming.h \
../../Timestamp.h \
../../TransitTunnel.h \
../../Transports.h \
../../TransportSession.h \
../../Tunnel.h \
../../TunnelBase.h \
../../TunnelConfig.h \
../../TunnelEndpoint.h \
../../TunnelGateway.h \
../../TunnelPool.h \
../../util.h \
../../version.h \
../../../android-ifaddrs/ifaddrs.h
FORMS += mainwindow.ui
CONFIG += mobility
MOBILITY =
LIBS += -lz
android {
message("Using Android settings")
DEFINES += ANDROID=1
# git clone https://github.com/emileb/Boost-for-Android-Prebuilt.git
# git clone https://github.com/anon5/OpenSSL-for-Android-Prebuilt.git
# git clone https://github.com/anon5/android-ifaddrs.git
INCLUDEPATH += /home/anon5/git/Boost-for-Android-Prebuilt/boost_1_53_0/include \
/home/anon5/git/OpenSSL-for-Android-Prebuilt/openssl-1.0.2/include \
../../../android-ifaddrs/
equals(ANDROID_TARGET_ARCH, armeabi-v7a){
# http://stackoverflow.com/a/30235934/529442
LIBS += -L/home/anon5/git/Boost-for-Android-Prebuilt/boost_1_53_0/armeabi-v7a/lib \
#/home/anon5/git/OpenSSL-for-Android-Prebuilt/openssl-1.0.2/armeabi-v7a/lib/libcrypto.a \
#/home/anon5/git/OpenSSL-for-Android-Prebuilt/openssl-1.0.2/armeabi-v7a/lib/libssl.a \
-lboost_system-gcc-mt-1_53 \
-lboost_date_time-gcc-mt-1_53 \
-lboost_filesystem-gcc-mt-1_53 \
-lboost_program_options-gcc-mt-1_53 \
-L$$PWD/../../../OpenSSL-for-Android-Prebuilt/openssl-1.0.2/armeabi-v7a/lib/ -lcrypto -lssl
PRE_TARGETDEPS += $$PWD/../../../OpenSSL-for-Android-Prebuilt/openssl-1.0.2/armeabi-v7a/lib/libcrypto.a \
$$PWD/../../../OpenSSL-for-Android-Prebuilt/openssl-1.0.2/armeabi-v7a/lib/libssl.a
DEPENDPATH += $$PWD/../../../OpenSSL-for-Android-Prebuilt/openssl-1.0.2/include
ANDROID_EXTRA_LIBS += /home/anon5/git/OpenSSL-for-Android-Prebuilt/openssl-1.0.2/armeabi-v7a/lib/libcrypto_1_0_0.so \
/home/anon5/git/OpenSSL-for-Android-Prebuilt/openssl-1.0.2/armeabi-v7a/lib/libssl_1_0_0.so
}
}
linux:!android {
message("Using Linux settings")
LIBS += -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
}
unix:!macx:

21
qt/i2pd_qt/main.cpp

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
#include "mainwindow.h"
#include <QApplication>
#include <stdlib.h>
#include "../../Daemon.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
if (Daemon.init(argc, argv))
{
if (Daemon.start())
Daemon.run ();
Daemon.stop();
}
return a.exec();
}

14
qt/i2pd_qt/mainwindow.cpp

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}

22
qt/i2pd_qt/mainwindow.h

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

21
qt/i2pd_qt/mainwindow.ui

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>480</height>
</rect>
</property>
<property name="windowTitle" >
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget" />
</widget>
<layoutDefault spacing="6" margin="11" />
<pixmapfunction></pixmapfunction>
<resources/>
<connections/>
</ui>

19
qt/i2pd_qt/to_string.h

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
#ifndef TO_STRING_H
#define TO_STRING_H
#include <string>
#include <sstream>
namespace tostr {
template <typename T>
std::string to_string(T value)
{
std::ostringstream os ;
os << value ;
return os.str() ;
}
}
using namespace tostr;
#endif // TO_STRING_H
Loading…
Cancel
Save