/***************************************************************************
    smb4tdeconfigdialog  -  The configuration dialog of Smb4K
                             -------------------
    begin                : Sa Apr 14 2007
    copyright            : (C) 2007 by Alexander Reinholdt
    email                : dustpuppy@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *   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 Street, Fifth Floor, Boston,   *
 *   MA  02110-1301 USA                                                    *
 ***************************************************************************/

// TQt includes
#include <tqradiobutton.h>
#include <tqcheckbox.h>

// KDE includes
#include <tdelistview.h>
#include <klineedit.h>
#include <kpushbutton.h>
#include <tdemessagebox.h>
#include <kurlrequester.h>

// system specific includes
#include <unistd.h>
#include <sys/types.h>

// application specific includes
#include "smb4tdeconfigdialog.h"
#include "smb4kuserinterfaceoptions.h"
#include "smb4knetworkoptions.h"
#include "smb4kshareoptions.h"
#include "smb4kauthoptions.h"
#include "smb4ksuperuseroptions.h"
#include "smb4ksambaoptions.h"
#include "smb4tdersyncoptions.h"
#include "../core/smb4ksettings.h"
#include "../core/smb4tdeglobal.h"
#include "../core/smb4ksambaoptionsinfo.h"
#include "../core/smb4ksambaoptionshandler.h"
#include "../core/smb4kcore.h"
#include "../core/smb4kauthinfo.h"
#include "../core/smb4kpasswordhandler.h"

using namespace Smb4TDEGlobal;

TDEInstance *Smb4TDEConfigDialogFactory::m_instance = 0L;
TDEAboutData *Smb4TDEConfigDialogFactory::m_about = 0L;

// Variables we need to determine if super user entries
// have to be written to /etc/sudoers or /etc/super.tab
bool use_sudo = false;
bool use_super = false;
#ifdef __linux__
bool force_unmount = false;
#endif
bool always_use_su = false;

// Use this variable to determine if the dialog should be
// closed after Smb4KFileIO::finished() was emitted.
bool close_dialog = false;


Smb4TDEConfigDialog::Smb4TDEConfigDialog( Smb4KSettings *settings, TQWidget *parent, const char *name )
: TDEConfigDialog( parent, name, settings )
{
  // FIXME: I guess, normally we would not need to close destructively,
  // but at the moment there are issues with the KURLRequester in file
  // mode. To work around those, we are closing the dialog destructively.
  // Maybe we can remove this if we moved to KDE4.
  setWFlags( TQt::WDestructiveClose );

  // Add the pages:
  Smb4KUserInterfaceOptions *interface_options = new Smb4KUserInterfaceOptions( this, "UserInterfaceOptions" );
  Smb4KNetworkOptions* network_options =         new Smb4KNetworkOptions( this, "NetworkOptions" );
  Smb4KShareOptions *share_options=              new Smb4KShareOptions( this, "ShareOptions" );
  Smb4KAuthOptions *auth_options =               new Smb4KAuthOptions( this, "AuthenticationOptions" );
  Smb4KSambaOptions *samba_options =             new Smb4KSambaOptions( this, "SambaOptions" );
  Smb4KRsyncOptions *rsync_options =             new Smb4KRsyncOptions( this, "SynchronizationOptions" );
  Smb4KSuperUserOptions *super_user_options =    new Smb4KSuperUserOptions( this, "SuperUserOptions" );

  // Disable widgets if the respective programs are not installed.
  if ( Smb4KSettings::rsync().isEmpty() )
  {
    rsync_options->setEnabled( false );
  }

  if ( Smb4KSettings::sudo().isEmpty() && Smb4KSettings::super().isEmpty() )
  {
    super_user_options->setEnabled( false );
  }
  else
  {
    // The search for the programs and all related actions have been
    // done by the core. We only need to disable widgets here.
    if ( Smb4KSettings::sudo().isEmpty() )
    {
      TQRadioButton *sudo = static_cast<TQRadioButton *>( super_user_options->child( "SudoButton", "TQRadioButton", true ) );

      if ( sudo )
      {
        sudo->setEnabled( false );
      }
    }
    else if ( Smb4KSettings::super().isEmpty() )
    {
      TQRadioButton *super = static_cast<TQRadioButton *>( super_user_options->child( "SuperButton", "TQRadioButton", true ) );

      if ( super )
      {
        super->setEnabled( false );
      }
    }
    else
    {
      // Do nothing
    }
  }

  // There are a few settings we need to the initial values of.
  // Initialize them here:
  switch ( Smb4KSettings::superUserProgram() )
  {
    case Smb4KSettings::EnumSuperUserProgram::Sudo:
    {
      use_sudo = true;

      break;
    }
    case Smb4KSettings::EnumSuperUserProgram::Super:
    {
      use_super = true;

      break;
    }
    default:
    {
      break;
    }
  }


#ifdef __linux__
  force_unmount = Smb4KSettings::useForceUnmount();
#endif
  always_use_su = Smb4KSettings::alwaysUseSuperUser();

  // Now add the pages to the configuration dialog
  addPage( interface_options, i18n( "User Interface" ), "view_choose" );
  addPage( network_options, i18n( "Network" ), "network" );
  addPage( share_options, i18n( "Shares" ), "drive-harddisk-mounted" );
  addPage( auth_options, i18n( "Authentication" ), "identity" );
  addPage( samba_options, i18n( "Samba" ), "samba" );
  addPage( rsync_options, i18n( "Synchronization" ), "go-bottom" );
  addPage( super_user_options, i18n( "Super User" ), "penguin" );

  // Stuff that's not managed by TDEConfig XT is loaded by
  // Smb4TDEConfigDialog::showEvent()!

  // Resize the dialog
  setInitialSize( configDialogSize( *(Smb4KSettings::self()->config()), "ConfigDialog" ) );

  // Connections
  connect( samba_options,       TQ_SIGNAL( customSettingsChanged() ),
           this,                TQ_SLOT( slotCustomSambaSettingsChanged() ) );

  connect( super_user_options,  TQ_SIGNAL( removeEntries() ),
           this,                TQ_SLOT( slotRemoveSuperUserEntries() ) );

  connect( Smb4KCore::fileIO(), TQ_SIGNAL( failed() ),
           this,                TQ_SLOT( slotReceivedFileIOFailed() ) );

  connect( Smb4KCore::fileIO(), TQ_SIGNAL( finished() ),
           this,                TQ_SLOT( slotReceivedFileIOFinished() ) );
}


