diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f062743..cd89def2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ project(pip) cmake_minimum_required(VERSION 2.6) -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) include(CheckFunctionExists) diff --git a/src/console/pikbdlistener.cpp b/src/console/pikbdlistener.cpp index 44eb40cd..3c5f06c4 100644 --- a/src/console/pikbdlistener.cpp +++ b/src/console/pikbdlistener.cpp @@ -41,6 +41,7 @@ * */ bool PIKbdListener::exiting; +PIKbdListener * PIKbdListener::_object = 0; #ifndef WINDOWS @@ -105,6 +106,7 @@ PRIVATE_DEFINITION_END(PIKbdListener) PIKbdListener::PIKbdListener(KBFunc slot, void * _data): PIThread() { setName("keyboard_listener"); + _object = this; #ifdef WINDOWS PRIVATE->hIn = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(PRIVATE->hIn, &PRIVATE->smode); @@ -140,7 +142,7 @@ void PIKbdListener::begin() { } -void PIKbdListener::run() { +void PIKbdListener::readKeyboard() { ke.key = 0; ke.modifiers = 0; memset(rc, 0, 8); diff --git a/src/console/pikbdlistener.h b/src/console/pikbdlistener.h index dfdeea12..f38dbe1b 100644 --- a/src/console/pikbdlistener.h +++ b/src/console/pikbdlistener.h @@ -110,6 +110,7 @@ public: //! Returns exit key, default 'Q' char exitKey() const {return exit_key;} + void readKeyboard(); //! Returns if keyboard listening is active (not running!) bool isActive() {return is_active;} @@ -144,10 +145,11 @@ public: //! \} static bool exiting; + static PIKbdListener * instance() {return _object;} private: void begin(); - void run(); + void run() {readKeyboard();} void end(); PRIVATE_DECLARATION @@ -163,6 +165,7 @@ private: void * data_; char rc[8]; KeyEvent ke; + static PIKbdListener * _object; }; diff --git a/src/console/piscreen.h b/src/console/piscreen.h index 08ace2b3..357b7513 100644 --- a/src/console/piscreen.h +++ b/src/console/piscreen.h @@ -77,9 +77,6 @@ public: //! \fn void waitForFinish() //! \brief block until finished (exit key will be pressed) - //! \fn void clearVariables(bool clearScreen = true) - //! \brief Remove all columns at current tab and if "clearScreen" clear the screen - //! \fn void start(bool wait = false) //! \brief Start console output and if "wait" block until finished (exit key will be pressed) @@ -93,6 +90,9 @@ public: //! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data) //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object + //! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e) + //! \brief Raise on some event "e" from tile "tile" + //! \} private: diff --git a/src/console/piscreentiles.cpp b/src/console/piscreentiles.cpp index 1293c76a..7c1d18a9 100644 --- a/src/console/piscreentiles.cpp +++ b/src/console/piscreentiles.cpp @@ -53,6 +53,12 @@ TileSimple::TileSimple(const PIString & n): PIScreenTile(n) { } +TileSimple::TileSimple(const TileSimple::Row & r): PIScreenTile() { + alignment = Left; + content << r; +} + + void TileSimple::sizeHint(int & w, int & h) const { w = h = 0; piForeachC (Row & r, content) @@ -95,7 +101,7 @@ void TileList::sizeHint(int & w, int & h) const { void TileList::drawEvent(PIScreenDrawer * d) { lhei = height - 2; - int osp = piMini(3, lhei / 4); + //int osp = piMini(3, lhei / 4); int is = piClampi(offset, 0, piMaxi(0, content.size_s() - 1)), ie = piClampi(offset + lhei, 0, content.size_s()); if (is > 0) d->drawText(x, y, PIString(" /\\ ").repeat(width / 4), Green, Default, Bold); //piCout << is << ie << offset << lhei << content.size_s(); @@ -428,3 +434,141 @@ bool TilePICout::keyEvent(PIKbdListener::KeyEvent key) { } return TileList::keyEvent(key); } + + + + +TileInput::TileInput(const PIString & n): PIScreenTile(n) { + focus_flags = CanHasFocus | NextByTab; + back_format.color_back = White; + format.color_char = Black; + format.color_back = White; + max_length = 1024; + cur = offset = 0; + inv = false; +} + + +void TileInput::sizeHint(int & w, int & h) const { + w = 32; + h = 1; +} + + +void TileInput::drawEvent(PIScreenDrawer * d) { + PIString ps = text.mid(offset, width - 2); + d->drawText(x + 1, y, ps, (Color)format.color_char, Transparent, (CharFlags)format.flags); + if (offset > 0) + d->drawText(x, y, "<", Green, Black, Bold); + if (text.size_s() - offset >= width - 2) + d->drawText(x + width - 1, y, ">", Green, Black, Bold); + if (!has_focus) return; + Color cb = (Color)format.color_char, cc = (Color)format.color_back; + if (tm_blink.elapsed_m() >= 650) { + tm_blink.reset(); + inv = !inv; + } + if (inv) piSwap(cb, cc); + d->drawText(x + 1 + cur - offset, y, text.mid(cur, 1).expandLeftTo(1, ' '), cc, cb, (CharFlags)format.flags); +} + + +bool TileInput::keyEvent(PIKbdListener::KeyEvent key) { + int lwid = piMaxi(0, width - 2); + int oo(0), osp = piMini(3, lwid / 4); + lwid--; + switch (key.key) { + case PIKbdListener::LeftArrow: + cur--; + oo--; + if (key.modifiers[PIKbdListener::Ctrl]) { + cur -= 4; + oo -= 4; + } + if (cur < 0) cur = 0; + if (cur - offset < osp) offset += oo; + if (offset < 0) offset = 0; + reserCursor(); + return true; + case PIKbdListener::RightArrow: + cur++; + oo++; + if (key.modifiers[PIKbdListener::Ctrl]) { + cur += 4; + oo += 4; + } + if (cur > text.size_s()) cur = text.size_s(); + if (cur - offset >= lwid - osp) offset += oo; + if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid; + if (offset < 0) offset = 0; + reserCursor(); + return true; + case PIKbdListener::Home: + cur = offset = 0; + reserCursor(); + return true; + case PIKbdListener::End: + cur = text.size_s(); + offset = text.size_s() - lwid; + if (offset < 0) offset = 0; + reserCursor(); + return true; + case PIKbdListener::Backspace: + if (cur > text.size_s() || text.isEmpty()) + return true; + text.remove(cur - 1, 1); + cur--; + if (cur > text.size_s()) cur = text.size_s(); + if (cur - offset >= lwid - osp) offset += oo; + if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid; + if (offset < 0) offset = 0; + reserCursor(); + return true; + case PIKbdListener::Delete: + if (cur >= text.size_s() || text.isEmpty()) + return true; + text.remove(cur, 1); + if (cur < 0) cur = 0; + if (cur > text.size_s()) cur = text.size_s(); + if (cur - offset < osp) offset += oo; + if (offset < 0) offset = 0; + reserCursor(); + return true; + case PIKbdListener::UpArrow: + case PIKbdListener::DownArrow: + case PIKbdListener::PageUp: + case PIKbdListener::PageDown: + case PIKbdListener::Insert: + case PIKbdListener::Return: + case PIKbdListener::Esc: + case PIKbdListener::F1: + case PIKbdListener::F2: + case PIKbdListener::F3: + case PIKbdListener::F4: + case PIKbdListener::F5: + case PIKbdListener::F6: + case PIKbdListener::F7: + case PIKbdListener::F8: + case PIKbdListener::F9: + case PIKbdListener::F10: + case PIKbdListener::F11: + case PIKbdListener::F12: + break; + default: + text.insert(cur, PIChar(key.key)); + cur++; + oo++; + if (cur - offset >= lwid - osp) offset += oo; + if (offset >= text.size_s() - lwid) offset = text.size_s() - lwid; + if (offset < 0) offset = 0; + reserCursor(); + return true; + } + return PIScreenTile::keyEvent(key); +} + + +void TileInput::reserCursor() { + tm_blink.reset(); + inv = false; +} diff --git a/src/console/piscreentiles.h b/src/console/piscreentiles.h index 1d647124..e338b905 100644 --- a/src/console/piscreentiles.h +++ b/src/console/piscreentiles.h @@ -28,8 +28,9 @@ class PIP_EXPORT TileSimple: public PIScreenTile { public: - TileSimple(const PIString & n = PIString()); typedef PIPair Row; + TileSimple(const PIString & n = PIString()); + TileSimple(const Row & r); PIVector content; PIScreenTypes::Alignment alignment; protected: @@ -148,4 +149,26 @@ protected: }; + + +class PIP_EXPORT TileInput: public PIScreenTile { +public: + TileInput(const PIString & n = PIString()); + /*enum EventType { + EditFinished + };*/ + PIScreenTypes::CellFormat format; + PIString text; + int max_length; +protected: + void sizeHint(int & w, int & h) const; + void drawEvent(PIScreenDrawer * d); + bool keyEvent(PIKbdListener::KeyEvent key); + void reserCursor(); + int cur, offset; + bool inv; + PITimeMeasurer tm_blink; +}; + + #endif // PISCREENTILES_H diff --git a/src/core/pistring.cpp b/src/core/pistring.cpp index a9f8ba27..068fc3d9 100755 --- a/src/core/pistring.cpp +++ b/src/core/pistring.cpp @@ -265,7 +265,7 @@ bool PIString::operator >(const PIString & str) const { PIString PIString::mid(const int start, const int len) const { //PIString str; int s = start, l = len; - if (l == 0) return PIString(); + if (l == 0 || start >= length()) return PIString(); if (s < 0) { l += s; s = 0; @@ -273,12 +273,13 @@ PIString PIString::mid(const int start, const int len) const { if (l < 0) { //for (uint i = s; i < size(); ++i) // str += at(i); - return PIString(&(at(s)), size() - s); + return PIString(&(at(s)), size_s() - s); } else { if (l > length() - s) l = length() - s; //for (int i = s; i < s + l; ++i) // str += at(i); + //std::cout << "mid " << s << " " << l << " " << size_s() << " " << start << " " << len << "\n"; return PIString(&(at(s)), l); } return PIString(); diff --git a/src/io/pipeer.cpp b/src/io/pipeer.cpp index 2b07552b..b1845466 100755 --- a/src/io/pipeer.cpp +++ b/src/io/pipeer.cpp @@ -698,6 +698,7 @@ void PIPeer::syncPeers() { PIMutexLocker locker(eth_mutex); PIString pn; bool change = false; + PIStringList dpeers; peers_mutex.lock(); for (int i = 0; i < peers.size_s(); ++i) { PeerInfo & cp(peers[i]); @@ -710,8 +711,7 @@ void PIPeer::syncPeers() { sendPeerRemove(pn); --i; removeNeighbour(pn); - peerDisconnected(pn); - peerDisconnectedEvent(pn); + dpeers << pn; change = true; continue; } @@ -731,6 +731,10 @@ void PIPeer::syncPeers() { ba << int(3) << self_info.name << self_info << peers; peers_mutex.unlock(); sendMBcast(ba); + piForeachC (PIString & p, dpeers) { + peerDisconnected(p); + peerDisconnectedEvent(p); + } } diff --git a/utils/system_daemon/daemon.cpp b/utils/system_daemon/daemon.cpp index 5cc776b9..401c8d5e 100644 --- a/utils/system_daemon/daemon.cpp +++ b/utils/system_daemon/daemon.cpp @@ -135,6 +135,7 @@ void Daemon::tileEvent(PIScreenTile * t, TileEvent e) { void Daemon::keyEvent(PIKbdListener::KeyEvent key) { if (!tile_root->visible) return; + if (screen.dialogTile()) return; switch (key.key) { case PIKbdListener::Esc: if (mode == 0) @@ -158,7 +159,7 @@ 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; + piCout << key.key << key.modifiers; switch (key.key) { case PIKbdListener::Return: { diff --git a/utils/system_daemon/file_manager.cpp b/utils/system_daemon/file_manager.cpp index afd3e5dc..4d87e1b9 100644 --- a/utils/system_daemon/file_manager.cpp +++ b/utils/system_daemon/file_manager.cpp @@ -4,6 +4,7 @@ extern PIScreen screen; + FileManager::TileDir::TileDir(): TileList() { label_path = 0; selection_mode = TileList::MultiSelection; @@ -13,19 +14,38 @@ FileManager::TileDir::TileDir(): TileList() { bool FileManager::TileDir::keyEvent(PIKbdListener::KeyEvent key) { - if (key.key == 'R') { - if (remote) { - ((void(*)(void*,PIKbdListener::KeyEvent))key_func)(fm, key); - } else { + bool pass = false; + PIString nd; + switch (key.key) { + case 'R': if (!remote) updateDir(); pass = true; break; + case PIKbdListener::F7: + nd = askNewDir(); + setFocus(); + if (nd.isEmpty()) return true; + if (!remote) { + PIDir::make(dir.absolutePath() + PIDir::separator + nd); updateDir(); } - return true; - } - if (key.key == PIKbdListener::Return) { + pass = true; + break; + case PIKbdListener::F8: + if (selected.isEmpty()) + selected << cur; + if (!askQuestion("Delete selected?")) return false; + setFocus(); + if (!remote) { + PIStringList sl; + PIVector sind = selected.toVector(); + piForeachC (int i, sind) + sl << entries[i].name(); + removeFiles(dir, sl); + updateDir(); + } + pass = true; + break; + case PIKbdListener::Return: if (cur < entries.size_s() && cur >= 0) { - if (remote) { - ((void(*)(void*,PIKbdListener::KeyEvent))key_func)(fm, key); - } else { + if (!remote) { //piCout << entries[cur]; if (entries[cur].isDir()) { prev_pos[dir.path()] = PIPair(cur, offset); @@ -37,7 +57,12 @@ bool FileManager::TileDir::keyEvent(PIKbdListener::KeyEvent key) { updateDir(); } } + pass = true; } + break; + } + if (remote && pass) { + ((void(*)(void*,PIKbdListener::KeyEvent))key_func)(fm, key); return true; } return TileList::keyEvent(key); @@ -75,8 +100,8 @@ void FileManager::TileDir::setContent(const PIVector & l) { bool root = dir.path() == PIDir::separator; for (int i = 0; i < l.size_s(); ++i) { if (l[i].name() == ".") continue; - if (l[i].name() == ".." && !root) { - dl.push_front(l[i]); + if (l[i].name() == "..") { + if (!root) dl.push_front(l[i]); continue; } if (l[i].isDir()) dl << l[i]; @@ -191,7 +216,7 @@ FileManager::FileManager(Daemon * d) { labels->size_policy = Fixed; labels->direction = Horizontal; PIVector ll; - ll << SSPair(" Esc", "Exit") << SSPair(" F5", "Copy") << SSPair(" F6", "Move") << SSPair(" F8", "Delete"); + 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)); @@ -259,6 +284,7 @@ void FileManager::remoteRestoreDir() { void FileManager::keyEvent(PIKbdListener::KeyEvent key) { if (!tile_root->visible) return; + if (screen.dialogTile()) return; switch (key.key) { case PIKbdListener::Esc: menuRequest(); diff --git a/utils/system_daemon/main.cpp b/utils/system_daemon/main.cpp index 118b9318..374412e0 100755 --- a/utils/system_daemon/main.cpp +++ b/utils/system_daemon/main.cpp @@ -196,6 +196,7 @@ public: } } EVENT_HANDLER1(void, keyEvent, PIKbdListener::KeyEvent, e) { + if (screen.dialogTile()) return; if (tpeer->visible || tinfo->visible) if (e.key == PIKbdListener::Esc) menuRequest(); //piCout << "key" << e.key; diff --git a/utils/system_daemon/shared.cpp b/utils/system_daemon/shared.cpp new file mode 100644 index 00000000..46e34340 --- /dev/null +++ b/utils/system_daemon/shared.cpp @@ -0,0 +1,122 @@ +#include "shared.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 askNewDir() { + 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("Enter new directory name:", 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.removeOne(".."); + PIString ap = dir.absolutePath(); + piForeachC (PIString & s, l) { + PIFile::FileInfo fi = PIFile::fileInfo(ap + PIDir::separator + s); + if (fi.isDir()) { + PIVector el = PIDir::allEntries(fi.path); + piForeachCR (PIFile::FileInfo & e, el) + PIFile::remove(e.path); + } + PIFile::remove(fi.path); + } +} diff --git a/utils/system_daemon/shared.h b/utils/system_daemon/shared.h index e8c02d65..b3be3a6b 100644 --- a/utils/system_daemon/shared.h +++ b/utils/system_daemon/shared.h @@ -1,4 +1,15 @@ +#ifndef SHARED_H +#define SHARED_H + +#include "pidir.h" #include "piscreen.h" #include "piscreentiles.h" using namespace PIScreenTypes; + +PIString askNewDir(); +bool askQuestion(const PIString & t); +void showInfo(const PIString & t); +void removeFiles(const PIDir & dir, PIStringList l); + +#endif // SHARED_H