• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KIO

kacleditwidget.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Sean Harmer <sh@rama.homelinux.org>             *
00003  *                 2005 - 2007 Till Adam <adam@kde.org>                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Library General Public License as       *
00007  *   published by  the Free Software Foundation; either version 2 of the   *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
00019  ***************************************************************************/
00020 
00021 #include "kacleditwidget.h"
00022 #include "kacleditwidget_p.h"
00023 
00024 #include <config-acl.h>
00025 #ifdef HAVE_POSIX_ACL
00026 
00027 #include <qpainter.h>
00028 #include <qpushbutton.h>
00029 #include <QButtonGroup>
00030 #include <QGroupBox>
00031 #include <qradiobutton.h>
00032 #include <qcombobox.h>
00033 #include <qlabel.h>
00034 #include <qcheckbox.h>
00035 #include <qlayout.h>
00036 #include <QStackedWidget>
00037 #include <QMouseEvent>
00038 #include <QHeaderView>
00039 
00040 #include <klocale.h>
00041 #include <kfileitem.h>
00042 #include <kdebug.h>
00043 #include <kdialog.h>
00044 #include <kvbox.h>
00045 #include <khbox.h>
00046 
00047 #ifdef HAVE_ACL_LIBACL_H
00048 # include <acl/libacl.h>
00049 #endif
00050 extern "C" {
00051 #include <pwd.h>
00052 #include <grp.h>
00053 }
00054 #include <assert.h>
00055 
00056 static struct {
00057     const char* label;
00058     const char* pixmapName;
00059     QPixmap* pixmap;
00060 } s_itemAttributes[] = {
00061     { I18N_NOOP( "Owner" ), "user-grey", 0 },
00062     { I18N_NOOP( "Owning Group" ), "group-grey", 0 },
00063     { I18N_NOOP( "Others" ), "others-grey", 0 },
00064     { I18N_NOOP( "Mask" ), "mask", 0 },
00065     { I18N_NOOP( "Named User" ), "user", 0 },
00066     { I18N_NOOP( "Named Group" ), "group", 0 },
00067 };
00068 
00069 class KACLEditWidget::KACLEditWidgetPrivate
00070 {
00071 public:
00072     KACLEditWidgetPrivate()
00073     {
00074     }
00075 
00076     // slots
00077     void _k_slotUpdateButtons();
00078 
00079     KACLListView *m_listView;
00080     QPushButton *m_AddBtn;
00081     QPushButton *m_EditBtn;
00082     QPushButton *m_DelBtn;
00083 };
00084 
00085 KACLEditWidget::KACLEditWidget( QWidget *parent )
00086     : QWidget(parent), d(new KACLEditWidgetPrivate)
00087 {
00088     QHBoxLayout *hbox = new QHBoxLayout( this );
00089     hbox->setMargin( 0 );
00090     d->m_listView = new KACLListView(this);
00091     hbox->addWidget(d->m_listView);
00092     connect(d->m_listView->selectionModel(),
00093             SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection& )),
00094             this,
00095             SLOT(_k_slotUpdateButtons()));
00096     QVBoxLayout *vbox = new QVBoxLayout();
00097     hbox->addLayout( vbox );
00098     d->m_AddBtn = new QPushButton(i18n("Add Entry..."), this);
00099     vbox->addWidget(d->m_AddBtn);
00100     d->m_AddBtn->setObjectName(QLatin1String("add_entry_button"));
00101     connect(d->m_AddBtn, SIGNAL(clicked()), d->m_listView, SLOT(slotAddEntry()));
00102     d->m_EditBtn = new QPushButton(i18n("Edit Entry..."), this);
00103     vbox->addWidget(d->m_EditBtn);
00104     d->m_EditBtn->setObjectName(QLatin1String("edit_entry_button"));
00105     connect(d->m_EditBtn, SIGNAL(clicked()), d->m_listView, SLOT(slotEditEntry()));
00106     d->m_DelBtn = new QPushButton(i18n("Delete Entry"), this);
00107     vbox->addWidget(d->m_DelBtn);
00108     d->m_DelBtn->setObjectName(QLatin1String("delete_entry_button"));
00109     connect(d->m_DelBtn, SIGNAL(clicked()), d->m_listView, SLOT(slotRemoveEntry()));
00110     vbox->addItem( new QSpacerItem( 10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
00111     d->_k_slotUpdateButtons();
00112 }
00113 
00114 KACLEditWidget::~KACLEditWidget()
00115 {
00116     delete d;
00117 }
00118 
00119 void KACLEditWidget::KACLEditWidgetPrivate::_k_slotUpdateButtons()
00120 {
00121     bool atLeastOneIsNotDeletable = false;
00122     bool atLeastOneIsNotAllowedToChangeType = false;
00123     int selectedCount = 0;
00124     QList<QTreeWidgetItem*> selected = m_listView->selectedItems();
00125     QListIterator<QTreeWidgetItem*> it( selected );
00126     while ( it.hasNext() ) {
00127         KACLListViewItem *item = static_cast<KACLListViewItem*>( it.next() );
00128         ++selectedCount;
00129         if ( !item->isDeletable() )
00130             atLeastOneIsNotDeletable = true;
00131         if ( !item->isAllowedToChangeType() )
00132             atLeastOneIsNotAllowedToChangeType = true;
00133     }
00134     m_EditBtn->setEnabled( selectedCount && !atLeastOneIsNotAllowedToChangeType );
00135     m_DelBtn->setEnabled( selectedCount && !atLeastOneIsNotDeletable );
00136 }
00137 
00138 KACL KACLEditWidget::getACL() const
00139 {
00140     return d->m_listView->getACL();
00141 }
00142 
00143 KACL KACLEditWidget::getDefaultACL() const
00144 {
00145     return d->m_listView->getDefaultACL();
00146 }
00147 
00148 void KACLEditWidget::setACL( const KACL &acl )
00149 {
00150     return d->m_listView->setACL(acl);
00151 }
00152 
00153 void KACLEditWidget::setDefaultACL( const KACL &acl )
00154 {
00155     return d->m_listView->setDefaultACL(acl);
00156 }
00157 
00158 void KACLEditWidget::setAllowDefaults( bool value )
00159 {
00160     d->m_listView->setAllowDefaults(value);
00161 }
00162 
00163 KACLListViewItem::KACLListViewItem( QTreeWidget* parent,
00164                                     KACLListView::EntryType _type,
00165                                     unsigned short _value, bool defaults,
00166                                     const QString& _qualifier )
00167  : QTreeWidgetItem( parent),
00168    type( _type ), value( _value ), isDefault( defaults ),
00169    qualifier( _qualifier ), isPartial( false )
00170 {
00171     m_pACLListView = qobject_cast<KACLListView*>( parent );
00172     repaint();
00173 }
00174 
00175 
00176 KACLListViewItem::~ KACLListViewItem()
00177 {
00178 
00179 }
00180 
00181 QString KACLListViewItem::key() const
00182 {
00183     QString key;
00184     if ( !isDefault )
00185         key = 'A';
00186     else
00187         key = 'B';
00188     switch ( type )
00189     {
00190         case KACLListView::User:
00191             key += 'A';
00192             break;
00193         case KACLListView::Group:
00194             key += 'B';
00195             break;
00196         case KACLListView::Others:
00197             key += 'C';
00198             break;
00199         case KACLListView::Mask:
00200             key += 'D';
00201             break;
00202         case KACLListView::NamedUser:
00203             key += 'E' + text( 1 );
00204             break;
00205         case KACLListView::NamedGroup:
00206             key += 'F' + text( 1 );
00207             break;
00208         default:
00209             key += text( 0 );
00210             break;
00211     }
00212     return key;
00213 }
00214 
00215 bool KACLListViewItem::operator< ( const QTreeWidgetItem& other ) const
00216 {
00217     return key() < static_cast<const KACLListViewItem&>(other).key();
00218 }
00219 
00220 #if 0
00221 void KACLListViewItem::paintCell( QPainter* p, const QColorGroup &cg,
00222                                   int column, int width, int alignment )
00223 {
00224     if ( isDefault ) {
00225         setForeground( QColor( 0, 0, 255 ) );
00226     }
00227     if ( isPartial ) {
00228         QFont font = p->font();
00229         font.setItalic( true );
00230         setForeground( QColor( 100, 100, 100 ) );
00231         p->setFont( font );
00232     }
00233     QTreeWidgetItem::paintCell( p, mycg, column, width, alignment );
00234 
00235     KACLListViewItem *below =0;
00236     if ( itemBelow() )
00237         below = static_cast<KACLListViewItem*>( itemBelow() );
00238     const bool lastUser = type == KACLListView::NamedUser && below && below->type == KACLListView::NamedGroup;
00239     const bool lastNonDefault = !isDefault && below && below->isDefault;
00240     if ( type == KACLListView::Mask || lastUser || lastNonDefault )
00241     {
00242         p->setPen( QPen( Qt::gray, 0, Qt::DotLine ) );
00243         if ( type == KACLListView::Mask )
00244             p->drawLine( 0, 0, width - 1, 0 );
00245         p->drawLine( 0, height() - 1, width - 1, height() - 1 );
00246     }
00247 }
00248 #endif
00249 
00250 
00251 void KACLListViewItem::updatePermPixmaps()
00252 {
00253     unsigned int partialPerms = value;
00254 
00255     if ( value & ACL_READ )
00256         setIcon( 2, m_pACLListView->getYesPixmap() );
00257     else if ( partialPerms & ACL_READ )
00258         setIcon( 2, m_pACLListView->getYesPartialPixmap() );
00259     else
00260         setIcon( 2, QIcon() );
00261 
00262     if ( value & ACL_WRITE )
00263         setIcon( 3, m_pACLListView->getYesPixmap() );
00264     else if ( partialPerms & ACL_WRITE )
00265         setIcon( 3, m_pACLListView->getYesPartialPixmap() );
00266     else
00267         setIcon( 3, QIcon() );
00268 
00269     if ( value & ACL_EXECUTE )
00270         setIcon( 4, m_pACLListView->getYesPixmap() );
00271     else if ( partialPerms & ACL_EXECUTE )
00272         setIcon( 4, m_pACLListView->getYesPartialPixmap() );
00273     else
00274         setIcon( 4, QIcon() );
00275 }
00276 
00277 void KACLListViewItem::repaint()
00278 {
00279     int idx = 0;
00280     switch ( type )
00281     {
00282       case KACLListView::User:
00283           idx = KACLListView::OWNER_IDX;
00284             break;
00285         case KACLListView::Group:
00286           idx = KACLListView::GROUP_IDX;
00287             break;
00288         case KACLListView::Others:
00289           idx = KACLListView::OTHERS_IDX;
00290             break;
00291         case KACLListView::Mask:
00292           idx = KACLListView::MASK_IDX;
00293             break;
00294         case KACLListView::NamedUser:
00295           idx = KACLListView::NAMED_USER_IDX;
00296             break;
00297         case KACLListView::NamedGroup:
00298           idx = KACLListView::NAMED_GROUP_IDX;
00299             break;
00300         default:
00301           idx = KACLListView::OWNER_IDX;
00302             break;
00303     }
00304     setText( 0, i18n(s_itemAttributes[idx].label) );
00305     setIcon( 0, *s_itemAttributes[idx].pixmap );
00306     if ( isDefault )
00307         setText( 0, text( 0 ) + i18n( " (Default)" ) );
00308     setText( 1, qualifier );
00309     // Set the pixmaps for which of the perms are set
00310     updatePermPixmaps();
00311 }
00312 
00313 void KACLListViewItem::calcEffectiveRights()
00314 {
00315     QString strEffective = QString( "---" );
00316 
00317     // Do we need to worry about the mask entry? It applies to named users,
00318     // owning group, and named groups
00319     if ( m_pACLListView->hasMaskEntry()
00320             && ( type == KACLListView::NamedUser
00321               || type == KACLListView::Group
00322               || type == KACLListView::NamedGroup )
00323             && !isDefault )
00324     {
00325 
00326         strEffective[0] = ( m_pACLListView->maskPermissions() & value & ACL_READ ) ? 'r' : '-';
00327         strEffective[1] = ( m_pACLListView->maskPermissions() & value & ACL_WRITE ) ? 'w' : '-';
00328         strEffective[2] = ( m_pACLListView->maskPermissions() & value & ACL_EXECUTE ) ? 'x' : '-';
00329 /*
00330         // What about any partial perms?
00331         if ( maskPerms & partialPerms & ACL_READ || // Partial perms on entry
00332              maskPartialPerms & perms & ACL_READ || // Partial perms on mask
00333              maskPartialPerms & partialPerms & ACL_READ ) // Partial perms on mask and entry
00334             strEffective[0] = 'R';
00335         if ( maskPerms & partialPerms & ACL_WRITE || // Partial perms on entry
00336              maskPartialPerms & perms & ACL_WRITE || // Partial perms on mask
00337              maskPartialPerms & partialPerms & ACL_WRITE ) // Partial perms on mask and entry
00338             strEffective[1] = 'W';
00339         if ( maskPerms & partialPerms & ACL_EXECUTE || // Partial perms on entry
00340              maskPartialPerms & perms & ACL_EXECUTE || // Partial perms on mask
00341              maskPartialPerms & partialPerms & ACL_EXECUTE ) // Partial perms on mask and entry
00342             strEffective[2] = 'X';
00343 */
00344     }
00345     else
00346     {
00347         // No, the effective value are just the value in this entry
00348         strEffective[0] = ( value & ACL_READ ) ? 'r' : '-';
00349         strEffective[1] = ( value & ACL_WRITE ) ? 'w' : '-';
00350         strEffective[2] = ( value & ACL_EXECUTE ) ? 'x' : '-';
00351 
00352         /*
00353         // What about any partial perms?
00354         if ( partialPerms & ACL_READ )
00355             strEffective[0] = 'R';
00356         if ( partialPerms & ACL_WRITE )
00357             strEffective[1] = 'W';
00358         if ( partialPerms & ACL_EXECUTE )
00359             strEffective[2] = 'X';
00360             */
00361     }
00362     setText( 5, strEffective );
00363 }
00364 
00365 bool KACLListViewItem::isDeletable() const
00366 {
00367     bool isMaskAndDeletable = false;
00368     if (type == KACLListView::Mask ) {
00369         if ( !isDefault &&  m_pACLListView->maskCanBeDeleted() )
00370             isMaskAndDeletable = true;
00371         else if ( isDefault &&  m_pACLListView->defaultMaskCanBeDeleted() )
00372             isMaskAndDeletable = true;
00373     }
00374     return type != KACLListView::User &&
00375            type != KACLListView::Group &&
00376            type != KACLListView::Others &&
00377            ( type != KACLListView::Mask || isMaskAndDeletable );
00378 }
00379 
00380 bool KACLListViewItem::isAllowedToChangeType() const
00381 {
00382     return type != KACLListView::User &&
00383            type != KACLListView::Group &&
00384            type != KACLListView::Others &&
00385            type != KACLListView::Mask;
00386 }
00387 
00388 void KACLListViewItem::togglePerm( acl_perm_t perm )
00389 {
00390     value ^= perm; // Toggle the perm
00391     if ( type == KACLListView::Mask && !isDefault ) {
00392         m_pACLListView->setMaskPermissions( value );
00393     }
00394     calcEffectiveRights();
00395     updatePermPixmaps();
00396 /*
00397     // If the perm is in the partial perms then remove it. i.e. Once
00398     // a user changes a partial perm it then applies to all selected files.
00399     if ( m_pEntry->m_partialPerms & perm )
00400         m_pEntry->m_partialPerms ^= perm;
00401 
00402     m_pEntry->setPartialEntry( false );
00403     // Make sure that all entries have their effective rights calculated if
00404     // we are changing the ACL_MASK entry.
00405     if ( type == Mask )
00406     {
00407         m_pACLListView->setMaskPartialPermissions( m_pEntry->m_partialPerms );
00408         m_pACLListView->setMaskPermissions( value );
00409         m_pACLListView->calculateEffectiveRights();
00410     }
00411 */
00412 }
00413 
00414 
00415 
00416 EditACLEntryDialog::EditACLEntryDialog( KACLListView *listView, KACLListViewItem *item,
00417                                         const QStringList &users,
00418                                         const QStringList &groups,
00419                                         const QStringList &defaultUsers,
00420                                         const QStringList &defaultGroups,
00421                                         int allowedTypes, int allowedDefaultTypes,
00422                                         bool allowDefaults )
00423       : KDialog( listView ),
00424         m_listView( listView ), m_item( item ), m_users( users ), m_groups( groups ),
00425         m_defaultUsers( defaultUsers ), m_defaultGroups( defaultGroups ),
00426         m_allowedTypes( allowedTypes ), m_allowedDefaultTypes( allowedDefaultTypes ),
00427         m_defaultCB( 0 )
00428 {
00429     setObjectName( "edit_entry_dialog" );
00430     setModal( true );
00431     setCaption( i18n( "Edit ACL Entry" ) );
00432     setButtons( KDialog::Ok | KDialog::Cancel );
00433     setDefaultButton( KDialog::Ok );
00434 
00435     QWidget *page = new QWidget(  this );
00436     setMainWidget( page );
00437     QVBoxLayout *mainLayout = new QVBoxLayout( page );
00438     mainLayout->setMargin( 0 );
00439     QGroupBox *gb = new QGroupBox( i18n("Entry Type"), page );
00440     QVBoxLayout *gbLayout = new QVBoxLayout( gb );
00441 
00442     m_buttonGroup = new QButtonGroup( page );
00443 
00444     if ( allowDefaults ) {
00445         m_defaultCB = new QCheckBox( i18n("Default for new files in this folder"), page );
00446         m_defaultCB->setObjectName( QLatin1String( "defaultCB" ) );
00447         mainLayout->addWidget( m_defaultCB );
00448         connect( m_defaultCB, SIGNAL( toggled( bool ) ),
00449                  this, SLOT( slotUpdateAllowedUsersAndGroups() ) );
00450         connect( m_defaultCB, SIGNAL( toggled( bool ) ),
00451                  this, SLOT( slotUpdateAllowedTypes() ) );
00452     }
00453 
00454     QRadioButton *ownerType = new QRadioButton( i18n("Owner"), gb );
00455     ownerType->setObjectName( QLatin1String( "ownerType" ) );
00456     gbLayout->addWidget( ownerType );
00457     m_buttonGroup->addButton( ownerType );
00458     m_buttonIds.insert( ownerType, KACLListView::User );
00459     QRadioButton *owningGroupType = new QRadioButton( i18n("Owning Group"), gb );
00460     owningGroupType->setObjectName( QLatin1String( "owningGroupType" ) );
00461     gbLayout->addWidget( owningGroupType );
00462     m_buttonGroup->addButton( owningGroupType );
00463     m_buttonIds.insert( owningGroupType, KACLListView::Group );
00464     QRadioButton *othersType = new QRadioButton( i18n("Others"), gb );
00465     othersType->setObjectName( QLatin1String( "othersType" ) );
00466     gbLayout->addWidget( othersType );
00467     m_buttonGroup->addButton( othersType );
00468     m_buttonIds.insert( othersType, KACLListView::Others );
00469     QRadioButton *maskType = new QRadioButton( i18n("Mask"), gb );
00470     maskType->setObjectName( QLatin1String( "maskType" ) );
00471     gbLayout->addWidget( maskType );
00472     m_buttonGroup->addButton( maskType );
00473     m_buttonIds.insert( maskType, KACLListView::Mask );
00474     QRadioButton *namedUserType = new QRadioButton( i18n("Named user"), gb );
00475     namedUserType->setObjectName( QLatin1String( "namesUserType" ) );
00476     gbLayout->addWidget( namedUserType );
00477     m_buttonGroup->addButton( namedUserType );
00478     m_buttonIds.insert( namedUserType, KACLListView::NamedUser );
00479     QRadioButton *namedGroupType = new QRadioButton( i18n("Named group"), gb );
00480     namedGroupType->setObjectName( QLatin1String( "namedGroupType" ) );
00481     gbLayout->addWidget( namedGroupType );
00482     m_buttonGroup->addButton( namedGroupType );
00483     m_buttonIds.insert( namedGroupType, KACLListView::NamedGroup );
00484 
00485     mainLayout->addWidget( gb );
00486 
00487     connect( m_buttonGroup, SIGNAL( buttonClicked( QAbstractButton* ) ),
00488              this, SLOT( slotSelectionChanged( QAbstractButton * ) ) );
00489 
00490     m_widgetStack = new QStackedWidget( page );
00491     mainLayout->addWidget( m_widgetStack );
00492 
00493     KHBox *usersBox = new KHBox( m_widgetStack );
00494     m_widgetStack->addWidget( usersBox );
00495 
00496     KHBox *groupsBox = new KHBox( m_widgetStack );
00497     m_widgetStack->addWidget( groupsBox );
00498 
00499     QLabel *usersLabel = new QLabel( i18n( "User: " ), usersBox );
00500     m_usersCombo = new KComboBox( usersBox );
00501     m_usersCombo->setEditable( false );
00502     m_usersCombo->setObjectName( QLatin1String( "users" ) );
00503     usersLabel->setBuddy( m_usersCombo );
00504 
00505     QLabel *groupsLabel = new QLabel( i18n( "Group: " ), groupsBox );
00506     m_groupsCombo = new KComboBox( groupsBox );
00507     m_groupsCombo->setEditable( false );
00508     m_groupsCombo->setObjectName( QLatin1String( "groups" ) );
00509     groupsLabel->setBuddy( m_groupsCombo );
00510 
00511     if ( m_item ) {
00512         m_buttonIds.key( m_item->type )->setChecked( true );
00513         if ( m_defaultCB )
00514             m_defaultCB->setChecked( m_item->isDefault );
00515         slotUpdateAllowedTypes();
00516         slotSelectionChanged( m_buttonIds.key( m_item->type ) );
00517         slotUpdateAllowedUsersAndGroups();
00518         if ( m_item->type == KACLListView::NamedUser ) {
00519             m_usersCombo->setItemText( m_usersCombo->currentIndex(), m_item->qualifier );
00520         } else if ( m_item->type == KACLListView::NamedGroup ) {
00521             m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), m_item->qualifier );
00522         }
00523     } else {
00524         // new entry, preselect "named user", arguably the most common one
00525         m_buttonIds.key( KACLListView::NamedUser )->setChecked( true );
00526         slotUpdateAllowedTypes();
00527         slotSelectionChanged( m_buttonIds.key( KACLListView::NamedUser ) );
00528         slotUpdateAllowedUsersAndGroups();
00529     }
00530     incrementInitialSize(  QSize( 100, 0 ) );
00531     connect(this,SIGNAL(okClicked()), this, SLOT(slotOk()));
00532 }
00533 
00534 void EditACLEntryDialog::slotUpdateAllowedTypes()
00535 {
00536     int allowedTypes = m_allowedTypes;
00537     if ( m_defaultCB && m_defaultCB->isChecked() ) {
00538         allowedTypes = m_allowedDefaultTypes;
00539     }
00540     for ( int i=1; i < KACLListView::AllTypes; i=i*2 ) {
00541         if ( allowedTypes & i )
00542             m_buttonIds.key( i )->show();
00543         else
00544             m_buttonIds.key( i )->hide();
00545     }
00546 }
00547 
00548 void EditACLEntryDialog::slotUpdateAllowedUsersAndGroups()
00549 {
00550     const QString oldUser = m_usersCombo->currentText();
00551     const QString oldGroup = m_groupsCombo->currentText();
00552     m_usersCombo->clear();
00553     m_groupsCombo->clear();
00554     if ( m_defaultCB && m_defaultCB->isChecked() ) {
00555         m_usersCombo->addItems( m_defaultUsers );
00556         if ( m_defaultUsers.contains( oldUser ) )
00557             m_usersCombo->setItemText( m_usersCombo->currentIndex(), oldUser );
00558         m_groupsCombo->addItems( m_defaultGroups );
00559         if ( m_defaultGroups.contains( oldGroup ) )
00560             m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), oldGroup );
00561     } else {
00562         m_usersCombo->addItems( m_users );
00563         if ( m_users.contains( oldUser ) )
00564             m_usersCombo->setItemText( m_usersCombo->currentIndex(), oldUser );
00565         m_groupsCombo->addItems( m_groups );
00566         if ( m_groups.contains( oldGroup ) )
00567             m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), oldGroup );
00568     }
00569 }
00570 void EditACLEntryDialog::slotOk()
00571 {
00572     KACLListView::EntryType type = static_cast<KACLListView::EntryType>( m_buttonIds[m_buttonGroup->checkedButton()] );
00573 
00574     kWarning() << "Type 2: " << type;
00575 
00576     QString qualifier;
00577     if ( type == KACLListView::NamedUser )
00578       qualifier = m_usersCombo->currentText();
00579     if ( type == KACLListView::NamedGroup )
00580       qualifier = m_groupsCombo->currentText();
00581 
00582     if ( !m_item ) {
00583         m_item = new KACLListViewItem( m_listView, type, ACL_READ | ACL_WRITE | ACL_EXECUTE, false, qualifier );
00584     } else {
00585         m_item->type = type;
00586         m_item->qualifier = qualifier;
00587     }
00588     if ( m_defaultCB )
00589         m_item->isDefault = m_defaultCB->isChecked();
00590     m_item->repaint();
00591 
00592     KDialog::accept();
00593 }
00594 
00595 void EditACLEntryDialog::slotSelectionChanged( QAbstractButton *button )
00596 {
00597     switch ( m_buttonIds[ button ] ) {
00598         case KACLListView::User:
00599         case KACLListView::Group:
00600         case KACLListView::Others:
00601         case KACLListView::Mask:
00602             m_widgetStack->setEnabled( false );
00603             break;
00604         case KACLListView::NamedUser:
00605             m_widgetStack->setEnabled( true );
00606             m_widgetStack->setCurrentIndex( 0 /* User */ );
00607             break;
00608         case KACLListView::NamedGroup:
00609             m_widgetStack->setEnabled( true );
00610             m_widgetStack->setCurrentIndex( 1 /* Group */ );
00611             break;
00612         default:
00613             break;
00614     }
00615 }
00616 
00617 
00618 KACLListView::KACLListView( QWidget* parent )
00619  : QTreeWidget( parent ),
00620    m_hasMask( false ), m_allowDefaults( false )
00621 {
00622     // Add the columns
00623     setColumnCount( 6 );
00624     QStringList headers;
00625     headers <<  i18n( "Type" );
00626     headers <<  i18n( "Name" );
00627     headers <<  i18nc( "read permission", "r" );
00628     headers <<  i18nc( "write permission", "w" );
00629     headers <<  i18nc( "execute permission", "x" );
00630     headers <<  i18n( "Effective" );
00631     setHeaderLabels( headers );
00632 
00633     setSortingEnabled( false );
00634     setSelectionMode( QAbstractItemView::ExtendedSelection );
00635     header()->setResizeMode( QHeaderView::ResizeToContents );
00636     setRootIsDecorated( false );
00637 
00638     // Load the avatars
00639     for ( int i=0; i < LAST_IDX; ++i ) {
00640         s_itemAttributes[i].pixmap = new QPixmap( QString::fromLatin1(":/images/%1").arg(s_itemAttributes[i].pixmapName) );
00641     }
00642     m_yesPixmap = new QPixmap( ":/images/yes.png" );
00643     m_yesPartialPixmap = new QPixmap( ":/images/yespartial.png" );
00644 
00645 
00646     // fill the lists of all legal users and groups
00647     struct passwd *user = 0;
00648     setpwent();
00649     while ( ( user = getpwent() ) != 0 ) {
00650        m_allUsers << QString::fromLatin1( user->pw_name );
00651     }
00652     endpwent();
00653 
00654     struct group *gr = 0;
00655     setgrent();
00656     while ( ( gr = getgrent() ) != 0 ) {
00657        m_allGroups << QString::fromLatin1( gr->gr_name );
00658     }
00659     endgrent();
00660     m_allUsers.sort();
00661     m_allGroups.sort();
00662 
00663     connect( this, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ),
00664              this, SLOT( slotItemClicked( QTreeWidgetItem*, int ) ) );
00665 }
00666 
00667 
00668 KACLListView::~KACLListView()
00669 {
00670     for ( int i=0; i < LAST_IDX; ++i ) {
00671        delete s_itemAttributes[i].pixmap;
00672     }
00673     delete m_yesPixmap;
00674     delete m_yesPartialPixmap;
00675 }
00676 
00677 QStringList KACLListView::allowedUsers( bool defaults, KACLListViewItem *allowedItem )
00678 {
00679     QStringList allowedUsers = m_allUsers;
00680     QTreeWidgetItemIterator it( this );
00681     while ( *it ) {
00682         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00683         ++it;
00684         if ( item->type != NamedUser || item->isDefault != defaults ) continue;
00685         if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00686         allowedUsers.removeAll( item->qualifier );
00687     }
00688     return allowedUsers;
00689 }
00690 
00691 QStringList KACLListView::allowedGroups( bool defaults, KACLListViewItem *allowedItem )
00692 {
00693     QStringList allowedGroups = m_allGroups;
00694     QTreeWidgetItemIterator it( this );
00695     while ( *it ) {
00696         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00697         ++it;
00698         if ( item->type != NamedGroup || item->isDefault != defaults ) continue;
00699         if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00700         allowedGroups.removeAll( item->qualifier );
00701     }
00702     return allowedGroups;
00703 }
00704 
00705 void KACLListView::fillItemsFromACL( const KACL &pACL, bool defaults )
00706 {
00707     // clear out old entries of that ilk
00708     QTreeWidgetItemIterator it( this );
00709     while ( KACLListViewItem *item = static_cast<KACLListViewItem*>( *it ) ) {
00710         ++it;
00711         if ( item->isDefault == defaults )
00712             delete item;
00713     }
00714     KACLListViewItem *item =
00715         new KACLListViewItem( this, User, pACL.ownerPermissions(), defaults );
00716 
00717     item = new KACLListViewItem( this, Group, pACL.owningGroupPermissions(), defaults );
00718 
00719     item = new KACLListViewItem( this, Others, pACL.othersPermissions(), defaults );
00720 
00721     bool hasMask = false;
00722     unsigned short mask = pACL.maskPermissions( hasMask );
00723     if ( hasMask ) {
00724         item = new KACLListViewItem( this, Mask, mask, defaults );
00725     }
00726 
00727     // read all named user entries
00728     const ACLUserPermissionsList &userList =  pACL.allUserPermissions();
00729     ACLUserPermissionsConstIterator itu = userList.begin();
00730     while ( itu != userList.end() ) {
00731         new KACLListViewItem( this, NamedUser, (*itu).second, defaults, (*itu).first );
00732         ++itu;
00733     }
00734 
00735     // and now all named groups
00736     const ACLUserPermissionsList &groupList =  pACL.allGroupPermissions();
00737     ACLUserPermissionsConstIterator itg = groupList.begin();
00738     while ( itg != groupList.end() ) {
00739         new KACLListViewItem( this, NamedGroup, (*itg).second, defaults, (*itg).first );
00740         ++itg;
00741     }
00742 }
00743 
00744 void KACLListView::setACL( const KACL &acl )
00745 {
00746     if ( !acl.isValid() ) return;
00747     // Remove any entries left over from displaying a previous ACL
00748     m_ACL = acl;
00749     fillItemsFromACL( m_ACL );
00750 
00751     m_mask = acl.maskPermissions( m_hasMask );
00752     calculateEffectiveRights();
00753 }
00754 
00755 void KACLListView::setDefaultACL( const KACL &acl )
00756 {
00757     if ( !acl.isValid() ) return;
00758     m_defaultACL = acl;
00759     fillItemsFromACL( m_defaultACL, true );
00760     calculateEffectiveRights();
00761 }
00762 
00763 KACL KACLListView::itemsToACL( bool defaults ) const
00764 {
00765     KACL newACL( 0 );
00766     bool atLeastOneEntry = false;
00767     ACLUserPermissionsList users;
00768     ACLGroupPermissionsList groups;
00769     QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00770     while ( QTreeWidgetItem* qlvi = *it ) {
00771         ++it;
00772         const KACLListViewItem* item = static_cast<KACLListViewItem*>( qlvi );
00773         if ( item->isDefault != defaults ) continue;
00774         atLeastOneEntry = true;
00775         switch ( item->type ) {
00776             case User:
00777                 newACL.setOwnerPermissions( item->value );
00778                 break;
00779             case Group:
00780                 newACL.setOwningGroupPermissions( item->value );
00781                 break;
00782             case Others:
00783                 newACL.setOthersPermissions( item->value );
00784                 break;
00785             case Mask:
00786                 newACL.setMaskPermissions( item->value );
00787                 break;
00788             case NamedUser:
00789                 users.append( qMakePair( item->text( 1 ), item->value ) );
00790                 break;
00791             case NamedGroup:
00792                 groups.append( qMakePair( item->text( 1 ), item->value ) );
00793                 break;
00794             default:
00795                 break;
00796         }
00797     }
00798     if ( atLeastOneEntry ) {
00799         newACL.setAllUserPermissions( users );
00800         newACL.setAllGroupPermissions( groups );
00801         if ( newACL.isValid() )
00802             return newACL;
00803     }
00804     return KACL();
00805 }
00806 
00807 KACL KACLListView::getACL()
00808 {
00809     return itemsToACL( false );
00810 }
00811 
00812 
00813 KACL KACLListView::getDefaultACL()
00814 {
00815     return itemsToACL( true );
00816 }
00817 
00818 void KACLListView::contentsMousePressEvent( QMouseEvent * e )
00819 {
00820     /*
00821     QTreeWidgetItem *clickedItem = itemAt( e->pos() );
00822     if ( !clickedItem ) return;
00823     // if the click is on an as yet unselected item, select it first
00824     if ( !clickedItem->isSelected() )
00825         QAbstractItemView::contentsMousePressEvent( e );
00826 
00827     if ( !currentItem() ) return;
00828     int column = header()->sectionAt( e->x() );
00829     acl_perm_t perm;
00830     switch ( column )
00831     {
00832         case 2:
00833             perm = ACL_READ;
00834             break;
00835         case 3:
00836             perm = ACL_WRITE;
00837             break;
00838         case 4:
00839             perm = ACL_EXECUTE;
00840             break;
00841         default:
00842             return QTreeWidget::contentsMousePressEvent( e );
00843     }
00844     KACLListViewItem* referenceItem = static_cast<KACLListViewItem*>( clickedItem );
00845     unsigned short referenceHadItSet = referenceItem->value & perm;
00846     QTreeWidgetItemIterator it( this );
00847     while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( *it ) ) {
00848         ++it;
00849         if ( !item->isSelected() ) continue;
00850         // toggle those with the same value as the clicked item, leave the others
00851         if ( referenceHadItSet == ( item->value & perm ) )
00852             item->togglePerm( perm );
00853     }
00854      */
00855 }
00856 
00857 void KACLListView::slotItemClicked( QTreeWidgetItem* pItem,  int col )
00858 {
00859     if ( !pItem ) return;
00860 
00861     QTreeWidgetItemIterator it( this );
00862     while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( *it ) ) {
00863         ++it;
00864         if ( !item->isSelected() ) continue;
00865         switch ( col )
00866         {
00867             case 2:
00868                 item->togglePerm( ACL_READ );
00869                 break;
00870             case 3:
00871                 item->togglePerm( ACL_WRITE );
00872                 break;
00873             case 4:
00874                 item->togglePerm( ACL_EXECUTE );
00875                 break;
00876 
00877             default:
00878                 ; // Do nothing
00879         }
00880     }
00881     /*
00882     // Has the user changed one of the required entries in a default ACL?
00883     if ( m_pACL->aclType() == ACL_TYPE_DEFAULT &&
00884     ( col == 2 || col == 3 || col == 4 ) &&
00885     ( pACLItem->entryType() == ACL_USER_OBJ ||
00886     pACLItem->entryType() == ACL_GROUP_OBJ ||
00887     pACLItem->entryType() == ACL_OTHER ) )
00888     {
00889     // Mark the required entries as no longer being partial entries.
00890     // That is, they will get applied to all selected directories.
00891     KACLListViewItem* pUserObj = findACLEntryByType( this, ACL_USER_OBJ );
00892     pUserObj->entry()->setPartialEntry( false );
00893 
00894     KACLListViewItem* pGroupObj = findACLEntryByType( this, ACL_GROUP_OBJ );
00895     pGroupObj->entry()->setPartialEntry( false );
00896 
00897     KACLListViewItem* pOther = findACLEntryByType( this, ACL_OTHER );
00898     pOther->entry()->setPartialEntry( false );
00899 
00900     update();
00901     }
00902      */
00903 }
00904 
00905 
00906 void KACLListView::calculateEffectiveRights()
00907 {
00908     QTreeWidgetItemIterator it( this );
00909     KACLListViewItem* pItem;
00910     while ( ( pItem = dynamic_cast<KACLListViewItem*>( *it ) ) != 0 )
00911     {
00912         ++it;
00913         pItem->calcEffectiveRights();
00914     }
00915 }
00916 
00917 
00918 unsigned short KACLListView::maskPermissions() const
00919 {
00920   return m_mask;
00921 }
00922 
00923 
00924 void KACLListView::setMaskPermissions( unsigned short maskPerms )
00925 {
00926     m_mask = maskPerms;
00927     calculateEffectiveRights();
00928 }
00929 
00930 
00931 acl_perm_t KACLListView::maskPartialPermissions() const
00932 {
00933   //  return m_pMaskEntry->m_partialPerms;
00934   return 0;
00935 }
00936 
00937 
00938 void KACLListView::setMaskPartialPermissions( acl_perm_t /*maskPartialPerms*/ )
00939 {
00940     //m_pMaskEntry->m_partialPerms = maskPartialPerms;
00941     calculateEffectiveRights();
00942 }
00943 
00944 bool KACLListView::hasDefaultEntries() const
00945 {
00946     QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00947     while ( *it ) {
00948         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00949         ++it;
00950         if ( item->isDefault ) return true;
00951     }
00952     return false;
00953 }
00954 
00955 const KACLListViewItem* KACLListView::findDefaultItemByType( EntryType type ) const
00956 {
00957     return findItemByType( type, true );
00958 }
00959 
00960 const KACLListViewItem* KACLListView::findItemByType( EntryType type, bool defaults ) const
00961 {
00962     QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00963     while ( *it ) {
00964         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00965         ++it;
00966         if ( item->isDefault == defaults && item->type == type ) {
00967             return item;
00968         }
00969     }
00970     return 0;
00971 }
00972 
00973 
00974 unsigned short KACLListView::calculateMaskValue( bool defaults ) const
00975 {
00976     // KACL auto-adds the relevant maks entries, so we can simply query
00977     bool dummy;
00978     return itemsToACL( defaults ).maskPermissions( dummy );
00979 }
00980 
00981 void KACLListView::slotAddEntry()
00982 {
00983     int allowedTypes = NamedUser | NamedGroup;
00984     if ( !m_hasMask )
00985         allowedTypes |= Mask;
00986     int allowedDefaultTypes = NamedUser | NamedGroup;
00987     if ( !findDefaultItemByType( Mask ) )
00988         allowedDefaultTypes |=  Mask;
00989     if ( !hasDefaultEntries() )
00990         allowedDefaultTypes |= User | Group;
00991     EditACLEntryDialog dlg( this, 0,
00992                             allowedUsers( false ), allowedGroups( false ),
00993                             allowedUsers( true ), allowedGroups( true ),
00994                             allowedTypes, allowedDefaultTypes, m_allowDefaults );
00995     dlg.exec();
00996     KACLListViewItem *item = dlg.item();
00997     if ( !item ) return; // canceled
00998     if ( item->type == Mask && !item->isDefault ) {
00999         m_hasMask = true;
01000         m_mask = item->value;
01001     }
01002     if ( item->isDefault && !hasDefaultEntries() ) {
01003         // first default entry, fill in what is needed
01004         if ( item->type != User ) {
01005             unsigned short v = findDefaultItemByType( User )->value;
01006             new KACLListViewItem( this, User, v, true );
01007         }
01008         if ( item->type != Group ) {
01009             unsigned short v = findDefaultItemByType( Group )->value;
01010             new KACLListViewItem( this, Group, v, true );
01011         }
01012         if ( item->type != Others ) {
01013             unsigned short v = findDefaultItemByType( Others )->value;
01014             new KACLListViewItem( this, Others, v, true );
01015         }
01016     }
01017     const KACLListViewItem *defaultMaskItem = findDefaultItemByType( Mask );
01018     if ( item->isDefault && !defaultMaskItem ) {
01019         unsigned short v = calculateMaskValue( true );
01020         new KACLListViewItem( this, Mask, v, true );
01021     }
01022     if ( !item->isDefault && !m_hasMask &&
01023             ( item->type == Group
01024               || item->type == NamedUser
01025               || item->type == NamedGroup ) ) {
01026         // auto-add a mask entry
01027         unsigned short v = calculateMaskValue( false );
01028         new KACLListViewItem( this, Mask, v, false );
01029         m_hasMask = true;
01030         m_mask = v;
01031     }
01032     calculateEffectiveRights();
01033     sortItems( sortColumn(), Qt::AscendingOrder );
01034     setCurrentItem( item );
01035     // QTreeWidget doesn't seem to emit, in this case, and we need to update
01036     // the buttons...
01037     if ( topLevelItemCount() == 1 )
01038         emit currentItemChanged( item, item );
01039 }
01040 
01041 void KACLListView::slotEditEntry()
01042 {
01043     QTreeWidgetItem * current = currentItem();
01044     if ( !current ) return;
01045     KACLListViewItem *item = static_cast<KACLListViewItem*>( current );
01046     int allowedTypes = item->type | NamedUser | NamedGroup;
01047     bool itemWasMask = item->type == Mask;
01048     if ( !m_hasMask || itemWasMask )
01049         allowedTypes |= Mask;
01050     int allowedDefaultTypes = item->type | NamedUser | NamedGroup;
01051     if ( !findDefaultItemByType( Mask ) )
01052         allowedDefaultTypes |=  Mask;
01053     if ( !hasDefaultEntries() )
01054         allowedDefaultTypes |= User | Group;
01055 
01056     EditACLEntryDialog dlg( this, item,
01057                             allowedUsers( false, item ), allowedGroups( false, item ),
01058                             allowedUsers( true, item ), allowedGroups( true, item ),
01059                             allowedTypes, allowedDefaultTypes, m_allowDefaults );
01060     dlg.exec();
01061     if ( itemWasMask && item->type != Mask ) {
01062         m_hasMask = false;
01063         m_mask = 0;
01064     }
01065     if ( !itemWasMask && item->type == Mask ) {
01066         m_mask = item->value;
01067         m_hasMask = true;
01068     }
01069     calculateEffectiveRights();
01070     sortItems( sortColumn(), Qt::AscendingOrder );
01071 }
01072 
01073 void KACLListView::slotRemoveEntry()
01074 {
01075     QTreeWidgetItemIterator it( this, QTreeWidgetItemIterator::Selected );
01076     while ( *it ) {
01077         KACLListViewItem *item = static_cast<KACLListViewItem*>( *it );
01078         ++it;
01079         /* First check if it's a mask entry and if so, make sure that there is
01080          * either no name user or group entry, which means the mask can be
01081          * removed, or don't remove it, but reset it. That is allowed. */
01082         if ( item->type == Mask ) {
01083             bool itemWasDefault = item->isDefault;
01084             if ( !itemWasDefault && maskCanBeDeleted() ) {
01085                 m_hasMask= false;
01086                 m_mask = 0;
01087                 delete item;
01088             } else if ( itemWasDefault && defaultMaskCanBeDeleted() ) {
01089                 delete item;
01090             } else {
01091                 item->value = 0;
01092                 item->repaint();
01093             }
01094             if ( !itemWasDefault )
01095                 calculateEffectiveRights();
01096         } else {
01097             // for the base permissions, disable them, which is what libacl does
01098             if ( !item->isDefault &&
01099                     ( item->type == User
01100                       || item->type == Group
01101                       || item->type == Others ) ) {
01102                 item->value = 0;
01103                 item->repaint();
01104             } else {
01105                 delete item;
01106             }
01107         }
01108     }
01109 }
01110 
01111 bool KACLListView::maskCanBeDeleted() const
01112 {
01113    return !findItemByType( NamedUser ) && !findItemByType( NamedGroup );
01114 }
01115 
01116 bool KACLListView::defaultMaskCanBeDeleted() const
01117 {
01118     return !findDefaultItemByType( NamedUser ) && !findDefaultItemByType( NamedGroup );
01119 }
01120 
01121 #include "kacleditwidget.moc"
01122 #include "kacleditwidget_p.moc"
01123 #endif
01124 // vim:set ts=8 sw=4:

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal