Logo Search packages:      
Sourcecode: kbear version File versions  Download package

kbearpropertiesdialog.cpp

/***************************************************************************
                          kbearpropertiesdialog.cpp  -  description
                             -------------------
    begin                : mån sep 16 2002
    copyright            : (C) 2002 by Björn Sahlström
    email                : kbjorn@users.sourceforge.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

//////////////////////////////////////////////////////////////////////
// Qt specific include files
#include <qfile.h>
#include <qdir.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qstrlist.h>
#include <qstringlist.h>
#include <qtextstream.h>
#include <qpainter.h>
#include <qlayout.h>
#include <qcombobox.h>
#include <qgroupbox.h>
#include <qtextcodec.h>
//////////////////////////////////////////////////////////////////////
// KDE specific include files
#include <kcharsets.h>
#include <kapplication.h>
#include <dcopclient.h>
#include <kdialog.h>
#include <kdirwatch.h>
#include <kdirnotify.h>
//#include <kdiskfreesp.h>
#include <kdebug.h>
#include <kdesktopfile.h>
#include <kicondialog.h>
#include <kurl.h>
#include <kurlrequester.h>
#include <klocale.h>
#include <kcharsets.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kstandarddirs.h>
#include <kio/job.h>
#include <kio/chmodjob.h>
#include <kio/renamedlg.h>
#include <kfiledialog.h>
#include <kmimetype.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <kservice.h>
#include <kcompletion.h>
#include <klineedit.h>
#include <kseparator.h>
#include <klibloader.h>
#include <ktrader.h>
#include <kparts/componentfactory.h>
//#include <kmetaprops.h>
#include <krun.h>
//#include <kfilesharedlg.h>
//////////////////////////////////////////////////////////////////////
// Application specific include files
#include "kbearpropertiesdialog.h"
#include "kbeardirsize.h"
#include "kbearchmodjob.h"
#include "../../base/kbearconnectionmanager.h"
#include "../../base/transfer.h"
#include "../../base/kbearcopyjob.h"

#include <config.h>
extern "C" {
#include <pwd.h>
#include <grp.h>
#include <time.h>
}
#include <unistd.h>
#include <errno.h>
#include <assert.h>

#ifdef Q_WS_X11
extern "C" {
#include <X11/Xlib.h> // for XSetTransientForHint
}
#endif

#include "kbearpropertiesdialog.moc"

//-----------------------------------------------
mode_t KBearFilePermissionsPropsPlugin::fperm[3][4] = {
        {S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID},
        {S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID},
        {S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX}
    };

//-----------------------------------------------
//  KBearPropertiesDialog::KBearPropertiesDialogPrivate
//-----------------------------------------------
class KBearPropertiesDialog::KBearPropertiesDialogPrivate {
      public:
            KBearPropertiesDialogPrivate() {
                  m_aborted = false;
            }
            ~KBearPropertiesDialogPrivate() {}
            bool m_aborted:1;
            bool modal:1;
            bool autoShow:1;
};
//-----------------------------------------------
//  KBearPropertiesDialog
//-----------------------------------------------
00119 KBearPropertiesDialog::KBearPropertiesDialog( unsigned long id, KFileItemList _items,
                                      QWidget* parent, const char* name, QTextCodec* codec )
  : KDialogBase (KDialogBase::Tabbed, i18n( "Properties for %1" ).
      arg(codec->toUnicode( KIO::decodeFileName(_items.first()->url().fileName()))),
                 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok,
                 parent, name, true), m_ID( id ), m_codec( codec )
{
  d = new KBearPropertiesDialogPrivate;

  assert( !_items.isEmpty() );
  m_singleUrl = _items.first()->url();
  assert(!m_singleUrl.isEmpty());

  KFileItemListIterator it ( _items );
  // Deep copy
  for ( ; it.current(); ++it )
      m_items.append( new KFileItem( **it ) );

  init ();
}
//-----------------------------------------------
00140 void KBearPropertiesDialog::init ()
{
  m_pageList.setAutoDelete( true );
  m_items.setAutoDelete( true );


  //  resize( 400, 400 ); // not sure what that's for

  insertPages();

  //kdDebug(250) << "KBearPropertiesDialog sizeHint " << sizeHint().width() << "x" << sizeHint().height() << endl;
  // This HACK forces KDialogBase to recompute the layout
  // It is necessary for the case where init is not called from the constructor,
  // but from slotStatResult. And I'm way too lazy to look into KDialogBase...
  enableLinkedHelp( true );
  enableLinkedHelp( false );
  resize(sizeHint());

}
//-----------------------------------------------
/*
void KBearPropertiesDialog::showFileSharingPage()
{
    KBearPropsDlgPlugin *it;

    for ( it=m_pageList.first(); it != 0L; it=m_pageList.next() )
    {
        KFileSharePropsPlugin* plugin = dynamic_cast<KFileSharePropsPlugin*>(it);
        if ( plugin )
        {
            showPage( pageIndex( plugin->page() ) );
            break;
        }
    }
}
*/
//-----------------------------------------------
00177 KBearPropertiesDialog::~KBearPropertiesDialog()
{
  m_pageList.clear();
  delete d;
}
//-----------------------------------------------
00183 void KBearPropertiesDialog::insertPlugin (KBearPropsDlgPlugin* plugin)
{
  connect (plugin, SIGNAL (changed ()),
           plugin, SLOT (setDirty ()));
      connect( plugin, SIGNAL( infoMessage( const QString& ) ),
                        this, SIGNAL( infoMessage( const QString& ) ) );

  m_pageList.append (plugin);
}
//-----------------------------------------------
00193 bool KBearPropertiesDialog::canDisplay( KFileItemList _items )
{
  return KBearFilePropsPlugin::supports( _items ) ||
         KBearFilePermissionsPropsPlugin::supports( _items );
      /*
 ||
         KExecPropsPlugin::supports( _items ) ||
         KApplicationPropsPlugin::supports( _items ) ||
         KBindingPropsPlugin::supports( _items ) ||
         KURLPropsPlugin::supports( _items ) ||
         KDevicePropsPlugin::supports( _items );
*/
}
//-----------------------------------------------
00207 void KBearPropertiesDialog::slotOk()
{
  KBearPropsDlgPlugin *page;
  d->m_aborted = false;

  KBearFilePropsPlugin * filePropsPlugin = 0L;
  if ( m_pageList.first()->isA("KBearFilePropsPlugin") )
    filePropsPlugin = static_cast<KBearFilePropsPlugin *>(m_pageList.first());

  // If any page is dirty, then set the main one (KBearFilePropsPlugin) as
  // dirty too. This is what makes it possible to save changes to a global
  // desktop file into a local one. In other cases, it doesn't hurt.
  for ( page = m_pageList.first(); page != 0L; page = m_pageList.next() )
    if ( page->isDirty() && filePropsPlugin )
    {
        filePropsPlugin->setDirty();
        break;
    }

  // Apply the changes in the _normal_ order of the tabs now
  // This is because in case of renaming a file, KBearFilePropsPlugin will call
  // KBearPropertiesDialog::rename, so other tab will be ok with whatever order
  // BUT for file copied from templates, we need to do the renaming first !
  for ( page = m_pageList.first(); page != 0L && !d->m_aborted; page = m_pageList.next() )
    if ( page->isDirty() )
    {
      kdDebug() << "applying changes for " << page->className() << endl;
      page->applyChanges();
      // applyChanges may change d->m_aborted.
    }
    else
      kdDebug() << "skipping page " << page->className() << endl;

  if ( !d->m_aborted && filePropsPlugin )
    filePropsPlugin->postApplyChanges();

  if ( !d->m_aborted )
  {
    emit applied();
    emit propertiesClosed();
    deleteLater();
    accept();
  } // else, keep dialog open for user to fix the problem.
}
//-----------------------------------------------
void KBearPropertiesDialog::slotCancel()
{
  emit canceled();
  emit propertiesClosed();

  deleteLater();
  done( Rejected );
}
//-----------------------------------------------
00261 void KBearPropertiesDialog::insertPages()
{
  if (m_items.isEmpty())
    return;

  if ( KBearFilePropsPlugin::supports( m_items ) )
  {
    KBearPropsDlgPlugin *p = new KBearFilePropsPlugin( m_ID, this );
    insertPlugin (p);
  }

  if ( KBearFilePermissionsPropsPlugin::supports( m_items ) )
  {
    KBearPropsDlgPlugin *p = new KBearFilePermissionsPropsPlugin( m_ID, this );
    insertPlugin (p);
  }
/*

  if ( KExecPropsPlugin::supports( m_items ) )
  {
    KBearPropsDlgPlugin *p = new KExecPropsPlugin( this );
    insertPlugin (p);
  }

  if ( KApplicationPropsPlugin::supports( m_items ) )
  {
    KBearPropsDlgPlugin *p = new KApplicationPropsPlugin( this );
    insertPlugin (p);
  }

  if ( KBindingPropsPlugin::supports( m_items ) )
  {
    KBearPropsDlgPlugin *p = new KBindingPropsPlugin( this );
    insertPlugin (p);
  }

  if ( KURLPropsPlugin::supports( m_items ) )
  {
    KBearPropsDlgPlugin *p = new KURLPropsPlugin( this );
    insertPlugin (p);
  }

  if ( KDevicePropsPlugin::supports( m_items ) )
  {
    KBearPropsDlgPlugin *p = new KDevicePropsPlugin( m_ID, this );
    insertPlugin (p);
  }

  if ( KFileMetaPropsPlugin::supports( m_items ) )
  {
    KBearPropsDlgPlugin *p = new KFileMetaPropsPlugin( this );
    insertPlugin (p);
  }
  if ( KFileSharePropsPlugin::supports( m_items ) )
  {
    KBearPropsDlgPlugin *p = new KFileSharePropsPlugin( this );
    insertPlugin (p);
  }

  //plugins

  if ( m_items.count() != 1 )
    return;

  KFileItem *item = m_items.first();
  QString mimetype = item->mimetype();

  if ( mimetype.isEmpty() )
    return;

  QString query = QString::fromLatin1(
      "('KPropsDlg/Plugin' in ServiceTypes) and "
      "((not exist [X-KDE-Protocol]) or "
      " ([X-KDE-Protocol] == '%1'  )   )"          ).arg(item->url().protocol());

  kdDebug( 250 ) << "trader query: " << query << endl;
  KTrader::OfferList offers = KTrader::self()->query( mimetype, query );
  KTrader::OfferList::ConstIterator it = offers.begin();
  KTrader::OfferList::ConstIterator end = offers.end();
  for (; it != end; ++it )
  {
    KBearPropsDlgPlugin *plugin = KParts::ComponentFactory
        ::createInstanceFromLibrary<KBearPropsDlgPlugin>( (*it)->library().local8Bit().data(),
                                                      this,
                                                      (*it)->name().latin1() );
    if ( !plugin )
        continue;

    insertPlugin( plugin );
  }
*/
}
//-----------------------------------------------
00354 void KBearPropertiesDialog::updateUrl( const KURL& _newUrl )
{
  Q_ASSERT( m_items.count() == 1 );
  kdDebug() << "KBearPropertiesDialog::updateUrl " << _newUrl.url() << endl;
  m_singleUrl = _newUrl;
  m_items.first()->setURL( _newUrl );
  assert(!m_singleUrl.isEmpty());
  // If we have an Exec page, set it dirty, so that a full file is saved locally
  // Same for a URL page (because of the Name= hack)
  for ( QPtrListIterator<KBearPropsDlgPlugin> it(m_pageList); it.current(); ++it )
   if ( it.current()->isA("KExecPropsPlugin") || it.current()->isA("KURLPropsPlugin") )
   {
     //kdDebug(250) << "Setting page dirty" << endl;
     it.current()->setDirty();
     break;
   }
}
//-----------------------------------------------
00372 void KBearPropertiesDialog::rename( const QString& _name )
{
  Q_ASSERT( m_items.count() == 1 );
  kdDebug() << "KBearPropertiesDialog::rename " << _name << endl;
  KURL newUrl;
  // if we're creating from a template : use currentdir
  if ( !m_currentDir.isEmpty() )
  {
    newUrl = m_currentDir;
    newUrl.addPath( _name );
  }
  else
  {
    QString tmpurl = m_singleUrl.url();
    if ( tmpurl.at(tmpurl.length() - 1) == '/')
      // It's a directory, so strip the trailing slash first
      tmpurl.truncate( tmpurl.length() - 1);
    newUrl = tmpurl;
    newUrl.setFileName( _name );
  }
  updateUrl( newUrl );
}
//-----------------------------------------------
00395 void KBearPropertiesDialog::abortApplying()
{
  d->m_aborted = true;
}
//-----------------------------------------------

