• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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 void KACLListViewItem::paintCell( QPainter* p, const QColorGroup &cg,
00221                                   int column, int width, int alignment )
00222 {
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 }
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     showButtonSeparator( false );
00435 
00436     QWidget *page = new QWidget(  this );
00437     setMainWidget( page );
00438     QVBoxLayout *mainLayout = new QVBoxLayout( page );
00439     mainLayout->setMargin( 0 );
00440     QGroupBox *gb = new QGroupBox( i18n("Entry Type"), page );
00441     QVBoxLayout *gbLayout = new QVBoxLayout( gb );
00442 
00443     m_buttonGroup = new QButtonGroup( page );
00444 
00445     if ( allowDefaults ) {
00446         m_defaultCB = new QCheckBox( i18n("Default for new files in this folder"), page );
00447         m_defaultCB->setObjectName( QLatin1String( "defaultCB" ) );
00448         mainLayout->addWidget( m_defaultCB );
00449         connect( m_defaultCB, SIGNAL( toggled( bool ) ),
00450                  this, SLOT( slotUpdateAllowedUsersAndGroups() ) );
00451         connect( m_defaultCB, SIGNAL( toggled( bool ) ),
00452                  this, SLOT( slotUpdateAllowedTypes() ) );
00453     }
00454 
00455     QRadioButton *ownerType = new QRadioButton( i18n("Owner"), gb );
00456     ownerType->setObjectName( QLatin1String( "ownerType" ) );
00457     gbLayout->addWidget( ownerType );
00458     m_buttonGroup->addButton( ownerType );
00459     m_buttonIds.insert( ownerType, KACLListView::User );
00460     QRadioButton *owningGroupType = new QRadioButton( i18n("Owning Group"), gb );
00461     owningGroupType->setObjectName( QLatin1String( "owningGroupType" ) );
00462     gbLayout->addWidget( owningGroupType );
00463     m_buttonGroup->addButton( owningGroupType );
00464     m_buttonIds.insert( owningGroupType, KACLListView::Group );
00465     QRadioButton *othersType = new QRadioButton( i18n("Others"), gb );
00466     othersType->setObjectName( QLatin1String( "othersType" ) );
00467     gbLayout->addWidget( othersType );
00468     m_buttonGroup->addButton( othersType );
00469     m_buttonIds.insert( othersType, KACLListView::Others );
00470     QRadioButton *maskType = new QRadioButton( i18n("Mask"), gb );
00471     maskType->setObjectName( QLatin1String( "maskType" ) );
00472     gbLayout->addWidget( maskType );
00473     m_buttonGroup->addButton( maskType );
00474     m_buttonIds.insert( maskType, KACLListView::Mask );
00475     QRadioButton *namedUserType = new QRadioButton( i18n("Named user"), gb );
00476     namedUserType->setObjectName( QLatin1String( "namesUserType" ) );
00477     gbLayout->addWidget( namedUserType );
00478     m_buttonGroup->addButton( namedUserType );
00479     m_buttonIds.insert( namedUserType, KACLListView::NamedUser );
00480     QRadioButton *namedGroupType = new QRadioButton( i18n("Named group"), gb );
00481     namedGroupType->setObjectName( QLatin1String( "namedGroupType" ) );
00482     gbLayout->addWidget( namedGroupType );
00483     m_buttonGroup->addButton( namedGroupType );
00484     m_buttonIds.insert( namedGroupType, KACLListView::NamedGroup );
00485 
00486     mainLayout->addWidget( gb );
00487 
00488     connect( m_buttonGroup, SIGNAL( buttonClicked( QAbstractButton* ) ),
00489              this, SLOT( slotSelectionChanged( QAbstractButton * ) ) );
00490 
00491     m_widgetStack = new QStackedWidget( page );
00492     mainLayout->addWidget( m_widgetStack );
00493 
00494     KHBox *usersBox = new KHBox( m_widgetStack );
00495     m_widgetStack->addWidget( usersBox );
00496 
00497     KHBox *groupsBox = new KHBox( m_widgetStack );
00498     m_widgetStack->addWidget( groupsBox );
00499 
00500     QLabel *usersLabel = new QLabel( i18n( "User: " ), usersBox );
00501     m_usersCombo = new KComboBox( usersBox );
00502     m_usersCombo->setEditable( false );
00503     m_usersCombo->setObjectName( QLatin1String( "users" ) );
00504     usersLabel->setBuddy( m_usersCombo );
00505 
00506     QLabel *groupsLabel = new QLabel( i18n( "Group: " ), groupsBox );
00507     m_groupsCombo = new KComboBox( groupsBox );
00508     m_groupsCombo->setEditable( false );
00509     m_groupsCombo->setObjectName( QLatin1String( "groups" ) );
00510     groupsLabel->setBuddy( m_groupsCombo );
00511 
00512     if ( m_item ) {
00513         m_buttonIds.key( m_item->type )->setChecked( true );
00514         if ( m_defaultCB )
00515             m_defaultCB->setChecked( m_item->isDefault );
00516         slotUpdateAllowedTypes();
00517         slotSelectionChanged( m_buttonIds.key( m_item->type ) );
00518         slotUpdateAllowedUsersAndGroups();
00519         if ( m_item->type == KACLListView::NamedUser ) {
00520             m_usersCombo->setItemText( m_usersCombo->currentIndex(), m_item->qualifier );
00521         } else if ( m_item->type == KACLListView::NamedGroup ) {
00522             m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), m_item->qualifier );
00523         }
00524     } else {
00525         // new entry, preselect "named user", arguably the most common one
00526         m_buttonIds.key( KACLListView::NamedUser )->setChecked( true );
00527         slotUpdateAllowedTypes();
00528         slotSelectionChanged( m_buttonIds.key( KACLListView::NamedUser ) );
00529         slotUpdateAllowedUsersAndGroups();
00530     }
00531     incrementInitialSize(  QSize( 100, 0 ) );
00532     connect(this,SIGNAL(okClicked()), this, SLOT(slotOk()));
00533 }
00534 
00535 void EditACLEntryDialog::slotUpdateAllowedTypes()
00536 {
00537     int allowedTypes = m_allowedTypes;
00538     if ( m_defaultCB && m_defaultCB->isChecked() ) {
00539         allowedTypes = m_allowedDefaultTypes;
00540     }
00541     for ( int i=1; i < KACLListView::AllTypes; i=i*2 ) {
00542         if ( allowedTypes & i )
00543             m_buttonIds.key( i )->show();
00544         else
00545             m_buttonIds.key( i )->hide();
00546     }
00547 }
00548 
00549 void EditACLEntryDialog::slotUpdateAllowedUsersAndGroups()
00550 {
00551     const QString oldUser = m_usersCombo->currentText();
00552     const QString oldGroup = m_groupsCombo->currentText();
00553     m_usersCombo->clear();
00554     m_groupsCombo->clear();
00555     if ( m_defaultCB && m_defaultCB->isChecked() ) {
00556         m_usersCombo->addItems( m_defaultUsers );
00557         if ( m_defaultUsers.contains( oldUser ) )
00558             m_usersCombo->setItemText( m_usersCombo->currentIndex(), oldUser );
00559         m_groupsCombo->addItems( m_defaultGroups );
00560         if ( m_defaultGroups.contains( oldGroup ) )
00561             m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), oldGroup );
00562     } else {
00563         m_usersCombo->addItems( m_users );
00564         if ( m_users.contains( oldUser ) )
00565             m_usersCombo->setItemText( m_usersCombo->currentIndex(), oldUser );
00566         m_groupsCombo->addItems( m_groups );
00567         if ( m_groups.contains( oldGroup ) )
00568             m_groupsCombo->setItemText( m_groupsCombo->currentIndex(), oldGroup );
00569     }
00570 }
00571 void EditACLEntryDialog::slotOk()
00572 {
00573     KACLListView::EntryType type = static_cast<KACLListView::EntryType>( m_buttonIds[m_buttonGroup->checkedButton()] );
00574 
00575     kWarning() << "Type 2: " << type;
00576 
00577     QString qualifier;
00578     if ( type == KACLListView::NamedUser )
00579       qualifier = m_usersCombo->currentText();
00580     if ( type == KACLListView::NamedGroup )
00581       qualifier = m_groupsCombo->currentText();
00582 
00583     if ( !m_item ) {
00584         m_item = new KACLListViewItem( m_listView, type, ACL_READ | ACL_WRITE | ACL_EXECUTE, false, qualifier );
00585     } else {
00586         m_item->type = type;
00587         m_item->qualifier = qualifier;
00588     }
00589     if ( m_defaultCB )
00590         m_item->isDefault = m_defaultCB->isChecked();
00591     m_item->repaint();
00592 
00593     KDialog::accept();
00594 }
00595 
00596 void EditACLEntryDialog::slotSelectionChanged( QAbstractButton *button )
00597 {
00598     switch ( m_buttonIds[ button ] ) {
00599         case KACLListView::User:
00600         case KACLListView::Group:
00601         case KACLListView::Others:
00602         case KACLListView::Mask:
00603             m_widgetStack->setEnabled( false );
00604             break;
00605         case KACLListView::NamedUser:
00606             m_widgetStack->setEnabled( true );
00607             m_widgetStack->setCurrentIndex( 0 /* User */ );
00608             break;
00609         case KACLListView::NamedGroup:
00610             m_widgetStack->setEnabled( true );
00611             m_widgetStack->setCurrentIndex( 1 /* Group */ );
00612             break;
00613         default:
00614             break;
00615     }
00616 }
00617 
00618 
00619 KACLListView::KACLListView( QWidget* parent )
00620  : QTreeWidget( parent ),
00621    m_hasMask( false ), m_allowDefaults( false )
00622 {
00623     // Add the columns
00624     setColumnCount( 6 );
00625     QStringList headers;
00626     headers <<  i18n( "Type" );
00627     headers <<  i18n( "Name" );
00628     headers <<  i18nc( "read permission", "r" );
00629     headers <<  i18nc( "write permission", "w" );
00630     headers <<  i18nc( "execute permission", "x" );
00631     headers <<  i18n( "Effective" );
00632     setHeaderLabels( headers );
00633 
00634     setSortingEnabled( false );
00635     setSelectionMode( QAbstractItemView::ExtendedSelection );
00636     header()->setResizeMode( QHeaderView::ResizeToContents );
00637     setRootIsDecorated( false );
00638 
00639     // Load the avatars
00640     for ( int i=0; i < LAST_IDX; ++i ) {
00641         s_itemAttributes[i].pixmap = new QPixmap( QString::fromLatin1(":/images/%1").arg(s_itemAttributes[i].pixmapName) );
00642     }
00643     m_yesPixmap = new QPixmap( ":/images/yes.png" );
00644     m_yesPartialPixmap = new QPixmap( ":/images/yespartial.png" );
00645 
00646 
00647     // fill the lists of all legal users and groups
00648     struct passwd *user = 0;
00649     setpwent();
00650     while ( ( user = getpwent() ) != 0 ) {
00651        m_allUsers << QString::fromLatin1( user->pw_name );
00652     }
00653     endpwent();
00654 
00655     struct group *gr = 0;
00656     setgrent();
00657     while ( ( gr = getgrent() ) != 0 ) {
00658        m_allGroups << QString::fromLatin1( gr->gr_name );
00659     }
00660     endgrent();
00661     m_allUsers.sort();
00662     m_allGroups.sort();
00663 
00664     connect( this, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ),
00665              this, SLOT( slotItemClicked( QTreeWidgetItem*, int ) ) );
00666 }
00667 
00668 
00669 KACLListView::~KACLListView()
00670 {
00671     for ( int i=0; i < LAST_IDX; ++i ) {
00672        delete s_itemAttributes[i].pixmap;
00673     }
00674     delete m_yesPixmap;
00675     delete m_yesPartialPixmap;
00676 }
00677 
00678 QStringList KACLListView::allowedUsers( bool defaults, KACLListViewItem *allowedItem )
00679 {
00680     QStringList allowedUsers = m_allUsers;
00681     QTreeWidgetItemIterator it( this );
00682     while ( *it ) {
00683         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00684         ++it;
00685         if ( item->type != NamedUser || item->isDefault != defaults ) continue;
00686         if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00687         allowedUsers.removeAll( item->qualifier );
00688     }
00689     return allowedUsers;
00690 }
00691 
00692 QStringList KACLListView::allowedGroups( bool defaults, KACLListViewItem *allowedItem )
00693 {
00694     QStringList allowedGroups = m_allGroups;
00695     QTreeWidgetItemIterator it( this );
00696     while ( *it ) {
00697         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00698         ++it;
00699         if ( item->type != NamedGroup || item->isDefault != defaults ) continue;
00700         if ( allowedItem && item == allowedItem && allowedItem->isDefault == defaults ) continue;
00701         allowedGroups.removeAll( item->qualifier );
00702     }
00703     return allowedGroups;
00704 }
00705 
00706 void KACLListView::fillItemsFromACL( const KACL &pACL, bool defaults )
00707 {
00708     // clear out old entries of that ilk
00709     QTreeWidgetItemIterator it( this );
00710     while ( KACLListViewItem *item = static_cast<KACLListViewItem*>( *it ) ) {
00711         ++it;
00712         if ( item->isDefault == defaults )
00713             delete item;
00714     }
00715     KACLListViewItem *item =
00716         new KACLListViewItem( this, User, pACL.ownerPermissions(), defaults );
00717 
00718     item = new KACLListViewItem( this, Group, pACL.owningGroupPermissions(), defaults );
00719 
00720     item = new KACLListViewItem( this, Others, pACL.othersPermissions(), defaults );
00721 
00722     bool hasMask = false;
00723     unsigned short mask = pACL.maskPermissions( hasMask );
00724     if ( hasMask ) {
00725         item = new KACLListViewItem( this, Mask, mask, defaults );
00726     }
00727 
00728     // read all named user entries
00729     const ACLUserPermissionsList &userList =  pACL.allUserPermissions();
00730     ACLUserPermissionsConstIterator itu = userList.begin();
00731     while ( itu != userList.end() ) {
00732         new KACLListViewItem( this, NamedUser, (*itu).second, defaults, (*itu).first );
00733         ++itu;
00734     }
00735 
00736     // and now all named groups
00737     const ACLUserPermissionsList &groupList =  pACL.allGroupPermissions();
00738     ACLUserPermissionsConstIterator itg = groupList.begin();
00739     while ( itg != groupList.end() ) {
00740         new KACLListViewItem( this, NamedGroup, (*itg).second, defaults, (*itg).first );
00741         ++itg;
00742     }
00743 }
00744 
00745 void KACLListView::setACL( const KACL &acl )
00746 {
00747     if ( !acl.isValid() ) return;
00748     // Remove any entries left over from displaying a previous ACL
00749     m_ACL = acl;
00750     fillItemsFromACL( m_ACL );
00751 
00752     m_mask = acl.maskPermissions( m_hasMask );
00753     calculateEffectiveRights();
00754 }
00755 
00756 void KACLListView::setDefaultACL( const KACL &acl )
00757 {
00758     if ( !acl.isValid() ) return;
00759     m_defaultACL = acl;
00760     fillItemsFromACL( m_defaultACL, true );
00761     calculateEffectiveRights();
00762 }
00763 
00764 KACL KACLListView::itemsToACL( bool defaults ) const
00765 {
00766     KACL newACL( 0 );
00767     bool atLeastOneEntry = false;
00768     ACLUserPermissionsList users;
00769     ACLGroupPermissionsList groups;
00770     QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00771     while ( QTreeWidgetItem* qlvi = *it ) {
00772         ++it;
00773         const KACLListViewItem* item = static_cast<KACLListViewItem*>( qlvi );
00774         if ( item->isDefault != defaults ) continue;
00775         atLeastOneEntry = true;
00776         switch ( item->type ) {
00777             case User:
00778                 newACL.setOwnerPermissions( item->value );
00779                 break;
00780             case Group:
00781                 newACL.setOwningGroupPermissions( item->value );
00782                 break;
00783             case Others:
00784                 newACL.setOthersPermissions( item->value );
00785                 break;
00786             case Mask:
00787                 newACL.setMaskPermissions( item->value );
00788                 break;
00789             case NamedUser:
00790                 users.append( qMakePair( item->text( 1 ), item->value ) );
00791                 break;
00792             case NamedGroup:
00793                 groups.append( qMakePair( item->text( 1 ), item->value ) );
00794                 break;
00795             default:
00796                 break;
00797         }
00798     }
00799     if ( atLeastOneEntry ) {
00800         newACL.setAllUserPermissions( users );
00801         newACL.setAllGroupPermissions( groups );
00802         if ( newACL.isValid() )
00803             return newACL;
00804     }
00805     return KACL();
00806 }
00807 
00808 KACL KACLListView::getACL()
00809 {
00810     return itemsToACL( false );
00811 }
00812 
00813 
00814 KACL KACLListView::getDefaultACL()
00815 {
00816     return itemsToACL( true );
00817 }
00818 
00819 void KACLListView::contentsMousePressEvent( QMouseEvent * e )
00820 {
00821     /*
00822     QTreeWidgetItem *clickedItem = itemAt( e->pos() );
00823     if ( !clickedItem ) return;
00824     // if the click is on an as yet unselected item, select it first
00825     if ( !clickedItem->isSelected() )
00826         QAbstractItemView::contentsMousePressEvent( e );
00827 
00828     if ( !currentItem() ) return;
00829     int column = header()->sectionAt( e->x() );
00830     acl_perm_t perm;
00831     switch ( column )
00832     {
00833         case 2:
00834             perm = ACL_READ;
00835             break;
00836         case 3:
00837             perm = ACL_WRITE;
00838             break;
00839         case 4:
00840             perm = ACL_EXECUTE;
00841             break;
00842         default:
00843             return QTreeWidget::contentsMousePressEvent( e );
00844     }
00845     KACLListViewItem* referenceItem = static_cast<KACLListViewItem*>( clickedItem );
00846     unsigned short referenceHadItSet = referenceItem->value & perm;
00847     QTreeWidgetItemIterator it( this );
00848     while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( *it ) ) {
00849         ++it;
00850         if ( !item->isSelected() ) continue;
00851         // toggle those with the same value as the clicked item, leave the others
00852         if ( referenceHadItSet == ( item->value & perm ) )
00853             item->togglePerm( perm );
00854     }
00855      */
00856 }
00857 
00858 void KACLListView::slotItemClicked( QTreeWidgetItem* pItem,  int col )
00859 {
00860     if ( !pItem ) return;
00861 
00862     QTreeWidgetItemIterator it( this );
00863     while ( KACLListViewItem* item = static_cast<KACLListViewItem*>( *it ) ) {
00864         ++it;
00865         if ( !item->isSelected() ) continue;
00866         switch ( col )
00867         {
00868             case 2:
00869                 item->togglePerm( ACL_READ );
00870                 break;
00871             case 3:
00872                 item->togglePerm( ACL_WRITE );
00873                 break;
00874             case 4:
00875                 item->togglePerm( ACL_EXECUTE );
00876                 break;
00877 
00878             default:
00879                 ; // Do nothing
00880         }
00881     }
00882     /*
00883     // Has the user changed one of the required entries in a default ACL?
00884     if ( m_pACL->aclType() == ACL_TYPE_DEFAULT &&
00885     ( col == 2 || col == 3 || col == 4 ) &&
00886     ( pACLItem->entryType() == ACL_USER_OBJ ||
00887     pACLItem->entryType() == ACL_GROUP_OBJ ||
00888     pACLItem->entryType() == ACL_OTHER ) )
00889     {
00890     // Mark the required entries as no longer being partial entries.
00891     // That is, they will get applied to all selected directories.
00892     KACLListViewItem* pUserObj = findACLEntryByType( this, ACL_USER_OBJ );
00893     pUserObj->entry()->setPartialEntry( false );
00894 
00895     KACLListViewItem* pGroupObj = findACLEntryByType( this, ACL_GROUP_OBJ );
00896     pGroupObj->entry()->setPartialEntry( false );
00897 
00898     KACLListViewItem* pOther = findACLEntryByType( this, ACL_OTHER );
00899     pOther->entry()->setPartialEntry( false );
00900 
00901     update();
00902     }
00903      */
00904 }
00905 
00906 
00907 void KACLListView::calculateEffectiveRights()
00908 {
00909     QTreeWidgetItemIterator it( this );
00910     KACLListViewItem* pItem;
00911     while ( ( pItem = dynamic_cast<KACLListViewItem*>( *it ) ) != 0 )
00912     {
00913         ++it;
00914         pItem->calcEffectiveRights();
00915     }
00916 }
00917 
00918 
00919 unsigned short KACLListView::maskPermissions() const
00920 {
00921   return m_mask;
00922 }
00923 
00924 
00925 void KACLListView::setMaskPermissions( unsigned short maskPerms )
00926 {
00927     m_mask = maskPerms;
00928     calculateEffectiveRights();
00929 }
00930 
00931 
00932 acl_perm_t KACLListView::maskPartialPermissions() const
00933 {
00934   //  return m_pMaskEntry->m_partialPerms;
00935   return 0;
00936 }
00937 
00938 
00939 void KACLListView::setMaskPartialPermissions( acl_perm_t /*maskPartialPerms*/ )
00940 {
00941     //m_pMaskEntry->m_partialPerms = maskPartialPerms;
00942     calculateEffectiveRights();
00943 }
00944 
00945 bool KACLListView::hasDefaultEntries() const
00946 {
00947     QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00948     while ( *it ) {
00949         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00950         ++it;
00951         if ( item->isDefault ) return true;
00952     }
00953     return false;
00954 }
00955 
00956 const KACLListViewItem* KACLListView::findDefaultItemByType( EntryType type ) const
00957 {
00958     return findItemByType( type, true );
00959 }
00960 
00961 const KACLListViewItem* KACLListView::findItemByType( EntryType type, bool defaults ) const
00962 {
00963     QTreeWidgetItemIterator it( const_cast<KACLListView*>( this ) );
00964     while ( *it ) {
00965         const KACLListViewItem *item = static_cast<const KACLListViewItem*>( *it );
00966         ++it;
00967         if ( item->isDefault == defaults && item->type == type ) {
00968             return item;
00969         }
00970     }
00971     return 0;
00972 }
00973 
00974 
00975 unsigned short KACLListView::calculateMaskValue( bool defaults ) const
00976 {
00977     // KACL auto-adds the relevant maks entries, so we can simply query
00978     bool dummy;
00979     return itemsToACL( defaults ).maskPermissions( dummy );
00980 }
00981 
00982 void KACLListView::slotAddEntry()
00983 {
00984     int allowedTypes = NamedUser | NamedGroup;
00985     if ( !m_hasMask )
00986         allowedTypes |= Mask;
00987     int allowedDefaultTypes = NamedUser | NamedGroup;
00988     if ( !findDefaultItemByType( Mask ) )
00989         allowedDefaultTypes |=  Mask;
00990     if ( !hasDefaultEntries() )
00991         allowedDefaultTypes |= User | Group;
00992     EditACLEntryDialog dlg( this, 0,
00993                             allowedUsers( false ), allowedGroups( false ),
00994                             allowedUsers( true ), allowedGroups( true ),
00995                             allowedTypes, allowedDefaultTypes, m_allowDefaults );
00996     dlg.exec();
00997     KACLListViewItem *item = dlg.item();
00998     if ( !item ) return; // canceled
00999     if ( item->type == Mask && !item->isDefault ) {
01000         m_hasMask = true;
01001         m_mask = item->value;
01002     }
01003     if ( item->isDefault && !hasDefaultEntries() ) {
01004         // first default entry, fill in what is needed
01005         if ( item->type != User ) {
01006             unsigned short v = findDefaultItemByType( User )->value;
01007             new KACLListViewItem( this, User, v, true );
01008         }
01009         if ( item->type != Group ) {
01010             unsigned short v = findDefaultItemByType( Group )->value;
01011             new KACLListViewItem( this, Group, v, true );
01012         }
01013         if ( item->type != Others ) {
01014             unsigned short v = findDefaultItemByType( Others )->value;
01015             new KACLListViewItem( this, Others, v, true );
01016         }
01017     }
01018     const KACLListViewItem *defaultMaskItem = findDefaultItemByType( Mask );
01019     if ( item->isDefault && !defaultMaskItem ) {
01020         unsigned short v = calculateMaskValue( true );
01021         new KACLListViewItem( this, Mask, v, true );
01022     }
01023     if ( !item->isDefault && !m_hasMask &&
01024             ( item->type == Group
01025               || item->type == NamedUser
01026               || item->type == NamedGroup ) ) {
01027         // auto-add a mask entry
01028         unsigned short v = calculateMaskValue( false );
01029         new KACLListViewItem( this, Mask, v, false );
01030         m_hasMask = true;
01031         m_mask = v;
01032     }
01033     calculateEffectiveRights();
01034     sortItems( sortColumn(), Qt::AscendingOrder );
01035     setCurrentItem( item );
01036     // QTreeWidget doesn't seem to emit, in this case, and we need to update
01037     // the buttons...
01038     if ( topLevelItemCount() == 1 )
01039         emit currentItemChanged( item, item );
01040 }
01041 
01042 void KACLListView::slotEditEntry()
01043 {
01044     QTreeWidgetItem * current = currentItem();
01045     if ( !current ) return;
01046     KACLListViewItem *item = static_cast<KACLListViewItem*>( current );
01047     int allowedTypes = item->type | NamedUser | NamedGroup;
01048     bool itemWasMask = item->type == Mask;
01049     if ( !m_hasMask || itemWasMask )
01050         allowedTypes |= Mask;
01051     int allowedDefaultTypes = item->type | NamedUser | NamedGroup;
01052     if ( !findDefaultItemByType( Mask ) )
01053         allowedDefaultTypes |=  Mask;
01054     if ( !hasDefaultEntries() )
01055         allowedDefaultTypes |= User | Group;
01056 
01057     EditACLEntryDialog dlg( this, item,
01058                             allowedUsers( false, item ), allowedGroups( false, item ),
01059                             allowedUsers( true, item ), allowedGroups( true, item ),
01060                             allowedTypes, allowedDefaultTypes, m_allowDefaults );
01061     dlg.exec();
01062     if ( itemWasMask && item->type != Mask ) {
01063         m_hasMask = false;
01064         m_mask = 0;
01065     }
01066     if ( !itemWasMask && item->type == Mask ) {
01067         m_mask = item->value;
01068         m_hasMask = true;
01069     }
01070     calculateEffectiveRights();
01071     sortItems( sortColumn(), Qt::AscendingOrder );
01072 }
01073 
01074 void KACLListView::slotRemoveEntry()
01075 {
01076     QTreeWidgetItemIterator it( this, QTreeWidgetItemIterator::Selected );
01077     while ( *it ) {
01078         KACLListViewItem *item = static_cast<KACLListViewItem*>( *it );
01079         ++it;
01080         /* First check if it's a mask entry and if so, make sure that there is
01081          * either no name user or group entry, which means the mask can be
01082          * removed, or don't remove it, but reset it. That is allowed. */
01083         if ( item->type == Mask ) {
01084             bool itemWasDefault = item->isDefault;
01085             if ( !itemWasDefault && maskCanBeDeleted() ) {
01086                 m_hasMask= false;
01087                 m_mask = 0;
01088                 delete item;
01089             } else if ( itemWasDefault && defaultMaskCanBeDeleted() ) {
01090                 delete item;
01091             } else {
01092                 item->value = 0;
01093                 item->repaint();
01094             }
01095             if ( !itemWasDefault )
01096                 calculateEffectiveRights();
01097         } else {
01098             // for the base permissions, disable them, which is what libacl does
01099             if ( !item->isDefault &&
01100                     ( item->type == User
01101                       || item->type == Group
01102                       || item->type == Others ) ) {
01103                 item->value = 0;
01104                 item->repaint();
01105             } else {
01106                 delete item;
01107             }
01108         }
01109     }
01110 }
01111 
01112 bool KACLListView::maskCanBeDeleted() const
01113 {
01114    return !findItemByType( NamedUser ) && !findItemByType( NamedGroup );
01115 }
01116 
01117 bool KACLListView::defaultMaskCanBeDeleted() const
01118 {
01119     return !findDefaultItemByType( NamedUser ) && !findDefaultItemByType( NamedGroup );
01120 }
01121 
01122 #include "kacleditwidget.moc"
01123 #include "kacleditwidget_p.moc"
01124 #endif
01125 // 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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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