/* volumemanagerui.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2009-2023 Ralf Hoffmann.
 * You can contact me at: ralf@boomerangsworld.de
 *   or http://www.boomerangsworld.de/worker
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "volumemanagerui.hh"
#include "aguix/aguix.h"
#include "aguix/awindow.h"
#include "aguix/text.h"
#include "aguix/fieldlistview.h"
#include "aguix/button.h"
#include "aguix/solidbutton.h"
#include <algorithm>
#include "hw_volume.hh"
#include "hw_volume_manager.hh"
#include <functional>
#include "nwc_path.hh"
#include "worker.h"
#include "pers_string_list.hh"
#include "aguix/textview.h"
#include "aguix/popupmenu.hh"
#include "worker_locale.h"

VolumeManagerUI::VolumeManagerUI( AGUIX &aguix, HWVolumeManager &hwman ) : m_aguix( aguix ),
                                                                           m_hwman( hwman ),
                                                                           m_eject_menu( NULL ),
                                                                           m_menu_command( VOLMANUI_MENU_EJECT )
{
    m_status_info = std::make_shared< TextStorageString >( "",
                                                           RefCount<AWidth>( new AFontWidth( &aguix,
                                                                                             NULL ) ) );
    std::string cfgfile = getHiddenDevicesFile();
    m_hide_entries = std::unique_ptr< PersistentStringList >( new PersistentStringList( cfgfile ) );

    m_win = std::unique_ptr<AWindow>( new AWindow( &m_aguix,
                                                   10, 10,
                                                   500, 400,
                                                   catalog.getLocale( 871 ),
                                                   AWindow::AWINDOW_DIALOG ) );
    m_win->create();

    AContainer *cont0 = m_win->setContainer( new AContainer( m_win.get(), 1, 4 ), true );
    cont0->setMaxSpace( 5 );
    
    cont0->add( new Text( &m_aguix, 0, 0, catalog.getLocale( 872 ) ),
                0, 0, AContainer::CO_INCW );
    m_cont2 = cont0->add( new AContainer( m_win.get(), 2, 1 ), 0, 1 );
    m_cont2->setBorderWidth( 0 );
    m_cont2->setMinSpace( 5 );
    m_cont2->setMaxSpace( 5 );
    
    m_lv = dynamic_cast<FieldListView*>( m_cont2->add( new FieldListView( &m_aguix, 0, 0, 
                                                                          200, 200, 0 ),
                                                       0, 0, AContainer::CO_MIN ) );
    m_lv->setNrOfFields( 5 );
    m_lv->setShowHeader( true );
    m_lv->setFieldText( 0, catalog.getLocale( 873 ) );
    m_lv->setFieldText( 1, catalog.getLocale( 874 ) );
    m_lv->setFieldText( 2, catalog.getLocale( 875 ) );
    m_lv->setFieldText( 3, catalog.getLocale( 912 ) );
    m_lv->setFieldText( 4, catalog.getLocale( 913 ) );
    m_lv->setHBarState( 2 );
    m_lv->setVBarState( 2 );
    m_lv->setAcceptFocus( true );
    m_lv->setDisplayFocus( true );
    m_lv->setGlobalFieldSpace( 5 );

    AContainer *cont4 = m_cont2->add( new AContainer( m_win.get(), 1, 7 ), 1, 0 );
    cont4->setBorderWidth( 0 );
    cont4->setMinSpace( 5 );
    cont4->setMaxSpace( 5 );
    
    m_mountb = dynamic_cast<Button*>( cont4->add( new Button( &m_aguix, 0, 0, catalog.getLocale( 885 ), 0 ),
                                                  0, 0, AContainer::CO_FIX ) );
    m_unmountb = dynamic_cast<Button*>( cont4->add( new Button( &m_aguix, 0, 0, catalog.getLocale( 886 ), 0 ),
                                                     0, 1, AContainer::CO_FIX ) );
    m_ejectb = dynamic_cast<Button*>( cont4->add( new Button( &m_aguix, 0, 0,
                                                              catalog.getLocale( 965 ),
                                                              catalog.getLocale( 929 ),
                                                              0 ),
                                                  0, 2, AContainer::CO_FIX ) );
    m_closetrayb = dynamic_cast<Button*>( cont4->add( new Button( &m_aguix, 0, 0,
                                                                  catalog.getLocale( 966 ),
                                                                  catalog.getLocale( 930 ),
                                                                  0 ),
						      0, 3, AContainer::CO_FIX ) );
    m_hideb = dynamic_cast<Button*>( cont4->add( new Button( &m_aguix,
                                                             0, 0,
                                                             catalog.getLocale( 887 ),
                                                             catalog.getLocale( 888 ),
                                                             0 ),
                                                 0, 4, AContainer::CO_FIX ) );

    bool dbus_disconnected = m_hwman.systemConnectionFailed();

    m_updateb = dynamic_cast<Button*>( cont4->add( new Button( &m_aguix, 0, 0, dbus_disconnected ? catalog.getLocale( 1527 ) : catalog.getLocale( 922 ), 0 ),
						   0, 5, AContainer::CO_FIX ) );
    AContainer *cont7 = cont0->add( new AContainer( m_win.get(), 2, 1 ), 0, 2 );
    cont7->setBorderWidth( 0 );
    cont7->setMinSpace( 5 );
    cont7->setMaxSpace( 5 );
    
    cont7->add( new Text( &m_aguix, 0, 0, catalog.getLocale( 876 ) ),
                0, 0, AContainer::CO_FIX );

    if ( dbus_disconnected ) {
        m_status_info->setContent( catalog.getLocale( 1528 ) );
    }
    
    m_status_tv = new TextView( &m_aguix, 0, 0, 100, 50, "", m_status_info );
    cont7->add( m_status_tv, 1, 0, AContainer::CO_INCW );
    m_status_tv->create();
    m_status_tv->show();
    m_status_tv->setLineWrap( true );

    TextView::ColorDef tv_cd = m_status_tv->getColors();
    tv_cd.setBackground( 0 );
    tv_cd.setTextColor( 1 );
    m_status_tv->setColors( tv_cd );

    AContainer *cont10 = cont0->add( new AContainer( m_win.get(), 2, 1 ), 0, 3 );
    cont10->setBorderWidth( 0 );
    cont10->setMinSpace( 5 );
    cont10->setMaxSpace( -1 );
    
    m_okb = dynamic_cast<Button*>( cont10->add( new Button( &m_aguix, 0, 0,
                                                            catalog.getLocale( 877 ),
                                                            0 ),
                                                0, 0, AContainer::CO_FIX ) );
    m_closeb = dynamic_cast<Button*>( cont10->add( new Button( &m_aguix, 0, 0,
                                                               catalog.getLocale( 633 ),
                                                               0 ),
                                                   1, 0, AContainer::CO_FIX ) );
   
    m_win->contMaximize( true );
    m_win->setDoTabCycling( true );
}

VolumeManagerUI::~VolumeManagerUI()
{
    if ( m_eject_menu != NULL ) {
	delete m_eject_menu;
    }
}

int VolumeManagerUI::mainLoop()
{
    updateLV();

    maximizeWin();
    m_win->show();

    m_lv->takeFocus();

    AGMessage *msg;
    int endmode = 0;

    {
        std::string start_entry = NWC::Path::join( m_dirname,
                                                   m_basename );
        int best_hit = -1;
        std::string::size_type last_len = 0;
        for ( int row = 0;; row++ ) {
            if ( m_lv->isValidRow( row ) == false ) break;
            std::string d = m_lv->getText( row, 2 );
            if ( ! d.empty() ) {
                if ( start_entry.compare( 0, d.length(), d ) == 0 ) {
                    if ( d.length() > last_len ) {
                        best_hit = row;
                        last_len = d.length();
                    }
                }
            }

            d = m_lv->getText( row, 0 );
            if ( ! d.empty() ) {
                if ( start_entry.compare( 0, d.length(), d ) == 0 ) {
                    if ( d.length() > last_len ) {
                        best_hit = row;
                        last_len = d.length();
                    }
                }
            }
        }

        if ( best_hit >= 0 ) {
            m_lv->setActiveRow( best_hit );
            m_lv->showActive();
        }
    }

    for ( ; endmode == 0; ) {
        msg = m_aguix.WaitMessage( NULL );
        if ( msg != NULL ) {
            switch ( msg->type ) {
              case AG_CLOSEWINDOW:
                  endmode = -1;
                  break;
              case AG_BUTTONCLICKED:
                  if ( msg->button.button == m_okb ) {
                      endmode = 1;
                  } else if ( msg->button.button == m_closeb ) {
                      endmode = -1;
                  } else if ( msg->button.button == m_mountb ) {
                      mountRow( m_lv->getActiveRow() );
                  } else if ( msg->button.button == m_unmountb ) {
                      unmountRow( m_lv->getActiveRow() );
                  } else if ( msg->button.button == m_ejectb ) {
                      if ( msg->button.state == 2 ) {
                          buildEjectMenu( VOLMANUI_MENU_EJECT );
                      } else {
                          ejectOrCloseTray( VOLMANUI_MENU_EJECT );
                      }
                  } else if ( msg->button.button == m_closetrayb ) {
                      if ( msg->button.state == 2 ) {
                          buildEjectMenu( VOLMANUI_MENU_CLOSETRAY );
                      } else {
                          ejectOrCloseTray( VOLMANUI_MENU_CLOSETRAY );
                      }
                  } else if ( msg->button.button == m_updateb ) {
                      if ( m_hwman.systemConnectionFailed() ) {
                          if ( m_hwman.retrySystemConnection() == 0 ) {
                              m_status_info->setContent( catalog.getLocale( 1525 ) );
                              m_status_tv->textStorageChanged();
                              m_updateb->setText( 0, catalog.getLocale( 922 ) );
                              updateLV();
                              maximizeWin();
                              m_aguix.Flush();
                          } else {
                              m_status_info->setContent( catalog.getLocale( 1526 ) );
                              m_status_tv->textStorageChanged();
                              m_aguix.Flush();
                          }
                      } else {
                          updateLV();
                          maximizeWin();
                      }
                  } else if ( msg->button.button == m_hideb ) {
                      if ( msg->button.state == 2 ) {
                          editHideList();
                      } else {
                          hide( m_lv->getActiveRow() );
                      }
                  }
                  break;
              case AG_KEYPRESSED:
                  if ( msg->key.key == XK_Return ) {
                      endmode = 1;
                  } else if ( msg->key.key == XK_Escape ) {
                      endmode = -1;
                  } else if ( msg->key.key == XK_m ) {
                      mountRow( m_lv->getActiveRow() );
                  } else if ( msg->key.key == XK_u ) {
                      unmountRow( m_lv->getActiveRow() );
                  } else if ( msg->key.key == XK_o ) {
                      ejectOrCloseTray( VOLMANUI_MENU_EJECT );
                  } else if ( msg->key.key == XK_c ) {
                      ejectOrCloseTray( VOLMANUI_MENU_CLOSETRAY );
                  }
                  break;
              case AG_FIELDLV_DOUBLECLICK:
                  if ( msg->fieldlv.lv == m_lv ) {
                      // double click in lv, actual element is unimportant here
                      endmode = 1;
                  }
                  break;
#if 0
                case AG_FIELDLV_HEADERCLICKED:
                    if ( ( msg->fieldlv.lv == m_lv ) &&
                         ( msg->fieldlv.button == Button1 ) ) {
                        // store current active entry
                        BookmarkDBEntry active_entry = getActiveEntry( current_cat );

                        // switch sort mode
                        switch ( msg->fieldlv.row ) {
                            case 0:
                                m_filtered_data->toggleSortMode( BookmarkDBFilter::SORT_BY_NAME );
                                showData( current_cat );
                                break;
                            case 2:
                                m_filtered_data->toggleSortMode( BookmarkDBFilter::SORT_BY_ALIAS );
                                showData( current_cat );
                                break;
                            case 4:
                                m_filtered_data->toggleSortMode( BookmarkDBFilter::SORT_BY_CATEGORY );
                                showData( current_cat );
                                break;
                            default:
                                break;
                        }

                        // find previously stored entry and activate it
                        std::list<BookmarkDBEntry> e = m_filtered_data->getEntries( current_cat );
                        int row = 0;
                        for ( std::list<BookmarkDBEntry>::iterator it1 = e.begin();
                              it1 != e.end();
                              it1++, row++ ) {
                            if ( *it1 == active_entry ) {
                                m_lv->setActiveRow( row );
                                break;
                            }
                        }
                    }
                    break;
#endif
		case AG_POPUPMENU_CLICKED:
		    if ( msg->popupmenu.menu == m_eject_menu ) {
			handlePopupMsg( msg );
		    }
		    break;
            }
            m_aguix.ReplyMessage( msg );
        }
    }

    if ( endmode == 1 ) {
        int row = m_lv->getActiveRow();
        if ( m_lv->isValidRow( row ) == true ) {
            m_dir_to_enter = m_row_to_volume[row].getMountPoint();
        }
    }

    m_win->hide();
    
    return endmode;
}

std::string VolumeManagerUI::getDirectoryToEnter() const
{
    return m_dir_to_enter;
}

void VolumeManagerUI::maximizeWin()
{
    int old_w = m_lv->getWidth();
    int old_h = m_lv->getHeight();

    int new_w = m_lv->getMaximumWidth();
    int new_h = m_lv->getMaximumHeight();

    if ( new_w <= old_w &&
         new_h <= old_h ) {
        m_cont2->rearrange();
    } else {
        int my_w = new_w + 10;
        int my_h = new_h + 10;

        if ( my_w < 400 ) my_w = 400;
        if ( my_h < 300 ) my_h = 300;

        int rx, ry, rw, rh;

        m_aguix.getLargestDimensionOfCurrentScreen( &rx, &ry,
                                                    &rw, &rh );

        int mw = rw * 80 / 100;
        int mh = rh * 80 / 100;
        m_cont2->resize( mw, mh );
        m_cont2->rearrange();

        if ( my_w < new_w ) {
            m_cont2->setMinWidth( my_w, 0, 0 );
        } else {
            m_cont2->setMinWidth( new_w, 0, 0 );
        }
        if ( my_h < new_h ) {
            m_cont2->setMinHeight( my_h, 0, 0 );
        } else {
            m_cont2->setMinHeight( new_h, 0, 0 );
        }
        m_win->contMaximize( true );
    }
}

static bool volumeInList( const HWVolume &vol,
                          const std::list<HWVolume> &list )
{
    if ( std::find( list.begin(), list.end(), vol ) != list.end() ) return true;
    return false;
}

void VolumeManagerUI::updateLV()
{
    std::list<HWVolume> l = m_hwman.getVolumes();
    std::list<HWVolume> nl = m_hwman.getNewVolumes( false );

    int cur_row = m_lv->getActiveRow();
    std::string cur_dev, cur_smp;
    if ( m_lv->isValidRow( cur_row ) ) {
        cur_dev = m_lv->getText( cur_row, 1 );
        cur_smp = m_lv->getText( cur_row, 0 );
    }
    
    l.sort( []( auto &lhs, auto &rhs ) {
                return lhs.getDevice() < rhs.getDevice();
            });

    m_lv->setSize( 0 );
    m_row_to_volume.clear();
    
    for ( std::list<HWVolume>::const_iterator it1 = l.begin();
          it1 != l.end();
          it1++ ) {
        if ( ! m_hide_entries->contains( it1->getDevice() ) ) {
            int row = m_lv->addRow();
            m_lv->setText( row, 0, it1->getSupposedMountPoint() );
            m_lv->setText( row, 1, it1->getDevice() );
            m_lv->setText( row, 2, it1->getMountPoint() );
            m_lv->setText( row, 3, it1->getLabel() );

            if ( it1->getSize() > 0 ) {
                std::string ssize;
                
                ssize = AGUIXUtils::bytes_to_human_readable_f( it1->getSize() );
                m_lv->setText( row, 4, ssize );
            }

            m_lv->setPreColors( row, FieldListView::PRECOLOR_ONLYACTIVE );
            m_row_to_volume[row] = *it1;

            if ( volumeInList( *it1, nl ) ) {
                m_lv->setVisMarkQ( row, true );
            }

            if ( cur_dev.empty() == false &&
                 it1->getDevice() == cur_dev &&
                 it1->getSupposedMountPoint() == cur_smp ) {
                m_lv->setActiveRow( row );
            }
        }
    }
    m_lv->showActive();
    m_lv->redraw();
}

void VolumeManagerUI::mountRow( int row )
{
    if ( m_lv->isValidRow( row ) ) {
        HWVolume vol = m_row_to_volume[row];

        m_win->setCursor( AGUIX::WAIT_CURSOR );
        m_status_info->setContent( catalog.getLocale( 878 ) );
        m_status_tv->textStorageChanged();
        m_aguix.Flush();

        std::string error;
        
        if ( m_hwman.mount( vol, error ) == 0 ) {
            m_status_info->setContent( catalog.getLocale( 879 ) );
        } else {
            m_status_info->setContent( error );
        }
        m_status_tv->textStorageChanged();

        m_win->unsetCursor();

        updateLV();
        maximizeWin();
    }
}

void VolumeManagerUI::unmountRow( int row )
{
    if ( m_lv->isValidRow( row ) ) {
        HWVolume vol = m_row_to_volume[row];

        m_win->setCursor( AGUIX::WAIT_CURSOR );
        m_status_info->setContent( catalog.getLocale( 880 ) );
        m_status_tv->textStorageChanged();
        m_aguix.Flush();

        std::string error;

        if ( m_hwman.umount( vol, error ) == 0 ) {
            m_status_info->setContent( catalog.getLocale( 881 ) );
        } else {
            m_status_info->setContent( error );
        }
        m_status_tv->textStorageChanged();

        m_win->unsetCursor();

        updateLV();
        maximizeWin();
    }
}

void VolumeManagerUI::setCurrentDirname( const std::string &dirname )
{
    m_dirname = dirname;
}

void VolumeManagerUI::setCurrentBasename( const std::string &basename )
{
    m_basename = basename;
}

void VolumeManagerUI::hide( int row )
{
    if ( m_lv->isValidRow( row ) ) {
        HWVolume vol = m_row_to_volume[row];
        m_hide_entries->pushEntry( vol.getDevice() );
        updateLV();
    }
}

void VolumeManagerUI::editHideList()
{
    AWindow *win = new AWindow( &m_aguix,
                                0, 0,
                                500, 400,
                                catalog.getLocale( 882 ),
                                AWindow::AWINDOW_DIALOG );
    win->create();
    
    AContainer *cont0 = win->setContainer( new AContainer( win, 1, 4 ), true );
    cont0->setMaxSpace( 5 );
    
    cont0->add( new Text( &m_aguix, 0, 0, catalog.getLocale( 883 ) ),
                0, 0, AContainer::CO_INCW );
    
    FieldListView *lv = dynamic_cast<FieldListView*>( cont0->add( new FieldListView( &m_aguix, 0, 0, 
                                                                                     200, 200, 0 ),
                                                                  0, 1, AContainer::CO_MIN ) );
    lv->setHBarState( 2 );
    lv->setVBarState( 2 );
    lv->setAcceptFocus( true );
    lv->setDisplayFocus( true );

    {
        std::list< std::string > list = m_hide_entries->getList();
        for ( std::list< std::string >::const_iterator it1 = list.begin();
              it1 != list.end();
              it1++ ) {
            int row = lv->addRow();
            lv->setText( row, 0, *it1 );
        }
    }

    Button *remove_b = dynamic_cast<Button*>( cont0->add( new Button( &m_aguix, 0, 0, catalog.getLocale( 884 ), 0 ),
                                                          0, 2, AContainer::CO_INCW ) );
    AContainer *cont1 = cont0->add( new AContainer( win, 2, 1 ), 0, 3 );
    cont1->setBorderWidth( 0 );
    cont1->setMinSpace( 5 );
    cont1->setMaxSpace( -1 );
    
    Button *okb = dynamic_cast<Button*>( cont1->add( new Button( &m_aguix, 0, 0,
                                                                 catalog.getLocale( 11 ),
                                                                 0 ),
                                                     0, 0, AContainer::CO_FIX ) );
    Button *cancelb = dynamic_cast<Button*>( cont1->add( new Button( &m_aguix, 0, 0,
                                                                     catalog.getLocale( 8 ),
                                                                     0 ),
                                                         1, 0, AContainer::CO_FIX ) );
    
    win->contMaximize( true );
    win->setDoTabCycling( true );
    win->show();

    AGMessage *msg;
    int endmode = 0;

    for ( ; endmode == 0; ) {
        msg = m_aguix.WaitMessage( NULL );
        if ( msg != NULL ) {
            switch ( msg->type ) {
                case AG_CLOSEWINDOW:
                    endmode = -1;
                    break;
                case AG_BUTTONCLICKED:
                    if ( msg->button.button == okb ) {
                        endmode = 1;
                    } else if ( msg->button.button == cancelb ) {
                        endmode = -1;
                    } else if ( msg->button.button == remove_b ) {
                        for ( int row = 0; row < lv->getElements(); ) {
                            if ( lv->getSelect( row ) == true ) {
                                lv->deleteRow( row );
                            } else {
                                row++;
                            }
                        }
                        lv->redraw();
                    }
                    break;
                default:
                    break;
            }
            m_aguix.ReplyMessage( msg );
        }
    }
    
    if ( endmode == 1 ) {
        std::set< std::string > devices_to_use;

        for ( int row = 0; row < lv->getElements(); row++ ) {
            devices_to_use.insert( lv->getText( row, 0 ) );
        }

        std::list< std::string > list = m_hide_entries->getList();
        for ( std::list< std::string >::const_iterator it1 = list.begin();
              it1 != list.end();
              it1++ ) {
            if ( devices_to_use.count( *it1 ) == 0 ) {
                m_hide_entries->removeEntry( *it1 );
            }
        }
    }

    delete win;

    updateLV();
}

std::string VolumeManagerUI::getHiddenDevicesFile()
{
    std::string cfgfile = Worker::getWorkerConfigDir();
#ifdef DEBUG
    cfgfile = NWC::Path::join( cfgfile, "volman_ignore_devices2" );
#else
    cfgfile = NWC::Path::join( cfgfile, "volman_ignore_devices" );
#endif
    return cfgfile;
}

std::list< std::string > VolumeManagerUI::getListOfHiddenDevices()
{
    PersistentStringList psl( getHiddenDevicesFile() );
    return psl.getList();
}

void VolumeManagerUI::buildEjectMenu( const menu_command_t &menu_command )
{
    if ( m_eject_menu != NULL ) {
	delete m_eject_menu;
	m_eject_menu = NULL;
    }

    m_menu_command = menu_command;
    std::list< HWVolume > l = m_hwman.getEjectableDevices();
    l.sort( []( auto &lhs, auto &rhs ) {
                return lhs.getDevice() < rhs.getDevice();
            });

    m_ejectable_devices.clear();
    for ( std::list< HWVolume >::iterator it1 = l.begin();
	  it1 != l.end();
	  it1++ ) {
	if ( ! m_hide_entries->contains( it1->getDevice() ) ) {
	    m_ejectable_devices.push_back( *it1 );
	}
    }

    if ( m_ejectable_devices.size() < 1 ) {
        m_status_info->setContent( catalog.getLocale( 934 ) );
        m_status_tv->textStorageChanged();
        m_aguix.Flush();
        return;
    }

    if ( m_ejectable_devices.size() == 1 ) {
	// only one device, directly eject/closetray
	if ( m_menu_command == VOLMANUI_MENU_EJECT ) {
	    eject( *( m_ejectable_devices.begin() ) );
	} else {
	    closeTray( *( m_ejectable_devices.begin() ) );
	}
	return;
    }

    std::list<PopUpMenu::PopUpEntry> m1;
    PopUpMenu::PopUpEntry e1;
    if ( m_menu_command == VOLMANUI_MENU_EJECT ) {
	e1.name = catalog.getLocale( 920 );
    } else {
	e1.name = catalog.getLocale( 921 );
    }
    e1.type = PopUpMenu::HEADER;
    m1.push_back( e1 );
    e1.type = PopUpMenu::HLINE;
    m1.push_back( e1 );

    int pos = 0;
    for ( std::list< HWVolume >::iterator it1 = m_ejectable_devices.begin();
	  it1 != m_ejectable_devices.end();
	  it1++, pos++ ) {
	e1.type = PopUpMenu::NORMAL;

        std::string descr = m_hwman.getDescription( *it1 );

        if ( ! descr.empty() ) {
            descr += " (";
            descr += it1->getDevice();
            descr += ")";
        } else {
            descr = it1->getDevice();
        }

	e1.name = descr;
	e1.id = pos;
	m1.push_back( e1 );
    }

    m_eject_menu = new PopUpMenu( &m_aguix, m1 );
    m_eject_menu->create();
    m_eject_menu->show();
}

void VolumeManagerUI::closeEjectMenu()
{
    if ( m_eject_menu != NULL ) {
	delete m_eject_menu;
	m_eject_menu = NULL;
    }
}

void VolumeManagerUI::handlePopupMsg( AGMessage *msg )
{
    if ( msg->popupmenu.menu != m_eject_menu ) return;

    int pos = msg->popupmenu.clicked_entry_id;
    
    if ( pos >= 0 && pos < (int)m_ejectable_devices.size() ) {
	std::list< HWVolume >::iterator it1 = m_ejectable_devices.begin();

	while ( pos > 0 ) {
	    if ( it1 == m_ejectable_devices.end() ) {
		break;
	    }

	    it1++;
	    pos--;
	}

	if ( it1 != m_ejectable_devices.end() ) {
	    if ( m_menu_command == VOLMANUI_MENU_EJECT ) {
		eject( *it1 );
	    } else {
		closeTray( *it1 );
	    }
	}
    }
}

void VolumeManagerUI::eject( HWVolume &vol )
{
    m_win->setCursor( AGUIX::WAIT_CURSOR );
    m_status_info->setContent( catalog.getLocale( 918 ) );
    m_status_tv->textStorageChanged();
    m_aguix.Flush();
    
    std::string error;
    
    if ( m_hwman.eject( vol, error ) == 0 ) {
        m_status_info->setContent( catalog.getLocale( 919 ) );
    } else {
        m_status_info->setContent( error );
    }
    m_status_tv->textStorageChanged();
    
    m_win->unsetCursor();

    updateLV();
    maximizeWin();

    m_last_device = vol.getDevice();
}

void VolumeManagerUI::closeTray( HWVolume &vol )
{
    m_win->setCursor( AGUIX::WAIT_CURSOR );
    m_status_info->setContent( catalog.getLocale( 916 ) );
    m_status_tv->textStorageChanged();
    m_aguix.Flush();
    
    std::string error;
    
    if ( m_hwman.closeTray( vol, error ) == 0 ) {
        m_status_info->setContent( catalog.getLocale( 917 ) );
    } else {
        m_status_info->setContent( error );
    }
    m_status_tv->textStorageChanged();
    
    m_win->unsetCursor();

    updateLV();
    maximizeWin();

    m_last_device = vol.getDevice();
}

void VolumeManagerUI::ejectOrCloseTray( const menu_command_t &menu_command )
{
    std::list< HWVolume > l = m_hwman.getEjectableDevices();
    std::string dev;

    if ( m_lv->isValidRow( m_lv->getActiveRow() ) ) {
        dev = m_lv->getText( m_lv->getActiveRow(), 1 );
    } else {
        dev = m_last_device;
    }

    std::list< HWVolume >::iterator it1 = l.end();

    if ( ! dev.empty() ) {
        for ( it1 = l.begin();
              it1 != l.end();
              it1++ ) {
	    if ( ! m_hide_entries->contains( it1->getDevice() ) ) {
		if ( it1->getDevice() == dev ) break;
	    }
        }
    }

    if ( it1 == l.end() &&
         ! m_last_device.empty() ) {
        dev = m_last_device;

        for ( it1 = l.begin();
              it1 != l.end();
              it1++ ) {
            if ( it1->getDevice() == dev ) break;
        }
    }

    if ( it1 != l.end() ) {
        if ( menu_command == VOLMANUI_MENU_EJECT ) {
            eject( *it1 );
        } else {
            closeTray( *it1 );
        }
    } else {
        if ( menu_command == VOLMANUI_MENU_EJECT ) {
            m_status_info->setContent( catalog.getLocale( 931 ) );
        } else {
            m_status_info->setContent( catalog.getLocale( 932 ) );
        }
        m_status_tv->textStorageChanged();
        buildEjectMenu( menu_command );
    }
}