class KBearPropsDlgPlugin::KBearPropsDlgPluginPrivate
{
public:
  KBearPropsDlgPluginPrivate()
  {
  }
  ~KBearPropsDlgPluginPrivate()
  {
  }

  bool m_bDirty;
};

00414 KBearPropsDlgPlugin::KBearPropsDlgPlugin( unsigned long id, KBearPropertiesDialog *_props )
: QObject( _props, 0L ), m_ID( id )
{
  d = new KBearPropsDlgPluginPrivate;
  properties = _props;
  fontHeight = 2*properties->dialog()->fontMetrics().height();
  d->m_bDirty = false;
}

KBearPropsDlgPlugin::~KBearPropsDlgPlugin()
{
  delete d;
}

void KBearPropsDlgPlugin::slotInfoMessage( const QString&, const QString& m ) {
      emit infoMessage( m );
}
void KBearPropsDlgPlugin::slotInfoMessage( KIO::Job*, const QString& m ) {
      emit infoMessage( m );
}
00434 bool KBearPropsDlgPlugin::isDesktopFile( KFileItem * _item )
{
  // only local files
  if ( !_item->isLocalFile() )
    return false;

  // only regular files
  if ( !S_ISREG( _item->mode() ) )
    return false;

  QString t( _item->url().path() );

  // only if readable
  FILE *f = fopen( QFile::encodeName(t), "r" );
  if ( f == 0L )
    return false;
  fclose(f);

  // return true if desktop file
  return ( _item->mimetype() == QString::fromLatin1("application/x-desktop") );
}

