diff --git a/main.cpp b/main.cpp index fd83ea52..ecb57532 100644 --- a/main.cpp +++ b/main.cpp @@ -135,6 +135,29 @@ public: #include int main (int argc, char * argv[]) { + PIString s, s2; + s = "test"; + PICout(0xFFFF) << s << s.length(); + s += PIString(" test") + " !"; + PICout(0xFFFF) << s << s.length(); + s.clear(); + PICout(0xFFFF) << s << s.length(); + s += " test"; + PICout(0xFFFF) << s << s.length(); + s.insert(1, PIString("|") + ",|"); + PICout(0xFFFF) << s << s.length() << (s == (PIString(" |,|")+"test")); + s.resize(4); + PICout(0xFFFF) << s << s.length(); + s = PIString("new"); + PICout(0xFFFF) << s << s.length(); + + PIByteArray ba; + ba << s; + piCout << ba.size() << ba; + ba >> s2; + PICout(0xFFFF) << s2 << s2.length(); + return 0; + hostent * he = 0; he = gethostbyname(argv[1]); piCout << he->h_name; diff --git a/src/console/piscreentiles.h b/src/console/piscreentiles.h index 975cc8b6..3a520313 100644 --- a/src/console/piscreentiles.h +++ b/src/console/piscreentiles.h @@ -56,12 +56,13 @@ public: PIVector content; PIScreenTypes::Alignment alignment; SelectionMode selection_mode; + PISet selected; + int cur, offset; protected: void sizeHint(int & w, int & h) const; void drawEvent(PIScreenDrawer * d); bool keyEvent(PIKbdListener::KeyEvent key); - int lhei, offset, cur; - PISet selected; + int lhei; }; diff --git a/src/core/pistring.cpp b/src/core/pistring.cpp index 1f6b16de..a9f8ba27 100755 --- a/src/core/pistring.cpp +++ b/src/core/pistring.cpp @@ -127,6 +127,32 @@ void PIString::appendFromChars(const char * c, int s) { } +void PIString::buildData() const { + data_.clear(); + uint wc; + uchar tc; + //printf("PIString::data %d\n", size_s()); + for (int i = 0, j = 0; i < size_s(); ++i) { + wc = uint(at(i).toInt()); + //printf("__%d_%d\n", i, wc); + tc = wc & 0xFF; + while (tc) { + data_ << uchar(tc); ++j; + wc >>= 8; + tc = wc & 0xFF; + //printf("____%d\n", wc); + } + /*if (at(i).isAscii()) + data_.push_back(uchar(at(i).toAscii())); + else { + data_.push_back((at(i).toCharPtr()[0])); ++j; + data_.push_back((at(i).toCharPtr()[1])); + }*/ + } + data_ << uchar('\0'); +} + + PIString & PIString::operator +=(const char * str) { int l = 0; while (str[l] != '\0') ++l; @@ -625,39 +651,6 @@ PIString PIString::toLowerCase() const { } -int PIString::lengthAscii() const { - int j = 0; - for (int i = 0; i < size_s(); ++i, ++j) - if (!at(i).isAscii()) ++j; - return j; -} - - -const char * PIString::data() const { - data_.clear(); - uint wc; - uchar tc; - //printf("PIString::data %d\n", size_s()); - for (int i = 0, j = 0; i < size_s(); ++i) { - wc = uint(at(i).toInt()); - //printf("__%d_%d\n", i, wc); - while (tc = wc & 0xFF, tc) { - data_.push_back(uchar(tc)); ++j; - wc >>= 8; - //printf("____%d\n", wc); - } - /*if (at(i).isAscii()) - data_.push_back(uchar(at(i).toAscii())); - else { - data_.push_back((at(i).toCharPtr()[0])); ++j; - data_.push_back((at(i).toCharPtr()[1])); - }*/ - } - data_.push_back(uchar('\0')); - return (const char * )data_.data(); -} - - std::string PIString::convertToStd() const { std::string s; uint wc; diff --git a/src/core/pistring.h b/src/core/pistring.h index 3337738c..4f33148a 100755 --- a/src/core/pistring.h +++ b/src/core/pistring.h @@ -32,6 +32,7 @@ class PIStringList; class PIP_EXPORT PIString: public PIDeque { + friend PIByteArray & operator >>(PIByteArray & s, PIString & v); public: //! Contructs an empty string PIString(): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--;} @@ -122,7 +123,7 @@ public: operator const char*() {return data();} //! Return std::string representation of string - operator const std::string() {if (size() == 0) return std::string(); std::string s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toAscii()); return s;} + //operator const std::string() {if (size() == 0) return std::string(); std::string s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toAscii()); return s;} //! Return symbol at index "pos" PIChar operator [](const int pos) const {return at(pos);} @@ -452,10 +453,10 @@ public: /*! \brief Return real bytes count of this string * \details It`s equivalent length of char sequence - * returned by function \a data() \n + * returned by function \a data() - 1, without terminating null-char \n * Example: \snippet pistring.cpp PIString::lengthAscii * \sa \a data() */ - int lengthAscii() const; + int lengthAscii() const {buildData(); return data_.size_s() - 1;} /*! \brief Return \c char * representation of this string * \details This function fill buffer by sequence @@ -464,7 +465,7 @@ public: * execution of this function.\n * Example: \snippet pistring.cpp PIString::data * \sa \a lengthAscii() */ - const char * data() const; + const char * data() const {buildData(); return (const char *)(data_.data());} //! \brief Return \c std::string representation of this string std::string stdString() const {return convertToStd();} @@ -473,8 +474,8 @@ public: wstring stdWString() const {return convertToWString();} #endif - //! \brief Return \a PIByteArray contains \a data() of this string - PIByteArray toByteArray() const {const char * d = data(); return PIByteArray(d, lengthAscii());} + //! \brief Return \a PIByteArray contains \a data() of this string without terminating null-char + PIByteArray toByteArray() const {buildData(); return data_.resized(data_.size_s() - 1);} /*! \brief Split string with delimiter "delim" to \a PIStringList and return it * \details Example: \snippet pistring.cpp PIString::split */ @@ -779,6 +780,7 @@ private: return ret; } void appendFromChars(const char * c, int s); + void buildData() const; std::string convertToStd() const; #ifdef HAS_LOCALE wstring convertToWString() const {wstring s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toWChar()); return s;} @@ -802,10 +804,10 @@ inline PICout operator <<(PICout s, const PIString & v) {s.space(); s.quote(); s //! \relatesalso PIString \relatesalso PIByteArray \brief Output operator to PIByteArray -inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {int l = v.lengthAscii(); s << l; if (l <= 0) return s; int os = s.size_s(); s.enlarge(l); memcpy(s.data(os), v.data(), l); return s;} +inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {s << v.toByteArray(); return s;} //! \relatesalso PIString \relatesalso PIByteArray \brief Input operator from PIByteArray -inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {if (s.size() < 4) {v.clear(); return s;} int l; s >> l; if (l <= 0) return s; v = PIString((const char * )s.data(), l); s.remove(0, l); return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {PIByteArray sc; s >> sc; v.clear(); v.appendFromChars((const char *)sc.data(), sc.size_s()); return s;} //! \relatesalso PIString \brief Return concatenated string diff --git a/utils/system_daemon/daemon.cpp b/utils/system_daemon/daemon.cpp index bb216d5a..208272e0 100644 --- a/utils/system_daemon/daemon.cpp +++ b/utils/system_daemon/daemon.cpp @@ -10,6 +10,7 @@ Daemon::Daemon(): PIPeer("_pisd_" + PISystemInfo::instance()->hostname + "_" + P mode = offset = cur = height = 0; CONNECTU(&screen, keyPressed, this, keyEvent) CONNECTU(&timer, tickEvent, this, timerEvent) + CONNECTU(&fm, tileKey, this, fmKeyEvent) timer.addDelimiter(5); timer.start(200); @@ -35,6 +36,7 @@ Daemon::Daemon(): PIPeer("_pisd_" + PISystemInfo::instance()->hostname + "_" + P tile_info = new TileSimple("daemon info"); tile_info->hide(); + fm.setRemote(true); tile_fm = fm.tile(); tile_fm->hide(); @@ -49,6 +51,14 @@ Daemon::Daemon(): PIPeer("_pisd_" + PISystemInfo::instance()->hostname + "_" + P } +Daemon::~Daemon() { + PIVector rl = remotes.values(); + piForeach (Remote * r, rl) + delete r; + remotes.clear(); +} + + PIScreenTile * Daemon::tile() const { return tile_root; } @@ -110,7 +120,11 @@ void Daemon::tileEvent(PIScreenTile * t, TileEvent e) { if (e.type == TileList::RowPressed) { switch (e.data.toInt()) { case 0: mode = 2; showTile(tile_info, "Information"); break; - case 1: mode = 3; showTile(tile_fm, "File manager"); break; + case 1: + mode = 3; + showTile(tile_fm, "File manager"); + requestChDir("."); + break; default: break; } } @@ -141,6 +155,26 @@ void Daemon::keyEvent(PIKbdListener::KeyEvent key) { } +void Daemon::fmKeyEvent(PIKbdListener::KeyEvent key) { + PIByteArray ba; + //Remote * r = remotes.value(conn_name); + //piCout << 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::timerEvent(void * _d, int delim) { screen.lock(); list_daemons->content.clear(); @@ -192,6 +226,10 @@ void Daemon::peerConnected(const PIString & name) { /*piCout << "connected" << name; mode = 2; conn_name = name;*/ + Remote * r = new Remote(name); + CONNECTU(&(r->dt), sendRequest, this, dtSendRequest) + CONNECTU(&(r->dt), receiveFinished, this, dtReceived) + remotes.insert(name, r); } @@ -199,6 +237,26 @@ void Daemon::peerDisconnected(const PIString & name) { if (name == conn_name) { disconnect(); } + Remote * dt = remotes.value(name); + if (dt) delete dt; + remotes.remove(name); +} + + +void Daemon::dtSendRequest(PIByteArray & data) { + PIDataTransfer * dt = (PIDataTransfer*)emitter(); + if (!dt) return; + PIByteArray hdr; hdr << int(DataTransfer); + data.insert(0, hdr); + send(dt->name(), data); +} + + +void Daemon::dtReceived(bool ok) { + if (!ok) return; + PIDataTransfer * dt = (PIDataTransfer*)emitter(); + if (!dt) return; + dataReceived(emitter()->name(), dt->data()); } @@ -206,6 +264,8 @@ void Daemon::dataReceived(const PIString & from, const PIByteArray & data) { //if (conn_name != from) return; if (data.size() < 4) return; PIByteArray ba(data), rba; + Remote * r(0); + PIString dir; int type; ba >> type; //std::cout << "rec from " << from << type; switch (type) { @@ -213,11 +273,40 @@ void Daemon::dataReceived(const PIString & from, const PIByteArray & data) { makeMyHostInfo(); rba << int(ReplyHostInfo) << info_my; break; + case RequestChangeDir: + r = remotes.value(from); + if (!r) break; + ba >> dir; + r->dir.cd(dir); + { + PIVector fil = r->dir.entries(); + piForeach (PIFile::FileInfo & f, fil) + f.path = f.name(); + rba << int(ReplyChangeDir) << r->dir.absolutePath() << fil; + } + break; case ReplyHostInfo: ba >> info_other; makeOtherHostInfo(); fillInfoTile(info_other); break; + case ReplyChangeDir: + r = remotes.value(from); + if (!r) break; + { + PIVector fil; + ba >> dir >> fil; + r->dir.setDir(dir); + fm.setRemoteDir(dir); + fm.setRemoteContent(fil); + fm.remoteRestoreDir(); + } + break; + case DataTransfer: + r = remotes.value(from); + if (r) + r->dt.received(ba); + break; }; if (!rba.isEmpty()) send(from, rba); } @@ -310,3 +399,14 @@ void Daemon::tabInfo() { console.addVariable("of this process", &sys_mon_other, 2); finishTab();*/ } + + +void Daemon::requestChDir(const PIString & d) { + if (d.isEmpty()) return; + fm.remoteSaveDir(); + fm.readingRemote(); + PIByteArray ba; + ba << int(RequestChangeDir) << d; + send(conn_name, ba); + //piCout << "request chdir" << d; +} diff --git a/utils/system_daemon/daemon.h b/utils/system_daemon/daemon.h index 2fce9c29..6993d893 100644 --- a/utils/system_daemon/daemon.h +++ b/utils/system_daemon/daemon.h @@ -4,6 +4,8 @@ #include "piscreentiles.h" #include "pipeer.h" #include "pisystemmonitor.h" +#include "pidatatransfer.h" +#include "pifiletransfer.h" #include "file_manager.h" extern PISystemMonitor sys_mon; @@ -12,6 +14,7 @@ class Daemon: public PIPeer { PIOBJECT(Daemon) public: Daemon(); + ~Daemon(); struct HostInfo { HostInfo() { @@ -52,14 +55,32 @@ public: private: enum PacketType { RequestHostInfo = 10, + RequestChangeDir, - ReplyHostInfo = 20 + ReplyHostInfo = 20, + ReplyChangeDir, + DataTransfer = 30 + + }; + + class Remote: public PIThread { + public: + Remote(const PIString & n = PIString()) {dt.setName(n); ft.setName(n); dir = PIDir::current();} + void sendData(const PIByteArray & d) {_d = d; startOnce();} + PIDir dir; + PIDataTransfer dt; + PIFileTransfer ft; + PIByteArray _d; + void run() {dt.send(_d);} }; EVENT_HANDLER2(void, tileEvent, PIScreenTile *, t, PIScreenTypes::TileEvent, e); EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, key); + EVENT_HANDLER1(void, fmKeyEvent, PIKbdListener::KeyEvent, key); EVENT_HANDLER2(void, timerEvent, void * , _d, int, delim); + EVENT_HANDLER1(void, dtSendRequest, PIByteArray &, data); + EVENT_HANDLER1(void, dtReceived, bool, ok); EVENT(menuRequest); void hideAll(); void showTile(PIScreenTile * t, const PIString & header = PIString()); @@ -75,10 +96,13 @@ private: void tabFeature(); void tabInfo(); + void requestChDir(const PIString & d); + mutable PIStringList available_daemons; PITimer timer; PIString conn_name; PIMap dnames; + PIMap remotes; PISystemMonitor sys_mon_other; HostInfo info_my, info_other; FileManager fm; diff --git a/utils/system_daemon/file_manager.cpp b/utils/system_daemon/file_manager.cpp index 850a1b14..5f55a434 100644 --- a/utils/system_daemon/file_manager.cpp +++ b/utils/system_daemon/file_manager.cpp @@ -8,22 +8,34 @@ FileManager::TileDir::TileDir(): TileList() { label_path = 0; selection_mode = TileList::MultiSelection; dir = PIDir::current(); - resized = false; + resized = remote = false; } bool FileManager::TileDir::keyEvent(PIKbdListener::KeyEvent key) { + if (key.key == 'R') { + if (remote) { + ((void(*)(void*,PIKbdListener::KeyEvent))key_func)(fm, key); + } else { + updateDir(); + } + return true; + } if (key.key == PIKbdListener::Return) { if (cur < entries.size_s() && cur >= 0) { - //piCout << entries[cur]; - if (entries[cur].isDir()) { - prev_pos[dir.path()] = PIPair(cur, offset); - dir.cd(entries[cur].name()); - PIPair cp = prev_pos.value(dir.path()); - cur = cp.first; - offset = cp.second; - selected.clear(); - updateDir(); + if (remote) { + ((void(*)(void*,PIKbdListener::KeyEvent))key_func)(fm, key); + } else { + //piCout << entries[cur]; + if (entries[cur].isDir()) { + prev_pos[dir.path()] = PIPair(cur, offset); + dir.cd(entries[cur].name()); + PIPair cp = prev_pos.value(dir.path()); + cur = cp.first; + offset = cp.second; + selected.clear(); + updateDir(); + } } } return true; @@ -42,34 +54,45 @@ void FileManager::TileDir::unlock() { } -void FileManager::TileDir::updateDir() { - //if (!enabled) return; - entries.clear(); - lock(); - int pc = cur, po = offset; +void FileManager::TileDir::showReading() { cur = -1; offset = 0; + entries.clear(); content.resize(1); content[0] = Row("... Reading ...", CellFormat()); - unlock(); +} + + +void FileManager::TileDir::setContent(const PIVector & l) { PIVector el = dir.entries(), fl, dl; - if (el.isEmpty()) { + entries.clear(); + if (l.isEmpty()) { PIFile::FileInfo fi; fi.path = ".."; fi.flags |= PIFile::FileInfo::DotDot | PIFile::FileInfo::Dir; entries << fi; } else { - for (int i = 0; i < el.size_s(); ++i) { - if (el[i].name() == ".") continue; - if (el[i].name() == "..") { - dl.push_front(el[i]); + for (int i = 0; i < l.size_s(); ++i) { + if (l[i].name() == ".") continue; + if (l[i].name() == "..") { + dl.push_front(l[i]); continue; } - if (el[i].isDir()) dl << el[i]; - else fl << el[i]; + if (l[i].isDir()) dl << l[i]; + else fl << l[i]; } entries << dl << fl; } +} + + +void FileManager::TileDir::updateDir() { + //if (!enabled) return; + 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(); @@ -152,6 +175,8 @@ FileManager::FileManager(Daemon * d) { plabel->maximumWidth = 1; panel->direction = Vertical; panels[i] = new TileDir(); + panels[i]->fm = this; + panels[i]->key_func = (void*)tileKey_s; panels[i]->name = "file panel " + PIString(i); panels[i]->label_path = plabel; panel->addTile(plabel); @@ -184,6 +209,53 @@ PIScreenTile * FileManager::tile() const { } +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.absolutePath(); + } +} + + +void FileManager::setRemoteContent(const PIVector< PIFile::FileInfo > & el) { + panels[1]->setContent(el); + panels[1]->buildNames(); +} + + +PIStringList FileManager::selectedRemote() const { + PIStringList ret; + panels[1]->lock(); + PIVector 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(panels[1]->cur, panels[1]->offset); +} + + +void FileManager::remoteRestoreDir() { + PIPair 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; +} + + void FileManager::keyEvent(PIKbdListener::KeyEvent key) { if (!tile_root->visible) return; switch (key.key) { diff --git a/utils/system_daemon/file_manager.h b/utils/system_daemon/file_manager.h index 8b4a37f2..a50deab6 100644 --- a/utils/system_daemon/file_manager.h +++ b/utils/system_daemon/file_manager.h @@ -12,6 +12,18 @@ public: FileManager(Daemon * d = 0); PIScreenTile * tile() const; + PIScreenTile * remoteTile() const {return panels[1];} + + void setRemote(bool r) {panels[1]->remote = r;} + void setRemoteDir(const PIString & d); + void setRemoteContent(const PIVector & el); + PIString remoteDir() const {return panels[1]->dir.absolutePath();} + 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();} private: class TileDir: public TileList { @@ -24,15 +36,20 @@ private: void resizeEvent(int w, int h); void lock(); void unlock(); + void showReading(); + void setContent(const PIVector & l); TileSimple * label_path; PIVector entries; PIDir dir; PIMap > prev_pos; - bool resized; + bool resized, remote; + void * fm, * key_func; }; EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, key); + EVENT1(tileKey, PIKbdListener::KeyEvent, key); EVENT(menuRequest); + static void tileKey_s(void * fm, PIKbdListener::KeyEvent key) {((FileManager*)fm)->tileKey(key);} void updateConsole(); bool del_commit;