Smb4TDEConfigDialog::~Smb4TDEConfigDialog()
{
}


void Smb4TDEConfigDialog::loadCustomSambaOptions()
{
  // Get the list view:
  TDEListView *custom_list = static_cast<TDEListView *>( child( "CustomOptionsList", "TDEListView", true ) );

  if ( !custom_list )
  {
    return;
  }

  // First of all clear the list view:
  custom_list->clear();

  // Now get the default values:
  TQString default_filesystem, protocol_hint, default_uid, default_gid;
  bool write_access = true;

  switch( Smb4KSettings::filesystem() )
  {
    case Smb4KSettings::EnumFilesystem::CIFS:
    {
      default_filesystem = "cifs";

      break;
    }
    case Smb4KSettings::EnumFilesystem::SMBFS:
    {
      default_filesystem = "smbfs";

      break;
    }
    default:
    {
      // FIXME: Set default_filesystem to "cifs"?
      break;
    }
  }

  switch ( Smb4KSettings::protocolHint() )
  {
    case Smb4KSettings::EnumProtocolHint::Automatic:
    {
      // In this case the user leaves it to the net
      // command to determine the right protocol.
      protocol_hint = TQString();

      break;
    }
    case Smb4KSettings::EnumProtocolHint::RPC:
    {
      protocol_hint = "rpc";

      break;
    }
    case Smb4KSettings::EnumProtocolHint::RAP:
    {
      protocol_hint = "rap";

      break;
    }
    case Smb4KSettings::EnumProtocolHint::ADS:
    {
      protocol_hint = "ads";

      break;
    }
    default:
    {
      protocol_hint = TQString();

      break;
    }
  }

  switch( Smb4KSettings::writeAccess() )
  {
    case Smb4KSettings::EnumWriteAccess::ReadWrite:
    {
      write_access = true;

      break;
    }
    case Smb4KSettings::EnumWriteAccess::ReadOnly:
    {
      write_access = false;

      break;
    }
    default:
    {
      break;
    }
  }

  const TQValueList<Smb4KSambaOptionsInfo *> &list = optionsHandler()->customOptionsList();

  for ( TQValueList<Smb4KSambaOptionsInfo *>::ConstIterator it = list.begin();
        it != list.end(); ++it )
  {
    // If the only modification is that the share is to be remounted,
    // we will not put it into the list:
    if ( (*it)->type() == Smb4KSambaOptionsInfo::Share &&
         (*it)->remount() &&
         (*it)->port() == Smb4KSettings::remotePort() &&
#ifndef __FreeBSD__
         TQString::compare( (*it)->filesystem(), default_filesystem ) == 0 &&
         (*it)->writeAccess() == write_access &&
         (*it)->kerberos() == Smb4KSettings::useKerberos() /* FreeBSD does not know Kerberos for mounting */ &&
#endif
         ((TQString::compare( default_filesystem, "cifs" ) == 0 && (*it)->uid().toInt() == (int)getuid()) ||
         (!(*it)->uid().isEmpty() && TQString::compare( (*it)->uid(), Smb4KSettings::userID() ) == 0)) &&
         ((TQString::compare( default_filesystem, "cifs" ) == 0 && (*it)->gid().toInt() == (int)getgid()) ||
         (!(*it)->gid().isEmpty() && TQString::compare( (*it)->gid(), Smb4KSettings::groupID() ) == 0)) )
    {
      continue;
    }

    // Now put the item in the list:
    TDEListViewItem *item = new TDEListViewItem( custom_list );

    item->setText( Smb4KSambaOptions::ItemName, (*it)->itemName() );

    item->setText( Smb4KSambaOptions::Port, ((*it)->port() != -1 ?
                   TQString( "%1" ).arg( (*it)->port() ) :
                   TQString( "%1" ).arg( Smb4KSettings::remotePort() )) );

    switch ( (*it)->type() )
    {
      case Smb4KSambaOptionsInfo::Host:
      {
        item->setText( Smb4KSambaOptions::Protocol, !(*it)->protocol().isEmpty() ?
                       (TQString::compare( (*it)->protocol(), "auto" ) == 0 ? i18n( "auto" ) : (*it)->protocol().upper()) :
                       (protocol_hint.isEmpty() ? i18n( "auto" ) : protocol_hint.upper()) );

        item->setText( Smb4KSambaOptions::Kerberos, (*it)->kerberos() ?
                       i18n( "yes" ) :
                       i18n( "no" ) );

#ifndef __FreeBSD__
        item->setText( Smb4KSambaOptions::FileSystem, "-" );

        item->setText( Smb4KSambaOptions::WriteAccess, "-" );
#endif

        item->setText( Smb4KSambaOptions::UID, "-" );

        item->setText( Smb4KSambaOptions::GID, "-" );

        break;
      }
      case Smb4KSambaOptionsInfo::Share:
      {
        item->setText( Smb4KSambaOptions::Protocol, "-" );

#ifndef __FreeBSD__
        item->setText( Smb4KSambaOptions::Kerberos, (*it)->kerberos() ?
                       i18n( "yes" ) :
                       i18n( "no" ) );

        item->setText( Smb4KSambaOptions::FileSystem, !(*it)->filesystem().isEmpty() ?
                       (*it)->filesystem().upper() :
                        default_filesystem.upper() );

        item->setText( Smb4KSambaOptions::WriteAccess, (*it)->writeAccess() ?
                       i18n( "read-write" ) :
                       i18n( "read-only" ) );
#else
        // FreeBSD does not know Kerberos for mounting
        item->setText( Smb4KSambaOptions::Kerberos, "-" );
#endif
        item->setText( Smb4KSambaOptions::UID, !(*it)->uid().isEmpty() ?
                       (*it)->uid() :
                       Smb4KSettings::userID() );

        item->setText( Smb4KSambaOptions::GID, !(*it)->gid().isEmpty() ?
                       (*it)->gid() :
                       Smb4KSettings::groupID() );

        break;
      }
      default:
      {
        break;
      }
    }
  }

  Smb4KSambaOptions *samba_options = static_cast<Smb4KSambaOptions *>( child( "SambaOptions", "Smb4KSambaOptions", true ) );

  if ( samba_options )
  {
    samba_options->resetCustomTab();
  }
}


