1 /* copyopwin.cc
2 * This file belongs to Worker, a file manager for UN*X/X11.
3 * Copyright (C) 2001-2014 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 "worker.h"
23 #include "copyopwin.hh"
24 #include "aguix/util.h"
25 #include "aguix/lowlevelfunc.h"
26 #include "aguix/awindow.h"
27 #include "aguix/button.h"
28 #include "aguix/bevelbox.h"
29 #include "aguix/solidbutton.h"
30 #include "aguix/choosebutton.h"
31 #include "worker_locale.h"
32 #include "datei.h"
33 #include "pers_kvp.hh"
34
35 #define HUMAN_READABLE_DIALOG 1
36
CopyOpWin(AGUIX * taguix,bool _move)37 CopyOpWin::CopyOpWin( AGUIX*taguix, bool _move )
38 {
39 this->aguix=taguix;
40 copied_bytes_curfile=0;
41 bytes_curfile=0;
42 copied_bytes=0;
43 bytes=0;
44 copied_files=0;
45 files=0;
46 copied_dirs=0;
47 dirs=0;
48
49 window=NULL;
50 melw = 0;
51 filenamespace[0] = 0;
52 filenamespace[1] = 0;
53 ismessage[0] = false;
54 ismessage[1] = false;
55
56 update_sourcetext = false;
57 update_desttext = false;
58 update_filetext = false;
59 update_globtext = false;
60 update_files2gotext = false;
61 update_dirs2gotext = false;
62
63 mintime = 1000000;
64 lastbytes = 0;
65 lastrate = 0.0;
66 lastbytes_global = 0;
67 lastrate_global = 0.0;
68
69 glob_percent = 0;
70
71 move = _move;
72
73 lencalc = new AFontWidth( aguix, NULL );
74 memset( &stoptime, 0, sizeof( stoptime ) );
75 timer_stopped = false;
76
77 gettimeofday( &last_update_time, NULL );
78 skipped_updates = 0;
79
80 m_master_thread_id = std::this_thread::get_id();
81
82 m_finished = false;
83 m_detached = false;
84
85 int v = Worker::getPersKVPStore().getIntValue( "copy-keep-window" );
86
87 // 0 is default for non-existing entry, 2 means enabled
88 if ( v == 0 ||
89 v == 2 ) {
90 m_keep_window = true;
91 } else {
92 m_keep_window = false;
93 }
94
95 m_keep_window_cb = nullptr;
96 }
97
~CopyOpWin()98 CopyOpWin::~CopyOpWin()
99 {
100 if(window!=NULL) close();
101 delete lencalc;
102 }
103
104 int
open()105 CopyOpWin::open()
106 {
107 int w,h;
108 int tx,ty;
109 Text *ttext;
110
111 close();
112 w=400;
113 h=10;
114 window = new AWindow( aguix,
115 10, 10,
116 w, h,
117 ( move == true ) ? catalog.getLocale( 299 ) : catalog.getLocale( 1249 ),
118 AWindow::AWINDOW_NORMAL );
119 window->create();
120 tx=5;
121 ty=5;
122 sourcetext=(Text*)window->add(new Text(aguix,tx,ty,""));
123 ismessage[0] = true;
124 ty+=sourcetext->getHeight()+5;
125 desttext=(Text*)window->add(new Text(aguix,tx,ty,""));
126 ismessage[1] = true;
127 ty+=desttext->getHeight()+5;
128 fsb=(SolidButton*)window->add(new SolidButton(aguix,tx+1,ty+1,w-2*(tx+1),"","button-special1-fg", "button-special1-bg",0));
129 sbw=fsb->getWidth();
130 bb1=(BevelBox*)window->add(new BevelBox(aguix,tx,ty,w-2*tx,fsb->getHeight()+2,1));
131 fsb->toFront();
132 ty+=bb1->getHeight()+5;
133 tx=10;
134 filetext=(Text*)window->add(new Text(aguix,tx,ty,""));
135 ty+=filetext->getHeight()+5;
136
137 ttext = (Text*)window->add( new Text( aguix, tx, ty, catalog.getLocale( 90 ) ) );
138 tx += ttext->getWidth() + 5;
139 fileavgtext = (Text*)window->add( new Text( aguix, tx, ty, "" ) );
140 ty += fileavgtext->getHeight() + 5;
141
142 tx=5;
143 bb2=(BevelBox*)window->add(new BevelBox(aguix,tx,ty,w-2*tx,2,0));
144 ty+=bb2->getHeight()+5;
145
146 ttext=(Text*)window->add(new Text(aguix,tx,ty,catalog.getLocale(118)));
147 tx+=ttext->getWidth()+5;
148 files2gotext=(Text*)window->add(new Text(aguix,tx,ty,""));
149 tx=5;
150 ty+=ttext->getHeight()+5;
151 ttext=(Text*)window->add(new Text(aguix,tx,ty,catalog.getLocale(119)));
152 tx+=ttext->getWidth()+5;
153 dirs2gotext=(Text*)window->add(new Text(aguix,tx,ty,""));
154 tx=5;
155 ty+=ttext->getHeight()+5;
156 gsb=(SolidButton*)window->add(new SolidButton(aguix,tx+1,ty+1,w-2*(tx+1),"","button-special1-fg", "button-special1-bg",0));
157 bb3=(BevelBox*)window->add(new BevelBox(aguix,tx,ty,w-2*tx,gsb->getHeight()+2,1));
158 gsb->toFront();
159 ty+=bb3->getHeight()+5;
160 tx=10;
161 ttext=(Text*)window->add(new Text(aguix,tx,ty,catalog.getLocale(120)));
162 tx+=ttext->getWidth()+5;
163 globtext=(Text*)window->add(new Text(aguix,tx,ty,""));
164 tx=5;
165 ty+=globtext->getHeight()+5;
166 ttext=(Text*)window->add(new Text(aguix,tx,ty,catalog.getLocale(121)));
167 tx+=ttext->getWidth()+5;
168 timetext=(Text*)window->add(new Text(aguix,tx,ty,""));
169 ty+=timetext->getHeight()+5;
170 tx=5;
171 bb4=(BevelBox*)window->add(new BevelBox(aguix,tx,ty,w-2*tx,2,0));
172 ty+=bb4->getHeight()+5;
173
174 m_detach_b = (Button*)window->add( new Button( aguix, tx, ty, catalog.getLocale( 1039 ), 0 ) );
175
176 m_keep_window_cb = (ChooseButton*)window->add( new ChooseButton( aguix, tx, ty,
177 m_keep_window,
178 catalog.getLocale( 1047 ),
179 LABEL_RIGHT, 0 ) );
180 m_keep_window_cb->hide();
181
182 cb = (Button*)window->add( new Button( aguix, tx, ty, catalog.getLocale( 8 ), 0 ) );
183 cb->move( w - 5 - cb->getWidth(), cb->getY() );
184
185 ty+=cb->getHeight()+5;
186 h=ty;
187 window->setDoTabCycling( true );
188 window->resize(w,h);
189 window->setMinSize(w,h);
190 // window->setMaxSize(w,h);
191 window->centerScreen();
192 window->show();
193
194 filenamespace[0] = w - window->getBorderWidth() - sourcetext->getX();
195 filenamespace[0] -= aguix->getTextWidth( catalog.getLocale( ( move == true ) ? 594 : 116 ) ) - 2 * aguix->getTextWidth( " " );
196 filenamespace[1] = w - window->getBorderWidth() - desttext->getX();
197 filenamespace[1] -= aguix->getTextWidth( catalog.getLocale( 117 ) ) - 2 * aguix->getTextWidth( " " );
198
199 return 0;
200 }
201
202 void
close()203 CopyOpWin::close()
204 {
205 if(window!=NULL) {
206 delete window;
207 }
208 window=NULL;
209 }
210
211 void
starttimer()212 CopyOpWin::starttimer()
213 {
214 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
215
216 gettimeofday( &starttime, NULL );
217 lasttime_global = starttime;
218 }
219
220 void
set_files_to_copy(long nfiles)221 CopyOpWin::set_files_to_copy(long nfiles)
222 {
223 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
224
225 if(nfiles>0) files=nfiles;
226 else files=0;
227 update_files2gotext=true;
228 }
229
230 void
set_dirs_to_copy(long ndirs)231 CopyOpWin::set_dirs_to_copy(long ndirs)
232 {
233 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
234
235 if(ndirs>0) dirs=ndirs;
236 else dirs=0;
237 update_dirs2gotext=true;
238 }
239
240 void
set_bytes_to_copy(loff_t nbytes)241 CopyOpWin::set_bytes_to_copy(loff_t nbytes)
242 {
243 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
244
245 if(nbytes>0) bytes=nbytes;
246 else bytes=0;
247 update_globtext=true;
248 }
249
250 void
set_bytes_to_copy_curfile(loff_t nbytes)251 CopyOpWin::set_bytes_to_copy_curfile( loff_t nbytes )
252 {
253 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
254
255 if ( nbytes > 0 ) bytes_curfile = nbytes;
256 else bytes_curfile = 0;
257 update_filetext = true;
258 }
259
260 void
dir_finished()261 CopyOpWin::dir_finished()
262 {
263 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
264
265 copied_dirs++;
266 update_dirs2gotext=true;
267 }
268
269 void
file_finished()270 CopyOpWin::file_finished()
271 {
272 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
273
274 // inc counter
275 copied_files++;
276 update_files2gotext=true;
277 if ( skipped_updates > 0 ) {
278 update_filetext = true;
279 update_globtext = true;
280 }
281 }
282
283 void
add_curbytes_copied(loff_t nbytes)284 CopyOpWin::add_curbytes_copied( loff_t nbytes )
285 {
286 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
287
288 if ( nbytes > 0 ) {
289 copied_bytes_curfile += nbytes;
290 copied_bytes += nbytes;
291 }
292
293 struct timeval curtime;
294 gettimeofday( &curtime, NULL );
295 if ( ldiffgtod_m( &curtime, &last_update_time ) >= ( 1000 / UPDATES_PER_SECOND ) ) {
296 update_filetext = true;
297 update_globtext = true;
298 last_update_time = curtime;
299 skipped_updates = 0;
300 } else {
301 skipped_updates++;
302 }
303 }
304
305 void
newfile(const std::string & name,const std::string & ndest)306 CopyOpWin::newfile( const std::string &name,
307 const std::string &ndest )
308 {
309 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
310
311 source = name;
312
313 dest = ndest;
314
315 gettimeofday( &filestarttime, NULL );
316 update_sourcetext=true;
317 update_desttext=true;
318 ismessage[0] = false;
319 ismessage[1] = false;
320 copied_bytes_curfile = 0;
321 update_filetext=true;
322
323 lastbytes = 0;
324 lasttime = filestarttime;
325 lastrate = 0.0;
326 }
327
328 int
redraw(bool skip_message_handling)329 CopyOpWin::redraw( bool skip_message_handling )
330 { /* this functions will redraw the window AND process events for this window
331 * returns values:
332 * 0 for regular exit
333 * 1 when clicked Cancel-Button or closed window
334 * other not implemented */
335 int returnvalue=0;
336 long rtime, rtime_at_current_rate;
337 double drtime;
338 struct timeval curtime;
339 double difftime2, lastdiff2;
340 char tstr[1024],
341 *tstr2;
342 double rate;
343 int tw;
344 bool doresize = false;
345 int newglob_percent;
346 std::string copied_bytes_curfile_str,
347 bytes_curfile_str,
348 copied_bytes_str,
349 bytes_str;
350
351 char *tstr3;
352
353 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
354
355 timerclear( &curtime );
356 if ( update_sourcetext == true ) {
357 if ( ismessage[0] == false ) {
358 tstr3 = Datei::shrinkFilename( source.c_str(), filenamespace[0], *lencalc );
359 if ( tstr3 == NULL)
360 tstr3 = dupstring( source.c_str() );
361 tstr2 = (char*)_allocsafe( strlen( catalog.getLocale( ( move == true ) ? 594 : 116 ) ) + strlen( tstr3 ) + 1 );
362 sprintf( tstr2, catalog.getLocale( ( move == true ) ? 594 : 116 ), tstr3 );
363 _freesafe( tstr3 );
364 sourcetext->setText(tstr2);
365 _freesafe(tstr2);
366 /* no need for explicit redraw */
367 } else {
368 sourcetext->setText( source.c_str() );
369 }
370 update_sourcetext = false;
371 }
372 if ( update_desttext == true ) {
373 if ( ismessage[1] == false ) {
374 tstr3 = Datei::shrinkFilename( dest.c_str(), filenamespace[1], *lencalc );
375 if ( tstr3 == NULL)
376 tstr3 = dupstring( dest.c_str() );
377 tstr2 = (char*)_allocsafe( strlen( catalog.getLocale( 117 ) ) + strlen( tstr3 ) + 1 );
378 sprintf( tstr2, catalog.getLocale( 117 ), tstr3 );
379 _freesafe(tstr3);
380 desttext->setText(tstr2);
381 _freesafe(tstr2);
382 // no need for explicit redraw
383 } else {
384 desttext->setText( dest.c_str() );
385 }
386 update_desttext = false;
387 }
388 if(update_filetext==true) {
389 if ( ! timerisset( &curtime ) ) gettimeofday( &curtime, NULL );
390 difftime2 = diffgtod( &curtime, &filestarttime );
391 lastdiff2 = diffgtod( &curtime, &lasttime );
392
393 if ( lastdiff2 >= mintime ) {
394 lastrate = (double)( copied_bytes_curfile - lastbytes ) * 1000000.0 / lastdiff2;
395 lastbytes = copied_bytes_curfile;
396 lasttime = curtime;
397 }
398
399 if ( HUMAN_READABLE_DIALOG ) {
400 copied_bytes_curfile_str = AGUIXUtils::bytes_to_human_readable_f( (double)copied_bytes_curfile,
401 1, ( lastrate > 0.0 ) ? 5 : 0,
402 AGUIXUtils::BM_SYSTEM_SETTING,
403 lastrate );
404 bytes_curfile_str = AGUIXUtils::bytes_to_human_readable_f( (double)bytes_curfile,
405 1, ( lastrate > 0.0 ) ? 5 : 0,
406 AGUIXUtils::BM_SYSTEM_SETTING,
407 lastrate );
408
409 snprintf( tstr, sizeof( tstr ), "%s / %s @ %s/s",
410 copied_bytes_curfile_str.c_str(),
411 bytes_curfile_str.c_str(),
412 AGUIXUtils::bytes_to_human_readable_f( lastrate ).c_str() );
413 tstr[ sizeof( tstr ) - 1 ] = '\0';
414 } else {
415 MakeLong2NiceStr( copied_bytes_curfile, copied_bytes_curfile_str );
416
417 MakeLong2NiceStr( bytes_curfile, bytes_curfile_str );
418 snprintf( tstr, sizeof( tstr ), "%s / %s @ %.2f KB/s",
419 copied_bytes_curfile_str.c_str(),
420 bytes_curfile_str.c_str(),
421 lastrate / 1024.0 );
422 tstr[ sizeof( tstr ) - 1 ] = '\0';
423 }
424
425 filetext->setText(tstr);
426 tw = filetext->getX() + filetext->getWidth() + window->getBorderWidth();
427 if ( tw > melw ) {
428 melw = tw;
429 doresize = true;
430 }
431
432 if(difftime2>0) {
433 rate = (double)copied_bytes_curfile * 1000000.0 / difftime2;
434 } else rate=0.0;
435
436 if ( HUMAN_READABLE_DIALOG ) {
437 snprintf( tstr, sizeof( tstr ), "%s/s", AGUIXUtils::bytes_to_human_readable_f( rate ).c_str() );
438 } else {
439 snprintf( tstr, sizeof( tstr ), "%.2f KB/s", rate / 1024.0 );
440 }
441
442 tstr[ sizeof( tstr ) - 1 ] = '\0';
443 fileavgtext->setText( tstr );
444
445 int rate_precision = AGUIXUtils::calc_precision( rate * 100.0 / (double)bytes_curfile );
446 if ( rate_precision < 0 ) rate_precision = 0;
447
448 if(bytes_curfile>0)
449 rate = (double)copied_bytes_curfile/(double)bytes_curfile;
450 else
451 rate=0.0;
452 if ( rate < 0.01 )
453 rate = 0.0;
454
455 std::string fraction_str = AGUIXUtils::formatStringToString( "%%.%df %%%%",
456 rate_precision );
457
458 snprintf( tstr, sizeof( tstr ), fraction_str.c_str(), rate * 100.0 );
459 tstr[ sizeof( tstr ) - 1 ] = '\0';
460 fsb->setText(tstr);
461 fsb->resize( w_max( (int)( sbw * rate ), 2 ), fsb->getHeight() );
462 update_filetext=false;
463 }
464 if(update_globtext==true) {
465 if ( ! timerisset( &curtime ) ) gettimeofday( &curtime, NULL );
466 difftime2 = diffgtod( &curtime, &starttime );
467 if(difftime2>0.0) {
468 rate = (double)copied_bytes * 1000000.0 / difftime2;
469 } else rate=0.0;
470
471 double lastdiff_global = diffgtod( &curtime, &lasttime_global );
472
473 if ( lastdiff_global >= 10.0 * mintime ) {
474 lastrate_global = (double)( copied_bytes - lastbytes_global ) * 1000000.0 / lastdiff_global;
475 lastbytes_global = copied_bytes;
476 lasttime_global = curtime;
477 }
478
479 if ( HUMAN_READABLE_DIALOG ) {
480 copied_bytes_str = AGUIXUtils::bytes_to_human_readable_f( (double)copied_bytes,
481 1, ( rate > 0.0 ) ? 5 : 0,
482 AGUIXUtils::BM_SYSTEM_SETTING,
483 rate );
484
485 bytes_str = AGUIXUtils::bytes_to_human_readable_f( (double)bytes,
486 1, ( rate > 0.0 ) ? 5 : 0,
487 AGUIXUtils::BM_SYSTEM_SETTING,
488 rate );
489
490 snprintf( tstr, sizeof( tstr ), "%s / %s @ %s/s", copied_bytes_str.c_str(), bytes_str.c_str(), AGUIXUtils::bytes_to_human_readable_f( rate ).c_str() );
491 tstr[ sizeof( tstr ) - 1 ] = '\0';
492 } else {
493 MakeLong2NiceStr( copied_bytes, copied_bytes_str );
494 MakeLong2NiceStr( bytes, bytes_str );
495 snprintf( tstr, sizeof( tstr ), "%s / %s @ %.2f KB/s", copied_bytes_str.c_str(), bytes_str.c_str(), rate / 1024.0 );
496 tstr[ sizeof( tstr ) - 1 ] = '\0';
497 }
498
499 globtext->setText(tstr);
500 tw = globtext->getX() + globtext->getWidth() + window->getBorderWidth();
501 if ( tw > melw ) {
502 melw = tw;
503 doresize = true;
504 }
505
506 int rate_precision = AGUIXUtils::calc_precision( rate * 100.0 / (double)bytes );
507 if ( rate_precision < 0 ) rate_precision = 0;
508
509 if(bytes>0)
510 rate = (double)copied_bytes/(double)bytes;
511 else
512 rate=0.0;
513 if ( rate < 0.01 )
514 rate = 0.0;
515
516 std::string fraction_str = AGUIXUtils::formatStringToString( "%%.%df %%%%",
517 rate_precision );
518
519 snprintf( tstr, sizeof( tstr ), fraction_str.c_str(), rate * 100.0 );
520
521 tstr[ sizeof( tstr ) - 1 ] = '\0';
522 gsb->setText(tstr);
523 gsb->resize( w_max( (int)( sbw * rate ), 2 ), gsb->getHeight() );
524
525 newglob_percent = (int)( rate * 100.0 );
526 if ( newglob_percent != glob_percent ) {
527 glob_percent = newglob_percent;
528 tstr3 = (char*)_allocsafe( strlen( ( move == true ) ? catalog.getLocale( 299 ) : catalog.getLocale( 1249 ) ) +
529 strlen( " ( %)" ) +
530 A_BYTESFORNUMBER( glob_percent ) +
531 1 );
532 if ( ( glob_percent > 0 ) && ( glob_percent <= 100 ) ) {
533 sprintf( tstr3, "%s (%d %%)",
534 ( move == true ) ? catalog.getLocale( 299 ) : catalog.getLocale( 1249 ),
535 glob_percent );
536 } else {
537 sprintf( tstr3, "%s",
538 ( move == true ) ? catalog.getLocale( 299 ) : catalog.getLocale( 1249 ) );
539 }
540 window->setTitle( tstr3 );
541 _freesafe( tstr3 );
542 }
543
544 if(rate>0) {
545 drtime = difftime2 / rate;
546 drtime -= difftime2;
547 rtime = (long)( drtime / 1000000.0 );
548 } else
549 rtime = 700000; // no rate available => no real time calculatable
550
551 if ( lastrate_global != 0.0 ) {
552 double remaining_bytes = (double)bytes - (double)copied_bytes;
553 rtime_at_current_rate = remaining_bytes / lastrate_global;
554 rtime_at_current_rate++;
555 } else {
556 rtime_at_current_rate = 700000;
557 }
558
559 rtime++; // add a second because the last second will shown as 0:00
560 // and at least I don't like this
561 if ( rtime > 604800 ) // more then 7 days
562 sprintf( tstr, "--:--" );
563 else
564 sprintf( tstr, "%ld:%02ld", rtime / 60, rtime % 60 );
565
566 if ( rtime_at_current_rate <= 604800 &&
567 fabs( rtime - rtime_at_current_rate ) > 10.0 &&
568 fabs( rtime - rtime_at_current_rate ) / (double)rtime > 0.1 ) {
569 std::string alt_time_str = AGUIXUtils::formatStringToString( catalog.getLocale( 973 ),
570 tstr,
571 rtime_at_current_rate / 60,
572 rtime_at_current_rate % 60 );
573 timetext->setText( alt_time_str.c_str() );
574 } else {
575 timetext->setText(tstr);
576 }
577
578 tw = timetext->getX() + timetext->getWidth() + window->getBorderWidth();
579 if ( tw > melw ) {
580 melw = tw;
581 doresize = true;
582 }
583
584 update_globtext=false;
585 }
586 if(update_files2gotext==true) {
587 sprintf(tstr,"%ld",files-copied_files);
588 files2gotext->setText(tstr);
589 tw = files2gotext->getX() + files2gotext->getWidth() + window->getBorderWidth();
590 if ( tw > melw ) {
591 melw = tw;
592 doresize = true;
593 }
594
595 update_files2gotext=false;
596 }
597 if(update_dirs2gotext==true) {
598 sprintf(tstr,"%ld",dirs-copied_dirs);
599 dirs2gotext->setText(tstr);
600 tw = dirs2gotext->getX() + dirs2gotext->getWidth() + window->getBorderWidth();
601 if ( tw > melw ) {
602 melw = tw;
603 doresize = true;
604 }
605
606 update_dirs2gotext=false;
607 }
608 if ( doresize == true ) {
609 // only resize if window is smaller
610 if ( window->getWidth() < melw ) {
611 window->resize( melw, window->getHeight() );
612 }
613 // anyway the min size has changed so set it again
614 window->setMinSize( melw, bb4->getY() + bb4->getHeight() + 5 +cb->getHeight() + window->getBorderWidth() );
615 }
616
617 //window->redraw();
618 aguix->Flush();
619
620 if ( ! skip_message_handling ) {
621 /* update complete
622 now check for X-messages */
623 AGMessage *msg;
624 do {
625 msg=aguix->GetMessage( window );
626
627 returnvalue |= handleMessage( msg );
628
629 aguix->ReplyMessage(msg);
630 } while(msg!=NULL);
631 }
632
633 return returnvalue;
634 }
635
handleMessage(AGMessage * msg)636 int CopyOpWin::handleMessage( AGMessage *msg )
637 {
638 int returnvalue=0;
639
640 if(msg!=NULL) {
641 switch(msg->type) {
642 case AG_CLOSEWINDOW:
643 if ( msg->closewindow.window == window->getWindow() ) {
644 if ( m_finished ) {
645 returnvalue = 4;
646 } else {
647 returnvalue = 1;
648 }
649 }
650 break;
651 case AG_BUTTONCLICKED:
652 if ( msg->button.button == cb ) {
653 if ( m_finished ) {
654 returnvalue = 4;
655 } else {
656 returnvalue = 1;
657 }
658 } else if ( msg->button.button == m_detach_b ) {
659 returnvalue = 2;
660 }
661 break;
662 case AG_CHOOSECLICKED:
663 if ( msg->choose.button == m_keep_window_cb ) {
664 m_keep_window = m_keep_window_cb->getState();
665
666 Worker::getPersKVPStore().setIntValue( "copy-keep-window",
667 ( m_keep_window ? 2 : 1 ) );
668 }
669 break;
670 case AG_SIZECHANGED:
671 if ( msg->size.window == window->getWindow() ) {
672 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
673
674 bb1->resize( msg->size.neww - 2 * window->getBorderWidth(), bb1->getHeight() );
675 sbw = bb1->getWidth() - 2;
676 bb2->resize( msg->size.neww - 2 * window->getBorderWidth(), bb2->getHeight() );
677 bb3->resize( msg->size.neww - 2 * window->getBorderWidth(), bb3->getHeight() );
678 bb4->resize( msg->size.neww - 2 * window->getBorderWidth(), bb4->getHeight() );
679 cb->move( msg->size.neww -5 - cb->getWidth(),
680 msg->size.newh - window->getBorderWidth() - cb->getHeight() );
681
682 m_detach_b->move( 5,
683 msg->size.newh - window->getBorderWidth() - m_detach_b->getHeight() );
684 m_keep_window_cb->move( 5,
685 msg->size.newh - window->getBorderWidth() - m_keep_window_cb->getHeight() );
686
687 filenamespace[0] = msg->size.neww - window->getBorderWidth() - sourcetext->getX();
688 filenamespace[0] -= aguix->getTextWidth( catalog.getLocale( ( move == true ) ? 594 : 116 ) ) - 2 * aguix->getTextWidth( " " );
689 filenamespace[1] = msg->size.neww - window->getBorderWidth() - desttext->getX();
690 filenamespace[1] -= aguix->getTextWidth( catalog.getLocale( 117 ) ) - 2 * aguix->getTextWidth( " " );
691 update_sourcetext = true;
692 update_desttext = true;
693
694 // now gsb and fsb are not scaled for new width
695 // but next call of redraw they will so this shouldn't hurt anybody
696 // but a solution would be to first react for messages and then redraw
697
698 if ( m_finished ) {
699 double rate = 0.0;
700
701 if ( bytes_curfile > 0 ) {
702 rate = (double)copied_bytes_curfile / (double)bytes_curfile;
703 }
704
705 fsb->resize( w_max( (int)( sbw * rate ), 2 ), fsb->getHeight() );
706
707 if ( bytes > 0 ) {
708 rate = (double)copied_bytes / (double)bytes;
709 } else {
710 rate=0.0;
711 }
712
713 gsb->resize( w_max( (int)( sbw * rate ), 2 ), gsb->getHeight() );
714 }
715 }
716 break;
717 }
718 }
719
720 return returnvalue;
721 }
722
723 void
setmessage(const std::string & msg,int line)724 CopyOpWin::setmessage( const std::string &msg, int line )
725 {
726 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
727
728 switch(line) {
729 case 0:
730 source = msg;
731 ismessage[0] = true;
732 update_sourcetext = true;
733 break;
734 case 1:
735 dest = msg;
736 ismessage[1] = true;
737 update_desttext = true;
738 break;
739 }
740 }
741
742 void
dec_file_counter(unsigned long f)743 CopyOpWin::dec_file_counter(unsigned long f)
744 {
745 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
746
747 files-=f;
748 update_files2gotext=true;
749 }
750
751 void
dec_dir_counter(unsigned long d)752 CopyOpWin::dec_dir_counter(unsigned long d)
753 {
754 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
755
756 dirs-=d;
757 update_dirs2gotext=true;
758 }
759
760 void
dec_byte_counter(loff_t b)761 CopyOpWin::dec_byte_counter(loff_t b)
762 {
763 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
764
765 bytes-=b;
766 update_globtext=true;
767 }
768
769 void
stoptimer()770 CopyOpWin::stoptimer()
771 {
772 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
773
774 gettimeofday( &stoptime, NULL );
775 timer_stopped = true;
776 }
777
778 void
conttimer()779 CopyOpWin::conttimer()
780 {
781 struct timeval curtime;
782 long s, us;
783
784 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
785
786 if ( timer_stopped == false ) return;
787
788 gettimeofday( &curtime, NULL );
789
790 s = curtime.tv_sec - stoptime.tv_sec;
791 us = curtime.tv_usec - stoptime.tv_usec;
792 if ( us < 0 ) {
793 s--;
794 us += 1000000;
795 }
796
797 starttime.tv_sec += s;
798 starttime.tv_usec += us;
799 if ( starttime.tv_usec > 1000000 ) {
800 starttime.tv_sec++;
801 starttime.tv_usec -= 1000000;
802 }
803 filestarttime.tv_sec += s;
804 filestarttime.tv_usec += us;
805 if ( filestarttime.tv_usec > 1000000 ) {
806 filestarttime.tv_sec++;
807 filestarttime.tv_usec -= 1000000;
808 }
809
810 lasttime_global.tv_sec += s;
811 lasttime_global.tv_usec += us;
812 if ( lasttime_global.tv_usec > 1000000 ) {
813 lasttime_global.tv_sec++;
814 lasttime_global.tv_usec -= 1000000;
815 }
816 }
817
request_int(const char * title,const char * text,const char * buttons,Requester::request_flags_t flags)818 int CopyOpWin::request_int( const char *title,
819 const char *text,
820 const char *buttons,
821 Requester::request_flags_t flags )
822 {
823 if ( window != NULL ) {
824 return window->request( title, text, buttons, flags );
825 } else {
826 return Worker::getRequester()->request( title, text, buttons, flags );
827 }
828 }
829
string_request_int(const char * title,const char * lines,const char * default_str,const char * buttons,char ** return_str,Requester::request_flags_t flags)830 int CopyOpWin::string_request_int( const char *title,
831 const char *lines,
832 const char *default_str,
833 const char *buttons,
834 char **return_str,
835 Requester::request_flags_t flags )
836 {
837 if ( window != NULL ) {
838 return window->string_request( title, lines, default_str, buttons, return_str, flags );
839 } else {
840 return Worker::getRequester()->string_request( title, lines, default_str, buttons, return_str, flags );
841 }
842 }
843
file_skipped(loff_t byteSum,bool subCopied)844 void CopyOpWin::file_skipped( loff_t byteSum, bool subCopied )
845 {
846 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
847
848 if ( files > 0 ) files--;
849 if ( byteSum > 0 ) bytes -= byteSum;
850 if ( subCopied == true ) copied_bytes -= copied_bytes_curfile;
851 update_globtext = true;
852 update_files2gotext = true;
853 }
854
update_file_status()855 void CopyOpWin::update_file_status()
856 {
857 std::unique_lock< std::recursive_mutex > lck( m_status_update_lock );
858
859 if ( skipped_updates > 0 ) {
860 update_filetext = true;
861 update_globtext = true;
862 }
863 }
864
master_process_request()865 void CopyOpWin::master_process_request()
866 {
867 std::unique_lock<std::mutex> lck( m_request_lock );
868
869 if ( m_request ) {
870 process_request( *m_request );
871
872 std::unique_lock<std::mutex> lck( m_response_lock );
873
874 m_response = std::move( m_request );
875
876 m_response_cond.notify_one();
877 }
878 }
879
push_request(const BGCopyRequestMessage & msg)880 void CopyOpWin::push_request( const BGCopyRequestMessage &msg )
881 {
882 std::unique_lock<std::mutex> lck( m_request_lock );
883
884 m_request = std::unique_ptr< BGCopyRequestMessage >( new BGCopyRequestMessage( msg ) );
885 }
886
wait_for_response()887 BGCopyRequestMessage CopyOpWin::wait_for_response()
888 {
889 std::unique_lock<std::mutex> lck( m_response_lock );
890
891 while ( ! m_response ) {
892 m_response_cond.wait( lck );
893 }
894
895 BGCopyRequestMessage res = *m_response;
896
897 m_response.reset();
898
899 return res;
900 }
901
request(const std::string & title,const std::string & text,const std::string & buttons,Requester::request_flags_t flags)902 int CopyOpWin::request( const std::string &title,
903 const std::string &text,
904 const std::string &buttons,
905 Requester::request_flags_t flags )
906 {
907 BGCopyRequestMessage msg( title, text, buttons );
908
909 if ( std::this_thread::get_id() == m_master_thread_id ) {
910 process_request( msg );
911
912 return msg.getRes();
913 } else {
914 push_request( msg );
915
916 return wait_for_response().getRes();
917 }
918 }
919
string_request(const std::string & title,const std::string & lines,const std::string & default_str,const std::string & buttons,std::string & return_str,Requester::request_flags_t flags)920 int CopyOpWin::string_request( const std::string &title,
921 const std::string &lines,
922 const std::string &default_str,
923 const std::string &buttons,
924 std::string &return_str,
925 Requester::request_flags_t flags )
926 {
927 BGCopyRequestMessage msg( title, lines, default_str, buttons, flags );
928
929 if ( std::this_thread::get_id() == m_master_thread_id ) {
930 process_request( msg );
931
932 return_str = msg.getResultString();
933
934 return msg.getRes();
935 } else {
936 push_request( msg );
937
938 auto res = wait_for_response();
939
940 return_str = res.getResultString();
941
942 return res.getRes();
943 }
944 }
945
process_request(BGCopyRequestMessage & msg)946 void CopyOpWin::process_request( BGCopyRequestMessage &msg )
947 {
948 if ( msg.getType() == BGCopyRequestMessage::REGULAR_REQUEST ) {
949 msg.setRes( request_int( msg.getTitle().c_str(),
950 msg.getText().c_str(),
951 msg.getButtons().c_str() ) );
952 } else if ( msg.getType() == BGCopyRequestMessage::STRING_REQUEST ) {
953 char *result_string = NULL;
954 int res = string_request_int( msg.getTitle().c_str(),
955 msg.getText().c_str(),
956 msg.getDefaultString().c_str(),
957 msg.getButtons().c_str(),
958 &result_string,
959 msg.getFlags() );
960
961 if ( result_string ) {
962 msg.setResultString( result_string );
963
964 _freesafe( result_string );
965 }
966 msg.setRes( res );
967 } else {
968 throw 1;
969 }
970 }
971
hide_detach_button()972 void CopyOpWin::hide_detach_button()
973 {
974 m_detach_b->hide();
975
976 m_keep_window_cb->show();
977
978 m_detached = true;
979 }
980
getKeepWindow() const981 bool CopyOpWin::getKeepWindow() const
982 {
983 if ( ! m_detached ) return false;
984
985 return m_keep_window;
986 }
987
setFinished()988 void CopyOpWin::setFinished()
989 {
990 m_finished = true;
991
992 if ( getKeepWindow() ) {
993 cb->setText( 0, catalog.getLocale( 633 ) );
994
995 int tw = cb->getMaximumWidth();
996
997 if ( tw > cb->getWidth() ) {
998 cb->resize( tw, cb->getHeight() );
999 cb->move( window->getWidth() - 5 - cb->getWidth(), cb->getY() );
1000 }
1001
1002 setmessage( catalog.getLocale( 1046 ), 0 );
1003 setmessage( "", 1 );
1004
1005 redraw();
1006 }
1007 }
1008