void KBearPropsDlgPlugin::setDirty( bool b )
{
  d->m_bDirty = b;
}

void KBearPropsDlgPlugin::setDirty()
{
  d->m_bDirty = true;
}

bool KBearPropsDlgPlugin::isDirty() const
{
  return d->m_bDirty;
}

00471 void KBearPropsDlgPlugin::applyChanges()
{
  kdWarning() << "applyChanges() not implemented in page !" << endl;
}

///////////////////////////////////////////////////////////////////////////////

class KBearFilePropsPlugin::KBearFilePropsPluginPrivate
{
public:
  KBearFilePropsPluginPrivate()
  {
    dirSizeJob = 0L;
  }
  ~KBearFilePropsPluginPrivate()
  {
    if ( dirSizeJob )
      dirSizeJob->kill();
  }

  KBearDirSize * dirSizeJob;
  QFrame *m_frame;
  bool bMultiple;
  QLabel *m_freeSpaceLabel;
};

00497 KBearFilePropsPlugin::KBearFilePropsPlugin( unsigned long id, KBearPropertiesDialog *_props )
  : KBearPropsDlgPlugin( id, _props ), m_transfer( 0L )
{
  d = new KBearFilePropsPluginPrivate;
  d->bMultiple = (properties->items().count() > 1);
  kdDebug() << "KBearFilePropsPlugin::KBearFilePropsPlugin bMultiple=" << d->bMultiple << endl;

  // We set this data from the first item, and we'll
  // check that the other items match against it, resetting when not.
  bool isLocal = properties->kurl().isLocalFile();
  KFileItem * item = properties->item();
  bool bDesktopFile = isDesktopFile(item);
  mode_t mode = item->mode();
  bool hasDirs = item->isDir() && !item->isLink();
  bool hasRoot = isLocal && properties->kurl().path() == QString::fromLatin1("/");
  QString iconStr = KMimeType::iconForURL(properties->kurl(), mode);
  QString directory = properties->kurl().directory();
  QString protocol = properties->kurl().protocol();
  QString mimeComment = item->mimeComment();
  KIO::filesize_t totalSize = item->size();

  // Those things only apply to 'single file' mode
  QString filename = QString::null;
  bool isTrash = false;
  m_bFromTemplate = false;

  // And those only to 'multiple' mode
  uint iDirCount = S_ISDIR(mode) ? 1 : 0;
  uint iFileCount = 1-iDirCount;

  d->m_frame = properties->dialog()->addPage (i18n("&General"));

  QVBoxLayout *vbl = new QVBoxLayout( d->m_frame, KDialog::marginHint(),
                                      KDialog::spacingHint(), "vbl");
  QGridLayout *grid = new QGridLayout(0, 3); // unknown rows
  grid->setColStretch(2, 1);
  grid->addColSpacing(1, KDialog::spacingHint());
  vbl->addLayout(grid);
  int curRow = 0;

  if ( !d->bMultiple )
  {
    // Extract the file name only
    filename = properties->defaultName();
    if ( filename.isEmpty() ) // no template
      filename = properties->kurl().fileName();
    else
    {
      m_bFromTemplate = true;
      setDirty(); // to enforce that the copy happens
    }
    oldName = filename;

    // Make it human-readable (%2F => '/', ...)
    filename = KIO::decodeFileName( filename );

    QString path;

    if ( !m_bFromTemplate ) {
      QString tmp = properties->kurl().path( 1 );
      // is it the trash bin ?
      if ( isLocal && tmp == KGlobalSettings::trashPath())
        isTrash = true;

      // Extract the full name, but without file: for local files
      if ( isLocal )
        path = properties->kurl().path();
      else
        path = properties->kurl().prettyURL();
    } else {
      path = properties->currentDir().path(1) + properties->defaultName();
      directory = properties->currentDir().prettyURL();
    }

/*
    if (KExecPropsPlugin::supports(properties->items()) ||
        KBindingPropsPlugin::supports(properties->items())) {

      determineRelativePath( path );
    }
*/

  }
  else
  {
    // Multiple items: see what they have in common
    KFileItemList items = properties->items();
    KFileItemListIterator it( items );
    for ( ++it /*no need to check the first one again*/ ; it.current(); ++it )
    {
      KURL url = (*it)->url();
      kdDebug() << "KBearFilePropsPlugin::KBearFilePropsPlugin " << url.prettyURL() << endl;
      // The list of things we check here should match the variables defined
      // at the beginning of this method.
      if ( url.isLocalFile() != isLocal )
        isLocal = false; // not all local
      if ( bDesktopFile && isDesktopFile(*it) != bDesktopFile )
        bDesktopFile = false; // not all desktop files
      if ( (*it)->mode() != mode )
        mode = (mode_t)0;
      if ( KMimeType::iconForURL(url, mode) != iconStr )
        iconStr = "kmultiple";
      if ( url.directory() != directory )
        directory = QString::null;
      if ( url.protocol() != protocol )
        protocol = QString::null;
      if ( (*it)->mimeComment() != mimeComment )
        mimeComment = QString::null;
      if ( isLocal && url.path() == QString::fromLatin1("/") )
        hasRoot = true;
      if ( (*it)->isDir() && !(*it)->isLink() )
      {
        iDirCount++;
        hasDirs = true;
      }
      else
      {
        iFileCount++;
        totalSize += (*it)->size();
      }
    }
  }

  if (!isLocal && !protocol.isEmpty())
  {
    directory += ' ';
    directory += '(';
    directory += protocol;
    directory += ')';
  }

  if ( (bDesktopFile || S_ISDIR(mode)) && !d->bMultiple /*not implemented for multiple*/ )
  {
    KIconButton *iconButton = new KIconButton( d->m_frame );
    iconButton->setFixedSize(70, 70);
    iconButton->setStrictIconSize(false);
    iconButton->setIconType(KIcon::Desktop, KIcon::Device);
    // This works for everything except Device icons on unmounted devices
    // So we have to really open .desktop files
    QString iconStr = KMimeType::findByURL( properties->kurl(),
                                            mode )->icon( properties->kurl(),
                                                          isLocal );
    if ( bDesktopFile && isLocal )
    {
      KSimpleConfig config( properties->kurl().path() );
      config.setDesktopGroup();
      iconStr = config.readEntry( QString::fromLatin1("Icon") );
    }
    iconButton->setIcon(iconStr);
    iconArea = iconButton;
    connect( iconButton, SIGNAL( iconChanged(QString) ),
             this, SIGNAL( changed() ) );
  } else {
    QLabel *iconLabel = new QLabel( d->m_frame );
    iconLabel->setFixedSize(70, 70);
    iconLabel->setPixmap( DesktopIcon( iconStr ) );
    iconArea = iconLabel;
  }
  grid->addWidget(iconArea, curRow, 0, AlignLeft);

  if (d->bMultiple || isTrash || filename == QString::fromLatin1("/"))
  {
    QLabel *lab = new QLabel(d->m_frame );
    if ( d->bMultiple )
      lab->setText( KIO::itemsSummaryString( iFileCount + iDirCount, iFileCount, iDirCount, 0, false ) );
    else
      lab->setText( filename );
    nameArea = lab;
  } else
  {
    KLineEdit *lined = new KLineEdit( d->m_frame );
//TEST
      lined->setText( properties->codec()->toUnicode( filename ) );
//OLD
//    lined->setText(filename);
// OLD END
    nameArea = lined;
    lined->setFocus();
    connect( lined, SIGNAL( textChanged( const QString & ) ),
             this, SLOT( nameFileChanged(const QString & ) ) );
  }

  grid->addWidget(nameArea, curRow++, 2);

  KSeparator* sep = new KSeparator( KSeparator::HLine, d->m_frame);
  grid->addMultiCellWidget(sep, curRow, curRow, 0, 2);
  ++curRow;

  QLabel *l;
  if ( !mimeComment.isEmpty() )
  {
    l = new QLabel(i18n("Type:"), d->m_frame );
    grid->addWidget(l, curRow, 0);

    l = new QLabel(mimeComment, d->m_frame );
    grid->addWidget(l, curRow++, 2);
  }

  if ( !directory.isEmpty() )
  {
    l = new QLabel( i18n("Location:"), d->m_frame );
    grid->addWidget(l, curRow, 0);

    l = new QLabel( d->m_frame );
    l->setText( properties->codec()->toUnicode( directory ) );
    grid->addWidget(l, curRow++, 2);
  }

  l = new QLabel(i18n("Size:"), d->m_frame );
  grid->addWidget(l, curRow, 0);

  m_sizeLabel = new QLabel( d->m_frame );
  grid->addWidget( m_sizeLabel, curRow++, 2 );

  if ( !hasDirs ) // Only files [and symlinks]
  {
    m_sizeLabel->setText(QString::fromLatin1("%1 (%2)").arg(KIO::convertSize(totalSize)).arg(KGlobal::locale()->formatNumber(totalSize, 0)));
    m_sizeDetermineButton = 0L;
    m_sizeStopButton = 0L;
  }
  else // Directory
  {
    QHBoxLayout * sizelay = new QHBoxLayout(KDialog::spacingHint());
    grid->addLayout( sizelay, curRow++, 2 );

    // buttons
    m_sizeDetermineButton = new QPushButton( i18n("Calculate"), d->m_frame );
    m_sizeStopButton = new QPushButton( i18n("Stop"), d->m_frame );
    connect( m_sizeDetermineButton, SIGNAL( clicked() ), this, SLOT( slotSizeDetermine() ) );
    connect( m_sizeStopButton, SIGNAL( clicked() ), this, SLOT( slotSizeStop() ) );
    sizelay->addWidget(m_sizeDetermineButton, 0);
    sizelay->addWidget(m_sizeStopButton, 0);
    sizelay->addStretch(10); // so that the buttons don't grow horizontally

    // auto-launch for local dirs only, and not for '/'
    if ( isLocal && !hasRoot )
    {
      m_sizeDetermineButton->setText( i18n("Refresh") );
      slotSizeDetermine();
    }
    else
      m_sizeStopButton->setEnabled( false );
  }

/*
  if ( isLocal )
  {
      QString mountPoint = KIO::findPathMountPoint( properties->item()->url().path() );

      l = new QLabel(i18n("Free space on %1:").arg(mountPoint), d->m_frame );
      grid->addWidget(l, curRow, 0);

      d->m_freeSpaceLabel = new QLabel( d->m_frame );
      grid->addWidget( d->m_freeSpaceLabel, curRow++, 2 );

      KDiskFreeSp * job = new KDiskFreeSp;
      connect( job, SIGNAL( foundMountPoint( const unsigned long&, const unsigned long&, const unsigned long&, const QString& ) ),
               this, SLOT( slotFoundMountPoint( const unsigned long&, const unsigned long&, const unsigned long&, const QString& ) ) );
      job->readDF( mountPoint );
  }
*/

  if (!d->bMultiple && item->isLink()) {
    l = new QLabel(i18n("Points to:"), d->m_frame );
    grid->addWidget(l, curRow, 0);

    l = new QLabel(item->linkDest(), d->m_frame );
    grid->addWidget(l, curRow++, 2);
  }

  if (!d->bMultiple) // Dates for multiple don't make much sense...
  {
    sep = new KSeparator( KSeparator::HLine, d->m_frame);
    grid->addMultiCellWidget(sep, curRow, curRow, 0, 2);
    ++curRow;

    grid = new QGridLayout(0, 3); // unknown # of rows
    grid->setColStretch(2, 1);
    grid->addColSpacing(1, KDialog::spacingHint());
    vbl->addLayout(grid);
    curRow = 0;

    QDateTime dt;
    time_t tim = item->time(KIO::UDS_CREATION_TIME);
    if ( tim )
    {
      l = new QLabel(i18n("Created:"), d->m_frame );
      grid->addWidget(l, curRow, 0);

      dt.setTime_t( tim );
      l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
      grid->addWidget(l, curRow++, 2);
    }

    tim = item->time(KIO::UDS_MODIFICATION_TIME);
    if ( tim )
    {
      l = new QLabel(i18n("Modified:"), d->m_frame );
      grid->addWidget(l, curRow, 0);

      dt.setTime_t( tim );
      l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
      grid->addWidget(l, curRow++, 2);
    }

    tim = item->time(KIO::UDS_ACCESS_TIME);
    if ( tim )
    {
      l = new QLabel(i18n("Accessed:"), d->m_frame );
      grid->addWidget(l, curRow, 0);

      dt.setTime_t( tim );
      l = new QLabel(KGlobal::locale()->formatDateTime(dt), d->m_frame );
      grid->addWidget(l, curRow++, 2);
    }
  }

  vbl->addStretch(1);
}

