1 /* dirsizeop.cc
2 * This file belongs to Worker, a file manager for UN*X/X11.
3 * Copyright (C) 2001-2021 Ralf Hoffmann.
4 * You can contact me at: ralf@boomerangsworld.de
5 * or http://www.boomerangsworld.de/worker
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "showdircacheop.h"
23 #include "listermode.h"
24 #include "virtualdirmode.hh"
25 #include "worker.h"
26 #include "worker_locale.h"
27 #include "aguix/stringgadget.h"
28 #include "aguix/button.h"
29 #include "aguix/fieldlistview.h"
30 #include "nwc_path.hh"
31 #include "argclass.hh"
32 #include <algorithm>
33
34 const char *ShowDirCacheOp::name = "ShowDirCacheOp";
35
ShowDirCacheOp()36 ShowDirCacheOp::ShowDirCacheOp() : FunctionProto()
37 {
38 }
39
~ShowDirCacheOp()40 ShowDirCacheOp::~ShowDirCacheOp()
41 {
42 }
43
44 ShowDirCacheOp*
duplicate() const45 ShowDirCacheOp::duplicate() const
46 {
47 ShowDirCacheOp *ta=new ShowDirCacheOp();
48 return ta;
49 }
50
51 bool
isName(const char * str)52 ShowDirCacheOp::isName( const char *str )
53 {
54 if ( strcmp( str, name ) == 0 ) return true; else return false;
55 }
56
57 const char *
getName()58 ShowDirCacheOp::getName()
59 {
60 return name;
61 }
62
63 int
run(std::shared_ptr<WPUContext> wpu,ActionMessage * msg)64 ShowDirCacheOp::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
65 {
66 ListerMode *lm1;
67 if(msg->mode!=msg->AM_MODE_DNDACTION) {
68 Lister *l1=msg->getWorker()->getActiveLister();
69 if(l1!=NULL) {
70 lm1 = l1->getActiveMode();
71 if(lm1!=NULL) {
72 showCacheList( msg );
73 }
74 }
75 }
76 return 0;
77 }
78
79 const char *
getDescription()80 ShowDirCacheOp::getDescription()
81 {
82 return catalog.getLocale( 1286);
83 }
84
showCacheList(ActionMessage * msg)85 void ShowDirCacheOp::showCacheList( ActionMessage *msg )
86 {
87 ListerMode *lm1;
88 Lister *l1 = msg->getWorker()->getActiveLister();
89
90 if ( l1 == NULL ) return;
91
92 lm1 = l1->getActiveMode();
93
94 if ( lm1 == NULL ) return;
95
96 VirtualDirMode *vdm = dynamic_cast< VirtualDirMode *>( lm1 );
97
98 AWindow *win;
99 int my_w, my_h, endmode, mw, mh;
100 AGMessage *agmsg;
101 FieldListView *cachelv;
102 StringGadget *cachesg;
103 int parents, cachebegin;
104 AGUIX *aguix = Worker::getAGUIX();
105 std::list< std::string > cache_entries;
106 int row;
107
108 if ( vdm != NULL ) {
109 cache_entries = vdm->getNameOfCacheEntries();
110 }
111
112 win = new AWindow( aguix, 10, 10, 10, 10, catalog.getLocale( 523 ), AWindow::AWINDOW_DIALOG );
113 win->create();
114
115 AContainer *ac1 = win->setContainer( new AContainer( win, 1, 3 ), true );
116 ac1->setMinSpace( 5 );
117 ac1->setMaxSpace( 5 );
118 ac1->setBorderWidth( 5 );
119
120 ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 524 ) ),
121 0, 0, AContainer::CO_INCWNR );
122
123 AContainer *ac1_2 = ac1->add( new AContainer( win, 1, 2 ), 0, 1 );
124 ac1_2->setMinSpace( 0 );
125 ac1_2->setMaxSpace( 0 );
126 ac1_2->setBorderWidth( 0 );
127
128 cachelv = (FieldListView*)ac1_2->add( new FieldListView( aguix, 0, 0, 50, 50 ,0 ),
129 0, 0, AContainer::CO_MIN );
130 cachelv->setHBarState( 2 );
131 cachelv->setVBarState( 2 );
132
133 cachesg = (StringGadget*)ac1_2->add( new StringGadget( aguix, 0, 0, 50, "", 0 ),
134 0, 1, AContainer::CO_INCW );
135
136 AContainer *ac1_1 = ac1->add( new AContainer( win, 2, 1 ), 0, 2 );
137 ac1_1->setMinSpace( 5 );
138 ac1_1->setMaxSpace( -1 );
139 ac1_1->setBorderWidth( 0 );
140 Button *okb =(Button*)ac1_1->add( new Button( aguix,
141 0,
142 0,
143 catalog.getLocale( 11 ),
144 0 ), 0, 0, AContainer::CO_FIX );
145 Button *cancelb = (Button*)ac1_1->add( new Button( aguix,
146 0,
147 0,
148 catalog.getLocale( 8 ),
149 0 ), 1, 0, AContainer::CO_FIX );
150
151 std::string cwd = lm1->getCurrentDirectory();
152 if ( ! cwd.empty() ) {
153 char *tstr1 = dupstring( cwd.c_str() );
154 for ( ;; ) {
155 char *tstr2 = NWC::Path::parentDir( tstr1, NULL );
156 if ( tstr2 == NULL ) break;
157
158 // add tstr2 to the lv
159 row = cachelv->addRow();
160 cachelv->setText( row, 0 , tstr2 );
161 cachelv->setPreColors( row, FieldListView::PRECOLOR_ONLYACTIVE );
162
163 _freesafe( tstr1 );
164 tstr1 = tstr2;
165 if ( strcmp( tstr1, "/" ) == 0 ) break;
166 }
167 _freesafe( tstr1 );
168 }
169
170 parents = cachelv->getElements();
171
172 std::string delim1( strlen( catalog.getLocale( 523 ) ), '-' );
173 row = cachelv->addRow();
174 cachelv->setText( row, 0, delim1 );
175 cachelv->setPreColors( row, FieldListView::PRECOLOR_NOTSELORACT );
176 row = cachelv->addRow();
177 cachelv->setText( row, 0, catalog.getLocale( 523 ) );
178 cachelv->setPreColors( row, FieldListView::PRECOLOR_NOTSELORACT );
179 row = cachelv->addRow();
180 cachelv->setText( row, 0, catalog.getLocale( 812 ) );
181 cachelv->setPreColors( row, FieldListView::PRECOLOR_NOTSELORACT );
182 row = cachelv->addRow();
183 cachelv->setText( row, 0, delim1 );
184 cachelv->setPreColors( row, FieldListView::PRECOLOR_NOTSELORACT );
185
186 cachebegin = row + 1;
187
188 if ( ! cache_entries.empty() ) {
189 for ( auto &e : cache_entries ) {
190 row = cachelv->addRow();
191 cachelv->setText( row, 0, e );
192 cachelv->setPreColors( row, FieldListView::PRECOLOR_ONLYACTIVE );
193 }
194 }
195
196 // maximize cachelv and store sizes
197 cachelv->maximizeX();
198 cachelv->maximizeY();
199 my_w = cachelv->getWidth();
200 my_h = cachelv->getHeight();
201
202 // now resize container to 80% screen size
203 int rx, ry, rw, rh;
204
205 aguix->getLargestDimensionOfCurrentScreen( &rx, &ry,
206 &rw, &rh );
207
208 mw = rw * 80 / 100;
209 mh = rh * 80 / 100;
210 ac1->resize( mw, mh );
211 ac1->rearrange();
212
213 // and check whether the cachelv needs less space
214 // and set min parameter to match 80% or less
215 if ( my_w < cachelv->getWidth() ) {
216 ac1_2->setMinWidth( my_w, 0, 0 );
217 } else {
218 ac1_2->setMinWidth( cachelv->getWidth(), 0, 0 );
219 }
220 if ( my_h < cachelv->getHeight() ) {
221 ac1_2->setMinHeight( my_h, 0, 0 );
222 } else {
223 ac1_2->setMinHeight( cachelv->getHeight(), 0, 0 );
224 }
225
226 win->contMaximize( true );
227 win->setDoTabCycling( true );
228 cachesg->takeFocus();
229
230 if ( parents > 0 ) {
231 cachelv->setActiveRow( 0 );
232 cachesg->setText( cachelv->getText( 0, 0 ).c_str() );
233 } else if ( ! cache_entries.empty() ) {
234 cachelv->setActiveRow( cachebegin );
235 cachesg->setText( cachelv->getText( cachebegin, 0 ).c_str() );
236 }
237
238 // catch msgs before mapping, this are mostly resize msgs
239 while ( ( agmsg = aguix->GetMessage( win ) ) != NULL ) aguix->ReplyMessage( agmsg );
240
241 win->show();
242
243 for( endmode = -1; endmode == -1; ) {
244 agmsg = aguix->WaitMessage( win );
245 if ( agmsg != NULL ) {
246 switch ( agmsg->type ) {
247 case AG_CLOSEWINDOW:
248 if ( agmsg->closewindow.window == win->getWindow() ) endmode = 1;
249 break;
250 case AG_BUTTONCLICKED:
251 if ( agmsg->button.button == okb ) endmode = 0;
252 else if ( agmsg->button.button == cancelb ) endmode = 1;
253 break;
254 case AG_FIELDLV_ONESELECT:
255 case AG_FIELDLV_MULTISELECT:
256 if ( agmsg->fieldlv.lv == cachelv ) {
257 row = cachelv->getActiveRow();
258 if ( cachelv->isValidRow( row ) == true ) {
259 if ( ( row < parents ) ||
260 ( row >= cachebegin ) ) {
261 // this is one of the parents
262 cachesg->setText( cachelv->getText( row, 0 ).c_str() );
263 }
264 }
265 }
266 break;
267 case AG_FIELDLV_DOUBLECLICK:
268 if ( agmsg->fieldlv.lv == cachelv &&
269 cachelv->isValidRow( agmsg->fieldlv.row ) == true ) {
270 if ( ( agmsg->fieldlv.row < parents ) ||
271 ( agmsg->fieldlv.row >= cachebegin ) ) {
272 // this is one of the parents
273 endmode = 0;
274 }
275 }
276 break;
277 case AG_STRINGGADGET_CONTENTCHANGE:
278 if ( agmsg->stringgadget.sg == cachesg ) {
279 //TODO: U.U. merkt user ein Lag, deshalb koennte man ein Flag setzen und
280 // ausserhalb messen, wenn letzte Nachricht her ist und dann suchen
281 // Aber dann muss ich getMessage machen
282 const char *tstr = cachesg->getText();
283 for ( row = 0; row < cachelv->getElements(); row++ ) {
284 if ( strcmp( tstr, cachelv->getText( row, 0 ).c_str() ) == 0 ) {
285 if ( ( row >= 0 && row < parents ) ||
286 ( row >= cachebegin && row < ( cachebegin + (int)cache_entries.size() ) ) ) {
287 cachelv->setActiveRow( row );
288 cachelv->showActive();
289 }
290 break;
291 }
292 }
293 }
294 break;
295 case AG_STRINGGADGET_CANCEL:
296 if ( agmsg->stringgadget.sg == cachesg ) endmode = 1;
297 break;
298 case AG_STRINGGADGET_OK:
299 if ( agmsg->stringgadget.sg == cachesg ) endmode = 0;
300 break;
301 case AG_KEYPRESSED:
302 if ( win->isParent( agmsg->key.window, false ) == true ) {
303 switch ( agmsg->key.key ) {
304 case XK_Up:
305 row = cachelv->getActiveRow();
306 if ( cachelv->isValidRow( row ) == true ) {
307 if ( ( row >= parents ) && ( row <= cachebegin ) ) {
308 row = parents - 1;
309 } else {
310 row--;
311 }
312 if ( row >= 0 ) {
313 cachelv->setActiveRow( row );
314 cachelv->showActive();
315 cachesg->setText( cachelv->getText( row, 0 ).c_str() );
316 }
317 }
318 break;
319 case XK_Down:
320 row = cachelv->getActiveRow();
321 if ( cachelv->isValidRow( row ) == true ) {
322 if ( ( row >= ( parents - 1 ) ) && ( row < cachebegin ) ) {
323 row = cachebegin;
324 } else {
325 row++;
326 }
327 if ( cachelv->isValidRow( row ) == true ) {
328 cachelv->setActiveRow( row );
329 cachelv->showActive();
330 cachesg->setText( cachelv->getText( row, 0 ).c_str() );
331 }
332 }
333 break;
334 case XK_Prior:
335 row = cachelv->getActiveRow();
336 if ( cachelv->isValidRow( row ) == true ) {
337 row -= cachelv->getMaxDisplayV() - 1;
338 if ( ( row >= parents ) && ( row < cachebegin ) ) row = parents - 1;
339 if ( row < 0 ) {
340 if ( parents > 0 ) row = 0;
341 else row = cachebegin;
342 }
343 } else {
344 if ( parents > 0 ) row = 0;
345 else if ( ! cache_entries.empty() ) row = cachebegin;
346 }
347 if ( cachelv->isValidRow( row ) == true ) {
348 cachelv->setActiveRow( row );
349 cachelv->showActive();
350 cachesg->setText( cachelv->getText( row, 0 ).c_str() );
351 }
352 break;
353 case XK_Next:
354 row = cachelv->getActiveRow();
355 if ( cachelv->isValidRow( row ) == true ) {
356 row += cachelv->getMaxDisplayV() - 1;
357 if ( ( row >= parents ) && ( row < cachebegin ) ) row = cachebegin;
358 if ( row >= ( cachebegin + (int)cache_entries.size() ) ) {
359 if ( ! cache_entries.empty() ) row = cachebegin + cache_entries.size() - 1;
360 else row = parents - 1;
361 }
362 } else {
363 if ( parents > 0 ) row = 0;
364 else if ( ! cache_entries.empty() ) row = cachebegin;
365 }
366 if ( cachelv->isValidRow( row ) == true ) {
367 cachelv->setActiveRow( row );
368 cachelv->showActive();
369 cachesg->setText( cachelv->getText( row, 0 ).c_str() );
370 }
371 break;
372 case XK_Home:
373 row = -1;
374 if ( parents > 0 ) row = 0;
375 else if ( ! cache_entries.empty() ) row = cachebegin;
376 if ( cachelv->isValidRow( row ) == true ) {
377 cachelv->setActiveRow( row );
378 cachelv->showActive();
379 cachesg->setText( cachelv->getText( row, 0 ).c_str() );
380 }
381 break;
382 case XK_End:
383 row = -1;
384 if ( ! cache_entries.empty() ) row = cachebegin + cache_entries.size() - 1;
385 else if ( parents > 0 ) row = parents - 1;
386 if ( cachelv->isValidRow( row ) == true ) {
387 cachelv->setActiveRow( row );
388 cachelv->showActive();
389 cachesg->setText( cachelv->getText( row, 0 ).c_str() );
390 }
391 break;
392 case XK_Return:
393 case XK_KP_Enter:
394 if ( cancelb->getHasFocus() == false ) {
395 endmode = 0;
396 }
397 break;
398 case XK_Escape:
399 endmode = 1;
400 break;
401 }
402 }
403 break;
404 }
405 aguix->ReplyMessage( agmsg );
406 }
407 }
408 if ( endmode == 0 ) {
409 // ok->take cachesg and enterdir
410 std::string dir = cachesg->getText();
411
412 if ( std::find( cache_entries.begin(),
413 cache_entries.end(),
414 dir ) != cache_entries.end() ) {
415 std::list< RefCount< ArgClass > > args;
416
417 args.push_back( new StringArg( dir ) );
418 lm1->runCommand( "show_cache_entry", args );
419 } else {
420 std::list< RefCount< ArgClass > > args;
421
422 args.push_back( new StringArg( dir ) );
423 lm1->runCommand( "enter_dir", args );
424 }
425 }
426 delete win;
427
428 return;
429 }
430