void Smb4TDEConfigDialog::saveCustomSambaOptions()
{
  // Get the list view:
  TDEListView *custom_list = static_cast<TDEListView *>( child( "CustomOptionsList", "TDEListView", true ) );

  if ( !custom_list )
  {
    return;
  }

  if ( custom_list->childCount() != 0 )
  {
    // First remove all items that have been deleted in the
    // configuration dialog:
    TQValueList<Smb4KSambaOptionsInfo *> list = optionsHandler()->customOptionsList();

    for ( TQValueList<Smb4KSambaOptionsInfo *>::Iterator it = list.begin(); it != list.end(); ++it )
    {
      if ( !custom_list->findItem( (*it)->itemName(), Smb4KSambaOptions::ItemName ) )
      {
        optionsHandler()->removeItem( (*it)->itemName(), false );

        continue;
      }
      else
      {
        continue;
      }
    }

    // Now updated the remaining items:
    TQListViewItemIterator it( custom_list );

    while ( it.current() )
    {
      TQListViewItem *item = it.current();

      Smb4KSambaOptionsInfo *info = optionsHandler()->findItem( item->text( Smb4KSambaOptions::ItemName ) );

      if ( info )
      {
        switch( info->type() )
        {
          case Smb4KSambaOptionsInfo::Host:
          {
            info->setProtocol( (TQString::compare( item->text( Smb4KSambaOptions::Protocol ), "-" ) != 0 ?
                               item->text( Smb4KSambaOptions::Protocol ).lower() :
                               TQString()) );

            info->setKerberos( (TQString::compare( item->text( Smb4KSambaOptions::Kerberos ), i18n( "yes" ) ) == 0) );

            info->setPort( item->text( Smb4KSambaOptions::Port ).toInt() );

            break;
          }
          case Smb4KSambaOptionsInfo::Share:
          {
#ifndef __FreeBSD__
            // FreeBSD does not know Kerberos for mounting
            info->setKerberos( (TQString::compare( item->text( Smb4KSambaOptions::Kerberos ), i18n( "yes" ) ) == 0) );

            info->setFilesystem( (TQString::compare( item->text( Smb4KSambaOptions::FileSystem ), "-" ) != 0 ?
                                 item->text( Smb4KSambaOptions::FileSystem ).lower() :
                                 TQString()) );

            info->setWriteAccess( (TQString::compare( item->text( Smb4KSambaOptions::WriteAccess ),
                                  i18n( "read-write" ) ) == 0) );
#endif
            info->setUID( (TQString::compare( item->text( Smb4KSambaOptions::UID ), i18n( "default" ) ) != 0 &&
                          TQString::compare( item->text( Smb4KSambaOptions::UID ), "-" ) != 0) ?
                          item->text( Smb4KSambaOptions::UID ) :
                          TQString() );

            info->setGID( (TQString::compare( item->text( Smb4KSambaOptions::GID ), i18n( "default" ) ) != 0 &&
                          TQString::compare( item->text( Smb4KSambaOptions::GID ), "-" ) != 0) ?
                          item->text( Smb4KSambaOptions::GID ) :
                          TQString() );

            info->setPort( item->text( Smb4KSambaOptions::Port ).toInt() );

            break;
          }
          default:
          {
            break;
          }
        }
      }
      else
      {
        // We do not have this case.
      }

      ++it;
    }
  }
  else
  {
    // Remove all items, if the list view is empty:
    TQValueList<Smb4KSambaOptionsInfo *> list = optionsHandler()->customOptionsList();

    for ( TQValueList<Smb4KSambaOptionsInfo *>::Iterator it = list.begin(); it != list.end(); ++it )
    {
      if ( !(*it)->remount() )
      {
        optionsHandler()->removeItem( (*it)->itemName(), false );

        continue;
      }
      else
      {
        continue;
      }
    }
  }

  optionsHandler()->sync();
}