// QString KBearFilePropsPlugin::tabName () const
// {
//   return i18n ("&General");
// }


void KBearFilePropsPlugin::nameFileChanged(const QString &text )
{
  properties->enableButtonOK(!text.isEmpty());
  changed();
}
/*
void KBearFilePropsPlugin::determineRelativePath( const QString & path )
{
    m_sRelativePath = "";
    // now let's make it relative
    QStringList dirs;
    if (KBindingPropsPlugin::supports(properties->items()))
      dirs = KGlobal::dirs()->resourceDirs("mime");
    else
      dirs = KGlobal::dirs()->resourceDirs("apps");

    QStringList::ConstIterator it = dirs.begin();
    for ( ; it != dirs.end() && m_sRelativePath.isEmpty(); ++it ) {
      // might need canonicalPath() ...
      if ( path.find( *it ) == 0 ) // path is dirs + relativePath
        m_sRelativePath = path.mid( (*it).length() ); // skip appsdirs
    }
    if ( m_sRelativePath.isEmpty() )
    {
      if (KBindingPropsPlugin::supports(properties->items()))
        kdWarning() << "Warning : editing a mimetype file out of the mimetype dirs!" << endl;
      // for Application desktop files, no problem : we can editing a .desktop file anywhere...
    } else
        while ( m_sRelativePath.at(0) == '/' ) m_sRelativePath.remove( 0, 1 );
}

void KBearFilePropsPlugin::slotFoundMountPoint( const QString&, unsigned long kBSize, unsigned long ,, unsigned long kBAvail )
{
    d->m_freeSpaceLabel->setText( i18n("Available space out of total partition size (percent used)", "%1/%2 (%3% used)")
                               .arg(KIO::convertSizeFromKB(kBAvail))
                               .arg(KIO::convertSizeFromKB(kBSize))
                               .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
}

// attention: copy&paste below, due to compiler bug
// it doesn't like those unsigned long parameters -- unsigned long& are ok :-/
void KBearFilePropsPlugin::slotFoundMountPoint( const unsigned long& kBSize, const unsigned long& , const unsigned long& kBAvail, const QString& )
{
    d->m_freeSpaceLabel->setText( i18n("Available space out of total partition size (percent used)", "%1/%2 (%3% used)")
                               .arg(KIO::convertSizeFromKB(kBAvail))
                               .arg(KIO::convertSizeFromKB(kBSize))
                               .arg( 100 - (int)(100.0 * kBAvail / kBSize) ));
}
*/
void KBearFilePropsPlugin::slotDirSizeFinished( KIO::Job * job )
{
  if (job->error())
    m_sizeLabel->setText( job->errorString() );
  else
  {
    KIO::filesize_t totalSize = static_cast<KBearDirSize*>(job)->totalSize();
    m_sizeLabel->setText( QString::fromLatin1("%1 (%2)").arg(KIO::convertSize(totalSize)).arg(KGlobal::locale()->formatNumber(totalSize, 0)) );
  }
  m_sizeStopButton->setEnabled(false);
  // just in case you change something and try again :)
  m_sizeDetermineButton->setText( i18n("Refresh") );
  m_sizeDetermineButton->setEnabled(true);
  d->dirSizeJob = 0L;
}

