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