void Smb4TDEConfigDialog::loadAuthenticationData()
{
  // Load the default login info and put it into the configuration
  // page:
  Smb4KAuthInfo auth( TQString::null, TQString::null, TQString::null );

  (void) passwordHandler()->readDefaultAuth( &auth );

  KLineEdit *default_user = static_cast<KLineEdit *>( child( "DefaultUserName", "KLineEdit", true ) );

  if ( default_user )
  {
    default_user->setText( auth.user() );
  }

  KLineEdit *default_pass = static_cast<KLineEdit *>( child( "DefaultPassword", "KLineEdit", true ) );

  if ( default_pass )
  {
    default_pass->setText( auth.password() );
  }
}


void Smb4TDEConfigDialog::saveAuthenticationData()
{
  // Read the default login info from the configuration page
  // and pass it to the password handler, but only if the wallet
  // is open at this time. Otherwise we could end up with empty
  // entries:
  if ( passwordHandler()->walletIsOpen() )
  {
    Smb4KAuthInfo auth( TQString::null, TQString::null, TQString::null );

    KLineEdit *default_user = static_cast<KLineEdit *>( child( "DefaultUserName", "KLineEdit", true ) );

    if ( default_user )
    {
      auth.setUser( default_user->text() );
    }

    KLineEdit *default_pass = static_cast<KLineEdit *>( child( "DefaultPassword", "KLineEdit", true ) );

    if ( default_pass )
    {
      auth.setPassword( default_pass->text() );
    }

    passwordHandler()->writeDefaultAuth( &auth );
  }
  else
  {
    // Do nothing
  }
}