void KBearFilePropsPlugin::slotSizeDetermine()
{
  m_sizeLabel->setText( i18n("Calculating...") );
  kdDebug() << " KBearFilePropsPlugin::slotSizeDetermine() properties->item()=" <<  properties->item() << endl;
  kdDebug() << " URL=" << properties->item()->url().url() << endl;
  d->dirSizeJob = KBearDirSize::dirSizeJob( m_ID, properties->items() );
  connect( d->dirSizeJob, SIGNAL( result( KIO::Job * ) ),
           SLOT( slotDirSizeFinished( KIO::Job * ) ) );
  connect( d->dirSizeJob, SIGNAL( infoMessage( KIO::Job*, const QString& ) ),
           this, SIGNAL( infoMessage( KIO::Job*, const QString& ) ) );
  m_sizeStopButton->setEnabled(true);
  m_sizeDetermineButton->setEnabled(false);
}

void KBearFilePropsPlugin::slotSizeStop()
{
  if ( d->dirSizeJob )
  {
    m_sizeLabel->setText( i18n("Stopped") );
    d->dirSizeJob->kill();
    d->dirSizeJob = 0;
  }
  m_sizeStopButton->setEnabled(false);
  m_sizeDetermineButton->setEnabled(true);
}

KBearFilePropsPlugin::~KBearFilePropsPlugin()
{
      if( m_transfer )
            delete m_transfer;
      delete d;
}

00921 bool KBearFilePropsPlugin::supports( KFileItemList /*_items*/ )
{
  return true;
}

// Don't do this at home
void qt_enter_modal( QWidget *widget );
void qt_leave_modal( QWidget *widget );

