code format
This commit is contained in:
@@ -1,22 +1,22 @@
|
||||
#include "cloudserver.h"
|
||||
|
||||
CloudServer::CloudServer(DispatcherClient * c, const PIByteArray & sname) : server(c) {
|
||||
CloudServer::CloudServer(DispatcherClient * c, const PIByteArray & sname): server(c) {
|
||||
setName(sname.toHex());
|
||||
server_uuid = sname;
|
||||
CONNECTL(c, dataReadedServer, ([this](uint id, PIByteArray & ba){
|
||||
last_ping.reset();
|
||||
mutex_clients.lock();
|
||||
DispatcherClient * cl = index_clients.value(id, nullptr);
|
||||
mutex_clients.unlock();
|
||||
if (cl) cl->sendData(ba);
|
||||
}));
|
||||
CONNECTL(c, pingReceived, [this]() {last_ping.reset();});
|
||||
CONNECTL(c, dataReadedServer, ([this](uint id, PIByteArray & ba) {
|
||||
last_ping.reset();
|
||||
mutex_clients.lock();
|
||||
DispatcherClient * cl = index_clients.value(id, nullptr);
|
||||
mutex_clients.unlock();
|
||||
if (cl) cl->sendData(ba);
|
||||
}));
|
||||
CONNECTL(c, pingReceived, [this]() { last_ping.reset(); });
|
||||
last_ping.reset();
|
||||
}
|
||||
|
||||
|
||||
CloudServer::~CloudServer() {
|
||||
for (auto c :clients) {
|
||||
for (auto c: clients) {
|
||||
c->close();
|
||||
}
|
||||
}
|
||||
@@ -36,10 +36,10 @@ void CloudServer::addClient(DispatcherClient * c) {
|
||||
mutex_clients.unlock();
|
||||
c->sendConnected(1);
|
||||
server->sendConnected(cid);
|
||||
CONNECTL(c, dataReaded, ([this, cid](PIByteArray & ba){
|
||||
// piCoutObj << c->clientId() << "dataReaded";
|
||||
server->sendDataToClient(ba, cid);
|
||||
}));
|
||||
CONNECTL(c, dataReaded, ([this, cid](PIByteArray & ba) {
|
||||
// piCoutObj << c->clientId() << "dataReaded";
|
||||
server->sendDataToClient(ba, cid);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -68,11 +68,10 @@ double CloudServer::lastPing() {
|
||||
|
||||
void CloudServer::printStatus() {
|
||||
mutex_clients.lock();
|
||||
piCout << " " << "Clients for" << server->address() << server_uuid.toHex() << ":";
|
||||
piCout << " "
|
||||
<< "Clients for" << server->address() << server_uuid.toHex() << ":";
|
||||
for (auto c: clients) {
|
||||
piCout << " " << c->address() << c->clientId();
|
||||
}
|
||||
mutex_clients.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,23 +4,24 @@
|
||||
#include "dispatcherclient.h"
|
||||
|
||||
|
||||
class CloudServer : public PIObject {
|
||||
class CloudServer: public PIObject {
|
||||
PIOBJECT(CloudServer)
|
||||
|
||||
public:
|
||||
CloudServer(DispatcherClient * c, const PIByteArray & sname);
|
||||
~CloudServer();
|
||||
PIByteArray serverUUID() const;
|
||||
void addClient(DispatcherClient * c);
|
||||
void removeClient(DispatcherClient * c);
|
||||
PIVector<DispatcherClient*> getClients();
|
||||
PIVector<DispatcherClient *> getClients();
|
||||
EVENT_HANDLER0(void, printStatus);
|
||||
const DispatcherClient * getConnection() const {return server;}
|
||||
const DispatcherClient * getConnection() const { return server; }
|
||||
double lastPing();
|
||||
|
||||
private:
|
||||
DispatcherClient * server;
|
||||
PIVector<DispatcherClient*> clients;
|
||||
PIMap<uint, DispatcherClient*> index_clients;
|
||||
PIVector<DispatcherClient *> clients;
|
||||
PIMap<uint, DispatcherClient *> index_clients;
|
||||
PIByteArray server_uuid;
|
||||
PITimeMeasurer last_ping;
|
||||
PIMutex mutex_clients;
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
#include "dispatcherclient.h"
|
||||
|
||||
#include "picloudtcp.h"
|
||||
|
||||
|
||||
DispatcherClient::DispatcherClient(PIEthernet * eth_, int id) : authorised(false), eth(eth_), streampacker(eth_), tcp(&streampacker), client_id(id) {
|
||||
DispatcherClient::DispatcherClient(PIEthernet * eth_, int id)
|
||||
: authorised(false)
|
||||
, eth(eth_)
|
||||
, streampacker(eth_)
|
||||
, tcp(&streampacker)
|
||||
, client_id(id) {
|
||||
eth->setName(PIString::fromNumber(id));
|
||||
CONNECTU(&streampacker, packetReceiveEvent, this, readed);
|
||||
CONNECTU(eth, disconnected, this, disconnected);
|
||||
@@ -43,14 +49,18 @@ void DispatcherClient::sendDisconnected(uint client_id) {
|
||||
|
||||
|
||||
void DispatcherClient::sendData(const PIByteArray & data) {
|
||||
if (tcp.role() == PICloud::TCP::Client) tcp.sendData(data);
|
||||
else piCoutObj << "error sendData, invalid role";
|
||||
if (tcp.role() == PICloud::TCP::Client)
|
||||
tcp.sendData(data);
|
||||
else
|
||||
piCoutObj << "error sendData, invalid role";
|
||||
}
|
||||
|
||||
|
||||
void DispatcherClient::sendDataToClient(const PIByteArray & data, uint client_id) {
|
||||
if (tcp.role() == PICloud::TCP::Server) tcp.sendData(data, client_id);
|
||||
else piCoutObj << "error sendDataToClient, invalid role";
|
||||
if (tcp.role() == PICloud::TCP::Server)
|
||||
tcp.sendData(data, client_id);
|
||||
else
|
||||
piCoutObj << "error sendDataToClient, invalid role";
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +77,7 @@ void DispatcherClient::disconnected(bool withError) {
|
||||
|
||||
void DispatcherClient::readed(PIByteArray & ba) {
|
||||
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba);
|
||||
// piCoutObj << "readed" << hdr.first << hdr.second;
|
||||
// piCoutObj << "readed" << hdr.first << hdr.second;
|
||||
if (hdr.first == PICloud::TCP::InvalidType) {
|
||||
piCoutObj << "invalid message";
|
||||
disconnected(true);
|
||||
@@ -76,34 +86,35 @@ void DispatcherClient::readed(PIByteArray & ba) {
|
||||
if (authorised) {
|
||||
if (hdr.second == tcp.role()) {
|
||||
switch (hdr.first) {
|
||||
case PICloud::TCP::Connect:
|
||||
piCoutObj << "PICloud::TCP::Connect";
|
||||
return;
|
||||
case PICloud::TCP::Connect: piCoutObj << "PICloud::TCP::Connect"; return;
|
||||
case PICloud::TCP::Disconnect:
|
||||
piCoutObj << "PICloud::TCP::Disconnect";
|
||||
disconnected(false);
|
||||
return;
|
||||
return;
|
||||
case PICloud::TCP::Data:
|
||||
//piCoutObj << "TCP::Data" << tcp.role();
|
||||
// piCoutObj << "TCP::Data" << tcp.role();
|
||||
if (tcp.role() == PICloud::TCP::Client) {
|
||||
if (tcp.canParseData(ba)) dataReaded(ba);
|
||||
else piCoutObj << "invalid data from client";
|
||||
if (tcp.canParseData(ba))
|
||||
dataReaded(ba);
|
||||
else
|
||||
piCoutObj << "invalid data from client";
|
||||
}
|
||||
if (tcp.role() == PICloud::TCP::Server) {
|
||||
PIPair<uint, PIByteArray> dp = tcp.parseDataServer(ba);
|
||||
if (!dp.second.isEmpty()) dataReadedServer(dp.first, dp.second);
|
||||
else piCoutObj << "invalid data from server";
|
||||
if (!dp.second.isEmpty())
|
||||
dataReadedServer(dp.first, dp.second);
|
||||
else
|
||||
piCoutObj << "invalid data from server";
|
||||
}
|
||||
return;
|
||||
case PICloud::TCP::Ping:
|
||||
pingReceived();
|
||||
return;
|
||||
case PICloud::TCP::Ping: pingReceived(); return;
|
||||
default:
|
||||
piCoutObj << "unknown data";
|
||||
//disconnected(true);
|
||||
return;
|
||||
// disconnected(true);
|
||||
return;
|
||||
}
|
||||
} else piCoutObj << "invalid role";
|
||||
} else
|
||||
piCoutObj << "invalid role";
|
||||
} else {
|
||||
switch (hdr.first) {
|
||||
case PICloud::TCP::Connect: {
|
||||
@@ -116,12 +127,11 @@ void DispatcherClient::readed(PIByteArray & ba) {
|
||||
case PICloud::TCP::Disconnect:
|
||||
piCoutObj << "unauthorised PICloud::TCP::Disconnect";
|
||||
disconnected(false);
|
||||
return;
|
||||
return;
|
||||
default:
|
||||
piCoutObj << "authorised invalid message";
|
||||
disconnected(true);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#ifndef DISPATCHERCLIENT_H
|
||||
#define DISPATCHERCLIENT_H
|
||||
|
||||
#include "piethernet.h"
|
||||
#include "picloudtcp.h"
|
||||
#include "piethernet.h"
|
||||
#include "pistreampacker.h"
|
||||
|
||||
|
||||
class DispatcherClient: public PIObject {
|
||||
PIOBJECT(DispatcherClient)
|
||||
|
||||
public:
|
||||
DispatcherClient(PIEthernet * eth_, int id);
|
||||
~DispatcherClient();
|
||||
@@ -18,10 +19,10 @@ public:
|
||||
void sendData(const PIByteArray & data);
|
||||
void sendDataToClient(const PIByteArray & data, uint client_id);
|
||||
void authorise(bool ok);
|
||||
bool isAuthorised() const {return authorised;}
|
||||
PICloud::TCP::Role role() const {return tcp.role();}
|
||||
bool isAuthorised() const { return authorised; }
|
||||
PICloud::TCP::Role role() const { return tcp.role(); }
|
||||
PIString address();
|
||||
uint clientId() const {return client_id;}
|
||||
uint clientId() const { return client_id; }
|
||||
EVENT1(disconnectEvent, DispatcherClient *, client)
|
||||
EVENT2(registerServer, const PIByteArray &, sname, DispatcherClient *, client)
|
||||
EVENT2(registerClient, const PIByteArray &, sname, DispatcherClient *, client)
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#include "dispatcherserver.h"
|
||||
|
||||
#include "piscreentiles.h"
|
||||
|
||||
|
||||
DispatcherServer::DispatcherServer(PIEthernet::Address addr) : eth(PIEthernet::TCP_Server) {
|
||||
client_gid = 0;
|
||||
DispatcherServer::DispatcherServer(PIEthernet::Address addr): eth(PIEthernet::TCP_Server) {
|
||||
client_gid = 0;
|
||||
max_connections = 1000;
|
||||
eth.setParameter(PIEthernet::ReuseAddress);
|
||||
eth.setReadAddress(addr);
|
||||
// eth.setDebug(false);
|
||||
// eth.setDebug(false);
|
||||
CONNECTU(ð, newConnection, this, newConnection);
|
||||
CONNECTU(&timeout_timer, tickEvent, this, cleanClients);
|
||||
}
|
||||
@@ -15,7 +16,7 @@ DispatcherServer::DispatcherServer(PIEthernet::Address addr) : eth(PIEthernet::T
|
||||
|
||||
DispatcherServer::~DispatcherServer() {
|
||||
eth.close();
|
||||
//piCoutObj << "server stoped";
|
||||
// piCoutObj << "server stoped";
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +36,7 @@ void DispatcherServer::picoutStatus() {
|
||||
}
|
||||
piCout << "Servers:";
|
||||
auto it = c_servers.makeIterator();
|
||||
while(it.next()){
|
||||
while (it.next()) {
|
||||
piCout << " " << it.key();
|
||||
it.value()->printStatus();
|
||||
}
|
||||
@@ -52,14 +53,15 @@ void DispatcherServer::cleanClients() {
|
||||
for (auto c: clients) {
|
||||
if (!index_c_servers.contains(c) && !index_c_clients.contains(c)) {
|
||||
if (!rm_clients.contains(c)) rm_clients << c;
|
||||
} else rm_clients.removeAll(c);
|
||||
} else
|
||||
rm_clients.removeAll(c);
|
||||
}
|
||||
auto ss = c_servers.values();
|
||||
for (auto c: ss) {
|
||||
if (c->lastPing() > 15.0) {
|
||||
piCout << "remove Server by ping timeout" << c->getConnection()->clientId();
|
||||
PIVector<DispatcherClient *> cscv = c->getClients();
|
||||
for(auto csc : cscv) {
|
||||
for (auto csc: cscv) {
|
||||
clients.removeAll(csc);
|
||||
index_c_clients.remove(csc);
|
||||
c->removeClient(csc);
|
||||
@@ -79,7 +81,7 @@ void DispatcherServer::cleanClients() {
|
||||
}
|
||||
for (auto c: rmrf_clients) {
|
||||
clients.removeAll(c);
|
||||
if(index_c_servers.contains(c)) {
|
||||
if (index_c_servers.contains(c)) {
|
||||
c_servers.remove(c_servers.key(index_c_servers[c]));
|
||||
index_c_servers.remove(c);
|
||||
}
|
||||
@@ -96,18 +98,17 @@ void DispatcherServer::updateConnectionsTile(TileList * tl) {
|
||||
for (auto c: clients) {
|
||||
PIString role = "Invalid";
|
||||
switch (c->role()) {
|
||||
case PICloud::TCP::Client : {
|
||||
role = "Client";
|
||||
case PICloud::TCP::Client: {
|
||||
role = "Client";
|
||||
CloudServer * cs = index_c_clients.value(c, nullptr);
|
||||
if (cs) role += " \"" + cs->serverUUID().toHex().left(8) + "...\"";
|
||||
} break;
|
||||
case PICloud::TCP::Server : {
|
||||
role = "Server";
|
||||
case PICloud::TCP::Server: {
|
||||
role = "Server";
|
||||
CloudServer * cs = index_c_servers.value(c, nullptr);
|
||||
if (cs) role += " \"" + cs->serverUUID().toHex().left(8) + "...\"";
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
tl->content << TileList::Row(c->address() + " " + role, PIScreenTypes::CellFormat());
|
||||
}
|
||||
@@ -126,7 +127,9 @@ void DispatcherServer::updateServersTile(TileList * tl, PISet<const DispatcherCl
|
||||
tl->content.clear();
|
||||
auto mi = c_servers.makeIterator();
|
||||
while (mi.next()) {
|
||||
tl->content << TileList::Row(mi.value()->serverUUID().toHex().left(8) + "... - " + PIString::fromNumber(mi.value()->getClients().size()), PIScreenTypes::CellFormat());
|
||||
tl->content << TileList::Row(mi.value()->serverUUID().toHex().left(8) + "... - " +
|
||||
PIString::fromNumber(mi.value()->getClients().size()),
|
||||
PIScreenTypes::CellFormat());
|
||||
if (servers.contains(mi.value()->getConnection())) tl->selected << (tl->content.size_s() - 1);
|
||||
}
|
||||
map_mutex.unlock();
|
||||
@@ -138,7 +141,7 @@ void DispatcherServer::updateClientsTile(TileList * tl, PISet<const DispatcherCl
|
||||
tl->content.clear();
|
||||
auto mi = c_servers.makeIterator();
|
||||
while (mi.next()) {
|
||||
for (auto c : mi.value()->getClients()) {
|
||||
for (auto c: mi.value()->getClients()) {
|
||||
if (servers.isEmpty() || servers.contains(mi.value()->getConnection()))
|
||||
tl->content << TileList::Row(c->address(), PIScreenTypes::CellFormat());
|
||||
}
|
||||
@@ -150,7 +153,7 @@ void DispatcherServer::updateClientsTile(TileList * tl, PISet<const DispatcherCl
|
||||
const DispatcherClient * DispatcherServer::getConnection(int index) {
|
||||
const DispatcherClient * ret = nullptr;
|
||||
map_mutex.lock();
|
||||
if (index >=0 && index < clients.size_s()) ret = clients[index];
|
||||
if (index >= 0 && index < clients.size_s()) ret = clients[index];
|
||||
map_mutex.unlock();
|
||||
return ret;
|
||||
}
|
||||
@@ -159,7 +162,7 @@ const DispatcherClient * DispatcherServer::getConnection(int index) {
|
||||
const DispatcherClient * DispatcherServer::getServer(int index) {
|
||||
const DispatcherClient * ret = nullptr;
|
||||
map_mutex.lock();
|
||||
if (index >=0 && index < clients.size_s()) {
|
||||
if (index >= 0 && index < clients.size_s()) {
|
||||
if (index_c_servers.contains(clients[index])) ret = clients[index];
|
||||
}
|
||||
map_mutex.unlock();
|
||||
@@ -171,7 +174,7 @@ PISet<const DispatcherClient *> DispatcherServer::getServers(PISet<int> ids) {
|
||||
PISet<const DispatcherClient *> ret;
|
||||
if (ids.isEmpty()) return ret;
|
||||
map_mutex.lock();
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
auto mi = c_servers.makeIterator();
|
||||
while (mi.next()) {
|
||||
if (ids.contains(i)) ret << mi.value()->getConnection();
|
||||
@@ -187,9 +190,9 @@ void DispatcherServer::setMaxConnections(uint max_count) {
|
||||
}
|
||||
|
||||
|
||||
void DispatcherServer::disconnectClient(DispatcherClient *client) {
|
||||
void DispatcherServer::disconnectClient(DispatcherClient * client) {
|
||||
if (!clients.contains(client)) {
|
||||
//piCoutObj << "INVALID client" << client;
|
||||
// piCoutObj << "INVALID client" << client;
|
||||
return;
|
||||
}
|
||||
piCoutObj << "remove ..." << client->clientId();
|
||||
@@ -200,7 +203,7 @@ void DispatcherServer::disconnectClient(DispatcherClient *client) {
|
||||
if (cs) {
|
||||
piCoutObj << "remove Server" << client->clientId();
|
||||
PIVector<DispatcherClient *> cscv = cs->getClients();
|
||||
for(auto csc : cscv) {
|
||||
for (auto csc: cscv) {
|
||||
clients.removeAll(csc);
|
||||
index_c_clients.remove(csc);
|
||||
cs->removeClient(csc);
|
||||
@@ -217,21 +220,21 @@ void DispatcherServer::disconnectClient(DispatcherClient *client) {
|
||||
cc->removeClient(client);
|
||||
index_c_clients.remove(client);
|
||||
}
|
||||
//client->close();
|
||||
// client->close();
|
||||
rmrf_clients << client;
|
||||
map_mutex.unlock();
|
||||
piCoutObj << "remove done" << client->clientId();
|
||||
}
|
||||
|
||||
|
||||
void DispatcherServer::newConnection(PIEthernet *cl) {
|
||||
void DispatcherServer::newConnection(PIEthernet * cl) {
|
||||
if (clients.size() >= max_connections) {
|
||||
delete cl;
|
||||
return;
|
||||
}
|
||||
DispatcherClient * client = new DispatcherClient(cl, client_gid++);
|
||||
CONNECTU(client, disconnectEvent, this, disconnectClient);
|
||||
CONNECTL(client, registerServer, [this](const PIByteArray & sname, DispatcherClient * c){
|
||||
CONNECTL(client, registerServer, [this](const PIByteArray & sname, DispatcherClient * c) {
|
||||
map_mutex.lock();
|
||||
CloudServer * cs = c_servers.value(sname, nullptr);
|
||||
if (cs) {
|
||||
@@ -246,7 +249,7 @@ void DispatcherServer::newConnection(PIEthernet *cl) {
|
||||
}
|
||||
map_mutex.unlock();
|
||||
});
|
||||
CONNECTL(client, registerClient, [this](const PIByteArray & sname, DispatcherClient * c){
|
||||
CONNECTL(client, registerClient, [this](const PIByteArray & sname, DispatcherClient * c) {
|
||||
map_mutex.lock();
|
||||
CloudServer * cs = c_servers.value(sname, nullptr);
|
||||
if (cs) {
|
||||
@@ -260,7 +263,7 @@ void DispatcherServer::newConnection(PIEthernet *cl) {
|
||||
}
|
||||
map_mutex.unlock();
|
||||
});
|
||||
//piCoutObj << "add client" << client;
|
||||
// piCoutObj << "add client" << client;
|
||||
map_mutex.lock();
|
||||
clients.push_back(client);
|
||||
map_mutex.unlock();
|
||||
|
||||
@@ -8,6 +8,7 @@ class TileList;
|
||||
|
||||
class DispatcherServer: public PIObject {
|
||||
PIOBJECT(DispatcherServer)
|
||||
|
||||
public:
|
||||
DispatcherServer(PIEthernet::Address addr);
|
||||
~DispatcherServer();
|
||||
@@ -20,21 +21,21 @@ public:
|
||||
const DispatcherClient * getServer(int index);
|
||||
PISet<const DispatcherClient *> getServers(PISet<int> ids);
|
||||
void setMaxConnections(uint max_count);
|
||||
uint maxConnections() const {return max_connections;}
|
||||
uint maxConnections() const { return max_connections; }
|
||||
EVENT_HANDLER0(void, picoutStatus);
|
||||
|
||||
private:
|
||||
EVENT_HANDLER1(void, newConnection, PIEthernet * , cl);
|
||||
EVENT_HANDLER1(void, newConnection, PIEthernet *, cl);
|
||||
EVENT_HANDLER1(void, disconnectClient, DispatcherClient *, client);
|
||||
EVENT_HANDLER0(void, cleanClients);
|
||||
|
||||
PIEthernet eth;
|
||||
PIVector<DispatcherClient*> clients;
|
||||
PIVector<DispatcherClient *> clients;
|
||||
PIMap<PIByteArray, CloudServer *> c_servers;
|
||||
PIMap<const DispatcherClient *, CloudServer *> index_c_servers;
|
||||
PIMap<const DispatcherClient *, CloudServer *> index_c_clients;
|
||||
PIVector<DispatcherClient*> rm_clients;
|
||||
PIVector<DispatcherClient*> rmrf_clients;
|
||||
PIVector<DispatcherClient *> rm_clients;
|
||||
PIVector<DispatcherClient *> rmrf_clients;
|
||||
PITimer timeout_timer;
|
||||
PIMutex map_mutex;
|
||||
uint client_gid;
|
||||
|
||||
@@ -1,156 +1,159 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PICloud dispatcher
|
||||
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pip.h"
|
||||
#include "picrypt.h"
|
||||
#include "piiostream.h"
|
||||
#include "dispatcherserver.h"
|
||||
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << Bold << "PIP Cloud Dispatcher";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default << "\"picloud [-hsv] [-i <ip>] [-p <port>]\"" << NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << "-h --help " << Green << "- display this message and exit";
|
||||
piCout << "-i --ip " << Green << "- listen address, default \"0.0.0.0\"";
|
||||
piCout << "-p --port " << Green << "- listen port, default 10101";
|
||||
piCout << "-s --screen " << Green << "- start with console UI";
|
||||
piCout << "-v --verbose" << Green << "- print state (--screen ignore this flag)";
|
||||
}
|
||||
|
||||
|
||||
PIString confDir() {
|
||||
return
|
||||
#ifdef WINDOWS
|
||||
PIDir::home().path() + "/AppData/Local"
|
||||
#elif defined(MAC_OS)
|
||||
PIDir::home().path() + "/Library/Preferences"
|
||||
#elif defined(ANDROID)
|
||||
PIString(".")
|
||||
#else
|
||||
PIDir::home().path() + "/.config"
|
||||
#endif
|
||||
+ "/SHS";
|
||||
}
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
PICLI cli(argc, argv);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("ip", true);
|
||||
cli.addArgument("port", true);
|
||||
cli.addArgument("screen");
|
||||
cli.addArgument("verbose");
|
||||
|
||||
if (cli.hasArgument("help")) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
PIEthernet::Address addr = PIEthernet::Address("0.0.0.0", 10101);
|
||||
|
||||
PIString conf_path = confDir();
|
||||
PIDir::make(conf_path);
|
||||
conf_path += "/picloud.conf";
|
||||
uint max_connections = 1000;
|
||||
if (!PIFile::isExists(conf_path)) {
|
||||
PIFile f(conf_path, PIIODevice::ReadWrite);
|
||||
PIIOTextStream ts(&f);
|
||||
ts << "ip = " << addr.ipString() << "\n"
|
||||
<< "port = " << addr.port() << "\n"
|
||||
<< "max_connections = " << max_connections << "\n";
|
||||
}
|
||||
{
|
||||
PIConfig conf(conf_path, PIIODevice::ReadOnly);
|
||||
addr.setIP(conf.getValue("ip", addr.ipString()).toString());
|
||||
addr.setPort(conf.getValue("port", addr.port()).toUShort());
|
||||
max_connections = conf.getValue("max_connections", max_connections).toUInt();
|
||||
}
|
||||
|
||||
PITimer status_timer;
|
||||
if (cli.hasArgument("ip"))
|
||||
addr.setIP(cli.argumentValue("ip"));
|
||||
if (cli.hasArgument("port"))
|
||||
addr.setPort(cli.argumentValue("port").toInt());
|
||||
DispatcherServer server(addr);
|
||||
server.setMaxConnections(max_connections);
|
||||
if (cli.hasArgument("screen")) {
|
||||
PISet<const DispatcherClient *> sel_servers;
|
||||
PIScreen screen(false);
|
||||
PIScreenTile maintile("PICloud Dispatcher", PIScreenTypes::Horizontal, PIScreenTypes::Expanding);
|
||||
PIScreenTile tls[3];
|
||||
TileList conn_tl(PIString(), TileList::MultiSelection);
|
||||
TileList server_tl(PIString(), TileList::MultiSelection);
|
||||
TileList client_tl(PIString(), TileList::MultiSelection);
|
||||
tls[0].addTile(new TileSimple(TileSimple::Row("Connections", PIScreenTypes::CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Inverse))));
|
||||
tls[0].addTile(&conn_tl);
|
||||
tls[1].addTile(new TileSimple(TileSimple::Row("Servers", PIScreenTypes::CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Inverse))));
|
||||
tls[1].addTile(&server_tl);
|
||||
tls[2].addTile(new TileSimple(TileSimple::Row("Clients", PIScreenTypes::CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Inverse))));
|
||||
tls[2].addTile(&client_tl);
|
||||
CONNECTL(&screen, tileEvent, ([&](PIScreenTile * t, PIScreenTypes::TileEvent e){
|
||||
if (t == (PIScreenTile *)&server_tl) {
|
||||
if (e.type == TileList::SelectionChanged) {
|
||||
sel_servers = server.getServers(server_tl.selected);
|
||||
}
|
||||
}
|
||||
if (t == (PIScreenTile *)&conn_tl) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
sel_servers.clear();
|
||||
server_tl.selected.clear();
|
||||
const DispatcherClient * dc = server.getServer(e.data.toInt());
|
||||
if (dc) sel_servers << dc;
|
||||
}
|
||||
}
|
||||
}));
|
||||
for (auto & a : tls) {
|
||||
a.children()[0]->size_policy = PIScreenTypes::Fixed;
|
||||
maintile.addTile(&a);
|
||||
}
|
||||
CONNECTL(&status_timer, tickEvent, [&](void *, int){
|
||||
screen.lock();
|
||||
server.updateConnectionsTile(&conn_tl);
|
||||
server.updateServersTile(&server_tl, sel_servers);
|
||||
server.updateClientsTile(&client_tl, server.getServers(server_tl.selected));
|
||||
screen.unlock();
|
||||
});
|
||||
screen.enableExitCapture(PIKbdListener::F10);
|
||||
screen.rootTile()->addTile(new TileSimple(TileSimple::Row("PICloud Dispatcher " + addr.toString(), PIScreenTypes::CellFormat(PIScreenTypes::Yellow, PIScreenTypes::Default, PIScreenTypes::Bold))));
|
||||
screen.rootTile()->addTile(&maintile);
|
||||
screen.rootTile()->addTile(new TilePICout());
|
||||
screen.start();
|
||||
server.start();
|
||||
status_timer.start(100);
|
||||
screen.waitForFinish();
|
||||
} else {
|
||||
PIKbdListener ls;
|
||||
ls.enableExitCapture(PIKbdListener::F10);
|
||||
ls.start();
|
||||
server.start();
|
||||
if (cli.hasArgument("verbose")) {
|
||||
CONNECTU(&status_timer, tickEvent, &server, picoutStatus);
|
||||
status_timer.start(1000);
|
||||
}
|
||||
WAIT_FOR_EXIT
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PICloud dispatcher
|
||||
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dispatcherserver.h"
|
||||
#include "picrypt.h"
|
||||
#include "piiostream.h"
|
||||
#include "pip.h"
|
||||
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << Bold << "PIP Cloud Dispatcher";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default << "\"picloud [-hsv] [-i <ip>] [-p <port>]\"" << NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << "-h --help " << Green << "- display this message and exit";
|
||||
piCout << "-i --ip " << Green << "- listen address, default \"0.0.0.0\"";
|
||||
piCout << "-p --port " << Green << "- listen port, default 10101";
|
||||
piCout << "-s --screen " << Green << "- start with console UI";
|
||||
piCout << "-v --verbose" << Green << "- print state (--screen ignore this flag)";
|
||||
}
|
||||
|
||||
|
||||
PIString confDir() {
|
||||
return
|
||||
#ifdef WINDOWS
|
||||
PIDir::home().path() + "/AppData/Local"
|
||||
#elif defined(MAC_OS)
|
||||
PIDir::home().path() + "/Library/Preferences"
|
||||
#elif defined(ANDROID)
|
||||
PIString(".")
|
||||
#else
|
||||
PIDir::home().path() + "/.config"
|
||||
#endif
|
||||
+ "/SHS";
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
PICLI cli(argc, argv);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("ip", true);
|
||||
cli.addArgument("port", true);
|
||||
cli.addArgument("screen");
|
||||
cli.addArgument("verbose");
|
||||
|
||||
if (cli.hasArgument("help")) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
PIEthernet::Address addr = PIEthernet::Address("0.0.0.0", 10101);
|
||||
|
||||
PIString conf_path = confDir();
|
||||
PIDir::make(conf_path);
|
||||
conf_path += "/picloud.conf";
|
||||
uint max_connections = 1000;
|
||||
if (!PIFile::isExists(conf_path)) {
|
||||
PIFile f(conf_path, PIIODevice::ReadWrite);
|
||||
PIIOTextStream ts(&f);
|
||||
ts << "ip = " << addr.ipString() << "\n"
|
||||
<< "port = " << addr.port() << "\n"
|
||||
<< "max_connections = " << max_connections << "\n";
|
||||
}
|
||||
{
|
||||
PIConfig conf(conf_path, PIIODevice::ReadOnly);
|
||||
addr.setIP(conf.getValue("ip", addr.ipString()).toString());
|
||||
addr.setPort(conf.getValue("port", addr.port()).toUShort());
|
||||
max_connections = conf.getValue("max_connections", max_connections).toUInt();
|
||||
}
|
||||
|
||||
PITimer status_timer;
|
||||
if (cli.hasArgument("ip")) addr.setIP(cli.argumentValue("ip"));
|
||||
if (cli.hasArgument("port")) addr.setPort(cli.argumentValue("port").toInt());
|
||||
DispatcherServer server(addr);
|
||||
server.setMaxConnections(max_connections);
|
||||
if (cli.hasArgument("screen")) {
|
||||
PISet<const DispatcherClient *> sel_servers;
|
||||
PIScreen screen(false);
|
||||
PIScreenTile maintile("PICloud Dispatcher", PIScreenTypes::Horizontal, PIScreenTypes::Expanding);
|
||||
PIScreenTile tls[3];
|
||||
TileList conn_tl(PIString(), TileList::MultiSelection);
|
||||
TileList server_tl(PIString(), TileList::MultiSelection);
|
||||
TileList client_tl(PIString(), TileList::MultiSelection);
|
||||
tls[0].addTile(new TileSimple(
|
||||
TileSimple::Row("Connections",
|
||||
PIScreenTypes::CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Inverse))));
|
||||
tls[0].addTile(&conn_tl);
|
||||
tls[1].addTile(new TileSimple(
|
||||
TileSimple::Row("Servers", PIScreenTypes::CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Inverse))));
|
||||
tls[1].addTile(&server_tl);
|
||||
tls[2].addTile(new TileSimple(
|
||||
TileSimple::Row("Clients", PIScreenTypes::CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Inverse))));
|
||||
tls[2].addTile(&client_tl);
|
||||
CONNECTL(&screen, tileEvent, ([&](PIScreenTile * t, PIScreenTypes::TileEvent e) {
|
||||
if (t == (PIScreenTile *)&server_tl) {
|
||||
if (e.type == TileList::SelectionChanged) {
|
||||
sel_servers = server.getServers(server_tl.selected);
|
||||
}
|
||||
}
|
||||
if (t == (PIScreenTile *)&conn_tl) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
sel_servers.clear();
|
||||
server_tl.selected.clear();
|
||||
const DispatcherClient * dc = server.getServer(e.data.toInt());
|
||||
if (dc) sel_servers << dc;
|
||||
}
|
||||
}
|
||||
}));
|
||||
for (auto & a: tls) {
|
||||
a.children()[0]->size_policy = PIScreenTypes::Fixed;
|
||||
maintile.addTile(&a);
|
||||
}
|
||||
CONNECTL(&status_timer, tickEvent, [&](void *, int) {
|
||||
screen.lock();
|
||||
server.updateConnectionsTile(&conn_tl);
|
||||
server.updateServersTile(&server_tl, sel_servers);
|
||||
server.updateClientsTile(&client_tl, server.getServers(server_tl.selected));
|
||||
screen.unlock();
|
||||
});
|
||||
screen.enableExitCapture(PIKbdListener::F10);
|
||||
screen.rootTile()->addTile(
|
||||
new TileSimple(TileSimple::Row("PICloud Dispatcher " + addr.toString(),
|
||||
PIScreenTypes::CellFormat(PIScreenTypes::Yellow, PIScreenTypes::Default, PIScreenTypes::Bold))));
|
||||
screen.rootTile()->addTile(&maintile);
|
||||
screen.rootTile()->addTile(new TilePICout());
|
||||
screen.start();
|
||||
server.start();
|
||||
status_timer.start(100);
|
||||
screen.waitForFinish();
|
||||
} else {
|
||||
PIKbdListener ls;
|
||||
ls.enableExitCapture(PIKbdListener::F10);
|
||||
ls.start();
|
||||
server.start();
|
||||
if (cli.hasArgument("verbose")) {
|
||||
CONNECTU(&status_timer, tickEvent, &server, picoutStatus);
|
||||
status_timer.start(1000);
|
||||
}
|
||||
WAIT_FOR_EXIT
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,600 +1,645 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Code model generator
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "picli.h"
|
||||
#include "picodeparser.h"
|
||||
#include "piiostream.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
PICodeParser parser;
|
||||
|
||||
const char help_string[] =
|
||||
"-M (Metainfo)\n"
|
||||
"Generate classes and structs info. It contains\n"
|
||||
"names, subclass info, all methods and variables.\n"
|
||||
"Place information:\n"
|
||||
" * classes and structs - PICodeInfo::classesInfo\n"
|
||||
" * methods - ClassInfo::functions\n"
|
||||
" * variables - ClassInfo::variables\n"
|
||||
"\n"
|
||||
"-E (Enums)\n"
|
||||
"Generate enumeration descriptions.\n"
|
||||
"Useful for GUI integrations, because\n"
|
||||
"you can obtain enumerators value and name.\n"
|
||||
" * enums - PICodeInfo::enumsInfo\n"
|
||||
"\n"
|
||||
"-S (Stream operators)\n"
|
||||
"Generate store/restore operators with format\n"
|
||||
"BINARY_STREAM_WRITE(<type>);\n"
|
||||
"BINARY_STREAM_READ (<type>);\n"
|
||||
"Only public variables used. All variables stored/restored\n"
|
||||
"using PIChunkStream. IDs are variable number, starting from 1.\n"
|
||||
"You can override ID with PIMETA(id=<ID>). If in class or struct\n"
|
||||
"PIMETA(simple-stream) presence, then variables stored/restored\n"
|
||||
"with simple << and >> operators.\n"
|
||||
"If PIMETA(no-stream) presence, then class or struct ignored.\n"
|
||||
"\n"
|
||||
"-G (Getter functions)\n"
|
||||
"Generate anonymous access methods for member typenames and values.\n"
|
||||
"Every class or struct member typename can be obtained with:\n"
|
||||
"const char * getMemberType(const char * class_name, const char * member_name)\n"
|
||||
"Member value can be obtained with:\n"
|
||||
"PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name)\n"
|
||||
"where \"p\" - class or struct pointer, and returns serialized value.\n"
|
||||
"PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name)\n"
|
||||
"where \"p\" - class or struct pointer, and returns value as registered PIVariant.\n"
|
||||
""
|
||||
;
|
||||
|
||||
void header() {
|
||||
piCout << Bold << "PIP Code model generator";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default << "\"pip_cmg [-hHqPpsAMESTG] -o <output_file> [-I<include_dir1>] [-I<include_dir1>] [...] [-D<define1>] [-D<define1>] [...] <file1> [<file2>] [<file3>] [...]\"" << NewLine;
|
||||
}
|
||||
|
||||
void usage() {
|
||||
header();
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << Bold << "Debug control";
|
||||
piCout << "-h " << Green << "- display this message and exit";
|
||||
piCout << "-H " << Green << "- display details help";
|
||||
piCout << "-q " << Green << "- quiet, no debug output to console";
|
||||
piCout << "-P " << Green << "- print list of all parsed files to console before exit";
|
||||
piCout << "-p " << Green << "- print list of all parsed files without file with \"main\" function to console before exit";
|
||||
piCout << "";
|
||||
piCout << Bold << "Parsing control";
|
||||
piCout << "-s " << Green << "- single file (don`t follow includes)";
|
||||
piCout << "-I<include_dir> " << Green << "- add include dir (e.g. -I.. -I../some_dir -I/usr/include)";
|
||||
piCout << "-D<define> " << Green << "- add define to preprocessor, macro PICODE is always defined (e.g. -DMY_DEFINE will add MY_DEFINE define)";
|
||||
piCout << "";
|
||||
piCout << Bold << "Output control";
|
||||
piCout << "-A " << Green << "- write all";
|
||||
piCout << "-M " << Green << "- write metainfo";
|
||||
piCout << "-E " << Green << "- write enums";
|
||||
piCout << "-S " << Green << "- write stream operators";
|
||||
piCout << "-G " << Green << "- write getter functions";
|
||||
//piCout << "-T " << Green << "- write text serialize functions";
|
||||
piCout << "-o <output_file> " << Green << "- output file for code model without extension (e.g. \"ccm\" - files \"ccm.h\" and \"ccm.cpp\" will be created)";
|
||||
piCout << "";
|
||||
piCout << Bold << "Input control";
|
||||
piCout << "<file> " << Green << "- add file to code model, all includes of this file will be proceed (e.g. \"main.cpp\")";
|
||||
}
|
||||
|
||||
void help() {
|
||||
header();
|
||||
piCout << help_string;
|
||||
}
|
||||
|
||||
void printError(const PIString & msg) {
|
||||
std::cerr << msg.data() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
PIString toCName(const PIString &s) {
|
||||
PIString ret(s.trimmed());
|
||||
if (ret.isEmpty()) return ret;
|
||||
ret.replaceAll('<', '_').replaceAll('>', '_');
|
||||
for (int i = 0; i < ret.size_s(); ++i) {
|
||||
if (i == 0) {
|
||||
if (!(ret[i].isAlpha() || ret[i].toAscii() == '_')) {ret.pop_front(); --i;}
|
||||
} else {
|
||||
if (!(ret[i].isAlpha() || ret[i].isDigit() || ret[i].toAscii() == '_')) {ret.remove(i); --i;}
|
||||
}
|
||||
}
|
||||
ret.replaceAll("__", "_");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void makeClassInfo(PIIOTextStream & ts, const PICodeParser::Entity * e) {
|
||||
ts << "\n\t{\n\tClassInfo * ci = new ClassInfo();\n";
|
||||
ts << "\tci->type = \"" << e->type << "\";\n";
|
||||
ts << "\tci->name = \"" << e->name << "\";\n";
|
||||
ts << "\tci->has_name = " << (e->has_name ? "true" : "false") << ";\n";
|
||||
if (!e->meta.isEmpty()) {
|
||||
auto i = e->meta.makeIterator();
|
||||
while (i.next())
|
||||
ts << "\tci->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
ts << "\t(*classesInfo)[ci->name] = ci;\n";
|
||||
if (e->parent_scope) {
|
||||
ts << "\tpci = " << "classesInfo->value(\"" << e->parent_scope->name << "\", 0);\n";
|
||||
ts << "\tif (pci) pci->children_info << ci;\n";
|
||||
}
|
||||
for (const PICodeParser::Entity * p: e->parents)
|
||||
ts << "\tci->parents << \"" << p->name << "\";\n";
|
||||
if (!e->members.isEmpty()) ts << "\n\tTypeInfo ti;\n";
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
ts << "\tti = TypeInfo(\"" << m.name << "\", \"" << m.type << "\"";
|
||||
if (m.attributes != 0) {
|
||||
bool fir = true;
|
||||
ts << ", ";
|
||||
if (m.attributes[PICodeParser::Const ]) {if (fir) fir = false; else ts << " | "; ts << "Const";}
|
||||
if (m.attributes[PICodeParser::Static ]) {if (fir) fir = false; else ts << " | "; ts << "Static";}
|
||||
if (m.attributes[PICodeParser::Mutable ]) {if (fir) fir = false; else ts << " | "; ts << "Mutable";}
|
||||
if (m.attributes[PICodeParser::Volatile]) {if (fir) fir = false; else ts << " | "; ts << "Volatile";}
|
||||
if (m.attributes[PICodeParser::Inline ]) {if (fir) fir = false; else ts << " | "; ts << "Inline";}
|
||||
if (m.attributes[PICodeParser::Virtual ]) {if (fir) fir = false; else ts << " | "; ts << "Virtual";}
|
||||
} else {
|
||||
if (m.isBitfield())
|
||||
ts << ", 0";
|
||||
}
|
||||
if (m.isBitfield())
|
||||
ts << ", " << m.bits;
|
||||
ts << ");\n";
|
||||
if (!m.meta.isEmpty()) {
|
||||
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
|
||||
ts << "\tti.meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
ts << "\tci->variables << ti;\n";
|
||||
}
|
||||
PIString arg;
|
||||
bool has_fi = false;
|
||||
for (const PICodeParser::Member & m: e->functions) {
|
||||
if (e->name.findCWord(m.name) >= 0) continue;
|
||||
if (!has_fi)
|
||||
ts << "\n\tFunctionInfo * fi;\n";
|
||||
has_fi = true;
|
||||
ts << "\tci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back());\n";
|
||||
ts << "\tfi->name = \"" << m.name << "\";";
|
||||
ts << " fi->return_type = TypeInfo(\"\", \"" << m.type << "\"";
|
||||
if (m.attributes[PICodeParser::Const] || m.attributes[PICodeParser::Static]) {
|
||||
bool fir = true;
|
||||
ts << ", ";
|
||||
if (m.attributes[PICodeParser::Const ]) {if (fir) fir = false; else ts << " | "; ts << "Const";}
|
||||
if (m.attributes[PICodeParser::Static]) {if (fir) fir = false; else ts << " | "; ts << "Static";}
|
||||
}
|
||||
ts << ");\n";
|
||||
//piCout << "write func" << m.name;
|
||||
for (const PIString & a: m.arguments_full) {
|
||||
//piCout << "write arg" << a;
|
||||
ts << "\tfi->arguments << TypeInfo(";
|
||||
arg = a;
|
||||
bool con = false;
|
||||
arg.prepend(" ");
|
||||
if (arg.find(" const ") >= 0) {
|
||||
arg.replaceAll(" const ", " ");
|
||||
con = true;
|
||||
}
|
||||
arg.trim();
|
||||
int i = 0;
|
||||
for (i = arg.size_s() - 1; i > 0; --i)
|
||||
if (!_isCChar(arg[i]) && !(arg[i].isDigit())) break;
|
||||
ts << "\"" << arg.takeRight(arg.size_s() - i - 1).trim() << "\", ";
|
||||
ts << "\"" << arg.trim() << "\"";
|
||||
if (con) ts << ", Const";
|
||||
ts << ");\n";
|
||||
}
|
||||
if (!m.meta.isEmpty()) {
|
||||
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
|
||||
ts << "\tfi->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
}
|
||||
ts << "\n\t}";
|
||||
}
|
||||
|
||||
|
||||
void makeEnumInfo(PIIOTextStream & ts, const PICodeParser::Enum * e) {
|
||||
if (e->name.isEmpty()) {
|
||||
ts << "\n\tei = (*enumsInfo)[\"\"];\n";
|
||||
} else {
|
||||
ts << "\n\tei = new EnumInfo();\n";
|
||||
ts << "\t(*enumsInfo)[\"" << e->name << "\"] = ei;\n";
|
||||
ts << "\tei->name = \"" << e->name << "\";\n";
|
||||
if (!e->meta.isEmpty()) {
|
||||
auto i = e->meta.makeIterator();
|
||||
while (i.next())
|
||||
ts << "\tei->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
}
|
||||
for (const PICodeParser::EnumeratorInfo & m: e->members) {
|
||||
ts << "\tei->members << PICodeInfo::EnumeratorInfo(\"" << m.name << "\", " << m.value << ");\n";
|
||||
if (!m.meta.isEmpty()) {
|
||||
auto i = m.meta.makeIterator();
|
||||
while (i.next())
|
||||
ts << "\tei->members.back().meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool writeClassStreamMembersOut(PIIOTextStream & ts, const PICodeParser::Entity * e, int & cnt, bool simple) {
|
||||
PIVector<PICodeParser::Member> ml;
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
|
||||
ml << m;
|
||||
}
|
||||
bool is_union = e->type == "union";
|
||||
PISet<int> used_id;
|
||||
for (const PICodeParser::Member & m: ml) {
|
||||
if (is_union && m.isBitfield())
|
||||
continue;
|
||||
if (m.meta.value("id") == "-") continue;
|
||||
++cnt;
|
||||
if (m.meta.contains("id"))
|
||||
cnt = m.meta.value("id").toInt();
|
||||
if (used_id[cnt]) {
|
||||
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
|
||||
return false;
|
||||
}
|
||||
if (m.dims.isEmpty()) {
|
||||
if (simple) {
|
||||
ts << "\ts << ";
|
||||
if (parser.isEnum(m.type))
|
||||
ts << "(int)";
|
||||
ts << "v." << m.name << ";\n";
|
||||
} else {
|
||||
ts << "\tcs << cs.chunk(" << cnt << ", ";
|
||||
if (parser.isEnum(m.type))
|
||||
ts << "(int)";
|
||||
ts << "v." << m.name << ");\n";
|
||||
}
|
||||
} else {
|
||||
PIString ptype = m.type.left(m.type.find('[')).trim();
|
||||
PIString size = m.dims[0];
|
||||
for (int i = 1; i < m.dims.size_s(); ++i) {
|
||||
size += " * ";
|
||||
size += m.dims[i];
|
||||
}
|
||||
if (simple) {
|
||||
ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
|
||||
ts << "\t\ts << ((const " << ptype << " *)(v." << m.name << "))[i];\n";
|
||||
} else {
|
||||
ts << "\tcs << cs.chunk(" << cnt << ", PIVector<" << ptype << " >((const " << ptype << " *)(v." << m.name << "), ";
|
||||
ts << size << "));\n";
|
||||
}
|
||||
}
|
||||
if (is_union)
|
||||
break;
|
||||
}
|
||||
if (is_union) return true;
|
||||
for (const PICodeParser::Entity * ce: e->children) {
|
||||
if (ce->has_name) continue;
|
||||
if (!writeClassStreamMembersOut(ts, ce, cnt, simple)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool writeClassStreamMembersIn(PIIOTextStream & ts, const PICodeParser::Entity * e, int & cnt, bool simple) {
|
||||
PIVector<PICodeParser::Member> ml;
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
|
||||
ml << m;
|
||||
}
|
||||
bool is_union = e->type == "union";
|
||||
PISet<int> used_id;
|
||||
for (const PICodeParser::Member & m: ml) {
|
||||
if (is_union && m.isBitfield())
|
||||
continue;
|
||||
if (m.meta.value("id") == "-") continue;
|
||||
++cnt;
|
||||
if (m.meta.contains("id"))
|
||||
cnt = m.meta.value("id").toInt();
|
||||
if (used_id[cnt]) {
|
||||
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
|
||||
return false;
|
||||
}
|
||||
used_id << cnt;
|
||||
if (m.dims.isEmpty()) {
|
||||
bool is_enum = parser.isEnum(m.type);
|
||||
if (simple) {
|
||||
ts << "\t";
|
||||
if (is_enum) ts << "{int i; ";
|
||||
ts << "s >> ";
|
||||
if (is_enum) ts << "i;";
|
||||
else ts << "v." << m.name << ";";
|
||||
if (is_enum) ts << " v." << m.name << " = (" << m.type << ")i;}";
|
||||
ts << "\n";
|
||||
} else {
|
||||
ts << "\t\tcase " << cnt << ":";
|
||||
if (is_enum) ts << " {int i;";
|
||||
ts << " cs.get(";
|
||||
if (is_enum) ts << "i";
|
||||
else ts << "v." << m.name;
|
||||
ts << ");";
|
||||
if (is_enum) ts << " v." << m.name << " = (" << m.type << ")i;}";
|
||||
ts << " break;\n";
|
||||
}
|
||||
} else {
|
||||
PIString ptype = m.type.left(m.type.find('[')).trim();
|
||||
PIString size = m.dims[0];
|
||||
for (int i = 1; i < m.dims.size_s(); ++i) {
|
||||
size += " * ";
|
||||
size += m.dims[i];
|
||||
}
|
||||
if (simple) {
|
||||
ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
|
||||
ts << "\t\ts >> ((" << ptype << " *)(v." << m.name << "))[i];\n";
|
||||
} else {
|
||||
ts << "\t\tcase " << cnt << ": {\n\t\t\tPIVector<" << ptype << " > d; cs.get(d);\n";
|
||||
ts << "\t\t\tint cnt = piMini(d.size_s(), " << size << ");\n";
|
||||
ts << "\t\t\tfor (int i = 0; i < cnt; ++i)\n";
|
||||
ts << "\t\t\t\t((" << ptype << " *)(v." << m.name << "))[i] = d[i];\n";
|
||||
ts << "\t\t\t}\n";
|
||||
ts << "\t\t\tbreak;\n";
|
||||
}
|
||||
}
|
||||
if (is_union)
|
||||
break;
|
||||
}
|
||||
if (is_union) return true;
|
||||
for (const PICodeParser::Entity * ce: e->children) {
|
||||
if (ce->has_name) continue;
|
||||
if (!writeClassStreamMembersIn(ts, ce, cnt, simple)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool needClassStream(const PICodeParser::Entity * e) {
|
||||
if (e->meta.contains("no-stream")) return false;
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public))
|
||||
continue;
|
||||
if (m.meta.value("id") == "-") continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool makeClassStream(PIIOTextStream & ts, const PICodeParser::Entity * e) {
|
||||
if (!needClassStream(e)) return true;
|
||||
bool simple = e->meta.contains("simple-stream");
|
||||
ts << "\nBINARY_STREAM_WRITE(" << e->name << ") {\n";
|
||||
if (!simple)
|
||||
ts << "\tPIChunkStream cs;\n";
|
||||
int cnt = 0;
|
||||
if (!writeClassStreamMembersOut(ts, e, cnt, simple)) return false;
|
||||
if (!simple)
|
||||
ts << "\ts << cs.data();\n";
|
||||
ts << "\treturn s;\n}\n";
|
||||
ts << "BINARY_STREAM_READ (" << e->name << ") {\n";
|
||||
if (!simple) {
|
||||
//ts << "\tif (s.size_s() < 4) return s;\n";
|
||||
ts << "\tPIByteArray csba; s >> csba;\n";
|
||||
ts << "\tPIChunkStream cs(csba);\n";
|
||||
ts << "\twhile (!cs.atEnd()) {\n";
|
||||
ts << "\t\tswitch (cs.read()) {\n";
|
||||
}
|
||||
cnt = 0;
|
||||
if (!writeClassStreamMembersIn(ts, e, cnt, simple)) return false;
|
||||
if (!simple)
|
||||
ts << "\t\t}\n\t}\n";
|
||||
ts << "\treturn s;\n}\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void makeGetterType(PIIOTextStream & ts, const PICodeParser::Entity * e) {
|
||||
if (!needClassStream(e)) return;
|
||||
ts << "\nconst char * getterType" << toCName(e->name) << "(const char * name) {\n";
|
||||
ts << "\tif (!name) return \"\";\n";
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public))
|
||||
continue;
|
||||
ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) return \"" << m.type << "\";\n";
|
||||
}
|
||||
ts << "\treturn \"\";\n}\n";
|
||||
}
|
||||
|
||||
|
||||
void makeGetterValue(PIIOTextStream & ts, const PICodeParser::Entity * e) {
|
||||
if (!needClassStream(e)) return;
|
||||
ts << "\nPIByteArray getterValue" << toCName(e->name) << "(const void * p, const char * name) {\n";
|
||||
ts << "\tPIByteArray ret;\n";
|
||||
ts << "\tif (!p || !name) return ret;\n";
|
||||
ts << "\t" << e->name << " * o = (" << e->name << "*)p;\n";
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public))
|
||||
continue;
|
||||
ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) {serialize(ret, o->" << m.name << "); return ret;}\n";
|
||||
}
|
||||
ts << "\treturn ret;\n}\n";
|
||||
}
|
||||
|
||||
|
||||
bool writeModel(PICodeParser & parser, PICLI & cli, const PIString out, bool meta, bool enums, bool streams, bool texts, bool getters) {
|
||||
PIString defname = "CCM_" + PIString::fromNumber(out.hash()) + "_H";
|
||||
PISet<PIString> inc_files;
|
||||
for (const PICodeParser::Entity * e: parser.entities)
|
||||
if (!e->name.startsWith("_PI"))
|
||||
inc_files << e->file;
|
||||
PIString inc_string;
|
||||
PIVector<PIString> incf = inc_files.toVector();
|
||||
for (const PIString & i: incf) {
|
||||
if ((i != parser.mainFile()) && (streams || texts || getters))
|
||||
inc_string += "\n#include \"" + i + "\"";
|
||||
}
|
||||
|
||||
PIFile f(out + ".cpp");
|
||||
f.clear();
|
||||
if (!f.open(PIIODevice::WriteOnly)) {
|
||||
piCout << "Error: can`t open out file" << f.path();
|
||||
return false;
|
||||
}
|
||||
PIIOTextStream ts(&f);
|
||||
ts << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n");
|
||||
ts << "#include <string.h>\n";
|
||||
ts << "#include \"" << out << ".h\"\n";
|
||||
ts << "\nusing namespace PICodeInfo;\n";
|
||||
|
||||
if (meta || enums || getters) {
|
||||
if (getters) {
|
||||
ts << "\n\n// Getter funtions\n";
|
||||
for (const PICodeParser::Entity * e: parser.entities) {
|
||||
if (!e->has_name || e->name.startsWith("_PI")) continue;
|
||||
makeGetterType(ts, e);
|
||||
makeGetterValue(ts, e);
|
||||
}
|
||||
}
|
||||
ts << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n";
|
||||
ts << "\tif (_inited_) return;\n\t_inited_ = true;\n\n";
|
||||
if (meta) {
|
||||
ts << "\tClassInfo * pci = new ClassInfo();\n";
|
||||
ts << "\t(*classesInfo)[\"\"] = pci;\n";
|
||||
}
|
||||
if (enums && !parser.enums.isEmpty()) {
|
||||
ts << "\tEnumInfo * ei;\n";
|
||||
ts << "\t(*enumsInfo)[\"\"] = new EnumInfo();\n";
|
||||
}
|
||||
if (meta) {
|
||||
ts << "\n\n// Classes\n";
|
||||
for (const PICodeParser::Entity * e: parser.entities) {
|
||||
if (e->name.startsWith("_PI")) continue;
|
||||
makeClassInfo(ts, e);
|
||||
}
|
||||
}
|
||||
if (enums) {
|
||||
ts << "\n// Enums\n";
|
||||
for (const PICodeParser::Enum & e: parser.enums)
|
||||
makeEnumInfo(ts, &e);
|
||||
}
|
||||
if (getters) {
|
||||
ts << "\n// Getters\n";
|
||||
for (const PICodeParser::Entity * e: parser.entities) {
|
||||
if (!needClassStream(e)) continue;
|
||||
if (!e->has_name || e->name.startsWith("_PI")) continue;
|
||||
ts << "\t(*accessValueFunctions)[\"" << e->name << "\"] = getterValue" << toCName(e->name) << ";\n";
|
||||
ts << "\t(*accessTypeFunctions)[\"" << e->name << "\"] = getterType" << toCName(e->name) << ";\n";
|
||||
}
|
||||
}
|
||||
ts << "}\n";
|
||||
ts << "\n\nbool __ClassInfo_" << defname << "_Initializer__::_inited_ = false;\n";
|
||||
}
|
||||
|
||||
f.close();
|
||||
|
||||
|
||||
f.setPath(out + ".h");
|
||||
f.clear();
|
||||
if (!f.open(PIIODevice::WriteOnly)) {
|
||||
piCout << "Error: can`t open out file" << f.path();
|
||||
return false;
|
||||
}
|
||||
ts << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
|
||||
ts << "// Execute command:\n";
|
||||
for (const PIString & _a: cli.rawArguments())
|
||||
ts << "// \"" << _a << "\"\n";
|
||||
ts << "\n";
|
||||
ts << "#ifndef " << defname << "\n#define " << defname << "\n\n";
|
||||
ts << "#include <pivariant.h>\n#include <picodeinfo.h>";
|
||||
if (streams || texts)
|
||||
ts << "\n#include <pichunkstream.h>";
|
||||
ts << inc_string << "\n";
|
||||
if (streams) {
|
||||
ts << "\n\n// Stream operators\n";
|
||||
for (const PICodeParser::Entity * e: parser.entities) {
|
||||
if (!e->has_name || e->name.startsWith("_PI") ||
|
||||
!(e->visibility == PICodeParser::Global || e->visibility == PICodeParser::Public)) continue;
|
||||
if (!makeClassStream(ts, e))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (meta || enums || getters) {
|
||||
ts << "\n\n// Metainformation\n\nclass __ClassInfo_" << defname << "_Initializer__ {\n";
|
||||
ts << "public:\n\t__ClassInfo_" << defname << "_Initializer__();\n\tstatic bool _inited_;\n};\n";
|
||||
ts << "\nstatic __ClassInfo_" << defname << "_Initializer__ __classinfo_" << defname.toLowerCase() << "_initializer__;\n";
|
||||
}
|
||||
ts << "\n\n#endif // " << defname << "\n";
|
||||
f.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
PICLI cli(argc, argv);
|
||||
//piCout << cli.rawArguments();
|
||||
cli.setOptionalArgumentsCount(-1);
|
||||
cli.addArgument("output", true);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("Help");
|
||||
cli.addArgument("quiet");
|
||||
cli.addArgument("All");
|
||||
cli.addArgument("Metainfo");
|
||||
cli.addArgument("Enum");
|
||||
cli.addArgument("Stream");
|
||||
cli.addArgument("Getter");
|
||||
cli.addArgument("Text");
|
||||
cli.addArgument("print");
|
||||
cli.addArgument("Print");
|
||||
cli.addArgument("single");
|
||||
if (cli.hasArgument("Help")) {
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.optionalArguments().isEmpty()) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
piDebug = !cli.hasArgument("quiet");
|
||||
for (const PIString & a: cli.rawArguments()) {
|
||||
if (a.startsWith("-I")) parser.includeDirectory(a.mid(2));
|
||||
if (a.startsWith("-D")) parser.addDefine(a.mid(2), PIString());
|
||||
}
|
||||
PIStringList files;
|
||||
for (const PIString & a: cli.optionalArguments())
|
||||
if (!a.startsWith("-")) files << a;
|
||||
piCout << Cyan << Bold << "Parse files" << files << "...";
|
||||
parser.parseFiles(files, !cli.hasArgument("single"));
|
||||
piCout << Cyan << Bold << "Parsing done";
|
||||
piCout << Cyan << Bold << "Writing code model ...";
|
||||
bool all = cli.hasArgument("All");
|
||||
if (!writeModel(parser, cli, cli.argumentValue("output"), cli.hasArgument("Metainfo") || all,
|
||||
cli.hasArgument("Enum") || all,
|
||||
cli.hasArgument("Stream") || all,
|
||||
cli.hasArgument("Text") || all,
|
||||
cli.hasArgument("Getter") || all))
|
||||
return 1;
|
||||
piCout << Cyan << Bold << "Writing done";
|
||||
if (cli.hasArgument("print") || cli.hasArgument("Print")) {
|
||||
bool womain = cli.hasArgument("print");
|
||||
piDebug = true;
|
||||
PIStringList pf(parser.parsedFiles());
|
||||
for (const PIString & f: pf) {
|
||||
if (!womain || (f != parser.mainFile()))
|
||||
piCout << f;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Code model generator
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "picli.h"
|
||||
#include "picodeparser.h"
|
||||
#include "piiostream.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
PICodeParser parser;
|
||||
|
||||
const char help_string[] = "-M (Metainfo)\n"
|
||||
"Generate classes and structs info. It contains\n"
|
||||
"names, subclass info, all methods and variables.\n"
|
||||
"Place information:\n"
|
||||
" * classes and structs - PICodeInfo::classesInfo\n"
|
||||
" * methods - ClassInfo::functions\n"
|
||||
" * variables - ClassInfo::variables\n"
|
||||
"\n"
|
||||
"-E (Enums)\n"
|
||||
"Generate enumeration descriptions.\n"
|
||||
"Useful for GUI integrations, because\n"
|
||||
"you can obtain enumerators value and name.\n"
|
||||
" * enums - PICodeInfo::enumsInfo\n"
|
||||
"\n"
|
||||
"-S (Stream operators)\n"
|
||||
"Generate store/restore operators with format\n"
|
||||
"BINARY_STREAM_WRITE(<type>);\n"
|
||||
"BINARY_STREAM_READ (<type>);\n"
|
||||
"Only public variables used. All variables stored/restored\n"
|
||||
"using PIChunkStream. IDs are variable number, starting from 1.\n"
|
||||
"You can override ID with PIMETA(id=<ID>). If in class or struct\n"
|
||||
"PIMETA(simple-stream) presence, then variables stored/restored\n"
|
||||
"with simple << and >> operators.\n"
|
||||
"If PIMETA(no-stream) presence, then class or struct ignored.\n"
|
||||
"\n"
|
||||
"-G (Getter functions)\n"
|
||||
"Generate anonymous access methods for member typenames and values.\n"
|
||||
"Every class or struct member typename can be obtained with:\n"
|
||||
"const char * getMemberType(const char * class_name, const char * member_name)\n"
|
||||
"Member value can be obtained with:\n"
|
||||
"PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name)\n"
|
||||
"where \"p\" - class or struct pointer, and returns serialized value.\n"
|
||||
"PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name)\n"
|
||||
"where \"p\" - class or struct pointer, and returns value as registered PIVariant.\n"
|
||||
"";
|
||||
|
||||
void header() {
|
||||
piCout << Bold << "PIP Code model generator";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default
|
||||
<< "\"pip_cmg [-hHqPpsAMESTG] -o <output_file> [-I<include_dir1>] [-I<include_dir1>] [...] [-D<define1>] [-D<define1>] [...] "
|
||||
"<file1> [<file2>] [<file3>] [...]\""
|
||||
<< NewLine;
|
||||
}
|
||||
|
||||
void usage() {
|
||||
header();
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << Bold << "Debug control";
|
||||
piCout << "-h " << Green << "- display this message and exit";
|
||||
piCout << "-H " << Green << "- display details help";
|
||||
piCout << "-q " << Green << "- quiet, no debug output to console";
|
||||
piCout << "-P " << Green << "- print list of all parsed files to console before exit";
|
||||
piCout << "-p " << Green << "- print list of all parsed files without file with \"main\" function to console before exit";
|
||||
piCout << "";
|
||||
piCout << Bold << "Parsing control";
|
||||
piCout << "-s " << Green << "- single file (don`t follow includes)";
|
||||
piCout << "-I<include_dir> " << Green << "- add include dir (e.g. -I.. -I../some_dir -I/usr/include)";
|
||||
piCout << "-D<define> " << Green
|
||||
<< "- add define to preprocessor, macro PICODE is always defined (e.g. -DMY_DEFINE will add MY_DEFINE define)";
|
||||
piCout << "";
|
||||
piCout << Bold << "Output control";
|
||||
piCout << "-A " << Green << "- write all";
|
||||
piCout << "-M " << Green << "- write metainfo";
|
||||
piCout << "-E " << Green << "- write enums";
|
||||
piCout << "-S " << Green << "- write stream operators";
|
||||
piCout << "-G " << Green << "- write getter functions";
|
||||
// piCout << "-T " << Green << "- write text serialize functions";
|
||||
piCout << "-o <output_file> " << Green
|
||||
<< "- output file for code model without extension (e.g. \"ccm\" - files \"ccm.h\" and \"ccm.cpp\" will be created)";
|
||||
piCout << "";
|
||||
piCout << Bold << "Input control";
|
||||
piCout << "<file> " << Green << "- add file to code model, all includes of this file will be proceed (e.g. \"main.cpp\")";
|
||||
}
|
||||
|
||||
void help() {
|
||||
header();
|
||||
piCout << help_string;
|
||||
}
|
||||
|
||||
void printError(const PIString & msg) {
|
||||
std::cerr << msg.data() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
PIString toCName(const PIString & s) {
|
||||
PIString ret(s.trimmed());
|
||||
if (ret.isEmpty()) return ret;
|
||||
ret.replaceAll('<', '_').replaceAll('>', '_');
|
||||
for (int i = 0; i < ret.size_s(); ++i) {
|
||||
if (i == 0) {
|
||||
if (!(ret[i].isAlpha() || ret[i].toAscii() == '_')) {
|
||||
ret.pop_front();
|
||||
--i;
|
||||
}
|
||||
} else {
|
||||
if (!(ret[i].isAlpha() || ret[i].isDigit() || ret[i].toAscii() == '_')) {
|
||||
ret.remove(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret.replaceAll("__", "_");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void makeClassInfo(PIIOTextStream & ts, const PICodeParser::Entity * e) {
|
||||
ts << "\n\t{\n\tClassInfo * ci = new ClassInfo();\n";
|
||||
ts << "\tci->type = \"" << e->type << "\";\n";
|
||||
ts << "\tci->name = \"" << e->name << "\";\n";
|
||||
ts << "\tci->has_name = " << (e->has_name ? "true" : "false") << ";\n";
|
||||
if (!e->meta.isEmpty()) {
|
||||
auto i = e->meta.makeIterator();
|
||||
while (i.next())
|
||||
ts << "\tci->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
ts << "\t(*classesInfo)[ci->name] = ci;\n";
|
||||
if (e->parent_scope) {
|
||||
ts << "\tpci = "
|
||||
<< "classesInfo->value(\"" << e->parent_scope->name << "\", 0);\n";
|
||||
ts << "\tif (pci) pci->children_info << ci;\n";
|
||||
}
|
||||
for (const PICodeParser::Entity * p: e->parents)
|
||||
ts << "\tci->parents << \"" << p->name << "\";\n";
|
||||
if (!e->members.isEmpty()) ts << "\n\tTypeInfo ti;\n";
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
ts << "\tti = TypeInfo(\"" << m.name << "\", \"" << m.type << "\"";
|
||||
if (m.attributes != 0) {
|
||||
bool fir = true;
|
||||
ts << ", ";
|
||||
if (m.attributes[PICodeParser::Const]) {
|
||||
if (fir)
|
||||
fir = false;
|
||||
else
|
||||
ts << " | ";
|
||||
ts << "Const";
|
||||
}
|
||||
if (m.attributes[PICodeParser::Static]) {
|
||||
if (fir)
|
||||
fir = false;
|
||||
else
|
||||
ts << " | ";
|
||||
ts << "Static";
|
||||
}
|
||||
if (m.attributes[PICodeParser::Mutable]) {
|
||||
if (fir)
|
||||
fir = false;
|
||||
else
|
||||
ts << " | ";
|
||||
ts << "Mutable";
|
||||
}
|
||||
if (m.attributes[PICodeParser::Volatile]) {
|
||||
if (fir)
|
||||
fir = false;
|
||||
else
|
||||
ts << " | ";
|
||||
ts << "Volatile";
|
||||
}
|
||||
if (m.attributes[PICodeParser::Inline]) {
|
||||
if (fir)
|
||||
fir = false;
|
||||
else
|
||||
ts << " | ";
|
||||
ts << "Inline";
|
||||
}
|
||||
if (m.attributes[PICodeParser::Virtual]) {
|
||||
if (fir)
|
||||
fir = false;
|
||||
else
|
||||
ts << " | ";
|
||||
ts << "Virtual";
|
||||
}
|
||||
} else {
|
||||
if (m.isBitfield()) ts << ", 0";
|
||||
}
|
||||
if (m.isBitfield()) ts << ", " << m.bits;
|
||||
ts << ");\n";
|
||||
if (!m.meta.isEmpty()) {
|
||||
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
|
||||
ts << "\tti.meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
ts << "\tci->variables << ti;\n";
|
||||
}
|
||||
PIString arg;
|
||||
bool has_fi = false;
|
||||
for (const PICodeParser::Member & m: e->functions) {
|
||||
if (e->name.findCWord(m.name) >= 0) continue;
|
||||
if (!has_fi) ts << "\n\tFunctionInfo * fi;\n";
|
||||
has_fi = true;
|
||||
ts << "\tci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back());\n";
|
||||
ts << "\tfi->name = \"" << m.name << "\";";
|
||||
ts << " fi->return_type = TypeInfo(\"\", \"" << m.type << "\"";
|
||||
if (m.attributes[PICodeParser::Const] || m.attributes[PICodeParser::Static]) {
|
||||
bool fir = true;
|
||||
ts << ", ";
|
||||
if (m.attributes[PICodeParser::Const]) {
|
||||
if (fir)
|
||||
fir = false;
|
||||
else
|
||||
ts << " | ";
|
||||
ts << "Const";
|
||||
}
|
||||
if (m.attributes[PICodeParser::Static]) {
|
||||
if (fir)
|
||||
fir = false;
|
||||
else
|
||||
ts << " | ";
|
||||
ts << "Static";
|
||||
}
|
||||
}
|
||||
ts << ");\n";
|
||||
// piCout << "write func" << m.name;
|
||||
for (const PIString & a: m.arguments_full) {
|
||||
// piCout << "write arg" << a;
|
||||
ts << "\tfi->arguments << TypeInfo(";
|
||||
arg = a;
|
||||
bool con = false;
|
||||
arg.prepend(" ");
|
||||
if (arg.find(" const ") >= 0) {
|
||||
arg.replaceAll(" const ", " ");
|
||||
con = true;
|
||||
}
|
||||
arg.trim();
|
||||
int i = 0;
|
||||
for (i = arg.size_s() - 1; i > 0; --i)
|
||||
if (!_isCChar(arg[i]) && !(arg[i].isDigit())) break;
|
||||
ts << "\"" << arg.takeRight(arg.size_s() - i - 1).trim() << "\", ";
|
||||
ts << "\"" << arg.trim() << "\"";
|
||||
if (con) ts << ", Const";
|
||||
ts << ");\n";
|
||||
}
|
||||
if (!m.meta.isEmpty()) {
|
||||
for (PICodeParser::MetaMap::const_iterator i = m.meta.begin(); i != m.meta.end(); ++i)
|
||||
ts << "\tfi->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
}
|
||||
ts << "\n\t}";
|
||||
}
|
||||
|
||||
|
||||
void makeEnumInfo(PIIOTextStream & ts, const PICodeParser::Enum * e) {
|
||||
if (e->name.isEmpty()) {
|
||||
ts << "\n\tei = (*enumsInfo)[\"\"];\n";
|
||||
} else {
|
||||
ts << "\n\tei = new EnumInfo();\n";
|
||||
ts << "\t(*enumsInfo)[\"" << e->name << "\"] = ei;\n";
|
||||
ts << "\tei->name = \"" << e->name << "\";\n";
|
||||
if (!e->meta.isEmpty()) {
|
||||
auto i = e->meta.makeIterator();
|
||||
while (i.next())
|
||||
ts << "\tei->meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
}
|
||||
for (const PICodeParser::EnumeratorInfo & m: e->members) {
|
||||
ts << "\tei->members << PICodeInfo::EnumeratorInfo(\"" << m.name << "\", " << m.value << ");\n";
|
||||
if (!m.meta.isEmpty()) {
|
||||
auto i = m.meta.makeIterator();
|
||||
while (i.next())
|
||||
ts << "\tei->members.back().meta[\"" << i.key() << "\"] = PIString::fromUTF8(\"" << i.value() << "\");\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool writeClassStreamMembersOut(PIIOTextStream & ts, const PICodeParser::Entity * e, int & cnt, bool simple) {
|
||||
PIVector<PICodeParser::Member> ml;
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
|
||||
ml << m;
|
||||
}
|
||||
bool is_union = e->type == "union";
|
||||
PISet<int> used_id;
|
||||
for (const PICodeParser::Member & m: ml) {
|
||||
if (is_union && m.isBitfield()) continue;
|
||||
if (m.meta.value("id") == "-") continue;
|
||||
++cnt;
|
||||
if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
|
||||
if (used_id[cnt]) {
|
||||
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
|
||||
return false;
|
||||
}
|
||||
if (m.dims.isEmpty()) {
|
||||
if (simple) {
|
||||
ts << "\ts << ";
|
||||
if (parser.isEnum(m.type)) ts << "(int)";
|
||||
ts << "v." << m.name << ";\n";
|
||||
} else {
|
||||
ts << "\tcs << cs.chunk(" << cnt << ", ";
|
||||
if (parser.isEnum(m.type)) ts << "(int)";
|
||||
ts << "v." << m.name << ");\n";
|
||||
}
|
||||
} else {
|
||||
PIString ptype = m.type.left(m.type.find('[')).trim();
|
||||
PIString size = m.dims[0];
|
||||
for (int i = 1; i < m.dims.size_s(); ++i) {
|
||||
size += " * ";
|
||||
size += m.dims[i];
|
||||
}
|
||||
if (simple) {
|
||||
ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
|
||||
ts << "\t\ts << ((const " << ptype << " *)(v." << m.name << "))[i];\n";
|
||||
} else {
|
||||
ts << "\tcs << cs.chunk(" << cnt << ", PIVector<" << ptype << " >((const " << ptype << " *)(v." << m.name << "), ";
|
||||
ts << size << "));\n";
|
||||
}
|
||||
}
|
||||
if (is_union) break;
|
||||
}
|
||||
if (is_union) return true;
|
||||
for (const PICodeParser::Entity * ce: e->children) {
|
||||
if (ce->has_name) continue;
|
||||
if (!writeClassStreamMembersOut(ts, ce, cnt, simple)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool writeClassStreamMembersIn(PIIOTextStream & ts, const PICodeParser::Entity * e, int & cnt, bool simple) {
|
||||
PIVector<PICodeParser::Member> ml;
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
|
||||
ml << m;
|
||||
}
|
||||
bool is_union = e->type == "union";
|
||||
PISet<int> used_id;
|
||||
for (const PICodeParser::Member & m: ml) {
|
||||
if (is_union && m.isBitfield()) continue;
|
||||
if (m.meta.value("id") == "-") continue;
|
||||
++cnt;
|
||||
if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
|
||||
if (used_id[cnt]) {
|
||||
printError("Error with \"" + e->name + "\" stream operator: ID " + PIString::fromNumber(cnt) + " already used");
|
||||
return false;
|
||||
}
|
||||
used_id << cnt;
|
||||
if (m.dims.isEmpty()) {
|
||||
bool is_enum = parser.isEnum(m.type);
|
||||
if (simple) {
|
||||
ts << "\t";
|
||||
if (is_enum) ts << "{int i; ";
|
||||
ts << "s >> ";
|
||||
if (is_enum)
|
||||
ts << "i;";
|
||||
else
|
||||
ts << "v." << m.name << ";";
|
||||
if (is_enum) ts << " v." << m.name << " = (" << m.type << ")i;}";
|
||||
ts << "\n";
|
||||
} else {
|
||||
ts << "\t\tcase " << cnt << ":";
|
||||
if (is_enum) ts << " {int i;";
|
||||
ts << " cs.get(";
|
||||
if (is_enum)
|
||||
ts << "i";
|
||||
else
|
||||
ts << "v." << m.name;
|
||||
ts << ");";
|
||||
if (is_enum) ts << " v." << m.name << " = (" << m.type << ")i;}";
|
||||
ts << " break;\n";
|
||||
}
|
||||
} else {
|
||||
PIString ptype = m.type.left(m.type.find('[')).trim();
|
||||
PIString size = m.dims[0];
|
||||
for (int i = 1; i < m.dims.size_s(); ++i) {
|
||||
size += " * ";
|
||||
size += m.dims[i];
|
||||
}
|
||||
if (simple) {
|
||||
ts << "\tfor (int i = 0; i < " << size << "; ++i)\n";
|
||||
ts << "\t\ts >> ((" << ptype << " *)(v." << m.name << "))[i];\n";
|
||||
} else {
|
||||
ts << "\t\tcase " << cnt << ": {\n\t\t\tPIVector<" << ptype << " > d; cs.get(d);\n";
|
||||
ts << "\t\t\tint cnt = piMini(d.size_s(), " << size << ");\n";
|
||||
ts << "\t\t\tfor (int i = 0; i < cnt; ++i)\n";
|
||||
ts << "\t\t\t\t((" << ptype << " *)(v." << m.name << "))[i] = d[i];\n";
|
||||
ts << "\t\t\t}\n";
|
||||
ts << "\t\t\tbreak;\n";
|
||||
}
|
||||
}
|
||||
if (is_union) break;
|
||||
}
|
||||
if (is_union) return true;
|
||||
for (const PICodeParser::Entity * ce: e->children) {
|
||||
if (ce->has_name) continue;
|
||||
if (!writeClassStreamMembersIn(ts, ce, cnt, simple)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool needClassStream(const PICodeParser::Entity * e) {
|
||||
if (e->meta.contains("no-stream")) return false;
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
|
||||
if (m.meta.value("id") == "-") continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool makeClassStream(PIIOTextStream & ts, const PICodeParser::Entity * e) {
|
||||
if (!needClassStream(e)) return true;
|
||||
bool simple = e->meta.contains("simple-stream");
|
||||
ts << "\nBINARY_STREAM_WRITE(" << e->name << ") {\n";
|
||||
if (!simple) ts << "\tPIChunkStream cs;\n";
|
||||
int cnt = 0;
|
||||
if (!writeClassStreamMembersOut(ts, e, cnt, simple)) return false;
|
||||
if (!simple) ts << "\ts << cs.data();\n";
|
||||
ts << "\treturn s;\n}\n";
|
||||
ts << "BINARY_STREAM_READ (" << e->name << ") {\n";
|
||||
if (!simple) {
|
||||
// ts << "\tif (s.size_s() < 4) return s;\n";
|
||||
ts << "\tPIByteArray csba; s >> csba;\n";
|
||||
ts << "\tPIChunkStream cs(csba);\n";
|
||||
ts << "\twhile (!cs.atEnd()) {\n";
|
||||
ts << "\t\tswitch (cs.read()) {\n";
|
||||
}
|
||||
cnt = 0;
|
||||
if (!writeClassStreamMembersIn(ts, e, cnt, simple)) return false;
|
||||
if (!simple) ts << "\t\t}\n\t}\n";
|
||||
ts << "\treturn s;\n}\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void makeGetterType(PIIOTextStream & ts, const PICodeParser::Entity * e) {
|
||||
if (!needClassStream(e)) return;
|
||||
ts << "\nconst char * getterType" << toCName(e->name) << "(const char * name) {\n";
|
||||
ts << "\tif (!name) return \"\";\n";
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
|
||||
ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) return \"" << m.type << "\";\n";
|
||||
}
|
||||
ts << "\treturn \"\";\n}\n";
|
||||
}
|
||||
|
||||
|
||||
void makeGetterValue(PIIOTextStream & ts, const PICodeParser::Entity * e) {
|
||||
if (!needClassStream(e)) return;
|
||||
ts << "\nPIByteArray getterValue" << toCName(e->name) << "(const void * p, const char * name) {\n";
|
||||
ts << "\tPIByteArray ret;\n";
|
||||
ts << "\tif (!p || !name) return ret;\n";
|
||||
ts << "\t" << e->name << " * o = (" << e->name << "*)p;\n";
|
||||
for (const PICodeParser::Member & m: e->members) {
|
||||
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
|
||||
ts << "\tif (strcmp(name, \"" << m.name << "\") == 0) {serialize(ret, o->" << m.name << "); return ret;}\n";
|
||||
}
|
||||
ts << "\treturn ret;\n}\n";
|
||||
}
|
||||
|
||||
|
||||
bool writeModel(PICodeParser & parser, PICLI & cli, const PIString out, bool meta, bool enums, bool streams, bool texts, bool getters) {
|
||||
PIString defname = "CCM_" + PIString::fromNumber(out.hash()) + "_H";
|
||||
PISet<PIString> inc_files;
|
||||
for (const PICodeParser::Entity * e: parser.entities)
|
||||
if (!e->name.startsWith("_PI")) inc_files << e->file;
|
||||
PIString inc_string;
|
||||
PIVector<PIString> incf = inc_files.toVector();
|
||||
for (const PIString & i: incf) {
|
||||
if ((i != parser.mainFile()) && (streams || texts || getters)) inc_string += "\n#include \"" + i + "\"";
|
||||
}
|
||||
|
||||
PIFile f(out + ".cpp");
|
||||
f.clear();
|
||||
if (!f.open(PIIODevice::WriteOnly)) {
|
||||
piCout << "Error: can`t open out file" << f.path();
|
||||
return false;
|
||||
}
|
||||
PIIOTextStream ts(&f);
|
||||
ts << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n");
|
||||
ts << "#include <string.h>\n";
|
||||
ts << "#include \"" << out << ".h\"\n";
|
||||
ts << "\nusing namespace PICodeInfo;\n";
|
||||
|
||||
if (meta || enums || getters) {
|
||||
if (getters) {
|
||||
ts << "\n\n// Getter funtions\n";
|
||||
for (const PICodeParser::Entity * e: parser.entities) {
|
||||
if (!e->has_name || e->name.startsWith("_PI")) continue;
|
||||
makeGetterType(ts, e);
|
||||
makeGetterValue(ts, e);
|
||||
}
|
||||
}
|
||||
ts << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n";
|
||||
ts << "\tif (_inited_) return;\n\t_inited_ = true;\n\n";
|
||||
if (meta) {
|
||||
ts << "\tClassInfo * pci = new ClassInfo();\n";
|
||||
ts << "\t(*classesInfo)[\"\"] = pci;\n";
|
||||
}
|
||||
if (enums && !parser.enums.isEmpty()) {
|
||||
ts << "\tEnumInfo * ei;\n";
|
||||
ts << "\t(*enumsInfo)[\"\"] = new EnumInfo();\n";
|
||||
}
|
||||
if (meta) {
|
||||
ts << "\n\n// Classes\n";
|
||||
for (const PICodeParser::Entity * e: parser.entities) {
|
||||
if (e->name.startsWith("_PI")) continue;
|
||||
makeClassInfo(ts, e);
|
||||
}
|
||||
}
|
||||
if (enums) {
|
||||
ts << "\n// Enums\n";
|
||||
for (const PICodeParser::Enum & e: parser.enums)
|
||||
makeEnumInfo(ts, &e);
|
||||
}
|
||||
if (getters) {
|
||||
ts << "\n// Getters\n";
|
||||
for (const PICodeParser::Entity * e: parser.entities) {
|
||||
if (!needClassStream(e)) continue;
|
||||
if (!e->has_name || e->name.startsWith("_PI")) continue;
|
||||
ts << "\t(*accessValueFunctions)[\"" << e->name << "\"] = getterValue" << toCName(e->name) << ";\n";
|
||||
ts << "\t(*accessTypeFunctions)[\"" << e->name << "\"] = getterType" << toCName(e->name) << ";\n";
|
||||
}
|
||||
}
|
||||
ts << "}\n";
|
||||
ts << "\n\nbool __ClassInfo_" << defname << "_Initializer__::_inited_ = false;\n";
|
||||
}
|
||||
|
||||
f.close();
|
||||
|
||||
|
||||
f.setPath(out + ".h");
|
||||
f.clear();
|
||||
if (!f.open(PIIODevice::WriteOnly)) {
|
||||
piCout << "Error: can`t open out file" << f.path();
|
||||
return false;
|
||||
}
|
||||
ts << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
|
||||
ts << "// Execute command:\n";
|
||||
for (const PIString & _a: cli.rawArguments())
|
||||
ts << "// \"" << _a << "\"\n";
|
||||
ts << "\n";
|
||||
ts << "#ifndef " << defname << "\n#define " << defname << "\n\n";
|
||||
ts << "#include <pivariant.h>\n#include <picodeinfo.h>";
|
||||
if (streams || texts) ts << "\n#include <pichunkstream.h>";
|
||||
ts << inc_string << "\n";
|
||||
if (streams) {
|
||||
ts << "\n\n// Stream operators\n";
|
||||
for (const PICodeParser::Entity * e: parser.entities) {
|
||||
if (!e->has_name || e->name.startsWith("_PI") ||
|
||||
!(e->visibility == PICodeParser::Global || e->visibility == PICodeParser::Public))
|
||||
continue;
|
||||
if (!makeClassStream(ts, e)) return false;
|
||||
}
|
||||
}
|
||||
if (meta || enums || getters) {
|
||||
ts << "\n\n// Metainformation\n\nclass __ClassInfo_" << defname << "_Initializer__ {\n";
|
||||
ts << "public:\n\t__ClassInfo_" << defname << "_Initializer__();\n\tstatic bool _inited_;\n};\n";
|
||||
ts << "\nstatic __ClassInfo_" << defname << "_Initializer__ __classinfo_" << defname.toLowerCase() << "_initializer__;\n";
|
||||
}
|
||||
ts << "\n\n#endif // " << defname << "\n";
|
||||
f.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
PICLI cli(argc, argv);
|
||||
// piCout << cli.rawArguments();
|
||||
cli.setOptionalArgumentsCount(-1);
|
||||
cli.addArgument("output", true);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("Help");
|
||||
cli.addArgument("quiet");
|
||||
cli.addArgument("All");
|
||||
cli.addArgument("Metainfo");
|
||||
cli.addArgument("Enum");
|
||||
cli.addArgument("Stream");
|
||||
cli.addArgument("Getter");
|
||||
cli.addArgument("Text");
|
||||
cli.addArgument("print");
|
||||
cli.addArgument("Print");
|
||||
cli.addArgument("single");
|
||||
if (cli.hasArgument("Help")) {
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.optionalArguments().isEmpty()) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
piDebug = !cli.hasArgument("quiet");
|
||||
for (const PIString & a: cli.rawArguments()) {
|
||||
if (a.startsWith("-I")) parser.includeDirectory(a.mid(2));
|
||||
if (a.startsWith("-D")) parser.addDefine(a.mid(2), PIString());
|
||||
}
|
||||
PIStringList files;
|
||||
for (const PIString & a: cli.optionalArguments())
|
||||
if (!a.startsWith("-")) files << a;
|
||||
piCout << Cyan << Bold << "Parse files" << files << "...";
|
||||
parser.parseFiles(files, !cli.hasArgument("single"));
|
||||
piCout << Cyan << Bold << "Parsing done";
|
||||
piCout << Cyan << Bold << "Writing code model ...";
|
||||
bool all = cli.hasArgument("All");
|
||||
if (!writeModel(parser,
|
||||
cli,
|
||||
cli.argumentValue("output"),
|
||||
cli.hasArgument("Metainfo") || all,
|
||||
cli.hasArgument("Enum") || all,
|
||||
cli.hasArgument("Stream") || all,
|
||||
cli.hasArgument("Text") || all,
|
||||
cli.hasArgument("Getter") || all))
|
||||
return 1;
|
||||
piCout << Cyan << Bold << "Writing done";
|
||||
if (cli.hasArgument("print") || cli.hasArgument("Print")) {
|
||||
bool womain = cli.hasArgument("print");
|
||||
piDebug = true;
|
||||
PIStringList pf(parser.parsedFiles());
|
||||
for (const PIString & f: pf) {
|
||||
if (!womain || (f != parser.mainFile())) piCout << f;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,121 +1,129 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Crypth / decrypth files utility
|
||||
Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pip.h"
|
||||
#include "picrypt.h"
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << Bold << "PIP Crypt Utility";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default << "\"picrypt [-thr] [-g <pass>] [-o <out_file>] [{[-c <file>] [-d <file>]} {[-p <pass>] [-s <hash>] [-k <key_file>] [-x <hex_key>]}]\"" << NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << "-h --help " << Green << "- display this message and exit";
|
||||
piCout << "-g --genhash " << Green << "- generate hash from <pass> string";
|
||||
piCout << "-t --text " << Green << "- output in text base64";
|
||||
piCout << "-o --out <out_file> " << Green << "- write out to file <out_file>";
|
||||
piCout << "-c --crypt <file> " << Green << "- crypt file <file> using secret <pass> or <hash> or <key_file>";
|
||||
piCout << "-d --decrypt <file> " << Green << "- decrypt file <file> using secret <pass> or <hash> or <key_file>";
|
||||
piCout << "-p --pass <pass> " << Green << "- use secret from passphrase <pass>";
|
||||
piCout << "-s --secret <hash> " << Green << "- use secret from hash <hash>";
|
||||
piCout << "-k --key <key_file> " << Green << "- use secret from binary key_file <key_file>";
|
||||
piCout << "-x --hex [<hex_key>] " << Green << "- use secret from hex hash <hex_key> or output in text hex";
|
||||
piCout << "-r --random " << Green << "- generate random secret key";
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
PICrypt::hash("");
|
||||
PICrypt crypt;
|
||||
PIByteArray bout;
|
||||
PICLI cli(argc, argv);
|
||||
cli.addArgument("genhash", true);
|
||||
cli.addArgument("out", true);
|
||||
cli.addArgument("crypt", true);
|
||||
cli.addArgument("decrypt", true);
|
||||
cli.addArgument("pass", true);
|
||||
cli.addArgument("secret", true);
|
||||
cli.addArgument("key", true);
|
||||
cli.addArgument("hex", 'x', "hex", true);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("text");
|
||||
cli.addArgument("random");
|
||||
|
||||
if (!(cli.hasArgument("genhash") ||
|
||||
cli.hasArgument("crypt") ||
|
||||
cli.hasArgument("decrypt") ||
|
||||
cli.hasArgument("random")) ||
|
||||
cli.hasArgument("help")) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIString out_file = cli.argumentValue("out");
|
||||
PIFile outf;
|
||||
if (!out_file.isEmpty()) {
|
||||
if (outf.open(out_file, PIIODevice::ReadWrite)) {
|
||||
outf.resize(0);
|
||||
} else piCout << "error: while open out file";
|
||||
}
|
||||
|
||||
if (cli.hasArgument("genhash")) {
|
||||
PIString s = cli.argumentValue("genhash");
|
||||
bout = crypt.hash(s);
|
||||
} else if (cli.hasArgument("random")) bout = crypt.generateKey();
|
||||
|
||||
if (cli.hasArgument("crypt") || cli.hasArgument("decrypt")) {
|
||||
PIByteArray secret;
|
||||
if (cli.hasArgument("key")) {
|
||||
PIFile keyf(cli.argumentValue("key"), PIIODevice::ReadOnly);
|
||||
if (keyf.open()) secret = keyf.readAll();
|
||||
else piCout << "error: while open key file";
|
||||
}
|
||||
if (cli.hasArgument("pass")) secret = crypt.hash(cli.argumentValue("pass"));
|
||||
if (cli.hasArgument("secret")) secret = PIByteArray::fromBase64(cli.argumentValue("secret").toByteArray());
|
||||
if (cli.hasArgument("hex")) secret = PIByteArray::fromHex(cli.argumentValue("hex").toByteArray());
|
||||
if (secret.size() == crypt.sizeKey()) {
|
||||
PIFile inf;
|
||||
PIString in_file;
|
||||
PIByteArray bin;
|
||||
crypt.setKey(secret);
|
||||
if (cli.hasArgument("crypt")) in_file = cli.argumentValue("crypt");
|
||||
if (cli.hasArgument("decrypt")) in_file = cli.argumentValue("decrypt");
|
||||
if (inf.open(in_file, PIIODevice::ReadOnly)) {
|
||||
bin = inf.readAll();
|
||||
if (cli.hasArgument("crypt")) bout = crypt.crypt(bin);
|
||||
if (cli.hasArgument("decrypt")) bout = crypt.decrypt(bin);
|
||||
} else piCout << "error: while open input file";
|
||||
} else piCout << "error: invalid secret";
|
||||
}
|
||||
|
||||
if (!bout.isEmpty()) {
|
||||
if (cli.hasArgument("text")) bout.convertToBase64();
|
||||
else if (cli.hasArgument("hex") && cli.argumentValue("hex").isEmpty()) bout = bout.toHex().toByteArray();
|
||||
if (outf.isOpened()) {
|
||||
outf.write(bout);
|
||||
outf.close();
|
||||
}
|
||||
else fwrite(bout.data(), 1, bout.size(), stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Crypth / decrypth files utility
|
||||
Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "picrypt.h"
|
||||
#include "pip.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << Bold << "PIP Crypt Utility";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default
|
||||
<< "\"picrypt [-thr] [-g <pass>] [-o <out_file>] [{[-c <file>] [-d <file>]} {[-p <pass>] [-s <hash>] [-k <key_file>] [-x "
|
||||
"<hex_key>]}]\""
|
||||
<< NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << "-h --help " << Green << "- display this message and exit";
|
||||
piCout << "-g --genhash " << Green << "- generate hash from <pass> string";
|
||||
piCout << "-t --text " << Green << "- output in text base64";
|
||||
piCout << "-o --out <out_file> " << Green << "- write out to file <out_file>";
|
||||
piCout << "-c --crypt <file> " << Green << "- crypt file <file> using secret <pass> or <hash> or <key_file>";
|
||||
piCout << "-d --decrypt <file> " << Green << "- decrypt file <file> using secret <pass> or <hash> or <key_file>";
|
||||
piCout << "-p --pass <pass> " << Green << "- use secret from passphrase <pass>";
|
||||
piCout << "-s --secret <hash> " << Green << "- use secret from hash <hash>";
|
||||
piCout << "-k --key <key_file> " << Green << "- use secret from binary key_file <key_file>";
|
||||
piCout << "-x --hex [<hex_key>] " << Green << "- use secret from hex hash <hex_key> or output in text hex";
|
||||
piCout << "-r --random " << Green << "- generate random secret key";
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
PICrypt::hash("");
|
||||
PICrypt crypt;
|
||||
PIByteArray bout;
|
||||
PICLI cli(argc, argv);
|
||||
cli.addArgument("genhash", true);
|
||||
cli.addArgument("out", true);
|
||||
cli.addArgument("crypt", true);
|
||||
cli.addArgument("decrypt", true);
|
||||
cli.addArgument("pass", true);
|
||||
cli.addArgument("secret", true);
|
||||
cli.addArgument("key", true);
|
||||
cli.addArgument("hex", 'x', "hex", true);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("text");
|
||||
cli.addArgument("random");
|
||||
|
||||
if (!(cli.hasArgument("genhash") || cli.hasArgument("crypt") || cli.hasArgument("decrypt") || cli.hasArgument("random")) ||
|
||||
cli.hasArgument("help")) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIString out_file = cli.argumentValue("out");
|
||||
PIFile outf;
|
||||
if (!out_file.isEmpty()) {
|
||||
if (outf.open(out_file, PIIODevice::ReadWrite)) {
|
||||
outf.resize(0);
|
||||
} else
|
||||
piCout << "error: while open out file";
|
||||
}
|
||||
|
||||
if (cli.hasArgument("genhash")) {
|
||||
PIString s = cli.argumentValue("genhash");
|
||||
bout = crypt.hash(s);
|
||||
} else if (cli.hasArgument("random"))
|
||||
bout = crypt.generateKey();
|
||||
|
||||
if (cli.hasArgument("crypt") || cli.hasArgument("decrypt")) {
|
||||
PIByteArray secret;
|
||||
if (cli.hasArgument("key")) {
|
||||
PIFile keyf(cli.argumentValue("key"), PIIODevice::ReadOnly);
|
||||
if (keyf.open())
|
||||
secret = keyf.readAll();
|
||||
else
|
||||
piCout << "error: while open key file";
|
||||
}
|
||||
if (cli.hasArgument("pass")) secret = crypt.hash(cli.argumentValue("pass"));
|
||||
if (cli.hasArgument("secret")) secret = PIByteArray::fromBase64(cli.argumentValue("secret").toByteArray());
|
||||
if (cli.hasArgument("hex")) secret = PIByteArray::fromHex(cli.argumentValue("hex").toByteArray());
|
||||
if (secret.size() == crypt.sizeKey()) {
|
||||
PIFile inf;
|
||||
PIString in_file;
|
||||
PIByteArray bin;
|
||||
crypt.setKey(secret);
|
||||
if (cli.hasArgument("crypt")) in_file = cli.argumentValue("crypt");
|
||||
if (cli.hasArgument("decrypt")) in_file = cli.argumentValue("decrypt");
|
||||
if (inf.open(in_file, PIIODevice::ReadOnly)) {
|
||||
bin = inf.readAll();
|
||||
if (cli.hasArgument("crypt")) bout = crypt.crypt(bin);
|
||||
if (cli.hasArgument("decrypt")) bout = crypt.decrypt(bin);
|
||||
} else
|
||||
piCout << "error: while open input file";
|
||||
} else
|
||||
piCout << "error: invalid secret";
|
||||
}
|
||||
|
||||
if (!bout.isEmpty()) {
|
||||
if (cli.hasArgument("text"))
|
||||
bout.convertToBase64();
|
||||
else if (cli.hasArgument("hex") && cli.argumentValue("hex").isEmpty())
|
||||
bout = bout.toHex().toByteArray();
|
||||
if (outf.isOpened()) {
|
||||
outf.write(bout);
|
||||
outf.close();
|
||||
} else
|
||||
fwrite(bout.data(), 1, bout.size(), stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Deploy tool
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Deploy tool
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "picli.h"
|
||||
#include "pidir.h"
|
||||
#include "piprocess.h"
|
||||
#include "piiostream.h"
|
||||
#include "piprocess.h"
|
||||
|
||||
#define DELIM "::"
|
||||
|
||||
@@ -31,15 +31,15 @@ PIString qplatforms;
|
||||
|
||||
void setCommands() {
|
||||
#ifdef WINDOWS
|
||||
cmd_copy = "copy /y ";
|
||||
cmd_copy = "copy /y ";
|
||||
cmd_copydir = "copy /y ";
|
||||
cmd_suffix = " 1> NUL";
|
||||
qplatforms = "windows";
|
||||
cmd_suffix = " 1> NUL";
|
||||
qplatforms = "windows";
|
||||
#else
|
||||
cmd_copy = "cp -f ";
|
||||
cmd_copy = "cp -f ";
|
||||
cmd_copydir = "cp -rf ";
|
||||
# ifdef MAC_OS
|
||||
qplatforms = "cocoa";
|
||||
qplatforms = "cocoa";
|
||||
# else
|
||||
qplatforms = "xcb";
|
||||
# endif
|
||||
@@ -64,11 +64,13 @@ void usage() {
|
||||
piCout << "Default regexp set by \"*=<regexp>\".";
|
||||
piCout << "\"*=\" disable optional plugins.";
|
||||
piCout << "";
|
||||
piCout << Green << Bold << "Usage:" << Default << "\"deploy_tool [-hvfC] [--dependencies [--prefix <text>]] "
|
||||
"[--qt-plugins-dir <d>] [-s <search_path>] [--ignore <libs>] [-S <styles>] "
|
||||
"[-l <ldd>] [-D <dpkg>] [--dpkg-workdir <d>] [-L <readelf> | -W <objdump> | -M <otool>] "
|
||||
"[--name-tool <pathS>] [--rpath] [-d <depth>] [-q <qtdir>] [-a <add_libs>] [-S <styles>] "
|
||||
"[-P <platforms>] [--qt-plugins <d>] [--qt-modules <l>] [--qt-conf-dir <d>] -o <out_path> <file> [<file2> ...]\"" << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default
|
||||
<< "\"deploy_tool [-hvfC] [--dependencies [--prefix <text>]] "
|
||||
"[--qt-plugins-dir <d>] [-s <search_path>] [--ignore <libs>] [-S <styles>] "
|
||||
"[-l <ldd>] [-D <dpkg>] [--dpkg-workdir <d>] [-L <readelf> | -W <objdump> | -M <otool>] "
|
||||
"[--name-tool <pathS>] [--rpath] [-d <depth>] [-q <qtdir>] [-a <add_libs>] [-S <styles>] "
|
||||
"[-P <platforms>] [--qt-plugins <d>] [--qt-modules <l>] [--qt-conf-dir <d>] -o <out_path> <file> [<file2> ...]\""
|
||||
<< NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << Bold << "Debug control";
|
||||
piCout << "-h, --help " << Green << "- display this message and exit";
|
||||
@@ -76,7 +78,8 @@ void usage() {
|
||||
piCout << "";
|
||||
piCout << Bold << "Processing control";
|
||||
piCout << "-f, --fake " << Green << "- don`t copy, only print";
|
||||
piCout << "-s <search_path> " << Green << "- set search pathes for system libraries, may be separated by \"" DELIM "\", default \"/usr/lib\"";
|
||||
piCout << "-s <search_path> " << Green
|
||||
<< "- set search pathes for system libraries, may be separated by \"" DELIM "\", default \"/usr/lib\"";
|
||||
piCout << "--ignore <libs> " << Green << "- ignore libraries names, may be separated by \"" DELIM "\", default \"\"";
|
||||
piCout << "-l <ldd> " << Green << "- \"ldd\" path, default \"/usr/bin/ldd\"";
|
||||
piCout << "-L <readelf> " << Green << "- \"readelf\" path, overrides \"ldd\"";
|
||||
@@ -105,7 +108,8 @@ void usage() {
|
||||
piCout << "";
|
||||
piCout << Bold << "Input control";
|
||||
piCout << "<file> ... " << Green << "- executable to process";
|
||||
piCout << "-a <add_libs> " << Green << "- additional libs, separated by \"" DELIM "\". Libraries will be searched in <search_path>";
|
||||
piCout << "-a <add_libs> " << Green
|
||||
<< "- additional libs, separated by \"" DELIM "\". Libraries will be searched in <search_path>";
|
||||
}
|
||||
|
||||
struct QtDep {
|
||||
@@ -113,24 +117,27 @@ struct QtDep {
|
||||
PIString lib;
|
||||
PIStringList plugins;
|
||||
};
|
||||
QtDep qt_deps[] = {
|
||||
QtDep("core" , PIStringList() << "platforms"),
|
||||
QtDep("gui" , PIStringList() << "imageformats"),
|
||||
QtDep("widgets" , PIStringList() << "styles"),
|
||||
QtDep("sql" , PIStringList() << "sqldrivers"),
|
||||
QtDep("positioning" , PIStringList() << "position"),
|
||||
QtDep("location" , PIStringList() << "geoservices"),
|
||||
QtDep("multimedia" , PIStringList() << "audio" << "mediaservice" << "playlistformats"),
|
||||
QtDep("printsupport" , PIStringList() << "printsupport"),
|
||||
QtDep("virtualkeyboard", PIStringList() << "platforminputcontexts"),
|
||||
QtDep("sensors" , PIStringList() << "sensors" << "sensorgestures"),
|
||||
QtDep("texttospeech" , PIStringList() << "texttospeech"),
|
||||
QtDep("serialbus" , PIStringList() << "canbus"),
|
||||
QtDep()
|
||||
};
|
||||
QtDep qt_deps[] = {QtDep("core", PIStringList() << "platforms"),
|
||||
QtDep("gui", PIStringList() << "imageformats"),
|
||||
QtDep("widgets", PIStringList() << "styles"),
|
||||
QtDep("sql", PIStringList() << "sqldrivers"),
|
||||
QtDep("positioning", PIStringList() << "position"),
|
||||
QtDep("location", PIStringList() << "geoservices"),
|
||||
QtDep("multimedia",
|
||||
PIStringList() << "audio"
|
||||
<< "mediaservice"
|
||||
<< "playlistformats"),
|
||||
QtDep("printsupport", PIStringList() << "printsupport"),
|
||||
QtDep("virtualkeyboard", PIStringList() << "platforminputcontexts"),
|
||||
QtDep("sensors",
|
||||
PIStringList() << "sensors"
|
||||
<< "sensorgestures"),
|
||||
QtDep("texttospeech", PIStringList() << "texttospeech"),
|
||||
QtDep("serialbus", PIStringList() << "canbus"),
|
||||
QtDep()};
|
||||
|
||||
|
||||
int depth = 8;
|
||||
int depth = 8;
|
||||
bool fake = false, is_ldd = true, is_deps = false, need_qt = false, make_qt_format = true, rpath = false, win_target = false;
|
||||
PIString ldd, readelf, objdump, otool, dpkg, nametool, strip, out_dir, qt_dir, dpkg_workdir;
|
||||
PIString qt_pref, qt_suff, qt_conf_dir, qt_plugins_dir, target_dir;
|
||||
@@ -141,9 +148,8 @@ PIMap<PIString, PIStringList> qt_filters;
|
||||
|
||||
PIString findLib(const PIString & l) {
|
||||
if (PIFile::isExists(l)) return l;
|
||||
piForeachC (PIString & s, lib_dirs) {
|
||||
if (PIFile::isExists(s + l))
|
||||
return s + l;
|
||||
piForeachC(PIString & s, lib_dirs) {
|
||||
if (PIFile::isExists(s + l)) return s + l;
|
||||
if (win_target || l.toLowerCase().endsWith("dll")) {
|
||||
PIFile::FileInfo info(l);
|
||||
PIString fn = info.baseName(), fe = info.extension(), nn;
|
||||
@@ -166,7 +172,6 @@ PIString findLib(const PIString & l) {
|
||||
if (PIFile::isExists(nn)) return nn;
|
||||
nn = s + fn.toUpperCase() + "." + fe.toUpperCase();
|
||||
if (PIFile::isExists(nn)) return nn;
|
||||
|
||||
}
|
||||
}
|
||||
return "";
|
||||
@@ -176,7 +181,7 @@ PIString findLib(const PIString & l) {
|
||||
PIString frameworkName(const PIString & l) {
|
||||
if (!l.contains(".framework/")) return "";
|
||||
PIStringList ll = l.split("/");
|
||||
piForeachRC (PIString & _f, ll) {
|
||||
piForeachRC(PIString & _f, ll) {
|
||||
if (_f.endsWith(".framework")) {
|
||||
return _f;
|
||||
}
|
||||
@@ -218,22 +223,37 @@ PIStringList filter(const PIString & in, const PIString & f) {
|
||||
|
||||
void checkQtLib(PIString lib) {
|
||||
PIString base = lib.toLowerCase(), pref, suff;
|
||||
if (base.startsWith("lib")) {pref += "lib"; base.cutLeft(3);}
|
||||
if (base.startsWith("qt5")) {pref += "Qt5"; base.cutLeft(3);}
|
||||
if (base.startsWith("qt6")) {pref += "Qt6"; base.cutLeft(3);}
|
||||
if (base.startsWith("qt" )) {pref += "Qt" ; base.cutLeft(2);}
|
||||
if (base.find('.') >= 0) {suff = base.right(base.size_s() - base.find('.')); base = base.left(base.find('.'));}
|
||||
for (int i = 0; ; ++i) {
|
||||
if (base.startsWith("lib")) {
|
||||
pref += "lib";
|
||||
base.cutLeft(3);
|
||||
}
|
||||
if (base.startsWith("qt5")) {
|
||||
pref += "Qt5";
|
||||
base.cutLeft(3);
|
||||
}
|
||||
if (base.startsWith("qt6")) {
|
||||
pref += "Qt6";
|
||||
base.cutLeft(3);
|
||||
}
|
||||
if (base.startsWith("qt")) {
|
||||
pref += "Qt";
|
||||
base.cutLeft(2);
|
||||
}
|
||||
if (base.find('.') >= 0) {
|
||||
suff = base.right(base.size_s() - base.find('.'));
|
||||
base = base.left(base.find('.'));
|
||||
}
|
||||
for (int i = 0;; ++i) {
|
||||
if (qt_deps[i].lib.isEmpty()) break;
|
||||
if (qt_deps[i].lib == base) {
|
||||
qt_plugins << qt_deps[i].plugins;
|
||||
//piCout << "add qt plugins" << qt_deps[i].plugins << "now" << qt_plugins;
|
||||
// piCout << "add qt plugins" << qt_deps[i].plugins << "now" << qt_plugins;
|
||||
need_qt = true;
|
||||
qt_libs << lib;
|
||||
if (make_qt_format) {
|
||||
make_qt_format = false;
|
||||
qt_pref = pref;
|
||||
qt_suff = suff;
|
||||
qt_pref = pref;
|
||||
qt_suff = suff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -262,28 +282,30 @@ void procLdd(PIString file, bool ext_lib = false, int cur_depth = 0) {
|
||||
for (PIString & l: lines) {
|
||||
l.cutRight(1);
|
||||
l.cutLeft(l.find('[') + 1);
|
||||
l.trim();//.append('.').prepend('.');
|
||||
l.trim(); //.append('.').prepend('.');
|
||||
}
|
||||
}
|
||||
if (!objdump.isEmpty()) {
|
||||
PIString out = execute(objdump + " -p \"" + file + "\"");
|
||||
lines = filter(out, "DLL Name:");
|
||||
lines = filter(out, "DLL Name:");
|
||||
lines << filter(out, "NEEDED");
|
||||
for (PIString & l: lines) {
|
||||
if (l.startsWith("DLL")) l.cutLeft(9);
|
||||
else l.cutLeft(6);
|
||||
l.trim();//.append('.').prepend('.');
|
||||
if (l.startsWith("DLL"))
|
||||
l.cutLeft(9);
|
||||
else
|
||||
l.cutLeft(6);
|
||||
l.trim(); //.append('.').prepend('.');
|
||||
}
|
||||
}
|
||||
if (!otool.isEmpty()) {
|
||||
lines = filter(execute(otool + " -L \"" + file + "\""), "(");
|
||||
piForeach (PIString & l, lines) {
|
||||
piForeach(PIString & l, lines) {
|
||||
l = l.left(l.find('('));
|
||||
l.trim();//.append('.').prepend('.');
|
||||
l.trim(); //.append('.').prepend('.');
|
||||
}
|
||||
}
|
||||
}
|
||||
piForeachC (PIString & sl, lines) {
|
||||
piForeachC(PIString & sl, lines) {
|
||||
PIString l = sl.trimmed();
|
||||
if (!otool.isEmpty()) {
|
||||
PIString fname = frameworkName(l);
|
||||
@@ -297,26 +319,25 @@ void procLdd(PIString file, bool ext_lib = false, int cur_depth = 0) {
|
||||
if (is_ldd) {
|
||||
if (!l.contains("=>")) continue;
|
||||
l.cutLeft(l.find("=>") + 2);
|
||||
if (l.contains("("))
|
||||
l.cutRight(l.length() - l.find("("));
|
||||
if (l.contains("(")) l.cutRight(l.length() - l.find("("));
|
||||
l.trim();
|
||||
if (l.toLowerCase() == "not found") {
|
||||
miss_libs << sl.left(sl.find("=>")).trim();
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
//l.cutLeft(1).cutRight(1).trim();
|
||||
// l.cutLeft(1).cutRight(1).trim();
|
||||
if (l.isEmpty()) continue;
|
||||
if (!otool.isEmpty()) {
|
||||
if (!l.startsWith("/usr/local/")) {
|
||||
PIFile::FileInfo fi;
|
||||
fi.path = l;
|
||||
l = fi.name();
|
||||
l = fi.name();
|
||||
}
|
||||
}
|
||||
PIString flp = findLib(l);
|
||||
if (flp.isEmpty()) {
|
||||
//piCout << "Can`t find" << l;
|
||||
// piCout << "Can`t find" << l;
|
||||
miss_libs << l;
|
||||
continue;
|
||||
}
|
||||
@@ -324,10 +345,10 @@ void procLdd(PIString file, bool ext_lib = false, int cur_depth = 0) {
|
||||
}
|
||||
if (all_libs[l]) continue;
|
||||
PIFile::FileInfo fi;
|
||||
fi.path = l;
|
||||
fi.path = l;
|
||||
PIString lname = fi.baseName();
|
||||
if (lname.startsWith("lib")) lname.cutLeft(3);
|
||||
//piCout << "check ignore" << lname << ignore_libs;
|
||||
// piCout << "check ignore" << lname << ignore_libs;
|
||||
if (ignore_libs.contains(lname)) {
|
||||
continue;
|
||||
}
|
||||
@@ -336,9 +357,8 @@ void procLdd(PIString file, bool ext_lib = false, int cur_depth = 0) {
|
||||
all_libs << l;
|
||||
}
|
||||
PIVector<PIString> clibs = cur_libs.toVector();
|
||||
if (!clibs.isEmpty())
|
||||
piCout << " new dependencies:\n -" << PIStringList(clibs).join("\n - ");
|
||||
piForeachC (PIString & l, clibs) {
|
||||
if (!clibs.isEmpty()) piCout << " new dependencies:\n -" << PIStringList(clibs).join("\n - ");
|
||||
piForeachC(PIString & l, clibs) {
|
||||
procLdd(l, false, cur_depth);
|
||||
}
|
||||
}
|
||||
@@ -348,7 +368,8 @@ void copyWildcard(const PIString & from, const PIString & to) {
|
||||
if (fake) return;
|
||||
PIDir(to).make();
|
||||
#ifdef WINDOWS
|
||||
PIFile::FileInfo fi; fi.path = from;
|
||||
PIFile::FileInfo fi;
|
||||
fi.path = from;
|
||||
system(("robocopy \"" + fi.dir() + "\" \"" + to + "\" \"" + fi.name() + "\" /NJH /NJS /NP /NDL /NS /NC /NFL 1> NUL").data());
|
||||
#else
|
||||
system((cmd_copy + from + " \"" + to + "/\"" + cmd_suffix).data());
|
||||
@@ -357,7 +378,7 @@ void copyWildcard(const PIString & from, const PIString & to) {
|
||||
|
||||
|
||||
void procQt() {
|
||||
//piCout << "qmake ...";
|
||||
// piCout << "qmake ...";
|
||||
PIString vs;
|
||||
if (qt_dir.isEmpty()) {
|
||||
vs = execute("qmake -v");
|
||||
@@ -367,11 +388,10 @@ void procQt() {
|
||||
}
|
||||
} else
|
||||
vs = "QMake version ?.?\nUsing Qt version ?.?.? in " + qt_dir;
|
||||
PIStringList vsl = vs.split("\n");
|
||||
PIStringList vsl = vs.split("\n");
|
||||
PIStringList pdirs = qt_plugins.toVector();
|
||||
if (!fake)
|
||||
PIDir(qt_plugins_dir).make(true);
|
||||
piForeach (PIString l, vsl) {
|
||||
if (!fake) PIDir(qt_plugins_dir).make(true);
|
||||
piForeach(PIString l, vsl) {
|
||||
if (l.trim().contains("Qt version")) {
|
||||
l.cutLeft(l.find("Qt version") + 10).trim();
|
||||
PIString qv = l.takeWord();
|
||||
@@ -380,7 +400,7 @@ void procQt() {
|
||||
piCout << "Qt" << qv << "in" << qloc;
|
||||
PIString qdir;
|
||||
PIStringList suffixes({".", "..", "qt5", "../qt5", "qt6", "../qt6"});
|
||||
piForeachC (PIString s, suffixes) {
|
||||
piForeachC(PIString s, suffixes) {
|
||||
PIString qd = qloc + "/" + s + "/plugins/";
|
||||
if (piDebug) PICout(AddSpaces) << "Qt plugins root try" << qd << "...";
|
||||
if (PIDir::isExists(qd + "platforms")) {
|
||||
@@ -390,15 +410,14 @@ void procQt() {
|
||||
}
|
||||
piCout << " no";
|
||||
}
|
||||
if (qdir.isEmpty())
|
||||
break;
|
||||
piForeachC (PIString & plugin, pdirs) {
|
||||
if (qdir.isEmpty()) break;
|
||||
piForeachC(PIString & plugin, pdirs) {
|
||||
PIStringList filters = qt_filters[plugin];
|
||||
piForeachC (PIString & f, filters) {
|
||||
piForeachC(PIString & f, filters) {
|
||||
if (f.isEmpty()) continue;
|
||||
copyWildcard(qdir + plugin + "/" + f, qt_plugins_dir + plugin);
|
||||
PIVector<PIFile::FileInfo> copied = PIDir(qt_plugins_dir + plugin).entries();
|
||||
piForeachC (PIFile::FileInfo & fi, copied) {
|
||||
piForeachC(PIFile::FileInfo & fi, copied) {
|
||||
if (fi.isFile()) {
|
||||
procLdd(fi.path);
|
||||
plugin_libs << fi.path;
|
||||
@@ -414,20 +433,18 @@ void procQt() {
|
||||
|
||||
bool procDpkg(const PIString & l) {
|
||||
PIString dpkgdir;
|
||||
if (!dpkg_workdir.isEmpty())
|
||||
dpkgdir = " --admindir=" + dpkg_workdir;
|
||||
if (!dpkg_workdir.isEmpty()) dpkgdir = " --admindir=" + dpkg_workdir;
|
||||
PIFile::FileInfo fi;
|
||||
fi.path = l;
|
||||
fi.path = l;
|
||||
PIString cmd = dpkg + dpkgdir + " -S " + fi.name() + " 2> /dev/null";
|
||||
//PICout(true) << cmd;
|
||||
PIString vs = execute(cmd);
|
||||
// PICout(true) << cmd;
|
||||
PIString vs = execute(cmd);
|
||||
if (!vs.isEmpty()) {
|
||||
vs = vs.left(vs.find(":"));
|
||||
if (!vs.isEmpty())
|
||||
all_deps << vs;
|
||||
if (!vs.isEmpty()) all_deps << vs;
|
||||
return true;
|
||||
}
|
||||
//piCout << "No dep on" << l;
|
||||
// piCout << "No dep on" << l;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -437,31 +454,31 @@ void patchNameTool() {
|
||||
PIStringList clibs = all_libs.toVector(), flibs = framework_libs.toVector(), patch_list;
|
||||
PIStringList dlibs;
|
||||
PIString libname, cmd;
|
||||
//PICout(DefaultControls) << "start patch" << clibs;
|
||||
// PICout(DefaultControls) << "start patch" << clibs;
|
||||
PIFile::FileInfo fi;
|
||||
patch_list = input_files;
|
||||
patch_list << plugin_libs;
|
||||
piForeach (PIString l, clibs) {
|
||||
piForeach(PIString l, clibs) {
|
||||
fi.path = l;
|
||||
patch_list << (out_dir + fi.name());
|
||||
}
|
||||
piForeach (PIString local_lib, patch_list) {
|
||||
piForeach(PIString local_lib, patch_list) {
|
||||
execute("chmod +w \"" + local_lib + "\"");
|
||||
fi.path = local_lib;
|
||||
cmd = nametool + " -id \"@executable_path/../Frameworks/" + fi.name() + "\"";
|
||||
cmd = nametool + " -id \"@executable_path/../Frameworks/" + fi.name() + "\"";
|
||||
cmd += " \"" + local_lib + "\" 2> /dev/null";
|
||||
//piCout << " " << cmd;
|
||||
// piCout << " " << cmd;
|
||||
execute(cmd);
|
||||
}
|
||||
piForeach (PIString f, flibs) {
|
||||
piForeach(PIString f, flibs) {
|
||||
PIString fl = findLib(frameworkName(f));
|
||||
if (fl.isEmpty()) continue;
|
||||
patch_list << (out_dir + frameworkName(f) + "/" + frameworkInternalPath(f));
|
||||
//PICout(DefaultControls) << "map" << f << "->" << (out_dir + frameworkName(f) + "/" + frameworkInternalPath(f));
|
||||
// PICout(DefaultControls) << "map" << f << "->" << (out_dir + frameworkName(f) + "/" + frameworkInternalPath(f));
|
||||
}
|
||||
piForeach (PIString local_lib, patch_list) {
|
||||
piForeach(PIString local_lib, patch_list) {
|
||||
dlibs = filter(execute(otool + " -L \"" + local_lib + "\""), "(");
|
||||
piForeach (PIString & l, dlibs) {
|
||||
piForeach(PIString & l, dlibs) {
|
||||
l = l.left(l.find('('));
|
||||
l.trim();
|
||||
}
|
||||
@@ -469,12 +486,12 @@ void patchNameTool() {
|
||||
execute("chmod +w \"" + local_lib + "\"");
|
||||
}
|
||||
piCout << "patch" << local_lib;
|
||||
piForeach (PIString sys_lib, dlibs) {
|
||||
piForeach(PIString sys_lib, dlibs) {
|
||||
sys_lib.cutRight(1).trim();
|
||||
fi.path = sys_lib;
|
||||
libname = fi.name();
|
||||
fi.path = sys_lib;
|
||||
libname = fi.name();
|
||||
PIString fl = findLib(libname), fname = frameworkName(sys_lib);
|
||||
//piCout << " check" << sys_lib << fl;
|
||||
// piCout << " check" << sys_lib << fl;
|
||||
PIString new_path;
|
||||
if (all_libs.contains(fl) || all_libs.contains(sys_lib)) {
|
||||
new_path = "@executable_path/../Frameworks/" + libname;
|
||||
@@ -491,12 +508,12 @@ void patchNameTool() {
|
||||
cmd = nametool + " -change \"" + sys_lib + "\"";
|
||||
cmd += " \"" + new_path + "\"";
|
||||
cmd += " \"" + local_lib + "\" 2> /dev/null";
|
||||
//piCout << " *" << cmd;
|
||||
// piCout << " *" << cmd;
|
||||
execute(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
piForeach (PIString bin, input_files) {
|
||||
piForeach(PIString bin, input_files) {
|
||||
cmd = nametool + " -add_rpath \"@executable_path/../Frameworks\"";
|
||||
cmd += " \"" + bin + "\" 2> /dev/null";
|
||||
execute(cmd);
|
||||
@@ -507,10 +524,9 @@ void patchNameTool() {
|
||||
void patchRPathFile(const PIFile::FileInfo & file) {
|
||||
PIString fo = execute("file \"" + file.path + "\"");
|
||||
if (!fo.contains("ELF")) return;
|
||||
PIString rp = "\\$ORIGIN:\\$ORIGIN/lib";
|
||||
PIString rp = "\\$ORIGIN:\\$ORIGIN/lib";
|
||||
PIString arp = PIDir(file.dir()).relative(out_dir);
|
||||
if (!arp.isEmpty() && arp != "." && arp != "lib")
|
||||
rp.append(":\\$ORIGIN/" + arp);
|
||||
if (!arp.isEmpty() && arp != "." && arp != "lib") rp.append(":\\$ORIGIN/" + arp);
|
||||
PIString cmd = "patchelf --set-rpath \"" + rp + "\" \"" + file.path + "\" 2> /dev/null";
|
||||
piCout << "set rpath" << file.path << "to" << rp;
|
||||
execute(cmd);
|
||||
@@ -520,9 +536,9 @@ void patchRPathFile(const PIFile::FileInfo & file) {
|
||||
void patchRPath() {
|
||||
PIStringList dirs({out_dir, target_dir, qt_plugins_dir});
|
||||
dirs.removeDuplicates().removeStrings(PIString());
|
||||
piForeachC (PIString & d, dirs) {
|
||||
piForeachC(PIString & d, dirs) {
|
||||
PIVector<PIFile::FileInfo> files = PIDir(d).allEntries();
|
||||
piForeachC (PIFile::FileInfo & f, files) {
|
||||
piForeachC(PIFile::FileInfo & f, files) {
|
||||
if (f.isDir()) continue;
|
||||
patchRPathFile(f.path);
|
||||
}
|
||||
@@ -532,7 +548,7 @@ void patchRPath() {
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
PICLI cli(argc, argv);
|
||||
//piCout << cli.rawArguments();
|
||||
// piCout << cli.rawArguments();
|
||||
cli.setOptionalArgumentsCount(-1);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("verbose");
|
||||
@@ -567,26 +583,24 @@ int main(int argc, char * argv[]) {
|
||||
}
|
||||
setCommands();
|
||||
|
||||
fake = cli.hasArgument("fake");
|
||||
piDebug = cli.hasArgument("verbose");
|
||||
is_deps = cli.hasArgument("dependencies");
|
||||
out_dir = cli.argumentValue("output");
|
||||
lib_dirs = cli.argumentValue("search_path").split(DELIM);
|
||||
add_libs = cli.argumentValue("add_libs").split(DELIM);
|
||||
fake = cli.hasArgument("fake");
|
||||
piDebug = cli.hasArgument("verbose");
|
||||
is_deps = cli.hasArgument("dependencies");
|
||||
out_dir = cli.argumentValue("output");
|
||||
lib_dirs = cli.argumentValue("search_path").split(DELIM);
|
||||
add_libs = cli.argumentValue("add_libs").split(DELIM);
|
||||
ignore_libs = cli.argumentValue("ignore").split(DELIM);
|
||||
qt_dir = cli.argumentValue("qtdir");
|
||||
ldd = cli.argumentValue("ldd");
|
||||
readelf = cli.argumentValue("Lreadelf");
|
||||
objdump = cli.argumentValue("Wobjdump");
|
||||
otool = cli.argumentValue("Motool");
|
||||
nametool = cli.argumentValue("name-tool");
|
||||
strip = cli.argumentValue("strip");
|
||||
rpath = cli.hasArgument("rpath");
|
||||
if (nametool.isEmpty())
|
||||
nametool = "install_name_tool";
|
||||
if (strip.isEmpty())
|
||||
strip = "strip";
|
||||
dpkg = cli.argumentValue("Dpkg");
|
||||
qt_dir = cli.argumentValue("qtdir");
|
||||
ldd = cli.argumentValue("ldd");
|
||||
readelf = cli.argumentValue("Lreadelf");
|
||||
objdump = cli.argumentValue("Wobjdump");
|
||||
otool = cli.argumentValue("Motool");
|
||||
nametool = cli.argumentValue("name-tool");
|
||||
strip = cli.argumentValue("strip");
|
||||
rpath = cli.hasArgument("rpath");
|
||||
if (nametool.isEmpty()) nametool = "install_name_tool";
|
||||
if (strip.isEmpty()) strip = "strip";
|
||||
dpkg = cli.argumentValue("Dpkg");
|
||||
dpkg_workdir = cli.argumentValue("dpkg-workdir");
|
||||
#ifdef WINDOWS
|
||||
readelf.replaceAll("/", "\\");
|
||||
@@ -595,8 +609,7 @@ int main(int argc, char * argv[]) {
|
||||
nametool.replaceAll("/", "\\");
|
||||
dpkg.replaceAll("/", "\\");
|
||||
#endif
|
||||
if (dpkg.isEmpty())
|
||||
dpkg = "/usr/bin/dpkg";
|
||||
if (dpkg.isEmpty()) dpkg = "/usr/bin/dpkg";
|
||||
int etcnt = 0;
|
||||
if (!readelf.isEmpty()) ++etcnt;
|
||||
if (!objdump.isEmpty()) ++etcnt;
|
||||
@@ -611,7 +624,7 @@ int main(int argc, char * argv[]) {
|
||||
if (!qroot.endsWith("/")) qroot.append("/");
|
||||
lib_dirs << (qroot + "bin") << (qroot + "lib") << (qroot + "Frameworks");
|
||||
}
|
||||
piForeach (PIString & s, lib_dirs) {
|
||||
piForeach(PIString & s, lib_dirs) {
|
||||
s.trim();
|
||||
if (!s.endsWith("/")) s += "/";
|
||||
}
|
||||
@@ -621,26 +634,25 @@ int main(int argc, char * argv[]) {
|
||||
|
||||
out_dir.replaceAll("//", "/");
|
||||
|
||||
for (int i = 0; ; ++i) {
|
||||
for (int i = 0;; ++i) {
|
||||
if (qt_deps[i].lib.isEmpty()) break;
|
||||
qt_deps[i].plugins.forEach([](const PIString & p){qt_filters[p] = PIStringList("*");});
|
||||
qt_deps[i].plugins.forEach([](const PIString & p) { qt_filters[p] = PIStringList("*"); });
|
||||
}
|
||||
if (!cli.argumentValue("Platforms").isEmpty())
|
||||
qplatforms = cli.argumentValue("Platforms");
|
||||
if (!cli.argumentValue("Platforms").isEmpty()) qplatforms = cli.argumentValue("Platforms");
|
||||
if (platforms.contains("windows")) win_target = true;
|
||||
platforms = qplatforms.split(",");
|
||||
styles = cli.argumentValue("Styles").split(",");
|
||||
styles = cli.argumentValue("Styles").split(",");
|
||||
if (styles.isEmpty()) styles << "";
|
||||
PIStringList qpd = cli.argumentValue("qt-plugins").toLowerCase().split(DELIM);
|
||||
piForeachC (PIString & qp, qpd) {
|
||||
piForeachC(PIString & qp, qpd) {
|
||||
int _i = qp.find('=');
|
||||
if (_i < 0) continue;
|
||||
PIString pname = qp.left(_i).trim();
|
||||
PIString pname = qp.left(_i).trim();
|
||||
PIStringList pfilt = qp.mid(_i + 1).trim().split(",");
|
||||
if (pname == "*") {
|
||||
for (int i = 0; ; ++i) {
|
||||
for (int i = 0;; ++i) {
|
||||
if (qt_deps[i].lib.isEmpty()) break;
|
||||
qt_deps[i].plugins.forEach([&pfilt](const PIString & p){qt_filters[p] = pfilt;});
|
||||
qt_deps[i].plugins.forEach([&pfilt](const PIString & p) { qt_filters[p] = pfilt; });
|
||||
}
|
||||
} else {
|
||||
qt_plugins << pname;
|
||||
@@ -648,10 +660,10 @@ int main(int argc, char * argv[]) {
|
||||
}
|
||||
}
|
||||
qt_filters["platforms"] = platforms;
|
||||
qt_filters["styles" ] = styles ;
|
||||
qt_filters["styles"] = styles;
|
||||
|
||||
qt_add_libs = cli.argumentValue("qt-modules").split(DELIM);
|
||||
qt_conf_dir = cli.argumentValue("qt-conf-dir").trim();
|
||||
qt_add_libs = cli.argumentValue("qt-modules").split(DELIM);
|
||||
qt_conf_dir = cli.argumentValue("qt-conf-dir").trim();
|
||||
if (qt_conf_dir.isEmpty()) qt_conf_dir = out_dir;
|
||||
if (!qt_conf_dir.endsWith("/")) qt_conf_dir += "/";
|
||||
qt_plugins_dir = cli.argumentValue("qt-plugins-dir").trim();
|
||||
@@ -663,58 +675,51 @@ int main(int argc, char * argv[]) {
|
||||
|
||||
auto it = qt_filters.makeIterator();
|
||||
while (it.next())
|
||||
it.value().forEach([](PIString & i){
|
||||
it.value().forEach([](PIString & i) {
|
||||
if (!i.startsWith("*")) i.prepend("*");
|
||||
if (!i.endsWith("*")) i.append("*");
|
||||
});
|
||||
//PICout(PICoutManipulators::DefaultControls) << qt_filters;
|
||||
// PICout(PICoutManipulators::DefaultControls) << qt_filters;
|
||||
|
||||
if (!fake)
|
||||
PIDir(out_dir).make();
|
||||
if (!cli.argumentValue("depth").isEmpty())
|
||||
depth = cli.argumentValue("depth").toInt();
|
||||
if (!fake) PIDir(out_dir).make();
|
||||
if (!cli.argumentValue("depth").isEmpty()) depth = cli.argumentValue("depth").toInt();
|
||||
|
||||
cli.optionalArguments().forEach([](const PIString & a){
|
||||
cli.optionalArguments().forEach([](const PIString & a) {
|
||||
if (PIDir::isExists(a)) {
|
||||
if (target_dir.isEmpty())
|
||||
target_dir = a;
|
||||
PIDir(a).allEntries().forEach([](const PIFile::FileInfo & fi){
|
||||
if (fi.isFile())
|
||||
input_files << fi.path;
|
||||
if (target_dir.isEmpty()) target_dir = a;
|
||||
PIDir(a).allEntries().forEach([](const PIFile::FileInfo & fi) {
|
||||
if (fi.isFile()) input_files << fi.path;
|
||||
});
|
||||
} else {
|
||||
if (target_dir.isEmpty())
|
||||
target_dir = PIFile::FileInfo(a).dir();
|
||||
if (PIFile::isExists(a))
|
||||
input_files << a;
|
||||
if (target_dir.isEmpty()) target_dir = PIFile::FileInfo(a).dir();
|
||||
if (PIFile::isExists(a)) input_files << a;
|
||||
}
|
||||
});
|
||||
|
||||
//piCout << files;
|
||||
// piCout << files;
|
||||
if (depth > 0) {
|
||||
input_files.forEach([](const PIString & f){procLdd(f);});
|
||||
qt_add_libs.forEach([](const PIString & f){
|
||||
input_files.forEach([](const PIString & f) { procLdd(f); });
|
||||
qt_add_libs.forEach([](const PIString & f) {
|
||||
PIString l = findLib(qt_pref + f + qt_suff);
|
||||
if (l.isEmpty()) return;
|
||||
procLdd(l, true);
|
||||
checkQtLib(f);
|
||||
});
|
||||
}
|
||||
piForeach (PIString & s, add_libs) {
|
||||
piForeach(PIString & s, add_libs) {
|
||||
if (s.isEmpty()) continue;
|
||||
PIString alib = findLib(s);
|
||||
if (alib.isEmpty()) continue;
|
||||
piCout << s << "->" << alib;
|
||||
procLdd(alib, true);
|
||||
if (!all_libs[alib])
|
||||
all_libs << alib;
|
||||
if (!all_libs[alib]) all_libs << alib;
|
||||
}
|
||||
if (need_qt) {
|
||||
bool need_qt_plugins = true;
|
||||
if (is_deps) { // if Qt in system, then no plugins copy
|
||||
PIVector<PIString> qlibs = qt_libs.toVector();
|
||||
piCout << "check for installed Qt" << qlibs;
|
||||
piForeach (PIString l, qlibs) {
|
||||
piForeach(PIString l, qlibs) {
|
||||
l = findLib(l);
|
||||
if (l.isEmpty()) continue;
|
||||
if (procDpkg(l)) {
|
||||
@@ -735,7 +740,7 @@ int main(int argc, char * argv[]) {
|
||||
pp = "PlugIns";
|
||||
lp = "Resources/lang";
|
||||
}
|
||||
//piCout << pp;
|
||||
// piCout << pp;
|
||||
PIIOTextStream ts(&qtc);
|
||||
ts << "[Paths]\n\tPlugins = " << pp << "\n\tTranslations = " << lp << "\n";
|
||||
}
|
||||
@@ -746,15 +751,14 @@ int main(int argc, char * argv[]) {
|
||||
out_dir.replaceAll("/", "\\");
|
||||
#endif
|
||||
PIVector<PIString> clibs = all_libs.toVector();
|
||||
piForeach (PIString l, clibs) {
|
||||
piForeach(PIString l, clibs) {
|
||||
PIFile::FileInfo fi;
|
||||
fi.path = l;
|
||||
#ifdef WINDOWS
|
||||
l.replaceAll("/", "\\");
|
||||
#endif
|
||||
bool need_cp = true;
|
||||
if (is_deps)
|
||||
need_cp = !procDpkg(l);
|
||||
if (is_deps) need_cp = !procDpkg(l);
|
||||
if (need_cp) {
|
||||
piCout << "copy" << l;
|
||||
if (!fake) {
|
||||
@@ -767,31 +771,26 @@ int main(int argc, char * argv[]) {
|
||||
}
|
||||
}
|
||||
PIVector<PIString> fwdirs = frameworks.toVector();
|
||||
piForeachC (PIString & f, fwdirs) {
|
||||
piForeachC(PIString & f, fwdirs) {
|
||||
PIString fd = findLib(f);
|
||||
if (!fd.isEmpty()) {
|
||||
piCout << "copy framework" << f;
|
||||
if (!fake)
|
||||
system((cmd_copydir + "\"" + fd + "\" \"" + out_dir + "\"" + cmd_suffix).data());
|
||||
if (!fake) system((cmd_copydir + "\"" + fd + "\" \"" + out_dir + "\"" + cmd_suffix).data());
|
||||
} else
|
||||
miss_frameworks << f;
|
||||
}
|
||||
|
||||
if (!otool.isEmpty())
|
||||
patchNameTool();
|
||||
if (!otool.isEmpty()) patchNameTool();
|
||||
|
||||
if (rpath)
|
||||
patchRPath();
|
||||
if (rpath) patchRPath();
|
||||
|
||||
if (is_deps) {
|
||||
PICout(PICoutManipulators::AddNone) << cli.argumentValue("prefix");
|
||||
PICout(PICoutManipulators::AddNewLine) << PIStringList(all_deps.toVector()).join(", ");
|
||||
} else {
|
||||
piCout << "copied" << clibs.size_s() << "files";
|
||||
if (!miss_libs.isEmpty())
|
||||
piCout << "Missing libraries:\n -" << PIStringList(miss_libs.toVector()).join("\n - ");
|
||||
if (!miss_frameworks.isEmpty())
|
||||
piCout << "Missing frameworks:\n -" << PIStringList(miss_frameworks.toVector()).join("\n - ");
|
||||
if (!miss_libs.isEmpty()) piCout << "Missing libraries:\n -" << PIStringList(miss_libs.toVector()).join("\n - ");
|
||||
if (!miss_frameworks.isEmpty()) piCout << "Missing frameworks:\n -" << PIStringList(miss_frameworks.toVector()).join("\n - ");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,39 +1,40 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Terminal client for windows, used by PITerminal and pisd
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
PIP - Platform Independent Primitives
|
||||
Terminal client for windows, used by PITerminal and pisd
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "piincludes_p.h"
|
||||
#ifndef WINDOWS
|
||||
int main (int argc, char * argv[]) {
|
||||
int main(int argc, char * argv[]) {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
# define PIP_CONSOLE_STATIC_DEFINE
|
||||
# include "../../libs/console/piterminal.cpp"
|
||||
# include "pifile.h"
|
||||
# include "pip_console_export.h"
|
||||
# include "piscreentypes.h"
|
||||
# include "pisharedmemory.h"
|
||||
# include "pifile.h"
|
||||
# include <wingdi.h>
|
||||
|
||||
# include <wincon.h>
|
||||
# include "../../libs/console/piterminal.cpp"
|
||||
# include <wingdi.h>
|
||||
|
||||
|
||||
PIVector<PIVector<PIScreenTypes::Cell> > cells;
|
||||
PIVector<PIVector<PIScreenTypes::Cell>> cells;
|
||||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||||
CHAR_INFO * chars = 0;
|
||||
HANDLE console = 0, cstdin = 0, pipe = 0, cmd_proc = 0;
|
||||
@@ -44,23 +45,31 @@ int con_w = -1, con_h = -1;
|
||||
|
||||
PIScreenTypes::Cell CharInfo2Cell(const CHAR_INFO & c) {
|
||||
PIScreenTypes::Cell ret;
|
||||
ret.symbol = PIChar::fromConsole(c.Char.AsciiChar);
|
||||
ret.symbol = PIChar::fromConsole(c.Char.AsciiChar);
|
||||
ret.format.color_char = PIScreenTypes::Black;
|
||||
if ((c.Attributes & (FOREGROUND_RED)) == FOREGROUND_RED) ret.format.color_char = PIScreenTypes::Red;
|
||||
if ((c.Attributes & (FOREGROUND_GREEN)) == FOREGROUND_GREEN) ret.format.color_char = PIScreenTypes::Green;
|
||||
if ((c.Attributes & (FOREGROUND_BLUE)) == FOREGROUND_BLUE) ret.format.color_char = PIScreenTypes::Blue;
|
||||
if ((c.Attributes & (FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::Cyan;
|
||||
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::Magenta;
|
||||
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN)) == (FOREGROUND_RED | FOREGROUND_GREEN)) ret.format.color_char = PIScreenTypes::Yellow;
|
||||
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_char = PIScreenTypes::White;
|
||||
if ((c.Attributes & (FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_GREEN | FOREGROUND_BLUE))
|
||||
ret.format.color_char = PIScreenTypes::Cyan;
|
||||
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_BLUE))
|
||||
ret.format.color_char = PIScreenTypes::Magenta;
|
||||
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN)) == (FOREGROUND_RED | FOREGROUND_GREEN))
|
||||
ret.format.color_char = PIScreenTypes::Yellow;
|
||||
if ((c.Attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE))
|
||||
ret.format.color_char = PIScreenTypes::White;
|
||||
ret.format.color_back = PIScreenTypes::Black;
|
||||
if ((c.Attributes & (BACKGROUND_RED)) == (BACKGROUND_RED)) ret.format.color_back = PIScreenTypes::Red;
|
||||
if ((c.Attributes & (BACKGROUND_GREEN)) == (BACKGROUND_GREEN)) ret.format.color_back = PIScreenTypes::Green;
|
||||
if ((c.Attributes & (BACKGROUND_BLUE)) == (BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Blue;
|
||||
if ((c.Attributes & (BACKGROUND_GREEN | BACKGROUND_BLUE)) == (BACKGROUND_GREEN | BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Cyan;
|
||||
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_BLUE)) == (BACKGROUND_RED | BACKGROUND_BLUE)) ret.format.color_back = PIScreenTypes::Magenta;
|
||||
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN)) == (BACKGROUND_RED | BACKGROUND_GREEN)) ret.format.color_back = PIScreenTypes::Yellow;
|
||||
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)) ret.format.color_back = PIScreenTypes::White;
|
||||
if ((c.Attributes & (BACKGROUND_GREEN | BACKGROUND_BLUE)) == (BACKGROUND_GREEN | BACKGROUND_BLUE))
|
||||
ret.format.color_back = PIScreenTypes::Cyan;
|
||||
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_BLUE)) == (BACKGROUND_RED | BACKGROUND_BLUE))
|
||||
ret.format.color_back = PIScreenTypes::Magenta;
|
||||
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN)) == (BACKGROUND_RED | BACKGROUND_GREEN))
|
||||
ret.format.color_back = PIScreenTypes::Yellow;
|
||||
if ((c.Attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)) == (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE))
|
||||
ret.format.color_back = PIScreenTypes::White;
|
||||
if ((c.Attributes & (FOREGROUND_INTENSITY)) > 0) ret.format.flags |= PIScreenTypes::Bold;
|
||||
return ret;
|
||||
}
|
||||
@@ -68,32 +77,32 @@ PIScreenTypes::Cell CharInfo2Cell(const CHAR_INFO & c) {
|
||||
|
||||
int SpecialKey2VirtualKeyCode(PIKbdListener::SpecialKey k) {
|
||||
switch (k) {
|
||||
case PIKbdListener::Tab : return '\t'; break;
|
||||
case PIKbdListener::Return : return '\n'; break;
|
||||
case PIKbdListener::Space : return ' '; break;
|
||||
case PIKbdListener::Backspace : return 8 ;
|
||||
case PIKbdListener::PageUp : return 33 ;
|
||||
case PIKbdListener::PageDown : return 34 ;
|
||||
case PIKbdListener::End : return 35 ;
|
||||
case PIKbdListener::Home : return 36 ;
|
||||
case PIKbdListener::LeftArrow : return 37 ;
|
||||
case PIKbdListener::UpArrow : return 38 ;
|
||||
case PIKbdListener::RightArrow: return 39 ;
|
||||
case PIKbdListener::DownArrow : return 40 ;
|
||||
case PIKbdListener::Insert : return 45 ;
|
||||
case PIKbdListener::Delete : return 46 ;
|
||||
case PIKbdListener::F1 : return 112;
|
||||
case PIKbdListener::F2 : return 113;
|
||||
case PIKbdListener::F3 : return 114;
|
||||
case PIKbdListener::F4 : return 115;
|
||||
case PIKbdListener::F5 : return 116;
|
||||
case PIKbdListener::F6 : return 117;
|
||||
case PIKbdListener::F7 : return 118;
|
||||
case PIKbdListener::F8 : return 119;
|
||||
case PIKbdListener::F9 : return 120;
|
||||
case PIKbdListener::F10 : return 121;
|
||||
case PIKbdListener::F11 : return 122;
|
||||
case PIKbdListener::F12 : return 123;
|
||||
case PIKbdListener::Tab: return '\t'; break;
|
||||
case PIKbdListener::Return: return '\n'; break;
|
||||
case PIKbdListener::Space: return ' '; break;
|
||||
case PIKbdListener::Backspace: return 8;
|
||||
case PIKbdListener::PageUp: return 33;
|
||||
case PIKbdListener::PageDown: return 34;
|
||||
case PIKbdListener::End: return 35;
|
||||
case PIKbdListener::Home: return 36;
|
||||
case PIKbdListener::LeftArrow: return 37;
|
||||
case PIKbdListener::UpArrow: return 38;
|
||||
case PIKbdListener::RightArrow: return 39;
|
||||
case PIKbdListener::DownArrow: return 40;
|
||||
case PIKbdListener::Insert: return 45;
|
||||
case PIKbdListener::Delete: return 46;
|
||||
case PIKbdListener::F1: return 112;
|
||||
case PIKbdListener::F2: return 113;
|
||||
case PIKbdListener::F3: return 114;
|
||||
case PIKbdListener::F4: return 115;
|
||||
case PIKbdListener::F5: return 116;
|
||||
case PIKbdListener::F6: return 117;
|
||||
case PIKbdListener::F7: return 118;
|
||||
case PIKbdListener::F8: return 119;
|
||||
case PIKbdListener::F9: return 120;
|
||||
case PIKbdListener::F10: return 121;
|
||||
case PIKbdListener::F11: return 122;
|
||||
case PIKbdListener::F12: return 123;
|
||||
default: break;
|
||||
}
|
||||
return 0;
|
||||
@@ -119,7 +128,7 @@ void readConsole(int x, int y, int w, int h) {
|
||||
ReadConsoleOutput(console, chars, bs, bc, &(sbi.srWindow));
|
||||
for (int i = 0; i < h; ++i)
|
||||
for (int j = 0; j < w; ++j)
|
||||
cells[i][j] = CharInfo2Cell(chars[i * w + j]);
|
||||
cells[i][j] = CharInfo2Cell(chars[i * w + j]);
|
||||
}
|
||||
|
||||
|
||||
@@ -137,13 +146,15 @@ void resizeConsole(int w, int h) {
|
||||
con_w = w;
|
||||
con_h = h;
|
||||
GetConsoleScreenBufferInfo(console, &sbi);
|
||||
sbi.srWindow.Left = 0;
|
||||
sbi.srWindow.Right = sbi.srWindow.Left + w - 1;
|
||||
sbi.srWindow.Left = 0;
|
||||
sbi.srWindow.Right = sbi.srWindow.Left + w - 1;
|
||||
sbi.srWindow.Bottom = sbi.srWindow.Top + h - 1;
|
||||
COORD sz; sz.X = w; sz.Y = h;
|
||||
COORD sz;
|
||||
sz.X = w;
|
||||
sz.Y = h;
|
||||
SetConsoleScreenBufferSize(console, sz);
|
||||
SetConsoleWindowInfo(console, TRUE, &(sbi.srWindow));
|
||||
//system(("mode CON: COLS=" + PIString::fromNumber(w) + " LINES=" + PIString::fromNumber(h)).dataAscii());
|
||||
// system(("mode CON: COLS=" + PIString::fromNumber(w) + " LINES=" + PIString::fromNumber(h)).dataAscii());
|
||||
resizeCells(w, h);
|
||||
}
|
||||
|
||||
@@ -152,12 +163,10 @@ class PipeReader: public PIThread {
|
||||
public:
|
||||
PipeReader(): PIThread() {
|
||||
wrote = readed = 0;
|
||||
msg_size = 0;
|
||||
msg_size = 0;
|
||||
start(1);
|
||||
}
|
||||
~PipeReader() {
|
||||
stop();
|
||||
}
|
||||
~PipeReader() { stop(); }
|
||||
void run() {
|
||||
in.resize(PIPE_BUFFER_SIZE);
|
||||
ReadFile(pipe, in.data(), in.size_s(), &readed, 0);
|
||||
@@ -165,7 +174,7 @@ public:
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
//piCout << errorString();
|
||||
// piCout << errorString();
|
||||
if (readed > 0) {
|
||||
in.resize(readed);
|
||||
stream.append(in);
|
||||
@@ -185,8 +194,9 @@ public:
|
||||
void parseMessage() {
|
||||
if (msg.size_s() < 4) return;
|
||||
PIMutexLocker _ml(con_mutex);
|
||||
int type = 0; msg >> type;
|
||||
//piCout << "msg" << type;
|
||||
int type = 0;
|
||||
msg >> type;
|
||||
// piCout << "msg" << type;
|
||||
switch ((PITerminalAuxMessageType)type) {
|
||||
case mtKey: {
|
||||
PIVector<PIKbdListener::KeyEvent> ke;
|
||||
@@ -194,27 +204,27 @@ public:
|
||||
PIVector<INPUT_RECORD> ir(ke.size() * 2);
|
||||
for (int i = 0; i < ke.size_s(); ++i) {
|
||||
PIKbdListener::KeyEvent k(ke[i]);
|
||||
int j = i+i, z = j+1;
|
||||
ir[j].EventType = KEY_EVENT;
|
||||
ir[j].Event.KeyEvent.wRepeatCount = 1;
|
||||
int j = i + i, z = j + 1;
|
||||
ir[j].EventType = KEY_EVENT;
|
||||
ir[j].Event.KeyEvent.wRepeatCount = 1;
|
||||
ir[j].Event.KeyEvent.dwControlKeyState = KeyModifiers2ControlKeyState(k.modifiers);
|
||||
if (PITerminal::isSpecialKey(k.key)) {
|
||||
ir[j].Event.KeyEvent.wVirtualKeyCode = SpecialKey2VirtualKeyCode((PIKbdListener::SpecialKey)k.key);
|
||||
ir[j].Event.KeyEvent.uChar.AsciiChar = PIChar((ushort)piMaxi(k.key, 0)).toAscii();
|
||||
} else
|
||||
ir[j].Event.KeyEvent.uChar.UnicodeChar = PIChar((ushort)piMaxi(k.key, 0)).toWChar();
|
||||
//piCout << ir[j].Event.KeyEvent.wVirtualKeyCode << int(ir[j].Event.KeyEvent.uChar.AsciiChar);
|
||||
// piCout << ir[j].Event.KeyEvent.wVirtualKeyCode << int(ir[j].Event.KeyEvent.uChar.AsciiChar);
|
||||
ir[j].Event.KeyEvent.bKeyDown = true;
|
||||
ir[z] = ir[j];
|
||||
ir[z] = ir[j];
|
||||
ir[z].Event.KeyEvent.bKeyDown = false;
|
||||
}
|
||||
WriteConsoleInput(cstdin, ir.data(), ir.size_s(), &wrote);
|
||||
} break;
|
||||
} break;
|
||||
case mtResize: {
|
||||
int rw = -1, rh = -1;
|
||||
msg >> rw >> rh;
|
||||
if (rw > 0 && rh > 0) resizeConsole(rw, rh);
|
||||
} break;
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@@ -231,8 +241,8 @@ void getCursor(int & x, int & y) {
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
//piCout << "start";
|
||||
int main(int argc, char * argv[]) {
|
||||
// piCout << "start";
|
||||
STARTUPINFOA si;
|
||||
PROCESS_INFORMATION pi;
|
||||
memset(&si, 0, sizeof(si));
|
||||
@@ -241,39 +251,39 @@ int main (int argc, char * argv[]) {
|
||||
PIString shmh, pname;
|
||||
if (argc > 1) shmh = argv[1];
|
||||
if (argc > 2) pname = argv[2];
|
||||
if(!CreateProcessA(0, (LPSTR)"cmd", 0, 0, true, 0, 0, 0, &si, &pi)) {
|
||||
if (!CreateProcessA(0, (LPSTR) "cmd", 0, 0, true, 0, 0, 0, &si, &pi)) {
|
||||
return 1;
|
||||
}
|
||||
PISharedMemory shm("piterm_aux" + shmh, 1024*1024);
|
||||
PISharedMemory shm("piterm_aux" + shmh, 1024 * 1024);
|
||||
pipe = CreateFileA((LPSTR)pname.dataAscii(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
|
||||
if (pipe == INVALID_HANDLE_VALUE) {
|
||||
return 1;
|
||||
}
|
||||
CloseHandle(pi.hThread);
|
||||
cmd_proc = pi.hProcess;
|
||||
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
cstdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
cstdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
resizeConsole(80, 24);
|
||||
PipeReader pipe_reader;
|
||||
pipe_reader.waitForStart();
|
||||
PIByteArray scr;
|
||||
while (true) {
|
||||
//piCout << "loop";
|
||||
// piCout << "loop";
|
||||
if (!pipe_reader.isRunning()) break;
|
||||
con_mutex.lock();
|
||||
getCursor(data_out.cursor_x, data_out.cursor_y);
|
||||
readConsole(0, 0, con_w, con_h);
|
||||
scr.clear();
|
||||
scr << cells;
|
||||
data_out.size_x = con_w;
|
||||
data_out.size_y = con_h;
|
||||
data_out.size_x = con_w;
|
||||
data_out.size_y = con_h;
|
||||
data_out.cells_size = scr.size_s();
|
||||
con_mutex.unlock();
|
||||
shm.write(&data_out, sizeof(data_out));
|
||||
shm.write(scr, sizeof(data_out));
|
||||
piMSleep(25);
|
||||
}
|
||||
//piCout << "exit";
|
||||
// piCout << "exit";
|
||||
TerminateProcess(pi.hProcess, 0);
|
||||
CloseHandle(pi.hProcess);
|
||||
return 0;
|
||||
|
||||
@@ -1,86 +1,83 @@
|
||||
#include "generator.h"
|
||||
#include "piresourcesstorage.h"
|
||||
#include "piiostream.h"
|
||||
|
||||
|
||||
PIString initName(const PIString & n) {
|
||||
return PIFile::fileInfo(n).baseName().replaceAll(".", "_").replaceAll("/", "_")
|
||||
.replaceAll(":", "_").replaceAll("-", "_");
|
||||
}
|
||||
|
||||
|
||||
bool generate(const PIString & init_name, PIFile & file, const PIVector<ParserSection> & files) {
|
||||
if (!file.isOpened()) return false;
|
||||
PIString fcname = initName(file.path());
|
||||
PIString icname = "_PIRC_" + fcname + "_Initializer_";
|
||||
PIString dataname = "_pirc_" + fcname + "_data_";
|
||||
PIString descname = "_pirc_" + fcname + "_desc_";
|
||||
PIString funcname = "_pirc_" + init_name + "_init_";
|
||||
PIVector<PIResourcesStorage::__RCEntry> fv;
|
||||
piForeachC (ParserSection & s, files) {
|
||||
piForeachC (ParserEntry & p, s.files) {
|
||||
PIFile f;
|
||||
if (!f.open(p.path, PIIODevice::ReadOnly)) continue;
|
||||
//piCout << "gen" << p.name << p.alias << p.path;
|
||||
fv << PIResourcesStorage::__RCEntry(s.name, p.name, p.alias, p.path);
|
||||
}
|
||||
}
|
||||
if (fv.isEmpty()) return false;
|
||||
PIIOTextStream ts(&file);
|
||||
ts << "#include \"piresourcesstorage.h\"\n\nstatic const uchar " << dataname << "[] = {\n";
|
||||
bool first = true;
|
||||
int rcnt = -1;
|
||||
llong curoff = 0, curfile = 0;
|
||||
piForeach (PIResourcesStorage::__RCEntry & e, fv) {
|
||||
e.offset = curoff;
|
||||
PIFile f;
|
||||
f.open(e.file, PIIODevice::ReadOnly);
|
||||
PIByteArray readed;
|
||||
curfile = 0;
|
||||
while (!f.isEnd()) {
|
||||
readed = f.read(4096);
|
||||
curfile += readed.size_s();
|
||||
for (int i = 0; i < readed.size_s(); ++i) {
|
||||
if (!first)
|
||||
ts << ',';
|
||||
first = false;
|
||||
if (++rcnt >= 32) {
|
||||
ts << '\n';
|
||||
rcnt = 0;
|
||||
}
|
||||
ts << int(readed[i]);
|
||||
}
|
||||
}
|
||||
e.size = curfile;
|
||||
curoff += curfile;
|
||||
}
|
||||
ts << "\n};\n";
|
||||
PIByteArray dba;
|
||||
dba << fv;
|
||||
ts << "\nstatic const uchar " << descname << "[] = {\n";
|
||||
first = true;
|
||||
rcnt = -1;
|
||||
for (int i = 0; i < dba.size_s(); ++i) {
|
||||
if (!first)
|
||||
ts << ',';
|
||||
first = false;
|
||||
if (++rcnt >= 32) {
|
||||
ts << '\n';
|
||||
rcnt = 0;
|
||||
}
|
||||
ts << int(dba[i]);
|
||||
}
|
||||
ts << "\n};\n";
|
||||
|
||||
ts << "\nvoid " << funcname << "() {\n";
|
||||
ts << "\tPIResourcesStorage::instance()->registerSection(" << dataname << ", " << descname << ", sizeof(" << descname << "));\n";
|
||||
ts << "}\n";
|
||||
|
||||
ts << "\nclass " << icname << " {\n";
|
||||
ts << "public:\n\t" << icname << "() {\n";
|
||||
ts << "\t\t" << funcname << "();\n";
|
||||
ts << "\t}\n";
|
||||
ts << "} _pirc_" << fcname << "_initializer_;\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "generator.h"
|
||||
|
||||
#include "piiostream.h"
|
||||
#include "piresourcesstorage.h"
|
||||
|
||||
|
||||
PIString initName(const PIString & n) {
|
||||
return PIFile::fileInfo(n).baseName().replaceAll(".", "_").replaceAll("/", "_").replaceAll(":", "_").replaceAll("-", "_");
|
||||
}
|
||||
|
||||
|
||||
bool generate(const PIString & init_name, PIFile & file, const PIVector<ParserSection> & files) {
|
||||
if (!file.isOpened()) return false;
|
||||
PIString fcname = initName(file.path());
|
||||
PIString icname = "_PIRC_" + fcname + "_Initializer_";
|
||||
PIString dataname = "_pirc_" + fcname + "_data_";
|
||||
PIString descname = "_pirc_" + fcname + "_desc_";
|
||||
PIString funcname = "_pirc_" + init_name + "_init_";
|
||||
PIVector<PIResourcesStorage::__RCEntry> fv;
|
||||
piForeachC(ParserSection & s, files) {
|
||||
piForeachC(ParserEntry & p, s.files) {
|
||||
PIFile f;
|
||||
if (!f.open(p.path, PIIODevice::ReadOnly)) continue;
|
||||
// piCout << "gen" << p.name << p.alias << p.path;
|
||||
fv << PIResourcesStorage::__RCEntry(s.name, p.name, p.alias, p.path);
|
||||
}
|
||||
}
|
||||
if (fv.isEmpty()) return false;
|
||||
PIIOTextStream ts(&file);
|
||||
ts << "#include \"piresourcesstorage.h\"\n\nstatic const uchar " << dataname << "[] = {\n";
|
||||
bool first = true;
|
||||
int rcnt = -1;
|
||||
llong curoff = 0, curfile = 0;
|
||||
piForeach(PIResourcesStorage::__RCEntry & e, fv) {
|
||||
e.offset = curoff;
|
||||
PIFile f;
|
||||
f.open(e.file, PIIODevice::ReadOnly);
|
||||
PIByteArray readed;
|
||||
curfile = 0;
|
||||
while (!f.isEnd()) {
|
||||
readed = f.read(4096);
|
||||
curfile += readed.size_s();
|
||||
for (int i = 0; i < readed.size_s(); ++i) {
|
||||
if (!first) ts << ',';
|
||||
first = false;
|
||||
if (++rcnt >= 32) {
|
||||
ts << '\n';
|
||||
rcnt = 0;
|
||||
}
|
||||
ts << int(readed[i]);
|
||||
}
|
||||
}
|
||||
e.size = curfile;
|
||||
curoff += curfile;
|
||||
}
|
||||
ts << "\n};\n";
|
||||
PIByteArray dba;
|
||||
dba << fv;
|
||||
ts << "\nstatic const uchar " << descname << "[] = {\n";
|
||||
first = true;
|
||||
rcnt = -1;
|
||||
for (int i = 0; i < dba.size_s(); ++i) {
|
||||
if (!first) ts << ',';
|
||||
first = false;
|
||||
if (++rcnt >= 32) {
|
||||
ts << '\n';
|
||||
rcnt = 0;
|
||||
}
|
||||
ts << int(dba[i]);
|
||||
}
|
||||
ts << "\n};\n";
|
||||
|
||||
ts << "\nvoid " << funcname << "() {\n";
|
||||
ts << "\tPIResourcesStorage::instance()->registerSection(" << dataname << ", " << descname << ", sizeof(" << descname << "));\n";
|
||||
ts << "}\n";
|
||||
|
||||
ts << "\nclass " << icname << " {\n";
|
||||
ts << "public:\n\t" << icname << "() {\n";
|
||||
ts << "\t\t" << funcname << "();\n";
|
||||
ts << "\t}\n";
|
||||
ts << "} _pirc_" << fcname << "_initializer_;\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef PIRC_GENERATOR_H
|
||||
#define PIRC_GENERATOR_H
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
PIString initName(const PIString & n);
|
||||
bool generate(const PIString & init_name, PIFile & file, const PIVector<ParserSection> & files);
|
||||
|
||||
#endif // PIRC_GENERATOR_H
|
||||
#ifndef PIRC_GENERATOR_H
|
||||
#define PIRC_GENERATOR_H
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
PIString initName(const PIString & n);
|
||||
bool generate(const PIString & init_name, PIFile & file, const PIVector<ParserSection> & files);
|
||||
|
||||
#endif // PIRC_GENERATOR_H
|
||||
|
||||
@@ -1,98 +1,95 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Resources compiller
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "parser.h"
|
||||
#include "generator.h"
|
||||
#include "picli.h"
|
||||
#include "piiostream.h"
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << Bold << "PIP Resources Compiler";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default << "\"pip_rc [-hl] [-n <name>] -i <in_file> -o <out_file>\"" << NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << "-h --help " << Green << "- display this message and exit";
|
||||
piCout << "-n --name <name> " << Green << "- name of initialize function, by default is <out_file> base name";
|
||||
piCout << "-i --input <in_file> " << Green << "- resources description file";
|
||||
piCout << "-o --out <out_file> " << Green << "- output .cpp file";
|
||||
piCout << "-l --list " << Green << "- print readed files from description and exit";
|
||||
piCout << "-s --silent " << Green << "- no console output";
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
PICLI cli(argc, argv);
|
||||
cli.addArgument("input", true);
|
||||
cli.addArgument("out", true);
|
||||
cli.addArgument("name", true);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("list");
|
||||
cli.addArgument("silent");
|
||||
|
||||
if (cli.hasArgument("silent"))
|
||||
piDebug = false;
|
||||
if (cli.hasArgument("help") || !cli.hasArgument("input") ||
|
||||
(!cli.hasArgument("out") && !cli.hasArgument("list"))) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIVector<ParserSection> files = parse(cli.argumentValue("input"));
|
||||
if (files.isEmpty()) {
|
||||
piCout << "Error: resources description file is empty";
|
||||
return 0;
|
||||
}
|
||||
if (cli.hasArgument("list")) {
|
||||
piForeachC (ParserSection & s, files) {
|
||||
piForeachC (ParserEntry & e, s.files) {
|
||||
piCout << e.path;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIString out_file = cli.argumentValue("out");
|
||||
PIString init_name = cli.argumentValue("name");
|
||||
init_name = initName(init_name.isEmpty() ? out_file : init_name);
|
||||
PIFile outf;
|
||||
if (!out_file.isEmpty()) {
|
||||
if (outf.open(out_file, PIIODevice::ReadWrite)) {
|
||||
outf.clear();
|
||||
} else {
|
||||
piCout << "Error: can`t open out file" << out_file;
|
||||
return 1;
|
||||
}
|
||||
PIIOTextStream ts(&outf);
|
||||
ts << "// Generated by \"PIP Resources Compiler\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
|
||||
ts << "// Execute command:\n";
|
||||
piForeachC (PIString & _a, cli.rawArguments())
|
||||
ts << "// \"" << _a << "\"\n";
|
||||
ts << "\n";
|
||||
if (!generate(init_name, outf, files)) {
|
||||
piCout << "Error: generate fail";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
Resources compiller
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "generator.h"
|
||||
#include "parser.h"
|
||||
#include "picli.h"
|
||||
#include "piiostream.h"
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << Bold << "PIP Resources Compiler";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default << "\"pip_rc [-hl] [-n <name>] -i <in_file> -o <out_file>\"" << NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << "-h --help " << Green << "- display this message and exit";
|
||||
piCout << "-n --name <name> " << Green << "- name of initialize function, by default is <out_file> base name";
|
||||
piCout << "-i --input <in_file> " << Green << "- resources description file";
|
||||
piCout << "-o --out <out_file> " << Green << "- output .cpp file";
|
||||
piCout << "-l --list " << Green << "- print readed files from description and exit";
|
||||
piCout << "-s --silent " << Green << "- no console output";
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
PICLI cli(argc, argv);
|
||||
cli.addArgument("input", true);
|
||||
cli.addArgument("out", true);
|
||||
cli.addArgument("name", true);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("list");
|
||||
cli.addArgument("silent");
|
||||
|
||||
if (cli.hasArgument("silent")) piDebug = false;
|
||||
if (cli.hasArgument("help") || !cli.hasArgument("input") || (!cli.hasArgument("out") && !cli.hasArgument("list"))) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIVector<ParserSection> files = parse(cli.argumentValue("input"));
|
||||
if (files.isEmpty()) {
|
||||
piCout << "Error: resources description file is empty";
|
||||
return 0;
|
||||
}
|
||||
if (cli.hasArgument("list")) {
|
||||
piForeachC(ParserSection & s, files) {
|
||||
piForeachC(ParserEntry & e, s.files) {
|
||||
piCout << e.path;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PIString out_file = cli.argumentValue("out");
|
||||
PIString init_name = cli.argumentValue("name");
|
||||
init_name = initName(init_name.isEmpty() ? out_file : init_name);
|
||||
PIFile outf;
|
||||
if (!out_file.isEmpty()) {
|
||||
if (outf.open(out_file, PIIODevice::ReadWrite)) {
|
||||
outf.clear();
|
||||
} else {
|
||||
piCout << "Error: can`t open out file" << out_file;
|
||||
return 1;
|
||||
}
|
||||
PIIOTextStream ts(&outf);
|
||||
ts << "// Generated by \"PIP Resources Compiler\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
|
||||
ts << "// Execute command:\n";
|
||||
piForeachC(PIString & _a, cli.rawArguments())
|
||||
ts << "// \"" << _a << "\"\n";
|
||||
ts << "\n";
|
||||
if (!generate(init_name, outf, files)) {
|
||||
piCout << "Error: generate fail";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,121 +1,119 @@
|
||||
#include "parser.h"
|
||||
#include "piconfig.h"
|
||||
#include "piiostream.h"
|
||||
|
||||
|
||||
PIVector<ParserSection> parse(const PIString & path) {
|
||||
PIVector<ParserSection> ret;
|
||||
PIFile f;
|
||||
if (!f.open(path, PIIODevice::ReadOnly))
|
||||
return ret;
|
||||
PIString ext = f.fileInfo().extension().toLowerCase();
|
||||
PIString dir = PIDir(f.fileInfo().dir()).absolutePath() + "/";
|
||||
//piCout << dir;
|
||||
if (ext == "conf") return parseConf(f, dir);
|
||||
if (ext == "qrc") return parseQRC(f, dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ParserEntry makeEntry(PIString filename, const PIString & dir) {
|
||||
ParserEntry ret;
|
||||
ret.path = filename;
|
||||
if (!PIDir(PIFile::fileInfo(filename).dir()).isAbsolute()) {
|
||||
//piCout << "rel, add dir";
|
||||
ret.path.insert(0, dir);
|
||||
}
|
||||
//piCout << line << path;
|
||||
ret.name = filename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIVector<ParserSection> parseConf(PIFile & file, const PIString & dir) {
|
||||
PIVector<ParserSection> ret;
|
||||
if (!file.isOpened()) return ret;
|
||||
PIIOTextStream ts(&file);
|
||||
ParserSection ps;
|
||||
while (!ts.isEnd()) {
|
||||
PIString line = ts.readLine().trim();
|
||||
if (line.isEmpty()) continue;
|
||||
if (line.startsWith("[") && line.endsWith("]")) {
|
||||
if (!ps.files.isEmpty()) ret << ps;
|
||||
ps.name = line.cutLeft(1).cutRight(1).trim();
|
||||
ps.files.clear();
|
||||
continue;
|
||||
}
|
||||
PIString alias;
|
||||
int i = line.findLast("=");
|
||||
if (i > 0) {
|
||||
alias = line.takeMid(i + 1).trim();
|
||||
line.cutRight(1).trim();
|
||||
}
|
||||
ParserEntry e = makeEntry(line, dir);
|
||||
if (!alias.isEmpty())
|
||||
e.alias = alias;
|
||||
ps.files << e;
|
||||
}
|
||||
if (!ps.files.isEmpty()) ret << ps;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIVector<ParserSection> parseQRC(PIFile & file, const PIString & dir) {
|
||||
PIVector<ParserSection> ret;
|
||||
if (!file.isOpened()) return ret;
|
||||
PIIOTextStream ts(&file);
|
||||
ParserSection ps;
|
||||
bool is_files = false;
|
||||
while (!ts.isEnd()) {
|
||||
PIString line = ts.readLine().trim();
|
||||
if (line.isEmpty()) continue;
|
||||
if (line.startsWith("<qresource")) {
|
||||
if (!ps.files.isEmpty()) ret << ps;
|
||||
ps.name.clear();
|
||||
ps.files.clear();
|
||||
line.cutLeft(10);
|
||||
if (line.endsWith(">")) line.cutRight(1);
|
||||
line.trim();
|
||||
if (line.endsWith("/")) {
|
||||
is_files = false;
|
||||
continue;
|
||||
}
|
||||
is_files = true;
|
||||
if (line.startsWith("prefix")) {
|
||||
int i = line.find("=");
|
||||
if (i > 0) {
|
||||
line.cutLeft(i + 1).trim();
|
||||
if (line.startsWith("\"")) line.cutLeft(1);
|
||||
if (line.endsWith("\"")) line.cutRight(1);
|
||||
ps.name = line;
|
||||
}
|
||||
}
|
||||
//piCout << "section \"" << ps.name << "\"";
|
||||
continue;
|
||||
}
|
||||
if (line == "</qresource>") {
|
||||
is_files = false;
|
||||
continue;
|
||||
}
|
||||
if (!is_files) continue;
|
||||
if (!line.startsWith("<file")) continue;
|
||||
PIString alias = line.takeRange('<', '>', '\0');
|
||||
alias.cutLeft(4).trim();
|
||||
if (alias.startsWith("alias")) {
|
||||
int i = alias.find("=");
|
||||
if (i > 0) {
|
||||
alias.cutLeft(i + 1).trim();
|
||||
if (alias.startsWith("\"")) alias.cutLeft(1);
|
||||
if (alias.endsWith("\"")) alias.cutRight(1);
|
||||
}
|
||||
}
|
||||
if (line.endsWith("</file>")) line.cutRight(7).trim();
|
||||
ParserEntry e = makeEntry(line, dir);
|
||||
if (!alias.isEmpty())
|
||||
e.alias = alias;
|
||||
ps.files << e;
|
||||
//piCout << "file =" << line << "alias =" << alias;
|
||||
}
|
||||
if (!ps.files.isEmpty()) ret << ps;
|
||||
return ret;
|
||||
}
|
||||
#include "parser.h"
|
||||
|
||||
#include "piconfig.h"
|
||||
#include "piiostream.h"
|
||||
|
||||
|
||||
PIVector<ParserSection> parse(const PIString & path) {
|
||||
PIVector<ParserSection> ret;
|
||||
PIFile f;
|
||||
if (!f.open(path, PIIODevice::ReadOnly)) return ret;
|
||||
PIString ext = f.fileInfo().extension().toLowerCase();
|
||||
PIString dir = PIDir(f.fileInfo().dir()).absolutePath() + "/";
|
||||
// piCout << dir;
|
||||
if (ext == "conf") return parseConf(f, dir);
|
||||
if (ext == "qrc") return parseQRC(f, dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ParserEntry makeEntry(PIString filename, const PIString & dir) {
|
||||
ParserEntry ret;
|
||||
ret.path = filename;
|
||||
if (!PIDir(PIFile::fileInfo(filename).dir()).isAbsolute()) {
|
||||
// piCout << "rel, add dir";
|
||||
ret.path.insert(0, dir);
|
||||
}
|
||||
// piCout << line << path;
|
||||
ret.name = filename;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIVector<ParserSection> parseConf(PIFile & file, const PIString & dir) {
|
||||
PIVector<ParserSection> ret;
|
||||
if (!file.isOpened()) return ret;
|
||||
PIIOTextStream ts(&file);
|
||||
ParserSection ps;
|
||||
while (!ts.isEnd()) {
|
||||
PIString line = ts.readLine().trim();
|
||||
if (line.isEmpty()) continue;
|
||||
if (line.startsWith("[") && line.endsWith("]")) {
|
||||
if (!ps.files.isEmpty()) ret << ps;
|
||||
ps.name = line.cutLeft(1).cutRight(1).trim();
|
||||
ps.files.clear();
|
||||
continue;
|
||||
}
|
||||
PIString alias;
|
||||
int i = line.findLast("=");
|
||||
if (i > 0) {
|
||||
alias = line.takeMid(i + 1).trim();
|
||||
line.cutRight(1).trim();
|
||||
}
|
||||
ParserEntry e = makeEntry(line, dir);
|
||||
if (!alias.isEmpty()) e.alias = alias;
|
||||
ps.files << e;
|
||||
}
|
||||
if (!ps.files.isEmpty()) ret << ps;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIVector<ParserSection> parseQRC(PIFile & file, const PIString & dir) {
|
||||
PIVector<ParserSection> ret;
|
||||
if (!file.isOpened()) return ret;
|
||||
PIIOTextStream ts(&file);
|
||||
ParserSection ps;
|
||||
bool is_files = false;
|
||||
while (!ts.isEnd()) {
|
||||
PIString line = ts.readLine().trim();
|
||||
if (line.isEmpty()) continue;
|
||||
if (line.startsWith("<qresource")) {
|
||||
if (!ps.files.isEmpty()) ret << ps;
|
||||
ps.name.clear();
|
||||
ps.files.clear();
|
||||
line.cutLeft(10);
|
||||
if (line.endsWith(">")) line.cutRight(1);
|
||||
line.trim();
|
||||
if (line.endsWith("/")) {
|
||||
is_files = false;
|
||||
continue;
|
||||
}
|
||||
is_files = true;
|
||||
if (line.startsWith("prefix")) {
|
||||
int i = line.find("=");
|
||||
if (i > 0) {
|
||||
line.cutLeft(i + 1).trim();
|
||||
if (line.startsWith("\"")) line.cutLeft(1);
|
||||
if (line.endsWith("\"")) line.cutRight(1);
|
||||
ps.name = line;
|
||||
}
|
||||
}
|
||||
// piCout << "section \"" << ps.name << "\"";
|
||||
continue;
|
||||
}
|
||||
if (line == "</qresource>") {
|
||||
is_files = false;
|
||||
continue;
|
||||
}
|
||||
if (!is_files) continue;
|
||||
if (!line.startsWith("<file")) continue;
|
||||
PIString alias = line.takeRange('<', '>', '\0');
|
||||
alias.cutLeft(4).trim();
|
||||
if (alias.startsWith("alias")) {
|
||||
int i = alias.find("=");
|
||||
if (i > 0) {
|
||||
alias.cutLeft(i + 1).trim();
|
||||
if (alias.startsWith("\"")) alias.cutLeft(1);
|
||||
if (alias.endsWith("\"")) alias.cutRight(1);
|
||||
}
|
||||
}
|
||||
if (line.endsWith("</file>")) line.cutRight(7).trim();
|
||||
ParserEntry e = makeEntry(line, dir);
|
||||
if (!alias.isEmpty()) e.alias = alias;
|
||||
ps.files << e;
|
||||
// piCout << "file =" << line << "alias =" << alias;
|
||||
}
|
||||
if (!ps.files.isEmpty()) ret << ps;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
#ifndef PIRC_PARSER_H
|
||||
#define PIRC_PARSER_H
|
||||
|
||||
#include "pidir.h"
|
||||
#include "pifile.h"
|
||||
|
||||
struct ParserEntry {
|
||||
ParserEntry(const PIString & n = PIString(), const PIString & a = PIString(), const PIString & p = PIString()) {
|
||||
name = n;
|
||||
alias = a;
|
||||
path = p;
|
||||
}
|
||||
PIString name;
|
||||
PIString alias;
|
||||
PIString path;
|
||||
};
|
||||
|
||||
struct ParserSection {
|
||||
PIString name;
|
||||
PIVector<ParserEntry> files;
|
||||
};
|
||||
|
||||
PIVector<ParserSection> parse(const PIString & path);
|
||||
PIVector<ParserSection> parseConf(PIFile & file, const PIString & dir);
|
||||
PIVector<ParserSection> parseQRC(PIFile & file, const PIString & dir);
|
||||
|
||||
#endif // PIRC_PARSER_H
|
||||
#ifndef PIRC_PARSER_H
|
||||
#define PIRC_PARSER_H
|
||||
|
||||
#include "pidir.h"
|
||||
#include "pifile.h"
|
||||
|
||||
struct ParserEntry {
|
||||
ParserEntry(const PIString & n = PIString(), const PIString & a = PIString(), const PIString & p = PIString()) {
|
||||
name = n;
|
||||
alias = a;
|
||||
path = p;
|
||||
}
|
||||
PIString name;
|
||||
PIString alias;
|
||||
PIString path;
|
||||
};
|
||||
|
||||
struct ParserSection {
|
||||
PIString name;
|
||||
PIVector<ParserEntry> files;
|
||||
};
|
||||
|
||||
PIVector<ParserSection> parse(const PIString & path);
|
||||
PIVector<ParserSection> parseConf(PIFile & file, const PIString & dir);
|
||||
PIVector<ParserSection> parseQRC(PIFile & file, const PIString & dir);
|
||||
|
||||
#endif // PIRC_PARSER_H
|
||||
|
||||
@@ -1,885 +1,880 @@
|
||||
#include "daemon.h"
|
||||
#include "shared.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "picrypt.h"
|
||||
|
||||
const char self_name[] = "__self__";
|
||||
extern PIScreen * screen;
|
||||
extern PISystemMonitor sys_mon;
|
||||
|
||||
Daemon::Remote::Remote(const PIString & n): PIThread() {
|
||||
setName(n);
|
||||
term = 0;
|
||||
ft.setName(n);
|
||||
ft.setPacketSize(3984);
|
||||
ft.setCRCEnabled(false);
|
||||
CONNECTU(&ft, sendRequest, this, ftSendRequest)
|
||||
CONNECTU(&ft, receiveFilesFinished, this, ftReceived)
|
||||
CONNECTU(&ft, sendFilesFinished, this, ftSended)
|
||||
CONNECTU(&term_timer, tickEvent, this, termTimerTick)
|
||||
dir_my = PIDir::current();
|
||||
}
|
||||
|
||||
|
||||
Daemon::Remote::~Remote() {
|
||||
shellClose();
|
||||
ft.stop();
|
||||
stopAndWait();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::shellOpen() {
|
||||
if (term) return;
|
||||
piCoutObj << "shell open";
|
||||
term = new PITerminal();
|
||||
term->initialize();
|
||||
term_timer.start(50);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::shellClose() {
|
||||
if (!term) return;
|
||||
piCoutObj << "shell close";
|
||||
term_timer.stop();
|
||||
term->destroy();
|
||||
delete term;
|
||||
term = 0;
|
||||
//piCoutObj << "shellClose ok";
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::shellResize(int w, int h) {
|
||||
if (!term) return;
|
||||
term->resize(w, h);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::shellKeySend(PIKbdListener::KeyEvent k) {
|
||||
if (!term) return;
|
||||
term->write(k);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::termTimerTick() {
|
||||
if (!term) return;
|
||||
PIVector<PIVector<PIScreenTypes::Cell> > cells = term->content();
|
||||
if (pcells == cells) return;
|
||||
pcells = cells;
|
||||
PIByteArray ba;
|
||||
ba << int(ShellContent) << cells;
|
||||
//piCout << ba.size_s() << pcells.back().back().symbol.unicode16Code() << cells.back().back().symbol.unicode16Code();
|
||||
sendRequest(name(), ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::startAction(Daemon::PacketType a, const PIString & dir, const PIStringList & fl) {
|
||||
_fl = fl;
|
||||
if (!dir.isEmpty())
|
||||
piForeach (PIString & s, _fl)
|
||||
s.prepend(dir);
|
||||
//piCout << "send" << _fl;
|
||||
action = a;
|
||||
startOnce();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::run() {
|
||||
PIDir d(dir_my);
|
||||
switch (action) {
|
||||
case CopyFiles:
|
||||
ft.send(_fl);
|
||||
break;
|
||||
case RemoveFiles:
|
||||
::removeFiles(d, _fl);
|
||||
updateDirEntries();
|
||||
changeDirFinished(name(), d.absolutePath());
|
||||
break;
|
||||
case RequestChangeDir:
|
||||
updateDirEntries();
|
||||
changeDirFinished(name(), d.absolutePath());
|
||||
break;
|
||||
case MkDir:
|
||||
if (!_fl.isEmpty()) PIDir::make(d.absolutePath() + PIDir::separator + _fl.at(0));
|
||||
updateDirEntries();
|
||||
changeDirFinished(name(), d.absolutePath());
|
||||
break;
|
||||
case CryptFiles:
|
||||
piCoutObj << "CryptFiles";
|
||||
if (!_fl.isEmpty()) {
|
||||
PIString p = askUserInput("Password:");
|
||||
::cryptFiles(d, _fl, PICrypt::hash(p));
|
||||
}
|
||||
updateDirEntries();
|
||||
changeDirFinished(name(), d.absolutePath());
|
||||
break;
|
||||
default: break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::updateDirEntries() {
|
||||
//piCout << dir_my;
|
||||
if (!dir_my.isExists()) dir_my = PIDir::current();
|
||||
my_filelist = dir_my.entries();
|
||||
piForeach (PIFile::FileInfo & f, my_filelist) f.path = f.name();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Daemon::TileFileProgress::TileFileProgress(): PIScreenTile() {
|
||||
size_policy = PIScreenTypes::Fixed;
|
||||
ft = 0;
|
||||
rec = false;
|
||||
setMargins(1, 1, 1, 1);
|
||||
spacing = 1;
|
||||
back_format.color_back = Yellow;
|
||||
label_file = new TileSimple();
|
||||
label_speed = new TileSimple();
|
||||
label_cnt = new TileSimple();
|
||||
prog_file = new TileProgress();
|
||||
prog_all = new TileProgress();
|
||||
buttons = new TileButtons("fd_buttons");
|
||||
buttons->content << TileButtons::Button("Pause", CellFormat());
|
||||
buttons->content << TileButtons::Button("Cancel", CellFormat());
|
||||
label_file->content.resize(1);
|
||||
label_speed->content.resize(1);
|
||||
label_cnt->content.resize(1);
|
||||
buttons->back_format.color_back = Yellow;
|
||||
label_file->back_format.color_back = label_speed->back_format.color_back = label_cnt->back_format.color_back = Yellow;
|
||||
label_file->content[0].second = label_speed->content[0].second = label_cnt->content[0].second = CellFormat(Black, Transparent);
|
||||
addTile(label_file);
|
||||
addTile(label_speed);
|
||||
addTile(label_cnt);
|
||||
addTile(prog_file);
|
||||
addTile(prog_all);
|
||||
addTile(buttons);
|
||||
CONNECTU((::screen), tileEvent, this, tileEvent)
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::resizeEvent(int w, int h) {
|
||||
PIScreenTile::resizeEvent(w, h);
|
||||
w = ::screen->windowWidth() / 1.4;
|
||||
minimumWidth = maximumWidth = w;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::sizeHint(int & w, int & h) const {
|
||||
PIScreenTile::sizeHint(w, h);
|
||||
w = ::screen->windowWidth() / 1.4;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::drawEvent(PIScreenDrawer * d) {
|
||||
if (ft) {
|
||||
label_file->content[0].first = ft->stateString() + " " + ft->curFile();
|
||||
if (!label_file->content[0].first.isEmpty())
|
||||
label_file->content[0].first[0] = label_file->content[0].first[0].toUpper();
|
||||
PIString spd("Speed: "), cnt;
|
||||
if (ft->isReceiving()) spd = ft->diagnostic().receiveSpeed();
|
||||
else spd = ft->diagnostic().sendSpeed().expandRightTo(10, ' ');
|
||||
spd += " ETA: ";
|
||||
if (!ft->isReceiving() && !ft->isSending()) {
|
||||
tm.reset();
|
||||
spd += "-";
|
||||
} else {
|
||||
double el = tm.elapsed_s();
|
||||
int cb = ft->bytesCur();
|
||||
if ((el <= 0.) || (cb <= 0)) spd += "-";
|
||||
else {
|
||||
double s = (el / cb) * (ft->bytesAll() - cb);
|
||||
spd += readableTime(PITime::fromSystemTime(PISystemTime::fromSeconds(s)));
|
||||
}
|
||||
}
|
||||
spd += " Elapsed: " + readableTime(PITime::fromSystemTime(PISystemTime::fromSeconds(tme.elapsed_s())));
|
||||
label_speed->content[0].first = spd;
|
||||
cnt = "File: " + PIString::readableSize(ft->bytesFileCur()).expandLeftTo(8, ' ');
|
||||
cnt += " / " + PIString::readableSize(ft->bytesFileAll()).expandLeftTo(8, ' ');
|
||||
cnt += " All: " + PIString::readableSize(ft->bytesCur()).expandLeftTo(8, ' ');
|
||||
cnt += " / " + PIString::readableSize(ft->bytesAll()).expandLeftTo(8, ' ');
|
||||
label_cnt->content[0].first = cnt;
|
||||
if (ft->bytesFileAll() > 0)
|
||||
prog_file->value = piRoundd(ft->bytesFileCur() / double(ft->bytesFileAll()) * 100.);
|
||||
if (ft->bytesAll() > 0)
|
||||
prog_all->value = piRoundd(ft->bytesCur() / double(ft->bytesAll()) * 100.);
|
||||
}
|
||||
PIScreenTile::drawEvent(d);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::show(PIFileTransfer * f) {
|
||||
ft = f;
|
||||
if (ft) {
|
||||
conn_name = ft->name();
|
||||
::screen->setDialogTile(this);
|
||||
label_file->content[0].first = "Preparing ...";
|
||||
prog_file->value = prog_all->value = 0;
|
||||
buttons->cur = 0;
|
||||
buttons->setFocus();
|
||||
tm.reset();
|
||||
tme.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::close(bool ok) {
|
||||
buttons->content[0].first = "Pause";
|
||||
ft = 0;
|
||||
::screen->setDialogTile(0);
|
||||
if (!ok) {
|
||||
piCout << "file transfer aborted";
|
||||
showInfo("Error while file transfer, files may be invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::tileEvent(PIScreenTile * t, TileEvent e) {
|
||||
if (t->name() == "fd_buttons") {
|
||||
if (e.type != TileButtons::ButtonSelected || !ft) return;
|
||||
switch (e.data.toInt()) {
|
||||
case 0:
|
||||
if (buttons->content[0].first == "Pause") {
|
||||
buttons->content[0].first = "Resume";
|
||||
ft->pause();
|
||||
} else {
|
||||
buttons->content[0].first = "Pause";
|
||||
ft->resume();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
ft->stop();
|
||||
close();
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Daemon::Daemon(): PIPeer(pisd_prefix + PISystemInfo::instance()->hostname + "_" + PIString::fromNumber(randomi() % 100)) {
|
||||
// setName("Daemon");
|
||||
dtimer.setName("__S__Daemon_timer");
|
||||
mode = rmNone;
|
||||
offset = cur = height = 0;
|
||||
CONNECTU(screen, keyPressed, this, keyEvent)
|
||||
CONNECTU(&dtimer, tickEvent, this, timerEvent)
|
||||
CONNECTU(&fm, tileKey, this, fmKeyEvent)
|
||||
CONNECTU(&fm, actionRequest, this, fmActionRequest)
|
||||
_self = new Remote(self_name);
|
||||
CONNECTU(_self, sendRequest, this, localSend)
|
||||
CONNECTU(_self, receiveFinished, this, closeFileDialog)
|
||||
CONNECTU(_self, sendFinished, this, closeFileDialog)
|
||||
CONNECTU(_self, changeDirFinished, this, dirChanged)
|
||||
localft.setName(self_name);
|
||||
localft.setCRCEnabled(false);
|
||||
CONNECTU(&localft, sendRequest, _self, received)
|
||||
dtimer.addDelimiter(5);
|
||||
dtimer.start(200);
|
||||
|
||||
tile_root = new PIScreenTile();
|
||||
tile_root->direction = Vertical;
|
||||
|
||||
tile_header = new TileSimple("daemon header");
|
||||
tile_header->size_policy = Fixed;
|
||||
|
||||
list_daemons = new TileList("daemons list");
|
||||
list_daemons->hide();
|
||||
|
||||
list_actions = new TileList("actions list");
|
||||
list_actions->hide();
|
||||
list_actions->content << TileList::Row("Information", CellFormat());
|
||||
list_actions->content << TileList::Row("File manager", CellFormat());
|
||||
list_actions->content << TileList::Row("Shell", CellFormat());
|
||||
|
||||
tile_info = new TileSimple("daemon info");
|
||||
tile_info->hide();
|
||||
|
||||
fm.setRemote();
|
||||
tile_fm = fm.tile();
|
||||
tile_fm->hide();
|
||||
|
||||
tile_file_progress = new TileFileProgress();
|
||||
|
||||
tile_shell = new TileTerminal("shell");
|
||||
tile_shell->hide();
|
||||
CONNECTU(tile_shell, resizeRequest, this, shResizeRequest)
|
||||
CONNECTU(tile_shell, keyPressed, this, shKeyEvent)
|
||||
CONNECTU(tile_shell, closeRequest, this, requestCloseShell)
|
||||
CONNECTU(tile_shell, closeRequest, this, escPressed)
|
||||
|
||||
|
||||
tile_root->addTile(tile_header);
|
||||
tile_root->addTile(list_daemons);
|
||||
tile_root->addTile(list_actions);
|
||||
tile_root->addTile(tile_info);
|
||||
tile_root->addTile(tile_fm);
|
||||
tile_root->addTile(tile_shell);
|
||||
|
||||
CONNECTU(screen, tileEvent, this, tileEvent)
|
||||
reinit();
|
||||
inited__ = true;
|
||||
}
|
||||
|
||||
|
||||
Daemon::~Daemon() {
|
||||
requestCloseShell();
|
||||
PIVector<Remote*> rl = remotes.values();
|
||||
piForeach (Remote * r, rl) {
|
||||
r->shellClose();
|
||||
delete r;
|
||||
}
|
||||
remotes.clear();
|
||||
delete _self;
|
||||
}
|
||||
|
||||
|
||||
PIScreenTile * Daemon::tile() const {
|
||||
return tile_root;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::escPressed() {
|
||||
if (mode == rmNone || mode == rmLocalFileManager)
|
||||
menuRequest();
|
||||
else {
|
||||
if (mode > rmSelectMode) {
|
||||
mode = rmSelectMode;
|
||||
screen->lock();
|
||||
tile_info->content.clear();
|
||||
screen->unlock();
|
||||
showActionList();
|
||||
} else
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::shResizeRequest() {
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
PIByteArray ba;
|
||||
ba << int(ShellResizeRequest) << int(tile_shell->width()) << int(tile_shell->height());
|
||||
send(conn_name, ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::shKeyEvent(PIKbdListener::KeyEvent k) {
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
PIByteArray ba;
|
||||
ba << int(ShellKeyEvent) << k;
|
||||
send(conn_name, ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::localSend(const PIString & p_name, const PIByteArray & data) {
|
||||
//piCoutObj << "localSend" << localft.stateString();
|
||||
PIByteArray h; h << int(FileTransfer);
|
||||
PIByteArray ba = data;
|
||||
ba.remove(0, h.size());
|
||||
localft.received(ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::hideAll() {
|
||||
list_actions->hide();
|
||||
tile_info->hide();
|
||||
list_daemons->hide();
|
||||
tile_fm->hide();
|
||||
tile_shell->hide();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::showTile(PIScreenTile * t, const PIString & header) {
|
||||
hideAll();
|
||||
t->show();
|
||||
t->setFocus();
|
||||
tile_header->content.resize(1);
|
||||
tile_header->content[0].first = header;
|
||||
tile_header->content[0].second.flags = Bold;
|
||||
lock();
|
||||
if (!conn_name.isEmpty())
|
||||
tile_header->content[0].first.insert(0, PIString("Daemon \"") + connectedDaemon() + "\": ");
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::fillInfoTile(const Daemon::HostInfo & hi) {
|
||||
screen->lock();
|
||||
tile_info->content.clear();
|
||||
tile_info->content << TileSimple::Row("Exec command: " + hi.execCommand, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" Executed on " + hi.execDateTime.toString(), CellFormat());
|
||||
tile_info->content << TileSimple::Row(" Hostname: " + hi.hostname, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" Username: " + hi.user, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" OS name: " + hi.OS_name, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" OS version: " + hi.OS_version, CellFormat());
|
||||
tile_info->content << TileSimple::Row("Architecture: " + hi.architecture, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" CPU count: " + PIString::fromNumber(hi.processorsCount), CellFormat());
|
||||
screen->unlock();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::tileEvent(PIScreenTile * t, TileEvent e) {
|
||||
if (t == list_daemons) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
connectToDaemon(list_daemons->content[e.data.toInt()].first);
|
||||
showActionList();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (t == list_actions) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
switch (e.data.toInt()) {
|
||||
case 0:
|
||||
mode = rmInformation;
|
||||
showTile(tile_info, "Information");
|
||||
break;
|
||||
case 1:
|
||||
mode = rmFileManager;
|
||||
showTile(tile_fm, "File manager");
|
||||
requestChDir(".");
|
||||
break;
|
||||
case 2:
|
||||
mode = rmShell;
|
||||
showTile(tile_shell, "Shell");
|
||||
requestOpenShell();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::keyEvent(PIKbdListener::KeyEvent key) {
|
||||
if (!tile_root->visible) return;
|
||||
if (screen->dialogTile()) return;
|
||||
switch (key.key) {
|
||||
case PIKbdListener::Esc:
|
||||
escPressed();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::fmKeyEvent(PIKbdListener::KeyEvent key) {
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
// piCoutObj << key.key << key.modifiers;
|
||||
switch (key.key) {
|
||||
case PIKbdListener::Return:
|
||||
{
|
||||
PIFile::FileInfo fi = fm.currentRemoteEntry();
|
||||
if (!fi.isDir()) break;
|
||||
requestChDir(fi.name());
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
requestChDir(".");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::fmActionRequest(bool remote_tile, FileManager::Action type, PIVariant data) {
|
||||
Remote * r = 0;
|
||||
r = remotes.value(conn_name, 0);
|
||||
if (!r && type != FileManager::LocalCopy && type != FileManager::LocalCrypt) return;
|
||||
switch (type) {
|
||||
case FileManager::Copy:
|
||||
if (remote_tile) {
|
||||
PIByteArray ba;
|
||||
//piCout << fm.selectedRemote();
|
||||
ba << int(CopyFiles) << fm.selectedRemote();
|
||||
r->ft.setDirectory(fm.localDir());
|
||||
send(conn_name, ba);
|
||||
tile_file_progress->rec = true;
|
||||
tile_file_progress->show(&(r->ft));
|
||||
} else {
|
||||
r->sendFiles(fm.localDir() + PIDir::separator, data.toStringList());
|
||||
tile_file_progress->rec = false;
|
||||
tile_file_progress->show(&(r->ft));
|
||||
}
|
||||
break;
|
||||
case FileManager::Remove:
|
||||
if (remote_tile) {
|
||||
PIByteArray ba;
|
||||
ba << int(RemoveFiles) << fm.selectedRemote();
|
||||
send(conn_name, ba);
|
||||
}
|
||||
break;
|
||||
case FileManager::MkDir:
|
||||
if (remote_tile) {
|
||||
PIByteArray ba;
|
||||
ba << int(MkDir) << data.toString();
|
||||
send(conn_name, ba);
|
||||
}
|
||||
break;
|
||||
case FileManager::LocalCopy:
|
||||
//piCoutObj << "localCopy";
|
||||
if (remote_tile) {
|
||||
localft.setDirectory(fm.localDir());
|
||||
_self->sendFiles(fm.remoteDir() + PIDir::separator, data.toStringList());
|
||||
} else {
|
||||
localft.setDirectory(fm.remoteDir());
|
||||
_self->sendFiles(fm.localDir() + PIDir::separator, data.toStringList());
|
||||
}
|
||||
tile_file_progress->rec = false;
|
||||
tile_file_progress->show(&(_self->ft));
|
||||
case FileManager::Crypt:
|
||||
if (remote_tile) {
|
||||
PIByteArray ba;
|
||||
ba << int(CryptFiles) << fm.selectedRemote();
|
||||
send(conn_name, ba);
|
||||
} else {
|
||||
_self->dir_my.setDir(fm.localDir());
|
||||
_self->cryptFiles(data.toStringList());
|
||||
}
|
||||
break;
|
||||
case FileManager::LocalCrypt:
|
||||
piCoutObj << "LocalCrypt";
|
||||
if (remote_tile) {
|
||||
_self->dir_my.setDir(fm.remoteDir());
|
||||
} else {
|
||||
_self->dir_my.setDir(fm.localDir());
|
||||
}
|
||||
_self->cryptFiles(data.toStringList());
|
||||
break;
|
||||
default: break;
|
||||
};
|
||||
//piCout << remote_tile << type << data;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::timerEvent(void * _d, int delim) {
|
||||
screen->lock();
|
||||
list_daemons->content.clear();
|
||||
availableDaemons();
|
||||
piForeachC (PIString & i, available_daemons)
|
||||
list_daemons->content << TileList::Row(i, CellFormat());
|
||||
screen->unlock();
|
||||
if (delim == 5 && mode == rmInformation) {
|
||||
if (conn_name.isEmpty()) return;
|
||||
PIByteArray ba; ba << int(RequestHostInfo);
|
||||
send(conn_name, ba);
|
||||
//std::cout << "send " << std::hex << ba;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PIStringList Daemon::availableDaemons() {
|
||||
available_daemons.clear();
|
||||
lock();
|
||||
piForeachC (PIPeer::PeerInfo & p, allPeers()) {
|
||||
if (!p.name.startsWith(pisd_prefix)) continue;
|
||||
available_daemons << p.name.mid(6);
|
||||
}
|
||||
unlock();
|
||||
return available_daemons;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::connectToDaemon(const PIString & dn) {
|
||||
if (dn.isEmpty()) return;
|
||||
conn_name = pisd_prefix + dn;
|
||||
mode = rmSelectMode;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::disconnect() {
|
||||
screen->enableExitCapture(PIKbdListener::F10);
|
||||
conn_name.clear();
|
||||
mode = rmNone;
|
||||
showMainList();
|
||||
}
|
||||
|
||||
|
||||
PIString Daemon::connectedDaemon() const {
|
||||
return conn_name.mid(6);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::peerConnected(const PIString & p_name) {
|
||||
while (!inited__) piMSleep(PIP_MIN_MSLEEP*5);
|
||||
if (!p_name.startsWith(pisd_prefix)) return;
|
||||
Remote * r = new Remote(p_name);
|
||||
piCoutObj << "peer connected" << p_name;
|
||||
CONNECTU(r, sendRequest, this, sendRequest)
|
||||
CONNECTU(r, receiveFinished, this, filesReceived)
|
||||
CONNECTU(r, sendFinished, this, filesSended)
|
||||
CONNECTU(r, changeDirFinished, this, dirChanged)
|
||||
PIMutexLocker ml2(remote_mutex);
|
||||
remotes.insert(p_name, r);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::peerDisconnected(const PIString & p_name) {
|
||||
while (!inited__) piMSleep(PIP_MIN_MSLEEP*5);
|
||||
piCoutObj << "peer disconnect" << p_name;
|
||||
if (p_name == conn_name) {
|
||||
disconnect();
|
||||
}
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
Remote * dt = remotes.value(p_name, 0);
|
||||
if (!dt) return;
|
||||
dt->shellClose();
|
||||
if (tile_file_progress->ft == &(dt->ft)) {
|
||||
tile_file_progress->close(false);
|
||||
}
|
||||
remotes.remove(p_name);
|
||||
delete dt;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::filesReceived(const PIString & p_name, bool ok) {
|
||||
if (ok) {
|
||||
piCout << "files received from" << p_name;
|
||||
} else {
|
||||
piCout << "warning, files not received fromsended" << p_name;
|
||||
}
|
||||
closeFileDialog(p_name, ok);
|
||||
Remote * r = remotes.value(p_name, 0);
|
||||
if (!r) return;
|
||||
r->updateDir();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::filesSended(const PIString & p_name, bool ok) {
|
||||
if (ok) {
|
||||
piCout << "files sended to" << p_name;
|
||||
} else {
|
||||
piCout << "warning, files not sended to" << p_name;
|
||||
}
|
||||
closeFileDialog(p_name, ok);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::dirChanged(const PIString & p_name, const PIString & dir) {
|
||||
if (p_name == self_name) {
|
||||
fm.clearSelectionLocal();
|
||||
fm.clearSelectionRemote();
|
||||
fm.updateLocalDir();
|
||||
fm.updateRemoteDir();
|
||||
return;
|
||||
}
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
Remote * r = remotes.value(p_name, 0);
|
||||
if (!r) return;
|
||||
if (r->dir_my.absolutePath() != dir) return;
|
||||
sendDirToRemote(r);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::closeFileDialog(const PIString & p_name, bool ok) {
|
||||
//piCout << "CLOSE" << tile_file_progress->conn_name << name << ok;
|
||||
if (p_name == self_name) {
|
||||
tile_file_progress->close(ok);
|
||||
fm.clearSelectionLocal();
|
||||
fm.clearSelectionRemote();
|
||||
fm.updateLocalDir();
|
||||
fm.updateRemoteDir();
|
||||
return;
|
||||
}
|
||||
//piCout << "file transfer with" << p_name << (ok ? "success" : "failure");
|
||||
if (tile_file_progress->conn_name != p_name) return;
|
||||
tile_file_progress->close(ok);
|
||||
if (tile_file_progress->rec) {
|
||||
fm.remoteTile()->setFocus();
|
||||
fm.clearSelectionRemote();
|
||||
fm.updateLocalDir();
|
||||
} else {
|
||||
fm.localTile()->setFocus();
|
||||
fm.clearSelectionLocal();
|
||||
requestChDir(".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::dataReceived(const PIString & from, const PIByteArray & data) {
|
||||
// piCout << "rec" << data.size();
|
||||
if (data.size() < 4) return;
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
// piCout << "lock in dataReceived";
|
||||
PIByteArray ba(data), rba;
|
||||
Remote * r = remotes.value(from);
|
||||
PIString dir;
|
||||
int type; ba >> type;
|
||||
//piCout << "rec from " << from << type << r;
|
||||
switch (type) {
|
||||
case RequestHostInfo:
|
||||
makeMyHostInfo();
|
||||
rba << int(ReplyHostInfo) << info_my;
|
||||
break;
|
||||
case RequestChangeDir:
|
||||
if (!r) break;
|
||||
ba >> dir;
|
||||
r->dir_my.cd(dir);
|
||||
r->ft.setDirectory(r->dir_my);
|
||||
//piCout << "store to" << r->dir_my.absolutePath();
|
||||
piCoutObj << "cd to" << r->dir_my.absolutePath();
|
||||
r->updateDir();
|
||||
break;
|
||||
case ReplyHostInfo:
|
||||
ba >> info_other;
|
||||
makeOtherHostInfo();
|
||||
fillInfoTile(info_other);
|
||||
break;
|
||||
case ReplyChangeDir:
|
||||
if (!r) break;
|
||||
{
|
||||
PIVector<PIFile::FileInfo> fil;
|
||||
ba >> dir >> fil;
|
||||
fm.setRemoteDir(dir);
|
||||
fm.setRemoteContent(fil);
|
||||
fm.remoteRestoreDir();
|
||||
}
|
||||
break;
|
||||
case CopyFiles:
|
||||
if (!r) return;
|
||||
if (r->isRunning()) return;
|
||||
{
|
||||
PIStringList files;
|
||||
ba >> files;
|
||||
//piCout << "send" << files << "from" << r->dir_my.absolutePath();
|
||||
r->sendFiles(r->dir_my.absolutePath() + PIDir::separator, files);
|
||||
}
|
||||
break;
|
||||
case RemoveFiles:
|
||||
if (!r) return;
|
||||
if (r->isRunning()) return;
|
||||
{
|
||||
PIStringList files;
|
||||
ba >> files;
|
||||
//piCout << "send" << files << "from" << r->dir_my.absolutePath();
|
||||
r->removeFiles(files);
|
||||
}
|
||||
break;
|
||||
case MkDir:
|
||||
if (!r) return;
|
||||
{
|
||||
PIString dn;
|
||||
ba >> dn;
|
||||
//piCout << "send" << files << "from" << r->dir_my.absolutePath();
|
||||
r->makeDir(dn);
|
||||
}
|
||||
break;
|
||||
case FileTransfer:
|
||||
if (r) r->received(ba);
|
||||
break;
|
||||
case CryptFiles:
|
||||
if (!r) return;
|
||||
if (r->isRunning()) return;
|
||||
{
|
||||
PIStringList files;
|
||||
ba >> files;
|
||||
r->cryptFiles(files);
|
||||
}
|
||||
break;
|
||||
case ShellOpen:
|
||||
if (!r) return;
|
||||
r->shellOpen();
|
||||
break;
|
||||
case ShellClose:
|
||||
if (!r) return;
|
||||
r->shellClose();
|
||||
break;
|
||||
case ShellContent: {
|
||||
if (!r) return;
|
||||
PIVector<PIVector<PIScreenTypes::Cell> > cells;
|
||||
ba >> cells;
|
||||
tile_shell->setContent(cells);
|
||||
} break;
|
||||
case ShellResizeRequest: {
|
||||
if (!r) return;
|
||||
int w, h;
|
||||
ba >> w >> h;
|
||||
r->shellResize(w, h);
|
||||
} break;
|
||||
case ShellKeyEvent: {
|
||||
if (!r) return;
|
||||
PIKbdListener::KeyEvent k;
|
||||
ba >> k;
|
||||
r->shellKeySend(k);
|
||||
} break;
|
||||
};
|
||||
if (!rba.isEmpty()) send(from, rba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::sendDirToRemote(Remote * r) {
|
||||
if (!r) return;
|
||||
PIVector<PIFile::FileInfo> fil = r->my_filelist;
|
||||
PIByteArray ba;
|
||||
ba << int(ReplyChangeDir) << r->dir_my.absolutePath() << fil;
|
||||
send(r->name(), ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::requestOpenShell() {
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
screen->disableExitCapture();
|
||||
PIByteArray ba;
|
||||
ba << int(ShellOpen);
|
||||
send(conn_name, ba);
|
||||
executeQueued(this, "shResizeRequest");
|
||||
}
|
||||
|
||||
|
||||
void Daemon::requestCloseShell() {
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
screen->enableExitCapture(PIKbdListener::F10);
|
||||
PIByteArray ba;
|
||||
ba << int(ShellClose);
|
||||
send(conn_name, ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::makeMyHostInfo() {
|
||||
info_my.execCommand = PISystemInfo::instance()->execCommand;
|
||||
info_my.hostname = PISystemInfo::instance()->hostname;
|
||||
info_my.user = PISystemInfo::instance()->user;
|
||||
info_my.OS_name = PISystemInfo::instance()->OS_name;
|
||||
info_my.OS_version = PISystemInfo::instance()->OS_version;
|
||||
info_my.architecture = PISystemInfo::instance()->architecture;
|
||||
info_my.execDateTime = PISystemInfo::instance()->execDateTime;
|
||||
info_my.processorsCount = PISystemInfo::instance()->processorsCount;
|
||||
info_my.ID = sys_mon.statistic().ID;
|
||||
info_my.threads = sys_mon.statistic().threads;
|
||||
info_my.priority = sys_mon.statistic().priority;
|
||||
info_my.physical_memsize = sys_mon.statistic().physical_memsize;
|
||||
info_my.share_memsize = sys_mon.statistic().share_memsize;
|
||||
info_my.cpu_load_system = sys_mon.statistic().cpu_load_system;
|
||||
info_my.cpu_load_user = sys_mon.statistic().cpu_load_user;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::makeOtherHostInfo() {
|
||||
PISystemMonitor::ProcessStats ps(sys_mon_other.statistic());
|
||||
ps.ID = info_other.ID;
|
||||
ps.threads = info_other.threads;
|
||||
ps.priority = info_other.priority;
|
||||
ps.physical_memsize = info_other.physical_memsize;
|
||||
ps.share_memsize = info_other.share_memsize;
|
||||
ps.cpu_load_system = info_other.cpu_load_system;
|
||||
ps.cpu_load_user = info_other.cpu_load_user;
|
||||
sys_mon_other.setStatistic(ps);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::requestChDir(const PIString & d) {
|
||||
if (d.isEmpty()) return;
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
fm.remoteSaveDir();
|
||||
fm.readingRemote();
|
||||
PIByteArray ba;
|
||||
ba << int(RequestChangeDir) << d;
|
||||
send(conn_name, ba);
|
||||
}
|
||||
#include "daemon.h"
|
||||
|
||||
#include "picrypt.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "shared.h"
|
||||
|
||||
const char self_name[] = "__self__";
|
||||
extern PIScreen * screen;
|
||||
extern PISystemMonitor sys_mon;
|
||||
|
||||
Daemon::Remote::Remote(const PIString & n): PIThread() {
|
||||
setName(n);
|
||||
term = 0;
|
||||
ft.setName(n);
|
||||
ft.setPacketSize(3984);
|
||||
ft.setCRCEnabled(false);
|
||||
CONNECTU(&ft, sendRequest, this, ftSendRequest)
|
||||
CONNECTU(&ft, receiveFilesFinished, this, ftReceived)
|
||||
CONNECTU(&ft, sendFilesFinished, this, ftSended)
|
||||
CONNECTU(&term_timer, tickEvent, this, termTimerTick)
|
||||
dir_my = PIDir::current();
|
||||
}
|
||||
|
||||
|
||||
Daemon::Remote::~Remote() {
|
||||
shellClose();
|
||||
ft.stop();
|
||||
stopAndWait();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::shellOpen() {
|
||||
if (term) return;
|
||||
piCoutObj << "shell open";
|
||||
term = new PITerminal();
|
||||
term->initialize();
|
||||
term_timer.start(50);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::shellClose() {
|
||||
if (!term) return;
|
||||
piCoutObj << "shell close";
|
||||
term_timer.stop();
|
||||
term->destroy();
|
||||
delete term;
|
||||
term = 0;
|
||||
// piCoutObj << "shellClose ok";
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::shellResize(int w, int h) {
|
||||
if (!term) return;
|
||||
term->resize(w, h);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::shellKeySend(PIKbdListener::KeyEvent k) {
|
||||
if (!term) return;
|
||||
term->write(k);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::termTimerTick() {
|
||||
if (!term) return;
|
||||
PIVector<PIVector<PIScreenTypes::Cell>> cells = term->content();
|
||||
if (pcells == cells) return;
|
||||
pcells = cells;
|
||||
PIByteArray ba;
|
||||
ba << int(ShellContent) << cells;
|
||||
// piCout << ba.size_s() << pcells.back().back().symbol.unicode16Code() << cells.back().back().symbol.unicode16Code();
|
||||
sendRequest(name(), ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::startAction(Daemon::PacketType a, const PIString & dir, const PIStringList & fl) {
|
||||
_fl = fl;
|
||||
if (!dir.isEmpty())
|
||||
piForeach(PIString & s, _fl)
|
||||
s.prepend(dir);
|
||||
// piCout << "send" << _fl;
|
||||
action = a;
|
||||
startOnce();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::run() {
|
||||
PIDir d(dir_my);
|
||||
switch (action) {
|
||||
case CopyFiles: ft.send(_fl); break;
|
||||
case RemoveFiles:
|
||||
::removeFiles(d, _fl);
|
||||
updateDirEntries();
|
||||
changeDirFinished(name(), d.absolutePath());
|
||||
break;
|
||||
case RequestChangeDir:
|
||||
updateDirEntries();
|
||||
changeDirFinished(name(), d.absolutePath());
|
||||
break;
|
||||
case MkDir:
|
||||
if (!_fl.isEmpty()) PIDir::make(d.absolutePath() + PIDir::separator + _fl.at(0));
|
||||
updateDirEntries();
|
||||
changeDirFinished(name(), d.absolutePath());
|
||||
break;
|
||||
case CryptFiles:
|
||||
piCoutObj << "CryptFiles";
|
||||
if (!_fl.isEmpty()) {
|
||||
PIString p = askUserInput("Password:");
|
||||
::cryptFiles(d, _fl, PICrypt::hash(p));
|
||||
}
|
||||
updateDirEntries();
|
||||
changeDirFinished(name(), d.absolutePath());
|
||||
break;
|
||||
default: break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void Daemon::Remote::updateDirEntries() {
|
||||
// piCout << dir_my;
|
||||
if (!dir_my.isExists()) dir_my = PIDir::current();
|
||||
my_filelist = dir_my.entries();
|
||||
piForeach(PIFile::FileInfo & f, my_filelist)
|
||||
f.path = f.name();
|
||||
}
|
||||
|
||||
|
||||
Daemon::TileFileProgress::TileFileProgress(): PIScreenTile() {
|
||||
size_policy = PIScreenTypes::Fixed;
|
||||
ft = 0;
|
||||
rec = false;
|
||||
setMargins(1, 1, 1, 1);
|
||||
spacing = 1;
|
||||
back_format.color_back = Yellow;
|
||||
label_file = new TileSimple();
|
||||
label_speed = new TileSimple();
|
||||
label_cnt = new TileSimple();
|
||||
prog_file = new TileProgress();
|
||||
prog_all = new TileProgress();
|
||||
buttons = new TileButtons("fd_buttons");
|
||||
buttons->content << TileButtons::Button("Pause", CellFormat());
|
||||
buttons->content << TileButtons::Button("Cancel", CellFormat());
|
||||
label_file->content.resize(1);
|
||||
label_speed->content.resize(1);
|
||||
label_cnt->content.resize(1);
|
||||
buttons->back_format.color_back = Yellow;
|
||||
label_file->back_format.color_back = label_speed->back_format.color_back = label_cnt->back_format.color_back = Yellow;
|
||||
label_file->content[0].second = label_speed->content[0].second = label_cnt->content[0].second = CellFormat(Black, Transparent);
|
||||
addTile(label_file);
|
||||
addTile(label_speed);
|
||||
addTile(label_cnt);
|
||||
addTile(prog_file);
|
||||
addTile(prog_all);
|
||||
addTile(buttons);
|
||||
CONNECTU((::screen), tileEvent, this, tileEvent)
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::resizeEvent(int w, int h) {
|
||||
PIScreenTile::resizeEvent(w, h);
|
||||
w = ::screen->windowWidth() / 1.4;
|
||||
minimumWidth = maximumWidth = w;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::sizeHint(int & w, int & h) const {
|
||||
PIScreenTile::sizeHint(w, h);
|
||||
w = ::screen->windowWidth() / 1.4;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::drawEvent(PIScreenDrawer * d) {
|
||||
if (ft) {
|
||||
label_file->content[0].first = ft->stateString() + " " + ft->curFile();
|
||||
if (!label_file->content[0].first.isEmpty()) label_file->content[0].first[0] = label_file->content[0].first[0].toUpper();
|
||||
PIString spd("Speed: "), cnt;
|
||||
if (ft->isReceiving())
|
||||
spd = ft->diagnostic().receiveSpeed();
|
||||
else
|
||||
spd = ft->diagnostic().sendSpeed().expandRightTo(10, ' ');
|
||||
spd += " ETA: ";
|
||||
if (!ft->isReceiving() && !ft->isSending()) {
|
||||
tm.reset();
|
||||
spd += "-";
|
||||
} else {
|
||||
double el = tm.elapsed_s();
|
||||
int cb = ft->bytesCur();
|
||||
if ((el <= 0.) || (cb <= 0))
|
||||
spd += "-";
|
||||
else {
|
||||
double s = (el / cb) * (ft->bytesAll() - cb);
|
||||
spd += readableTime(PITime::fromSystemTime(PISystemTime::fromSeconds(s)));
|
||||
}
|
||||
}
|
||||
spd += " Elapsed: " + readableTime(PITime::fromSystemTime(PISystemTime::fromSeconds(tme.elapsed_s())));
|
||||
label_speed->content[0].first = spd;
|
||||
cnt = "File: " + PIString::readableSize(ft->bytesFileCur()).expandLeftTo(8, ' ');
|
||||
cnt += " / " + PIString::readableSize(ft->bytesFileAll()).expandLeftTo(8, ' ');
|
||||
cnt += " All: " + PIString::readableSize(ft->bytesCur()).expandLeftTo(8, ' ');
|
||||
cnt += " / " + PIString::readableSize(ft->bytesAll()).expandLeftTo(8, ' ');
|
||||
label_cnt->content[0].first = cnt;
|
||||
if (ft->bytesFileAll() > 0) prog_file->value = piRoundd(ft->bytesFileCur() / double(ft->bytesFileAll()) * 100.);
|
||||
if (ft->bytesAll() > 0) prog_all->value = piRoundd(ft->bytesCur() / double(ft->bytesAll()) * 100.);
|
||||
}
|
||||
PIScreenTile::drawEvent(d);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::show(PIFileTransfer * f) {
|
||||
ft = f;
|
||||
if (ft) {
|
||||
conn_name = ft->name();
|
||||
::screen->setDialogTile(this);
|
||||
label_file->content[0].first = "Preparing ...";
|
||||
prog_file->value = prog_all->value = 0;
|
||||
buttons->cur = 0;
|
||||
buttons->setFocus();
|
||||
tm.reset();
|
||||
tme.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::close(bool ok) {
|
||||
buttons->content[0].first = "Pause";
|
||||
ft = 0;
|
||||
::screen->setDialogTile(0);
|
||||
if (!ok) {
|
||||
piCout << "file transfer aborted";
|
||||
showInfo("Error while file transfer, files may be invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::TileFileProgress::tileEvent(PIScreenTile * t, TileEvent e) {
|
||||
if (t->name() == "fd_buttons") {
|
||||
if (e.type != TileButtons::ButtonSelected || !ft) return;
|
||||
switch (e.data.toInt()) {
|
||||
case 0:
|
||||
if (buttons->content[0].first == "Pause") {
|
||||
buttons->content[0].first = "Resume";
|
||||
ft->pause();
|
||||
} else {
|
||||
buttons->content[0].first = "Pause";
|
||||
ft->resume();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
ft->stop();
|
||||
close();
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Daemon::Daemon(): PIPeer(pisd_prefix + PISystemInfo::instance()->hostname + "_" + PIString::fromNumber(randomi() % 100)) {
|
||||
// setName("Daemon");
|
||||
dtimer.setName("__S__Daemon_timer");
|
||||
mode = rmNone;
|
||||
offset = cur = height = 0;
|
||||
CONNECTU(screen, keyPressed, this, keyEvent)
|
||||
CONNECTU(&dtimer, tickEvent, this, timerEvent)
|
||||
CONNECTU(&fm, tileKey, this, fmKeyEvent)
|
||||
CONNECTU(&fm, actionRequest, this, fmActionRequest)
|
||||
_self = new Remote(self_name);
|
||||
CONNECTU(_self, sendRequest, this, localSend)
|
||||
CONNECTU(_self, receiveFinished, this, closeFileDialog)
|
||||
CONNECTU(_self, sendFinished, this, closeFileDialog)
|
||||
CONNECTU(_self, changeDirFinished, this, dirChanged)
|
||||
localft.setName(self_name);
|
||||
localft.setCRCEnabled(false);
|
||||
CONNECTU(&localft, sendRequest, _self, received)
|
||||
dtimer.addDelimiter(5);
|
||||
dtimer.start(200);
|
||||
|
||||
tile_root = new PIScreenTile();
|
||||
tile_root->direction = Vertical;
|
||||
|
||||
tile_header = new TileSimple("daemon header");
|
||||
tile_header->size_policy = Fixed;
|
||||
|
||||
list_daemons = new TileList("daemons list");
|
||||
list_daemons->hide();
|
||||
|
||||
list_actions = new TileList("actions list");
|
||||
list_actions->hide();
|
||||
list_actions->content << TileList::Row("Information", CellFormat());
|
||||
list_actions->content << TileList::Row("File manager", CellFormat());
|
||||
list_actions->content << TileList::Row("Shell", CellFormat());
|
||||
|
||||
tile_info = new TileSimple("daemon info");
|
||||
tile_info->hide();
|
||||
|
||||
fm.setRemote();
|
||||
tile_fm = fm.tile();
|
||||
tile_fm->hide();
|
||||
|
||||
tile_file_progress = new TileFileProgress();
|
||||
|
||||
tile_shell = new TileTerminal("shell");
|
||||
tile_shell->hide();
|
||||
CONNECTU(tile_shell, resizeRequest, this, shResizeRequest)
|
||||
CONNECTU(tile_shell, keyPressed, this, shKeyEvent)
|
||||
CONNECTU(tile_shell, closeRequest, this, requestCloseShell)
|
||||
CONNECTU(tile_shell, closeRequest, this, escPressed)
|
||||
|
||||
|
||||
tile_root->addTile(tile_header);
|
||||
tile_root->addTile(list_daemons);
|
||||
tile_root->addTile(list_actions);
|
||||
tile_root->addTile(tile_info);
|
||||
tile_root->addTile(tile_fm);
|
||||
tile_root->addTile(tile_shell);
|
||||
|
||||
CONNECTU(screen, tileEvent, this, tileEvent)
|
||||
reinit();
|
||||
inited__ = true;
|
||||
}
|
||||
|
||||
|
||||
Daemon::~Daemon() {
|
||||
requestCloseShell();
|
||||
PIVector<Remote *> rl = remotes.values();
|
||||
piForeach(Remote * r, rl) {
|
||||
r->shellClose();
|
||||
delete r;
|
||||
}
|
||||
remotes.clear();
|
||||
delete _self;
|
||||
}
|
||||
|
||||
|
||||
PIScreenTile * Daemon::tile() const {
|
||||
return tile_root;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::escPressed() {
|
||||
if (mode == rmNone || mode == rmLocalFileManager)
|
||||
menuRequest();
|
||||
else {
|
||||
if (mode > rmSelectMode) {
|
||||
mode = rmSelectMode;
|
||||
screen->lock();
|
||||
tile_info->content.clear();
|
||||
screen->unlock();
|
||||
showActionList();
|
||||
} else
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::shResizeRequest() {
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
PIByteArray ba;
|
||||
ba << int(ShellResizeRequest) << int(tile_shell->width()) << int(tile_shell->height());
|
||||
send(conn_name, ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::shKeyEvent(PIKbdListener::KeyEvent k) {
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
PIByteArray ba;
|
||||
ba << int(ShellKeyEvent) << k;
|
||||
send(conn_name, ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::localSend(const PIString & p_name, const PIByteArray & data) {
|
||||
// piCoutObj << "localSend" << localft.stateString();
|
||||
PIByteArray h;
|
||||
h << int(FileTransfer);
|
||||
PIByteArray ba = data;
|
||||
ba.remove(0, h.size());
|
||||
localft.received(ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::hideAll() {
|
||||
list_actions->hide();
|
||||
tile_info->hide();
|
||||
list_daemons->hide();
|
||||
tile_fm->hide();
|
||||
tile_shell->hide();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::showTile(PIScreenTile * t, const PIString & header) {
|
||||
hideAll();
|
||||
t->show();
|
||||
t->setFocus();
|
||||
tile_header->content.resize(1);
|
||||
tile_header->content[0].first = header;
|
||||
tile_header->content[0].second.flags = Bold;
|
||||
lock();
|
||||
if (!conn_name.isEmpty()) tile_header->content[0].first.insert(0, PIString("Daemon \"") + connectedDaemon() + "\": ");
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::fillInfoTile(const Daemon::HostInfo & hi) {
|
||||
screen->lock();
|
||||
tile_info->content.clear();
|
||||
tile_info->content << TileSimple::Row("Exec command: " + hi.execCommand, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" Executed on " + hi.execDateTime.toString(), CellFormat());
|
||||
tile_info->content << TileSimple::Row(" Hostname: " + hi.hostname, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" Username: " + hi.user, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" OS name: " + hi.OS_name, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" OS version: " + hi.OS_version, CellFormat());
|
||||
tile_info->content << TileSimple::Row("Architecture: " + hi.architecture, CellFormat());
|
||||
tile_info->content << TileSimple::Row(" CPU count: " + PIString::fromNumber(hi.processorsCount), CellFormat());
|
||||
screen->unlock();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::tileEvent(PIScreenTile * t, TileEvent e) {
|
||||
if (t == list_daemons) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
connectToDaemon(list_daemons->content[e.data.toInt()].first);
|
||||
showActionList();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (t == list_actions) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
switch (e.data.toInt()) {
|
||||
case 0:
|
||||
mode = rmInformation;
|
||||
showTile(tile_info, "Information");
|
||||
break;
|
||||
case 1:
|
||||
mode = rmFileManager;
|
||||
showTile(tile_fm, "File manager");
|
||||
requestChDir(".");
|
||||
break;
|
||||
case 2:
|
||||
mode = rmShell;
|
||||
showTile(tile_shell, "Shell");
|
||||
requestOpenShell();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::keyEvent(PIKbdListener::KeyEvent key) {
|
||||
if (!tile_root->visible) return;
|
||||
if (screen->dialogTile()) return;
|
||||
switch (key.key) {
|
||||
case PIKbdListener::Esc: escPressed(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::fmKeyEvent(PIKbdListener::KeyEvent key) {
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
// piCoutObj << key.key << key.modifiers;
|
||||
switch (key.key) {
|
||||
case PIKbdListener::Return: {
|
||||
PIFile::FileInfo fi = fm.currentRemoteEntry();
|
||||
if (!fi.isDir()) break;
|
||||
requestChDir(fi.name());
|
||||
} break;
|
||||
case 'R': requestChDir("."); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::fmActionRequest(bool remote_tile, FileManager::Action type, PIVariant data) {
|
||||
Remote * r = 0;
|
||||
r = remotes.value(conn_name, 0);
|
||||
if (!r && type != FileManager::LocalCopy && type != FileManager::LocalCrypt) return;
|
||||
switch (type) {
|
||||
case FileManager::Copy:
|
||||
if (remote_tile) {
|
||||
PIByteArray ba;
|
||||
// piCout << fm.selectedRemote();
|
||||
ba << int(CopyFiles) << fm.selectedRemote();
|
||||
r->ft.setDirectory(fm.localDir());
|
||||
send(conn_name, ba);
|
||||
tile_file_progress->rec = true;
|
||||
tile_file_progress->show(&(r->ft));
|
||||
} else {
|
||||
r->sendFiles(fm.localDir() + PIDir::separator, data.toStringList());
|
||||
tile_file_progress->rec = false;
|
||||
tile_file_progress->show(&(r->ft));
|
||||
}
|
||||
break;
|
||||
case FileManager::Remove:
|
||||
if (remote_tile) {
|
||||
PIByteArray ba;
|
||||
ba << int(RemoveFiles) << fm.selectedRemote();
|
||||
send(conn_name, ba);
|
||||
}
|
||||
break;
|
||||
case FileManager::MkDir:
|
||||
if (remote_tile) {
|
||||
PIByteArray ba;
|
||||
ba << int(MkDir) << data.toString();
|
||||
send(conn_name, ba);
|
||||
}
|
||||
break;
|
||||
case FileManager::LocalCopy:
|
||||
// piCoutObj << "localCopy";
|
||||
if (remote_tile) {
|
||||
localft.setDirectory(fm.localDir());
|
||||
_self->sendFiles(fm.remoteDir() + PIDir::separator, data.toStringList());
|
||||
} else {
|
||||
localft.setDirectory(fm.remoteDir());
|
||||
_self->sendFiles(fm.localDir() + PIDir::separator, data.toStringList());
|
||||
}
|
||||
tile_file_progress->rec = false;
|
||||
tile_file_progress->show(&(_self->ft));
|
||||
case FileManager::Crypt:
|
||||
if (remote_tile) {
|
||||
PIByteArray ba;
|
||||
ba << int(CryptFiles) << fm.selectedRemote();
|
||||
send(conn_name, ba);
|
||||
} else {
|
||||
_self->dir_my.setDir(fm.localDir());
|
||||
_self->cryptFiles(data.toStringList());
|
||||
}
|
||||
break;
|
||||
case FileManager::LocalCrypt:
|
||||
piCoutObj << "LocalCrypt";
|
||||
if (remote_tile) {
|
||||
_self->dir_my.setDir(fm.remoteDir());
|
||||
} else {
|
||||
_self->dir_my.setDir(fm.localDir());
|
||||
}
|
||||
_self->cryptFiles(data.toStringList());
|
||||
break;
|
||||
default: break;
|
||||
};
|
||||
// piCout << remote_tile << type << data;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::timerEvent(void * _d, int delim) {
|
||||
screen->lock();
|
||||
list_daemons->content.clear();
|
||||
availableDaemons();
|
||||
piForeachC(PIString & i, available_daemons)
|
||||
list_daemons->content << TileList::Row(i, CellFormat());
|
||||
screen->unlock();
|
||||
if (delim == 5 && mode == rmInformation) {
|
||||
if (conn_name.isEmpty()) return;
|
||||
PIByteArray ba;
|
||||
ba << int(RequestHostInfo);
|
||||
send(conn_name, ba);
|
||||
// std::cout << "send " << std::hex << ba;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PIStringList Daemon::availableDaemons() {
|
||||
available_daemons.clear();
|
||||
lock();
|
||||
piForeachC(PIPeer::PeerInfo & p, allPeers()) {
|
||||
if (!p.name.startsWith(pisd_prefix)) continue;
|
||||
available_daemons << p.name.mid(6);
|
||||
}
|
||||
unlock();
|
||||
return available_daemons;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::connectToDaemon(const PIString & dn) {
|
||||
if (dn.isEmpty()) return;
|
||||
conn_name = pisd_prefix + dn;
|
||||
mode = rmSelectMode;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::disconnect() {
|
||||
screen->enableExitCapture(PIKbdListener::F10);
|
||||
conn_name.clear();
|
||||
mode = rmNone;
|
||||
showMainList();
|
||||
}
|
||||
|
||||
|
||||
PIString Daemon::connectedDaemon() const {
|
||||
return conn_name.mid(6);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::peerConnected(const PIString & p_name) {
|
||||
while (!inited__)
|
||||
piMSleep(PIP_MIN_MSLEEP * 5);
|
||||
if (!p_name.startsWith(pisd_prefix)) return;
|
||||
Remote * r = new Remote(p_name);
|
||||
piCoutObj << "peer connected" << p_name;
|
||||
CONNECTU(r, sendRequest, this, sendRequest)
|
||||
CONNECTU(r, receiveFinished, this, filesReceived)
|
||||
CONNECTU(r, sendFinished, this, filesSended)
|
||||
CONNECTU(r, changeDirFinished, this, dirChanged)
|
||||
PIMutexLocker ml2(remote_mutex);
|
||||
remotes.insert(p_name, r);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::peerDisconnected(const PIString & p_name) {
|
||||
while (!inited__)
|
||||
piMSleep(PIP_MIN_MSLEEP * 5);
|
||||
piCoutObj << "peer disconnect" << p_name;
|
||||
if (p_name == conn_name) {
|
||||
disconnect();
|
||||
}
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
Remote * dt = remotes.value(p_name, 0);
|
||||
if (!dt) return;
|
||||
dt->shellClose();
|
||||
if (tile_file_progress->ft == &(dt->ft)) {
|
||||
tile_file_progress->close(false);
|
||||
}
|
||||
remotes.remove(p_name);
|
||||
delete dt;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::filesReceived(const PIString & p_name, bool ok) {
|
||||
if (ok) {
|
||||
piCout << "files received from" << p_name;
|
||||
} else {
|
||||
piCout << "warning, files not received fromsended" << p_name;
|
||||
}
|
||||
closeFileDialog(p_name, ok);
|
||||
Remote * r = remotes.value(p_name, 0);
|
||||
if (!r) return;
|
||||
r->updateDir();
|
||||
}
|
||||
|
||||
|
||||
void Daemon::filesSended(const PIString & p_name, bool ok) {
|
||||
if (ok) {
|
||||
piCout << "files sended to" << p_name;
|
||||
} else {
|
||||
piCout << "warning, files not sended to" << p_name;
|
||||
}
|
||||
closeFileDialog(p_name, ok);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::dirChanged(const PIString & p_name, const PIString & dir) {
|
||||
if (p_name == self_name) {
|
||||
fm.clearSelectionLocal();
|
||||
fm.clearSelectionRemote();
|
||||
fm.updateLocalDir();
|
||||
fm.updateRemoteDir();
|
||||
return;
|
||||
}
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
Remote * r = remotes.value(p_name, 0);
|
||||
if (!r) return;
|
||||
if (r->dir_my.absolutePath() != dir) return;
|
||||
sendDirToRemote(r);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::closeFileDialog(const PIString & p_name, bool ok) {
|
||||
// piCout << "CLOSE" << tile_file_progress->conn_name << name << ok;
|
||||
if (p_name == self_name) {
|
||||
tile_file_progress->close(ok);
|
||||
fm.clearSelectionLocal();
|
||||
fm.clearSelectionRemote();
|
||||
fm.updateLocalDir();
|
||||
fm.updateRemoteDir();
|
||||
return;
|
||||
}
|
||||
// piCout << "file transfer with" << p_name << (ok ? "success" : "failure");
|
||||
if (tile_file_progress->conn_name != p_name) return;
|
||||
tile_file_progress->close(ok);
|
||||
if (tile_file_progress->rec) {
|
||||
fm.remoteTile()->setFocus();
|
||||
fm.clearSelectionRemote();
|
||||
fm.updateLocalDir();
|
||||
} else {
|
||||
fm.localTile()->setFocus();
|
||||
fm.clearSelectionLocal();
|
||||
requestChDir(".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Daemon::dataReceived(const PIString & from, const PIByteArray & data) {
|
||||
// piCout << "rec" << data.size();
|
||||
if (data.size() < 4) return;
|
||||
PIMutexLocker ml(remote_mutex);
|
||||
// piCout << "lock in dataReceived";
|
||||
PIByteArray ba(data), rba;
|
||||
Remote * r = remotes.value(from);
|
||||
PIString dir;
|
||||
int type;
|
||||
ba >> type;
|
||||
// piCout << "rec from " << from << type << r;
|
||||
switch (type) {
|
||||
case RequestHostInfo:
|
||||
makeMyHostInfo();
|
||||
rba << int(ReplyHostInfo) << info_my;
|
||||
break;
|
||||
case RequestChangeDir:
|
||||
if (!r) break;
|
||||
ba >> dir;
|
||||
r->dir_my.cd(dir);
|
||||
r->ft.setDirectory(r->dir_my);
|
||||
// piCout << "store to" << r->dir_my.absolutePath();
|
||||
piCoutObj << "cd to" << r->dir_my.absolutePath();
|
||||
r->updateDir();
|
||||
break;
|
||||
case ReplyHostInfo:
|
||||
ba >> info_other;
|
||||
makeOtherHostInfo();
|
||||
fillInfoTile(info_other);
|
||||
break;
|
||||
case ReplyChangeDir:
|
||||
if (!r) break;
|
||||
{
|
||||
PIVector<PIFile::FileInfo> fil;
|
||||
ba >> dir >> fil;
|
||||
fm.setRemoteDir(dir);
|
||||
fm.setRemoteContent(fil);
|
||||
fm.remoteRestoreDir();
|
||||
}
|
||||
break;
|
||||
case CopyFiles:
|
||||
if (!r) return;
|
||||
if (r->isRunning()) return;
|
||||
{
|
||||
PIStringList files;
|
||||
ba >> files;
|
||||
// piCout << "send" << files << "from" << r->dir_my.absolutePath();
|
||||
r->sendFiles(r->dir_my.absolutePath() + PIDir::separator, files);
|
||||
}
|
||||
break;
|
||||
case RemoveFiles:
|
||||
if (!r) return;
|
||||
if (r->isRunning()) return;
|
||||
{
|
||||
PIStringList files;
|
||||
ba >> files;
|
||||
// piCout << "send" << files << "from" << r->dir_my.absolutePath();
|
||||
r->removeFiles(files);
|
||||
}
|
||||
break;
|
||||
case MkDir:
|
||||
if (!r) return;
|
||||
{
|
||||
PIString dn;
|
||||
ba >> dn;
|
||||
// piCout << "send" << files << "from" << r->dir_my.absolutePath();
|
||||
r->makeDir(dn);
|
||||
}
|
||||
break;
|
||||
case FileTransfer:
|
||||
if (r) r->received(ba);
|
||||
break;
|
||||
case CryptFiles:
|
||||
if (!r) return;
|
||||
if (r->isRunning()) return;
|
||||
{
|
||||
PIStringList files;
|
||||
ba >> files;
|
||||
r->cryptFiles(files);
|
||||
}
|
||||
break;
|
||||
case ShellOpen:
|
||||
if (!r) return;
|
||||
r->shellOpen();
|
||||
break;
|
||||
case ShellClose:
|
||||
if (!r) return;
|
||||
r->shellClose();
|
||||
break;
|
||||
case ShellContent: {
|
||||
if (!r) return;
|
||||
PIVector<PIVector<PIScreenTypes::Cell>> cells;
|
||||
ba >> cells;
|
||||
tile_shell->setContent(cells);
|
||||
} break;
|
||||
case ShellResizeRequest: {
|
||||
if (!r) return;
|
||||
int w, h;
|
||||
ba >> w >> h;
|
||||
r->shellResize(w, h);
|
||||
} break;
|
||||
case ShellKeyEvent: {
|
||||
if (!r) return;
|
||||
PIKbdListener::KeyEvent k;
|
||||
ba >> k;
|
||||
r->shellKeySend(k);
|
||||
} break;
|
||||
};
|
||||
if (!rba.isEmpty()) send(from, rba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::sendDirToRemote(Remote * r) {
|
||||
if (!r) return;
|
||||
PIVector<PIFile::FileInfo> fil = r->my_filelist;
|
||||
PIByteArray ba;
|
||||
ba << int(ReplyChangeDir) << r->dir_my.absolutePath() << fil;
|
||||
send(r->name(), ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::requestOpenShell() {
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
screen->disableExitCapture();
|
||||
PIByteArray ba;
|
||||
ba << int(ShellOpen);
|
||||
send(conn_name, ba);
|
||||
executeQueued(this, "shResizeRequest");
|
||||
}
|
||||
|
||||
|
||||
void Daemon::requestCloseShell() {
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
screen->enableExitCapture(PIKbdListener::F10);
|
||||
PIByteArray ba;
|
||||
ba << int(ShellClose);
|
||||
send(conn_name, ba);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::makeMyHostInfo() {
|
||||
info_my.execCommand = PISystemInfo::instance()->execCommand;
|
||||
info_my.hostname = PISystemInfo::instance()->hostname;
|
||||
info_my.user = PISystemInfo::instance()->user;
|
||||
info_my.OS_name = PISystemInfo::instance()->OS_name;
|
||||
info_my.OS_version = PISystemInfo::instance()->OS_version;
|
||||
info_my.architecture = PISystemInfo::instance()->architecture;
|
||||
info_my.execDateTime = PISystemInfo::instance()->execDateTime;
|
||||
info_my.processorsCount = PISystemInfo::instance()->processorsCount;
|
||||
info_my.ID = sys_mon.statistic().ID;
|
||||
info_my.threads = sys_mon.statistic().threads;
|
||||
info_my.priority = sys_mon.statistic().priority;
|
||||
info_my.physical_memsize = sys_mon.statistic().physical_memsize;
|
||||
info_my.share_memsize = sys_mon.statistic().share_memsize;
|
||||
info_my.cpu_load_system = sys_mon.statistic().cpu_load_system;
|
||||
info_my.cpu_load_user = sys_mon.statistic().cpu_load_user;
|
||||
}
|
||||
|
||||
|
||||
void Daemon::makeOtherHostInfo() {
|
||||
PISystemMonitor::ProcessStats ps(sys_mon_other.statistic());
|
||||
ps.ID = info_other.ID;
|
||||
ps.threads = info_other.threads;
|
||||
ps.priority = info_other.priority;
|
||||
ps.physical_memsize = info_other.physical_memsize;
|
||||
ps.share_memsize = info_other.share_memsize;
|
||||
ps.cpu_load_system = info_other.cpu_load_system;
|
||||
ps.cpu_load_user = info_other.cpu_load_user;
|
||||
sys_mon_other.setStatistic(ps);
|
||||
}
|
||||
|
||||
|
||||
void Daemon::requestChDir(const PIString & d) {
|
||||
if (d.isEmpty()) return;
|
||||
Remote * r = remotes.value(conn_name, 0);
|
||||
if (!r) return;
|
||||
fm.remoteSaveDir();
|
||||
fm.readingRemote();
|
||||
PIByteArray ba;
|
||||
ba << int(RequestChangeDir) << d;
|
||||
send(conn_name, ba);
|
||||
}
|
||||
|
||||
@@ -1,215 +1,219 @@
|
||||
#ifndef DAEMON_H
|
||||
#define DAEMON_H
|
||||
|
||||
#include "piscreentiles.h"
|
||||
#include "pipeer.h"
|
||||
#include "pisystemmonitor.h"
|
||||
#include "pidatatransfer.h"
|
||||
#include "pifiletransfer.h"
|
||||
#include "file_manager.h"
|
||||
#include "terminal_tile.h"
|
||||
#include "piterminal.h"
|
||||
|
||||
extern PISystemMonitor sys_mon;
|
||||
|
||||
class Daemon: public PIPeer {
|
||||
PIOBJECT_SUBCLASS(Daemon, PIPeer)
|
||||
public:
|
||||
Daemon();
|
||||
~Daemon();
|
||||
|
||||
struct HostInfo {
|
||||
HostInfo() {
|
||||
processorsCount = ID = threads = priority = -1;
|
||||
physical_memsize = share_memsize = 0;
|
||||
cpu_load_system = cpu_load_user = 0.;
|
||||
}
|
||||
PIString execCommand;
|
||||
PIString hostname;
|
||||
PIString user;
|
||||
PIString OS_name;
|
||||
PIString OS_version;
|
||||
PIString architecture;
|
||||
PIDateTime execDateTime;
|
||||
int processorsCount;
|
||||
|
||||
int ID;
|
||||
int threads;
|
||||
int priority;
|
||||
ulong physical_memsize;
|
||||
ulong share_memsize;
|
||||
float cpu_load_system;
|
||||
float cpu_load_user;
|
||||
};
|
||||
|
||||
void showMainList() {showTile(list_daemons, "Select daemon");}
|
||||
void showActionList() {showTile(list_actions, "Select action");}
|
||||
void showLocalFilemanager() {mode = rmLocalFileManager; showTile(tile_fm, "File manager");}
|
||||
|
||||
PIStringList availableDaemons();
|
||||
void connectToDaemon(const PIString & dn);
|
||||
void disconnect();
|
||||
|
||||
PIString connectedDaemon() const;
|
||||
PIString thisDaemonName() const {return selfInfo().name.mid(6);}
|
||||
|
||||
PIScreenTile * tile() const;
|
||||
|
||||
FileManager fm;
|
||||
|
||||
private:
|
||||
enum PacketType {
|
||||
RequestHostInfo = 10,
|
||||
RequestChangeDir,
|
||||
|
||||
ReplyHostInfo = 20,
|
||||
ReplyChangeDir,
|
||||
CopyFiles,
|
||||
RemoveFiles,
|
||||
MkDir,
|
||||
CryptFiles,
|
||||
|
||||
FileTransfer = 30,
|
||||
|
||||
ShellOpen = 40,
|
||||
ShellClose,
|
||||
ShellContent,
|
||||
ShellResizeRequest,
|
||||
ShellKeyEvent
|
||||
|
||||
};
|
||||
|
||||
enum RemoteMode {
|
||||
rmNone,
|
||||
rmLocalFileManager,
|
||||
rmSelectMode,
|
||||
rmInformation,
|
||||
rmFileManager,
|
||||
rmShell
|
||||
};
|
||||
|
||||
class Remote: public PIThread {
|
||||
PIOBJECT_SUBCLASS(Remote, PIThread)
|
||||
public:
|
||||
explicit Remote(const PIString & n = PIString());
|
||||
~Remote();
|
||||
void sendFiles(const PIString & dir, const PIStringList & fl) {startAction(Daemon::CopyFiles, dir, fl);}
|
||||
void removeFiles(const PIStringList & fl) {startAction(Daemon::RemoveFiles, PIString(), fl);}
|
||||
void updateDir() {startAction(Daemon::RequestChangeDir, PIString(), PIStringList());}
|
||||
void makeDir(const PIString & dir) {startAction(Daemon::MkDir, dir, PIStringList() << "");}
|
||||
void cryptFiles(const PIStringList & fl) {startAction(Daemon::CryptFiles, PIString(), fl);}
|
||||
void shellOpen();
|
||||
void shellClose();
|
||||
void shellResize(int w, int h);
|
||||
void shellKeySend(PIKbdListener::KeyEvent k);
|
||||
EVENT_HANDLER1(void, ftSendRequest, PIByteArray &, data) {PIByteArray h; h << int(FileTransfer); data.insert(0, h); sendRequest(name(), data);}
|
||||
EVENT_HANDLER1(void, ftReceived, bool, ok) {receiveFinished(name(), ok);}
|
||||
EVENT_HANDLER1(void, ftSended, bool, ok) {sendFinished(name(), ok);}
|
||||
|
||||
EVENT2(sendRequest, const PIString &, p_name, const PIByteArray &, data)
|
||||
EVENT2(receiveFinished, const PIString & , p_name, bool, ok)
|
||||
EVENT2(sendFinished, const PIString & , p_name, bool, ok)
|
||||
EVENT2(changeDirFinished, const PIString & , p_name, const PIString & , dir)
|
||||
EVENT_HANDLER1(void, received, PIByteArray & , data) {ft.received(data);}
|
||||
EVENT_HANDLER(void, termTimerTick);
|
||||
|
||||
void startAction(PacketType a, const PIString & dir, const PIStringList & fl);
|
||||
void run() override;
|
||||
|
||||
PIDir dir_my;
|
||||
PIVector<PIFile::FileInfo> my_filelist;
|
||||
PIVector<PIVector<PIScreenTypes::Cell> > pcells;
|
||||
PIFileTransfer ft;
|
||||
PIStringList _fl;
|
||||
PacketType action;
|
||||
PITimer term_timer;
|
||||
PITerminal * term;
|
||||
|
||||
private:
|
||||
void updateDirEntries();
|
||||
};
|
||||
|
||||
class TileFileProgress: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileFileProgress, PIScreenTile)
|
||||
public:
|
||||
TileFileProgress();
|
||||
void show(PIFileTransfer * f);
|
||||
void close(bool ok = true);
|
||||
TileSimple * label_file, * label_speed, * label_cnt;
|
||||
TileProgress * prog_file, * prog_all;
|
||||
TileButtons * buttons;
|
||||
PIFileTransfer * ft;
|
||||
PITimeMeasurer tm, tme;
|
||||
void resizeEvent(int w, int h) override;
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
bool rec;
|
||||
PIString conn_name;
|
||||
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e);
|
||||
};
|
||||
|
||||
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e);
|
||||
EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, key);
|
||||
EVENT_HANDLER2(void, sendRequest, const PIString &, p_name, const PIByteArray &, data) {send(p_name, data);}
|
||||
EVENT_HANDLER1(void, fmKeyEvent, PIKbdListener::KeyEvent, key);
|
||||
EVENT_HANDLER3(void, fmActionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data);
|
||||
EVENT_HANDLER (void, shResizeRequest);
|
||||
EVENT_HANDLER1(void, shKeyEvent, PIKbdListener::KeyEvent, k);
|
||||
EVENT_HANDLER2(void, timerEvent, void * , _d, int, delim);
|
||||
EVENT_HANDLER2(void, filesReceived, const PIString & , p_name, bool, ok);
|
||||
EVENT_HANDLER2(void, filesSended, const PIString & , p_name, bool, ok);
|
||||
EVENT_HANDLER2(void, dirChanged, const PIString & , p_name, const PIString & , dir);
|
||||
EVENT_HANDLER2(void, closeFileDialog, const PIString & , p_name, bool, ok);
|
||||
EVENT_HANDLER2(void, localSend, const PIString & , p_name, const PIByteArray &, data);
|
||||
EVENT_HANDLER (void, escPressed);
|
||||
EVENT_HANDLER (void, requestOpenShell);
|
||||
EVENT_HANDLER (void, requestCloseShell);
|
||||
EVENT(menuRequest)
|
||||
void hideAll();
|
||||
void showTile(PIScreenTile * t, const PIString & header = PIString());
|
||||
void fillInfoTile(const HostInfo & hi);
|
||||
void peerConnected(const PIString & p_name) override;
|
||||
void peerDisconnected(const PIString & p_name) override;
|
||||
void dataReceived(const PIString & from, const PIByteArray & data) override;
|
||||
void makeMyHostInfo();
|
||||
void makeOtherHostInfo();
|
||||
|
||||
void requestChDir(const PIString & d);
|
||||
void sendDirToRemote(Remote * r);
|
||||
|
||||
mutable PIStringList available_daemons;
|
||||
PITimer dtimer;
|
||||
PIString conn_name;
|
||||
PIMutex remote_mutex;
|
||||
PIMap<PIString, Remote*> remotes;
|
||||
PISystemMonitor sys_mon_other;
|
||||
HostInfo info_my, info_other;
|
||||
PIScreenTile * tile_root, * tile_fm;
|
||||
TileSimple * tile_info, * tile_header;
|
||||
TileList * list_daemons, * list_actions;
|
||||
TileFileProgress * tile_file_progress;
|
||||
TileTerminal * tile_shell;
|
||||
PIFileTransfer localft;
|
||||
Remote * _self;
|
||||
RemoteMode mode;
|
||||
int offset, cur, height;
|
||||
};
|
||||
|
||||
BINARY_STREAM_WRITE(Daemon::HostInfo) {
|
||||
s << v.execCommand << v.hostname << v.user << v.OS_name
|
||||
<< v.OS_version << v.architecture << v.execDateTime
|
||||
<< v.processorsCount << v.ID << v.threads << v.priority
|
||||
<< v.physical_memsize << v.share_memsize
|
||||
<< v.cpu_load_system << v.cpu_load_user;
|
||||
return s;
|
||||
}
|
||||
BINARY_STREAM_READ (Daemon::HostInfo) {
|
||||
s >> v.execCommand >> v.hostname >> v.user >> v.OS_name
|
||||
>> v.OS_version >> v.architecture >> v.execDateTime
|
||||
>> v.processorsCount >> v.ID >> v.threads >> v.priority
|
||||
>> v.physical_memsize >> v.share_memsize
|
||||
>> v.cpu_load_system >> v.cpu_load_user;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // DAEMON_H
|
||||
#ifndef DAEMON_H
|
||||
#define DAEMON_H
|
||||
|
||||
#include "file_manager.h"
|
||||
#include "pidatatransfer.h"
|
||||
#include "pifiletransfer.h"
|
||||
#include "pipeer.h"
|
||||
#include "piscreentiles.h"
|
||||
#include "pisystemmonitor.h"
|
||||
#include "piterminal.h"
|
||||
#include "terminal_tile.h"
|
||||
|
||||
extern PISystemMonitor sys_mon;
|
||||
|
||||
class Daemon: public PIPeer {
|
||||
PIOBJECT_SUBCLASS(Daemon, PIPeer)
|
||||
|
||||
public:
|
||||
Daemon();
|
||||
~Daemon();
|
||||
|
||||
struct HostInfo {
|
||||
HostInfo() {
|
||||
processorsCount = ID = threads = priority = -1;
|
||||
physical_memsize = share_memsize = 0;
|
||||
cpu_load_system = cpu_load_user = 0.;
|
||||
}
|
||||
PIString execCommand;
|
||||
PIString hostname;
|
||||
PIString user;
|
||||
PIString OS_name;
|
||||
PIString OS_version;
|
||||
PIString architecture;
|
||||
PIDateTime execDateTime;
|
||||
int processorsCount;
|
||||
|
||||
int ID;
|
||||
int threads;
|
||||
int priority;
|
||||
ulong physical_memsize;
|
||||
ulong share_memsize;
|
||||
float cpu_load_system;
|
||||
float cpu_load_user;
|
||||
};
|
||||
|
||||
void showMainList() { showTile(list_daemons, "Select daemon"); }
|
||||
void showActionList() { showTile(list_actions, "Select action"); }
|
||||
void showLocalFilemanager() {
|
||||
mode = rmLocalFileManager;
|
||||
showTile(tile_fm, "File manager");
|
||||
}
|
||||
|
||||
PIStringList availableDaemons();
|
||||
void connectToDaemon(const PIString & dn);
|
||||
void disconnect();
|
||||
|
||||
PIString connectedDaemon() const;
|
||||
PIString thisDaemonName() const { return selfInfo().name.mid(6); }
|
||||
|
||||
PIScreenTile * tile() const;
|
||||
|
||||
FileManager fm;
|
||||
|
||||
private:
|
||||
enum PacketType {
|
||||
RequestHostInfo = 10,
|
||||
RequestChangeDir,
|
||||
|
||||
ReplyHostInfo = 20,
|
||||
ReplyChangeDir,
|
||||
CopyFiles,
|
||||
RemoveFiles,
|
||||
MkDir,
|
||||
CryptFiles,
|
||||
|
||||
FileTransfer = 30,
|
||||
|
||||
ShellOpen = 40,
|
||||
ShellClose,
|
||||
ShellContent,
|
||||
ShellResizeRequest,
|
||||
ShellKeyEvent
|
||||
};
|
||||
|
||||
enum RemoteMode {
|
||||
rmNone,
|
||||
rmLocalFileManager,
|
||||
rmSelectMode,
|
||||
rmInformation,
|
||||
rmFileManager,
|
||||
rmShell
|
||||
};
|
||||
|
||||
class Remote: public PIThread {
|
||||
PIOBJECT_SUBCLASS(Remote, PIThread)
|
||||
|
||||
public:
|
||||
explicit Remote(const PIString & n = PIString());
|
||||
~Remote();
|
||||
void sendFiles(const PIString & dir, const PIStringList & fl) { startAction(Daemon::CopyFiles, dir, fl); }
|
||||
void removeFiles(const PIStringList & fl) { startAction(Daemon::RemoveFiles, PIString(), fl); }
|
||||
void updateDir() { startAction(Daemon::RequestChangeDir, PIString(), PIStringList()); }
|
||||
void makeDir(const PIString & dir) { startAction(Daemon::MkDir, dir, PIStringList() << ""); }
|
||||
void cryptFiles(const PIStringList & fl) { startAction(Daemon::CryptFiles, PIString(), fl); }
|
||||
void shellOpen();
|
||||
void shellClose();
|
||||
void shellResize(int w, int h);
|
||||
void shellKeySend(PIKbdListener::KeyEvent k);
|
||||
EVENT_HANDLER1(void, ftSendRequest, PIByteArray &, data) {
|
||||
PIByteArray h;
|
||||
h << int(FileTransfer);
|
||||
data.insert(0, h);
|
||||
sendRequest(name(), data);
|
||||
}
|
||||
EVENT_HANDLER1(void, ftReceived, bool, ok) { receiveFinished(name(), ok); }
|
||||
EVENT_HANDLER1(void, ftSended, bool, ok) { sendFinished(name(), ok); }
|
||||
|
||||
EVENT2(sendRequest, const PIString &, p_name, const PIByteArray &, data)
|
||||
EVENT2(receiveFinished, const PIString &, p_name, bool, ok)
|
||||
EVENT2(sendFinished, const PIString &, p_name, bool, ok)
|
||||
EVENT2(changeDirFinished, const PIString &, p_name, const PIString &, dir)
|
||||
EVENT_HANDLER1(void, received, PIByteArray &, data) { ft.received(data); }
|
||||
EVENT_HANDLER(void, termTimerTick);
|
||||
|
||||
void startAction(PacketType a, const PIString & dir, const PIStringList & fl);
|
||||
void run() override;
|
||||
|
||||
PIDir dir_my;
|
||||
PIVector<PIFile::FileInfo> my_filelist;
|
||||
PIVector<PIVector<PIScreenTypes::Cell>> pcells;
|
||||
PIFileTransfer ft;
|
||||
PIStringList _fl;
|
||||
PacketType action;
|
||||
PITimer term_timer;
|
||||
PITerminal * term;
|
||||
|
||||
private:
|
||||
void updateDirEntries();
|
||||
};
|
||||
|
||||
class TileFileProgress: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileFileProgress, PIScreenTile)
|
||||
|
||||
public:
|
||||
TileFileProgress();
|
||||
void show(PIFileTransfer * f);
|
||||
void close(bool ok = true);
|
||||
TileSimple *label_file, *label_speed, *label_cnt;
|
||||
TileProgress *prog_file, *prog_all;
|
||||
TileButtons * buttons;
|
||||
PIFileTransfer * ft;
|
||||
PITimeMeasurer tm, tme;
|
||||
void resizeEvent(int w, int h) override;
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
bool rec;
|
||||
PIString conn_name;
|
||||
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e);
|
||||
};
|
||||
|
||||
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e);
|
||||
EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, key);
|
||||
EVENT_HANDLER2(void, sendRequest, const PIString &, p_name, const PIByteArray &, data) { send(p_name, data); }
|
||||
EVENT_HANDLER1(void, fmKeyEvent, PIKbdListener::KeyEvent, key);
|
||||
EVENT_HANDLER3(void, fmActionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data);
|
||||
EVENT_HANDLER(void, shResizeRequest);
|
||||
EVENT_HANDLER1(void, shKeyEvent, PIKbdListener::KeyEvent, k);
|
||||
EVENT_HANDLER2(void, timerEvent, void *, _d, int, delim);
|
||||
EVENT_HANDLER2(void, filesReceived, const PIString &, p_name, bool, ok);
|
||||
EVENT_HANDLER2(void, filesSended, const PIString &, p_name, bool, ok);
|
||||
EVENT_HANDLER2(void, dirChanged, const PIString &, p_name, const PIString &, dir);
|
||||
EVENT_HANDLER2(void, closeFileDialog, const PIString &, p_name, bool, ok);
|
||||
EVENT_HANDLER2(void, localSend, const PIString &, p_name, const PIByteArray &, data);
|
||||
EVENT_HANDLER(void, escPressed);
|
||||
EVENT_HANDLER(void, requestOpenShell);
|
||||
EVENT_HANDLER(void, requestCloseShell);
|
||||
EVENT(menuRequest)
|
||||
void hideAll();
|
||||
void showTile(PIScreenTile * t, const PIString & header = PIString());
|
||||
void fillInfoTile(const HostInfo & hi);
|
||||
void peerConnected(const PIString & p_name) override;
|
||||
void peerDisconnected(const PIString & p_name) override;
|
||||
void dataReceived(const PIString & from, const PIByteArray & data) override;
|
||||
void makeMyHostInfo();
|
||||
void makeOtherHostInfo();
|
||||
|
||||
void requestChDir(const PIString & d);
|
||||
void sendDirToRemote(Remote * r);
|
||||
|
||||
mutable PIStringList available_daemons;
|
||||
PITimer dtimer;
|
||||
PIString conn_name;
|
||||
PIMutex remote_mutex;
|
||||
PIMap<PIString, Remote *> remotes;
|
||||
PISystemMonitor sys_mon_other;
|
||||
HostInfo info_my, info_other;
|
||||
PIScreenTile *tile_root, *tile_fm;
|
||||
TileSimple *tile_info, *tile_header;
|
||||
TileList *list_daemons, *list_actions;
|
||||
TileFileProgress * tile_file_progress;
|
||||
TileTerminal * tile_shell;
|
||||
PIFileTransfer localft;
|
||||
Remote * _self;
|
||||
RemoteMode mode;
|
||||
int offset, cur, height;
|
||||
};
|
||||
|
||||
BINARY_STREAM_WRITE(Daemon::HostInfo) {
|
||||
s << v.execCommand << v.hostname << v.user << v.OS_name << v.OS_version << v.architecture << v.execDateTime << v.processorsCount << v.ID
|
||||
<< v.threads << v.priority << v.physical_memsize << v.share_memsize << v.cpu_load_system << v.cpu_load_user;
|
||||
return s;
|
||||
}
|
||||
BINARY_STREAM_READ(Daemon::HostInfo) {
|
||||
s >> v.execCommand >> v.hostname >> v.user >> v.OS_name >> v.OS_version >> v.architecture >> v.execDateTime >> v.processorsCount >>
|
||||
v.ID >> v.threads >> v.priority >> v.physical_memsize >> v.share_memsize >> v.cpu_load_system >> v.cpu_load_user;
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // DAEMON_H
|
||||
|
||||
@@ -1,340 +1,342 @@
|
||||
#include "file_manager.h"
|
||||
#include "shared.h"
|
||||
|
||||
|
||||
FileManager::TileDir::TileDir(): TileList() {
|
||||
label_path = 0;
|
||||
selection_mode = TileList::MultiSelection;
|
||||
dir = PIDir::current();
|
||||
resized = is_right = remote_mode = false;
|
||||
}
|
||||
|
||||
|
||||
PIStringList FileManager::TileDir::selectedNames() const {
|
||||
PIStringList ret;
|
||||
PIMutexLocker ml(e_mutex);
|
||||
PIVector<int> sind = selected.toVector();
|
||||
piForeachC (int i, sind)
|
||||
ret << entries[i].name();
|
||||
ret.removeOne("..");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool FileManager::TileDir::keyEvent(PIKbdListener::KeyEvent key) {
|
||||
bool pass = false;
|
||||
PIString nd;
|
||||
switch (key.key) {
|
||||
case 'R': if (!(is_right && remote_mode)) updateDir(); pass = true; break;
|
||||
case PIKbdListener::F5:
|
||||
if (selected.isEmpty())
|
||||
selected << cur;
|
||||
if (!askQuestion("Copy selected files?")) return true;
|
||||
setFocus();
|
||||
//piCoutObj << "remote" << remote_mode;
|
||||
if (remote_mode) actionRequest(is_right, Copy, selectedNames());
|
||||
else actionRequest(is_right, LocalCopy, selectedNames());
|
||||
break;
|
||||
case PIKbdListener::F6:
|
||||
if (key.modifiers[PIKbdListener::Shift]) {
|
||||
if (selected.isEmpty())
|
||||
selected << cur;
|
||||
if (!askQuestion("Crypt selected files?")) return true;
|
||||
setFocus();
|
||||
if (remote_mode) actionRequest(is_right, Crypt, selectedNames());
|
||||
else actionRequest(is_right, LocalCrypt, selectedNames());
|
||||
}
|
||||
break;
|
||||
case PIKbdListener::F7:
|
||||
nd = askUserInput("Enter new directory name:");
|
||||
setFocus();
|
||||
if (nd.isEmpty()) return true;
|
||||
if (is_right && remote_mode)
|
||||
actionRequest(is_right, MkDir, nd);
|
||||
else {
|
||||
PIDir::make(dir.absolutePath() + PIDir::separator + nd);
|
||||
updateDir();
|
||||
}
|
||||
pass = true;
|
||||
break;
|
||||
case PIKbdListener::F8:
|
||||
if (selected.isEmpty())
|
||||
selected << cur;
|
||||
if (!askQuestion("Delete selected?")) {
|
||||
setFocus();
|
||||
return false;
|
||||
}
|
||||
setFocus();
|
||||
if (is_right && remote_mode) {
|
||||
actionRequest(is_right, Remove, selectedNames());
|
||||
} else {
|
||||
removeFiles(dir, selectedNames());
|
||||
selected.clear();
|
||||
updateDir();
|
||||
}
|
||||
pass = true;
|
||||
break;
|
||||
case PIKbdListener::Return:
|
||||
{
|
||||
e_mutex.lock();
|
||||
bool ud = false;
|
||||
if (cur < entries.size_s() && cur >= 0) {
|
||||
if (!(is_right && remote_mode)) {
|
||||
//piCout << entries[cur];
|
||||
if (entries[cur].isDir()) {
|
||||
prev_pos[dir.path()] = PIPair<int, int>(cur, offset);
|
||||
dir.cd(entries[cur].name());
|
||||
PIPair<int, int> cp = prev_pos.value(dir.path());
|
||||
cur = cp.first;
|
||||
offset = cp.second;
|
||||
selected.clear();
|
||||
ud = true;
|
||||
}
|
||||
}
|
||||
pass = true;
|
||||
}
|
||||
e_mutex.unlock();
|
||||
if (ud) updateDir();
|
||||
}
|
||||
break;
|
||||
}
|
||||
// piCout << is_right << remote_mode << pass;
|
||||
if (is_right && remote_mode && pass) {
|
||||
((void(*)(void*,PIKbdListener::KeyEvent))key_func)(fm, key);
|
||||
return true;
|
||||
}
|
||||
return TileList::keyEvent(key);
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::lock() {
|
||||
if (screen && !resized) ((PIScreen*)screen)->lock();
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::unlock() {
|
||||
if (screen && !resized) ((PIScreen*)screen)->unlock();
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::showReading() {
|
||||
PIMutexLocker ml(e_mutex);
|
||||
cur = -1;
|
||||
offset = 0;
|
||||
entries.clear();
|
||||
content.resize(1);
|
||||
content[0] = Row("... Reading ...", CellFormat());
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::setContent(const PIVector<PIFile::FileInfo> & l) {
|
||||
PIMutexLocker ml(e_mutex);
|
||||
PIVector<PIFile::FileInfo> fl, dl;
|
||||
entries.clear();
|
||||
if (l.isEmpty()) {
|
||||
PIFile::FileInfo fi;
|
||||
fi.path = "..";
|
||||
fi.flags |= PIFile::FileInfo::DotDot | PIFile::FileInfo::Dir;
|
||||
entries << fi;
|
||||
} else {
|
||||
bool root = dir.path() == PIDir::separator;
|
||||
for (int i = 0; i < l.size_s(); ++i) {
|
||||
if (l[i].name() == ".") continue;
|
||||
if (l[i].name() == "..") {
|
||||
if (!root) dl.push_front(l[i]);
|
||||
continue;
|
||||
}
|
||||
if (l[i].isDir()) dl << l[i];
|
||||
else fl << l[i];
|
||||
}
|
||||
entries << dl << fl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::updateDir() {
|
||||
lock();
|
||||
int pc = cur, po = offset;
|
||||
showReading();
|
||||
unlock();
|
||||
setContent(dir.entries());
|
||||
if (label_path) {
|
||||
label_path->content.resize(1);
|
||||
label_path->content[0].first = dir.absolutePath();
|
||||
}
|
||||
cur = pc;
|
||||
offset = po;
|
||||
buildNames();
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::buildNames() {
|
||||
lock();
|
||||
PIMutexLocker ml(e_mutex);
|
||||
content.clear();
|
||||
PIChar t;
|
||||
CharFlags cf = 0;
|
||||
Color cc = Default;
|
||||
PIString fcol, scol;
|
||||
piForeachC (PIFile::FileInfo & e, entries) {
|
||||
if (e.isDir()) {
|
||||
t = '/';
|
||||
cf = Bold;
|
||||
scol = " dir";
|
||||
} else {
|
||||
if (e.perm_user.exec || e.perm_group.exec || e.perm_other.exec) {
|
||||
cf = Bold;
|
||||
cc = Green;
|
||||
t = '*';
|
||||
} else {
|
||||
t = ' ';
|
||||
cc = Default;
|
||||
cf = 0;
|
||||
}
|
||||
scol = PIString::readableSize(e.size);
|
||||
}
|
||||
if (e.isSymbolicLink() && (t != '*')) t = '~';
|
||||
scol = scol.expandRightTo(9, ' ') + "| " + e.time_modification.toString("dd.MM hh:mm:ss") + " | "
|
||||
+ e.perm_user.toString() + " " + e.perm_group.toString() + " " + e.perm_other.toString();
|
||||
fcol = t + e.name();
|
||||
if (fcol.size_s() >= width_ - 2 - scol.size_s())
|
||||
fcol = fcol.left(width_ - 5 - scol.size_s()) + "...";
|
||||
fcol.expandRightTo(width_ - 1 - scol.size_s(), ' ');
|
||||
content << Row(fcol + scol, CellFormat(cc, Transparent, cf));
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::sizeHint(int & w, int & h) const {
|
||||
w = h = 4;
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::resizeEvent(int w, int h) {
|
||||
resized = true;
|
||||
buildNames();
|
||||
resized = false;
|
||||
TileList::resizeEvent(w, h);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FileManager::FileManager() {
|
||||
setName("FileManager");
|
||||
TileSimple * tl;
|
||||
|
||||
tile_root = new PIScreenTile();
|
||||
tile_root->direction = Vertical;
|
||||
PIScreenTile * pt = new PIScreenTile();
|
||||
pt->direction = Horizontal;
|
||||
pt->spacing = 1;
|
||||
pt->back_format.color_back = Cyan;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
PIScreenTile * panel = new PIScreenTile();
|
||||
TileSimple * plabel = new TileSimple();
|
||||
plabel->size_policy = Fixed;
|
||||
plabel->maximumWidth = 1;
|
||||
panel->direction = Vertical;
|
||||
panels[i] = new TileDir();
|
||||
panels[i]->fm = this;
|
||||
panels[i]->key_func = (void*)tileKey_s;
|
||||
panels[i]->setName("file panel " + PIString::fromNumber(i));
|
||||
panels[i]->label_path = plabel;
|
||||
CONNECTU(panels[i], actionRequest, this, actionRequest)
|
||||
panel->addTile(plabel);
|
||||
panel->addTile(panels[i]);
|
||||
panels[i]->updateDir();
|
||||
pt->addTile(panel);
|
||||
}
|
||||
panels[1]->is_right = true;
|
||||
tile_root->addTile(pt);
|
||||
|
||||
PIScreenTile * labels = new PIScreenTile();
|
||||
labels->size_policy = Fixed;
|
||||
labels->direction = Horizontal;
|
||||
PIVector<SSPair> ll;
|
||||
ll << SSPair(" Esc", "Exit") << SSPair(" F5", "Copy") << SSPair(" F6", "Move") << SSPair(" F7", "MkDir") << SSPair(" F8", "Delete");
|
||||
piForeachC (SSPair & l, ll) {
|
||||
tl = new TileSimple(); labels->addTile(tl);
|
||||
tl->content << TileSimple::Row(l.first, CellFormat(White, Transparent, Bold));
|
||||
tl = new TileSimple(); labels->addTile(tl);
|
||||
tl->content << TileSimple::Row(l.second, CellFormat(Black, Cyan));
|
||||
}
|
||||
tl = new TileSimple(); labels->addTile(tl);
|
||||
tl->size_policy = Expanding;
|
||||
tile_root->addTile(labels);
|
||||
|
||||
}
|
||||
|
||||
|
||||
PIScreenTile * FileManager::tile() const {
|
||||
return tile_root;
|
||||
}
|
||||
|
||||
|
||||
void FileManager::setLocal() {
|
||||
if (panels[1]->remote_mode) setRemoteDir(panels[0]->dir.absolutePath());
|
||||
panels[0]->remote_mode = panels[1]->remote_mode = false;
|
||||
}
|
||||
|
||||
|
||||
void FileManager::setRemote() {
|
||||
panels[0]->remote_mode = panels[1]->remote_mode = true;
|
||||
}
|
||||
|
||||
|
||||
void FileManager::setRemoteDir(const PIString & d) {
|
||||
panels[1]->dir.setDir(d);
|
||||
if (panels[1]->label_path) {
|
||||
panels[1]->label_path->content.resize(1);
|
||||
panels[1]->label_path->content[0].first = panels[1]->dir.path();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FileManager::setRemoteContent(const PIVector< PIFile::FileInfo > & el) {
|
||||
panels[1]->setContent(el);
|
||||
panels[1]->buildNames();
|
||||
}
|
||||
|
||||
|
||||
int FileManager::selectedPanel() const {
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (panels[i]->hasFocus()) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PIStringList FileManager::selectedRemote() const {
|
||||
PIStringList ret;
|
||||
panels[1]->lock();
|
||||
PIVector<int> sil = panels[1]->selected.toVector();
|
||||
piForeachC (int i, sil)
|
||||
ret << panels[1]->entries[i].path;
|
||||
panels[1]->unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIFile::FileInfo FileManager::currentRemoteEntry() const {
|
||||
if ((panels[1]->cur < 0) || (panels[1]->cur >= panels[1]->content.size_s())) return PIFile::FileInfo();
|
||||
return panels[1]->entries[panels[1]->cur];
|
||||
}
|
||||
|
||||
|
||||
void FileManager::remoteSaveDir() {
|
||||
panels[1]->prev_pos[panels[1]->dir.path()] = PIPair<int, int>(panels[1]->cur, panels[1]->offset);
|
||||
}
|
||||
|
||||
|
||||
void FileManager::remoteRestoreDir() {
|
||||
PIPair<int, int> cp = panels[1]->prev_pos.value(panels[1]->dir.path());
|
||||
panels[1]->selected.clear();
|
||||
panels[1]->cur = cp.first;
|
||||
panels[1]->offset = cp.second;
|
||||
if ((panels[1]->cur < 0) || (panels[1]->cur >= panels[1]->content.size_s()))
|
||||
panels[1]->cur = 0;
|
||||
}
|
||||
|
||||
#include "file_manager.h"
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
|
||||
FileManager::TileDir::TileDir(): TileList() {
|
||||
label_path = 0;
|
||||
selection_mode = TileList::MultiSelection;
|
||||
dir = PIDir::current();
|
||||
resized = is_right = remote_mode = false;
|
||||
}
|
||||
|
||||
|
||||
PIStringList FileManager::TileDir::selectedNames() const {
|
||||
PIStringList ret;
|
||||
PIMutexLocker ml(e_mutex);
|
||||
PIVector<int> sind = selected.toVector();
|
||||
piForeachC(int i, sind)
|
||||
ret << entries[i].name();
|
||||
ret.removeOne("..");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool FileManager::TileDir::keyEvent(PIKbdListener::KeyEvent key) {
|
||||
bool pass = false;
|
||||
PIString nd;
|
||||
switch (key.key) {
|
||||
case 'R':
|
||||
if (!(is_right && remote_mode)) updateDir();
|
||||
pass = true;
|
||||
break;
|
||||
case PIKbdListener::F5:
|
||||
if (selected.isEmpty()) selected << cur;
|
||||
if (!askQuestion("Copy selected files?")) return true;
|
||||
setFocus();
|
||||
// piCoutObj << "remote" << remote_mode;
|
||||
if (remote_mode)
|
||||
actionRequest(is_right, Copy, selectedNames());
|
||||
else
|
||||
actionRequest(is_right, LocalCopy, selectedNames());
|
||||
break;
|
||||
case PIKbdListener::F6:
|
||||
if (key.modifiers[PIKbdListener::Shift]) {
|
||||
if (selected.isEmpty()) selected << cur;
|
||||
if (!askQuestion("Crypt selected files?")) return true;
|
||||
setFocus();
|
||||
if (remote_mode)
|
||||
actionRequest(is_right, Crypt, selectedNames());
|
||||
else
|
||||
actionRequest(is_right, LocalCrypt, selectedNames());
|
||||
}
|
||||
break;
|
||||
case PIKbdListener::F7:
|
||||
nd = askUserInput("Enter new directory name:");
|
||||
setFocus();
|
||||
if (nd.isEmpty()) return true;
|
||||
if (is_right && remote_mode)
|
||||
actionRequest(is_right, MkDir, nd);
|
||||
else {
|
||||
PIDir::make(dir.absolutePath() + PIDir::separator + nd);
|
||||
updateDir();
|
||||
}
|
||||
pass = true;
|
||||
break;
|
||||
case PIKbdListener::F8:
|
||||
if (selected.isEmpty()) selected << cur;
|
||||
if (!askQuestion("Delete selected?")) {
|
||||
setFocus();
|
||||
return false;
|
||||
}
|
||||
setFocus();
|
||||
if (is_right && remote_mode) {
|
||||
actionRequest(is_right, Remove, selectedNames());
|
||||
} else {
|
||||
removeFiles(dir, selectedNames());
|
||||
selected.clear();
|
||||
updateDir();
|
||||
}
|
||||
pass = true;
|
||||
break;
|
||||
case PIKbdListener::Return: {
|
||||
e_mutex.lock();
|
||||
bool ud = false;
|
||||
if (cur < entries.size_s() && cur >= 0) {
|
||||
if (!(is_right && remote_mode)) {
|
||||
// piCout << entries[cur];
|
||||
if (entries[cur].isDir()) {
|
||||
prev_pos[dir.path()] = PIPair<int, int>(cur, offset);
|
||||
dir.cd(entries[cur].name());
|
||||
PIPair<int, int> cp = prev_pos.value(dir.path());
|
||||
cur = cp.first;
|
||||
offset = cp.second;
|
||||
selected.clear();
|
||||
ud = true;
|
||||
}
|
||||
}
|
||||
pass = true;
|
||||
}
|
||||
e_mutex.unlock();
|
||||
if (ud) updateDir();
|
||||
} break;
|
||||
}
|
||||
// piCout << is_right << remote_mode << pass;
|
||||
if (is_right && remote_mode && pass) {
|
||||
((void (*)(void *, PIKbdListener::KeyEvent))key_func)(fm, key);
|
||||
return true;
|
||||
}
|
||||
return TileList::keyEvent(key);
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::lock() {
|
||||
if (screen && !resized) ((PIScreen *)screen)->lock();
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::unlock() {
|
||||
if (screen && !resized) ((PIScreen *)screen)->unlock();
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::showReading() {
|
||||
PIMutexLocker ml(e_mutex);
|
||||
cur = -1;
|
||||
offset = 0;
|
||||
entries.clear();
|
||||
content.resize(1);
|
||||
content[0] = Row("... Reading ...", CellFormat());
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::setContent(const PIVector<PIFile::FileInfo> & l) {
|
||||
PIMutexLocker ml(e_mutex);
|
||||
PIVector<PIFile::FileInfo> fl, dl;
|
||||
entries.clear();
|
||||
if (l.isEmpty()) {
|
||||
PIFile::FileInfo fi;
|
||||
fi.path = "..";
|
||||
fi.flags |= PIFile::FileInfo::DotDot | PIFile::FileInfo::Dir;
|
||||
entries << fi;
|
||||
} else {
|
||||
bool root = dir.path() == PIDir::separator;
|
||||
for (int i = 0; i < l.size_s(); ++i) {
|
||||
if (l[i].name() == ".") continue;
|
||||
if (l[i].name() == "..") {
|
||||
if (!root) dl.push_front(l[i]);
|
||||
continue;
|
||||
}
|
||||
if (l[i].isDir())
|
||||
dl << l[i];
|
||||
else
|
||||
fl << l[i];
|
||||
}
|
||||
entries << dl << fl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::updateDir() {
|
||||
lock();
|
||||
int pc = cur, po = offset;
|
||||
showReading();
|
||||
unlock();
|
||||
setContent(dir.entries());
|
||||
if (label_path) {
|
||||
label_path->content.resize(1);
|
||||
label_path->content[0].first = dir.absolutePath();
|
||||
}
|
||||
cur = pc;
|
||||
offset = po;
|
||||
buildNames();
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::buildNames() {
|
||||
lock();
|
||||
PIMutexLocker ml(e_mutex);
|
||||
content.clear();
|
||||
PIChar t;
|
||||
CharFlags cf = 0;
|
||||
Color cc = Default;
|
||||
PIString fcol, scol;
|
||||
piForeachC(PIFile::FileInfo & e, entries) {
|
||||
if (e.isDir()) {
|
||||
t = '/';
|
||||
cf = Bold;
|
||||
scol = " dir";
|
||||
} else {
|
||||
if (e.perm_user.exec || e.perm_group.exec || e.perm_other.exec) {
|
||||
cf = Bold;
|
||||
cc = Green;
|
||||
t = '*';
|
||||
} else {
|
||||
t = ' ';
|
||||
cc = Default;
|
||||
cf = 0;
|
||||
}
|
||||
scol = PIString::readableSize(e.size);
|
||||
}
|
||||
if (e.isSymbolicLink() && (t != '*')) t = '~';
|
||||
scol = scol.expandRightTo(9, ' ') + "| " + e.time_modification.toString("dd.MM hh:mm:ss") + " | " + e.perm_user.toString() + " " +
|
||||
e.perm_group.toString() + " " + e.perm_other.toString();
|
||||
fcol = t + e.name();
|
||||
if (fcol.size_s() >= width_ - 2 - scol.size_s()) fcol = fcol.left(width_ - 5 - scol.size_s()) + "...";
|
||||
fcol.expandRightTo(width_ - 1 - scol.size_s(), ' ');
|
||||
content << Row(fcol + scol, CellFormat(cc, Transparent, cf));
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::sizeHint(int & w, int & h) const {
|
||||
w = h = 4;
|
||||
}
|
||||
|
||||
|
||||
void FileManager::TileDir::resizeEvent(int w, int h) {
|
||||
resized = true;
|
||||
buildNames();
|
||||
resized = false;
|
||||
TileList::resizeEvent(w, h);
|
||||
}
|
||||
|
||||
|
||||
FileManager::FileManager() {
|
||||
setName("FileManager");
|
||||
TileSimple * tl;
|
||||
|
||||
tile_root = new PIScreenTile();
|
||||
tile_root->direction = Vertical;
|
||||
PIScreenTile * pt = new PIScreenTile();
|
||||
pt->direction = Horizontal;
|
||||
pt->spacing = 1;
|
||||
pt->back_format.color_back = Cyan;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
PIScreenTile * panel = new PIScreenTile();
|
||||
TileSimple * plabel = new TileSimple();
|
||||
plabel->size_policy = Fixed;
|
||||
plabel->maximumWidth = 1;
|
||||
panel->direction = Vertical;
|
||||
panels[i] = new TileDir();
|
||||
panels[i]->fm = this;
|
||||
panels[i]->key_func = (void *)tileKey_s;
|
||||
panels[i]->setName("file panel " + PIString::fromNumber(i));
|
||||
panels[i]->label_path = plabel;
|
||||
CONNECTU(panels[i], actionRequest, this, actionRequest)
|
||||
panel->addTile(plabel);
|
||||
panel->addTile(panels[i]);
|
||||
panels[i]->updateDir();
|
||||
pt->addTile(panel);
|
||||
}
|
||||
panels[1]->is_right = true;
|
||||
tile_root->addTile(pt);
|
||||
|
||||
PIScreenTile * labels = new PIScreenTile();
|
||||
labels->size_policy = Fixed;
|
||||
labels->direction = Horizontal;
|
||||
PIVector<SSPair> ll;
|
||||
ll << SSPair(" Esc", "Exit") << SSPair(" F5", "Copy") << SSPair(" F6", "Move") << SSPair(" F7", "MkDir") << SSPair(" F8", "Delete");
|
||||
piForeachC(SSPair & l, ll) {
|
||||
tl = new TileSimple();
|
||||
labels->addTile(tl);
|
||||
tl->content << TileSimple::Row(l.first, CellFormat(White, Transparent, Bold));
|
||||
tl = new TileSimple();
|
||||
labels->addTile(tl);
|
||||
tl->content << TileSimple::Row(l.second, CellFormat(Black, Cyan));
|
||||
}
|
||||
tl = new TileSimple();
|
||||
labels->addTile(tl);
|
||||
tl->size_policy = Expanding;
|
||||
tile_root->addTile(labels);
|
||||
}
|
||||
|
||||
|
||||
PIScreenTile * FileManager::tile() const {
|
||||
return tile_root;
|
||||
}
|
||||
|
||||
|
||||
void FileManager::setLocal() {
|
||||
if (panels[1]->remote_mode) setRemoteDir(panels[0]->dir.absolutePath());
|
||||
panels[0]->remote_mode = panels[1]->remote_mode = false;
|
||||
}
|
||||
|
||||
|
||||
void FileManager::setRemote() {
|
||||
panels[0]->remote_mode = panels[1]->remote_mode = true;
|
||||
}
|
||||
|
||||
|
||||
void FileManager::setRemoteDir(const PIString & d) {
|
||||
panels[1]->dir.setDir(d);
|
||||
if (panels[1]->label_path) {
|
||||
panels[1]->label_path->content.resize(1);
|
||||
panels[1]->label_path->content[0].first = panels[1]->dir.path();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FileManager::setRemoteContent(const PIVector<PIFile::FileInfo> & el) {
|
||||
panels[1]->setContent(el);
|
||||
panels[1]->buildNames();
|
||||
}
|
||||
|
||||
|
||||
int FileManager::selectedPanel() const {
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (panels[i]->hasFocus()) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
PIStringList FileManager::selectedRemote() const {
|
||||
PIStringList ret;
|
||||
panels[1]->lock();
|
||||
PIVector<int> sil = panels[1]->selected.toVector();
|
||||
piForeachC(int i, sil)
|
||||
ret << panels[1]->entries[i].path;
|
||||
panels[1]->unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIFile::FileInfo FileManager::currentRemoteEntry() const {
|
||||
if ((panels[1]->cur < 0) || (panels[1]->cur >= panels[1]->content.size_s())) return PIFile::FileInfo();
|
||||
return panels[1]->entries[panels[1]->cur];
|
||||
}
|
||||
|
||||
|
||||
void FileManager::remoteSaveDir() {
|
||||
panels[1]->prev_pos[panels[1]->dir.path()] = PIPair<int, int>(panels[1]->cur, panels[1]->offset);
|
||||
}
|
||||
|
||||
|
||||
void FileManager::remoteRestoreDir() {
|
||||
PIPair<int, int> cp = panels[1]->prev_pos.value(panels[1]->dir.path());
|
||||
panels[1]->selected.clear();
|
||||
panels[1]->cur = cp.first;
|
||||
panels[1]->offset = cp.second;
|
||||
if ((panels[1]->cur < 0) || (panels[1]->cur >= panels[1]->content.size_s())) panels[1]->cur = 0;
|
||||
}
|
||||
|
||||
@@ -1,74 +1,83 @@
|
||||
#ifndef FILE_MANAGER_H
|
||||
#define FILE_MANAGER_H
|
||||
|
||||
#include "piscreentiles.h"
|
||||
#include "pidir.h"
|
||||
|
||||
|
||||
class FileManager: public PIObject {
|
||||
PIOBJECT(FileManager)
|
||||
public:
|
||||
FileManager();
|
||||
|
||||
PIScreenTile * tile() const;
|
||||
PIScreenTile * localTile() const {return panels[0];}
|
||||
PIScreenTile * remoteTile() const {return panels[1];}
|
||||
|
||||
enum Action {MkDir, Remove, Copy, Move, LocalCopy, Crypt, LocalCrypt};
|
||||
|
||||
void setLocal();
|
||||
void setRemote();
|
||||
void setRemoteDir(const PIString & d);
|
||||
void setRemoteContent(const PIVector<PIFile::FileInfo> & el);
|
||||
PIString remoteDir() const {return panels[1]->dir.absolutePath();}
|
||||
PIString localDir() const {return panels[0]->dir.absolutePath();}
|
||||
int selectedPanel() const;
|
||||
PIStringList selectedRemote() const;
|
||||
PIFile::FileInfo currentRemoteEntry() const;
|
||||
PIFile::FileInfo selectedRemoteEntry(int index) const {return panels[1]->entries[index];}
|
||||
void remoteSaveDir();
|
||||
void remoteRestoreDir();
|
||||
void readingRemote() const {panels[1]->showReading();}
|
||||
void updateLocalDir() {panels[0]->updateDir();}
|
||||
void updateRemoteDir() {panels[1]->updateDir();}
|
||||
void clearSelectionLocal() {panels[0]->selected.clear();}
|
||||
void clearSelectionRemote() {panels[1]->selected.clear();}
|
||||
|
||||
EVENT3(actionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data)
|
||||
|
||||
private:
|
||||
class TileDir: public TileList {
|
||||
PIOBJECT_SUBCLASS(TileDir, TileList)
|
||||
public:
|
||||
TileDir();
|
||||
void updateDir();
|
||||
void buildNames();
|
||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void resizeEvent(int w, int h) override;
|
||||
void lock();
|
||||
void unlock();
|
||||
void showReading();
|
||||
void setContent(const PIVector<PIFile::FileInfo> & l);
|
||||
PIStringList selectedNames() const;
|
||||
TileSimple * label_path;
|
||||
PIVector<PIFile::FileInfo> entries;
|
||||
PIDir dir;
|
||||
PIMap<PIString, PIPair<int, int> > prev_pos;
|
||||
mutable PIMutex e_mutex;
|
||||
bool resized, is_right, remote_mode;
|
||||
void * fm, * key_func;
|
||||
EVENT3(actionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data)
|
||||
};
|
||||
|
||||
EVENT1(tileKey, PIKbdListener::KeyEvent, key)
|
||||
static void tileKey_s(void * fm, PIKbdListener::KeyEvent key) {((FileManager*)fm)->tileKey(key);}
|
||||
|
||||
TileDir * panels[2];
|
||||
PIScreenTile * tile_root;
|
||||
typedef PIPair<PIString, PIString> SSPair;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // FILE_MANAGER_H
|
||||
#ifndef FILE_MANAGER_H
|
||||
#define FILE_MANAGER_H
|
||||
|
||||
#include "pidir.h"
|
||||
#include "piscreentiles.h"
|
||||
|
||||
|
||||
class FileManager: public PIObject {
|
||||
PIOBJECT(FileManager)
|
||||
|
||||
public:
|
||||
FileManager();
|
||||
|
||||
PIScreenTile * tile() const;
|
||||
PIScreenTile * localTile() const { return panels[0]; }
|
||||
PIScreenTile * remoteTile() const { return panels[1]; }
|
||||
|
||||
enum Action {
|
||||
MkDir,
|
||||
Remove,
|
||||
Copy,
|
||||
Move,
|
||||
LocalCopy,
|
||||
Crypt,
|
||||
LocalCrypt
|
||||
};
|
||||
|
||||
void setLocal();
|
||||
void setRemote();
|
||||
void setRemoteDir(const PIString & d);
|
||||
void setRemoteContent(const PIVector<PIFile::FileInfo> & el);
|
||||
PIString remoteDir() const { return panels[1]->dir.absolutePath(); }
|
||||
PIString localDir() const { return panels[0]->dir.absolutePath(); }
|
||||
int selectedPanel() const;
|
||||
PIStringList selectedRemote() const;
|
||||
PIFile::FileInfo currentRemoteEntry() const;
|
||||
PIFile::FileInfo selectedRemoteEntry(int index) const { return panels[1]->entries[index]; }
|
||||
void remoteSaveDir();
|
||||
void remoteRestoreDir();
|
||||
void readingRemote() const { panels[1]->showReading(); }
|
||||
void updateLocalDir() { panels[0]->updateDir(); }
|
||||
void updateRemoteDir() { panels[1]->updateDir(); }
|
||||
void clearSelectionLocal() { panels[0]->selected.clear(); }
|
||||
void clearSelectionRemote() { panels[1]->selected.clear(); }
|
||||
|
||||
EVENT3(actionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data)
|
||||
|
||||
private:
|
||||
class TileDir: public TileList {
|
||||
PIOBJECT_SUBCLASS(TileDir, TileList)
|
||||
|
||||
public:
|
||||
TileDir();
|
||||
void updateDir();
|
||||
void buildNames();
|
||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
||||
void sizeHint(int & w, int & h) const override;
|
||||
void resizeEvent(int w, int h) override;
|
||||
void lock();
|
||||
void unlock();
|
||||
void showReading();
|
||||
void setContent(const PIVector<PIFile::FileInfo> & l);
|
||||
PIStringList selectedNames() const;
|
||||
TileSimple * label_path;
|
||||
PIVector<PIFile::FileInfo> entries;
|
||||
PIDir dir;
|
||||
PIMap<PIString, PIPair<int, int>> prev_pos;
|
||||
mutable PIMutex e_mutex;
|
||||
bool resized, is_right, remote_mode;
|
||||
void *fm, *key_func;
|
||||
EVENT3(actionRequest, bool, remote_tile, FileManager::Action, type, PIVariant, data)
|
||||
};
|
||||
|
||||
EVENT1(tileKey, PIKbdListener::KeyEvent, key)
|
||||
static void tileKey_s(void * fm, PIKbdListener::KeyEvent key) { ((FileManager *)fm)->tileKey(key); }
|
||||
|
||||
TileDir * panels[2];
|
||||
PIScreenTile * tile_root;
|
||||
typedef PIPair<PIString, PIString> SSPair;
|
||||
};
|
||||
|
||||
|
||||
#endif // FILE_MANAGER_H
|
||||
|
||||
@@ -1,414 +1,435 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PIP System Daemon
|
||||
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pisingleapplication.h"
|
||||
#include "pisystemmonitor.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "piprocess.h"
|
||||
#include "picli.h"
|
||||
#include "file_manager.h"
|
||||
#include "daemon.h"
|
||||
#include "shared.h"
|
||||
#include "piintrospection_server.h"
|
||||
|
||||
class _Init {
|
||||
public:
|
||||
_Init() {randomize();}
|
||||
};
|
||||
_Init _pisd_init;
|
||||
|
||||
PISystemMonitor sys_mon;
|
||||
PIScreen * screen = 0;
|
||||
|
||||
|
||||
class MainMenu: public PITimer {
|
||||
PIOBJECT_SUBCLASS(MainMenu, PITimer)
|
||||
public:
|
||||
MainMenu(Daemon & d): daemon_(d) {
|
||||
cur_peer = -1;
|
||||
title = new TileSimple("title");
|
||||
updateTitle(title);
|
||||
title->back_format.color_back = Yellow;
|
||||
title->size_policy = Fixed;
|
||||
screen->rootTile()->addTile(title);
|
||||
|
||||
PIScreenTile * center = new PIScreenTile("center");
|
||||
center->back_format.color_back = Cyan;
|
||||
center->size_policy = Expanding;
|
||||
center->setMargins(2, 2, 1, 1);
|
||||
screen->rootTile()->addTile(center);
|
||||
|
||||
PIScreenTile * mt = tmenu = menuTile();
|
||||
mt->show(); mt->name() = "main menu";
|
||||
center->addTile(mt); mtiles << mt;
|
||||
|
||||
mt = tinfo = infoTile();
|
||||
mt->hide(); mt->name() = "local info";
|
||||
center->addTile(mt); mtiles << mt;
|
||||
|
||||
mt = tdaemon = daemon_.tile();
|
||||
mt->hide(); mt->name() = "daemon";
|
||||
center->addTile(mt); mtiles << mt;
|
||||
|
||||
mt = tpeer = peerTile();
|
||||
mt->hide(); mt->name() = "peer info";
|
||||
center->addTile(mt); mtiles << mt;
|
||||
|
||||
mt = tpeerdiag = peerDiagTile();
|
||||
mt->hide(); mt->name() = "peer diag";
|
||||
center->addTile(mt); mtiles << mt;
|
||||
|
||||
tpicout = new TilePICout();
|
||||
tpicout->hide();
|
||||
tpicout->size_policy = PIScreenTypes::Expanding;
|
||||
screen->rootTile()->addTile(tpicout);
|
||||
|
||||
CONNECTU(screen, tileEvent, this, tileEvent)
|
||||
CONNECTU(screen, keyPressed, this, keyEvent)
|
||||
CONNECTU(&daemon_, menuRequest, this, menuRequest)
|
||||
start(25);
|
||||
}
|
||||
PIScreenTile * menuTile() {
|
||||
TileList * ret = new TileList();
|
||||
ret->content << TileList::Row("Show local info", CellFormat());
|
||||
ret->content << TileList::Row("Local file manager", CellFormat());
|
||||
ret->content << TileList::Row("Connect to another daemon", CellFormat());
|
||||
ret->content << TileList::Row("Peer info", CellFormat());
|
||||
ret->content << TileList::Row("Peer reinit", CellFormat());
|
||||
ret->content << TileList::Row("Peer diagnostics", CellFormat());
|
||||
ret->content << TileList::Row("Peer change self name", CellFormat());
|
||||
ret->content << TileList::Row("Exit", CellFormat());
|
||||
ret->selection_mode = TileList::NoSelection;
|
||||
return ret;
|
||||
}
|
||||
PIScreenTile * infoTile() {
|
||||
TileList * ret = new TileList();
|
||||
local_info_base << TileList::Row("Exec command: " + PISystemInfo::instance()->execCommand, CellFormat());
|
||||
local_info_base << TileList::Row(" Executed on " + PISystemInfo::instance()->execDateTime.toString(), CellFormat());
|
||||
local_info_base << TileList::Row(" Hostname: " + PISystemInfo::instance()->hostname, CellFormat());
|
||||
local_info_base << TileList::Row(" Username: " + PISystemInfo::instance()->user, CellFormat());
|
||||
local_info_base << TileList::Row(" OS name: " + PISystemInfo::instance()->OS_name, CellFormat());
|
||||
local_info_base << TileList::Row(" OS version: " + PISystemInfo::instance()->OS_version, CellFormat());
|
||||
local_info_base << TileList::Row("Architecture: " + PISystemInfo::instance()->architecture, CellFormat());
|
||||
local_info_base << TileList::Row(" CPU count: " + PIString::fromNumber(PISystemInfo::instance()->processorsCount), CellFormat());
|
||||
local_info_base << TileList::Row("", CellFormat());
|
||||
return ret;
|
||||
}
|
||||
PIScreenTile * peerDiagTile() {
|
||||
PIScreenTile * ret = new PIScreenTile();
|
||||
TileSimple * htl = new TileSimple();
|
||||
htl->size_policy = PIScreenTypes::Fixed;
|
||||
ret->direction = PIScreenTypes::Vertical;
|
||||
htl->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name, CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
|
||||
PIScreenTile * diag = new PIScreenTile();
|
||||
diag->direction = PIScreenTypes::Horizontal;
|
||||
peerdiagdata_tl = new TileSimple();
|
||||
peerdiagservice_tl = new TileSimple();
|
||||
ret->addTile(htl);
|
||||
ret->addTile(diag);
|
||||
diag->addTile(peerdiagdata_tl);
|
||||
diag->addTile(peerdiagservice_tl);
|
||||
return ret;
|
||||
}
|
||||
PIScreenTile * peerTile() {
|
||||
PIScreenTile* ret = new PIScreenTile();
|
||||
ret->direction = PIScreenTypes::Vertical;
|
||||
peerinfo_header = new TileSimple();
|
||||
peerinfo_header->size_policy = PIScreenTypes::Fixed;
|
||||
peerinfo_header->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name, CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
|
||||
addrs_tl = new TileList();
|
||||
peers_tl = new TileList();
|
||||
peerinfo_tl = new TileSimple();
|
||||
peermap_tl = new TileList();
|
||||
peerinfo_tl->size_policy = PIScreenTypes::Fixed;
|
||||
ret->addTile(peerinfo_header);
|
||||
ret->addTile(peers_tl);
|
||||
ret->addTile(peerinfo_tl);
|
||||
ret->addTile(addrs_tl);
|
||||
ret->addTile(peermap_tl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void updateTitle(TileSimple * tl) {
|
||||
tl->content.clear();
|
||||
tl->content << TileSimple::Row("pisd (PI System Daemon, PIP version " + PIPVersion() + ")", CellFormat(Black, Transparent));
|
||||
tl->content << TileSimple::Row("This daemon: \"" + daemon_.thisDaemonName() + "\"", CellFormat(Black, Transparent));
|
||||
}
|
||||
void updatePeerDiag(TileSimple * tl, const PIDiagnostics & diag) {
|
||||
tl->content.clear();
|
||||
PIDiagnostics::State ds = diag.state();
|
||||
tl->content << TileSimple::Row(diag.name() + " diagnostics", CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
|
||||
tl->content << TileSimple::Row("Received count: " + PIString::fromNumber(ds.received_packets), CellFormat());
|
||||
tl->content << TileSimple::Row("Invalid count: " + PIString::fromNumber(ds.received_packets_wrong), CellFormat());
|
||||
tl->content << TileSimple::Row("Sended count: " + PIString::fromNumber(ds.sended_packets), CellFormat());
|
||||
tl->content << TileSimple::Row("Immediate Frequency, Hz: " + PIString::fromNumber(ds.immediate_freq), CellFormat());
|
||||
tl->content << TileSimple::Row("Integral Frequency, Hz: " + PIString::fromNumber(ds.integral_freq), CellFormat());
|
||||
tl->content << TileSimple::Row("Receive speed: " + ds.receive_speed, CellFormat());
|
||||
tl->content << TileSimple::Row("Send speed: " + ds.send_speed, CellFormat());
|
||||
tl->content << TileSimple::Row("Quality: " + PIString::fromNumber((int)ds.quality), CellFormat());
|
||||
}
|
||||
void updatePeerInfo() {
|
||||
// bool pm = daemon_.lockedPeers();
|
||||
screen->lock();
|
||||
daemon_.lock();
|
||||
peers_tl->content.clear();
|
||||
addrs_tl->content.clear();
|
||||
peerinfo_tl->content.clear();
|
||||
peermap_tl->content.clear();
|
||||
peers_tl->content << TileList::Row("this | 0 | 0 | " + PIString::fromNumber(daemon_.allPeers().size_s())
|
||||
// + " [em = " + PIString::fromBool(daemon_.lockedEth()) + ", "
|
||||
// "mm = " + PIString::fromBool(daemon_.lockedMBcasts()) + ", "
|
||||
// "sm = " + PIString::fromBool(daemon_.lockedSends()) + ", "
|
||||
// "ms = " + PIString::fromBool(daemon_.lockedMCSends()) + ", "
|
||||
// "pm = " + PIString::fromBool(pm) + "]"
|
||||
, CellFormat());
|
||||
piForeachC(PIPeer::PeerInfo &p , daemon_.allPeers())
|
||||
peers_tl->content << TileList::Row(p.name + " | d = " + PIString::fromNumber(p.dist) +
|
||||
" | p = " + PIString::fromNumber(p.ping()) +
|
||||
" | n = " + PIString::fromBool(p.isNeighbour())
|
||||
, CellFormat());
|
||||
PIPeer::PeerInfo pi = daemon_.selfInfo();
|
||||
if (cur_peer >= 0 && cur_peer < daemon_.allPeers().size_s()) pi = daemon_.allPeers()[cur_peer];
|
||||
peerinfo_tl->content << TileSimple::Row("Name: " + pi.name, CellFormat());
|
||||
peerinfo_tl->content << TileSimple::Row("Addreses: " + PIString::fromNumber(pi.addresses.size()), CellFormat());
|
||||
peerinfo_tl->content << TileSimple::Row("Neighbours: " + pi.neighbours.join(", "), CellFormat());
|
||||
piForeachC(PIPeer::PeerInfo::PeerAddress &a , pi.addresses)
|
||||
addrs_tl->content << TileList::Row(a.address.toString() +
|
||||
" | p = " + PIString::fromNumber(a.ping) +
|
||||
" | a = " + PIString::fromBool(a.isAvailable()), CellFormat());
|
||||
PIStringList peermap;
|
||||
for (auto p = daemon_._peerMap().begin(); p != daemon_._peerMap().end(); p++) {
|
||||
PIString s = p.key() + " | ";
|
||||
piForeachCR(PIPeer::PeerInfo * pp, p.value()) s += " -> " + pp->name;
|
||||
peermap << s;
|
||||
}
|
||||
piForeachC(PIString &s , peermap)
|
||||
peermap_tl->content << TileList::Row(s, CellFormat());
|
||||
updatePeerDiag(peerdiagdata_tl, daemon_.diagnosticData());
|
||||
updatePeerDiag(peerdiagservice_tl, daemon_.diagnosticService());
|
||||
daemon_.unlock();
|
||||
screen->unlock();
|
||||
}
|
||||
void updateSysMon() {
|
||||
TileList * tile = (TileList*)tinfo;
|
||||
PIVector<PISystemMonitor::ThreadStats> ts = sys_mon.threadsStatistic();
|
||||
screen->lock();
|
||||
tile->content = local_info_base;
|
||||
int num = 0, maxlen = 0;
|
||||
PIString line = "Process load: k ";
|
||||
PIString ns = PIString::fromNumber(sys_mon.statistic().cpu_load_system, 'f', 2);
|
||||
line += ns.expandLeftTo(5, ' ') + " %, u ";
|
||||
ns = PIString::fromNumber(sys_mon.statistic().cpu_load_user, 'f', 2);
|
||||
line += ns.expandLeftTo(5, ' ') + " %";
|
||||
tile->content << TileList::Row("PID: " + PIString::fromNumber(sys_mon.statistic().ID), CellFormat());
|
||||
tile->content << TileList::Row(line, CellFormat());
|
||||
tile->content << TileList::Row("Threads:", CellFormat());
|
||||
piForeachC (PISystemMonitor::ThreadStats & t, ts)
|
||||
maxlen = piMaxi(maxlen, t.name.length());
|
||||
piForeachC (PISystemMonitor::ThreadStats & t, ts) {
|
||||
line = PIString::fromNumber(++num).expandLeftTo(2, ' ') + ": ";
|
||||
line += PIString(t.name).expandRightTo(maxlen, ' ') + ": k ";
|
||||
PIString ns = PIString::fromNumber(t.cpu_load_kernel, 'f', 2);
|
||||
line += ns.expandLeftTo(5, ' ') + " %, u ";
|
||||
ns = PIString::fromNumber(t.cpu_load_user, 'f', 2);
|
||||
line += ns.expandLeftTo(5, ' ') + " %";
|
||||
tile->content << TileList::Row(line, CellFormat());
|
||||
}
|
||||
screen->unlock();
|
||||
}
|
||||
void tick(void* data_, int delimiter) override {
|
||||
if (tpeerdiag->visible || tpeer->visible)
|
||||
updatePeerInfo();
|
||||
if (tinfo->visible)
|
||||
updateSysMon();
|
||||
}
|
||||
EVENT_HANDLER(void, menuRequest) {
|
||||
piForeach (PIScreenTile * t, mtiles)
|
||||
t->hide();
|
||||
daemon_.disconnect();
|
||||
tmenu->show();
|
||||
tmenu->setFocus();
|
||||
}
|
||||
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e) {
|
||||
if (t == tmenu) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
piForeach (PIScreenTile * t, mtiles)
|
||||
t->hide();
|
||||
switch (e.data.toInt()) {
|
||||
case 0: tinfo->show(); break;
|
||||
case 1: daemon_.fm.setLocal(); daemon_.showLocalFilemanager(); tdaemon->show(); break;
|
||||
case 2: daemon_.fm.setRemote(); daemon_.showMainList(); tdaemon->show(); break;
|
||||
case 3: tpeer->show(); peers_tl->setFocus(); break;
|
||||
case 4: daemon_.reinit(); tmenu->show(); break;
|
||||
case 5: tpeerdiag->show(); break;
|
||||
case 6:
|
||||
{
|
||||
PIString nn = askUserInput("Peer name:");
|
||||
if (!nn.isEmpty()) {
|
||||
daemon_.changeName(pisd_prefix + nn);
|
||||
peerinfo_header->content.clear();
|
||||
peerinfo_header->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name, CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
|
||||
updateTitle(title);
|
||||
}
|
||||
menuRequest();
|
||||
}
|
||||
break;
|
||||
case 7: PIKbdListener::exiting = true; break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (t == peers_tl) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
cur_peer = e.data.toInt() - 1;
|
||||
updatePeerInfo();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, e) {
|
||||
if (e.key == PIKbdListener::F9) {
|
||||
tpicout->visible = !tpicout->visible;
|
||||
return;
|
||||
}
|
||||
if (e.key == PIKbdListener::Esc && e.modifiers[PIKbdListener::Shift]) {
|
||||
PIKbdListener::exiting = true;
|
||||
return;
|
||||
}
|
||||
if (screen->dialogTile()) return;
|
||||
if (tpeer->visible || tinfo->visible || tpeerdiag->visible)
|
||||
if (e.key == PIKbdListener::Esc) menuRequest();
|
||||
//piCout << "key" << e.key;
|
||||
}
|
||||
EVENT_HANDLER1(void, messageFromApp, PIByteArray, m) {
|
||||
if (m[0] == 'k') PIKbdListener::exiting = true;
|
||||
|
||||
}
|
||||
Daemon & daemon_;
|
||||
PIScreenTile * tmenu, * tinfo, * tfm, * tdaemon, * tpeer, * tpeerdiag;
|
||||
TileList * peers_tl, * addrs_tl, * peermap_tl;
|
||||
TilePICout * tpicout;
|
||||
TileSimple * title;
|
||||
TileSimple * peerinfo_tl, * peerinfo_header;
|
||||
TileSimple * peerdiagdata_tl, * peerdiagservice_tl;
|
||||
PIVector<PIScreenTile * > mtiles;
|
||||
PIDeque<TileList::Row> local_info_base;
|
||||
int cur_peer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << PICoutManipulators::Bold << "PIP System Daemon";
|
||||
piCout << PICoutManipulators::Cyan << "Version" << PICoutManipulators::Bold << PIPVersion() << PICoutManipulators::NewLine;
|
||||
piCout << PICoutManipulators::Green << PICoutManipulators::Bold << "Usage:" << PICoutManipulators::Default
|
||||
<< "\"pisd [-1hdfk] [-n <name>] [-a <ip>]\"" << PICoutManipulators::NewLine;
|
||||
piCout << PICoutManipulators::Green << PICoutManipulators::Bold << "Details:";
|
||||
piCout << "-h --help " << PICoutManipulators::Green << "- display this message and exit";
|
||||
piCout << "-d --daemon " << PICoutManipulators::Green << "- start as daemon";
|
||||
piCout << "-k --kill " << PICoutManipulators::Green << "- kill daemon";
|
||||
piCout << "-f --force " << PICoutManipulators::Green << "- don`t check for another running instance";
|
||||
piCout << "-n --name <name> " << PICoutManipulators::Green << "- set daemon name";
|
||||
piCout << "-a --address <ip>" << PICoutManipulators::Green << "- connect to remote daemon via tcp";
|
||||
piCout << "-s --silent " << PICoutManipulators::Green << "- run without user interfase";
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
sys_mon.startOnSelf();
|
||||
//piDebug = false;
|
||||
PICLI cli(argc, argv);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("daemon");
|
||||
cli.addArgument("force");
|
||||
cli.addArgument("kill");
|
||||
cli.addArgument("1");
|
||||
cli.addArgument("silent");
|
||||
cli.addArgument("name", true);
|
||||
cli.addArgument("address", true);
|
||||
if (cli.hasArgument("help")) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
PIString name = cli.argumentValue("name");
|
||||
PIString sip = cli.argumentValue("address");
|
||||
PISingleApplication * sapp = 0;
|
||||
if ((cli.hasArgument("1") && !cli.hasArgument("force")) || cli.hasArgument("kill")) {
|
||||
sapp = new PISingleApplication("pisd");
|
||||
if (cli.hasArgument("1")) {
|
||||
if (!sapp->isFirst()) {
|
||||
piCout << "Another pisd is running, exit";
|
||||
delete sapp;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (cli.hasArgument("kill")) {
|
||||
sapp->sendMessage(PIByteArray("k", 1));
|
||||
delete sapp;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PIINTROSPECTION_START(pisd)
|
||||
if (cli.hasArgument("daemon")) {
|
||||
PIStringList args;
|
||||
args << "-1" << "-s";
|
||||
if (cli.hasArgument("force"))
|
||||
args << "-f";
|
||||
if (cli.hasArgument("address"))
|
||||
args << "-a" << sip;
|
||||
if (!name.isEmpty())
|
||||
args << "-n" << name;
|
||||
PIString exe;
|
||||
#ifdef WINDOWS
|
||||
exe = PISystemInfo::instance()->execCommand;
|
||||
#else
|
||||
exe = PIProcess::getEnvironmentVariable("_");
|
||||
#endif
|
||||
piCout << "start in background:" << exe;// << "; with args" << args;
|
||||
PIProcess::execIndependent(exe, args);
|
||||
return 0;
|
||||
}
|
||||
screen = new PIScreen(false);
|
||||
screen->setMouseEnabled(true);
|
||||
Daemon * daemon = new Daemon();
|
||||
if (!sip.isEmpty()) daemon->setTcpServerIP(sip);
|
||||
screen->enableExitCapture(PIKbdListener::F10);
|
||||
if (!name.isEmpty())
|
||||
daemon->changeName(pisd_prefix + name);
|
||||
MainMenu * menu = new MainMenu(*daemon);
|
||||
if (sapp) CONNECTU(sapp, messageReceived, menu, messageFromApp);
|
||||
if (cli.hasArgument("silent")) {
|
||||
PICout::setOutputDevices(PICout::StdOut);
|
||||
PIKbdListener ls;
|
||||
ls.enableExitCapture(PIKbdListener::F10);
|
||||
ls.start();
|
||||
WAIT_FOR_EXIT
|
||||
ls.stop();
|
||||
} else {
|
||||
screen->start();
|
||||
screen->waitForFinish();
|
||||
screen->stop(true);
|
||||
}
|
||||
sys_mon.stop();
|
||||
delete menu;
|
||||
delete daemon;
|
||||
delete screen;
|
||||
if (sapp) delete sapp;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
PIP System Daemon
|
||||
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "daemon.h"
|
||||
#include "file_manager.h"
|
||||
#include "picli.h"
|
||||
#include "piintrospection_server.h"
|
||||
#include "piprocess.h"
|
||||
#include "pisingleapplication.h"
|
||||
#include "pisysteminfo.h"
|
||||
#include "pisystemmonitor.h"
|
||||
#include "shared.h"
|
||||
|
||||
class _Init {
|
||||
public:
|
||||
_Init() { randomize(); }
|
||||
};
|
||||
_Init _pisd_init;
|
||||
|
||||
PISystemMonitor sys_mon;
|
||||
PIScreen * screen = 0;
|
||||
|
||||
|
||||
class MainMenu: public PITimer {
|
||||
PIOBJECT_SUBCLASS(MainMenu, PITimer)
|
||||
|
||||
public:
|
||||
MainMenu(Daemon & d): daemon_(d) {
|
||||
cur_peer = -1;
|
||||
title = new TileSimple("title");
|
||||
updateTitle(title);
|
||||
title->back_format.color_back = Yellow;
|
||||
title->size_policy = Fixed;
|
||||
screen->rootTile()->addTile(title);
|
||||
|
||||
PIScreenTile * center = new PIScreenTile("center");
|
||||
center->back_format.color_back = Cyan;
|
||||
center->size_policy = Expanding;
|
||||
center->setMargins(2, 2, 1, 1);
|
||||
screen->rootTile()->addTile(center);
|
||||
|
||||
PIScreenTile * mt = tmenu = menuTile();
|
||||
mt->show();
|
||||
mt->name() = "main menu";
|
||||
center->addTile(mt);
|
||||
mtiles << mt;
|
||||
|
||||
mt = tinfo = infoTile();
|
||||
mt->hide();
|
||||
mt->name() = "local info";
|
||||
center->addTile(mt);
|
||||
mtiles << mt;
|
||||
|
||||
mt = tdaemon = daemon_.tile();
|
||||
mt->hide();
|
||||
mt->name() = "daemon";
|
||||
center->addTile(mt);
|
||||
mtiles << mt;
|
||||
|
||||
mt = tpeer = peerTile();
|
||||
mt->hide();
|
||||
mt->name() = "peer info";
|
||||
center->addTile(mt);
|
||||
mtiles << mt;
|
||||
|
||||
mt = tpeerdiag = peerDiagTile();
|
||||
mt->hide();
|
||||
mt->name() = "peer diag";
|
||||
center->addTile(mt);
|
||||
mtiles << mt;
|
||||
|
||||
tpicout = new TilePICout();
|
||||
tpicout->hide();
|
||||
tpicout->size_policy = PIScreenTypes::Expanding;
|
||||
screen->rootTile()->addTile(tpicout);
|
||||
|
||||
CONNECTU(screen, tileEvent, this, tileEvent)
|
||||
CONNECTU(screen, keyPressed, this, keyEvent)
|
||||
CONNECTU(&daemon_, menuRequest, this, menuRequest)
|
||||
start(25);
|
||||
}
|
||||
PIScreenTile * menuTile() {
|
||||
TileList * ret = new TileList();
|
||||
ret->content << TileList::Row("Show local info", CellFormat());
|
||||
ret->content << TileList::Row("Local file manager", CellFormat());
|
||||
ret->content << TileList::Row("Connect to another daemon", CellFormat());
|
||||
ret->content << TileList::Row("Peer info", CellFormat());
|
||||
ret->content << TileList::Row("Peer reinit", CellFormat());
|
||||
ret->content << TileList::Row("Peer diagnostics", CellFormat());
|
||||
ret->content << TileList::Row("Peer change self name", CellFormat());
|
||||
ret->content << TileList::Row("Exit", CellFormat());
|
||||
ret->selection_mode = TileList::NoSelection;
|
||||
return ret;
|
||||
}
|
||||
PIScreenTile * infoTile() {
|
||||
TileList * ret = new TileList();
|
||||
local_info_base << TileList::Row("Exec command: " + PISystemInfo::instance()->execCommand, CellFormat());
|
||||
local_info_base << TileList::Row(" Executed on " + PISystemInfo::instance()->execDateTime.toString(), CellFormat());
|
||||
local_info_base << TileList::Row(" Hostname: " + PISystemInfo::instance()->hostname, CellFormat());
|
||||
local_info_base << TileList::Row(" Username: " + PISystemInfo::instance()->user, CellFormat());
|
||||
local_info_base << TileList::Row(" OS name: " + PISystemInfo::instance()->OS_name, CellFormat());
|
||||
local_info_base << TileList::Row(" OS version: " + PISystemInfo::instance()->OS_version, CellFormat());
|
||||
local_info_base << TileList::Row("Architecture: " + PISystemInfo::instance()->architecture, CellFormat());
|
||||
local_info_base << TileList::Row(" CPU count: " + PIString::fromNumber(PISystemInfo::instance()->processorsCount), CellFormat());
|
||||
local_info_base << TileList::Row("", CellFormat());
|
||||
return ret;
|
||||
}
|
||||
PIScreenTile * peerDiagTile() {
|
||||
PIScreenTile * ret = new PIScreenTile();
|
||||
TileSimple * htl = new TileSimple();
|
||||
htl->size_policy = PIScreenTypes::Fixed;
|
||||
ret->direction = PIScreenTypes::Vertical;
|
||||
htl->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name,
|
||||
CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
|
||||
PIScreenTile * diag = new PIScreenTile();
|
||||
diag->direction = PIScreenTypes::Horizontal;
|
||||
peerdiagdata_tl = new TileSimple();
|
||||
peerdiagservice_tl = new TileSimple();
|
||||
ret->addTile(htl);
|
||||
ret->addTile(diag);
|
||||
diag->addTile(peerdiagdata_tl);
|
||||
diag->addTile(peerdiagservice_tl);
|
||||
return ret;
|
||||
}
|
||||
PIScreenTile * peerTile() {
|
||||
PIScreenTile * ret = new PIScreenTile();
|
||||
ret->direction = PIScreenTypes::Vertical;
|
||||
peerinfo_header = new TileSimple();
|
||||
peerinfo_header->size_policy = PIScreenTypes::Fixed;
|
||||
peerinfo_header->content << TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name,
|
||||
CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
|
||||
addrs_tl = new TileList();
|
||||
peers_tl = new TileList();
|
||||
peerinfo_tl = new TileSimple();
|
||||
peermap_tl = new TileList();
|
||||
peerinfo_tl->size_policy = PIScreenTypes::Fixed;
|
||||
ret->addTile(peerinfo_header);
|
||||
ret->addTile(peers_tl);
|
||||
ret->addTile(peerinfo_tl);
|
||||
ret->addTile(addrs_tl);
|
||||
ret->addTile(peermap_tl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void updateTitle(TileSimple * tl) {
|
||||
tl->content.clear();
|
||||
tl->content << TileSimple::Row("pisd (PI System Daemon, PIP version " + PIPVersion() + ")", CellFormat(Black, Transparent));
|
||||
tl->content << TileSimple::Row("This daemon: \"" + daemon_.thisDaemonName() + "\"", CellFormat(Black, Transparent));
|
||||
}
|
||||
void updatePeerDiag(TileSimple * tl, const PIDiagnostics & diag) {
|
||||
tl->content.clear();
|
||||
PIDiagnostics::State ds = diag.state();
|
||||
tl->content << TileSimple::Row(diag.name() + " diagnostics",
|
||||
CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
|
||||
tl->content << TileSimple::Row("Received count: " + PIString::fromNumber(ds.received_packets), CellFormat());
|
||||
tl->content << TileSimple::Row("Invalid count: " + PIString::fromNumber(ds.received_packets_wrong), CellFormat());
|
||||
tl->content << TileSimple::Row("Sended count: " + PIString::fromNumber(ds.sended_packets), CellFormat());
|
||||
tl->content << TileSimple::Row("Immediate Frequency, Hz: " + PIString::fromNumber(ds.immediate_freq), CellFormat());
|
||||
tl->content << TileSimple::Row("Integral Frequency, Hz: " + PIString::fromNumber(ds.integral_freq), CellFormat());
|
||||
tl->content << TileSimple::Row("Receive speed: " + ds.receive_speed, CellFormat());
|
||||
tl->content << TileSimple::Row("Send speed: " + ds.send_speed, CellFormat());
|
||||
tl->content << TileSimple::Row("Quality: " + PIString::fromNumber((int)ds.quality), CellFormat());
|
||||
}
|
||||
void updatePeerInfo() {
|
||||
// bool pm = daemon_.lockedPeers();
|
||||
screen->lock();
|
||||
daemon_.lock();
|
||||
peers_tl->content.clear();
|
||||
addrs_tl->content.clear();
|
||||
peerinfo_tl->content.clear();
|
||||
peermap_tl->content.clear();
|
||||
peers_tl->content << TileList::Row("this | 0 | 0 | " + PIString::fromNumber(daemon_.allPeers().size_s())
|
||||
// + " [em = " + PIString::fromBool(daemon_.lockedEth()) + ",
|
||||
//" "mm = " + PIString::fromBool(daemon_.lockedMBcasts()) + ", " "sm = " +
|
||||
//PIString::fromBool(daemon_.lockedSends()) + ", " "ms = " +
|
||||
//PIString::fromBool(daemon_.lockedMCSends()) + ", " "pm = " + PIString::fromBool(pm) + "]"
|
||||
,
|
||||
CellFormat());
|
||||
piForeachC(PIPeer::PeerInfo & p, daemon_.allPeers())
|
||||
peers_tl->content << TileList::Row(p.name + " | d = " + PIString::fromNumber(p.dist) + " | p = " +
|
||||
PIString::fromNumber(p.ping()) + " | n = " + PIString::fromBool(p.isNeighbour()),
|
||||
CellFormat());
|
||||
PIPeer::PeerInfo pi = daemon_.selfInfo();
|
||||
if (cur_peer >= 0 && cur_peer < daemon_.allPeers().size_s()) pi = daemon_.allPeers()[cur_peer];
|
||||
peerinfo_tl->content << TileSimple::Row("Name: " + pi.name, CellFormat());
|
||||
peerinfo_tl->content << TileSimple::Row("Addreses: " + PIString::fromNumber(pi.addresses.size()), CellFormat());
|
||||
peerinfo_tl->content << TileSimple::Row("Neighbours: " + pi.neighbours.join(", "), CellFormat());
|
||||
piForeachC(PIPeer::PeerInfo::PeerAddress & a, pi.addresses)
|
||||
addrs_tl->content << TileList::Row(a.address.toString() + " | p = " + PIString::fromNumber(a.ping) +
|
||||
" | a = " + PIString::fromBool(a.isAvailable()),
|
||||
CellFormat());
|
||||
PIStringList peermap;
|
||||
for (auto p = daemon_._peerMap().begin(); p != daemon_._peerMap().end(); p++) {
|
||||
PIString s = p.key() + " | ";
|
||||
piForeachCR(PIPeer::PeerInfo * pp, p.value())
|
||||
s += " -> " + pp->name;
|
||||
peermap << s;
|
||||
}
|
||||
piForeachC(PIString & s, peermap)
|
||||
peermap_tl->content << TileList::Row(s, CellFormat());
|
||||
updatePeerDiag(peerdiagdata_tl, daemon_.diagnosticData());
|
||||
updatePeerDiag(peerdiagservice_tl, daemon_.diagnosticService());
|
||||
daemon_.unlock();
|
||||
screen->unlock();
|
||||
}
|
||||
void updateSysMon() {
|
||||
TileList * tile = (TileList *)tinfo;
|
||||
PIVector<PISystemMonitor::ThreadStats> ts = sys_mon.threadsStatistic();
|
||||
screen->lock();
|
||||
tile->content = local_info_base;
|
||||
int num = 0, maxlen = 0;
|
||||
PIString line = "Process load: k ";
|
||||
PIString ns = PIString::fromNumber(sys_mon.statistic().cpu_load_system, 'f', 2);
|
||||
line += ns.expandLeftTo(5, ' ') + " %, u ";
|
||||
ns = PIString::fromNumber(sys_mon.statistic().cpu_load_user, 'f', 2);
|
||||
line += ns.expandLeftTo(5, ' ') + " %";
|
||||
tile->content << TileList::Row("PID: " + PIString::fromNumber(sys_mon.statistic().ID), CellFormat());
|
||||
tile->content << TileList::Row(line, CellFormat());
|
||||
tile->content << TileList::Row("Threads:", CellFormat());
|
||||
piForeachC(PISystemMonitor::ThreadStats & t, ts)
|
||||
maxlen = piMaxi(maxlen, t.name.length());
|
||||
piForeachC(PISystemMonitor::ThreadStats & t, ts) {
|
||||
line = PIString::fromNumber(++num).expandLeftTo(2, ' ') + ": ";
|
||||
line += PIString(t.name).expandRightTo(maxlen, ' ') + ": k ";
|
||||
PIString ns = PIString::fromNumber(t.cpu_load_kernel, 'f', 2);
|
||||
line += ns.expandLeftTo(5, ' ') + " %, u ";
|
||||
ns = PIString::fromNumber(t.cpu_load_user, 'f', 2);
|
||||
line += ns.expandLeftTo(5, ' ') + " %";
|
||||
tile->content << TileList::Row(line, CellFormat());
|
||||
}
|
||||
screen->unlock();
|
||||
}
|
||||
void tick(void * data_, int delimiter) override {
|
||||
if (tpeerdiag->visible || tpeer->visible) updatePeerInfo();
|
||||
if (tinfo->visible) updateSysMon();
|
||||
}
|
||||
EVENT_HANDLER(void, menuRequest) {
|
||||
piForeach(PIScreenTile * t, mtiles)
|
||||
t->hide();
|
||||
daemon_.disconnect();
|
||||
tmenu->show();
|
||||
tmenu->setFocus();
|
||||
}
|
||||
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e) {
|
||||
if (t == tmenu) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
piForeach(PIScreenTile * t, mtiles)
|
||||
t->hide();
|
||||
switch (e.data.toInt()) {
|
||||
case 0: tinfo->show(); break;
|
||||
case 1:
|
||||
daemon_.fm.setLocal();
|
||||
daemon_.showLocalFilemanager();
|
||||
tdaemon->show();
|
||||
break;
|
||||
case 2:
|
||||
daemon_.fm.setRemote();
|
||||
daemon_.showMainList();
|
||||
tdaemon->show();
|
||||
break;
|
||||
case 3:
|
||||
tpeer->show();
|
||||
peers_tl->setFocus();
|
||||
break;
|
||||
case 4:
|
||||
daemon_.reinit();
|
||||
tmenu->show();
|
||||
break;
|
||||
case 5: tpeerdiag->show(); break;
|
||||
case 6: {
|
||||
PIString nn = askUserInput("Peer name:");
|
||||
if (!nn.isEmpty()) {
|
||||
daemon_.changeName(pisd_prefix + nn);
|
||||
peerinfo_header->content.clear();
|
||||
peerinfo_header->content
|
||||
<< TileSimple::Row("Peer: " + daemon_.name() + " | " + daemon_.selfInfo().name,
|
||||
CellFormat(PIScreenTypes::Default, PIScreenTypes::Default, PIScreenTypes::Bold));
|
||||
updateTitle(title);
|
||||
}
|
||||
menuRequest();
|
||||
} break;
|
||||
case 7: PIKbdListener::exiting = true; break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (t == peers_tl) {
|
||||
if (e.type == TileList::RowPressed) {
|
||||
cur_peer = e.data.toInt() - 1;
|
||||
updatePeerInfo();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, e) {
|
||||
if (e.key == PIKbdListener::F9) {
|
||||
tpicout->visible = !tpicout->visible;
|
||||
return;
|
||||
}
|
||||
if (e.key == PIKbdListener::Esc && e.modifiers[PIKbdListener::Shift]) {
|
||||
PIKbdListener::exiting = true;
|
||||
return;
|
||||
}
|
||||
if (screen->dialogTile()) return;
|
||||
if (tpeer->visible || tinfo->visible || tpeerdiag->visible)
|
||||
if (e.key == PIKbdListener::Esc) menuRequest();
|
||||
// piCout << "key" << e.key;
|
||||
}
|
||||
EVENT_HANDLER1(void, messageFromApp, PIByteArray, m) {
|
||||
if (m[0] == 'k') PIKbdListener::exiting = true;
|
||||
}
|
||||
Daemon & daemon_;
|
||||
PIScreenTile *tmenu, *tinfo, *tfm, *tdaemon, *tpeer, *tpeerdiag;
|
||||
TileList *peers_tl, *addrs_tl, *peermap_tl;
|
||||
TilePICout * tpicout;
|
||||
TileSimple * title;
|
||||
TileSimple *peerinfo_tl, *peerinfo_header;
|
||||
TileSimple *peerdiagdata_tl, *peerdiagservice_tl;
|
||||
PIVector<PIScreenTile *> mtiles;
|
||||
PIDeque<TileList::Row> local_info_base;
|
||||
int cur_peer;
|
||||
};
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << PICoutManipulators::Bold << "PIP System Daemon";
|
||||
piCout << PICoutManipulators::Cyan << "Version" << PICoutManipulators::Bold << PIPVersion() << PICoutManipulators::NewLine;
|
||||
piCout << PICoutManipulators::Green << PICoutManipulators::Bold << "Usage:" << PICoutManipulators::Default
|
||||
<< "\"pisd [-1hdfk] [-n <name>] [-a <ip>]\"" << PICoutManipulators::NewLine;
|
||||
piCout << PICoutManipulators::Green << PICoutManipulators::Bold << "Details:";
|
||||
piCout << "-h --help " << PICoutManipulators::Green << "- display this message and exit";
|
||||
piCout << "-d --daemon " << PICoutManipulators::Green << "- start as daemon";
|
||||
piCout << "-k --kill " << PICoutManipulators::Green << "- kill daemon";
|
||||
piCout << "-f --force " << PICoutManipulators::Green << "- don`t check for another running instance";
|
||||
piCout << "-n --name <name> " << PICoutManipulators::Green << "- set daemon name";
|
||||
piCout << "-a --address <ip>" << PICoutManipulators::Green << "- connect to remote daemon via tcp";
|
||||
piCout << "-s --silent " << PICoutManipulators::Green << "- run without user interfase";
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
sys_mon.startOnSelf();
|
||||
// piDebug = false;
|
||||
PICLI cli(argc, argv);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("daemon");
|
||||
cli.addArgument("force");
|
||||
cli.addArgument("kill");
|
||||
cli.addArgument("1");
|
||||
cli.addArgument("silent");
|
||||
cli.addArgument("name", true);
|
||||
cli.addArgument("address", true);
|
||||
if (cli.hasArgument("help")) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
PIString name = cli.argumentValue("name");
|
||||
PIString sip = cli.argumentValue("address");
|
||||
PISingleApplication * sapp = 0;
|
||||
if ((cli.hasArgument("1") && !cli.hasArgument("force")) || cli.hasArgument("kill")) {
|
||||
sapp = new PISingleApplication("pisd");
|
||||
if (cli.hasArgument("1")) {
|
||||
if (!sapp->isFirst()) {
|
||||
piCout << "Another pisd is running, exit";
|
||||
delete sapp;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (cli.hasArgument("kill")) {
|
||||
sapp->sendMessage(PIByteArray("k", 1));
|
||||
delete sapp;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PIINTROSPECTION_START(pisd)
|
||||
if (cli.hasArgument("daemon")) {
|
||||
PIStringList args;
|
||||
args << "-1"
|
||||
<< "-s";
|
||||
if (cli.hasArgument("force")) args << "-f";
|
||||
if (cli.hasArgument("address")) args << "-a" << sip;
|
||||
if (!name.isEmpty()) args << "-n" << name;
|
||||
PIString exe;
|
||||
#ifdef WINDOWS
|
||||
exe = PISystemInfo::instance()->execCommand;
|
||||
#else
|
||||
exe = PIProcess::getEnvironmentVariable("_");
|
||||
#endif
|
||||
piCout << "start in background:" << exe; // << "; with args" << args;
|
||||
PIProcess::execIndependent(exe, args);
|
||||
return 0;
|
||||
}
|
||||
screen = new PIScreen(false);
|
||||
screen->setMouseEnabled(true);
|
||||
Daemon * daemon = new Daemon();
|
||||
if (!sip.isEmpty()) daemon->setTcpServerIP(sip);
|
||||
screen->enableExitCapture(PIKbdListener::F10);
|
||||
if (!name.isEmpty()) daemon->changeName(pisd_prefix + name);
|
||||
MainMenu * menu = new MainMenu(*daemon);
|
||||
if (sapp) CONNECTU(sapp, messageReceived, menu, messageFromApp);
|
||||
if (cli.hasArgument("silent")) {
|
||||
PICout::setOutputDevices(PICout::StdOut);
|
||||
PIKbdListener ls;
|
||||
ls.enableExitCapture(PIKbdListener::F10);
|
||||
ls.start();
|
||||
WAIT_FOR_EXIT
|
||||
ls.stop();
|
||||
} else {
|
||||
screen->start();
|
||||
screen->waitForFinish();
|
||||
screen->stop(true);
|
||||
}
|
||||
sys_mon.stop();
|
||||
delete menu;
|
||||
delete daemon;
|
||||
delete screen;
|
||||
if (sapp) delete sapp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,176 +1,181 @@
|
||||
#include "shared.h"
|
||||
#include "picrypt.h"
|
||||
|
||||
extern PIScreen * screen;
|
||||
|
||||
|
||||
class DlgWatcher: public PIThread {
|
||||
PIOBJECT(DlgWatcher)
|
||||
public:
|
||||
DlgWatcher() {close = ok = false;}
|
||||
EVENT_HANDLER2(void, tileEvent, PIScreenTile * , tile, PIScreenTypes::TileEvent, e) {
|
||||
if (e.type == TileButtons::ButtonSelected) {
|
||||
ok = e.data.toInt() == 0;
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
EVENT_HANDLER1(void, keyPressed, PIKbdListener::KeyEvent, key) {
|
||||
if (key.key == PIKbdListener::Return) {
|
||||
ok = true;
|
||||
close = true;
|
||||
}
|
||||
if (key.key == PIKbdListener::Esc) {
|
||||
ok = false;
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
bool ok;
|
||||
bool close;
|
||||
};
|
||||
|
||||
|
||||
PIString readableTime(const PITime & t) {
|
||||
PIString ret;
|
||||
bool pt = false;
|
||||
if (t.hours > 0) {ret += PIString::fromNumber(t.hours).expandLeftTo(2, '0') + " h "; pt = true;}
|
||||
if ((t.minutes > 0) || pt) {ret += PIString::fromNumber(t.minutes).expandLeftTo(2, '0') + " m "; pt = true;}
|
||||
if ((t.seconds > 0) || pt) ret += PIString::fromNumber(t.seconds).expandLeftTo(2, '0') + " s";
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString askUserInput(const PIString & desc) {
|
||||
PIScreenTile dlg;
|
||||
dlg.setMargins(1, 1, 1, 1);
|
||||
dlg.spacing = 1;
|
||||
dlg.back_format.color_back = Yellow;
|
||||
TileSimple * lbl = new TileSimple();
|
||||
TileInput * input = new TileInput();
|
||||
TileButtons * btns = new TileButtons();
|
||||
lbl->back_format.color_back = Yellow;
|
||||
btns->back_format.color_back = Yellow;
|
||||
lbl->content << TileSimple::Row(desc, CellFormat(Black, Transparent));
|
||||
btns->content << TileButtons::Button(" Ok ", CellFormat());
|
||||
btns->content << TileButtons::Button("Cancel", CellFormat());
|
||||
dlg.addTile(lbl);
|
||||
dlg.addTile(input);
|
||||
dlg.addTile(btns);
|
||||
DlgWatcher w;
|
||||
CONNECTU(screen, keyPressed, &w, keyPressed)
|
||||
CONNECTU(screen, tileEvent, &w, tileEvent)
|
||||
screen->setDialogTile(&dlg);
|
||||
while (!w.close) {
|
||||
PIKbdListener::instance()->readKeyboard();
|
||||
piMSleep(10);
|
||||
}
|
||||
if (!w.ok) return PIString();
|
||||
return input->text;
|
||||
}
|
||||
|
||||
|
||||
bool askQuestion(const PIString & t) {
|
||||
PIScreenTile dlg;
|
||||
dlg.setMargins(1, 1, 1, 1);
|
||||
dlg.spacing = 1;
|
||||
dlg.back_format.color_back = Yellow;
|
||||
TileSimple * lbl = new TileSimple();
|
||||
TileButtons * btns = new TileButtons();
|
||||
lbl->back_format.color_back = Yellow;
|
||||
btns->back_format.color_back = Yellow;
|
||||
lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
|
||||
btns->content << TileButtons::Button(" Ok ", CellFormat());
|
||||
btns->content << TileButtons::Button("Cancel", CellFormat());
|
||||
dlg.addTile(lbl);
|
||||
dlg.addTile(btns);
|
||||
DlgWatcher w;
|
||||
CONNECTU(screen, keyPressed, &w, keyPressed)
|
||||
CONNECTU(screen, tileEvent, &w, tileEvent)
|
||||
screen->setDialogTile(&dlg);
|
||||
while (!w.close) {
|
||||
PIKbdListener::instance()->readKeyboard();
|
||||
piMSleep(10);
|
||||
}
|
||||
return w.ok;
|
||||
}
|
||||
|
||||
|
||||
void showInfo(const PIString & t) {
|
||||
PIScreenTile dlg;
|
||||
dlg.setMargins(1, 1, 1, 1);
|
||||
dlg.spacing = 1;
|
||||
dlg.back_format.color_back = Yellow;
|
||||
TileSimple * lbl = new TileSimple();
|
||||
TileButtons * btns = new TileButtons();
|
||||
lbl->back_format.color_back = Yellow;
|
||||
btns->back_format.color_back = Yellow;
|
||||
lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
|
||||
btns->content << TileButtons::Button(" Ok ", CellFormat());
|
||||
dlg.addTile(lbl);
|
||||
dlg.addTile(btns);
|
||||
DlgWatcher w;
|
||||
CONNECTU(screen, keyPressed, &w, keyPressed)
|
||||
CONNECTU(screen, tileEvent, &w, tileEvent)
|
||||
screen->setDialogTile(&dlg);
|
||||
while (!w.close) {
|
||||
PIKbdListener::instance()->readKeyboard();
|
||||
piMSleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void removeFiles(const PIDir & dir, PIStringList l) {
|
||||
l.removeAll("..");
|
||||
PIString ap = dir.absolutePath();
|
||||
//piCout << "remove from" << ap;
|
||||
piForeachC (PIString & s, l) {
|
||||
PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
|
||||
if (fi.isDir()) {
|
||||
PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
|
||||
piForeachCR (PIFile::FileInfo & e, el) {
|
||||
//piCout << "remove" << e.path;
|
||||
PIFile::remove(e.path);
|
||||
}
|
||||
}
|
||||
//piCout << "remove" << fi.path;
|
||||
PIFile::remove(fi.path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool cryptFiles(const PIDir & dir, PIStringList l, const PIByteArray & secret) {
|
||||
if (secret.size() != PICrypt::sizeKey() || secret.isEmpty()) return false;
|
||||
l.removeAll("..");
|
||||
PIString ap = dir.absolutePath();
|
||||
piForeachC (PIString & s, l) {
|
||||
PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
|
||||
if (fi.isDir()) {
|
||||
PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
|
||||
piForeachCR (PIFile::FileInfo & e, el) {
|
||||
if (e.size != 0)
|
||||
cryptFile(e.path, secret);
|
||||
}
|
||||
}
|
||||
if (fi.size != 0)
|
||||
cryptFile(fi.path, secret);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool cryptFile(const PIString & path, const PIByteArray & secret){
|
||||
PIFile inf;
|
||||
PIByteArray ba;
|
||||
PICrypt crypt;
|
||||
if (!crypt.setKey(secret)) return false;
|
||||
if (!inf.open(path, PIIODevice::ReadOnly)) return false;
|
||||
ba = inf.readAll();
|
||||
ba = crypt.crypt(ba);
|
||||
if (ba.isEmpty()) return false;
|
||||
PIFile outf;
|
||||
if (!outf.open(path + ".crypt", PIIODevice::ReadWrite)) return false;
|
||||
outf.resize(0);
|
||||
outf.write(ba);
|
||||
outf.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
#include "picrypt.h"
|
||||
|
||||
extern PIScreen * screen;
|
||||
|
||||
|
||||
class DlgWatcher: public PIThread {
|
||||
PIOBJECT(DlgWatcher)
|
||||
|
||||
public:
|
||||
DlgWatcher() { close = ok = false; }
|
||||
EVENT_HANDLER2(void, tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e) {
|
||||
if (e.type == TileButtons::ButtonSelected) {
|
||||
ok = e.data.toInt() == 0;
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
EVENT_HANDLER1(void, keyPressed, PIKbdListener::KeyEvent, key) {
|
||||
if (key.key == PIKbdListener::Return) {
|
||||
ok = true;
|
||||
close = true;
|
||||
}
|
||||
if (key.key == PIKbdListener::Esc) {
|
||||
ok = false;
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
bool ok;
|
||||
bool close;
|
||||
};
|
||||
|
||||
|
||||
PIString readableTime(const PITime & t) {
|
||||
PIString ret;
|
||||
bool pt = false;
|
||||
if (t.hours > 0) {
|
||||
ret += PIString::fromNumber(t.hours).expandLeftTo(2, '0') + " h ";
|
||||
pt = true;
|
||||
}
|
||||
if ((t.minutes > 0) || pt) {
|
||||
ret += PIString::fromNumber(t.minutes).expandLeftTo(2, '0') + " m ";
|
||||
pt = true;
|
||||
}
|
||||
if ((t.seconds > 0) || pt) ret += PIString::fromNumber(t.seconds).expandLeftTo(2, '0') + " s";
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PIString askUserInput(const PIString & desc) {
|
||||
PIScreenTile dlg;
|
||||
dlg.setMargins(1, 1, 1, 1);
|
||||
dlg.spacing = 1;
|
||||
dlg.back_format.color_back = Yellow;
|
||||
TileSimple * lbl = new TileSimple();
|
||||
TileInput * input = new TileInput();
|
||||
TileButtons * btns = new TileButtons();
|
||||
lbl->back_format.color_back = Yellow;
|
||||
btns->back_format.color_back = Yellow;
|
||||
lbl->content << TileSimple::Row(desc, CellFormat(Black, Transparent));
|
||||
btns->content << TileButtons::Button(" Ok ", CellFormat());
|
||||
btns->content << TileButtons::Button("Cancel", CellFormat());
|
||||
dlg.addTile(lbl);
|
||||
dlg.addTile(input);
|
||||
dlg.addTile(btns);
|
||||
DlgWatcher w;
|
||||
CONNECTU(screen, keyPressed, &w, keyPressed)
|
||||
CONNECTU(screen, tileEvent, &w, tileEvent)
|
||||
screen->setDialogTile(&dlg);
|
||||
while (!w.close) {
|
||||
PIKbdListener::instance()->readKeyboard();
|
||||
piMSleep(10);
|
||||
}
|
||||
if (!w.ok) return PIString();
|
||||
return input->text;
|
||||
}
|
||||
|
||||
|
||||
bool askQuestion(const PIString & t) {
|
||||
PIScreenTile dlg;
|
||||
dlg.setMargins(1, 1, 1, 1);
|
||||
dlg.spacing = 1;
|
||||
dlg.back_format.color_back = Yellow;
|
||||
TileSimple * lbl = new TileSimple();
|
||||
TileButtons * btns = new TileButtons();
|
||||
lbl->back_format.color_back = Yellow;
|
||||
btns->back_format.color_back = Yellow;
|
||||
lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
|
||||
btns->content << TileButtons::Button(" Ok ", CellFormat());
|
||||
btns->content << TileButtons::Button("Cancel", CellFormat());
|
||||
dlg.addTile(lbl);
|
||||
dlg.addTile(btns);
|
||||
DlgWatcher w;
|
||||
CONNECTU(screen, keyPressed, &w, keyPressed)
|
||||
CONNECTU(screen, tileEvent, &w, tileEvent)
|
||||
screen->setDialogTile(&dlg);
|
||||
while (!w.close) {
|
||||
PIKbdListener::instance()->readKeyboard();
|
||||
piMSleep(10);
|
||||
}
|
||||
return w.ok;
|
||||
}
|
||||
|
||||
|
||||
void showInfo(const PIString & t) {
|
||||
PIScreenTile dlg;
|
||||
dlg.setMargins(1, 1, 1, 1);
|
||||
dlg.spacing = 1;
|
||||
dlg.back_format.color_back = Yellow;
|
||||
TileSimple * lbl = new TileSimple();
|
||||
TileButtons * btns = new TileButtons();
|
||||
lbl->back_format.color_back = Yellow;
|
||||
btns->back_format.color_back = Yellow;
|
||||
lbl->content << TileSimple::Row(t, CellFormat(Black, Transparent));
|
||||
btns->content << TileButtons::Button(" Ok ", CellFormat());
|
||||
dlg.addTile(lbl);
|
||||
dlg.addTile(btns);
|
||||
DlgWatcher w;
|
||||
CONNECTU(screen, keyPressed, &w, keyPressed)
|
||||
CONNECTU(screen, tileEvent, &w, tileEvent)
|
||||
screen->setDialogTile(&dlg);
|
||||
while (!w.close) {
|
||||
PIKbdListener::instance()->readKeyboard();
|
||||
piMSleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void removeFiles(const PIDir & dir, PIStringList l) {
|
||||
l.removeAll("..");
|
||||
PIString ap = dir.absolutePath();
|
||||
// piCout << "remove from" << ap;
|
||||
piForeachC(PIString & s, l) {
|
||||
PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
|
||||
if (fi.isDir()) {
|
||||
PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
|
||||
piForeachCR(PIFile::FileInfo & e, el) {
|
||||
// piCout << "remove" << e.path;
|
||||
PIFile::remove(e.path);
|
||||
}
|
||||
}
|
||||
// piCout << "remove" << fi.path;
|
||||
PIFile::remove(fi.path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool cryptFiles(const PIDir & dir, PIStringList l, const PIByteArray & secret) {
|
||||
if (secret.size() != PICrypt::sizeKey() || secret.isEmpty()) return false;
|
||||
l.removeAll("..");
|
||||
PIString ap = dir.absolutePath();
|
||||
piForeachC(PIString & s, l) {
|
||||
PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s);
|
||||
if (fi.isDir()) {
|
||||
PIVector<PIFile::FileInfo> el = PIDir::allEntries(fi.path);
|
||||
piForeachCR(PIFile::FileInfo & e, el) {
|
||||
if (e.size != 0) cryptFile(e.path, secret);
|
||||
}
|
||||
}
|
||||
if (fi.size != 0) cryptFile(fi.path, secret);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool cryptFile(const PIString & path, const PIByteArray & secret) {
|
||||
PIFile inf;
|
||||
PIByteArray ba;
|
||||
PICrypt crypt;
|
||||
if (!crypt.setKey(secret)) return false;
|
||||
if (!inf.open(path, PIIODevice::ReadOnly)) return false;
|
||||
ba = inf.readAll();
|
||||
ba = crypt.crypt(ba);
|
||||
if (ba.isEmpty()) return false;
|
||||
PIFile outf;
|
||||
if (!outf.open(path + ".crypt", PIIODevice::ReadWrite)) return false;
|
||||
outf.resize(0);
|
||||
outf.write(ba);
|
||||
outf.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
#ifndef SHARED_H
|
||||
#define SHARED_H
|
||||
|
||||
#include "pidir.h"
|
||||
#include "piscreen.h"
|
||||
#include "piscreentiles.h"
|
||||
|
||||
static const char pisd_prefix[] = "_pisd_";
|
||||
|
||||
using namespace PIScreenTypes;
|
||||
|
||||
PIString readableTime(const PITime & t);
|
||||
|
||||
PIString askUserInput(const PIString &desc);
|
||||
bool askQuestion(const PIString & t);
|
||||
void showInfo(const PIString & t);
|
||||
void removeFiles(const PIDir & dir, PIStringList l);
|
||||
bool cryptFiles(const PIDir & dir, PIStringList l, const PIByteArray & secret);
|
||||
bool cryptFile(const PIString & path, const PIByteArray & secret);
|
||||
|
||||
#endif // SHARED_H
|
||||
#ifndef SHARED_H
|
||||
#define SHARED_H
|
||||
|
||||
#include "pidir.h"
|
||||
#include "piscreen.h"
|
||||
#include "piscreentiles.h"
|
||||
|
||||
static const char pisd_prefix[] = "_pisd_";
|
||||
|
||||
using namespace PIScreenTypes;
|
||||
|
||||
PIString readableTime(const PITime & t);
|
||||
|
||||
PIString askUserInput(const PIString & desc);
|
||||
bool askQuestion(const PIString & t);
|
||||
void showInfo(const PIString & t);
|
||||
void removeFiles(const PIDir & dir, PIStringList l);
|
||||
bool cryptFiles(const PIDir & dir, PIStringList l, const PIByteArray & secret);
|
||||
bool cryptFile(const PIString & path, const PIByteArray & secret);
|
||||
|
||||
#endif // SHARED_H
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
#include "terminal_tile.h"
|
||||
#include "piscreendrawer.h"
|
||||
|
||||
|
||||
TileTerminal::TileTerminal(const PIString & n): PIScreenTile(n) {
|
||||
focus_flags = PIScreenTypes::CanHasFocus;
|
||||
size_policy = PIScreenTypes::Expanding;
|
||||
lastp[0] = lastp[1] = lastp[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
void TileTerminal::drawEvent(PIScreenDrawer * d) {
|
||||
//piCout << "draw" << visible;
|
||||
d->fillRect(x_, y_, x_ + width_, y_ + height_, cells);
|
||||
}
|
||||
|
||||
|
||||
bool TileTerminal::keyEvent(PIKbdListener::KeyEvent key) {
|
||||
lastp[0] = lastp[1];
|
||||
lastp[1] = lastp[2];
|
||||
lastp[2] = char(key.key);
|
||||
if (lastp[0] == '\e' && lastp[1] == '~' && lastp[2] == '.') {
|
||||
closeRequest();
|
||||
return true;
|
||||
}
|
||||
//piCout << "key";
|
||||
keyPressed(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TileTerminal::resizeEvent(int w, int h) {
|
||||
resizeRequest();
|
||||
}
|
||||
#include "terminal_tile.h"
|
||||
|
||||
#include "piscreendrawer.h"
|
||||
|
||||
|
||||
TileTerminal::TileTerminal(const PIString & n): PIScreenTile(n) {
|
||||
focus_flags = PIScreenTypes::CanHasFocus;
|
||||
size_policy = PIScreenTypes::Expanding;
|
||||
lastp[0] = lastp[1] = lastp[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
void TileTerminal::drawEvent(PIScreenDrawer * d) {
|
||||
// piCout << "draw" << visible;
|
||||
d->fillRect(x_, y_, x_ + width_, y_ + height_, cells);
|
||||
}
|
||||
|
||||
|
||||
bool TileTerminal::keyEvent(PIKbdListener::KeyEvent key) {
|
||||
lastp[0] = lastp[1];
|
||||
lastp[1] = lastp[2];
|
||||
lastp[2] = char(key.key);
|
||||
if (lastp[0] == '\e' && lastp[1] == '~' && lastp[2] == '.') {
|
||||
closeRequest();
|
||||
return true;
|
||||
}
|
||||
// piCout << "key";
|
||||
keyPressed(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TileTerminal::resizeEvent(int w, int h) {
|
||||
resizeRequest();
|
||||
}
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
#ifndef TERMINAL_TILE_H
|
||||
#define TERMINAL_TILE_H
|
||||
|
||||
#include "piscreentile.h"
|
||||
#include "pikbdlistener.h"
|
||||
|
||||
|
||||
class TileTerminal: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileTerminal, PIScreenTile)
|
||||
public:
|
||||
TileTerminal(const PIString & n);
|
||||
|
||||
void setContent(const PIVector<PIVector<PIScreenTypes::Cell> > & c) {cells = c;}
|
||||
|
||||
EVENT(resizeRequest)
|
||||
EVENT1(keyPressed, PIKbdListener::KeyEvent, k)
|
||||
EVENT(closeRequest)
|
||||
|
||||
private:
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
||||
void resizeEvent(int w, int h) override;
|
||||
|
||||
PIVector<PIVector<PIScreenTypes::Cell> > cells;
|
||||
char lastp[3];
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // TERMINAL_TILE_H
|
||||
#ifndef TERMINAL_TILE_H
|
||||
#define TERMINAL_TILE_H
|
||||
|
||||
#include "pikbdlistener.h"
|
||||
#include "piscreentile.h"
|
||||
|
||||
|
||||
class TileTerminal: public PIScreenTile {
|
||||
PIOBJECT_SUBCLASS(TileTerminal, PIScreenTile)
|
||||
|
||||
public:
|
||||
TileTerminal(const PIString & n);
|
||||
|
||||
void setContent(const PIVector<PIVector<PIScreenTypes::Cell>> & c) { cells = c; }
|
||||
|
||||
EVENT(resizeRequest)
|
||||
EVENT1(keyPressed, PIKbdListener::KeyEvent, k)
|
||||
EVENT(closeRequest)
|
||||
|
||||
private:
|
||||
void drawEvent(PIScreenDrawer * d) override;
|
||||
bool keyEvent(PIKbdListener::KeyEvent key) override;
|
||||
void resizeEvent(int w, int h) override;
|
||||
|
||||
PIVector<PIVector<PIScreenTypes::Cell>> cells;
|
||||
char lastp[3];
|
||||
};
|
||||
|
||||
|
||||
#endif // TERMINAL_TILE_H
|
||||
|
||||
@@ -1,106 +1,106 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
System tests program
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pip.h"
|
||||
#include "pisystemtests.h"
|
||||
#ifdef CC_GCC
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
#if defined(WINDOWS) || defined(MAC_OS)
|
||||
piCout << "This program is useless for Windows";
|
||||
return 0;
|
||||
#else
|
||||
if (getuid() != 0) {
|
||||
piCout << "You should run this program as root!";
|
||||
return 0;
|
||||
}
|
||||
PIConfig conf(
|
||||
#ifndef WINDOWS
|
||||
"/etc/pip.conf"
|
||||
#else
|
||||
"pip.conf"
|
||||
#endif
|
||||
);
|
||||
PITimeMeasurer timer, tm;
|
||||
timespec ts;
|
||||
long stc = 0;
|
||||
double st;
|
||||
llong sts = 0;
|
||||
clock_getres(CLOCK_REALTIME, &ts);
|
||||
stc = long(ts.tv_sec) * 1000000000l + long(ts.tv_nsec);
|
||||
conf.setValue("time_resolution_ns", stc);
|
||||
piCout << "Timer resolution is " << stc << " ns";
|
||||
|
||||
piCout << "\"PITimer.elapsed_*\" test ... ";
|
||||
stc = 0;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1000;
|
||||
PIVector<double> times;
|
||||
times.resize(8192);
|
||||
tm.reset();
|
||||
PISystemTests::time_elapsed_ns = 0;
|
||||
while (tm.elapsed_s() < 3.) {
|
||||
for (int i = 0; i < times.size_s(); ++i) {
|
||||
timer.reset();
|
||||
times[i] = timer.elapsed_m();
|
||||
times[i] = timer.elapsed_s();
|
||||
times[i] = timer.elapsed_u();
|
||||
}
|
||||
st = 0;
|
||||
for (int i = 0; i < times.size_s(); ++i)
|
||||
st += times[i];
|
||||
//cout << times[0] << endl;
|
||||
//cout << st / times.size_s() / 3. * 1000. << endl;
|
||||
sts += piRoundd(st / times.size_s() / 3. * 1000.);
|
||||
//cout << sts << endl;
|
||||
stc++;
|
||||
}
|
||||
sts /= stc;
|
||||
conf.setValue("time_elapsed_ns", long(sts));
|
||||
piCout << "ok, cost" << sts << "ns, average in" << stc << "series (" << (stc * 3 * times.size_s()) << "executes)";
|
||||
|
||||
piCout << "\"usleep\" offset test ... ";
|
||||
PISystemTests::time_elapsed_ns = sts;
|
||||
tm.reset();
|
||||
stc = 0;
|
||||
sts = 0;
|
||||
times.resize(128);
|
||||
while (tm.elapsed_s() < 3.) {
|
||||
for (int i = 0; i < times.size_s(); ++i) {
|
||||
timer.reset();
|
||||
usleep(1000);
|
||||
times[i] = timer.elapsed_u();
|
||||
}
|
||||
st = 0;
|
||||
for (int i = 0; i < times.size_s(); ++i)
|
||||
st += times[i] - 1000;
|
||||
//cout << times[0] << endl;
|
||||
//cout << st / times.size_s() / 3. * 1000. << endl;
|
||||
sts += piRoundd(st / times.size_s());
|
||||
//cout << sts << endl;
|
||||
stc++;
|
||||
}
|
||||
sts /= stc;
|
||||
conf.setValue("usleep_offset_us", long(sts));
|
||||
piCout << "ok," << sts << "us, average in" << stc << "series (" << (stc * times.size_s()) << "executes)";
|
||||
return 0;
|
||||
#endif
|
||||
};
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
System tests program
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pip.h"
|
||||
#include "pisystemtests.h"
|
||||
#ifdef CC_GCC
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
#if defined(WINDOWS) || defined(MAC_OS)
|
||||
piCout << "This program is useless for Windows";
|
||||
return 0;
|
||||
#else
|
||||
if (getuid() != 0) {
|
||||
piCout << "You should run this program as root!";
|
||||
return 0;
|
||||
}
|
||||
PIConfig conf(
|
||||
# ifndef WINDOWS
|
||||
"/etc/pip.conf"
|
||||
# else
|
||||
"pip.conf"
|
||||
# endif
|
||||
);
|
||||
PITimeMeasurer timer, tm;
|
||||
timespec ts;
|
||||
long stc = 0;
|
||||
double st;
|
||||
llong sts = 0;
|
||||
clock_getres(CLOCK_REALTIME, &ts);
|
||||
stc = long(ts.tv_sec) * 1000000000l + long(ts.tv_nsec);
|
||||
conf.setValue("time_resolution_ns", stc);
|
||||
piCout << "Timer resolution is " << stc << " ns";
|
||||
|
||||
piCout << "\"PITimer.elapsed_*\" test ... ";
|
||||
stc = 0;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1000;
|
||||
PIVector<double> times;
|
||||
times.resize(8192);
|
||||
tm.reset();
|
||||
PISystemTests::time_elapsed_ns = 0;
|
||||
while (tm.elapsed_s() < 3.) {
|
||||
for (int i = 0; i < times.size_s(); ++i) {
|
||||
timer.reset();
|
||||
times[i] = timer.elapsed_m();
|
||||
times[i] = timer.elapsed_s();
|
||||
times[i] = timer.elapsed_u();
|
||||
}
|
||||
st = 0;
|
||||
for (int i = 0; i < times.size_s(); ++i)
|
||||
st += times[i];
|
||||
// cout << times[0] << endl;
|
||||
// cout << st / times.size_s() / 3. * 1000. << endl;
|
||||
sts += piRoundd(st / times.size_s() / 3. * 1000.);
|
||||
// cout << sts << endl;
|
||||
stc++;
|
||||
}
|
||||
sts /= stc;
|
||||
conf.setValue("time_elapsed_ns", long(sts));
|
||||
piCout << "ok, cost" << sts << "ns, average in" << stc << "series (" << (stc * 3 * times.size_s()) << "executes)";
|
||||
|
||||
piCout << "\"usleep\" offset test ... ";
|
||||
PISystemTests::time_elapsed_ns = sts;
|
||||
tm.reset();
|
||||
stc = 0;
|
||||
sts = 0;
|
||||
times.resize(128);
|
||||
while (tm.elapsed_s() < 3.) {
|
||||
for (int i = 0; i < times.size_s(); ++i) {
|
||||
timer.reset();
|
||||
usleep(1000);
|
||||
times[i] = timer.elapsed_u();
|
||||
}
|
||||
st = 0;
|
||||
for (int i = 0; i < times.size_s(); ++i)
|
||||
st += times[i] - 1000;
|
||||
// cout << times[0] << endl;
|
||||
// cout << st / times.size_s() / 3. * 1000. << endl;
|
||||
sts += piRoundd(st / times.size_s());
|
||||
// cout << sts << endl;
|
||||
stc++;
|
||||
}
|
||||
sts /= stc;
|
||||
conf.setValue("usleep_offset_us", long(sts));
|
||||
piCout << "ok," << sts << "us, average in" << stc << "series (" << (stc * times.size_s()) << "executes)";
|
||||
return 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1,251 +1,245 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
UDP file transfer (send /receive files) utility
|
||||
Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pip.h"
|
||||
#include "pifiletransfer.h"
|
||||
#include "pidatatransfer.h"
|
||||
#include "piscreen.h"
|
||||
#include "piscreentiles.h"
|
||||
|
||||
|
||||
TileSimple pmt;
|
||||
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
class UDPFileTransfer: public PITimer {
|
||||
PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer)
|
||||
public:
|
||||
UDPFileTransfer(const PIString &src_ip_port, const PIString &dst_ip_port, bool test = false) {
|
||||
quet_ = false;
|
||||
test_ = test;
|
||||
eth.setReadAddress(src_ip_port);
|
||||
eth.setSendAddress(dst_ip_port);
|
||||
if (test_) {
|
||||
testt.setCRCEnabled(false);
|
||||
testt.setName("TEST");
|
||||
CONNECT1(void, PIByteArray &, &testt, sendRequest, this, ftsend);
|
||||
} else {
|
||||
ft.setPacketSize(65000);
|
||||
ft.setName("PIFT");
|
||||
CONNECT1(void, PIByteArray &, &ft, sendRequest, this, ftsend);
|
||||
CONNECTU(&ft, sendFilesStarted, this, ftevent);
|
||||
CONNECTU(&ft, receiveFilesStarted, this, ftevent);
|
||||
CONNECTU(&ft, sendFilesFinished, this, ftevent);
|
||||
CONNECTU(&ft, receiveFilesFinished, this, ftevent);
|
||||
}
|
||||
CONNECT2(void, const uchar *, ssize_t, ð, threadedReadEvent, this, received);
|
||||
start(50);
|
||||
eth.setParameter(PIEthernet::SeparateSockets);
|
||||
eth.startThreadedRead();
|
||||
}
|
||||
|
||||
void setQuet(bool quet) {quet_ = quet;}
|
||||
|
||||
void startSend(const PIStringList &file) {
|
||||
ft.send(file);
|
||||
}
|
||||
|
||||
void startTest() {
|
||||
PIByteArray ba(1024*1024*8);
|
||||
testt.send(ba);
|
||||
}
|
||||
|
||||
PIFileTransfer ft;
|
||||
PIDataTransfer testt;
|
||||
bool test_;
|
||||
|
||||
private:
|
||||
PIEthernet eth;
|
||||
bool quet_;
|
||||
|
||||
void tick(void *, int) override {
|
||||
if (ft.isStarted()) {
|
||||
ftevent();
|
||||
updatePMT();
|
||||
if (PIKbdListener::exiting) {
|
||||
ft.stopSend();
|
||||
ft.stopReceive();
|
||||
}
|
||||
}
|
||||
if (testt.isSending() || testt.isReceiving()) {
|
||||
ftevent();
|
||||
updatePMT();
|
||||
}
|
||||
}
|
||||
|
||||
EVENT_HANDLER(void, ftevent) {
|
||||
if (test_) {
|
||||
|
||||
#ifdef WINDOWS
|
||||
piCout
|
||||
#else
|
||||
PICout(AddSpaces) << ClearLine
|
||||
#endif
|
||||
<< testt.stateString()
|
||||
<< testt.diagnostic().receiveSpeed()
|
||||
<< testt.diagnostic().sendSpeed()
|
||||
<< "("
|
||||
<< PIString::readableSize(testt.bytesCur()) << "/" << PIString::readableSize(testt.bytesAll())
|
||||
<< ")"
|
||||
#ifndef WINDOWS
|
||||
<< Flush
|
||||
#endif
|
||||
;
|
||||
return;
|
||||
}
|
||||
if (quet_) return;
|
||||
|
||||
#ifdef WINDOWS
|
||||
piCout
|
||||
#else
|
||||
PICout(AddSpaces) << ClearLine
|
||||
#endif
|
||||
<< ft.stateString() << ft.curFile()
|
||||
<< ft.diagnostic().receiveSpeed()
|
||||
<< ft.diagnostic().sendSpeed()
|
||||
<< "(" << PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", "
|
||||
<< PIString::readableSize(ft.bytesCur()) << "/" << PIString::readableSize(ft.bytesAll()) << ")"
|
||||
<< "ETA" << (ft.diagnostic().state().received_bytes_per_sec > 0 ?
|
||||
PIString::fromNumber(PISystemTime::fromSeconds((ft.bytesAll() - ft.bytesCur()) /
|
||||
ft.diagnostic().state().received_bytes_per_sec).toSeconds())
|
||||
: PIString("unknown"))
|
||||
#ifndef WINDOWS
|
||||
<< Flush
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
EVENT_HANDLER1(void, ftsend, PIByteArray &, data) {
|
||||
eth.send(data);
|
||||
}
|
||||
|
||||
EVENT_HANDLER2(void, received, const uchar * , readed, ssize_t, size) {
|
||||
PIByteArray ba(readed, size);
|
||||
if(test_) {
|
||||
testt.received(ba);
|
||||
return;
|
||||
}
|
||||
ft.received(ba);
|
||||
}
|
||||
|
||||
void updatePMT() {
|
||||
PIString pm;
|
||||
if (test_) pm = testt.packetMap();
|
||||
else pm = ft.packetMap();
|
||||
int wd = 110;
|
||||
pmt.content.resize(pm.size() / wd + 1);
|
||||
for (int i=0; i<pmt.content.size_s(); i++) {
|
||||
pmt.content[i].first = pm.mid(wd*i, piMini(pm.size() - i*wd, wd));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << Bold << "PIP UDP file transfer";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default << "\"pift [-hqf] -r <receive_ip> -s <send_ip> [-d <work_dir>] [-p <port>] [<path1>] [<path2>] [<path3>] [...]\"" << NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << "-f --fullpath " << Green << "- full path in <receive_ip> and <send_ip>";
|
||||
piCout << "-h --help " << Green << "- display this message and exit";
|
||||
piCout << "-q --quet " << Green << "- quiet, no debug output to console";
|
||||
piCout << "-r --receive <receive_ip> " << Green << "- set receive ip address, must be ip address of this computer";
|
||||
piCout << "-s --send <send_ip> " << Green << "- set send ip address, address of computer which communicate with you";
|
||||
piCout << "-p --port <port> " << Green << "- UDP port for transfer, by default 50005";
|
||||
piCout << "-d --dir <work_dir> " << Green << "- directory, where place received files";
|
||||
piCout << "<path> " << Green << "- add path to send, if no path, then \"pift\" working in receive mode";
|
||||
piCout << "-t --test " << Green << "- test mode";
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
PICLI cli(argc, argv);
|
||||
cli.setOptionalArgumentsCount(-1);
|
||||
cli.addArgument("send", true);
|
||||
cli.addArgument("receive", true);
|
||||
cli.addArgument("dir", true);
|
||||
cli.addArgument("port", true);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("quet");
|
||||
cli.addArgument("fullpath");
|
||||
cli.addArgument("test", true);
|
||||
if (cli.hasArgument("test")) {
|
||||
PIString src;
|
||||
PIString dst;
|
||||
bool send_ = false;
|
||||
if (cli.argumentValue("test") == "1") {
|
||||
src = "127.0.0.1:50005";
|
||||
dst = "127.0.0.1:50006";
|
||||
send_ = true;
|
||||
} else {
|
||||
src = "127.0.0.1:50006";
|
||||
dst = "127.0.0.1:50005";
|
||||
}
|
||||
if (cli.hasArgument("send") && cli.hasArgument("receive") && cli.hasArgument("fullpath")) {
|
||||
src = cli.argumentValue("receive");
|
||||
dst = cli.argumentValue("send");
|
||||
}
|
||||
PIScreen screen(false);
|
||||
screen.enableExitCapture();
|
||||
screen.rootTile()->addTile(new TilePICout());
|
||||
screen.rootTile()->addTile(&pmt);
|
||||
UDPFileTransfer tuf(src, dst, true);
|
||||
screen.start();
|
||||
if (send_) tuf.startTest();
|
||||
screen.waitForFinish();
|
||||
return 0;
|
||||
}
|
||||
if ((!cli.hasArgument("send") || !cli.hasArgument("receive")) || cli.hasArgument("help")) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
PIString src = cli.argumentValue("receive");
|
||||
PIString dst = cli.argumentValue("send");
|
||||
int port = -1;
|
||||
if (cli.hasArgument("port")) port = cli.argumentValue("port").toInt();
|
||||
if (port <=0) port = 50005;
|
||||
if (!cli.hasArgument("fullpath")) {
|
||||
src += ":"+PIString::fromNumber(port);
|
||||
dst += ":"+PIString::fromNumber(port);
|
||||
}
|
||||
PIScreen screen(false);
|
||||
screen.enableExitCapture();
|
||||
screen.rootTile()->addTile(new TilePICout());
|
||||
screen.rootTile()->addTile(&pmt);
|
||||
screen.start();
|
||||
UDPFileTransfer f(src, dst);
|
||||
if (cli.hasArgument("dir")) f.ft.setDirectory(cli.argumentValue("dir"));
|
||||
if (cli.hasArgument("quet")) f.setQuet(true);
|
||||
piCout << "work directory" << f.ft.directory().absolutePath() << ", listen on" << src << ", send to" << dst;
|
||||
PIStringList fls = cli.optionalArguments();
|
||||
if (fls.size() > 0) {
|
||||
piCout << "send files" << fls;
|
||||
f.startSend(fls);
|
||||
PICout(PICoutManipulators::AddNone) << "\n";
|
||||
return 0;
|
||||
} else {
|
||||
piCout << "wait for receiving";
|
||||
}
|
||||
PICout(PICoutManipulators::AddNone) << "\n";
|
||||
screen.waitForFinish();
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
UDP file transfer (send /receive files) utility
|
||||
Andrey Bychkov work.a.b@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pidatatransfer.h"
|
||||
#include "pifiletransfer.h"
|
||||
#include "pip.h"
|
||||
#include "piscreen.h"
|
||||
#include "piscreentiles.h"
|
||||
|
||||
|
||||
TileSimple pmt;
|
||||
|
||||
|
||||
using namespace PICoutManipulators;
|
||||
|
||||
class UDPFileTransfer: public PITimer {
|
||||
PIOBJECT_SUBCLASS(UDPFileTransfer, PITimer)
|
||||
|
||||
public:
|
||||
UDPFileTransfer(const PIString & src_ip_port, const PIString & dst_ip_port, bool test = false) {
|
||||
quet_ = false;
|
||||
test_ = test;
|
||||
eth.setReadAddress(src_ip_port);
|
||||
eth.setSendAddress(dst_ip_port);
|
||||
if (test_) {
|
||||
testt.setCRCEnabled(false);
|
||||
testt.setName("TEST");
|
||||
CONNECT1(void, PIByteArray &, &testt, sendRequest, this, ftsend);
|
||||
} else {
|
||||
ft.setPacketSize(65000);
|
||||
ft.setName("PIFT");
|
||||
CONNECT1(void, PIByteArray &, &ft, sendRequest, this, ftsend);
|
||||
CONNECTU(&ft, sendFilesStarted, this, ftevent);
|
||||
CONNECTU(&ft, receiveFilesStarted, this, ftevent);
|
||||
CONNECTU(&ft, sendFilesFinished, this, ftevent);
|
||||
CONNECTU(&ft, receiveFilesFinished, this, ftevent);
|
||||
}
|
||||
CONNECT2(void, const uchar *, ssize_t, ð, threadedReadEvent, this, received);
|
||||
start(50);
|
||||
eth.setParameter(PIEthernet::SeparateSockets);
|
||||
eth.startThreadedRead();
|
||||
}
|
||||
|
||||
void setQuet(bool quet) { quet_ = quet; }
|
||||
|
||||
void startSend(const PIStringList & file) { ft.send(file); }
|
||||
|
||||
void startTest() {
|
||||
PIByteArray ba(1024 * 1024 * 8);
|
||||
testt.send(ba);
|
||||
}
|
||||
|
||||
PIFileTransfer ft;
|
||||
PIDataTransfer testt;
|
||||
bool test_;
|
||||
|
||||
private:
|
||||
PIEthernet eth;
|
||||
bool quet_;
|
||||
|
||||
void tick(void *, int) override {
|
||||
if (ft.isStarted()) {
|
||||
ftevent();
|
||||
updatePMT();
|
||||
if (PIKbdListener::exiting) {
|
||||
ft.stopSend();
|
||||
ft.stopReceive();
|
||||
}
|
||||
}
|
||||
if (testt.isSending() || testt.isReceiving()) {
|
||||
ftevent();
|
||||
updatePMT();
|
||||
}
|
||||
}
|
||||
|
||||
EVENT_HANDLER(void, ftevent) {
|
||||
if (test_) {
|
||||
#ifdef WINDOWS
|
||||
piCout
|
||||
#else
|
||||
PICout(AddSpaces) << ClearLine
|
||||
#endif
|
||||
<< testt.stateString() << testt.diagnostic().receiveSpeed() << testt.diagnostic().sendSpeed() << "("
|
||||
<< PIString::readableSize(testt.bytesCur()) << "/" << PIString::readableSize(testt.bytesAll()) << ")"
|
||||
#ifndef WINDOWS
|
||||
<< Flush
|
||||
#endif
|
||||
;
|
||||
return;
|
||||
}
|
||||
if (quet_) return;
|
||||
|
||||
#ifdef WINDOWS
|
||||
piCout
|
||||
#else
|
||||
PICout(AddSpaces)
|
||||
<< ClearLine
|
||||
#endif
|
||||
<< ft.stateString() << ft.curFile() << ft.diagnostic().receiveSpeed() << ft.diagnostic().sendSpeed() << "("
|
||||
<< PIString::readableSize(ft.bytesFileCur()) << "/" << PIString::readableSize(ft.bytesFileAll()) << ", "
|
||||
<< PIString::readableSize(ft.bytesCur()) << "/" << PIString::readableSize(ft.bytesAll()) << ")"
|
||||
<< "ETA"
|
||||
<< (ft.diagnostic().state().received_bytes_per_sec > 0
|
||||
? PIString::fromNumber(
|
||||
PISystemTime::fromSeconds((ft.bytesAll() - ft.bytesCur()) / ft.diagnostic().state().received_bytes_per_sec)
|
||||
.toSeconds())
|
||||
: PIString("unknown"))
|
||||
#ifndef WINDOWS
|
||||
<< Flush
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
EVENT_HANDLER1(void, ftsend, PIByteArray &, data) { eth.send(data); }
|
||||
|
||||
EVENT_HANDLER2(void, received, const uchar *, readed, ssize_t, size) {
|
||||
PIByteArray ba(readed, size);
|
||||
if (test_) {
|
||||
testt.received(ba);
|
||||
return;
|
||||
}
|
||||
ft.received(ba);
|
||||
}
|
||||
|
||||
void updatePMT() {
|
||||
PIString pm;
|
||||
if (test_)
|
||||
pm = testt.packetMap();
|
||||
else
|
||||
pm = ft.packetMap();
|
||||
int wd = 110;
|
||||
pmt.content.resize(pm.size() / wd + 1);
|
||||
for (int i = 0; i < pmt.content.size_s(); i++) {
|
||||
pmt.content[i].first = pm.mid(wd * i, piMini(pm.size() - i * wd, wd));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void usage() {
|
||||
piCout << Bold << "PIP UDP file transfer";
|
||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||
piCout << Green << Bold << "Usage:" << Default
|
||||
<< "\"pift [-hqf] -r <receive_ip> -s <send_ip> [-d <work_dir>] [-p <port>] [<path1>] [<path2>] [<path3>] [...]\"" << NewLine;
|
||||
piCout << Green << Bold << "Details:";
|
||||
piCout << "-f --fullpath " << Green << "- full path in <receive_ip> and <send_ip>";
|
||||
piCout << "-h --help " << Green << "- display this message and exit";
|
||||
piCout << "-q --quet " << Green << "- quiet, no debug output to console";
|
||||
piCout << "-r --receive <receive_ip> " << Green << "- set receive ip address, must be ip address of this computer";
|
||||
piCout << "-s --send <send_ip> " << Green << "- set send ip address, address of computer which communicate with you";
|
||||
piCout << "-p --port <port> " << Green << "- UDP port for transfer, by default 50005";
|
||||
piCout << "-d --dir <work_dir> " << Green << "- directory, where place received files";
|
||||
piCout << "<path> " << Green << "- add path to send, if no path, then \"pift\" working in receive mode";
|
||||
piCout << "-t --test " << Green << "- test mode";
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
PICLI cli(argc, argv);
|
||||
cli.setOptionalArgumentsCount(-1);
|
||||
cli.addArgument("send", true);
|
||||
cli.addArgument("receive", true);
|
||||
cli.addArgument("dir", true);
|
||||
cli.addArgument("port", true);
|
||||
cli.addArgument("help");
|
||||
cli.addArgument("quet");
|
||||
cli.addArgument("fullpath");
|
||||
cli.addArgument("test", true);
|
||||
if (cli.hasArgument("test")) {
|
||||
PIString src;
|
||||
PIString dst;
|
||||
bool send_ = false;
|
||||
if (cli.argumentValue("test") == "1") {
|
||||
src = "127.0.0.1:50005";
|
||||
dst = "127.0.0.1:50006";
|
||||
send_ = true;
|
||||
} else {
|
||||
src = "127.0.0.1:50006";
|
||||
dst = "127.0.0.1:50005";
|
||||
}
|
||||
if (cli.hasArgument("send") && cli.hasArgument("receive") && cli.hasArgument("fullpath")) {
|
||||
src = cli.argumentValue("receive");
|
||||
dst = cli.argumentValue("send");
|
||||
}
|
||||
PIScreen screen(false);
|
||||
screen.enableExitCapture();
|
||||
screen.rootTile()->addTile(new TilePICout());
|
||||
screen.rootTile()->addTile(&pmt);
|
||||
UDPFileTransfer tuf(src, dst, true);
|
||||
screen.start();
|
||||
if (send_) tuf.startTest();
|
||||
screen.waitForFinish();
|
||||
return 0;
|
||||
}
|
||||
if ((!cli.hasArgument("send") || !cli.hasArgument("receive")) || cli.hasArgument("help")) {
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
PIString src = cli.argumentValue("receive");
|
||||
PIString dst = cli.argumentValue("send");
|
||||
int port = -1;
|
||||
if (cli.hasArgument("port")) port = cli.argumentValue("port").toInt();
|
||||
if (port <= 0) port = 50005;
|
||||
if (!cli.hasArgument("fullpath")) {
|
||||
src += ":" + PIString::fromNumber(port);
|
||||
dst += ":" + PIString::fromNumber(port);
|
||||
}
|
||||
PIScreen screen(false);
|
||||
screen.enableExitCapture();
|
||||
screen.rootTile()->addTile(new TilePICout());
|
||||
screen.rootTile()->addTile(&pmt);
|
||||
screen.start();
|
||||
UDPFileTransfer f(src, dst);
|
||||
if (cli.hasArgument("dir")) f.ft.setDirectory(cli.argumentValue("dir"));
|
||||
if (cli.hasArgument("quet")) f.setQuet(true);
|
||||
piCout << "work directory" << f.ft.directory().absolutePath() << ", listen on" << src << ", send to" << dst;
|
||||
PIStringList fls = cli.optionalArguments();
|
||||
if (fls.size() > 0) {
|
||||
piCout << "send files" << fls;
|
||||
f.startSend(fls);
|
||||
PICout(PICoutManipulators::AddNone) << "\n";
|
||||
return 0;
|
||||
} else {
|
||||
piCout << "wait for receiving";
|
||||
}
|
||||
PICout(PICoutManipulators::AddNone) << "\n";
|
||||
screen.waitForFinish();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user