#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 sind = selected.toVector(); for (const auto 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(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; } // 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 & l) { PIMutexLocker ml(e_mutex); PIVector 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; for (const auto & 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 ll; ll << SSPair(" Esc", "Exit") << SSPair(" F5", "Copy") << SSPair(" F6", "Move") << SSPair(" F7", "MkDir") << SSPair(" F8", "Delete"); for (const auto & 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 & 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 sil = panels[1]->selected.toVector(); for (const auto 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; }