00930 void KBearFilePropsPlugin::applyChanges()
{
  if ( d->dirSizeJob )
    slotSizeStop();

  kdDebug() << "KBearFilePropsPlugin::applyChanges" << endl;

  if (nameArea->inherits("QLineEdit"))
  {
      QString n = KIO::encodeFileName(((QLineEdit *) nameArea)->text());
//TEST
      n = properties->codec()->fromUnicode( ((QLineEdit *) nameArea)->text());

    // Remove trailing spaces (#4345)
    while ( n[n.length()-1].isSpace() )
      n.truncate( n.length() - 1 );
    if ( n.isEmpty() )
    {
      KMessageBox::sorry( properties, i18n("The new file name is empty!"));
      properties->abortApplying();
      return;
    }

    // Do we need to rename the file ?
    kdDebug() << "oldname = " << oldName << endl;
    kdDebug() << "newname = " << n << endl;
    if ( oldName != n || m_bFromTemplate ) { // true for any from-template file
      KBearCopyJob * job = 0L;
      KURL oldurl = properties->kurl();
      // Tell properties. Warning, this changes the result of properties->kurl() !
      properties->rename( n );

      // Update also relative path (for apps and mimetypes)
/*
      if ( !m_sRelativePath.isEmpty() )
        determineRelativePath( properties->kurl().path() );
*/
      kdDebug() << "New URL = " << properties->kurl().url() << endl;
      kdDebug() << "old = " << oldurl.url() << endl;

      // Don't remove the template !!
            
/*
      if ( !m_bFromTemplate ) // (normal renaming)
        job = KIO::move( oldurl, properties->kurl(), false );
      else // Copying a template
        job = KIO::move( oldurl, properties->kurl(), false );
*/
      Connection* tmpConn = connectionManager->getConnection( m_ID );
      m_transfer = new Transfer;
      m_transfer->setDestConnection( *tmpConn );
      m_transfer->setSourceConnection( *tmpConn );
      m_transfer->setDestURL( properties->kurl() );
      m_transfer->sourceList().append( oldurl );
      
      job = connectionManager->move( m_transfer, m_ID, m_ID );
      connect( job, SIGNAL( logMessage( const QString&, const QString& ) ),
                  this, SLOT( slotInfoMessage( const QString&, const QString& ) ) );

      connect( job, SIGNAL( result( KIO::Job * ) ),
               SLOT( slotCopyFinished( KIO::Job * ) ) );
      connect( job, SIGNAL( renamed( KIO::Job *, const KURL &, const KURL & ) ),
               SLOT( slotFileRenamed( KIO::Job *, const KURL &, const KURL & ) ) );
      job->slotStart();
      // wait for job
      QWidget dummy(0,0,WType_Dialog|WShowModal);
      qt_enter_modal(&dummy);
      qApp->enter_loop();
      qt_leave_modal(&dummy);
      return;
    }
  }

  // No job, keep going
  slotCopyFinished( 0L );
}

void KBearFilePropsPlugin::slotCopyFinished( KIO::Job * job )
{
  kdDebug() << "KBearFilePropsPlugin::slotCopyFinished" << endl;
  if (job)
  {
    // allow apply() to return
    qApp->exit_loop();
    if ( job->error() )
    {
        job->showErrorDialog( d->m_frame );
        // Didn't work. Revert the URL to the old one
        properties->updateUrl( static_cast<KIO::CopyJob*>(job)->srcURLs().first() );
        properties->abortApplying(); // Don't apply the changes to the wrong file !
        return;
    }
  }

  assert( properties->item() );
  assert( !properties->item()->url().isEmpty() );

/*
  // Save the file where we can -> usually in ~/.kde/...
  if (KBindingPropsPlugin::supports(properties->items()) && !m_sRelativePath.isEmpty())
  {
    KURL newURL;
    newURL.setPath( locateLocal("mime", m_sRelativePath) );
    properties->updateUrl( newURL );
  }
  else if (KExecPropsPlugin::supports(properties->items()) && !m_sRelativePath.isEmpty())
  {
    kdDebug() << "KBearFilePropsPlugin::slotCopyFinished " << m_sRelativePath << endl;
    KURL newURL;
    newURL.setPath( locateLocal("apps", m_sRelativePath) );
    kdDebug() << "KBearFilePropsPlugin::slotCopyFinished path=" << newURL.path() << endl;
    properties->updateUrl( newURL );
  }
*/
  // handle icon changes - only local files for now
  // TODO: Use KTempFile and KIO::file_copy with resume = true
  if (!iconArea->isA("QLabel") && properties->kurl().isLocalFile()) {
    KIconButton *iconButton = (KIconButton *) iconArea;
    QString path;

    if (S_ISDIR(properties->item()->mode()))
    {
      path = properties->kurl().path(1) + QString::fromLatin1(".directory");
      // don't call updateUrl because the other tabs (i.e. permissions)
      // apply to the directory, not the .directory file.
    }
    else
      path = properties->kurl().path();

    // Get the default image
    QString str = KMimeType::findByURL( properties->kurl(),
                                        properties->item()->mode(),
                                        true )->KServiceType::icon();
    // Is it another one than the default ?
    QString sIcon;
    if ( str != iconButton->icon() )
      sIcon = iconButton->icon();
    // (otherwise write empty value)

    kdDebug() << "**" << path << "**" << endl;
    QFile f( path );

    // If default icon and no .directory file -> don't create one
    if ( !sIcon.isEmpty() || f.exists() )
    {
        if ( !f.open( IO_ReadWrite ) ) {
          KMessageBox::sorry( 0, i18n("<qt>Could not save properties. You do not have sufficient access to write to <b>%1</b>.</qt>").arg(path));
          return;
        }
        f.close();

        KDesktopFile cfg(path);
        kdDebug() << "sIcon = " << (sIcon) << endl;
        kdDebug() << "str = " << (str) << endl;
        cfg.writeEntry( QString::fromLatin1("Icon"), sIcon );
        cfg.sync();
    }
  }
}

void KBearFilePropsPlugin::slotFileRenamed( KIO::Job *, const KURL &, const KURL & newUrl )
{
  // This is called in case of an existing local file during the copy/move operation,
  // if the user chooses Rename.
  properties->updateUrl( newUrl );
}

01097 void KBearFilePropsPlugin::postApplyChanges()
{
  KURL::List lst;
  KFileItemList items = properties->items();
  for ( KFileItemListIterator it( items ); it.current(); ++it )
    lst.append((*it)->url());
      QByteArray data;
      QDataStream arg( data, IO_WriteOnly );
      arg << lst;
      kapp->dcopClient()->send( "*", "KDirNotify", "FilesChanged(const KURL::List&)", data );
}

class KBearFilePermissionsPropsPlugin::KBearFilePermissionsPropsPluginPrivate
{
public:
  KBearFilePermissionsPropsPluginPrivate()
  {
  }
  ~KBearFilePermissionsPropsPluginPrivate()
  {
  }

  QFrame *m_frame;
  QCheckBox *cbRecursive;
  mode_t partialPermissions;
};

