code format
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user