#include "file_manager.h" #include "shared.h" #include "daemon.h" extern PIScreen screen; FileManager::TileDir::TileDir(): TileList() { label_path = 0; selection_mode = TileList::MultiSelection; dir = PIDir::current(); resized = remote = remote_mode = false; } PIStringList FileManager::TileDir::selectedNames() const { PIStringList ret; PIMutexLocker ml(e_mutex); PIVector 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 (!remote) updateDir(); pass = true; break; case PIKbdListener::F5: if (remote_mode) { if (selected.isEmpty()) selected << cur; if (!askQuestion("Copy selected files?")) return true; setFocus(); actionRequest(remote, Copy, selectedNames()); } break; case PIKbdListener::F7: nd = askNewDir(); setFocus(); if (nd.isEmpty()) return true; if (remote) actionRequest(remote, 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 (remote) { actionRequest(remote, 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 (!remote) { //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(); ud = true; } } pass = true; } e_mutex.unlock(); if (ud) updateDir(); } break; } if (remote && 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 & l) { PIMutexLocker ml(e_mutex); PIVector el = dir.entries(), 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() { //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(); } cur = pc; offset = po; buildNames(); } void FileManager::TileDir::buildNames() { //if (!enabled) return; 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; } FileManager::FileManager(Daemon * d) { setName("FileManager"); del_commit = false; daemon = d; CONNECTU(&screen, keyPressed, this, keyEvent) //dir.setDir("/home/peri4/Documents"); 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(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); } tile_root->addTile(pt); PIScreenTile * labels = new PIScreenTile(); labels->size_policy = Fixed; labels->direction = Horizontal; PIVector 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::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(); } 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; if (screen.dialogTile()) return; switch (key.key) { case PIKbdListener::Esc: menuRequest(); break; default: break; } /*if (!enabled) return; if (key.key == 'D') { if (cur >= files.size_s() || cur < 0) return; if (del_commit) { piForeachC (PIString & f, selected) { PIFile::remove(dir.absolutePath() + PIDir::separator + f); //piCout << "remove" << (dir.absolutePath() + PIDir::separator + f); } selected.clear(); updateDir(); console.clearCustomStatus(); del_commit = false; } else { if (selected.isEmpty()) selected << files[cur].path; console.addCustomStatus("Delete " + PIString(selected.size_s()) + " file, are you sure? D as yes"); del_commit = true; } updateConsole(); return; } console.clearCustomStatus(); del_commit = false; PIStringList nsel; switch (key.key) { case PIKbdListener::UpArrow: cur--; if (cur < 0) cur = 0; if (cur - offset < 3) offset--; if (offset < 0) offset = 0; updateConsole(); break; case PIKbdListener::Space: if (cur < 0 || cur >= files.size_s()) return; if (selected.contains(files[cur].path)) selected.removeOne(files[cur].path); else selected << files[cur].path; case PIKbdListener::DownArrow: cur++; if (cur >= files.size_s()) cur = files.size_s() - 1; if (cur - offset >= height - 3) offset++; if (offset >= files.size_s() - height) offset = files.size_s() - height; updateConsole(); //piCout << offset << files.size_s() << height; break; case PIKbdListener::Home: cur = offset = 0; updateConsole(); break; case PIKbdListener::End: cur = files.size_s() - 1; offset = files.size_s() - height; updateConsole(); //piCout << offset << files.size_s() << height; break; case PIKbdListener::Return: if (cur < files.size_s() && cur >= 0) { piCout << files[cur]; if (files[cur].isDir()) { prev_pos[dir.path()] = cur; prev_off[dir.path()] = offset; dir.cd(files[cur].name()); cur = prev_pos.value(dir.path(), 0); offset = prev_off.value(dir.path(), 0); selected.clear(); updateDir(); updateConsole(); } } break; case 'A': selected.clear(); piForeach (PIFile::FileInfo & e, files) selected << e.path; updateConsole(); break; case 'R': updateDir(); piForeach (PIFile::FileInfo & e, files) if (selected.contains(e.path)) nsel << e.path; selected = nsel; updateConsole(); break; case PIKbdListener::Esc: //selected.clear(); //updateConsole(); menuRequest(); break; default: break; }*/ } void FileManager::updateConsole() { /*if (!enabled) return; startTab(2); console.addString("File manager", 1, Yellow | Inverse); console.addString("Path: " + dir.absolutePath(), 1, Green | Inverse | Bold); console.addString("Name", 1, Green | Inverse | Bold); console.addString(" ", 2, Yellow | Inverse); console.addString(" ", 2, Green | Inverse); console.addString(" ", 2, Green | Inverse); buildNames(); console.addString("A - select all, D - remove, R - refresh, Esc - exit", 1, Green | Inverse | Bold); finishTab();*/ }