01124 KBearFilePermissionsPropsPlugin::KBearFilePermissionsPropsPlugin( unsigned long id,KBearPropertiesDialog *_props )
  : KBearPropsDlgPlugin( id, _props )
{
  d = new KBearFilePermissionsPropsPluginPrivate;
  d->cbRecursive = 0L;
  grpCombo = 0L; grpEdit = 0;
  usrEdit = 0L;
  QString path = properties->kurl().path(-1);
  QString fname = properties->kurl().fileName();
  bool isLocal = properties->kurl().isLocalFile();

  bool IamRoot = (geteuid() == 0);

  KFileItem * item = properties->item();
  bool isLink = item->isLink();
  bool isDir = item->isDir(); // all dirs
  bool hasDir = item->isDir(); // at least one dir
  permissions = item->permissions(); // common permissions to all files
  d->partialPermissions = permissions; // permissions that only some files have (at first we take everything)
  strOwner = item->user();
  strGroup = item->group();

  if ( properties->items().count() > 1 )
  {
    // Multiple items: see what they have in common
    KFileItemList items = properties->items();
    KFileItemListIterator it( items );
    for ( ++it /*no need to check the first one again*/ ; it.current(); ++it )
    {
      if ( (*it)->isLink() != isLink )
        isLink = false;
      if ( (*it)->isDir() != isDir )
        isDir = false;
      hasDir |= (*it)->isDir();
      if ( (*it)->permissions() != permissions )
      {
        permissions &= (*it)->permissions();
        d->partialPermissions |= (*it)->permissions();
      }
      if ( (*it)->user() != strOwner )
        strOwner = QString::null;
      if ( (*it)->group() != strGroup )
        strGroup = QString::null;
    }
  }

  // keep only what's not in the common permissions
  d->partialPermissions = d->partialPermissions & ~permissions;

  bool isMyFile = false;

  if (isLocal && !strOwner.isEmpty()) { // local files, and all owned by the same person
    struct passwd *myself = getpwuid( geteuid() );
    if ( myself != 0L )
    {
      isMyFile = (strOwner == QString::fromLocal8Bit(myself->pw_name));
    } else
      kdWarning() << "I don't exist ?! geteuid=" << geteuid() << endl;
  } else {
    //We don't know, for remote files, if they are ours or not.
    //So we let the user change permissions, and
    //KIO::chmod will tell, if he had no right to do it.
    isMyFile = true;
  }

  d->m_frame = properties->dialog()->addPage(i18n("&Permissions"));

  QBoxLayout *box = new QVBoxLayout( d->m_frame, KDialog::spacingHint() );

  QLabel *l, *cl[3];
  QGroupBox *gb;
  QGridLayout *gl;

  /* Group: Access Permissions */
  gb = new QGroupBox ( i18n("Access Permissions"), d->m_frame );
  box->addWidget (gb);

  gl = new QGridLayout (gb, 6, 6, 15);
  gl->addRowSpacing(0, 10);

  l = new QLabel(i18n("Class"), gb);
  gl->addWidget(l, 1, 0);

  if (isDir)
    l = new QLabel( i18n("Show\nEntries"), gb );
  else
    l = new QLabel( i18n("Read"), gb );
  gl->addWidget (l, 1, 1);

  if (isDir)
    l = new QLabel( i18n("Write\nEntries"), gb );
  else
    l = new QLabel( i18n("Write"), gb );
  gl->addWidget (l, 1, 2);

  if (isDir)
    l = new QLabel( i18n("Enter directory", "Enter"), gb );
  else
    l = new QLabel( i18n("Exec"), gb );
  // GJ: Add space between normal and special modes
  QSize size = l->sizeHint();
  size.setWidth(size.width() + 15);
  l->setFixedSize(size);
  gl->addWidget (l, 1, 3);

  l = new QLabel( i18n("Special"), gb );
  gl->addMultiCellWidget(l, 1, 1, 4, 5);

  cl[0] = new QLabel( i18n("User"), gb );
  gl->addWidget (cl[0], 2, 0);

  cl[1] = new QLabel( i18n("Group"), gb );
  gl->addWidget (cl[1], 3, 0);

  cl[2] = new QLabel( i18n("Others"), gb );
  gl->addWidget (cl[2], 4, 0);

  l = new QLabel(i18n("Set UID"), gb);
  gl->addWidget(l, 2, 5);

  l = new QLabel(i18n("Set GID"), gb);
  gl->addWidget(l, 3, 5);

  l = new QLabel(i18n("File permission, sets user or group ID on execution", "Sticky"), gb);
  gl->addWidget(l, 4, 5);

  bool enablePage = (isMyFile || IamRoot) && (!isLink);
  /* Draw Checkboxes */
  for (int row = 0; row < 3 ; ++row) {
    for (int col = 0; col < 4; ++col) {
      QCheckBox *cb = new QCheckBox(gb);
      cb->setChecked(permissions & fperm[row][col]);
      if ( d->partialPermissions & fperm[row][col] )
      {
        cb->setTristate( true );
        cb->setNoChange();
      }
      cb->setEnabled( enablePage );
      permBox[row][col] = cb;
      gl->addWidget (permBox[row][col], row+2, col+1);
      connect( cb, SIGNAL( clicked() ),
               this, SIGNAL( changed() ) );
    }
  }
  gl->setColStretch(6, 10);
  gb->setEnabled( enablePage );

  /**** Group: Ownership ****/
  gb = new QGroupBox ( i18n("Ownership"), d->m_frame );
  box->addWidget (gb);

  gl = new QGridLayout (gb, 4, 3, 15);
  gl->addRowSpacing(0, 10);

  /*** Set Owner ***/
  l = new QLabel( i18n("User:"), gb );
  gl->addWidget (l, 1, 0);

  /* GJ: Don't autocomplete more than 1000 users. This is a kind of random
   * value. Huge sites having 10.000+ user have a fair chance of using NIS,
   * (possibly) making this unacceptably slow.
   * OTOH, it is nice to offer this functionality for the standard user.
   */
  int i, maxEntries = 1000;
  struct passwd *user;
  struct group *ge;

  /* File owner: For root, offer a KLineEdit with autocompletion.
   * For a user, who can never chown() a file, offer a QLabel.
   */
  if (IamRoot && isLocal)
  {
    usrEdit = new KLineEdit( gb );
    KCompletion *kcom = usrEdit->completionObject();
    kcom->setOrder(KCompletion::Sorted);
    setpwent();
    for (i=0; ((user = getpwent()) != 0L) && (i < maxEntries); i++)
      kcom->addItem(QString::fromLatin1(user->pw_name));
    endpwent();
    usrEdit->setCompletionMode((i < maxEntries) ? KGlobalSettings::CompletionAuto :
                               KGlobalSettings::CompletionNone);
    usrEdit->setText(strOwner);
    gl->addWidget(usrEdit, 1, 1);
    connect( usrEdit, SIGNAL( textChanged( const QString & ) ),
             this, SIGNAL( changed() ) );
  }
  else
  {
    l = new QLabel(strOwner, gb);
    gl->addWidget(l, 1, 1);
  }

  /*** Set Group ***/

  QStringList groupList;
  QCString strUser;
  user = getpwuid(geteuid());
  if (user != 0L)
    strUser = user->pw_name;

  setgrent();
  for (i=0; ((ge = getgrent()) != 0L) && (i < maxEntries); i++)
  {
    if (IamRoot)
      groupList += QString::fromLatin1(ge->gr_name);
    else
    {
      /* pick the groups to which the user belongs */
      char ** members = ge->gr_mem;
      char * member;
      while ((member = *members) != 0L) {
        if (strUser == member) {
          groupList += QString::fromLocal8Bit(ge->gr_name);
          break;
        }
        ++members;
      }
    }
  }
  endgrent();

  /* add the effective Group to the list .. */
  ge = getgrgid (getegid());
  if (ge) {
    QString name = QString::fromLatin1(ge->gr_name);
    if (name.isEmpty())
      name.setNum(ge->gr_gid);
    if (groupList.find(name) == groupList.end())
      groupList += name;
  }

  bool isMyGroup = groupList.contains(strGroup);

  /* add the group the file currently belongs to ..
   * .. if its not there already
   */
  if (!isMyGroup)
    groupList += strGroup;

  l = new QLabel( i18n("Group:"), gb );
  gl->addWidget (l, 2, 0);

  /* Set group: if possible to change:
   * - Offer a KLineEdit for root, since he can change to any group.
   * - Offer a QComboBox for a normal user, since he can change to a fixed
   *   (small) set of groups only.
   * If not changeable: offer a QLabel.
   */
  if (IamRoot && isLocal)
  {
    grpEdit = new KLineEdit(gb);
    KCompletion *kcom = new KCompletion;
    kcom->setItems(groupList);
    grpEdit->setCompletionObject(kcom, true);
    grpEdit->setAutoDeleteCompletionObject( true );
    grpEdit->setCompletionMode(KGlobalSettings::CompletionAuto);
    grpEdit->setText(strGroup);
    gl->addWidget(grpEdit, 2, 1);
    connect( grpEdit, SIGNAL( textChanged( const QString & ) ),
             this, SIGNAL( changed() ) );
  }
  else if ((groupList.count() > 1) && isMyFile && isLocal)
  {
    grpCombo = new QComboBox(gb, "combogrouplist");
    grpCombo->insertStringList(groupList);
    grpCombo->setCurrentItem(groupList.findIndex(strGroup));
    gl->addWidget(grpCombo, 2, 1);
    connect( grpCombo, SIGNAL( activated( int ) ),
             this, SIGNAL( changed() ) );
  }
  else
  {
    l = new QLabel(strGroup, gb);
    gl->addWidget(l, 2, 1);
  }

  gl->setColStretch(2, 10);

  // "Apply recursive" checkbox
  if ( hasDir )
  {
      d->cbRecursive = new QCheckBox( i18n("Apply changes to all subdirectories and their contents"), d->m_frame );
      box->addWidget( d->cbRecursive );
      connect( d->cbRecursive, SIGNAL( clicked() ),
               this, SLOT( slotRecursiveClicked() ) );
  }

  box->addStretch (10);

  if (isMyFile)
    cl[0]->setText(i18n("<b>User</b>"));
  else if (isMyGroup)
    cl[1]->setText(i18n("<b>Group</b>"));
  else
    cl[2]->setText(i18n("<b>Others</b>"));
}

