FrameExpRemoto.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. unit FrameExpRemoto;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, FileUtil, IDEWindowIntf, Forms, Controls, ComCtrls, LCLType,
  6. Menus, ActnList, ExtCtrls, StdCtrls, FrameTabSession, MisUtils,
  7. RegExpr2; //Se usa RegExpr2, en lugar del RegExpr estándar de Lazarus, porque este tiene fallas.
  8. const
  9. //índice a las imágenes
  10. IMG_ARCHIVO = 0;
  11. IMG_CARPETA = 2;
  12. type
  13. { TfraExpRemoto }
  14. TfraExpRemoto = class(TFrame)
  15. acConfig: TAction;
  16. acEdDelete: TAction;
  17. acFilRename: TAction;
  18. acEdEdit: TAction;
  19. acHerEjec: TAction;
  20. acFileAccess: TAction;
  21. acFilNewFile: TAction;
  22. acFilNewFold: TAction;
  23. acVerRefres: TAction;
  24. ActionList1: TActionList;
  25. txtRuta: TEdit;
  26. ImageList1: TImageList;
  27. Label1: TLabel;
  28. ListView1: TListView;
  29. MenuItem1: TMenuItem;
  30. MenuItem2: TMenuItem;
  31. MenuItem3: TMenuItem;
  32. MenuItem4: TMenuItem;
  33. MenuItem5: TMenuItem;
  34. MenuItem6: TMenuItem;
  35. MenuItem7: TMenuItem;
  36. MenuItem8: TMenuItem;
  37. MenuItem9: TMenuItem;
  38. Panel1: TPanel;
  39. PopupMenu1: TPopupMenu;
  40. StatusBar1: TStatusBar;
  41. procedure acFilNewFoldExecute(Sender: TObject);
  42. procedure acFilNewFileExecute(Sender: TObject);
  43. procedure acFilRenameExecute(Sender: TObject);
  44. procedure acConfigExecute(Sender: TObject);
  45. procedure acEdEditExecute(Sender: TObject);
  46. procedure acEdDeleteExecute(Sender: TObject);
  47. procedure acHerEjecExecute(Sender: TObject);
  48. procedure acVerRefresExecute(Sender: TObject);
  49. procedure ListView1DblClick(Sender: TObject);
  50. procedure ListView1Edited(Sender: TObject; Item: TListItem;
  51. var AValue: string);
  52. procedure ListView1KeyDown(Sender: TObject; var Key: Word;
  53. Shift: TShiftState);
  54. procedure ListView1KeyPress(Sender: TObject; var Key: char);
  55. procedure ListView1SelectItem(Sender: TObject; Item: TListItem;
  56. Selected: Boolean);
  57. private
  58. lisArc: Tstringlist; //lista de archivos
  59. listmp: Tstringlist; //lista temporal
  60. ListDet: boolean; //lista detallada
  61. MosOcul: boolean; //mostrar archivos ocultos
  62. re: TRegExpr; //motor de expresiones regulares
  63. procedure ActualizarSel(arc: string);
  64. procedure AgregarCarpAtras;
  65. procedure AgregarFila(lin: string; iconIndex: integer);
  66. procedure AgregarFilaArc(lin: string);
  67. procedure AgregarFilaCar(lin: string);
  68. procedure AgregarFilaErr(lin: string);
  69. procedure AgregarMensajeEspera(lin: string);
  70. // procedure BuscaPosicionCampos;
  71. procedure ConfigurarColumnasDetalladas;
  72. procedure ConfigurarColumnasSimple;
  73. function EnviarComando(com: string; var salida: TStringList): string;
  74. public
  75. OnDblClickArch: procedure of object; //doble click en archivo
  76. procedure Actualizar;
  77. //funciones de búsqueda
  78. function BuscarItem(nomb: string): TListItem;
  79. function ItemSeleccionado: TListItem;
  80. function SelecMultiple: boolean;
  81. function SelecMulTodArchivos: boolean;
  82. function NumSeleccionados: integer;
  83. constructor Create(AOwner: TComponent) ; override;
  84. destructor Destroy; override;
  85. end;
  86. implementation
  87. uses FormPrincipal, FormConfig, FormRemoteEditor;
  88. {$R *.lfm}
  89. { TfraExpRemoto }
  90. procedure TfraExpRemoto.AgregarFila(lin: string; iconIndex: integer);
  91. //Agrega una fila de datos a la lista de archivos
  92. var
  93. it: TListItem;
  94. begin
  95. if ListDet then begin
  96. //hay información de campos
  97. it := ListView1.Items.Add;
  98. //Identifica campos
  99. if (re.Exec(lin)) then begin
  100. //encontró los campos
  101. it.Caption:=re.Match[7]; //nombre
  102. it.SubItems.Add(re.Match[6]); //fecha
  103. it.SubItems.Add(re.Match[5]); //tamaño
  104. it.SubItems.Add(re.Match[1]); //atributos
  105. it.SubItems.Add(re.Match[3]); //propietario
  106. it.SubItems.Add(re.Match[4]); //grupo
  107. it.SubItems.Add(re.Match[2]); //enlaces
  108. it.ImageIndex:=iconIndex;
  109. end else begin
  110. //no pudo extraer los campos
  111. it.Caption:='???';
  112. it.ImageIndex:=3; //error
  113. end;
  114. end else begin
  115. it := ListView1.Items.Add;
  116. it.Caption:=lin;
  117. it.ImageIndex:=iconIndex;
  118. end;
  119. end;
  120. procedure TfraExpRemoto.AgregarFilaArc(lin: string); // archivo
  121. begin
  122. AgregarFila(lin, IMG_ARCHIVO)
  123. end;
  124. procedure TfraExpRemoto.AgregarFilaCar(lin: string); //carpeta
  125. begin
  126. AgregarFila(lin,IMG_CARPETA)
  127. end;
  128. procedure TfraExpRemoto.AgregarFilaErr(lin: string); //Mensaje de error
  129. var
  130. it: TListItem;
  131. begin
  132. it := ListView1.Items.Add;
  133. it.Caption:=lin;
  134. it.ImageIndex:=3;
  135. end;
  136. procedure TfraExpRemoto.AgregarMensajeEspera(lin: string); //Mensaje en espera
  137. var
  138. it: TListItem;
  139. begin
  140. ListView1.Items.Clear; //limpia todo lo que había antes
  141. it := ListView1.Items.Add;
  142. it.Caption:=lin;
  143. it.ImageIndex:=4;
  144. end;
  145. procedure TfraExpRemoto.AgregarCarpAtras; //Carpeta ".."
  146. var
  147. it: TListItem;
  148. begin
  149. it := ListView1.Items.Add;
  150. it.Caption:='..';
  151. it.ImageIndex:=2;
  152. end;
  153. procedure TfraExpRemoto.ConfigurarColumnasSimple;
  154. var
  155. Col: TListColumn;
  156. begin
  157. ListView1.Columns.Clear;
  158. Col := ListView1.Columns.Add;
  159. Col.Caption := 'Name';
  160. Col.Alignment := taLeftJustify;
  161. Col.Width := 200;
  162. end;
  163. procedure TfraExpRemoto.ConfigurarColumnasDetalladas;
  164. var
  165. Col: TListColumn;
  166. begin
  167. ListView1.Columns.Clear;
  168. Col := ListView1.Columns.Add;
  169. Col.Caption := 'Name';
  170. Col.Alignment := taLeftJustify;
  171. Col.Width := 160;
  172. Col := ListView1.Columns.Add;
  173. Col.Caption := 'Modified Date';
  174. Col.Alignment := taLeftJustify;
  175. Col.Width := 100;
  176. Col := ListView1.Columns.Add;
  177. Col.Caption := 'Size';
  178. Col.Alignment := taRightJustify;
  179. Col.Width := 80;
  180. Col := ListView1.Columns.Add;
  181. Col.Caption := 'Attributes';
  182. Col.Alignment := taLeftJustify;
  183. Col.Width := 90;
  184. Col := ListView1.Columns.Add;
  185. Col.Caption := 'Owner';
  186. Col.Alignment := taLeftJustify;
  187. Col.Width := 80;
  188. Col := ListView1.Columns.Add;
  189. Col.Caption := 'Group';
  190. Col.Alignment := taLeftJustify;
  191. Col.Width := 80;
  192. Col := ListView1.Columns.Add;
  193. Col.Caption := 'Associated links';
  194. Col.Alignment := taRightJustify;
  195. Col.Width := 40;
  196. end;
  197. function TfraExpRemoto.BuscarItem(nomb: string): TListItem;
  198. //Busca un ítem por nombre
  199. var
  200. it: TListItem;
  201. begin
  202. Result:= nil;
  203. for it in listView1.Items do
  204. if it.Caption = nomb then exit(it);
  205. end;
  206. function TfraExpRemoto.ItemSeleccionado: TListItem;
  207. //Devuelve el ítem seleccionado
  208. begin
  209. Result := nil;
  210. if ListView1.ItemIndex<>-1 then
  211. Result := listView1.Items[ListView1.ItemIndex];
  212. end;
  213. function TfraExpRemoto.SelecMultiple: boolean;
  214. //Indica si hay selección múltiple
  215. var
  216. it: TListItem;
  217. n: Integer;
  218. begin
  219. n := 0;
  220. Result := false;
  221. for it in ListView1.Items do begin
  222. if it.Selected then begin
  223. inc(n); if n>1 then exit(true);
  224. end;
  225. end;
  226. end;
  227. function TfraExpRemoto.SelecMulTodArchivos: boolean;
  228. //Indica si la selección incluye solamente archivos
  229. var
  230. it: TListItem;
  231. begin
  232. Result := true; //se asume que todos lo son
  233. for it in ListView1.Items do if it.Selected then begin
  234. if it.ImageIndex <> IMG_ARCHIVO then begin
  235. exit(false); //hay al menos uno que no.
  236. end;
  237. end;
  238. end;
  239. function TfraExpRemoto.NumSeleccionados: integer;
  240. var
  241. it: TListItem;
  242. begin
  243. Result := 0;
  244. for it in ListView1.Items do begin
  245. if it.Selected then inc(Result);
  246. end;
  247. end;
  248. function TfraExpRemoto.EnviarComando(com: string; var salida: TStringList): string;
  249. {Envía un comando a la sesión actual.}
  250. var
  251. ses: TfraTabSession;
  252. begin
  253. if frmPrincipal.GetCurSession(ses) then begin
  254. Result := ses.EnviarComando(com, salida);
  255. end else begin
  256. Result := '';
  257. end;
  258. end;
  259. procedure TfraExpRemoto.Actualizar;
  260. //actualiza la lista de archivos de la ruta actual
  261. var
  262. i: Integer;
  263. MsjErr : string;
  264. n: Integer;
  265. fil: String;
  266. begin
  267. ListDet := config.ListDet; //lee bandera
  268. MosOcul := config.MosOcul;
  269. if ListDet then ConfigurarColumnasDetalladas //actualiza apariencia
  270. else ConfigurarColumnasSimple;
  271. if not frmPrincipal.AvailableConnection then begin
  272. MsgExc('No available connection');
  273. ListView1.Items.Clear;
  274. AgregarFilaErr('Error on reading data.');
  275. exit;
  276. end;
  277. AgregarMensajeEspera('Reading...'); //sería bueno mostrar una animación
  278. //actualiza lista de archivos
  279. if config.MosRut then begin //debe actualizar ruta
  280. EnviarComando('pwd',listmp); //lee ruta
  281. txtRuta.Text:= listmp.Text;
  282. Panel1.Visible:=true; //muestra panel de ruta
  283. end else begin
  284. Panel1.Visible:=false;
  285. end;
  286. if ListDet then begin
  287. ConfigurarColumnasDetalladas;
  288. if MosOcul then MsjErr := EnviarComando('ls -la',lisArc)
  289. else MsjErr := EnviarComando('ls -l',lisArc);
  290. end else begin
  291. ConfigurarColumnasSimple;
  292. if MosOcul then MsjErr := EnviarComando('ls -1a',lisArc)
  293. else MsjErr := EnviarComando('ls -1',lisArc);
  294. end;
  295. if MsjErr <> '' then begin
  296. ListView1.Items.Clear;
  297. AgregarFilaErr('Error on reading data.');
  298. end else begin //no hubo MsjErr
  299. ListView1.Items.Clear;
  300. if not MosOcul then AgregarCarpAtras; //para que se pueda retroceder
  301. n := 0; //contador
  302. if ListDet then begin //////lista detallada
  303. ListView1.BeginUpdate;
  304. //agrega primero las carpetas
  305. for fil in lisArc do begin
  306. if length(fil) > 20 then begin //filtra TOTAL: ####
  307. if fil[1] = 'd' then begin AgregarFilaCar(fil); inc(n); end;
  308. end;
  309. end;
  310. //agrega luego los archivos
  311. for fil in lisArc do begin
  312. if length(fil) > 20 then begin //filtra TOTAL: ####
  313. if fil[1] <> 'd' then begin AgregarFilaArc(fil); inc(n); end;
  314. end;
  315. end;
  316. ListView1.EndUpdate;
  317. end else begin //////////lista simple
  318. for i:=0 to lisArc.Count-1 do begin
  319. AgregarFilaArc(lisArc[i]);
  320. inc(n);
  321. end;
  322. end;
  323. StatusBar1.Panels[0].Text := IntToStr(n) + ' files read.';
  324. end;
  325. end;
  326. procedure TfraExpRemoto.ActualizarSel(arc: string);
  327. //Actualiza la lista de archivos y selecciona un archivo o carpeta
  328. var
  329. it: TListItem;
  330. begin
  331. Actualizar;
  332. it := BuscarItem(arc);
  333. if it = nil then exit;
  334. it.Selected:=true;
  335. end;
  336. constructor TfraExpRemoto.Create(AOwner: TComponent);
  337. begin
  338. inherited Create(AOwner);
  339. //Prepara lista.
  340. ListView1.RowSelect:=true;
  341. ListView1.MultiSelect:=true;
  342. ListView1.ViewStyle:=vsReport;
  343. ListView1.ReadOnly:=true; //para que no se edite con doble click
  344. ListView1.OnEdited:=@ListView1Edited;
  345. lisArc := TStringlist.Create; //crea lista de archivos
  346. listmp := TStringlist.Create; //crea lista de archivos
  347. re := TRegExpr.Create;
  348. //Define expresión regular para extraer campos de la lista de archivos
  349. re.Expression := '^(\S+)\x20+(\d+)\x20+(\w+)\x20+(\w+)\x20+(\d+)\x20+'+ //primeros campos
  350. '(\w{3}\x20+\d+\x20+\S+|\d+\x20+\w{3}\x20+\S+)\x20+(.+)'; //fecha y nombre
  351. end;
  352. destructor TfraExpRemoto.Destroy;
  353. begin
  354. re.Free;
  355. lisArc.Destroy;
  356. listmp.Destroy;
  357. inherited Destroy;
  358. end;
  359. ////////////////////// acciones ///////////////////
  360. procedure TfraExpRemoto.acVerRefresExecute(Sender: TObject);
  361. begin
  362. Actualizar;
  363. end;
  364. procedure TfraExpRemoto.ListView1DblClick(Sender: TObject);
  365. var
  366. it: TListItem;
  367. begin
  368. if ListView1.ItemIndex<>-1 then begin
  369. //doble click en ítem
  370. it := listView1.Items[ListView1.ItemIndex];
  371. if it.ImageIndex = IMG_CARPETA then begin //es carpeta
  372. EnviarComando('cd "'+it.Caption+'"', listmp);
  373. if trim(listmp.Text)<>'' then msgErr(listmp.Text);
  374. ActualizarSel('..');
  375. end else begin //es archivo
  376. //dispara evento
  377. if OnDblClickArch<>nil then OnDblClickArch;
  378. end;
  379. end;
  380. end;
  381. procedure TfraExpRemoto.ListView1Edited(Sender: TObject; Item: TListItem;
  382. var AValue: string);
  383. //Evento porducido después de editar un nombre
  384. begin
  385. if Item.Caption <> Avalue then begin
  386. EnviarComando('mv "'+ Item.Caption + '" "'+ Avalue+'"', listmp);
  387. if trim(listmp.Text)<>'' then msgErr(listmp.Text);
  388. if config.RefDesp then ActualizarSel(Avalue);
  389. end;
  390. end;
  391. procedure TfraExpRemoto.ListView1KeyDown(Sender: TObject; var Key: Word;
  392. Shift: TShiftState);
  393. begin
  394. if Key = VK_DELETE then begin
  395. acEdDeleteExecute(self);
  396. end;
  397. end;
  398. procedure TfraExpRemoto.ListView1KeyPress(Sender: TObject; var Key: char);
  399. begin
  400. if Key = #8 then begin //backspace
  401. EnviarComando('cd ..', listmp);
  402. if trim(listmp.Text)<>'' then msgErr(listmp.Text);
  403. ActualizarSel('..');
  404. end;
  405. if key = #13 then begin
  406. ListView1DblClick(self);
  407. end;
  408. end;
  409. procedure TfraExpRemoto.ListView1SelectItem(Sender: TObject; Item: TListItem;
  410. Selected: Boolean);
  411. begin
  412. StatusBar1.Panels[1].Text:=IntToStr(NumSeleccionados)+' items selected.';
  413. end;
  414. procedure TfraExpRemoto.acFilNewFileExecute(Sender: TObject); //nuevo archivo
  415. var
  416. nom: String;
  417. n: Integer;
  418. begin
  419. //Genera nuevo nombre
  420. nom := 'NewFile';
  421. n := 1;
  422. while BuscarItem(nom)<>nil do
  423. begin
  424. inc(n); nom := 'NewFile' + IntToStr(n);
  425. end;
  426. EnviarComando('echo "" >'+ nom, listmp);
  427. if config.RefDesp then ActualizarSel(nom);
  428. self.SetFocus;
  429. end;
  430. procedure TfraExpRemoto.acFilRenameExecute(Sender: TObject); //renombrar
  431. var
  432. it: TListItem;
  433. begin
  434. it := ItemSeleccionado;
  435. if it = nil then exit;
  436. ListView1.ReadOnly:=false; //para editar
  437. // anterior := it.Caption;
  438. it.EditCaption; //inicia edición
  439. ListView1.ReadOnly:=true; //para que no se edite con doble click
  440. end;
  441. procedure TfraExpRemoto.acFilNewFoldExecute(Sender: TObject); //nueva carpeta
  442. var
  443. nom: String;
  444. n: Integer;
  445. begin
  446. //Genera nuevo nombre
  447. nom := 'NewFolder';
  448. n := 1;
  449. while BuscarItem(nom)<>nil do
  450. begin
  451. inc(n); nom := 'NewFolder' + IntToStr(n);
  452. end;
  453. EnviarComando('mkdir '+nom, listmp);
  454. if config.RefDesp then ActualizarSel(nom);
  455. end;
  456. procedure TfraExpRemoto.acEdDeleteExecute(Sender: TObject); //eliminar
  457. var
  458. it: TListItem;
  459. begin
  460. it := ItemSeleccionado;
  461. if it = nil then exit;
  462. if SelecMultiple then begin //selección múltiple
  463. if SelecMulTodArchivos then begin //todos son archivos
  464. if MsgYesNo('Delete %d files?',[NumSeleccionados]) = 1 then begin
  465. for it in ListView1.Items do if it.Selected then begin
  466. EnviarComando('rm "' + it.Caption+'"', listmp);
  467. end;
  468. if config.RefDesp then Actualizar;
  469. end;
  470. end else begin //hay carpetas entre los seleccionados
  471. MsgExc('Cannot delete files and folders together.');
  472. end;
  473. end else begin //selección simple
  474. if it.ImageIndex = IMG_CARPETA then begin //es carpeta
  475. if MsgYesNo('Delete folder: %s ?',[it.Caption]) = 1 then begin
  476. EnviarComando('rmdir '+it.Caption, listmp);
  477. if trim(listmp.Text)<>'' then msgErr(listmp.Text);
  478. if config.RefDesp then Actualizar;
  479. end;
  480. end else begin //es archivo
  481. if MsgYesNo('Delete file: %s ?', [it.Caption]) = 1 then begin
  482. EnviarComando('rm "' + it.Caption+'"', listmp);
  483. if trim(listmp.Text)<>'' then msgErr(listmp.Text);
  484. if config.RefDesp then Actualizar;
  485. end;
  486. end;
  487. end;
  488. end;
  489. procedure TfraExpRemoto.acHerEjecExecute(Sender: TObject); //ejecutar
  490. var
  491. it: TListItem;
  492. begin
  493. it := ItemSeleccionado;
  494. if it = nil then exit;
  495. EnviarComando(it.Caption, listmp);
  496. end;
  497. procedure TfraExpRemoto.acEdEditExecute(Sender: TObject); //editar archivo
  498. var
  499. it: TListItem;
  500. begin
  501. it := ItemSeleccionado;
  502. if it = nil then exit;
  503. if it.ImageIndex = IMG_CARPETA then begin //es carpeta
  504. // EnviarComando('cd '+it.Caption, listmp);
  505. // if config.fcExpRem.RefDesp then Actualizar;
  506. end else begin //es archivo
  507. frmRemoteEditor.AbrirRemoto(it.Caption);
  508. end;
  509. end;
  510. procedure TfraExpRemoto.acConfigExecute(Sender: TObject);
  511. begin
  512. config.Configurar('6.1');
  513. end;
  514. end.