bool Smb4TDEConfigDialog::writeSuperUserEntries()
{
  TQRadioButton *sudo =  static_cast<TQRadioButton *>( child( "SudoButton", "TQRadioButton", true ) );
  TQRadioButton *super = static_cast<TQRadioButton *>( child( "SuperButton", "TQRadioButton", true ) );
#ifdef __linux__
  TQCheckBox *force =    static_cast<TQCheckBox *>( child( "kcfg_UseForceUnmount", "TQCheckBox", true ) );
#endif
  TQCheckBox *full_use = static_cast<TQCheckBox *>( child( "kcfg_AlwaysUseSuperUser", "TQCheckBox", true ) );

  // Check if we need to write anything at all:
  Smb4KFileIO::Operation op = Smb4KFileIO::NoOperation;
  bool success = true;

#ifdef __linux__
  if ( sudo && super && force && full_use )
#else
  if ( sudo && super && full_use )
#endif
  {
    if ( sudo->isChecked() )
    {
#ifdef __linux__
      if ( (!use_sudo && (force->isChecked() || full_use->isChecked())) ||
           (use_sudo &&
           ((force->isChecked() && force_unmount != force->isChecked()) ||
           (full_use->isChecked() && always_use_su != full_use->isChecked()))) )
#else
      if ( (!use_sudo && full_use->isChecked()) ||
           (use_sudo &&
           (full_use->isChecked() && always_use_su != full_use->isChecked())) )
#endif
      {
        success = Smb4KCore::fileIO()->writeSudoers( (op = Smb4KFileIO::Insert) );
      }
    }
    else if ( super->isChecked() )
    {
#ifdef __linux__
      if ( (!use_super && (force->isChecked() || full_use->isChecked())) ||
           (use_super &&
           ((force->isChecked() && force_unmount != force->isChecked()) ||
           (full_use->isChecked() && always_use_su != full_use->isChecked()))) )
#else
      if ( (!use_super && full_use->isChecked()) ||
           (use_super &&
           (full_use->isChecked() && always_use_su != full_use->isChecked())) )
#endif
      {
        success = Smb4KCore::fileIO()->writeSuperTab( (op = Smb4KFileIO::Insert) );
      }
    }
    else
    {
      // Do nothing
    }

    use_sudo =      sudo->isChecked();
    use_super =     super->isChecked();
#ifdef __linux__
    force_unmount = force->isChecked();
#endif
    always_use_su = full_use->isChecked();
  }
  else
  {
    // Do nothing
  }

  return (!success || op == Smb4KFileIO::NoOperation) ? false : true;
}


void Smb4TDEConfigDialog::removeSuperUserEntries()
{
  TQRadioButton *sudo =  static_cast<TQRadioButton *>( child( "SudoButton", "TQRadioButton", true ) );
  TQRadioButton *super = static_cast<TQRadioButton *>( child( "SuperButton", "TQRadioButton", true ) );
#ifdef __linux__
  TQCheckBox *force =    static_cast<TQCheckBox *>( child( "kcfg_UseForceUnmount", "TQCheckBox", true ) );
#endif
  TQCheckBox *full_use = static_cast<TQCheckBox *>( child( "kcfg_AlwaysUseSuperUser", "TQCheckBox", true ) );

#ifdef __linux__
  if ( sudo && super && force && full_use )
#else
  if ( sudo && super && full_use )
#endif

  {
    if ( sudo->isChecked() )
    {
      Smb4KCore::fileIO()->writeSudoers( Smb4KFileIO::Remove );
    }
    else if ( super->isChecked() )
    {
      Smb4KCore::fileIO()->writeSuperTab( Smb4KFileIO::Remove );
    }
    else
    {
      // Do nothing
    }

#ifdef __linux__
    force->setChecked( false );
#endif
    full_use->setChecked( false );

    use_sudo =      sudo->isChecked();
    use_super =     super->isChecked();
#ifdef __linux__
    force_unmount = force->isChecked();
#endif
    always_use_su = full_use->isChecked();
  }
  else
  {
    // Do nothing
  }
}