// QString KBearFilePermissionsPropsPlugin::tabName () const
// {
//   return i18n ("&Permissions");
// }

KBearFilePermissionsPropsPlugin::~KBearFilePermissionsPropsPlugin()
{
  delete d;
}

01431 bool KBearFilePermissionsPropsPlugin::supports( KFileItemList /*_items*/ )
{
  return true;
}

void KBearFilePermissionsPropsPlugin::slotRecursiveClicked()
{
  // If we want to apply permissions recursively, then we didn't
  // show up the right permissions to start with. Files in subdirs might
  // have other flags.... At least, let the user the possibility
  // to set any flag to "unchanged", so that he isn't forced to set +x
  // on all files !
  for (int row = 0;row < 3; ++row)
    for (int col = 0; col < 4; ++col)
      permBox[row][col]->setTristate();
}

01448 void KBearFilePermissionsPropsPlugin::applyChanges()
{
  mode_t newPermission = 0;
  mode_t newPartialPermission = 0;
  mode_t permissionMask = 0;
  for (int row = 0;row < 3; ++row)
    for (int col = 0; col < 4; ++col)
    {
      switch (permBox[row][col]->state())
      {
          case QCheckBox::On:
            newPermission |= fperm[row][col];
            //fall through
          case QCheckBox::Off:
            permissionMask |= fperm[row][col];
            break;
          default: // NoChange
          newPartialPermission |= fperm[ row ][ col ];
            break;
      }
    }

  QString owner, group;
  if (usrEdit)
    owner = usrEdit->text();
  if (grpEdit)
    group = grpEdit->text();
  else if (grpCombo)
    group = grpCombo->currentText();

  if (owner == strOwner)
      owner = QString::null; // no change

  if (group == strGroup)
      group = QString::null;

  kdDebug() << "old permissions : " << QString::number(permissions,8) << endl;
  kdDebug() << "new permissions : " << QString::number(newPermission,8) << endl;
  kdDebug() << "permissions mask : " << QString::number(permissionMask,8) << endl;
  kdDebug() << "url=" << properties->items().first()->url().url() << endl;

  if ( permissions != newPermission || d->partialPermissions != newPartialPermission
              || !owner.isEmpty() || !group.isEmpty() )
  {
    KIO::Job * job = KBearChmodJob::chmod( m_ID, properties->items(), newPermission, permissionMask,
                                 owner, group,
                                 d->cbRecursive && d->cbRecursive->isChecked(), false );
      connect( job, SIGNAL( result( KIO::Job * ) ),
             SLOT( slotChmodResult( KIO::Job * ) ) );
      connect( job, SIGNAL( infoMessage( KIO::Job*, const QString& ) ),
             this, SLOT( slotInfoMessage( KIO::Job*, const QString& ) ) );
    // Wait for job
    QWidget dummy(0,0,WType_Dialog|WShowModal);
    qt_enter_modal(&dummy);
    qApp->enter_loop();
    qt_leave_modal(&dummy);
  }
}

void KBearFilePermissionsPropsPlugin::slotChmodResult( KIO::Job * job )
{
  kdDebug() << "KBearFilePermissionsPropsPlugin::slotChmodResult" << endl;
  if (job->error())
    job->showErrorDialog( d->m_frame );
  // allow apply() to return
  qApp->exit_loop();
}


Generated by  Doxygen 1.6.0   Back to index