bool Smb4TDEConfigDialog::checkSettings()
{
  bool ok = true;
  TQString issues = TQString();
  int index = 0;

  // If the user chose "Query custom master browser" in the
  // "Network" tab, there must be a master browser present:
  TQRadioButton *query_custom_master = static_cast<TQRadioButton *>( child( "CustomMasterBrowserLabel", "TQRadioButton", true ) );
  KLineEdit *custom_master_input    = static_cast<KLineEdit *>( child( "kcfg_CustomMasterBrowser", "KLineEdit", true ) );

  if ( query_custom_master && custom_master_input &&
       query_custom_master->isChecked() &&
       custom_master_input->text().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Network] The custom master browser has not been entered.\n" ) );
  }

  // If the user chose "Scan broadcast areas" in the
  // "Network" tab, there must broadcast areas present:
  TQRadioButton *scan_bcast_areas    = static_cast<TQRadioButton *>( child( "BroadcastAreasLabel", "TQRadioButton", true ) );
  KLineEdit *bcast_areas_input      = static_cast<KLineEdit *>( child( "kcfg_BroadcastAreas", "KLineEdit", true ) );

  if ( scan_bcast_areas && bcast_areas_input &&
       scan_bcast_areas->isChecked() &&
       bcast_areas_input->text().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Network] The broadcast areas have not been entered.\n" ) );
  }

  // The mount prefix must not be empty:
  KURLRequester *mount_prefix       = static_cast<KURLRequester *>( child( "kcfg_MountPrefix", "KURLRequester", true ) );

  if ( mount_prefix && mount_prefix->url().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Shares] The mount prefix is empty.\n" ) );
  }

  // If the user wants to use a default login, the user
  // name must not be empty.
  TQCheckBox *use_default_login      = static_cast<TQCheckBox *>( child( "kcfg_UseDefaultLogin", "TQCheckBox", true ) );
  KLineEdit *default_user_name      = static_cast<KLineEdit *>( child( "kcfg_DefaultUserName", "KLineEdit", true ) );

  if ( use_default_login && default_user_name &&
       use_default_login->isChecked() &&
       default_user_name->text().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Authentication] The default user name has not been entered.\n" ) );
  }

  // The file mask must not be empty.
  KLineEdit *file_mask              = static_cast<KLineEdit *>( child( "kcfg_FileMask", "KLineEdit", true ) );

  if ( file_mask && file_mask->text().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Samba] The file mask is empty.\n" ) );
  }

  // The directory mask must not be empty.
  KLineEdit *directory_mask         = static_cast<KLineEdit *>( child( "kcfg_DirectoryMask", "KLineEdit", true ) );

  if ( directory_mask && directory_mask->text().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Samba] The directory mask is empty.\n" ) );
  }

  // The UID must not be empty.
  KLineEdit *user_id                = static_cast<KLineEdit *>( child( "kcfg_UserID", "KLineEdit", true ) );

  if ( user_id && user_id->text().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Samba] The UID is empty.\n" ) );
  }

  // The GID must not be empty.
  KLineEdit *group_id               = static_cast<KLineEdit *>( child( "kcfg_GroupID", "KLineEdit", true ) );

  if ( group_id && group_id->text().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Samba] The GID is empty.\n" ) );
  }

  // The rsync prefix must not be empty.
  KURLRequester *rsync_prefix       = static_cast<KURLRequester *>( child( "kcfg_RsyncPrefix", "KURLRequester", true ) );

  if ( rsync_prefix && rsync_prefix->url().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Synchronization] The rsync prefix is empty.\n" ) );
  }

  // The path where to store partial files must not be empty.
  TQCheckBox *use_partical_directory = static_cast<TQCheckBox *>( child( "kcfg_UsePartialDirectory", "TQCheckBox", true ) );
  KURLRequester *partial_directory  = static_cast<KURLRequester *>( child( "kcfg_PartialDirectory", "KURLRequester", true ) );

  if ( use_partical_directory && use_partical_directory->isChecked() &&
       partial_directory && partial_directory->url().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Synchronization] The directory where partially transferred files should be stored is empty.\n" ) );
  }

  // The the exclude patterns must not be empty.
  TQCheckBox *use_exclude_pattern    = static_cast<TQCheckBox *>( child( "kcfg_UseExcludePattern", "TQCheckBox", true ) );
  KLineEdit *exclude_pattern        = static_cast<KLineEdit *>( child( "kcfg_ExcludePattern", "KLineEdit", true ) );

  if ( use_exclude_pattern && use_exclude_pattern->isChecked() &&
       exclude_pattern && exclude_pattern->text().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Synchronization] The exclude patterns have not been entered.\n" ) );
  }

  // The the path of the exclude file must not be empty.
  TQCheckBox *use_exclude_file       = static_cast<TQCheckBox *>( child( "kcfg_UseExcludeFrom", "TQCheckBox", true ) );
  KURLRequester *exclude_file       = static_cast<KURLRequester *>( child( "kcfg_ExcludeFrom", "KURLRequester", true ) );

  if ( use_exclude_file && use_exclude_file->isChecked() &&
       exclude_file && exclude_file->url().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Synchronization] The path of the exclude file is empty.\n" ) );
  }

  // The the include patterns must not be empty.
  TQCheckBox *use_include_pattern    = static_cast<TQCheckBox *>( child( "kcfg_UseIncludePattern", "TQCheckBox", true ) );
  KLineEdit *include_pattern        = static_cast<KLineEdit *>( child( "kcfg_IncludePattern", "KLineEdit", true ) );

  if ( use_include_pattern && use_include_pattern->isChecked() &&
       include_pattern && include_pattern->text().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Synchronization] The include patterns have not been entered.\n" ) );
  }

  // The the path of the exclude file must not be empty.
  TQCheckBox *use_include_file       = static_cast<TQCheckBox *>( child( "kcfg_UseIncludeFrom", "TQCheckBox", true ) );
  KURLRequester *include_file       = static_cast<KURLRequester *>( child( "kcfg_IncludeFrom", "KURLRequester", true ) );

  if ( use_include_file && use_include_file->isChecked() &&
       include_file && include_file->url().stripWhiteSpace().isEmpty() )
  {
    ok = false;
    index++;

    issues.append( "* "+i18n( "[Synchronization] The path of the include file is empty.\n" ) );
  }

  // If you make backups, check that the suffix and that the
  // backup directory is not empty.
  TQCheckBox *make_backups           = static_cast<TQCheckBox *>( child( "kcfg_MakeBackups", "TQCheckBox", true ) );

  if ( make_backups && make_backups->isChecked() )
  {
    // The backup suffix must not be empty.
    TQCheckBox *use_backup_suffix    = static_cast<TQCheckBox *>( child( "kcfg_UseBackupSuffix", "TQCheckBox", true ) );
    KLineEdit *backup_suffix        = static_cast<KLineEdit *>( child( "kcfg_BackupSuffix", "KLineEdit", true ) );

    if ( use_backup_suffix && use_backup_suffix->isChecked() &&
         backup_suffix && backup_suffix->text().stripWhiteSpace().isEmpty() )
    {
      ok = false;
      index++;

      issues.append( "* "+i18n( "[Synchronization] The backup suffix has not been defined.\n" ) );
    }

    // The the path for backups must not be empty.
    TQCheckBox *use_backup_dir       = static_cast<TQCheckBox *>( child( "kcfg_UseBackupDirectory", "TQCheckBox", true ) );
    KURLRequester *backup_dir       = static_cast<KURLRequester *>( child( "kcfg_BackupDirectory", "KURLRequester", true ) );

    if ( use_backup_dir && use_backup_dir->isChecked() &&
         backup_dir && backup_dir->url().stripWhiteSpace().isEmpty() )
    {
      ok = false;
      index++;

      issues.append( "* "+i18n( "[Synchronization] The backup directory is empty.\n" ) );
    }
  }

  if ( !ok )
  {
    if ( index == 1 )
    {
      KMessageBox::error( this, i18n( "The configuration could not be written, because one setting is incomplete:\n%1Please correct this issue." ).arg( issues ) );
    }
    else
    {
      KMessageBox::error( this, i18n( "The configuration could not be written, because %1 settings are incomplete:\n%1Please correct these issues." ).arg( index ).arg( issues ) );
    }
  }

  return ok;
}


void Smb4TDEConfigDialog::showEvent( TQShowEvent *e )
{
  // Spontaneous show events come from outside the application.
  // We do not want to react on them.
  if ( !e->spontaneous() )
  {
    loadCustomSambaOptions();
    loadAuthenticationData();
  }
}


/////////////////////////////////////////////////////////////////////////////
// SLOT IMPLEMENTATIONS
/////////////////////////////////////////////////////////////////////////////

void Smb4TDEConfigDialog::slotApply()
{
  // If some settings are not complete, stop here and give
  // the user the opportunity to fill in the needed string(s).
  if ( !checkSettings() )
  {
    return;
  }

  saveCustomSambaOptions();
  saveAuthenticationData();

  if ( writeSuperUserEntries() )
  {
    // Disable this widget until Smb4KFileIO::finished()
    // is received.
    setEnabled( false );
  }

  // The 'Apply' button will be disabled by TDEConfigDialog, so we do not
  // need to do it here.

  TDEConfigDialog::slotApply();
}


void Smb4TDEConfigDialog::slotOk()
{
  // If some settings are not complete, stop here and give
  // the user the opportunity to fill in the needed string(s).
  if ( !checkSettings() )
  {
    return;
  }

  saveCustomSambaOptions();
  saveAuthenticationData();

  saveDialogSize( *(Smb4KSettings::self()->config()), "ConfigDialog" );

  // If the something needs to be written to either /etc/super.tab
  // or /etc/sudoers, do not close the dialog but wait until the
  // Smb4KFileIO::finished() signal is received.
  if ( !writeSuperUserEntries() )
  {
    TDEConfigDialog::slotOk();
  }
  else
  {
    // Disable this widget until Smb4KFileIO::finished()
    // is received.
    setEnabled( false );

    // Tell Smb4TDEConfigDialog::slotReceivedFileIOFinished()
    // to close the dialog.
    close_dialog = true;
  }
}


void Smb4TDEConfigDialog::slotCancel()
{
  // Reset the custom Samba options tab:
  Smb4KSambaOptions *samba_options = static_cast<Smb4KSambaOptions *>( child( "SambaOptions", "Smb4KSambaOptions", true ) );

  if ( samba_options )
  {
    samba_options->resetCustomTab();
  }

  TDEConfigDialog::slotCancel();
}


void Smb4TDEConfigDialog::slotCustomSambaSettingsChanged()
{
  // Get the list view and all other input widgets:
  TDEListView *view = static_cast<TDEListView *>( child( "CustomOptionsList", "TDEListView", true ) );

  if ( !view )
  {
    return;
  }

  // Get the list of custom options:
  TQValueList<Smb4KSambaOptionsInfo *> list = optionsHandler()->customOptionsList();

  bool changed = false;

  // Loop through the list view items to see what changed and if
  // we need to enable the 'Apply' button:
  for ( TQValueList<Smb4KSambaOptionsInfo *>::ConstIterator it = list.begin();
        it != list.end(); ++it )
  {
    // Find the item in the list view:
    TQListViewItem *item = view->findItem( (*it)->itemName(), Smb4KSambaOptions::ItemName );

    if ( item )
    {
      if ( (*it)->type() == Smb4KSambaOptionsInfo::Host )
      {
        // Check if the protocol changed.
        if ( ((*it)->protocol().isEmpty() &&
             TQString::compare( item->text( Smb4KSambaOptions::Protocol ).lower(), i18n( "auto" ) ) != 0) ||
             TQString::compare( (*it)->protocol(), item->text( Smb4KSambaOptions::Protocol ).lower() ) != 0 )
        {
          changed = true;

          break;
        }
      }
      else if ( (*it)->type() == Smb4KSambaOptionsInfo::Share )
      {
#ifndef __FreeBSD__
        // Check if the file system changed.
        if ( TQString::compare( (*it)->filesystem(), item->text( Smb4KSambaOptions::FileSystem ).lower() ) != 0 )
        {
          changed = true;

          break;
        }

        // Check if the write access changed.
        TQString write_access = (*it)->writeAccess() ?
                               i18n( "read-write" ) :
                               i18n( "read-only" );

        if ( TQString::compare( write_access, item->text( Smb4KSambaOptions::WriteAccess ) ) != 0 )
        {
          changed = true;

          break;
        }
#endif
        // Check if the UID changed.
        if ( ((*it)->uid().isEmpty() &&
             TQString::compare( i18n( "default" ), item->text( Smb4KSambaOptions::UID ) ) != 0) ||
             TQString::compare( (*it)->uid(), item->text( Smb4KSambaOptions::UID ) ) != 0 )
        {
          changed = true;

          break;
        }

        // Check if the GID changed.
        if ( ((*it)->gid().isEmpty() &&
             TQString::compare( i18n( "default" ), item->text( Smb4KSambaOptions::GID ) ) != 0) ||
             TQString::compare( (*it)->gid(), item->text( Smb4KSambaOptions::GID ) ) != 0 )
        {
          changed = true;

          break;
        }
      }
      else
      {
        // Something went wrong. Stop right here.
        break;
      }

      // Check if the Kerberos entry changed.
      TQString kerberos = (*it)->kerberos() ?
                         i18n( "yes" ) :
                         i18n( "no" );

      if ( TQString::compare( kerberos, item->text( Smb4KSambaOptions::Kerberos ) ) != 0 )
      {
        changed = true;

        break;
      }

      // Check if the port value changed.
      if ( (*it)->port() != item->text( Smb4KSambaOptions::Port ).toInt() )
      {
        changed = true;

        break;
      }
    }
    else
    {
      break;
    }
  }

  enableButtonApply( changed );
}


void Smb4TDEConfigDialog::slotRemoveSuperUserEntries()
{
  // Disable this widget until Smb4KFileIO::finished()
  // is received.
  setEnabled( false );

  removeSuperUserEntries();
}


void Smb4TDEConfigDialog::slotReceivedFileIOFailed()
{
#ifdef __linux__
  TQCheckBox *force =    static_cast<TQCheckBox *>( child( "kcfg_UseForceUnmount", "TQCheckBox", true ) );
#endif
  TQCheckBox *full_use = static_cast<TQCheckBox *>( child( "kcfg_AlwaysUseSuperUser", "TQCheckBox", true ) );

#ifdef __linux__
  if ( force && full_use )
  {
    force->setChecked( false );
#else
  if ( full_use )
  {
#endif
    full_use->setChecked( false );
  }
}


void Smb4TDEConfigDialog::slotReceivedFileIOFinished()
{
  // Enable the widget again.
  setEnabled( true );

  if ( close_dialog )
  {
    TDEConfigDialog::slotOk();
  }
}


/////////////////////////////////////////////////////////////////////////////
// FACTORY STUFF
/////////////////////////////////////////////////////////////////////////////

Smb4TDEConfigDialogFactory::Smb4TDEConfigDialogFactory()
: KLibFactory()
{
}


Smb4TDEConfigDialogFactory::~Smb4TDEConfigDialogFactory()
{
  delete m_instance;
  delete m_about;

  m_instance = 0L;
}


TDEInstance *Smb4TDEConfigDialogFactory::instance()
{
  if( !m_instance )
  {
    m_about = new TDEAboutData( "smb4tdeconfigdialog", I18N_NOOP( "Smb4TDEConfigDialog" ), "1.0" );
    m_about->addAuthor("Alexander Reinholdt", 0, "dustpuppy@users.berlios.de");
    m_about->setLicense( TDEAboutData::License_GPL );
    m_instance = new TDEInstance( m_about );
  }

  return m_instance;
}


TQObject *Smb4TDEConfigDialogFactory::createObject( TQObject *parent, const char *name, const char *,
const TQStringList & )
{
  return  new Smb4TDEConfigDialog( Smb4KSettings::self(), static_cast<TQWidget*>( parent ), name ) ;
}


/////////////////////////////////////////////////////////////////////////////
// INIT
/////////////////////////////////////////////////////////////////////////////


extern "C"
{
  KDE_EXPORT void *init_libsmb4tdeconfigdialog()
  {
    TDEGlobal::locale()->insertCatalogue( "smb4k" );
    return new Smb4TDEConfigDialogFactory;
  }
}

#include "smb4tdeconfigdialog.moc"
